资讯动态

1+?=2:用知识约束与开源模型打造无幻觉内部问答系统

发布时间:2026/10/22 18:58:40 来源:尧图企业网站定制
做内部知识问答系统的时候我差点被AI幻觉折磨到放弃。模型总能一本正经地给出一个看起来毫无破绽、实际上完全编造的答案而且语气越自信越难发现。后来我把整套方案拆开重组提炼成一个非常朴素的公式1 2。这里的1是思想核心是预先定义好的、不可动摇的约束条件是模型唯一需要推理的空间2是最终要交付的答案。这个公式听起来像在做数学题但它真正解决的是“如何让AI不说瞎话、不跑偏、按你的意志输出”这个工程问题。所以我就把整个思路整理出来连同可复现的开源方案一起讲清楚。不管你是开发者还是正在给团队做AI落地的人都能从中找到能直接用的方法。1. 拆解“12”一个专门反幻觉的思维框架1.1 为什么大模型会一本正经地胡说八道幻觉不是模型“坏掉了”而是生成式模型的工作原理决定的。大模型本质上是在做概率预测每个字都是根据前文概率采样得到的。它在训练时见过海量文本但并没有一个独立的“事实数据库”可以随时查证。当问题超出它的知识边界或者上下文信息不足时它就会沿着语言惯性继续编下去。我做一个生活化类比你让一个记性很好但从不查资料的实习生汇报工作他能把不知道的事情说得头头是道。因为他掌握了说话的套路却没有“不知道就去查”的机制。大模型也是一样它擅长的是语言模式不是事实核查。更麻烦的是幻觉分两种。一种是事实性幻觉把不存在的事件、数字、引用说得像真的一样另一种是逻辑性幻觉推理链条中间断了但结论看起来合理。这两种在工程上的解法不完全一样——事实性幻觉要靠知识约束来堵逻辑性幻觉要靠结构化校验来拦后面我会分开讲。1.2 把“1”定义为不可动摇的约束底座既然模型天生会编那我们就不要把所有主动权交给它。把整个输出过程拆成两部分一部分是我们说了算的另一部分才允许模型自由发挥。这里的“1”就是前者我称它为思想核心它至少包含三样东西角色与目标定义告诉模型它是什么为什么存在不许做什么。知识边界哪些内容是允许引用的哪些情况必须说不知道。输出协议结构、格式、语气、必须包含的字段、禁止出现的表述。这三样东西合在一起就是一个“绝对不会被模型推翻”的底座。任何回答都必须从底座出发模型只能在这个底座限定的通道里做填充。这不是靠一句“请你准确回答”就能做到的而是需要把约束拆成明确、无歧义的规则让模型在解读时没有发挥空间。我见过很多人忽略这一步直接把用户问题丢给模型结果模型自由发挥的空间太大幻觉率居高不下。把1定义好等于先把80%的幻觉问题挡在门外剩下那20%才轮到模型自己发挥。1.3 把“”定义为有边界的推理空间 是模型真正要做的事是它唯一可以活动的那部分。但要注意这个问号必须有边界不是开放式问号。怎么做边界我把它分成三个维度信息边界模型能用的材料必须来自你提供的知识库、数据库或检索结果而不是它记忆里的模糊印象。逻辑边界推理步骤要可拆、可查。如果答案是分步推理得到的每一步都要能追溯到材料。表达边界允许的语气、详略、是否有结论、是否需要引用来源都提前定死。这样模型的活动空间从“一张白纸随便写”变成“一个填字游戏”空格是确定的答案也是从给定材料里选的。这听起来会牺牲一些灵活性但换来的是稳定可控在多数业务场景里是值得的。其实这个框架最有价值的地方是它把“让AI听话”这个大而空的目标变成了两个可以分别解决的问题定义好1约束好剩下的“2”自然而然就到手了。2. 为什么必须走开源路线可控性的底层逻辑2.1 闭源服务的黑盒局限要实现对模型行为的深度控制闭源服务会遇到几个现实问题。第一你改不了系统底层的生成策略顶多只能调表面参数第二知识、数据、上下文都要经过外部服务链路敏感内容怎么处理是个大问题第三请求级延迟和成本不可控内部系统对稳定性要求高的时候会很被动。闭源服务当然有它的优点效果强、接入快。但从“让AI完全听你号令”这个目标出发只靠外部接口很难做到“号令”两个字。因为号令意味着可配置、可观测、可干预这三个词都需要底层可控才能实现。这里说个我踩过的坑曾经有个阶段图省事把内部问答系统接在闭源服务上。结果某个字段的格式要求对方不支持为了解决这个问题我在业务层打了大量补丁。事后我才意识到问题的根源在于我不拥有生成链路任何一点不满足需求都要绕路。这就是黑盒的代价很多问题看起来是业务问题本质上是可控性问题。2.2 开源工具链的选型思路走开源路线之后我的选型思路是三层分离模型层、编排层、知识层。模型层选择可以在本地或自有服务器部署的开源模型。我选的是一套70亿参数左右的对话模型量化后单卡就能跑。它不是参数最大、效果最好的那个但在这个场景里足够用而且推理速度快、可控性强。编排层用一套主流的开源编排框架来管理提示词、调用顺序、输出校验。选型时我主要看重四点提示词模板是否支持变量注入、是否有现成的结构化输出能力、社区文档是否完整、以及插件机制是否方便。这一层是整个链路的粘合剂很多幻觉问题其实可以在编排层通过流程设计来规避。知识层用一个开源的向量数据库存放资料切片再加上一层检索逻辑让模型只能基于检索到的内容作答。选型时我重点看检索速度、中文分词效果和过滤能力。这一层是堵住事实性幻觉的关键模型有源可查才不会凭空乱说。这套组合最大的好处是每一层都可以被替换、可以加监控、可以出报告。出了问题你能一层一层往下查而不是对着黑盒干瞪眼。2.3 最小可用架构长什么样如果从零开始搭我会先在心中画一张非常朴素的链路用户问题进来先做意图识别和查询改写再到知识层检索把命中的资料切片和问题一起拼成完整的提示词交给模型生成最后用一套校验器检查输出格式和知识引用是否合规不合规就重新生成或直接打回。这段链路里每一个环节都是可控的。特别是最后一步输出校验很多人会忽略但实际上它就像一个质检员把模型偶尔犯的错拦在交付之前。加上这层之后系统的可靠性会上一个台阶因为你不理会模型是不是偶尔犯迷糊你只在意有没有把错误的输出拦住。我在内部知识问答场景里用这套架构实测过幻觉率从最初完全无法接受降到了几乎可以忽略的地步。下面具体讲实操。3. 从理念到代码搭一套“无幻觉”最小系统3.1 第一步写好思想核心的系统提示词系统提示词是“1”的载体也是整个方案的重中之重。我在写的时候会用一套固定结构这里贴一个简化版供参考你是企业内部知识助手只回答与知识库相关的问题。 你的任务基于下方提供的资料片段回答问题。 规则 1. 只能使用下方资料中的信息禁止使用个人记忆补充。 2. 资料中没有明确说明的信息统一回复“知识库中未找到相关信息”。 3. 回答必须给出引用来源格式为[来源编号]。 4. 禁止编造数据、日期、人名和结论。 5. 用户问题如果与知识库无关直接拒绝回答并引导查询范围。 资料片段 {{检索结果}} 用户问题 {{用户问题}}这里面最重要的是规则2和规则3。规则2是告诉模型“不知道”是合法答案不要硬编。规则3是强制模型把每个结论挂到来源上后续校验就可以拿着这个来源去反查。这条提示词我迭代了很多版最终验证了一个结论规则越具体模型越老实。模糊的“请准确回答”几乎没用明确的“没有资料时必须说不知道”才是真正有效的约束。3.2 第二步用本地知识库堵住事实性幻觉光靠提示词约束还不够因为模型在训练时留下的记忆惯性太强了。所以必须让它在回答之前先去知识库检索只依据检索结果生成答案。我的做法是把知识材料切成固定长度的片段切的时候保留段落边界避免一句话被拦腰截断。用嵌入模型把片段向量化存入本地向量库。每次用户提问时先在知识库检索出最相关的前若干条片段。这里有一个关键细节检索的召回质量直接决定回答质量。如果检索不到正确答案提示词约束得再严也没用。所以我在检索前会加一层“查询改写”把口语化问题改写成更适合检索的关键词组合提升召回率。你可以把它理解成“翻译官”把用户的日常表达翻译成知识库更容易命中的检索语言。你可能会问知识库里没有答案怎么办这正是“让AI没有幻觉”的难点所在。我的处理方式是当知识库检索结果低于相似度阈值时不触发生成流程直接让用户重新描述问题或者由人工介入。这个兜底策略保住了下限——宁可不说不能乱说。把这条逻辑写进系统里之后模型的“胡说八道”基本就断粮了。3.3 第三步用结构化输出锁死编造空间自由文本是最难校验的因为同一个意思可以有一百种写法。所以我在输出协议里尽量要求结构化输出把模型的自由度进一步压缩。具体到实现上我会要求模型输出JSON格式并且提前定义好字段结构比如{ answer: 回答正文不超过200字, citations: [来源编号1, 来源编号2], confidence: high|medium|low, needs_human: true }然后我在代码里用JSON Schema做校验。字段缺失、格式错误、来源编号不存在都会触发拦截并重新生成。这样做有一个额外的好处下游系统可以直接解析结果不需要再跟自然语言战斗。这一步看起来简单但实际效果非常明显。在我做过的测试里加上结构化约束之后格式违规率几乎降为零同时因为格式固定模型在内容上也会更收敛——瞎编的内容很难填进一个有校验的结构里模型会下意识地回到资料提供的真实信息里去。3.4 第四步把三者串成一个管线有了上面三个部分最后就是把它们串成完整的处理管线。我用Python写过一个概念版本流程大概是这样的def run_pipeline(user_query): # 1. 查询改写 rewritten_query rewrite_query(user_query) # 2. 知识检索 snippets search_knowledge_base(rewritten_query, top_k5) # 3. 相似度阈值检查 if snippets is None or snippets[0].score 0.6: return 知识库中未找到足够相关的信息请重新描述问题。 # 4. 拼装系统提示词与用户提示词 system_prompt build_system_prompt(snippets) prompt build_user_prompt(user_query) # 5. 生成候选回答 response generate_with_open_model(system_prompt, prompt) # 6. 结构化校验 if not validate_response(response, snippets): return regenerate_or_refuse(response) return parse_response(response)这段伪代码里最关键的是第3步和第6步。第3步把“无中生有”的可能直接拦掉第6步把格式和来源引用的问题拦在输出之前。实际部署的时候每一步输出都要留日志方便事后回溯。不要跳过日志因为模型出错的时候日志是你唯一的破案线索。很多团队在原型阶段跑得很顺一上生产就翻车差的就是这层可观测性。4. 实测调优幻觉率是怎么降下来的4.1 我遇到的三类典型问题调优过程中我踩了不少坑这里整理三类最典型的。第一类是“模型过度自信”。即使提示词里写了“知识库未找到就回答不知道”模型有时还是会用模糊的话糊弄过去。比如资料里只提到产品支持三个平台模型硬是推断出“正在扩展更多平台”。这种问题靠提示词很难完全压制我最后的解法是加强输出校验专门检查有没有出现资料中不存在的扩展性表述。与其反复劝模型别说不如在出口处装一道闸。第二类是“引用错位”。模型回答引用了来源但来源内容根本支撑不了它的结论。这种情况最阴险因为看起来完全合规。我的排查方式是定期抽检把回答里的每个结论和引用来源做人工比对发现规律后再用更细的检索片段和更严格的提示词限制来缓解。引用错位说明模型在“找借口”它学会了引用格式但没学会诚实。第三类是“检索噪声干扰”。有时候知识库返回的相关片段里混着一些看似相关、实则无关的内容模型会被带偏。这个问题的根源在检索质量而不是生成。我通过调整切分策略、增加重复度过滤、优化查询改写来解决而不是在提示词层面硬压。检索这一步干净了后面所有环节的压力都会小很多。4.2 评估方法量化你的幻觉率没有量化就没有改善。我建立了一套简单但有效的评估流程。准备一份测试集大概一两百个问题要求覆盖四类场景知识库有明确答案、知识库有部分答案、知识库没有答案、问题与知识库完全无关。然后为每类场景设定期望行为。跑完一轮之后统计两个指标幻觉率——出现编造内容的比例以及拒答率——正确说不知道的比例。这里有一个重要取舍幻觉率和拒答率是跷跷板。压得太死模型会变得过于保守明明知道的东西也说不知道放得太松又会开始编。我一般先定一个可接受的幻觉率底线比如1%以内然后尽量把拒答率压到最低。调参时每次只改一个变量记录两个指标的变化用数据说话而不是凭感觉。我实测下来在加装知识库和输出校验之后测试集幻觉率能降到1%上下而单独依赖提示词时幻觉率可能有5%到10%甚至更高。这个差距是决定性的也是值得投入工程精力的原因所在。4.3 调优顺序和判断标准很多人在调优时喜欢先在提示词上反复磨效果不好就怀疑模型太弱。我的经验是调优顺序应该从外到内、从数据到生成。先把知识库做得足够干净、检索质量提上去再去看生成的幻觉率。如果检索结果准确且完整大多数幻觉问题会自动消失如果检索结果本身有问题提示词再怎么写也是白搭。接下来才轮到提示词和输出校验最后才考虑换更大的模型。换模型是成本最高的一步不要一上来就换。先检查前两层有没有做到位通常问题都出在那里。我见过的很多“模型不行”的案例最后查下来都是数据或检索的锅模型是在替错误的知识管线背锅。这个判断标准帮我省下了大量无意义的模型切换实验。5. 避坑清单与实操心得5.1 六条源于实践的避坑经验这里分享几条我亲测有效的避坑经验每一条都是拿真金白银换来的。第一知识切片要保留语义完整性。我最早按固定字数硬切结果一句话被拦腰截断检索出来全是残句生成质量惨不忍睹。后来改成按段落切并允许相邻句子重叠拼接情况立刻好转。切片看起来是个小问题但它直接决定了检索的上限。第二系统提示词里的规则不要超过七条。规则太多模型会顾此失彼甚至会额外引入不稳定。我习惯把规则按优先级排列最重要的放在最前面让模型先看到、先执行。第三输出校验器一定要能定位到具体错误。比如哪个字段缺失、哪条引用不存在、哪个值不在枚举范围内这样才能驱动上游调优。校验器只输出“不合格”没有任何意义它必须告诉你到底错在哪儿。第四日志记录要包含完整链路。用户问题、改写后的问题、检索结果、构造的提示词、模型原始输出、校验结果这六项缺一不可。没有完整链路日志出了问题就只能靠猜。我甚至会把日志沉淀成数据集用来迭代下一版提示词。第五单测要覆盖“知识库无答案”的场景。这类问题最容易被忽视但往往是幻觉的高发区。把它单独列成测试子集持续回归监测防止某次调优把兜底逻辑改没。第六不要追求零幻觉。把幻觉率压到绝对零需要付出极高的成本而且可能让系统失去可用性。设定一个业务可接受的下限比追求完美的零容忍更现实。5.2 常见问题速查表问题现象可能原因排查思路推荐解法模型频繁编造事实知识库没有被正确引用检查检索结果是否进入提示词加强知识库检索召回提高相似度阈值明明有答案却拒答输出校验过严查看校验器拦截的具体原因放宽无关字段校验保留核心约束引用存在但内容不支撑结论检索片段语义不完整人工抽检错误样本调整切分策略增加片段上下文模型输出格式总出错提示词格式说明不清晰比对错误样例使用结构化输出协议和Schema校验调优后幻觉率反弹改动影响了提示词或检索对比历史日志每次只改一个变量保留回归测试知识库无答案时仍硬答兜底逻辑被覆盖检查阈值判断是否被跳过在管线入口强制相似度阈值检查这张表不是万能药但能帮你快速定位大部分问题。把它贴在你的工作文档里遇到问题先对着排查能省下大量瞎猜的时间。5.3 关于“让所有AI听你号令”的一点实话写到最后我想说点实在的。标题里那句“让所有AI听你号令”听着很爽但真正的含义不是让AI对你百依百顺而是让它的每一次输出都在你设定的轨道上运行。你定义边界它负责填充你提供材料它负责表达你设置校验它负责接受裁决。这个分工清晰了AI就不再是一个不可控的“魔术师”而是一个可以被信任的执行者。我在实际项目中反复体会到控住AI的关键从来不是命令它“别骗人”而是让它没有机会骗人。知识库是它的唯一信源规则是它的唯一航线校验器是它的最后一关。三个环节守住幻觉自然无处滋生。这套方法不完美但它能落地、能复制、能验证。希望这套思路和代码能让你少走一些我曾经走过的弯路。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑