mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 13:03:50 +00:00
4.8.10 test (#2601)
* perf: workflow children run params * feat: workflow userId * fix: ui size * perf: Markdown whitespace and ai images split * fix: openai sdk ts
This commit is contained in:
@@ -121,46 +121,22 @@ export const loadRequestMessages = async ({
|
||||
const imageRegex =
|
||||
/(https?:\/\/[^\s/$.?#].[^\s]*\.(?:png|jpe?g|gif|webp|bmp|tiff?|svg|ico|heic|avif))/i;
|
||||
|
||||
const result: { type: 'text' | 'image'; value: string }[] = [];
|
||||
let lastIndex = 0;
|
||||
let match;
|
||||
const result: ChatCompletionContentPart[] = [];
|
||||
|
||||
// 使用正则表达式查找所有匹配项
|
||||
while ((match = imageRegex.exec(input.slice(lastIndex))) !== null) {
|
||||
const textBefore = input.slice(lastIndex, lastIndex + match.index);
|
||||
|
||||
// 如果图片URL前有文本,添加文本部分
|
||||
if (textBefore) {
|
||||
result.push({ type: 'text', value: textBefore });
|
||||
}
|
||||
|
||||
// 添加图片URL
|
||||
result.push({ type: 'image', value: match[0] });
|
||||
|
||||
lastIndex += match.index + match[0].length;
|
||||
}
|
||||
|
||||
// 添加剩余的文本(如果有的话)
|
||||
if (lastIndex < input.length) {
|
||||
result.push({ type: 'text', value: input.slice(lastIndex) });
|
||||
}
|
||||
|
||||
return result
|
||||
.map((item) => {
|
||||
if (item.type === 'text') {
|
||||
return { type: 'text', text: item.value };
|
||||
// 提取所有HTTPS图片URL并添加到result开头
|
||||
const httpsImages = input.match(imageRegex) || [];
|
||||
httpsImages.forEach((url) => {
|
||||
result.push({
|
||||
type: 'image_url',
|
||||
image_url: {
|
||||
url: url
|
||||
}
|
||||
if (item.type === 'image') {
|
||||
return {
|
||||
type: 'image_url',
|
||||
image_url: {
|
||||
url: item.value
|
||||
}
|
||||
};
|
||||
}
|
||||
return { type: 'text', text: item.value };
|
||||
})
|
||||
.filter(Boolean) as ChatCompletionContentPart[];
|
||||
});
|
||||
});
|
||||
|
||||
// 添加原始input作为文本
|
||||
result.push({ type: 'text', text: input });
|
||||
return result;
|
||||
}
|
||||
// Load image
|
||||
const parseUserContent = async (content: string | ChatCompletionContentPart[]) => {
|
||||
|
@@ -31,7 +31,7 @@ type Response = DispatchNodeResultType<{
|
||||
|
||||
export const dispatchAppRequest = async (props: Props): Promise<Response> => {
|
||||
const {
|
||||
app: workflowApp,
|
||||
runningAppInfo,
|
||||
workflowStreamResponse,
|
||||
histories,
|
||||
query,
|
||||
@@ -45,7 +45,7 @@ export const dispatchAppRequest = async (props: Props): Promise<Response> => {
|
||||
// 检查该工作流的tmb是否有调用该app的权限(不是校验对话的人,是否有权限)
|
||||
const { app: appData } = await authAppByTmbId({
|
||||
appId: app.id,
|
||||
tmbId: workflowApp.tmbId,
|
||||
tmbId: runningAppInfo.tmbId,
|
||||
per: ReadPermissionVal
|
||||
});
|
||||
|
||||
@@ -61,7 +61,11 @@ export const dispatchAppRequest = async (props: Props): Promise<Response> => {
|
||||
|
||||
const { flowResponses, flowUsages, assistantResponses } = await dispatchWorkFlow({
|
||||
...props,
|
||||
app: appData,
|
||||
runningAppInfo: {
|
||||
id: String(appData._id),
|
||||
teamId: String(appData.teamId),
|
||||
tmbId: String(appData.tmbId)
|
||||
},
|
||||
runtimeNodes: storeNodes2RuntimeNodes(
|
||||
appData.modules,
|
||||
getWorkflowEntryNodeIds(appData.modules)
|
||||
|
@@ -37,7 +37,7 @@ export async function dispatchDatasetSearch(
|
||||
props: DatasetSearchProps
|
||||
): Promise<DatasetSearchResponse> {
|
||||
const {
|
||||
teamId,
|
||||
runningAppInfo: { teamId },
|
||||
histories,
|
||||
node,
|
||||
params: {
|
||||
|
@@ -6,7 +6,8 @@ import {
|
||||
import { NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
import type {
|
||||
ChatDispatchProps,
|
||||
ModuleDispatchProps
|
||||
ModuleDispatchProps,
|
||||
SystemVariablesType
|
||||
} from '@fastgpt/global/core/workflow/runtime/type';
|
||||
import type { RuntimeNodeItemType } from '@fastgpt/global/core/workflow/runtime/type.d';
|
||||
import type {
|
||||
@@ -554,13 +555,15 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
|
||||
/* get system variable */
|
||||
export function getSystemVariable({
|
||||
user,
|
||||
app,
|
||||
runningAppInfo,
|
||||
chatId,
|
||||
responseChatItemId,
|
||||
histories = []
|
||||
}: Props) {
|
||||
histories = [],
|
||||
uid
|
||||
}: Props): SystemVariablesType {
|
||||
return {
|
||||
appId: String(app._id),
|
||||
userId: uid,
|
||||
appId: String(runningAppInfo.id),
|
||||
chatId,
|
||||
responseChatItemId,
|
||||
histories,
|
||||
|
@@ -29,7 +29,7 @@ type UserSelectResponse = DispatchNodeResultType<{
|
||||
export const dispatchUserSelect = async (props: Props): Promise<UserSelectResponse> => {
|
||||
const {
|
||||
workflowStreamResponse,
|
||||
app: { _id: appId },
|
||||
runningAppInfo: { id: appId },
|
||||
chatId,
|
||||
node: { nodeId, isEntry },
|
||||
params: { description, userSelectOptions },
|
||||
|
@@ -13,6 +13,7 @@ import { authPluginByTmbId } from '../../../../support/permission/app/auth';
|
||||
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
|
||||
import { computedPluginUsage } from '../../../app/plugin/utils';
|
||||
import { filterSystemVariables } from '../utils';
|
||||
import { getPluginRunUserQuery } from '../../utils';
|
||||
|
||||
type RunPluginProps = ModuleDispatchProps<{
|
||||
[key: string]: any;
|
||||
@@ -22,9 +23,8 @@ type RunPluginResponse = DispatchNodeResultType<{}>;
|
||||
export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPluginResponse> => {
|
||||
const {
|
||||
node: { pluginId },
|
||||
app: workflowApp,
|
||||
runningAppInfo,
|
||||
mode,
|
||||
teamId,
|
||||
params: data // Plugin input
|
||||
} = props;
|
||||
|
||||
@@ -33,9 +33,9 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPlugi
|
||||
}
|
||||
|
||||
// auth plugin
|
||||
await authPluginByTmbId({
|
||||
const pluginData = await authPluginByTmbId({
|
||||
appId: pluginId,
|
||||
tmbId: workflowApp.tmbId,
|
||||
tmbId: runningAppInfo.tmbId,
|
||||
per: ReadPermissionVal
|
||||
});
|
||||
|
||||
@@ -61,14 +61,21 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPlugi
|
||||
showStatus: false
|
||||
};
|
||||
});
|
||||
const runtimeVariables = {
|
||||
...filterSystemVariables(props.variables),
|
||||
appId: String(plugin.id)
|
||||
};
|
||||
|
||||
const { flowResponses, flowUsages, assistantResponses } = await dispatchWorkFlow({
|
||||
...props,
|
||||
|
||||
variables: {
|
||||
...filterSystemVariables(props.variables),
|
||||
appId: String(plugin.id)
|
||||
runningAppInfo: {
|
||||
id: String(plugin.id),
|
||||
teamId: plugin.teamId || '',
|
||||
tmbId: pluginData?.tmbId || ''
|
||||
},
|
||||
variables: runtimeVariables,
|
||||
query: getPluginRunUserQuery(plugin.nodes, runtimeVariables).value,
|
||||
chatConfig: {},
|
||||
runtimeNodes,
|
||||
runtimeEdges: initWorkflowEdgeStatus(plugin.edges)
|
||||
});
|
||||
@@ -90,7 +97,7 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPlugi
|
||||
totalPoints: usagePoints,
|
||||
pluginOutput: output?.pluginOutput,
|
||||
pluginDetail:
|
||||
mode === 'test' && plugin.teamId === teamId
|
||||
mode === 'test' && plugin.teamId === runningAppInfo.teamId
|
||||
? flowResponses.filter((item) => {
|
||||
const filterArr = [FlowNodeTypeEnum.pluginOutput];
|
||||
return !filterArr.includes(item.moduleType as any);
|
||||
|
@@ -16,6 +16,7 @@ import { chatValue2RuntimePrompt, runtimePrompt2ChatsValue } from '@fastgpt/glob
|
||||
import { DispatchNodeResultType } from '@fastgpt/global/core/workflow/runtime/type';
|
||||
import { authAppByTmbId } from '../../../../support/permission/app/auth';
|
||||
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
|
||||
import { getAppLatestVersion } from '../../../app/controller';
|
||||
|
||||
type Props = ModuleDispatchProps<{
|
||||
[NodeInputKeyEnum.userChatInput]: string;
|
||||
@@ -29,7 +30,7 @@ type Response = DispatchNodeResultType<{
|
||||
|
||||
export const dispatchRunAppNode = async (props: Props): Promise<Response> => {
|
||||
const {
|
||||
app: workflowApp,
|
||||
runningAppInfo,
|
||||
histories,
|
||||
query,
|
||||
node: { pluginId },
|
||||
@@ -49,9 +50,10 @@ export const dispatchRunAppNode = async (props: Props): Promise<Response> => {
|
||||
// Auth the app by tmbId(Not the user, but the workflow user)
|
||||
const { app: appData } = await authAppByTmbId({
|
||||
appId: pluginId,
|
||||
tmbId: workflowApp.tmbId,
|
||||
tmbId: runningAppInfo.tmbId,
|
||||
per: ReadPermissionVal
|
||||
});
|
||||
const { nodes, edges, chatConfig } = await getAppLatestVersion(pluginId);
|
||||
|
||||
// Auto line
|
||||
workflowStreamResponse?.({
|
||||
@@ -64,27 +66,31 @@ export const dispatchRunAppNode = async (props: Props): Promise<Response> => {
|
||||
const chatHistories = getHistories(history, histories);
|
||||
const { files } = chatValue2RuntimePrompt(query);
|
||||
|
||||
// Concat variables
|
||||
// Rewrite children app variables
|
||||
const systemVariables = filterSystemVariables(variables);
|
||||
const childrenRunVariables = {
|
||||
...systemVariables,
|
||||
...childrenAppVariables
|
||||
...childrenAppVariables,
|
||||
histories: chatHistories,
|
||||
appId: String(appData._id)
|
||||
};
|
||||
|
||||
const { flowResponses, flowUsages, assistantResponses } = await dispatchWorkFlow({
|
||||
...props,
|
||||
app: appData,
|
||||
runtimeNodes: storeNodes2RuntimeNodes(
|
||||
appData.modules,
|
||||
getWorkflowEntryNodeIds(appData.modules)
|
||||
),
|
||||
runtimeEdges: initWorkflowEdgeStatus(appData.edges),
|
||||
runningAppInfo: {
|
||||
id: String(appData._id),
|
||||
teamId: String(appData.teamId),
|
||||
tmbId: String(appData.tmbId)
|
||||
},
|
||||
runtimeNodes: storeNodes2RuntimeNodes(nodes, getWorkflowEntryNodeIds(nodes)),
|
||||
runtimeEdges: initWorkflowEdgeStatus(edges),
|
||||
histories: chatHistories,
|
||||
variables: childrenRunVariables,
|
||||
query: runtimePrompt2ChatsValue({
|
||||
files,
|
||||
text: userChatInput
|
||||
}),
|
||||
variables: childrenRunVariables
|
||||
chatConfig
|
||||
});
|
||||
|
||||
const completeMessages = chatHistories.concat([
|
||||
|
@@ -15,7 +15,7 @@ type Response = DispatchNodeResultType<{}>;
|
||||
|
||||
export const dispatchCustomFeedback = (props: Record<string, any>): Response => {
|
||||
const {
|
||||
app: { _id: appId },
|
||||
runningAppInfo: { id: appId },
|
||||
chatId,
|
||||
responseChatItemId: chatItemId,
|
||||
stream,
|
||||
|
@@ -42,7 +42,7 @@ const UNDEFINED_SIGN = 'UNDEFINED_SIGN';
|
||||
|
||||
export const dispatchHttp468Request = async (props: HttpRequestProps): Promise<HttpResponse> => {
|
||||
let {
|
||||
app: { _id: appId },
|
||||
runningAppInfo: { id: appId },
|
||||
chatId,
|
||||
responseChatItemId,
|
||||
variables,
|
||||
|
@@ -44,7 +44,7 @@ ${content.slice(0, 100)}${content.length > 100 ? '......' : ''}
|
||||
export const dispatchReadFiles = async (props: Props): Promise<Response> => {
|
||||
const {
|
||||
requestOrigin,
|
||||
teamId,
|
||||
runningAppInfo: { teamId },
|
||||
histories,
|
||||
chatConfig,
|
||||
params: { fileUrlList = [] }
|
||||
|
@@ -21,7 +21,7 @@ const UNDEFINED_SIGN = 'UNDEFINED_SIGN';
|
||||
|
||||
export const dispatchLafRequest = async (props: LafRequestProps): Promise<LafResponse> => {
|
||||
let {
|
||||
app: { _id: appId },
|
||||
runningAppInfo: { id: appId },
|
||||
chatId,
|
||||
responseChatItemId,
|
||||
variables,
|
||||
|
@@ -5,7 +5,10 @@ import {
|
||||
WorkflowIOValueTypeEnum,
|
||||
NodeOutputKeyEnum
|
||||
} from '@fastgpt/global/core/workflow/constants';
|
||||
import { RuntimeEdgeItemType } from '@fastgpt/global/core/workflow/runtime/type';
|
||||
import {
|
||||
RuntimeEdgeItemType,
|
||||
SystemVariablesType
|
||||
} from '@fastgpt/global/core/workflow/runtime/type';
|
||||
import { responseWrite } from '../../../common/response';
|
||||
import { NextApiResponse } from 'next';
|
||||
import { SseResponseEventEnum } from '@fastgpt/global/core/workflow/runtime/constants';
|
||||
@@ -144,8 +147,9 @@ export const removeSystemVariable = (variables: Record<string, any>) => {
|
||||
|
||||
return copyVariables;
|
||||
};
|
||||
export const filterSystemVariables = (variables: Record<string, any>) => {
|
||||
export const filterSystemVariables = (variables: Record<string, any>): SystemVariablesType => {
|
||||
return {
|
||||
userId: variables.userId,
|
||||
appId: variables.appId,
|
||||
chatId: variables.chatId,
|
||||
responseChatItemId: variables.responseChatItemId,
|
||||
|
@@ -1,5 +1,13 @@
|
||||
import { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type';
|
||||
import { countPromptTokens } from '../../common/string/tiktoken/index';
|
||||
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
||||
import { ChatItemValueTypeEnum, ChatRoleEnum } from '@fastgpt/global/core/chat/constants';
|
||||
import {
|
||||
getPluginInputsFromStoreNodes,
|
||||
getPluginRunContent
|
||||
} from '@fastgpt/global/core/app/plugin/utils';
|
||||
import { StoreNodeItemType } from '@fastgpt/global/core/workflow/type/node';
|
||||
import { UserChatItemType } from '@fastgpt/global/core/chat/type';
|
||||
|
||||
/* filter search result */
|
||||
export const filterSearchResultsByMaxChars = async (
|
||||
@@ -23,3 +31,25 @@ export const filterSearchResultsByMaxChars = async (
|
||||
|
||||
return results.length === 0 ? list.slice(0, 1) : results;
|
||||
};
|
||||
|
||||
/* Get plugin runtime input user query */
|
||||
export const getPluginRunUserQuery = (
|
||||
nodes: StoreNodeItemType[],
|
||||
variables: Record<string, any>
|
||||
): UserChatItemType & { dataId: string } => {
|
||||
return {
|
||||
dataId: getNanoid(24),
|
||||
obj: ChatRoleEnum.Human,
|
||||
value: [
|
||||
{
|
||||
type: ChatItemValueTypeEnum.text,
|
||||
text: {
|
||||
content: getPluginRunContent({
|
||||
pluginInputs: getPluginInputsFromStoreNodes(nodes),
|
||||
variables
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
};
|
||||
|
@@ -25,11 +25,13 @@ export const authPluginByTmbId = async ({
|
||||
}) => {
|
||||
const { source } = await splitCombinePluginId(appId);
|
||||
if (source === PluginSourceEnum.personal) {
|
||||
await authAppByTmbId({
|
||||
const { app } = await authAppByTmbId({
|
||||
appId,
|
||||
tmbId,
|
||||
per
|
||||
});
|
||||
|
||||
return app;
|
||||
}
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user