fix: savechat.feat: extract flow

This commit is contained in:
archer
2023-08-01 21:51:54 +08:00
parent 58153306c5
commit ae95a8908e
18 changed files with 334 additions and 158 deletions

View File

@@ -6,7 +6,7 @@ interface Props extends TooltipProps {
forceShow?: boolean; forceShow?: boolean;
} }
const MyTooltip = ({ children, forceShow = false, ...props }: Props) => { const MyTooltip = ({ children, forceShow = false, shouldWrapChildren = true, ...props }: Props) => {
const { isPc } = useGlobalStore(); const { isPc } = useGlobalStore();
return isPc || forceShow ? ( return isPc || forceShow ? (
<Tooltip <Tooltip
@@ -21,6 +21,7 @@ const MyTooltip = ({ children, forceShow = false, ...props }: Props) => {
borderRadius={'8px'} borderRadius={'8px'}
whiteSpace={'pre-wrap'} whiteSpace={'pre-wrap'}
boxShadow={'1px 1px 10px rgba(0,0,0,0.2)'} boxShadow={'1px 1px 10px rgba(0,0,0,0.2)'}
shouldWrapChildren={shouldWrapChildren}
{...props} {...props}
> >
{children} {children}

View File

@@ -109,7 +109,6 @@ export const HistoryModule: FlowModuleTemplateType = {
] ]
}; };
const defaultModel = chatModelList[0];
export const ChatModule: FlowModuleTemplateType = { export const ChatModule: FlowModuleTemplateType = {
logo: '/imgs/module/AI.png', logo: '/imgs/module/AI.png',
name: 'AI 对话', name: 'AI 对话',
@@ -120,7 +119,7 @@ export const ChatModule: FlowModuleTemplateType = {
key: 'model', key: 'model',
type: FlowInputItemTypeEnum.custom, type: FlowInputItemTypeEnum.custom,
label: '对话模型', label: '对话模型',
value: defaultModel?.model, value: chatModelList[0]?.model,
list: chatModelList.map((item) => ({ label: item.name, value: item.model })) list: chatModelList.map((item) => ({ label: item.name, value: item.model }))
}, },
{ {
@@ -140,15 +139,15 @@ export const ChatModule: FlowModuleTemplateType = {
key: 'maxToken', key: 'maxToken',
type: FlowInputItemTypeEnum.custom, type: FlowInputItemTypeEnum.custom,
label: '回复上限', label: '回复上限',
value: defaultModel ? defaultModel.contextMaxToken / 2 : 2000, value: chatModelList[0] ? chatModelList[0].contextMaxToken / 2 : 2000,
min: 100, min: 100,
max: defaultModel?.contextMaxToken || 4000, max: chatModelList[0]?.contextMaxToken || 4000,
step: 50, step: 50,
markList: [ markList: [
{ label: '100', value: 100 }, { label: '100', value: 100 },
{ {
label: `${defaultModel?.contextMaxToken || 4000}`, label: `${chatModelList[0]?.contextMaxToken || 4000}`,
value: defaultModel?.contextMaxToken || 4000 value: chatModelList[0]?.contextMaxToken || 4000
} }
] ]
}, },
@@ -280,8 +279,10 @@ export const AnswerModule: FlowModuleTemplateType = {
key: SpecialInputKeyEnum.answerText, key: SpecialInputKeyEnum.answerText,
value: '', value: '',
type: FlowInputItemTypeEnum.textarea, type: FlowInputItemTypeEnum.textarea,
valueType: FlowValueTypeEnum.string,
label: '回复的内容', label: '回复的内容',
description: '可以使用 \\n 来实现换行' description:
'可以使用 \\n 来实现换行。也可以通过外部模块输入实现回复,外部模块输入时会覆盖当前填写的内容'
} }
], ],
outputs: [] outputs: []
@@ -407,13 +408,8 @@ export const ContextExtractModule: FlowModuleTemplateType = {
description: "由 '描述' 和 'key' 组成一个目标字段,可提取多个目标字段", description: "由 '描述' 和 'key' 组成一个目标字段,可提取多个目标字段",
value: [ value: [
{ {
key: 'a', key: 'key',
desc: '描述', desc: '目标字段',
required: true
},
{
key: 'n',
desc: '描述',
required: true required: true
} }
] ]
@@ -436,9 +432,16 @@ export const ContextExtractModule: FlowModuleTemplateType = {
}, },
{ {
key: ContextExtractEnum.fields, key: ContextExtractEnum.fields,
label: '提取结果', label: '完整提取结果',
description: '一个 JSON 对象,例如 {"name:":"YY","Time":"2023/7/2 18:00"}', description: '一个 JSON 对象,例如 {"name:":"YY","Time":"2023/7/2 18:00"}',
valueType: FlowValueTypeEnum.other, valueType: FlowValueTypeEnum.any,
type: FlowOutputItemTypeEnum.source,
targets: []
},
{
key: 'key',
label: '提取结果-目标字段',
valueType: FlowValueTypeEnum.string,
type: FlowOutputItemTypeEnum.source, type: FlowOutputItemTypeEnum.source,
targets: [] targets: []
} }
@@ -502,6 +505,9 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
outputs: [ outputs: [
{ {
key: 'userChatInput', key: 'userChatInput',
label: '用户问题',
type: 'source',
valueType: 'string',
targets: [ targets: [
{ {
moduleId: 'chatModule', moduleId: 'chatModule',
@@ -521,7 +527,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
inputs: [ inputs: [
{ {
key: 'maxContext', key: 'maxContext',
value: 10, value: 6,
connected: true connected: true
}, },
{ {
@@ -532,6 +538,9 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
outputs: [ outputs: [
{ {
key: 'history', key: 'history',
label: '聊天记录',
valueType: 'chat_history',
type: 'source',
targets: [ targets: [
{ {
moduleId: 'chatModule', moduleId: 'chatModule',
@@ -544,14 +553,14 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
{ {
moduleId: 'chatModule', moduleId: 'chatModule',
position: { position: {
x: 981.9682828103937, x: 998.0312473867093,
y: 890.014595014464 y: 803.8586941051353
}, },
flowType: 'chatNode', flowType: 'chatNode',
inputs: [ inputs: [
{ {
key: 'model', key: 'model',
value: 'gpt-3.5-turbo-16k', value: 'gpt-3.5-turbo',
connected: true connected: true
}, },
{ {
@@ -561,7 +570,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
}, },
{ {
key: 'maxToken', key: 'maxToken',
value: 8000, value: 2000,
connected: true connected: true
}, },
{ {
@@ -594,6 +603,17 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
outputs: [ outputs: [
{ {
key: 'answerText', key: 'answerText',
label: '模型回复',
description: '直接响应,无需配置',
type: 'hidden',
targets: []
},
{
key: 'finish',
label: '回复结束',
description: 'AI 回复完成后触发',
valueType: 'boolean',
type: 'source',
targets: [] targets: []
} }
] ]
@@ -616,8 +636,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
inputs: [ inputs: [
{ {
key: 'welcomeText', key: 'welcomeText',
value: value: '你好,我是 laf 助手,有什么可以帮助你的么?',
'我是 laf 助手,请问有什么可以帮助你的么?\n[laf 是什么?]\n[laf 官网是多少?]\n[交流群]',
connected: true connected: true
} }
], ],
@@ -639,6 +658,9 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
outputs: [ outputs: [
{ {
key: 'userChatInput', key: 'userChatInput',
label: '用户问题',
type: 'source',
valueType: 'string',
targets: [ targets: [
{ {
moduleId: 'chatModule', moduleId: 'chatModule',
@@ -655,14 +677,14 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
{ {
moduleId: 'history', moduleId: 'history',
position: { position: {
x: 458.37518916304566, x: 452.5466249541586,
y: 1296.7930057645262 y: 1276.3930310334215
}, },
flowType: 'historyNode', flowType: 'historyNode',
inputs: [ inputs: [
{ {
key: 'maxContext', key: 'maxContext',
value: 10, value: 6,
connected: true connected: true
}, },
{ {
@@ -673,6 +695,9 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
outputs: [ outputs: [
{ {
key: 'history', key: 'history',
label: '聊天记录',
valueType: 'chat_history',
type: 'source',
targets: [ targets: [
{ {
moduleId: 'chatModule', moduleId: 'chatModule',
@@ -697,7 +722,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
}, },
{ {
key: 'similarity', key: 'similarity',
value: 0.82, value: 0.8,
connected: true connected: true
}, },
{ {
@@ -717,15 +742,21 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
outputs: [ outputs: [
{ {
key: 'isEmpty', key: 'isEmpty',
label: '搜索结果为空',
type: 'source',
valueType: 'boolean',
targets: [ targets: [
{ {
moduleId: 'asv5cb', moduleId: 'chatModule',
key: 'switch' key: 'switch'
} }
] ]
}, },
{ {
key: 'unEmpty', key: 'unEmpty',
label: '搜索结果不为空',
type: 'source',
valueType: 'boolean',
targets: [ targets: [
{ {
moduleId: 'chatModule', moduleId: 'chatModule',
@@ -735,6 +766,10 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
}, },
{ {
key: 'quoteQA', key: 'quoteQA',
label: '引用内容',
description: '搜索结果为空时不返回',
type: 'source',
valueType: 'kb_quote',
targets: [ targets: [
{ {
moduleId: 'chatModule', moduleId: 'chatModule',
@@ -747,34 +782,34 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
{ {
moduleId: 'chatModule', moduleId: 'chatModule',
position: { position: {
x: 1521.114092861523, x: 1564.2820496250988,
y: 1038.6910820851604 y: 842.3852152224699
}, },
flowType: 'chatNode', flowType: 'chatNode',
inputs: [ inputs: [
{ {
key: 'model', key: 'model',
value: 'gpt-3.5-turbo-16k', value: 'gpt-3.5-turbo',
connected: true connected: true
}, },
{ {
key: 'temperature', key: 'temperature',
value: 5, value: 0,
connected: true connected: true
}, },
{ {
key: 'maxToken', key: 'maxToken',
value: 16000, value: 2000,
connected: true connected: true
}, },
{ {
key: 'systemPrompt', key: 'systemPrompt',
value: '知识库是关于 laf 的内容。', value: '',
connected: true connected: true
}, },
{ {
key: 'limitPrompt', key: 'limitPrompt',
value: '根据知识库回答用户问题,回答范围仅限知识库。', value: '',
connected: true connected: true
}, },
{ {
@@ -797,29 +832,20 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
outputs: [ outputs: [
{ {
key: 'answerText', key: 'answerText',
label: '模型回复',
description: '直接响应,无需配置',
type: 'hidden',
targets: []
},
{
key: 'finish',
label: '回复结束',
description: 'AI 回复完成后触发',
valueType: 'boolean',
type: 'source',
targets: [] targets: []
} }
] ]
},
{
moduleId: 'asv5cb',
position: {
x: 1517.320542832093,
y: 699.8757371712562
},
flowType: 'answerNode',
inputs: [
{
key: 'switch',
connected: true
},
{
key: 'text',
value: '对不起,我找不到你的问题,请更加详细的描述 laf 相关的问题。',
connected: true
}
],
outputs: []
} }
] ]
}, },
@@ -839,8 +865,53 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
inputs: [ inputs: [
{ {
key: 'welcomeText', key: 'welcomeText',
value: value: '你好,我可以为你翻译各种语言,请告诉我你需要翻译成什么语言?',
'你好,我是翻译助手,可以帮你把内容翻译成任何语言,请告诉我,你需要翻译成什么语言?', connected: true
}
],
outputs: []
},
{
moduleId: 'variable',
position: {
x: 444.0369195277651,
y: 1008.5185781784537
},
flowType: 'variable',
inputs: [
{
key: 'variables',
value: [
{
id: '35c640eb-cf22-431f-bb57-3fc21643880e',
key: 'language',
label: '目标语言',
type: 'input',
required: true,
maxLen: 50,
enums: [
{
value: ''
}
]
},
{
id: '2011ff08-91aa-4f60-ae69-f311ab4797b3',
key: 'language2',
label: '下拉框测试',
type: 'select',
required: false,
maxLen: 50,
enums: [
{
value: '英语'
},
{
value: '法语'
}
]
}
],
connected: true connected: true
} }
], ],
@@ -862,6 +933,9 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
outputs: [ outputs: [
{ {
key: 'userChatInput', key: 'userChatInput',
label: '用户问题',
type: 'source',
valueType: 'string',
targets: [ targets: [
{ {
moduleId: 'chatModule', moduleId: 'chatModule',
@@ -892,6 +966,9 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
outputs: [ outputs: [
{ {
key: 'history', key: 'history',
label: '聊天记录',
valueType: 'chat_history',
type: 'source',
targets: [ targets: [
{ {
moduleId: 'chatModule', moduleId: 'chatModule',
@@ -911,7 +988,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
inputs: [ inputs: [
{ {
key: 'model', key: 'model',
value: 'gpt-3.5-turbo-16k', value: 'gpt-3.5-turbo',
connected: true connected: true
}, },
{ {
@@ -921,7 +998,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
}, },
{ {
key: 'maxToken', key: 'maxToken',
value: 8000, value: 2000,
connected: true connected: true
}, },
{ {
@@ -931,7 +1008,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
}, },
{ {
key: 'limitPrompt', key: 'limitPrompt',
value: '把用户发送的内容直接翻译成{{language}},不要做其他回答。', value: '将我的问题直接翻译成英语{{language}}',
connected: true connected: true
}, },
{ {
@@ -954,39 +1031,20 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
outputs: [ outputs: [
{ {
key: 'answerText', key: 'answerText',
label: '模型回复',
description: '直接响应,无需配置',
type: 'hidden',
targets: []
},
{
key: 'finish',
label: '回复结束',
description: 'AI 回复完成后触发',
valueType: 'boolean',
type: 'source',
targets: [] targets: []
} }
] ]
},
{
moduleId: 'fo9i68',
position: {
x: 445.17843864558927,
y: 992.4891333735476
},
flowType: 'variable',
inputs: [
{
key: 'variables',
value: [
{
id: '9qjnai',
key: 'language',
label: '目标语言',
type: 'input',
required: true,
maxLen: 50,
enums: [
{
value: ''
}
]
}
],
connected: true
}
],
outputs: []
} }
] ]
}, },
@@ -1012,6 +1070,9 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
outputs: [ outputs: [
{ {
key: 'userChatInput', key: 'userChatInput',
label: '用户问题',
type: 'source',
valueType: 'string',
targets: [ targets: [
{ {
moduleId: 'remuj3', moduleId: 'remuj3',
@@ -1039,7 +1100,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
inputs: [ inputs: [
{ {
key: 'maxContext', key: 'maxContext',
value: 10, value: 6,
connected: true connected: true
}, },
{ {
@@ -1050,6 +1111,9 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
outputs: [ outputs: [
{ {
key: 'history', key: 'history',
label: '聊天记录',
valueType: 'chat_history',
type: 'source',
targets: [ targets: [
{ {
moduleId: 'nlfwkc', moduleId: 'nlfwkc',
@@ -1082,7 +1146,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
connected: true connected: true
}, },
{ {
key: SpecialInputKeyEnum.agents, key: 'agents',
value: [ value: [
{ {
value: '打招呼、问候等问题', value: '打招呼、问候等问题',
@@ -1093,8 +1157,12 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
key: 'fqsw' key: 'fqsw'
}, },
{ {
value: '其他问题', value: '商务问题',
key: 'fesw' key: 'fesw'
},
{
value: '其他问题',
key: 'oy1c'
} }
], ],
connected: true connected: true
@@ -1103,6 +1171,8 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
outputs: [ outputs: [
{ {
key: 'fasw', key: 'fasw',
label: '',
type: 'hidden',
targets: [ targets: [
{ {
moduleId: 'a99p6z', moduleId: 'a99p6z',
@@ -1112,6 +1182,8 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
}, },
{ {
key: 'fqsw', key: 'fqsw',
label: '',
type: 'hidden',
targets: [ targets: [
{ {
moduleId: 'fljhzy', moduleId: 'fljhzy',
@@ -1121,6 +1193,19 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
}, },
{ {
key: 'fesw', key: 'fesw',
label: '',
type: 'hidden',
targets: [
{
moduleId: '5v78ap',
key: 'switch'
}
]
},
{
key: 'oy1c',
label: '',
type: 'hidden',
targets: [ targets: [
{ {
moduleId: 'iejcou', moduleId: 'iejcou',
@@ -1153,8 +1238,8 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
{ {
moduleId: 'iejcou', moduleId: 'iejcou',
position: { position: {
x: 1301.7531189034548, x: 1294.2531189034548,
y: 1842.1297123368286 y: 2127.1297123368286
}, },
flowType: 'answerNode', flowType: 'answerNode',
inputs: [ inputs: [
@@ -1224,6 +1309,17 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
outputs: [ outputs: [
{ {
key: 'answerText', key: 'answerText',
label: '模型回复',
description: '直接响应,无需配置',
type: 'hidden',
targets: []
},
{
key: 'finish',
label: '回复结束',
description: 'AI 回复完成后触发',
valueType: 'boolean',
type: 'source',
targets: [] targets: []
} }
] ]
@@ -1249,6 +1345,9 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
outputs: [ outputs: [
{ {
key: 'history', key: 'history',
label: '聊天记录',
valueType: 'chat_history',
type: 'source',
targets: [ targets: [
{ {
moduleId: 'remuj3', moduleId: 'remuj3',
@@ -1268,7 +1367,11 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
inputs: [ inputs: [
{ {
key: 'kbList', key: 'kbList',
value: [], value: [
{
kbId: '646627f4f7b896cfd8910e24'
}
],
connected: true connected: true
}, },
{ {
@@ -1293,6 +1396,9 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
outputs: [ outputs: [
{ {
key: 'isEmpty', key: 'isEmpty',
label: '搜索结果为空',
type: 'source',
valueType: 'boolean',
targets: [ targets: [
{ {
moduleId: 'tc90wz', moduleId: 'tc90wz',
@@ -1302,6 +1408,9 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
}, },
{ {
key: 'unEmpty', key: 'unEmpty',
label: '搜索结果不为空',
type: 'source',
valueType: 'boolean',
targets: [ targets: [
{ {
moduleId: 'nlfwkc', moduleId: 'nlfwkc',
@@ -1311,6 +1420,10 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
}, },
{ {
key: 'quoteQA', key: 'quoteQA',
label: '引用内容',
description: '搜索结果为空时不返回',
type: 'source',
valueType: 'kb_quote',
targets: [ targets: [
{ {
moduleId: 'nlfwkc', moduleId: 'nlfwkc',
@@ -1356,6 +1469,26 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
} }
], ],
outputs: [] outputs: []
},
{
moduleId: '5v78ap',
position: {
x: 1294.814522053934,
y: 1822.7626988141562
},
flowType: 'answerNode',
inputs: [
{
key: 'switch',
connected: true
},
{
key: 'text',
value: '这是一个商务问题',
connected: true
}
],
outputs: []
} }
] ]
} }

View File

@@ -45,7 +45,7 @@ export enum FlowValueTypeEnum {
'boolean' = 'boolean', 'boolean' = 'boolean',
'chatHistory' = 'chat_history', 'chatHistory' = 'chat_history',
'kbQuote' = 'kb_quote', 'kbQuote' = 'kb_quote',
'other' = 'other' 'any' = 'any'
} }
export const FlowValueTypeStyle: Record<`${FlowValueTypeEnum}`, BoxProps> = { export const FlowValueTypeStyle: Record<`${FlowValueTypeEnum}`, BoxProps> = {
@@ -64,7 +64,7 @@ export const FlowValueTypeStyle: Record<`${FlowValueTypeEnum}`, BoxProps> = {
[FlowValueTypeEnum.kbQuote]: { [FlowValueTypeEnum.kbQuote]: {
background: '#A558C9' background: '#A558C9'
}, },
[FlowValueTypeEnum.other]: { [FlowValueTypeEnum.any]: {
background: '#9CA2A8' background: '#9CA2A8'
} }
}; };

View File

@@ -6,7 +6,7 @@ export const Input_Template_TFSwitch: FlowInputItemType = {
key: SystemInputEnum.switch, key: SystemInputEnum.switch,
type: FlowInputItemTypeEnum.target, type: FlowInputItemTypeEnum.target,
label: '触发器', label: '触发器',
valueType: FlowValueTypeEnum.boolean valueType: FlowValueTypeEnum.any
}; };
export const Input_Template_History: FlowInputItemType = { export const Input_Template_History: FlowInputItemType = {

View File

@@ -139,7 +139,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
// } // }
// save chat // save chat
if (typeof chatId === 'string') { if (chatId) {
await saveChat({ await saveChat({
chatId, chatId,
appId, appId,

View File

@@ -11,8 +11,7 @@ const NodeAnswer = ({
}: NodeProps<FlowModuleItemType>) => { }: NodeProps<FlowModuleItemType>) => {
return ( return (
<NodeCard minW={'400px'} moduleId={moduleId} {...props}> <NodeCard minW={'400px'} moduleId={moduleId} {...props}>
<Divider text="Input" /> <Container borderTop={'2px solid'} borderTopColor={'myGray.200'}>
<Container>
<RenderInput moduleId={moduleId} onChangeNode={onChangeNode} flowInputList={inputs} /> <RenderInput moduleId={moduleId} onChangeNode={onChangeNode} flowInputList={inputs} />
</Container> </Container>
</NodeCard> </NodeCard>

View File

@@ -55,7 +55,7 @@ const NodeCQNode = ({
onChangeNode({ onChangeNode({
moduleId, moduleId,
type: 'outputs', type: 'outputs',
key: agentKey, key: '',
value: newOutputVal value: newOutputVal
}); });
}} }}

View File

@@ -13,6 +13,8 @@ import RenderOutput from '../render/RenderOutput';
import MyIcon from '@/components/Icon'; import MyIcon from '@/components/Icon';
import ExtractFieldModal from '../modules/ExtractFieldModal'; import ExtractFieldModal from '../modules/ExtractFieldModal';
import { ContextExtractEnum } from '@/constants/flow/flowField'; import { ContextExtractEnum } from '@/constants/flow/flowField';
import SourceHandle from '../render/SourceHandle';
import { FlowOutputItemTypeEnum, FlowValueTypeEnum } from '@/constants/flow';
const NodeExtract = ({ const NodeExtract = ({
data: { inputs, outputs, moduleId, onChangeNode, ...props } data: { inputs, outputs, moduleId, onChangeNode, ...props }
@@ -36,7 +38,22 @@ const NodeExtract = ({
key: string; key: string;
value?: ContextExtractAgentItemType[]; value?: ContextExtractAgentItemType[];
}) => ( }) => (
<Box> <Box pt={2}>
<Box position={'absolute'} top={0} right={0}>
<Button
variant={'base'}
leftIcon={<AddIcon fontSize={'10px'} />}
onClick={() =>
setEditExtractField({
desc: '',
key: '',
required: true
})
}
>
</Button>
</Box>
<TableContainer> <TableContainer>
<Table> <Table>
<Thead> <Thead>
@@ -49,10 +66,10 @@ const NodeExtract = ({
</Thead> </Thead>
<Tbody> <Tbody>
{extractKeys.map((item, index) => ( {extractKeys.map((item, index) => (
<Tr key={index}> <Tr key={index} position={'relative'}>
<Td>{item.key}</Td> <Td>{item.key}</Td>
<Td whiteSpace={'pre-line'} wordBreak={'break-all'}> <Td whiteSpace={'pre-line'} wordBreak={'break-all'}>
{item.desc}{' '} {item.desc}
</Td> </Td>
<Td>{item.required ? '✔' : ''}</Td> <Td>{item.required ? '✔' : ''}</Td>
<Td whiteSpace={'nowrap'}> <Td whiteSpace={'nowrap'}>
@@ -70,11 +87,24 @@ const NodeExtract = ({
w={'16px'} w={'16px'}
cursor={'pointer'} cursor={'pointer'}
onClick={() => { onClick={() => {
const newInputValue = extractKeys.filter(
(extract) => item.key !== extract.key
);
const newOutputVal = outputs.filter(
(output) => output.key !== item.key
);
onChangeNode({ onChangeNode({
moduleId, moduleId,
type: 'inputs', type: 'inputs',
key: ContextExtractEnum.extractKeys, key: ContextExtractEnum.extractKeys,
value: extractKeys.filter((extract) => item.key !== extract.key) value: newInputValue
});
onChangeNode({
moduleId,
type: 'outputs',
key: '',
value: newOutputVal
}); });
}} }}
/> />
@@ -84,21 +114,6 @@ const NodeExtract = ({
</Tbody> </Tbody>
</Table> </Table>
</TableContainer> </TableContainer>
<Box mt={2} textAlign={'right'}>
<Button
variant={'base'}
leftIcon={<AddIcon fontSize={'10px'} />}
onClick={() =>
setEditExtractField({
desc: '',
key: '',
required: true
})
}
>
</Button>
</Box>
</Box> </Box>
) )
}} }}
@@ -119,21 +134,39 @@ const NodeExtract = ({
const exists = extracts.find((item) => item.key === editExtractFiled.key); const exists = extracts.find((item) => item.key === editExtractFiled.key);
if (exists) { const newInputs = exists
onChangeNode({ ? extracts.map((item) => (item.key === editExtractFiled.key ? data : item))
moduleId, : extracts.concat(data);
type: 'inputs', const newOutputs = exists
key: ContextExtractEnum.extractKeys, ? outputs.map((output) =>
value: extracts.map((item) => (item.key === editExtractFiled.key ? data : item)) output.key === editExtractFiled.key
}); ? {
} else { ...output,
onChangeNode({ key: data.key,
moduleId, label: `提取结果-${data.desc}`
type: 'inputs', }
key: ContextExtractEnum.extractKeys, : output
value: extracts.concat(data) )
}); : outputs.concat({
} key: data.key,
label: `提取结果-${data.desc}`,
valueType: FlowValueTypeEnum.string,
type: FlowOutputItemTypeEnum.source,
targets: []
});
onChangeNode({
moduleId,
type: 'inputs',
key: ContextExtractEnum.extractKeys,
value: newInputs
});
onChangeNode({
moduleId,
type: 'outputs',
key: '',
value: newOutputs
});
setEditExtractField(undefined); setEditExtractField(undefined);
}} }}

View File

@@ -35,7 +35,7 @@ export const Label = ({
)} )}
{description && ( {description && (
<MyTooltip label={description} forceShow> <MyTooltip label={description} forceShow>
<QuestionOutlineIcon display={['none', 'inline']} transform={'translateY(-1px)'} ml={1} /> <QuestionOutlineIcon display={['none', 'inline']} ml={1} />
</MyTooltip> </MyTooltip>
)} )}
</Box> </Box>

View File

@@ -17,14 +17,14 @@ const Label = ({
<Flex as={'label'} justifyContent={'right'} alignItems={'center'} position={'relative'}> <Flex as={'label'} justifyContent={'right'} alignItems={'center'} position={'relative'}>
{description && ( {description && (
<MyTooltip label={description} forceShow> <MyTooltip label={description} forceShow>
<QuestionOutlineIcon display={['none', 'inline']} transform={'translateY(-1px)'} mr={1} /> <QuestionOutlineIcon display={['none', 'inline']} mr={1} />
</MyTooltip> </MyTooltip>
)} )}
{children} {children}
</Flex> </Flex>
); );
const RenderBody = ({ flowOutputList }: { flowOutputList: FlowOutputItemType[] }) => { const RenderOutput = ({ flowOutputList }: { flowOutputList: FlowOutputItemType[] }) => {
return ( return (
<> <>
{flowOutputList.map( {flowOutputList.map(
@@ -44,4 +44,4 @@ const RenderBody = ({ flowOutputList }: { flowOutputList: FlowOutputItemType[] }
); );
}; };
export default React.memo(RenderBody); export default RenderOutput;

View File

@@ -14,8 +14,8 @@ const SourceHandle = ({ handleKey, valueType, ...props }: Props) => {
() => () =>
valueType valueType
? FlowValueTypeStyle[valueType] ? FlowValueTypeStyle[valueType]
: (FlowValueTypeStyle[FlowValueTypeEnum.other] as any), : (FlowValueTypeStyle[FlowValueTypeEnum.any] as any),
[] [valueType]
); );
return ( return (

View File

@@ -15,7 +15,7 @@ const TargetHandle = ({ handleKey, valueType, onConnect, ...props }: Props) => {
() => () =>
valueType valueType
? FlowValueTypeStyle[valueType] ? FlowValueTypeStyle[valueType]
: (FlowValueTypeStyle[FlowValueTypeEnum.other] as any), : (FlowValueTypeStyle[FlowValueTypeEnum.any] as any),
[] []
); );

View File

@@ -132,7 +132,7 @@ const AppEdit = ({ app, fullScreen, onFullScreen }: Props) => {
connected: item.type !== FlowInputItemTypeEnum.target connected: item.type !== FlowInputItemTypeEnum.target
})), })),
outputs: item.data.outputs.map((item) => ({ outputs: item.data.outputs.map((item) => ({
key: item.key, ...item,
targets: [] as FlowOutputTargetItemType[] targets: [] as FlowOutputTargetItemType[]
})) }))
})); }));
@@ -254,7 +254,11 @@ const AppEdit = ({ app, fullScreen, onFullScreen }: Props) => {
title: t('app.Connection is invalid') title: t('app.Connection is invalid')
}); });
} }
if (sourceType !== targetType) { if (
sourceType !== FlowValueTypeEnum.any &&
targetType !== FlowValueTypeEnum.any &&
sourceType !== targetType
) {
return toast({ return toast({
status: 'warning', status: 'warning',
title: t('app.Connection type is different') title: t('app.Connection type is different')
@@ -280,6 +284,7 @@ const AppEdit = ({ app, fullScreen, onFullScreen }: Props) => {
const { mutate: onclickSave, isLoading } = useRequest({ const { mutate: onclickSave, isLoading } = useRequest({
mutationFn: () => { mutationFn: () => {
console.log(flow2AppModules(), '====');
return updateAppDetail(app._id, { return updateAppDetail(app._id, {
modules: flow2AppModules() modules: flow2AppModules()
}); });

View File

@@ -96,7 +96,6 @@ export async function dispatchContentExtract({
return {}; return {};
} }
})(); })();
console.log(adaptMessages, arg);
// auth fields // auth fields
let success = !extractKeys.find((item) => !arg[item.key]); let success = !extractKeys.find((item) => !arg[item.key]);
@@ -109,6 +108,7 @@ export async function dispatchContentExtract({
} }
} }
} }
console.log(arg, '====');
const tokens = response.data.usage?.total_tokens || 0; const tokens = response.data.usage?.total_tokens || 0;
@@ -116,6 +116,7 @@ export async function dispatchContentExtract({
[ContextExtractEnum.success]: success ? true : undefined, [ContextExtractEnum.success]: success ? true : undefined,
[ContextExtractEnum.failed]: success ? undefined : true, [ContextExtractEnum.failed]: success ? undefined : true,
[ContextExtractEnum.fields]: arg, [ContextExtractEnum.fields]: arg,
...arg,
[TaskResponseKeyEnum.responseData]: { [TaskResponseKeyEnum.responseData]: {
moduleName: ChatModuleEnum.Extract, moduleName: ChatModuleEnum.Extract,
price: userOpenaiAccount?.key ? 0 : countModelPrice({ model: agentModel, tokens }), price: userOpenaiAccount?.key ? 0 : countModelPrice({ model: agentModel, tokens }),

View File

@@ -36,7 +36,7 @@ export async function saveChat({
if (chatHistory) { if (chatHistory) {
promise.push( promise.push(
Chat.findOneAndUpdate( Chat.findOneAndUpdate(
{ chatId }, { chatId, userId },
{ {
$push: { $push: {
content: { content: {

View File

@@ -64,13 +64,12 @@ export type VariableItemType = {
/* app module */ /* app module */
export type AppModuleInputItemType = { key: string; value?: any; connected?: boolean }; export type AppModuleInputItemType = { key: string; value?: any; connected?: boolean };
export type AppModuleOutputItemType = { key: string; targets: FlowOutputTargetItemType[] };
export type AppModuleItemType = { export type AppModuleItemType = {
moduleId: string; moduleId: string;
position?: XYPosition; position?: XYPosition;
flowType: `${FlowModuleTypeEnum}`; flowType: `${FlowModuleTypeEnum}`;
inputs: AppModuleInputItemType[]; inputs: AppModuleInputItemType[];
outputs: AppModuleOutputItemType[]; outputs: FlowOutputItemType[];
}; };
export type AppItemType = { export type AppItemType = {

View File

@@ -39,10 +39,10 @@ export type FlowOutputTargetItemType = {
}; };
export type FlowOutputItemType = { export type FlowOutputItemType = {
key: string; // 字段名 key: string; // 字段名
label: string; label?: string;
description?: string; description?: string;
valueType?: `${FlowValueTypeEnum}`; valueType?: `${FlowValueTypeEnum}`;
type: `${FlowOutputItemTypeEnum}`; type?: `${FlowOutputItemTypeEnum}`;
targets: FlowOutputTargetItemType[]; targets: FlowOutputTargetItemType[];
}; };

View File

@@ -73,6 +73,10 @@ export const appModule2FlowNode = ({
const template = const template =
ModuleTemplatesFlat.find((template) => template.flowType === item.flowType) || EmptyModule; ModuleTemplatesFlat.find((template) => template.flowType === item.flowType) || EmptyModule;
const mergeOutputs = item.outputs.concat(
template.outputs.filter((output) => !item.outputs.find((item) => item.key === output.key))
);
// replace item data // replace item data
const moduleItem: FlowModuleItemType = { const moduleItem: FlowModuleItemType = {
...item, ...item,
@@ -85,14 +89,14 @@ export const appModule2FlowNode = ({
value: itemInput.value value: itemInput.value
}; };
}), }),
outputs: template.outputs.map((templateOutput) => { // 合并 template 和数据库,文案以 template 为准
outputs: mergeOutputs.map((output) => {
// unChange outputs // unChange outputs
const itemOutput = const templateOutput = template.outputs.find((item) => item.key === output.key);
item.outputs.find((item) => item.key === templateOutput.key) || templateOutput;
return { return {
...templateOutput, ...(templateOutput ? templateOutput : output),
targets: itemOutput.targets || [] targets: output.targets || []
}; };
}), }),
onChangeNode, onChangeNode,
@@ -131,5 +135,6 @@ export const appModule2FlowEdge = ({
}) })
) )
); );
return edges; return edges;
}; };