fix(ai): AI越界生成——Prompt增加内容边界约束
- systemPrompt去掉'基于全局信息补充完善'诱导性措辞,改为明确【内容边界】警告
- systemPrompt明确告知AI:全局参考仅供理解上下文,updatedHtml只能包含目标区域本身内容
- promptText增加⚠️防越界指令:明确列出禁止混入的模块类型(术后情况、标本描述、病理结果、签名等)
This commit is contained in:
@@ -892,7 +892,7 @@ export default function ReportEditor() {
|
|||||||
if (aiModifyEnabled && targetRegionEl) {
|
if (aiModifyEnabled && targetRegionEl) {
|
||||||
promptText += `【你需要进行修改的目标区域 HTML 源码】:\n${currentHtml || '(当前区域为空)'}\n\n`;
|
promptText += `【你需要进行修改的目标区域 HTML 源码】:\n${currentHtml || '(当前区域为空)'}\n\n`;
|
||||||
}
|
}
|
||||||
promptText += `【医生指令】: ${text}\n\n【格式要求】:\n1. 生成完整、结构化的多段落 HTML 内容,不要只改写现有段落\n2. 段落使用 <p> 标签,段落之间不要使用 <br> 标签或换行符\n3. 输出紧凑 HTML,标签间不要有空格或换行`;
|
promptText += `【医生指令】: ${text}\n\n【格式要求】:\n1. 仅针对【目标区域】的主题生成对应的多段落 HTML 内容\n2. ⚠️ 绝对禁止将【全局参考内容】中的其他模块(如:基本信息、术后情况、标本描述、病理结果、医生签名、日期等)生成并混入你的输出中!你只能输出该区域应有的内容\n3. 段落使用 <p> 标签,段落之间不要使用 <br> 标签或换行符\n4. 输出紧凑 HTML,标签间不要有空格或换行`;
|
||||||
if (allImages.length > 0) {
|
if (allImages.length > 0) {
|
||||||
messageContent = [];
|
messageContent = [];
|
||||||
allImages.forEach(url => {
|
allImages.forEach(url => {
|
||||||
@@ -903,7 +903,7 @@ export default function ReportEditor() {
|
|||||||
messageContent = promptText;
|
messageContent = promptText;
|
||||||
}
|
}
|
||||||
const systemPrompt = aiModifyEnabled
|
const systemPrompt = aiModifyEnabled
|
||||||
? '你是一名专业的外科医生助理。当前处于【修改模式】。\n我为你提供了当前手术报告的【全局参考内容】作为背景知识,以及你需要修改的【目标区域 HTML 源码】。\n请根据全局内容和用户的【医生指令】,直接重写并输出目标区域的 HTML。\n重要指令:\n1. 必须返回合法的 JSON 对象\n2. 必须包含 "reply"(简短回复话术)和 "updatedHtml"(修改后的完整内部 HTML 代码)两个字段\n3. updatedHtml 必须生成完整、结构化的多段落内容,不要只改写现有段落,要基于全局信息补充完善\n4. 段落必须使用 <p> 标签包裹,段落之间绝对不要使用 <br> 标签,也不要使用任何换行符 (\\n)\n5. 输出的 HTML 必须紧凑,标签之间不要有空格或换行\n6. 绝对不要包含任何 Markdown 标记(如 ```json)'
|
? '你是一名专业的外科医生助理。当前处于【修改模式】。\n我为你提供了当前手术报告的【全局参考内容】作为背景知识,以及你需要修改的【目标区域 HTML 源码】。\n请根据用户的【医生指令】,直接重写并输出目标区域的 HTML。\n\n重要指令:\n1. 必须返回合法的 JSON 对象\n2. 必须包含 "reply"(简短回复)和 "updatedHtml"(修改后的完整 HTML 代码)两个字段\n3. 【内容边界】:全局参考内容仅供你理解上下文。你的 updatedHtml 只能包含目标区域本身的内容(例如:如果目标区域是"手术步骤",你就只写步骤)。严禁输出签名、落款、术后总结等属于报告其他部分的结构!\n4. 段落必须使用 <p> 标签包裹,段落间绝对不要使用 <br> 标签,也不要使用换行符 (\\n)\n5. 输出的 HTML 必须紧凑,标签之间不要有空格或换行\n6. 绝对不要包含任何 Markdown 标记(如 ```json)'
|
||||||
: '你是一名专业的外科医生助理。当前处于【对话模式】。\n请仔细阅读我提供的【全局手术报告参考内容】,并根据【医生指令】进行专业解答。\n重要指令:\n1. 必须返回合法的 JSON 对象\n2. 仅包含 "reply"(你的专业回答)一个字段\n3. 不要返回任何 HTML 代码\n4. 绝对不要包含任何 Markdown 标记';
|
: '你是一名专业的外科医生助理。当前处于【对话模式】。\n请仔细阅读我提供的【全局手术报告参考内容】,并根据【医生指令】进行专业解答。\n重要指令:\n1. 必须返回合法的 JSON 对象\n2. 仅包含 "reply"(你的专业回答)一个字段\n3. 不要返回任何 HTML 代码\n4. 绝对不要包含任何 Markdown 标记';
|
||||||
const response = await fetch(`${apiEndpoint}/chat/completions`, {
|
const response = await fetch(`${apiEndpoint}/chat/completions`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
|||||||
43
工程分析/20260419_0424/实现方案.md
Normal file
43
工程分析/20260419_0424/实现方案.md
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# 实现方案
|
||||||
|
|
||||||
|
## 修改文件
|
||||||
|
- `src/pages/ReportEditor.tsx`
|
||||||
|
|
||||||
|
## 修改位置 1:Prompt 文本增加内容边界约束(约 line 895)
|
||||||
|
|
||||||
|
**原代码**:
|
||||||
|
```tsx
|
||||||
|
promptText += `【医生指令】: ${text}\n\n【格式要求】:\n1. 生成完整、结构化的多段落 HTML 内容,不要只改写现有段落\n2. 段落使用 <p> 标签,段落之间不要使用 <br> 标签或换行符\n3. 输出紧凑 HTML,标签间不要有空格或换行`;
|
||||||
|
```
|
||||||
|
|
||||||
|
**新代码**:
|
||||||
|
```tsx
|
||||||
|
promptText += `【医生指令】: ${text}\n\n【格式要求】:\n1. 仅针对【目标区域】的主题生成对应的多段落 HTML 内容\n2. ⚠️ 绝对禁止将【全局参考内容】中的其他模块(如:基本信息、术后情况、标本描述、病理结果、医生签名、日期等)生成并混入你的输出中!你只能输出该区域应有的内容\n3. 段落使用 <p> 标签,段落之间不要使用 <br> 标签或换行符\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. 段落必须使用 <p> 标签包裹,段落之间绝对不要使用 <br> 标签,也不要使用任何换行符 (\\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. 段落必须使用 <p> 标签包裹,段落间绝对不要使用 <br> 标签,也不要使用换行符 (\\n)\n5. 输出的 HTML 必须紧凑,标签之间不要有空格或换行\n6. 绝对不要包含任何 Markdown 标记(如 ```json)'
|
||||||
|
: '你是一名专业的外科医生助理。当前处于【对话模式】。\n请仔细阅读我提供的【全局手术报告参考内容】,并根据【医生指令】进行专业解答。\n重要指令:\n1. 必须返回合法的 JSON 对象\n2. 仅包含 "reply"(你的专业回答)一个字段\n3. 不要返回任何 HTML 代码\n4. 绝对不要包含任何 Markdown 标记';
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更点**:
|
||||||
|
1. 去掉 `请根据全局内容和用户的【医生指令】` 中的"全局内容",改为 `请根据用户的【医生指令】`
|
||||||
|
2. 第 3 点从 `updatedHtml 必须生成完整...要基于全局信息补充完善` 改为明确的【内容边界】警告
|
||||||
|
3. 明确告知 AI:全局参考仅供理解上下文,updatedHtml 只能包含目标区域本身的内容
|
||||||
|
4. 明确列出严禁输出的内容类型:签名、落款、术后总结等
|
||||||
49
工程分析/20260419_0424/测试方案.md
Normal file
49
工程分析/20260419_0424/测试方案.md
Normal file
@@ -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` 成功完成
|
||||||
|
- 预览页面可正常访问
|
||||||
34
工程分析/20260419_0424/需求分析.md
Normal file
34
工程分析/20260419_0424/需求分析.md
Normal file
@@ -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 中明确列出禁止混入的模块类型
|
||||||
25
工程分析/经验记录.md
25
工程分析/经验记录.md
@@ -749,3 +749,28 @@ ReportEditor 采用 `useRef` 作为自动保存的数据快照机制(避免 Re
|
|||||||
**D. 后续如何避免问题**
|
**D. 后续如何避免问题**
|
||||||
- 当大模型返回的 HTML 需要在前端渲染时,**必须同时在输入端(prompt)和输出端(后处理)进行格式约束**,单靠一端无法完全控制不同 LLM 的输出随机性。
|
- 当大模型返回的 HTML 需要在前端渲染时,**必须同时在输入端(prompt)和输出端(后处理)进行格式约束**,单靠一端无法完全控制不同 LLM 的输出随机性。
|
||||||
- 对于「生成完整性」类需求,必须在 prompt 中明确使用「必须生成完整...」「不要只改写...」等强制性措辞,否则大模型倾向于做最小化修改。
|
- 对于「生成完整性」类需求,必须在 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 中明确声明"仅供理解,严禁输出"。
|
||||||
|
- 避免使用"补充完善""基于全局信息扩展"等容易被大模型过度解读的措辞。大模型会尽其所能地"满足"用户的指令,即使这意味着越界生成。
|
||||||
|
|||||||
Reference in New Issue
Block a user