From 514c08a93295fe8cb7d7c578e297545f9ef968df Mon Sep 17 00:00:00 2001 From: so95 Date: Mon, 12 May 2025 16:15:19 +0700 Subject: [PATCH] add show debug (#7390) ### What problem does this PR solve? add show debug ![Recording2025-04-28142829-ezgif com-video-to-gif-converter](https://github.com/user-attachments/assets/0c67da34-c2b6-428f-ae9b-b5b21464885c) ### Type of change - [x] New Feature (non-breaking change which adds functionality) --- .gitignore | 2 + agent/canvas.py | 6 +- agent/component/base.py | 5 +- agent/component/categorize.py | 2 + agent/component/generate.py | 4 +- agent/component/keyword.py | 2 + api/apps/canvas_app.py | 2 - web/src/locales/en.ts | 1 + web/src/pages/flow/canvas/node/popover.tsx | 308 +++++++++++++++++---- 9 files changed, 267 insertions(+), 65 deletions(-) diff --git a/.gitignore b/.gitignore index 904202681..b9c688dcc 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,5 @@ nltk_data/ # Exclude hash-like temporary files like 9b5ad71b2ce5302211f9c61530b329a4922fc6a4 *[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]* .lh/ +.venv +docker/data diff --git a/agent/canvas.py b/agent/canvas.py index 3b22128b3..302b98c5f 100644 --- a/agent/canvas.py +++ b/agent/canvas.py @@ -17,7 +17,6 @@ import logging import json from copy import deepcopy from functools import partial - import pandas as pd from agent.component import component_class @@ -362,4 +361,7 @@ class Canvas: return self.components["begin"]["obj"]._param.query def get_component_input_elements(self, cpnnm): - return self.components[cpnnm]["obj"].get_input_elements() \ No newline at end of file + return self.components[cpnnm]["obj"].get_input_elements() + + def set_component_infor(self, cpn_id, infor): + self.components[cpn_id]["obj"].set_infor(infor) diff --git a/agent/component/base.py b/agent/component/base.py index f03c5d107..15b3c345e 100644 --- a/agent/component/base.py +++ b/agent/component/base.py @@ -34,6 +34,7 @@ _IS_RAW_CONF = "_is_raw_conf" class ComponentParamBase(ABC): def __init__(self): self.output_var_name = "output" + self.infor_var_name = "infor" self.message_history_window_size = 22 self.query = [] self.inputs = [] @@ -462,6 +463,9 @@ class ComponentBase(ABC): def set_output(self, v): setattr(self._param, self._param.output_var_name, v) + def set_infor(self, v): + setattr(self._param, self._param.infor_var_name, v) + def _fetch_outputs_from(self, sources: list[dict[str, Any]]) -> list[pd.DataFrame]: outs = [] for q in sources: @@ -488,7 +492,6 @@ class ComponentBase(ABC): elif q.get("value"): outs.append(pd.DataFrame([{"content": q["value"]}])) return outs - def get_input(self): if self._param.debug_inputs: return pd.DataFrame([{"content": v["value"]} for v in self._param.debug_inputs if v.get("value")]) diff --git a/agent/component/categorize.py b/agent/component/categorize.py index 4d8715f09..9171f809a 100644 --- a/agent/component/categorize.py +++ b/agent/component/categorize.py @@ -85,6 +85,8 @@ class Categorize(Generate, ABC): input = self.get_input() input = " - ".join(input["content"]) if "content" in input else "" chat_mdl = LLMBundle(self._canvas.get_tenant_id(), LLMType.CHAT, self._param.llm_id) + self._canvas.set_component_infor(self._id, {"prompt":self._param.get_prompt(input),"messages": [{"role": "user", "content": "\nCategory: "}],"conf": self._param.gen_conf()}) + ans = chat_mdl.chat(self._param.get_prompt(input), [{"role": "user", "content": "\nCategory: "}], self._param.gen_conf()) logging.debug(f"input: {input}, answer: {str(ans)}") diff --git a/agent/component/generate.py b/agent/component/generate.py index 7972f77d7..ed0eeeeee 100644 --- a/agent/component/generate.py +++ b/agent/component/generate.py @@ -201,7 +201,7 @@ class Generate(ComponentBase): msg.append({"role": "user", "content": "Output: "}) ans = chat_mdl.chat(msg[0]["content"], msg[1:], self._param.gen_conf()) ans = re.sub(r"^.*", "", ans, flags=re.DOTALL) - + self._canvas.set_component_infor(self._id, {"prompt":msg[0]["content"],"messages": msg[1:],"conf": self._param.gen_conf()}) if self._param.cite and "chunks" in retrieval_res.columns: res = self.set_cite(retrieval_res, ans) return pd.DataFrame([res]) @@ -234,7 +234,7 @@ class Generate(ComponentBase): if self._param.cite and "chunks" in retrieval_res.columns: res = self.set_cite(retrieval_res, answer) yield res - + self._canvas.set_component_infor(self._id, {"prompt":msg[0]["content"],"messages": msg[1:],"conf": self._param.gen_conf()}) self.set_output(Generate.be_output(res)) def debug(self, **kwargs): diff --git a/agent/component/keyword.py b/agent/component/keyword.py index 4a0b54f28..a34a1ad46 100644 --- a/agent/component/keyword.py +++ b/agent/component/keyword.py @@ -58,6 +58,8 @@ class KeywordExtract(Generate, ABC): chat_mdl = LLMBundle(self._canvas.get_tenant_id(), LLMType.CHAT, self._param.llm_id) + self._canvas.set_component_infor(self._id, {"prompt":self._param.get_prompt(),"messages": [{"role": "user", "content": query}],"conf": self._param.gen_conf()}) + ans = chat_mdl.chat(self._param.get_prompt(), [{"role": "user", "content": query}], self._param.gen_conf()) diff --git a/api/apps/canvas_app.py b/api/apps/canvas_app.py index 6a9787f6c..efb1e1cd3 100644 --- a/api/apps/canvas_app.py +++ b/api/apps/canvas_app.py @@ -26,7 +26,6 @@ from api.utils.api_utils import get_json_result, server_error_response, validate from agent.canvas import Canvas from peewee import MySQLDatabase, PostgresqlDatabase from api.db.db_models import APIToken -import logging import time @manager.route('/templates', methods=['GET']) # noqa: F821 @@ -89,7 +88,6 @@ def save(): @login_required def get(canvas_id): e, c = UserCanvasService.get_by_tenant_id(canvas_id) - logging.info(f"get canvas_id: {canvas_id} c: {c}") if not e: return get_data_error_result(message="canvas not found.") return get_json_result(data=c) diff --git a/web/src/locales/en.ts b/web/src/locales/en.ts index 82c3a367c..b98574c60 100644 --- a/web/src/locales/en.ts +++ b/web/src/locales/en.ts @@ -1258,6 +1258,7 @@ This delimiter is used to split the input text into several text pieces echo of promptTip: 'Use the system prompt to describe the task for the LLM, specify how it should respond, and outline other miscellaneous requirements. The system prompt is often used in conjunction with keys (variables), which serve as various data inputs for the LLM. Use a forward slash `/` or the (x) button to show the keys to use.', promptMessage: 'Prompt is required', + infor: 'Information run', knowledgeBasesTip: 'Select the knowledge bases to associate with this chat assistant, or choose variables containing knowledge base IDs below.', knowledgeBaseVars: 'Knowledge base variables', diff --git a/web/src/pages/flow/canvas/node/popover.tsx b/web/src/pages/flow/canvas/node/popover.tsx index 342ce40eb..871aa8064 100644 --- a/web/src/pages/flow/canvas/node/popover.tsx +++ b/web/src/pages/flow/canvas/node/popover.tsx @@ -1,11 +1,15 @@ import { useFetchFlow } from '@/hooks/flow-hooks'; import get from 'lodash/get'; -import React, { MouseEventHandler, useCallback, useMemo } from 'react'; +import React, { + MouseEventHandler, + useCallback, + useMemo, + useState, +} from 'react'; import JsonView from 'react18-json-view'; import 'react18-json-view/src/style.css'; import { useReplaceIdWithText } from '../../hooks'; -import { useTheme } from '@/components/theme-provider'; import { Popover, PopoverContent, @@ -20,6 +24,17 @@ import { TableRow, } from '@/components/ui/table'; import { useTranslate } from '@/hooks/common-hooks'; +import { + Button, + Card, + Col, + Input, + Row, + Space, + Tabs, + Typography, + message, +} from 'antd'; import { useGetComponentLabelByValue } from '../../hooks/use-get-begin-query'; interface IProps extends React.PropsWithChildren { @@ -31,7 +46,8 @@ export function NextNodePopover({ children, nodeId, name }: IProps) { const { t } = useTranslate('flow'); const { data } = useFetchFlow(); - const { theme } = useTheme(); + console.log(data); + const component = useMemo(() => { return get(data, ['dsl', 'components', nodeId], {}); }, [nodeId, data]); @@ -42,6 +58,11 @@ export function NextNodePopover({ children, nodeId, name }: IProps) { [], ); const output = get(component, ['obj', 'output'], {}); + const { conf, messages, prompt } = get( + component, + ['obj', 'params', 'infor'], + {}, + ); const { replacedOutput } = useReplaceIdWithText(output); const stopPropagation: MouseEventHandler = useCallback((e) => { e.stopPropagation(); @@ -49,6 +70,13 @@ export function NextNodePopover({ children, nodeId, name }: IProps) { const getLabel = useGetComponentLabelByValue(nodeId); + const [inputPage, setInputPage] = useState(1); + const pageSize = 3; + const pagedInputs = inputs.slice( + (inputPage - 1) * pageSize, + inputPage * pageSize, + ); + return ( @@ -59,62 +87,226 @@ export function NextNodePopover({ children, nodeId, name }: IProps) { side={'right'} sideOffset={20} onClick={stopPropagation} - className="w-[400px]" + className="w-[800px] p-4" + style={{ maxHeight: 600, overflow: 'auto' }} > -
- {name} {t('operationResults')} -
-
-
- {t('input')} -
- - - - {t('componentId')} - {t('content')} - - - - {inputs.map((x, idx) => ( - - {getLabel(x.component_id)} - {x.content} - - ))} - -
-
-
-
- {t('output')} -
- -
-
-
+ + + {name} {t('operationResults')} + + + + + + + {t('componentId')} + + {t('content')} + + + + + {pagedInputs.map((x, idx) => ( + + {getLabel(x.component_id)} + + {x.content} + + + ))} + +
+ {/* Pagination */} + {inputs.length > pageSize && ( + + + + + {inputPage} / {Math.ceil(inputs.length / pageSize)} + + + + + )} + + ), + }, + { + key: 'output', + label: t('output'), + children: ( + + + + ), + }, + { + key: 'infor', + label: t('infor'), + children: ( + + + + {conf && ( + + + Configuration: + + + + )} + {prompt && ( + + + + + Prompt: + + + + + + + + + )} + + + {messages && ( + + + Messages: + +
+ +
+
+ )} + +
+
+ ), + }, + ]} + />
);