From d27d39c74d49eb7347f33c34e9a0a9095814d1c4 Mon Sep 17 00:00:00 2001 From: ayang <473033518@qq.com> Date: Mon, 1 Dec 2025 17:17:55 +0800 Subject: [PATCH] fix: fixed parameter issues between the model and the assistant --- web/src/locales/langs/en-us/page.ts | 37 +++- web/src/locales/langs/zh-cn/page.ts | 20 +- .../modules/AvailableVariable.tsx | 57 ++++++ .../pages/ai-assistant/modules/DeepThink.tsx | 1 + .../pages/ai-assistant/modules/EditForm.tsx | 65 ++++--- .../pages/ai-assistant/modules/MCPConfig.tsx | 3 +- .../ai-assistant/modules/ModelSelect.tsx | 11 +- .../ai-assistant/modules/UploadConfig.tsx | 173 +++++++++--------- web/src/pages/ai-assistant/new/index.tsx | 82 +++++---- web/src/pages/model-provider/new/index.tsx | 63 +++++-- 10 files changed, 333 insertions(+), 179 deletions(-) create mode 100644 web/src/pages/ai-assistant/modules/AvailableVariable.tsx diff --git a/web/src/locales/langs/en-us/page.ts b/web/src/locales/langs/en-us/page.ts index c7ebd9e2a..9e4f67b1b 100644 --- a/web/src/locales/langs/en-us/page.ts +++ b/web/src/locales/langs/en-us/page.ts @@ -82,20 +82,30 @@ const page: App.I18n.Schema['translation']['page'] = { 'The scope of selected vocabulary is limited. The lower the value, the more predictable the result; the higher the value, the more diverse the possibilities. It is not recommended to change this alongside randomness.', type: 'Type', upload: 'Upload Settings', - internet_search: 'Internet Search', + internet_search: 'Search', document_retrieval: 'Document Retrieval', feature_visibility: 'Feature Visibility', - large_model_tool: 'Large Model Tool', - tool_invoked_model: 'Tool-invoked Model', + large_model_tool: 'LLM Tool', + tool_invoked_model: 'Caller Model', prompt_template: 'Prompt Template', mcp_service: 'MCP Server', - built_in_large_model_tool: 'Built-in Large Model Tool', - intent_recognition: 'Intent Recognition', - intent_recognition_model: 'Intent Recognition Model', - feature_visibility_deep_thought: 'Feature Visibility (Deep Thought)', + built_in_large_model_tool: 'Built-in LLM Tool', + intent_recognition: 'Intent Analysis', + intent_recognition_model: 'Intent Analysis Model', + feature_visibility_deep_thought: 'Feature Visibility (Deep Think)', generate_response: 'Generate Response', capability_extension: 'Capability Extension', - workflow_configuration: 'Workflow Configuration' + workflow_configuration: 'Workflow Configuration', + executionStrategy: 'Execution Strategy', + availableVariables: 'Available Variables', + availableVariablesDesc: 'List of available variables', + searchContext: 'Search Results Context', + userQuery: 'User Query', + chatHistory: 'Chat History', + toolList: 'Tool List', + webSources: 'Network Sources List', + detectedIntent: 'Detected Intent', + matchedDocs: 'Retrieved Documents' }, mode: { deep_think: 'Deep Think', @@ -103,7 +113,14 @@ const page: App.I18n.Schema['translation']['page'] = { workflow: 'External workflow' }, hints: { - system_prompt: 'Please enter the system prompt instructions' + system_prompt: 'Please enter the system prompt instructions', + searchExecutionStrategy: + 'The model determines whether to execute the process based on context, query intent, etc.', + llmExecutionStrategy: 'Execute the process whether or not the model deems it necessary.' + }, + options: { + intelligentDecisionMaking: 'Intelligent Decision Making', + alwaysExecute: 'Always Execute' } }, connector: { @@ -724,7 +741,7 @@ const page: App.I18n.Schema['translation']['page'] = { inferenceMode: 'Inference Mode' }, options: { - dialogModel: 'Dialog Model' + dialogModel: 'Chat Model' }, hints: { selectOrInputModel: 'Select or input a model', diff --git a/web/src/locales/langs/zh-cn/page.ts b/web/src/locales/langs/zh-cn/page.ts index 2430da201..d2be863e4 100644 --- a/web/src/locales/langs/zh-cn/page.ts +++ b/web/src/locales/langs/zh-cn/page.ts @@ -90,7 +90,17 @@ const page: App.I18n.Schema['translation']['page'] = { feature_visibility_deep_thought: '功能可见性(深度思考)', generate_response: '生成回答', capability_extension: '能力扩展', - workflow_configuration: '流程配置' + workflow_configuration: '流程配置', + executionStrategy: '执行策略', + availableVariables: '可用变量', + availableVariablesDesc: '可用的变量', + searchContext: '搜索结果上下文', + userQuery: '用户查询内容', + chatHistory: '对话历史', + toolList: '工具列表', + webSources: '网络来源列表', + detectedIntent: '识别到的意图', + matchedDocs: '匹配到的文档' }, mode: { deep_think: '深度思考', @@ -98,7 +108,13 @@ const page: App.I18n.Schema['translation']['page'] = { workflow: '外部工作流' }, hints: { - system_prompt: '请输入系统提示词' + system_prompt: '请输入系统提示词', + searchExecutionStrategy: '由模型根据上下文、查询意图等判断是否执行该流程。', + llmExecutionStrategy: '无论模型是否认为必要,都执行该流程。' + }, + options: { + intelligentDecisionMaking: '智能决策', + alwaysExecute: '总是执行' } }, connector: { diff --git a/web/src/pages/ai-assistant/modules/AvailableVariable.tsx b/web/src/pages/ai-assistant/modules/AvailableVariable.tsx new file mode 100644 index 000000000..458b8813c --- /dev/null +++ b/web/src/pages/ai-assistant/modules/AvailableVariable.tsx @@ -0,0 +1,57 @@ +import { Flex, Popover } from 'antd'; +import { Info } from 'lucide-react'; +import type { FC } from 'react'; + +interface AvailableVariableProps { + readonly type: 'answering_model' | 'caller_model' | 'intent_analysis_model' | 'picking_doc_model'; +} + +const AvailableVariable: FC = props => { + const { type } = props; + const { t } = useTranslation(); + + const variables: Record = { + answering_model: [ + `{{.context}} ${t('page.assistant.labels.searchContext')}`, + `{{.query}} ${t('page.assistant.labels.userQuery')}` + ], + caller_model: [], + intent_analysis_model: [ + `{{.history}} ${t('page.assistant.labels.chatHistory')}`, + `{{.tool_list}} ${t('page.assistant.labels.toolList')}`, + `{{.network_sources}} ${t('page.assistant.labels.webSources')}`, + `{{.query}} ${t('page.assistant.labels.userQuery')}` + ], + picking_doc_model: [ + `{{.query}} ${t('page.assistant.labels.userQuery')}`, + `{{.intent}} ${t('page.assistant.labels.detectedIntent')}`, + `{{.docs}} ${t('page.assistant.labels.matchedDocs')}` + ] + }; + + return ( + variables[type].length !== 0 && ( + + {variables[type].map(variable => ( + {variable} + ))} + + } + > +
+ {t('page.assistant.labels.availableVariables')} + + +
+
+ ) + ); +}; + +export default AvailableVariable; diff --git a/web/src/pages/ai-assistant/modules/DeepThink.tsx b/web/src/pages/ai-assistant/modules/DeepThink.tsx index e4cd59b1e..caa17f176 100644 --- a/web/src/pages/ai-assistant/modules/DeepThink.tsx +++ b/web/src/pages/ai-assistant/modules/DeepThink.tsx @@ -19,6 +19,7 @@ export const DeepThink = (props: DeepThinkProps) => { > diff --git a/web/src/pages/ai-assistant/modules/EditForm.tsx b/web/src/pages/ai-assistant/modules/EditForm.tsx index 94eed59f0..bac36bc04 100644 --- a/web/src/pages/ai-assistant/modules/EditForm.tsx +++ b/web/src/pages/ai-assistant/modules/EditForm.tsx @@ -12,13 +12,14 @@ import { DatasourceConfig } from './DatasourceConfig'; import { MCPConfig } from './MCPConfig'; import { DeepThink } from './DeepThink'; import { formatESSearchResult } from '@/service/request/es'; -import ModelSelect from './ModelSelect'; +import ModelSelect, { DefaultPromptTemplates } from './ModelSelect'; import { ToolsConfig } from './ToolsConfig'; import { getUUID } from '@/utils/common'; import { Tags } from '@/components/common/tags'; import { getAssistantCategory } from '@/service/api/assistant'; import { UploadConfig } from './UploadConfig'; import classNames from 'classnames'; +import AvailableVariable from './AvailableVariable'; interface AssistantFormProps { initialValues: any; @@ -91,7 +92,7 @@ export const EditForm = memo((props: AssistantFormProps) => { }, []); const { defaultRequiredRule, formRules } = useFormRules(); - const [showAdvanced, setShowAdvanced] = useState(true); + const [showAdvanced, setShowAdvanced] = useState(false); const { data: result, run, @@ -184,6 +185,7 @@ export const EditForm = memo((props: AssistantFormProps) => { return ( { key: 'internet-search', label: t('page.assistant.labels.internet_search'), extra: ( - { + event.stopPropagation(); + }} > - - + + + + ), children: ( <> @@ -221,20 +230,20 @@ export const EditForm = memo((props: AssistantFormProps) => { <> { > @@ -506,6 +524,7 @@ export const EditForm = memo((props: AssistantFormProps) => { > { {assistantMode === 'simple' && ( } + initialValue={DefaultPromptTemplates.answering_model} label={t('page.assistant.labels.role_prompt')} - name={['prompt', 'template']} + name={['answering_model', 'prompt', 'template']} > { tags. }; export default (props: any) => { - const { value: propsValue, onChange, providers = [], width, modelType, showTemplate = true } = props; + const { value: propsValue, onChange, providers = [], width, modelType, showTemplate = true, namePrefix = [] } = props; let defaultPromptTpl = ''; if (DefaultPromptTemplates[modelType]) { defaultPromptTpl = DefaultPromptTemplates[modelType]; @@ -286,10 +288,11 @@ export default (props: any) => { {showTemplate && ( } initialValue={defaultPromptTpl} label={t('page.assistant.labels.prompt_template')} layout='vertical' - name={['prompt', 'template']} + name={[...namePrefix, 'prompt', 'template']} > diff --git a/web/src/pages/ai-assistant/modules/UploadConfig.tsx b/web/src/pages/ai-assistant/modules/UploadConfig.tsx index 321fb07f2..0b55539bb 100644 --- a/web/src/pages/ai-assistant/modules/UploadConfig.tsx +++ b/web/src/pages/ai-assistant/modules/UploadConfig.tsx @@ -1,4 +1,5 @@ import { Input, InputNumber, Select, Space, Switch } from 'antd'; +import classNames from 'classnames'; interface UploadConfigProps { readonly value?: any; @@ -56,100 +57,102 @@ export const UploadConfig = (props: UploadConfigProps) => { return ( -
- -
-
- -

{t('page.assistant.labels.allowed_file_extensions')}

- + + {value.enabled && ( + <> + { - const newValue = e.target.value.replace(/[.\s]/g, ''); - onChange?.({ - ...value, - allowed_file_extensions: newValue ? newValue.split(',') : [] - }); - }} - /> - -
-
- -

{t('page.assistant.labels.max_file_size_in_bytes')}

- { - setMaxFileSize({ - ...maxFileSize, - unit: v - }); - onChange?.({ - ...value, - max_file_size_in_bytes: maxFileSize.value * v - }); - }} - > - B - KB - MB - GB - - } - onChange={v => { - setMaxFileSize({ - ...maxFileSize, - value: v || 1 - }); - onChange?.({ - ...value, - max_file_size_in_bytes: (v || 1) * maxFileSize.unit - }); - }} - /> -
-
-
- -

{t('page.assistant.labels.max_file_count')}

- { - onChange?.({ - ...value, - max_file_count: v - }); - }} - /> -
-
- {/*
+ direction='vertical' + > +

{t('page.assistant.labels.allowed_file_extensions')}

+ { + const newValue = e.target.value.replace(/[.\s]/g, ''); + onChange?.({ + ...value, + allowed_file_extensions: newValue ? newValue.split(',') : [] + }); + }} + /> + + + +

{t('page.assistant.labels.max_file_size_in_bytes')}

+ { + setMaxFileSize({ + ...maxFileSize, + unit: v + }); + onChange?.({ + ...value, + max_file_size_in_bytes: maxFileSize.value * v + }); + }} + > + B + KB + MB + GB + + } + onChange={v => { + setMaxFileSize({ + ...maxFileSize, + value: v || 1 + }); + onChange?.({ + ...value, + max_file_size_in_bytes: (v || 1) * maxFileSize.unit + }); + }} + /> +
+ + +

{t('page.assistant.labels.max_file_count')}

+ { + onChange?.({ + ...value, + max_file_count: v + }); + }} + /> +
+ + {/*

{t("page.assistant.labels.caller_model")}

*/} + + )} ); }; diff --git a/web/src/pages/ai-assistant/new/index.tsx b/web/src/pages/ai-assistant/new/index.tsx index fe96f8660..8444f7603 100644 --- a/web/src/pages/ai-assistant/new/index.tsx +++ b/web/src/pages/ai-assistant/new/index.tsx @@ -1,6 +1,5 @@ - -import {EditForm} from "../modules/EditForm"; -import {createAssistant} from "@/service/api/assistant"; +import { EditForm } from '../modules/EditForm'; +import { createAssistant } from '@/service/api/assistant'; export function Component() { const { t } = useTranslation(); @@ -8,42 +7,43 @@ export function Component() { const initialValues = { enabled: true, chat_settings: { - greeting_message: "Hi! I’m Coco, nice to meet you. I can help answer your questions by tapping into the internet and your data sources. How can I assist you today?", + greeting_message: + 'Hi! I’m Coco, nice to meet you. I can help answer your questions by tapping into the internet and your data sources. How can I assist you today?', suggested: { enabled: false, - questions: [], + questions: [] }, - history_message:{ + history_message: { compression_threshold: 1000, summary: true, - number: 5, - }, + number: 5 + } }, model_settings: { temperature: 0.5, top_p: 0.5, presence_penalty: 0, frequency_penalty: 0, - max_tokens: 4000, + max_tokens: 4000 }, - datasource:{ - ids: ["*"], - enabled: true, + datasource: { + ids: ['*'], + enabled: false, visible: true }, - mcp_servers:{ - ids: ["*"], - enabled: true, + mcp_servers: { + ids: ['*'], + enabled: false, visible: true }, - upload:{ - allowed_file_extensions: ["*"], + upload: { + allowed_file_extensions: ['*'], max_file_size_in_bytes: 1024 * 1024, max_file_count: 6, - enabled: false, + enabled: false }, - keepalive: "30m", - type: "simple", + keepalive: '30m', + type: 'simple' }; const [loading, setLoading] = useState(false); @@ -52,40 +52,42 @@ export function Component() { ...values, datasource: { ...(values.datasource || {}), - ids: values.datasource?.ids?.includes('*') ? ['*'] : values.datasource?.ids, + ids: values.datasource?.ids?.includes('*') ? ['*'] : values.datasource?.ids } }; - + setLoading(true); - createAssistant(params).then((res)=>{ - if(res?.data?.result === 'created') { - window.$message?.success(t('common.addSuccess')); - nav(`/ai-assistant/list`) - } - }).finally(()=>{ - setLoading(false); - }) - } + createAssistant(params) + .then(res => { + if (res?.data?.result === 'created') { + window.$message?.success(t('common.addSuccess')); + nav(`/ai-assistant/list`); + } + }) + .finally(() => { + setLoading(false); + }); + }; return ( -
+
-
-
+
+
{t(`route.ai-assistant_new`)}
-
+
- ) -} \ No newline at end of file + ); +} diff --git a/web/src/pages/model-provider/new/index.tsx b/web/src/pages/model-provider/new/index.tsx index 875e60583..97d0dccb7 100644 --- a/web/src/pages/model-provider/new/index.tsx +++ b/web/src/pages/model-provider/new/index.tsx @@ -10,6 +10,8 @@ import { ModalForm, ProFormSelect, ProFormSwitch, ProFormText } from '@ant-desig import type { AnyObject } from 'antd/es/_util/type'; // @ts-ignore import { IconSelector } from '../../connector/new/icon_selector'; +import { Settings } from 'lucide-react'; +import { isArray } from 'lodash'; export function Component() { const { t } = useTranslation(); @@ -225,6 +227,8 @@ export const ModelsComponent = ({ value = [], onChange }: any) => { }; const [form] = Form.useForm(); + const [modelOpen, setModelOpen] = useState(false); + const [editKey, setEditKey] = useState(); return ( <> @@ -243,10 +247,18 @@ export const ModelsComponent = ({ value = [], onChange }: any) => { {value?.settings?.reasoning ? t('page.modelprovider.labels.inferenceMode') : '-'} , - onSettingsChange(key, settings)} + { + form.setFieldsValue({ + ...value + }); + + setEditKey(key); + + setModelOpen(true); + }} />,
{ {t('common.add')}} width={560} modalProps={{ centered: true, - destroyOnClose: true + destroyOnClose: true, + onCancel: () => { + setEditKey(undefined); + setModelOpen(false); + } }} onFinish={async values => { - setInnerValue([ - ...innerValue, - { - key: getUUID(), - value: { - ...values, - name: values.name[0] - } - } - ]); + const name = isArray(values.name) ? values.name[0] : values.name; + + const matched = innerValue.find(item => item.key === editKey); + + if (matched) { + setInnerValue(prev => { + return prev.map(item => { + if (item.key === editKey) { + return { + ...item, + value: { + ...item.value, + ...values, + name + } + }; + } + + return item; + }); + }); + + return setModelOpen(false); + } + + setInnerValue(prev => [...prev, { key: getUUID(), value: { ...values, name } }]); return true; }}