OPC中国智能体如何降低幻觉:从 RAG 知识库到可追溯评测的工程实践
一、问题背景:小型智能体项目为什么需要控制幻觉?
在OPC中国所代表的 AI 协同型 One Person Company(一人公司)实践中,一个人可能同时负责研究、开发、内容和交付。本文只讨论这种小型智能体项目,不涉及工业自动化领域的 OPC/OPC UA 协议。
在传统团队中,一份对外材料可能经过研究、撰写、技术审核和发布审批。OPC 的执行主体更精简,AI 智能体又能快速生成大量内容,因此一个未经核验的错误也可能被更快地复制到文章、方案、客服回复或客户报告中。
常见风险包括:
- 把已经失效的产品信息当作当前事实;
- 混淆组织、人物、日期和版本;
- 在资料没有给出答案时,根据语言模式补全细节;
- 引用了真实文档,但引用片段并不支持最终结论;
- 检索不到资料时仍给出语气肯定的回答。
因此,OPC中国智能体的目标不应是“任何问题都能回答”,而应是:有证据时给出可追溯答案,证据不足时明确拒答,并把高风险结论交给人确认。
二、先建立正确预期:RAG 只能降低风险,不能消除幻觉
RAG(Retrieval-Augmented Generation,检索增强生成)的基本流程是:收到问题后,从外部知识源检索相关片段,再把问题与片段一并交给模型生成答案。
阿里云百炼官方文档将知识库描述为 RAG 能力,可用于补充私有知识和更新信息;工作流中的知识库节点则负责将检索片段传递给下游模型。它能改善大模型缺少私域知识或知识陈旧的问题,但不等于天然保证答案正确。阿里云百炼知识库文档
RAG 链路至少可能在四处出错:
- 知识源错误:文档本身过期、冲突或缺少上下文;
- 切片错误:标题和正文被拆开,表格含义丢失;
- 检索错误:召回片段相似,但不能回答问题;
- 生成错误:模型忽略证据、过度概括或拼接出新结论。
所以,可靠链路不是“上传文件—打开知识库—完成”,而是从资料治理开始,以持续评测结束。
三、适合 OPC 的最小可信 RAG 架构
一套适合个人开发者或小团队的架构可以保持简单,但必须包含六个阶段。
1. 可信知识源
只接入当前业务真正需要的资料,例如产品说明、项目约束、常见问答、交付模板和经过确认的历史案例。不要把整个网盘一次性导入知识库。
每份文档至少记录:
document_id: product-guide-2026-07
title: 产品使用说明
owner: 内容负责人
source_type: official_document
effective_from: 2026-07-01
expires_at: 2026-10-01
security_level: internal
review_status: approved
owner 决定谁负责更新;expires_at 防止过期资料长期参与检索;security_level 用于限制不同应用的访问范围;只有 approved 状态的文档才能进入生产知识库。
2. 解析与切片
文档切片不是越小越好。切片过大,会把无关信息一起送入模型;切片过小,则容易失去标题、条件和例外说明。
可先采用以下经验规则:
- 按标题和自然段落切分,避免从句子中间截断;
- 让每个切片带上文档标题、章节名、版本和来源地址;
- 表格、代码与步骤列表尽量保持完整;
- 对“仅适用于某版本”“不包括某场景”等限定语重点检查;
- 更新文档时删除或停用旧版本,避免新旧片段同时被召回。
阿里云百炼文档也建议非结构化资料使用便于解析的格式,并通过明确标题、段落、列表和编号突出概念。创建和使用知识库
3. Query 改写与混合检索
用户问题往往口语化。例如“账号里那个库能不能给别人看”,实际可能在询问知识库的隔离范围。Query 改写可以补充核心实体,但不能擅自改变意图。
对于包含产品名、版本号、错误码等精确词的场景,单纯向量检索可能不够。可以组合语义检索与关键词检索,再使用 Rerank 对结果重新排序。
阿里云百炼知识检索服务支持 Query 改写、向量与关键词混合检索、排序模型、相似度阈值以及标签/结构化字段过滤。调试时可查看返回片段、来源文档、得分和耗时。知识检索服务文档
阈值不应凭感觉一次确定:过低会引入无关片段,过高则可能丢失正确资料。应使用固定问题集比较调整前后的召回结果。
4. 基于证据生成
生成节点需要清楚说明“什么能做、什么不能做”。例如:
你是内部知识问答助手。
仅依据 CONTEXT 中的资料回答,不使用未提供的事实补全细节。
每个关键结论必须列出 source_id。
若资料冲突,分别列出冲突内容,不自行选择其中一方。
若资料不足以回答,返回 status=insufficient_evidence,并说明缺少什么。
输出必须符合指定 JSON Schema,不得添加未定义字段。
这里最重要的不是措辞,而是让拒答成为合法结果。如果业务流程只接受“回答成功”,模型就会受到隐性压力,在证据不足时继续生成。
5. 引用与来源卡
不要只在答案末尾列出几个链接。应建立“结论—片段—原文”的对应关系:
{
"status": "answered",
"answer": "知识库仅限当前业务空间使用。",
"claims": [
{
"claim_id": "c1",
"source_id": "doc-17#chunk-08",
"source_title": "知识库常见问题",
"source_uri": "kb://official-doc/privacy#paragraph-3",
"quote_start": 120,
"quote_end": 138
}
]
}
source_uri 是知识库内部定位示例,不是外部链接。生产环境中,source_id 必须能够定位到真实切片,而不是只指向知识库首页;字符位置或段落编号有助于审计时快速还原原文。
6. 人工审批
并非所有回答都需要同样强度的审核。可以按影响分级:
| 风险级别 | 示例 | 推荐处理 |
| 低 | 内部资料定位、格式转换 | 自动输出并记录日志 |
| 中 | 对外文章草稿、一般客户答复 | 人工抽检或发布前审批 |
| 高 | 合同、价格、退款、隐私、安全结论 | 必须逐条人工确认 |
对外发布、资金操作、删除数据和生产环境变更不能因为“引用了知识库”就自动放行。
四、如何实现“证据不足就拒答”?
拒答不能只靠提示词,还应使用检索信号与规则共同判断。下面是与具体 SDK 无关的 Python 示例:
from dataclasses import dataclass
@dataclass
class RetrievedChunk:
source_id: str
score: float
text: str
def evidence_gate(chunks: list[RetrievedChunk], threshold: float = 0.72):
qualified = [item for item in chunks if item.score >= threshold]
if not qualified:
return {
"status": "insufficient_evidence",
"reason": "没有检索到达到阈值的资料片段",
"context": [],
}
return {
"status": "ready_for_generation",
"reason": None,
"context": [
{"source_id": item.source_id, "text": item.text}
for item in qualified[:5]
],
}
示例中的 0.72 只是演示值,不能直接作为生产参数。不同排序模型、知识库和任务的得分分布不同,应在自己的评测集上确定阈值。
还应增加以下情况的拒答或转人工规则:
- 最高得分片段仍无法覆盖问题中的关键实体;
- 多份有效文档给出互相冲突的结论;
- 问题涉及知识库规定范围之外的信息;
- 用户要求作出合同、法律、资金或隐私相关决定;
- 输出无法生成完整引用。
五、本地最小验证:先复现一次错误拒答
为了避免文章只停留在架构建议,我编写了一个不依赖第三方库的最小实验程序 rag_evidence_eval.py。它包含3条知识片段和4个问题,用字符二元组重叠模拟最简检索。这个算法不用于生产,只用于观察证据闸门的行为。
运行环境与命令:
Python 3.12
python examples/rag_evidence_eval.py
第一版只判断“是否存在超过阈值的片段”。前三个可回答问题均命中正确来源,但“知识库能不能公开下载”错误召回了“知识库仅限当前业务空间使用,不对外公开”,结果如下:
source_recall=3/3
refusal_accuracy=0/1
问题并不在模型生成,而在检索后的证据判断:“公开”与“知识库”等重叠词让片段获得了分数,但该片段根本没有回答“下载”。
第二版增加一条规则:如果问题中的关键动作(如下载、导出、删除)没有出现在合格证据中,则直接返回 insufficient_evidence。再次运行得到:
知识库会被其他业务空间访问吗 => answered, source=kb-space
怎样组织非结构化文档 => answered, source=kb-format
检索流程包含哪些环节 => answered, source=kb-retrieval
知识库能不能公开下载 => insufficient_evidence, missing_terms=下载
source_recall=3/3
refusal_accuracy=1/1
这个结果只说明4条固定样本通过,不能代表生产准确率。它验证了一个具体事实:相似度超过阈值不等于证据能够回答问题,证据闸门还需要检查关键实体、动作和限定条件是否被覆盖。
六、扩展为一个 30 条问题的评测集
没有评测集,就无法判断修改切片、阈值或提示词后,系统究竟变好还是变坏。
OPC 项目可以从 30 条问题开始,覆盖六种类型:
| 类型 | 数量建议 | 评测目的 |
| 直接事实题 | 8 | 能否召回明确答案 |
| 同义表达题 | 5 | Query 改写是否有效 |
| 多片段综合题 | 5 | 能否组合证据而不扩写 |
| 条件与例外题 | 4 | 是否保留限制条件 |
| 无答案问题 | 5 | 是否正确拒答 |
| 冲突/过期资料题 | 3 | 是否提示冲突并转人工 |
每条评测数据至少包含:问题、期望状态、必需来源、关键答案点、禁止出现的结论。例如:
{
"question": "个人知识库会不会被其他业务空间访问?",
"expected_status": "answered",
"required_source_ids": ["kb-faq#privacy-01"],
"required_points": ["仅限当前业务空间"],
"forbidden_points": ["完全公开", "默认跨账号共享"]
}
阿里云百炼的应用评测支持预置评估器以及自定义 LLM 评估器和 Code 评估器,可覆盖通用质量、文本匹配、格式校验和智能体能力等场景。百炼评估器文档
七、不要只评“答案像不像”,要分层定位问题
一个合理的评测结果至少分为三层:
检索层
- 必需来源是否进入召回结果;
- 正确片段是否排在前 K;
- 无关片段是否过多;
- 过期文档是否被过滤。
生成层
- 答案中的每个关键结论是否有证据支持;
- 是否保留条件、例外和不确定性;
- 证据不足时是否拒答;
- 输出格式是否满足 Schema。
业务层
- 人工修改了哪些内容;
- 用户是否真的解决问题;
- 错误是否造成外部影响;
- 单次调用成本与耗时是否可接受。
如果必需来源根本没有被召回,继续调整生成提示词通常没有意义;如果检索正确而回答错误,才应重点检查生成指令、上下文组织和模型选择。
八、小型智能体项目的上线检查清单
[ ] 只有已审批且在有效期内的文档进入生产知识库
[ ] 每个切片保留标题、版本、来源与安全级别
[ ] 关键问题已测试关键词检索、向量检索与重排效果
[ ] 证据不足、资料冲突和高风险请求有明确处理路径
[ ] 每个关键结论能够定位到具体来源片段
[ ] 对外发布、资金、隐私和生产变更保留人工审批
[ ] 日志不记录明文密钥及非必要个人信息
[ ] 固定评测集已保存,配置变更后自动回归
[ ] 知识库过期文档有负责人和清理机制
九、结语:可信度比生成速度更重要
对于一人团队和小型智能体项目,AI的价值不是无限生成内容,而是建立可重复的交付能力。若输出无法追溯、错误不能定位、风险没有负责人,生成速度越快,潜在损失也可能越大。
从一小组经过确认的文档开始,保留元数据和版本;用混合检索与重排提高证据召回;让模型只能基于证据作答;证据不足时允许拒答;最后通过人工审批和固定评测集持续验证。完成这条链路后,AI 才从“会说话的助手”变成一项能够被治理的生产能力。