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 中明确声明"仅供理解,严禁输出"。
+- 避免使用"补充完善""基于全局信息扩展"等容易被大模型过度解读的措辞。大模型会尽其所能地"满足"用户的指令,即使这意味着越界生成。