diff --git a/graph/test/dsl_examples/intergreper.json b/graph/test/dsl_examples/interpreter.json similarity index 100% rename from graph/test/dsl_examples/intergreper.json rename to graph/test/dsl_examples/interpreter.json diff --git a/web/src/assets/svg/nothing.svg b/web/src/assets/svg/nothing.svg new file mode 100644 index 000000000..dbbad2d4b --- /dev/null +++ b/web/src/assets/svg/nothing.svg @@ -0,0 +1,24 @@ + + + + + + + + + \ No newline at end of file diff --git a/web/src/hooks/flow-hooks.ts b/web/src/hooks/flow-hooks.ts index 8dc501a65..5bb8af6cd 100644 --- a/web/src/hooks/flow-hooks.ts +++ b/web/src/hooks/flow-hooks.ts @@ -5,6 +5,44 @@ import flowService from '@/services/flow-service'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { message } from 'antd'; import { useParams } from 'umi'; +import { v4 as uuid } from 'uuid'; + +export const EmptyDsl = { + graph: { + nodes: [ + { + id: 'Begin', + type: 'beginNode', + position: { + x: 50, + y: 200, + }, + data: { + label: 'Begin', + name: 'begin', + }, + sourcePosition: 'left', + targetPosition: 'right', + }, + ], + edges: [], + }, + components: { + begin: { + obj: { + component_name: 'Begin', + params: {}, + }, + downstream: ['Answer:China'], // other edge target is downstream, edge source is current node id + upstream: [], // edge source is upstream, edge target is current node id + }, + }, + messages: [], + reference: [], + history: [], + path: [], + answer: [], +}; export const useFetchFlowTemplates = (): ResponseType => { const { data } = useQuery({ @@ -12,6 +50,14 @@ export const useFetchFlowTemplates = (): ResponseType => { initialData: [], queryFn: async () => { const { data } = await flowService.listTemplates(); + if (Array.isArray(data?.data)) { + data.data.unshift({ + id: uuid(), + title: 'Blank', + description: 'Create from nothing', + dsl: EmptyDsl, + }); + } return data; }, diff --git a/web/src/pages/flow/hooks.ts b/web/src/pages/flow/hooks.ts index 4a5ce7439..6581da68c 100644 --- a/web/src/pages/flow/hooks.ts +++ b/web/src/pages/flow/hooks.ts @@ -253,7 +253,7 @@ export const useValidateConnection = () => { // restricted lines cannot be connected successfully. const isValidConnection = useCallback( (connection: Connection) => { - // limit there to be only one line between two nodes + // limit the connection between two nodes to only one connection line in one direction const hasLine = edges.some( (x) => x.source === connection.source && x.target === connection.target, ); diff --git a/web/src/pages/flow/interpreter.json b/web/src/pages/flow/interpreter.json new file mode 100644 index 000000000..8bc5f149d --- /dev/null +++ b/web/src/pages/flow/interpreter.json @@ -0,0 +1,75 @@ +{ + "edges": [ + { + "id": "c87c7805-8cf0-4cd4-b45b-152031811020", + "label": "", + "source": "begin", + "target": "answer:0" + }, + { + "id": "e30320bb-601b-4885-acb3-79becdc49f08", + "label": "", + "source": "generate:0", + "target": "answer:0" + }, + { + "id": "83927e42-739a-402a-9f75-a88d4fab37ed", + "label": "", + "source": "answer:0", + "target": "generate:0" + } + ], + "nodes": [ + { + "id": "begin", + "type": "beginNode", + "position": { + "x": 0, + "y": 0 + }, + "data": { + "label": "Begin", + "name": "FruityPianosSend", + "form": { + "prologue": "Hi there! Please enter the text you want to translate in format like: 'text you want to translate' => target language. For an example: 您好! => English" + } + }, + "sourcePosition": "left", + "targetPosition": "right" + }, + { + "id": "answer:0", + "type": "ragNode", + "position": { + "x": 0, + "y": 0 + }, + "data": { + "label": "Answer", + "name": "YummyBoatsFlow", + "form": {} + }, + "sourcePosition": "left", + "targetPosition": "right" + }, + { + "id": "generate:0", + "type": "ragNode", + "position": { + "x": 0, + "y": 0 + }, + "data": { + "label": "Generate", + "name": "SwiftTramsDrop", + "form": { + "llm_id": "deepseek-chat", + "prompt": "You are an professional interpreter.\n- Role: an professional interpreter.\n- Input format: content need to be translated => target language. \n- Answer format: => translated content in target language. \n- Examples:\n - user: 您好! => English. assistant: => How are you doing!\n - user: You look good today. => Japanese. assistant: => 今日は調子がいいですね 。\n", + "temperature": 0.5 + } + }, + "sourcePosition": "left", + "targetPosition": "right" + } + ] +} diff --git a/web/src/pages/flow/list/create-flow-modal.tsx b/web/src/pages/flow/list/create-flow-modal.tsx index e344f6f9c..8a11e5687 100644 --- a/web/src/pages/flow/list/create-flow-modal.tsx +++ b/web/src/pages/flow/list/create-flow-modal.tsx @@ -1,8 +1,8 @@ +import { ReactComponent as NothingIcon } from '@/assets/svg/nothing.svg'; import { IModalManagerChildrenProps } from '@/components/modal-manager'; import { useTranslate } from '@/hooks/commonHooks'; import { useFetchFlowTemplates } from '@/hooks/flow-hooks'; import { useSelectItem } from '@/hooks/logicHooks'; -import { UserOutlined } from '@ant-design/icons'; import { Avatar, Card, @@ -79,7 +79,7 @@ const CreateFlowModal = ({ - Choose from templates + Create from templates {list?.map((x) => ( - } src={x.avatar} /> + {x.avatar ? ( + } src={x.avatar} /> + ) : ( + + )} {x.title}

{x.description}

diff --git a/web/src/pages/flow/list/hooks.ts b/web/src/pages/flow/list/hooks.ts index 8b4ff74f9..6b191d4ad 100644 --- a/web/src/pages/flow/list/hooks.ts +++ b/web/src/pages/flow/list/hooks.ts @@ -11,6 +11,8 @@ import { useNavigate } from 'umi'; // import dslJson from '../../../../../dls.json'; // import customerServiceBase from '../../../../../graph/test/dsl_examples/customer_service.json'; // import customerService from '../customer_service.json'; +// import interpreterBase from '../../../../../graph/test/dsl_examples/interpreter.json'; +// import interpreter from '../interpreter.json'; export const useFetchDataOnMount = () => { const { data, loading } = useFetchFlowList(); @@ -41,7 +43,7 @@ export const useSaveFlow = () => { title, dsl, // dsl: dslJson, - // dsl: { ...customerServiceBase, graph: customerService }, + // dsl: { ...interpreterBase, graph: interpreter }, }); if (ret?.retcode === 0) { diff --git a/web/src/pages/flow/message-form/index.tsx b/web/src/pages/flow/message-form/index.tsx index 64138474f..aafcde546 100644 --- a/web/src/pages/flow/message-form/index.tsx +++ b/web/src/pages/flow/message-form/index.tsx @@ -54,7 +54,8 @@ const MessageForm = ({ onValuesChange, form }: IOperatorForm) => { ]} noStyle > - diff --git a/web/src/pages/flow/utils.test.ts b/web/src/pages/flow/utils.test.ts index c8487c879..6491f83f2 100644 --- a/web/src/pages/flow/utils.test.ts +++ b/web/src/pages/flow/utils.test.ts @@ -2,6 +2,7 @@ import fs from 'fs'; import path from 'path'; import customer_service from '../../../../graph/test/dsl_examples/customer_service.json'; import headhunter_zh from '../../../../graph/test/dsl_examples/headhunter_zh.json'; +import interpreter from '../../../../graph/test/dsl_examples/interpreter.json'; import { dsl } from './mock'; import { buildNodesAndEdgesFromDSLComponents } from './utils'; @@ -68,3 +69,21 @@ test('build nodes and edges from customer_service dsl', () => { } expect(nodes.length).toEqual(12); }); + +test('build nodes and edges from interpreter dsl', () => { + const { edges, nodes } = buildNodesAndEdgesFromDSLComponents( + interpreter.components, + ); + console.info('node length', nodes.length); + console.info('edge length', edges.length); + try { + fs.writeFileSync( + path.join(__dirname, 'interpreter.json'), + JSON.stringify({ edges, nodes }, null, 4), + ); + console.log('JSON data is saved.'); + } catch (error) { + console.warn(error); + } + expect(nodes.length).toEqual(12); +});