From a3cafcb67212dd18d0151b2008a3299cfca15710 Mon Sep 17 00:00:00 2001 From: admin <572701190@qq.com> Date: Sun, 19 Apr 2026 04:26:16 +0800 Subject: [PATCH] =?UTF-8?q?fix(ai):=20AI=E8=B6=8A=E7=95=8C=E7=94=9F?= =?UTF-8?q?=E6=88=90=E2=80=94=E2=80=94Prompt=E5=A2=9E=E5=8A=A0=E5=86=85?= =?UTF-8?q?=E5=AE=B9=E8=BE=B9=E7=95=8C=E7=BA=A6=E6=9D=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - systemPrompt去掉'基于全局信息补充完善'诱导性措辞,改为明确【内容边界】警告 - systemPrompt明确告知AI:全局参考仅供理解上下文,updatedHtml只能包含目标区域本身内容 - promptText增加⚠️防越界指令:明确列出禁止混入的模块类型(术后情况、标本描述、病理结果、签名等) --- src/pages/ReportEditor.tsx | 4 +-- 工程分析/20260419_0424/实现方案.md | 43 ++++++++++++++++++++++++++ 工程分析/20260419_0424/测试方案.md | 49 ++++++++++++++++++++++++++++++ 工程分析/20260419_0424/需求分析.md | 34 +++++++++++++++++++++ 工程分析/经验记录.md | 25 +++++++++++++++ 5 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 工程分析/20260419_0424/实现方案.md create mode 100644 工程分析/20260419_0424/测试方案.md create mode 100644 工程分析/20260419_0424/需求分析.md diff --git a/src/pages/ReportEditor.tsx b/src/pages/ReportEditor.tsx index 3bcb59b..81121a3 100644 --- a/src/pages/ReportEditor.tsx +++ b/src/pages/ReportEditor.tsx @@ -892,7 +892,7 @@ export default function ReportEditor() { if (aiModifyEnabled && targetRegionEl) { promptText += `【你需要进行修改的目标区域 HTML 源码】:\n${currentHtml || '(当前区域为空)'}\n\n`; } - promptText += `【医生指令】: ${text}\n\n【格式要求】:\n1. 生成完整、结构化的多段落 HTML 内容,不要只改写现有段落\n2. 段落使用

标签,段落之间不要使用
标签或换行符\n3. 输出紧凑 HTML,标签间不要有空格或换行`; + promptText += `【医生指令】: ${text}\n\n【格式要求】:\n1. 仅针对【目标区域】的主题生成对应的多段落 HTML 内容\n2. ⚠️ 绝对禁止将【全局参考内容】中的其他模块(如:基本信息、术后情况、标本描述、病理结果、医生签名、日期等)生成并混入你的输出中!你只能输出该区域应有的内容\n3. 段落使用

标签,段落之间不要使用
标签或换行符\n4. 输出紧凑 HTML,标签间不要有空格或换行`; if (allImages.length > 0) { messageContent = []; allImages.forEach(url => { @@ -903,7 +903,7 @@ export default function ReportEditor() { messageContent = promptText; } const systemPrompt = aiModifyEnabled - ? '你是一名专业的外科医生助理。当前处于【修改模式】。\n我为你提供了当前手术报告的【全局参考内容】作为背景知识,以及你需要修改的【目标区域 HTML 源码】。\n请根据全局内容和用户的【医生指令】,直接重写并输出目标区域的 HTML。\n重要指令:\n1. 必须返回合法的 JSON 对象\n2. 必须包含 "reply"(简短回复话术)和 "updatedHtml"(修改后的完整内部 HTML 代码)两个字段\n3. updatedHtml 必须生成完整、结构化的多段落内容,不要只改写现有段落,要基于全局信息补充完善\n4. 段落必须使用

标签包裹,段落之间绝对不要使用
标签,也不要使用任何换行符 (\\n)\n5. 输出的 HTML 必须紧凑,标签之间不要有空格或换行\n6. 绝对不要包含任何 Markdown 标记(如 ```json)' + ? '你是一名专业的外科医生助理。当前处于【修改模式】。\n我为你提供了当前手术报告的【全局参考内容】作为背景知识,以及你需要修改的【目标区域 HTML 源码】。\n请根据用户的【医生指令】,直接重写并输出目标区域的 HTML。\n\n重要指令:\n1. 必须返回合法的 JSON 对象\n2. 必须包含 "reply"(简短回复)和 "updatedHtml"(修改后的完整 HTML 代码)两个字段\n3. 【内容边界】:全局参考内容仅供你理解上下文。你的 updatedHtml 只能包含目标区域本身的内容(例如:如果目标区域是"手术步骤",你就只写步骤)。严禁输出签名、落款、术后总结等属于报告其他部分的结构!\n4. 段落必须使用

标签包裹,段落间绝对不要使用
标签,也不要使用换行符 (\\n)\n5. 输出的 HTML 必须紧凑,标签之间不要有空格或换行\n6. 绝对不要包含任何 Markdown 标记(如 ```json)' : '你是一名专业的外科医生助理。当前处于【对话模式】。\n请仔细阅读我提供的【全局手术报告参考内容】,并根据【医生指令】进行专业解答。\n重要指令:\n1. 必须返回合法的 JSON 对象\n2. 仅包含 "reply"(你的专业回答)一个字段\n3. 不要返回任何 HTML 代码\n4. 绝对不要包含任何 Markdown 标记'; const response = await fetch(`${apiEndpoint}/chat/completions`, { method: 'POST', diff --git a/工程分析/20260419_0424/实现方案.md b/工程分析/20260419_0424/实现方案.md new file mode 100644 index 0000000..c61a121 --- /dev/null +++ b/工程分析/20260419_0424/实现方案.md @@ -0,0 +1,43 @@ +# 实现方案 + +## 修改文件 +- `src/pages/ReportEditor.tsx` + +## 修改位置 1:Prompt 文本增加内容边界约束(约 line 895) + +**原代码**: +```tsx + promptText += `【医生指令】: ${text}\n\n【格式要求】:\n1. 生成完整、结构化的多段落 HTML 内容,不要只改写现有段落\n2. 段落使用

标签,段落之间不要使用
标签或换行符\n3. 输出紧凑 HTML,标签间不要有空格或换行`; +``` + +**新代码**: +```tsx + promptText += `【医生指令】: ${text}\n\n【格式要求】:\n1. 仅针对【目标区域】的主题生成对应的多段落 HTML 内容\n2. ⚠️ 绝对禁止将【全局参考内容】中的其他模块(如:基本信息、术后情况、标本描述、病理结果、医生签名、日期等)生成并混入你的输出中!你只能输出该区域应有的内容\n3. 段落使用

标签,段落之间不要使用
标签或换行符\n4. 输出紧凑 HTML,标签间不要有空格或换行`; +``` + +**变更点**: +1. 第 1 点改为"仅针对【目标区域】的主题生成" +2. 新增第 2 点:用 ⚠️ 警告符号明确列出禁止混入的模块类型 +3. 原第 2-3 点顺延为第 3-4 点 + +## 修改位置 2:System Prompt 去掉"补充完善"、强化边界(约 line 905-907) + +**原代码**: +```tsx + const systemPrompt = aiModifyEnabled + ? '你是一名专业的外科医生助理。当前处于【修改模式】。\n我为你提供了当前手术报告的【全局参考内容】作为背景知识,以及你需要修改的【目标区域 HTML 源码】。\n请根据全局内容和用户的【医生指令】,直接重写并输出目标区域的 HTML。\n重要指令:\n1. 必须返回合法的 JSON 对象\n2. 必须包含 "reply"(简短回复话术)和 "updatedHtml"(修改后的完整内部 HTML 代码)两个字段\n3. updatedHtml 必须生成完整、结构化的多段落内容,不要只改写现有段落,要基于全局信息补充完善\n4. 段落必须使用

标签包裹,段落之间绝对不要使用
标签,也不要使用任何换行符 (\\n)\n5. 输出的 HTML 必须紧凑,标签之间不要有空格或换行\n6. 绝对不要包含任何 Markdown 标记(如 ```json)' + : '你是一名专业的外科医生助理。当前处于【对话模式】。\n请仔细阅读我提供的【全局手术报告参考内容】,并根据【医生指令】进行专业解答。\n重要指令:\n1. 必须返回合法的 JSON 对象\n2. 仅包含 "reply"(你的专业回答)一个字段\n3. 不要返回任何 HTML 代码\n4. 绝对不要包含任何 Markdown 标记'; +``` + +**新代码**: +```tsx + const systemPrompt = aiModifyEnabled + ? '你是一名专业的外科医生助理。当前处于【修改模式】。\n我为你提供了当前手术报告的【全局参考内容】作为背景知识,以及你需要修改的【目标区域 HTML 源码】。\n请根据用户的【医生指令】,直接重写并输出目标区域的 HTML。\n\n重要指令:\n1. 必须返回合法的 JSON 对象\n2. 必须包含 "reply"(简短回复)和 "updatedHtml"(修改后的完整 HTML 代码)两个字段\n3. 【内容边界】:全局参考内容仅供你理解上下文。你的 updatedHtml 只能包含目标区域本身的内容(例如:如果目标区域是"手术步骤",你就只写步骤)。严禁输出签名、落款、术后总结等属于报告其他部分的结构!\n4. 段落必须使用

标签包裹,段落间绝对不要使用
标签,也不要使用换行符 (\\n)\n5. 输出的 HTML 必须紧凑,标签之间不要有空格或换行\n6. 绝对不要包含任何 Markdown 标记(如 ```json)' + : '你是一名专业的外科医生助理。当前处于【对话模式】。\n请仔细阅读我提供的【全局手术报告参考内容】,并根据【医生指令】进行专业解答。\n重要指令:\n1. 必须返回合法的 JSON 对象\n2. 仅包含 "reply"(你的专业回答)一个字段\n3. 不要返回任何 HTML 代码\n4. 绝对不要包含任何 Markdown 标记'; +``` + +**变更点**: +1. 去掉 `请根据全局内容和用户的【医生指令】` 中的"全局内容",改为 `请根据用户的【医生指令】` +2. 第 3 点从 `updatedHtml 必须生成完整...要基于全局信息补充完善` 改为明确的【内容边界】警告 +3. 明确告知 AI:全局参考仅供理解上下文,updatedHtml 只能包含目标区域本身的内容 +4. 明确列出严禁输出的内容类型:签名、落款、术后总结等 diff --git a/工程分析/20260419_0424/测试方案.md b/工程分析/20260419_0424/测试方案.md new file mode 100644 index 0000000..7a57748 --- /dev/null +++ b/工程分析/20260419_0424/测试方案.md @@ -0,0 +1,49 @@ +# 测试方案 + +## 测试环境 +- 浏览器访问 `http://localhost:4173/` +- 进入「图文报告生成」→ 新建报告 + +## 测试用例 1:AI 不越界生成其他模块 + +**步骤**: +1. 编辑器中有完整报告内容(包含手术步骤、术后情况、标本描述、病理结果、手术者签名等) +2. 插入 AI 可编辑区域「手术步骤」 +3. 勾选「允许修改正文」→ 选中「手术步骤」区域 +4. 发送「请完善手术步骤描述」 + +**预期结果**: +- diff 弹窗右侧 AI 提议版本**只包含手术步骤相关内容** +- 不应出现:术后情况、标本描述、病理结果、手术者签名、日期等属于其他模块的内容 +- 左侧原始版本显示该区域原有的内容 + +## 测试用例 2:AI 基于全局上下文理解但不越界 + +**步骤**: +1. 全局报告中有患者信息(如胆囊结石伴慢性胆囊炎) +2. AI 区域为「手术步骤」,原有内容较简略 +3. 发送「请根据患者病情完善手术步骤」 + +**预期结果**: +- AI 生成的手术步骤应体现对患者病情(胆囊结石伴慢性胆囊炎)的理解 +- 但不应把「术后情况」「病理结果」等其他模块的内容混进来 + +## 测试用例 3:对话模式不修改 + +**步骤**: +1. 取消勾选「允许修改正文」 +2. 发送任意指令 + +**预期结果**: +- AI 只回复聊天内容,不修改编辑器,不弹 diff 弹窗 + +## 测试用例 4:编译与部署 + +**步骤**: +1. 执行 `npm run build` +2. 确认无 TypeScript 编译错误 +3. 预览服务正常启动并返回 200 + +**预期结果**: +- `vite build` 成功完成 +- 预览页面可正常访问 diff --git a/工程分析/20260419_0424/需求分析.md b/工程分析/20260419_0424/需求分析.md new file mode 100644 index 0000000..fc25e02 --- /dev/null +++ b/工程分析/20260419_0424/需求分析.md @@ -0,0 +1,34 @@ +# 需求分析 + +## 时间戳 +2026-04-19 04:24 + +## 需求来源 +用户在使用 AI 修改确认弹窗时发现两个问题: +1. diff 弹窗左侧原始版本的内容似乎不完整(或被截断) +2. diff 弹窗右侧 AI 提议版本混入了不该出现的内容(术后情况、标本描述、病理结果、手术者签名等) + +## 问题分析 + +### 问题 1:AI 越界生成其他模块内容 + +**现象**:右侧 AI 提议版本中出现了"手术后情况"、"切除标本描述"、"是否送病理检查"、"冰冻病理结果"、"手术者签名"等本不属于"手术步骤"区域的内容。 + +**根因**: +1. `globalContextText` 包含了整个编辑器的纯文本,AI 看到了全局所有内容 +2. systemPrompt 第 3 点写着:`updatedHtml 必须生成完整、结构化的多段落内容,不要只改写现有段落,要基于全局信息补充完善` +3. AI 为了达成"补充完善"的指令,把全局上下文中看到的其他模块内容都塞进了 updatedHtml + +### 问题 2:左侧内容显示 + +**现象**:左侧原始版本显示了多段内容(1-3段),但可能被截断。 + +**根因**: +- 左侧 `currentHtml` 取自 `.ai-content` 的 innerHTML,其内容取决于模板中 `.ai-content` 实际包含了多少段落 +- 这不是代码层面的 Bug,而是模板结构中 `.ai-content` 的包裹范围问题 + +## 解决方向 + +1. **Prompt 边界加固**:去掉"基于全局信息补充完善"这种容易被 AI 过度解读的措辞,改为明确的内容边界警告 +2. **System Prompt 职责界定**:明确告知 AI"全局参考仅供理解上下文,严禁输出其他模块" +3. **Prompt 增加防越界指令**:在 promptText 中明确列出禁止混入的模块类型 diff --git a/工程分析/经验记录.md b/工程分析/经验记录.md index 63f5427..0b35de5 100644 --- a/工程分析/经验记录.md +++ b/工程分析/经验记录.md @@ -749,3 +749,28 @@ ReportEditor 采用 `useRef` 作为自动保存的数据快照机制(避免 Re **D. 后续如何避免问题** - 当大模型返回的 HTML 需要在前端渲染时,**必须同时在输入端(prompt)和输出端(后处理)进行格式约束**,单靠一端无法完全控制不同 LLM 的输出随机性。 - 对于「生成完整性」类需求,必须在 prompt 中明确使用「必须生成完整...」「不要只改写...」等强制性措辞,否则大模型倾向于做最小化修改。 + + +--- + +## 记录 33:AI 越界生成——Prompt 中"补充完善"导致大模型过度联想 + +**A. 具体问题** +AI 修改确认弹窗右侧出现了不属于目标区域的内容:术后情况、切除标本描述、是否送病理检查、冰冻病理结果、手术者签名等。这些模块本应在报告的其他位置,却被 AI 混入了"手术步骤"区域的 updatedHtml 中。 + +**B. 产生问题原因** +1. **全局上下文暴露过多**:`globalContextText` 包含了整个编辑器的纯文本,AI 看到了报告中所有模块的内容。 +2. **Prompt 措辞诱导过度联想**:systemPrompt 中写着 `要基于全局信息补充完善`,大模型非常"听话"地把它在全局上下文中看到的所有内容都"补充"进了输出。 +3. **缺少内容边界约束**:Prompt 中没有明确告知 AI"只能输出目标区域本身的内容,严禁混入其他模块"。 + +**C. 解决问题方案** +1. **System Prompt 去掉诱导性措辞**: + - 将 `请根据全局内容和用户的【医生指令】` 改为 `请根据用户的【医生指令】` + - 将 `updatedHtml 必须生成完整...要基于全局信息补充完善` 改为明确的【内容边界】警告: + > "全局参考内容仅供你理解上下文。你的 updatedHtml 只能包含目标区域本身的内容。严禁输出签名、落款、术后总结等属于报告其他部分的结构!" +2. **User Prompt 增加防越界指令**: + - 增加第 2 点:用 ⚠️ 警告符号明确列出禁止混入的模块类型(基本信息、术后情况、标本描述、病理结果、医生签名、日期等) + +**D. 后续如何避免问题** +- 在向大模型发送局部修改请求时,**必须设置严格的内容边界(Fencing)**。全局上下文可以提供给 AI 作为背景理解,但必须在 Prompt 中明确声明"仅供理解,严禁输出"。 +- 避免使用"补充完善""基于全局信息扩展"等容易被大模型过度解读的措辞。大模型会尽其所能地"满足"用户的指令,即使这意味着越界生成。