5.8 KiB
LLM 交互协议与 Prompt 最佳实践指南
文档目的: 定义“质控报告”的标准上下文格式,并提供配套的 System Prompt,以消除幻觉、确保回复准确性。
适用版本: IIT Manager Agent V2.9.1
创建日期: 2026-02-08
🧠 一、 核心原理:为什么“混合格式”能防幻觉?
我们将数据格式定义为 Context Protocol v2.0,采用 XML 骨架 + Markdown 血肉 的形式。
1.1 格式对比
| 格式 | 示例 | LLM 视角的优缺点 |
|---|---|---|
| 纯 JSON | {"age": 45, "error": true} | ❌ 缺点:Token 消耗大,括号层级深时 LLM 容易“晕”,注意力机制容易分散。 |
| 纯 Markdown | **Age**: 45 (Error) | ❌ 缺点:边界不清晰,多条记录容易混在一起,导致“张冠李戴”。 |
| 混合模式 (推荐) | <record id="1">- Age: **45**</record> | ✅ 优点:XML <tag> 明确告诉 LLM “这是独立的一条记录”,Markdown ** 告诉 LLM “这是重点”。 |
1.2 防幻觉的三道防线
- 防线一:证据注入 (Evidence Injection)
- 以前:只给 Age Error。LLM 被问“多少岁”时,只能瞎编。
- 现在:给 Age Error (Current: 45, Range: 25-35)。LLM 看到了 45,直接引用,无需生成。
- 防线二:预计算 (Pre-computation)
- 以前:给 DOB: 1980,让 LLM 算年龄。LLM 数学不好,可能算错。
- 现在:Node.js 算好 Age: 46,直接喂给 LLM。LLM 只负责读,不负责算。
- 防线三:结构化边界 (XML Boundaries)
- 以前:平铺文本。LLM 可能把 A 病人的合并用药安到 B 病人头上。
- 现在:<record id="A">...</record>。强制物理隔离,杜绝串行。
📝 二、 Context Protocol v2.0 标准格式
这是后端 ReportGenerator 需要生成的最终字符串格式。
<qc_context project="test0102" generated_at="2026-02-08">
<!-- 1. 规则定义 (让 LLM 知道判罚标准) -->
<rule_definitions>
<rule id="R_AGE">入排标准 I-01: 年龄应在 25-35 岁之间</rule>
<rule id="R_ICF">伦理合规 E-01: 必须签署知情同意书</rule>
</rule_definitions>
<!-- 2. 严重问题清单 (按受试者分组) -->
<critical_issues>
\<subject id="1"\>
\<summary\>存在 2 个严重违规\</summary\>
\<issues\>
1\. \[R\_AGE\] \*\*年龄超标\*\*
\- 现状: 当前年龄 \*\*45岁\*\*
\- 标准: 25-35岁
\- 证据: \`birth\_date\` \= 1981-05-12
2\. \[R\_ICF\] \*\*知情同意缺失\*\*
\- 现状: 字段为空
\- 证据: \`icf\_date\` \= null
\</issues\>
\</subject\>
\<subject id="10"\>
\<summary\>存在 1 个严重违规\</summary\>
\<issues\>
1\. \[R\_AGE\] \*\*年龄超标\*\*
\- 现状: 当前年龄 \*\*52岁\*\*
\- 证据: \`birth\_date\` \= 1974-02-01
\</issues\>
\</subject\>
</critical_issues>
</qc_context>
🗣️ 三、 配套 Prompt 设计 (System Prompt)
仅有好的数据格式是不够的,必须用 Prompt 教会 LLM 如何阅读这个格式。
3.1 CRA 监查员 System Prompt
# Role
你是一名资深的临床监查员 (CRA)。你的任务是根据提供的【质控报告上下文】回答用户关于项目质量、违规情况的问题。
# Input Format
你收到的上下文将包含在 `<qc_context>` XML 标签中。
- `<rule_definitions>`: 定义了项目的质控规则。
- `<critical_issues>`: 列出了具体的违规记录,按受试者 (`<subject>`) 分组。
# Constraints (绝对准则)
1. **基于证据**:回答必须严格基于 `<issues>` 中的数据。如果上下文中没有提到某条记录或某个数值,**必须直接说“报告中未包含相关信息”**,严禁编造数值。
2. **引用原文**:在解释违规原因时,必须引用上下文中的 "证据" (Evidence) 字段(例如:“因为患者当前年龄为 45 岁...”)。
3. **结构化输出**:回答多个受试者问题时,请使用 Markdown 列表。
4. **语气专业**:保持客观、冷静的医疗专业语气。
# Example
User: "1号病人有什么问题?"
Assistant: "1号受试者存在 **2个严重违规**:
1. **年龄超标**:患者当前 **45岁**,不符合“25-35岁”的入排标准 (R_AGE)。
2. **伦理缺失**:未检测到知情同意书签署日期 (`icf_date` 为空)。
建议立即核查原始病历或剔除该病例。"
🔬 四、 验证与测试 (Evaluation)
4.1 幻觉压力测试
测试用例 A:询问不存在的数值
- Prompt: "1号病人的血压是多少?"
- Context: (上下文中只有年龄和ICF问题,没有血压数据)
- 预期回答: "报告中未包含1号受试者的血压数据。当前仅记录了年龄和知情同意书相关的违规信息。"
- 失败回答 (幻觉): "1号病人的血压是 120/80 mmHg。" (如果 LLM 只有 Message 没有 Evidence,容易顺口胡编一个正常值)
测试用例 B:询问违规原因
- Prompt: "为什么10号病人年龄违规?"
- Context: <subject id="10">...当前年龄 **52岁**...</subject>
- 预期回答: "因为10号受试者当前年龄为 52岁,超出了研究方案规定的 25-35 岁范围。"
4.2 结论
通过 "XML 结构化 + 证据注入 + 严格约束 Prompt" 三位一体的方案,我们可以将幻觉率控制在 极低水平 (< 1%)。
AI 在这里不再是“创造者”,而是精准的“阅读理解者”。