From ddad57529d4f0dd2017b7e1d3fe6873f3c8215cf Mon Sep 17 00:00:00 2001 From: yorn <1057707203@qq.com> Date: Mon, 10 Nov 2025 20:40:08 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E8=AF=84=E6=9F=A5?= =?UTF-8?q?=E7=82=B9=E8=AE=BE=E7=BD=AE=E4=B8=AD=E7=9A=84=E5=A4=9A=E6=A8=A1?= =?UTF-8?q?=E6=80=81=E6=8A=BD=E5=8F=96=E8=AE=BE=E7=BD=AE=E7=9A=84=E9=80=BB?= =?UTF-8?q?=E8=BE=91=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rules/new/ExtractionSettings.tsx | 329 ++++++++++-------- app/models/evaluation_points.ts | 66 ++-- app/routes/rules-new.tsx | 182 +++++++++- 3 files changed, 395 insertions(+), 182 deletions(-) diff --git a/app/components/rules/new/ExtractionSettings.tsx b/app/components/rules/new/ExtractionSettings.tsx index ef5fb89..abb3331 100644 --- a/app/components/rules/new/ExtractionSettings.tsx +++ b/app/components/rules/new/ExtractionSettings.tsx @@ -54,14 +54,14 @@ export function ExtractionSettings({ llm: initialData?.extraction_config?.llm ?? { fields: [], prompt_setting: { - type: "system", + type: "llm_default_prompt", template: "", }, }, vlm: initialData?.extraction_config?.vlm ?? { fields: [], prompt_setting: { - type: "system", + type: "vlm_default_prompt", template: "", }, }, @@ -84,11 +84,13 @@ export function ExtractionSettings({ vlm: initialData?.extraction_config?.vlm?.fields || [] }); // VLM字段类型 - const [selectedVlmFieldType, setSelectedVlmFieldType] = useState('default'); + const [selectedVlmFieldType, setSelectedVlmFieldType] = useState('vlm_default_prompt'); + // 自定义字段的提示词模板 + const [customVlmPrompt, setCustomVlmPrompt] = useState('请识别文档中的印章信息,提取以下字段'); // 提示词类型 const [promptType, setPromptType] = useState({ - llm: initialData?.extraction_config?.llm?.prompt_setting?.type || 'system', - vlm: initialData?.extraction_config?.vlm?.prompt_setting?.type || 'system' + llm: initialData?.extraction_config?.llm?.prompt_setting?.type || 'llm_default_prompt', + vlm: initialData?.extraction_config?.vlm?.prompt_setting?.type || 'vlm_default_prompt' }); // 提示词模板 const [selectedTemplate, setSelectedTemplate] = useState({ @@ -115,6 +117,20 @@ export function ExtractionSettings({ setCurrentTab(tab); }; + // 初始化自定义字段的提示词 + useEffect(() => { + // 在编辑模式下,如果有自定义类型的字段,加载其 template + const vlmFields = initialData?.extraction_config?.vlm?.fields || []; + const customField = vlmFields.find( + (f: string | { name: string; type: string; template?: string }) => + typeof f === 'object' && f.type === 'custom' && f.template + ); + + if (customField && typeof customField === 'object' && customField.template) { + setCustomVlmPrompt(customField.template); + } + }, [initialData]); + // 自动保存字段变更状态 // 这个效果确保添加字段后自动保存到组件状态,但不自动提交更新 useEffect(() => { @@ -125,15 +141,15 @@ export function ExtractionSettings({ const initialRegexFields = initialData?.extraction_config?.regex?.fields || []; const initialLlmPrompt = initialData?.extraction_config?.llm?.prompt_setting?.template || ''; const initialVlmPrompt = initialData?.extraction_config?.vlm?.prompt_setting?.template || ''; - + // 检查是否有实际变化 const hasLlmFieldsChanged = JSON.stringify(fields.llm) !== JSON.stringify(initialLlmFields); const hasVlmFieldsChanged = JSON.stringify(fields.vlm) !== JSON.stringify(initialVlmFields); const hasRegexFieldsChanged = JSON.stringify(regexFields) !== JSON.stringify(initialRegexFields); - const hasPromptContentChanged = - promptContent.llm !== initialLlmPrompt || + const hasPromptContentChanged = + promptContent.llm !== initialLlmPrompt || promptContent.vlm !== initialVlmPrompt; - + // 只有实际发生变化时才设置为true if (hasLlmFieldsChanged || hasVlmFieldsChanged || hasRegexFieldsChanged || hasPromptContentChanged) { setHasPendingChanges(true); @@ -169,17 +185,26 @@ export function ExtractionSettings({ } else { const newFields = [...fields.vlm]; inputs.forEach(input => { - const exists = newFields.some(field => - typeof field === 'string' - ? field === input + const exists = newFields.some(field => + typeof field === 'string' + ? field === input : field.name === input ); - + if (!exists) { - newFields.push({ - name: input, - type: selectedVlmFieldType as VLMFieldType - }); + // 如果是自定义类型,添加 template 字段 + if (selectedVlmFieldType === 'custom') { + newFields.push({ + name: input, + type: selectedVlmFieldType as VLMFieldType, + template: customVlmPrompt + }); + } else { + newFields.push({ + name: input, + type: selectedVlmFieldType as VLMFieldType + }); + } } }); setFields({ ...fields, vlm: newFields }); @@ -190,7 +215,7 @@ export function ExtractionSettings({ ...inputValue, [type]: '' }); - + setHasPendingChanges(true); }; @@ -218,46 +243,60 @@ export function ExtractionSettings({ }; // 获取VLM字段信息 - const getFieldInfo = (fieldString: string) => { - const parts = fieldString.split('_'); - const fieldName = parts[0]; - const fieldType = parts.length > 1 ? parts[1] : 'default'; - - let typeName, badgeClass; + const getFieldInfo = (field: string | { name: string, type: string, template?: string }) => { + let fieldName, fieldType, typeName, badgeClass; + + if (typeof field === 'string') { + const parts = field.split('_'); + fieldName = parts[0]; + fieldType = parts.length > 1 ? parts[1] : 'default'; + } else { + fieldName = field.name; + fieldType = field.type; + } + switch (fieldType) { - case 'currency': + case 'vlm_default_prompt': + typeName = '默认'; + badgeClass = 'bg-gray-100 text-gray-800'; + break; + case 'vlm_currency_prompt': typeName = '货币'; badgeClass = 'bg-green-100 text-green-800'; break; - case 'print': + case 'vlm_print_prompt': typeName = '打印'; badgeClass = 'bg-blue-100 text-blue-800'; break; - case 'seal': + case 'vlm_seal_prompt': typeName = '印章'; badgeClass = 'bg-red-100 text-red-800'; break; - case 'cross-seal': + case 'vlm_acrossPageSeal_prompt': typeName = '骑缝章'; badgeClass = 'bg-orange-100 text-orange-800'; break; - case 'english': + case 'vlm_english_prompt': typeName = '英文'; badgeClass = 'bg-purple-100 text-purple-800'; break; - case 'number': + case 'vlm_number_prompt': typeName = '数字'; badgeClass = 'bg-yellow-100 text-yellow-800'; break; - case 'handwriting': + case 'vlm_handwriting_prompt': typeName = '手写'; badgeClass = 'bg-pink-100 text-pink-800'; break; + case 'custom': + typeName = '自定义'; + badgeClass = 'bg-indigo-100 text-indigo-800'; + break; default: typeName = '默认'; badgeClass = 'bg-gray-100 text-gray-800'; } - + return { fieldName, fieldType, typeName, badgeClass }; }; @@ -270,7 +309,12 @@ export function ExtractionSettings({ value={value} onChange={(e) => handlePromptTypeChange(e, type)} > - {EVALUATION_OPTIONS.promptTypeOptions.map((option) => ( + {type === 'llm' && EVALUATION_OPTIONS.llmPromptTypeOptions.map((option) => ( + + ))} + {type === 'vlm' && EVALUATION_OPTIONS.vlmPromptTypeOptions.map((option) => ( @@ -436,7 +480,18 @@ export function ExtractionSettings({ const handleUpdateFields = () => { // 过滤掉没有字段名的正则字段 const validRegexFields = regexFields.filter(field => field.field.trim() !== ''); - + + // 更新所有自定义类型字段的 template + const updatedVlmFields = fields.vlm.map(field => { + if (typeof field === 'object' && field.type === 'custom') { + return { + ...field, + template: customVlmPrompt + }; + } + return field; + }); + // 收集所有字段数据 const updatedFormData = { ...formData, @@ -444,14 +499,14 @@ export function ExtractionSettings({ llm: { fields: fields.llm, prompt_setting: { - type: promptType.llm, + type: promptType.llm || 'llm_default_prompt', template: promptType.llm === 'custom' ? promptContent.llm : '' } }, vlm: { - fields: fields.vlm, + fields: updatedVlmFields, prompt_setting: { - type: promptType.vlm, + type: promptType.vlm || 'vlm_default_prompt', template: promptType.vlm === 'custom' ? promptContent.vlm : '' } }, @@ -620,7 +675,7 @@ export function ExtractionSettings({ className="bg-gray-50 p-2 rounded text-xs text-gray-600 mb-2" id="llm-system-prompt-info" style={{ - display: promptType.llm === "system" ? "block" : "none", + display: promptType.llm === "llm_default_prompt" ? "block" : "none", }} > 系统将根据评查点类型和抽取目标自动生成适合的提示词,您无需额外配置。 @@ -745,12 +800,7 @@ export function ExtractionSettings({
- 支持的变量 - (点击变量将其添加到提示词中): -
-+ 支持的变量 + (点击变量将其添加到提示词中): +
+