十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

从AI幻觉到RAG:构建可追溯的知识库问答系统

从AI幻觉到RAG:构建可追溯的知识库问答系统 在技术文章、项目评审和社交媒体评论里最常听到的一句话是有人会说这是AI。说这句话的人往往指文本一眼就看出来是AI生成的或者代码结构、配图风格带有明显的大模型痕迹。这类判断并不全靠直觉背后是大模型生成机制留下的可识别特征尤其是AI幻觉导致的事实性错误以及模式化表达带来的“AI味”。不少开发者遇到这个评价后第一反应是想办法让AI生成的文字更像人写的。但工程上更值得做的方向是反过来理解AI为什么会被识别再通过提示词设计、检索增强生成和评估机制让AI输出变得可控制、可追溯、可验证。当一段回答有明确来源、能被人工复核时它是不是AI生成的其实并不重要。下面先讲清楚生成机制和幻觉原理再给出一个带知识库检索的最小问答项目最后补充质量评估、常见排查和最佳实践。适合正在学习大模型应用开发、想把AI能力接入业务系统或者收到过“这是AI吧”反馈的开发者阅读。1. 为什么“有人会说这是AI”能一眼被看穿1.1 大模型的生成机制是先预测下一个词而不是先查资料大语言模型本质上是一个自回归模型。它生成文本时做的事情是根据前面已经生成的token计算下一个token的概率分布然后采样出一个token再把这个token拼接进来继续预测下一个。token可以简单理解为模型处理文本的基本单位通常是单词、子词或字符。整个过程像是一个在单行道上逐步往前走的打字机。它并不存在一个“知识库查询”的动作也没有在生成前把数据库、文档、网页全部查一遍再组织答案。这个机制决定了两个重要结果。第一模型回答问题时优先保证的是“接下去说出来的内容在统计上合理”而不是“内容在事实层面正确”。第二模型对长上下文的依赖很强一旦prompt里没有提供相关证据它就只能依赖训练时学到的参数记忆。这种记忆是压缩过的、有时间截断的并且会互相混淆。理解这一点就能明白为什么AI会在一些细节上编出看似合理但实际不存在的内容。在工程上这个机制带来的启示是想让模型回答问题更可靠不能只依赖模型内部的记忆而要在生成过程之外增加“检索”和“约束”两个环节。这也正是RAG和提示词工程能够起效的根本原因。1.2 AI文本的表达指纹经常阅读AI生成文本的人会形成一些直觉判断。这不是玄学而是因为大模型训练数据里包含了大量结构规范、逻辑完整的文本比如技术文档、新闻通稿、论文摘要。这类文本经过自回归采样后会在表达上形成一些典型特征大量使用“首先”“其次”“最后”“总的来说”“需要注意的是”等过渡词。每个段落喜欢先抛结论再展开说明最后收束。排比句和递进结构出现频率高。表达周到但相对“安全”很少出现口语化的偏离。在事实细节上如果知识不足会用概率上最常见的组合去补全。这里并不是说带有这些特征就一定不是人写的而是说这类特征叠加起来会成为读者和检测工具判断“这像是AI生成”的依据。文本分类模型同样基于这些统计特征做判断。对工程人员来说更重要的是意识到一件事如果业务场景里需要AI直接面向用户输出内容输出风格、结构和事实准确性都应该被视为和功能逻辑同级别的产品需求而不是模型返回什么就展示什么。1.3 AI幻觉才是“识别AI”背后最值得关注的问题“有人会说这是AI”这句话里包含着一种隐含的怀疑这个内容不一定可信。这种怀疑的主要依据很大程度上来自AI幻觉。AI幻觉指的是模型生成的内容看起来流畅、结构完整但事实性内容错误、逻辑不合理或者引用了不存在的数据、文献和上下文。常见的幻觉类型包括三种。第一种是事实性幻觉比如把某项目使用的数据库从PostgreSQL写成MySQL。第二种是逻辑幻觉比如分析问题时前提和结论矛盾。第三种是引用幻觉比如生成一篇看起来规范的技术文章却加上根本不存在的论文编号或链接。幻觉在生产环境中的破坏力比文本风格更致命。如果AI只是用来写营销文案风格问题还能靠人工修改补救如果AI被接入客服、文档助手、代码生成管线一次事实错误就可能造成决策失误或代码漏洞。所以不能把“减少AI味”作为目标而应该把“降低幻觉、增强可追溯性”作为目标。这也是后面会重点介绍RAG和评估方法的原因。2. 从识别AI到控制AI围绕生成过程做约束2.1 提示词是生成过程的第一层约束提示词的本质不是让模型“理解”人的意图而是在给定上下文里为下一个token的预测设置更强的条件概率分布。你可以把模型想象成一个非常擅长接话的助手它说什么取决于你给它多少背景、多少要求、多少示例。角色设定、任务描述、输出格式、约束条件、few-shot示例都是在缩小它的输出空间。举个例子。如果不做任何约束直接问“这个项目用什么数据库”模型的回答可能是一段解释。如果把它改写成你是一个企业知识库问答助手。你只能根据用户提供的资料回答。如果资料中没有相关信息请直接回答“知识库中没有找到相关信息”不要编造。回答时先给结论再列出依据原文。这段提示词的作用就非常明确把开放问答变成了受限的抽取式问答。但要注意提示词并不能完全消除幻觉尤其是当检索到的资料与问题不相关或者资料本身存在歧义时模型仍然有可能“编造补充”。所以提示词只是第一层约束不是万能的。在实际开发中提示词应该具备可迭代性。建议把系统提示词独立成模板通过配置管理而不是硬编码在业务代码里。每次修改后都要跑一组固定的验证用例用真实问题确认行为变化避免因为一次prompt改动引入新的问题。2.2 RAG让模型回答前先检索证据RAGRetrieval-Augmented Generation检索增强生成是目前降低AI幻觉、增强答案可追溯性最常用的工程方案。它的核心思路并不复杂让模型在回答前先从外部知识库检索与问题相关的文档片段把这些片段作为上下文拼进prompt再让模型基于这些片段生成答案。为什么RAG能起作用因为生成模型的问题在于“过度依赖内部记忆”。RAG在生成链路中额外插入了一个“先查资料”的环节相当于在考试时给模型开卷。模型需要做的从“回忆出正确答案”变成了“根据提供的资料组织答案”。这对事实性问题的效果非常明显但仍有两个边界一是检索质量决定了答案上限如果资料本身不相关模型会基于错误上下文回答二是模型可能忽略prompt里的“只能根据资料回答”约束继续补充自己的知识。所以RAG方案必须配合显式的“来源引用”设计让模型在回答中给出基于哪条资料的提示。在选型上RAG不一定需要复杂的向量数据库。项目早期可以先用内存向量计算跑通流程再迁移到FAISS、Milvus、Elasticsearch等专业组件。关键是先理解链路再考虑规模化。2.3 Agent把“背诵”变成“执行”大模型的另一个常见问题是面对需要多步操作的任务时能力有限。比如用户问“帮我把上个月的销售数据汇总成一张表并指出异常项”如果只做一次问答模型很难完成因为它需要读取数据、计算、分析、生成表格。Agent智能体解决的是这个场景。Agent的基本形态是模型不再只负责“生成下一句话”而是负责任务规划、调用工具、观察结果、修正计划。常见的工具包括搜索、数据库查询、代码执行、发送HTTP请求、操作文件等。每一步执行结果都会作为新的上下文被模型继续推理直到任务完成。工程上引入Agent后要特别注意权限与成本控制。Agent每一步都消耗token如果任务没有明确的终止条件可能出现反复调用工具、预算超限的情况。生产环境需要设置最大步骤数、超时时间、敏感操作审批机制并对Agent的每步输出做日志记录。这篇文章后面的最小示例不涉及Agent因为RAG更适合演示“如何提高回答可信度”Agent更偏向任务编排是RAG之上的进阶方向。3. 最小可运行示例做一个带知识来源的问答服务3.1 环境准备与依赖这个示例的目标是用一个很小的代码量演示RAG链路知识库切片、向量化、按问题检索、把检索结果拼入提示词、调用大模型生成回答。示例使用Python语言通过OpenAI兼容接口调用大模型API适合多数大模型平台。不同平台的模型名和base_url不同实际使用时按对应平台的文档替换。环境要求如下项目要求Python3.9 及以上依赖包openai、numpy、pandas大模型API具备embedding和chat能力的OpenAI兼容接口环境变量OPENAI_API_KEY、OPENAI_BASE_URL、CHAT_MODEL、EMBEDDING_MODEL安装命令pip install openai numpy pandas在项目根目录创建.env文件按实际平台填写export OPENAI_API_KEY你的密钥 export OPENAI_BASE_URL你的接口地址 export CHAT_MODEL你的对话模型名称 export EMBEDDING_MODEL你的向量模型名称建议只通过环境变量读取密钥不要把密钥硬编码到代码里避免提交到仓库后泄露。3.2 准备知识库并切片下面用几段企业知识库示例文档作为演示数据。真实项目中文档来源一般是内部Wiki、产品需求、运维手册、数据库说明等。切片是把长文档拆成较短的片段保证检索单元足够聚焦也保证能放入模型上下文窗口。切片长度没有绝对标准常见做法是按段落切再按字符上限做二次截断。import os import numpy as np from openai import OpenAI client OpenAI( api_keyos.getenv(OPENAI_API_KEY), base_urlos.getenv(OPENAI_BASE_URL) ) CHAT_MODEL os.getenv(CHAT_MODEL, gpt-4o-mini) EMBEDDING_MODEL os.getenv(EMBEDDING_MODEL, text-embedding-3-small) knowledge_docs [ 项目X使用Spring Boot 3构建后端服务业务数据存储在PostgreSQL中。, 项目X在生产环境使用Nginx作为反向代理Java服务监听8080端口。, 项目X通过Prometheus采集指标Grafana展示监控面板告警由运维团队负责。, 项目X使用Flyway管理数据库版本迁移脚本位于src/main/resources/db/migration目录。, ] def chunk_docs(docs, max_chars200): chunks [] for doc in docs: doc doc.strip() if len(doc) max_chars: for i in range(0, len(doc), max_chars): chunks.append(doc[i:i max_chars]) else: chunks.append(doc) return chunks chunks chunk_docs(knowledge_docs) print(切片数量:, len(chunks))这里要注意示例切片只是按字符截断真实项目需要保留文档ID、标题、路径、章节号等元信息这样模型引用来源时才能给出可追溯的出处。切片后还需要清洗空行和无意义文本。3.3 向量化与相似度检索向量化的目标是把文本变成数值向量再用余弦相似度衡量问题和文档片段的语义距离。这个步骤的目的是找到和问题最相关的若干条资料。def get_embeddings(texts): resp client.embeddings.create(modelEMBEDDING_MODEL, inputtexts) return [item.embedding for item in resp.data] chunk_vectors get_embeddings(chunks) def top_k(query, k2): q_vec np.array(get_embeddings([query])[0]) scored [] for i, vec in enumerate(chunk_vectors): vec np.array(vec) score float(np.dot(q_vec, vec) / (np.linalg.norm(q_vec) * np.linalg.norm(vec))) scored.append((score, i)) scored.sort(reverseTrue) return [chunks[i] for _, i in scored[:k]]这段代码在数据量很小时足够用。生产环境里文档数量通常是几万甚至百万级别继续用内存遍历计算相似度会让检索延迟明显增加。这时应该引入支持向量索引的组件例如FAISS、Milvus、Qdrant或者使用Elasticsearch的向量检索能力。但检索逻辑本身不变都是“先向量化再找topk”。3.4 把检索结果拼进提示词检索到相关片段后需要把它们组装成system prompt。这里的关键是明确告诉模型三件事只能依据资料回答、资料中没有就明说、回答时要能对应到资料原文。def ask(question): relevant top_k(question, k2) context \n.join(relevant) system_prompt ( 你是一个企业知识库问答助手。请只依据下面提供的资料回答问题。 如果资料中没有相关信息请直接回答“知识库中没有找到相关信息”不要编造。 回答时先给出结论再简要列出依据原文。\n\n f资料\n{context} ) resp client.chat.completions.create( modelCHAT_MODEL, temperature0.2, messages[ {role: system, content: system_prompt}, {role: user, content: question}, ], ) return resp.choices[0].message.contenttemperature设置为0.2是为了让生成结果更稳定减少随机性。如果业务场景需要更多多样性和创造性可以调高如果做知识问答和结构化输出建议保持在0到0.3之间。注意temperature0.2 适用于知识问答和结构化输出不代表其他所有任务都合适。创意写作、营销文案等场景可以提高该参数但也要做好随机性带来的质量波动。3.5 运行验证与预期输出执行下面这段入口代码if __name__ __main__: print(ask(项目X使用什么数据库)) print(ask(项目X的监控方案是什么)) print(ask(项目X使用什么日志框架))正常情况下的预期输出项目X使用PostgreSQL作为业务数据库。依据项目X使用Spring Boot 3构建后端服务业务数据存储在PostgreSQL中。 项目X通过Prometheus采集指标Grafana展示监控面板告警由运维团队负责。依据项目X通过Prometheus采集指标Grafana展示监控面板告警由运维团队负责。 知识库中没有找到相关信息。第三个问题“使用什么日志框架”在知识库里没有对应资料符合预期的回答是明确表示没有相关信息而不是猜测“可能使用了Logback”这类模型常见偏好。这一步是验证RAG是否生效的关键如果模型在资料缺失时仍然给出一个看似合理的答案说明prompt约束还没有生效需要回到提示词和检索质量上排查。验证RAG是否生效不能只看回答是否流利而是要看“资料缺失时模型是否承认不知道”。4. AI输出质量怎么评估不能只看“看起来流利”4.1 评估维度表很多项目在接入大模型后验收时只看“回答是否流畅”这是不够的。流利只是生成质量的一个维度在工程化场景里更应该关注事实性、可追溯性和稳定性。下面是一张可以直接用于评估的维度表维度说明评估方法事实一致性回答中的事实是否与知识库、资料或真实数据一致人工核对回答与资料原文或使用标注集抽样可追溯性回答是否能定位到来源文档、段落或数据记录检查模型是否输出来源标识验证标识可点击跳转完整性是否覆盖了用户问题的关键部分人工对照问题清单检查遗漏项格式正确性返回的JSON、表格、代码块是否符合约定自动解析校验解析失败率纳入监控稳定性相同问题多次调用结果是否一致对同一组测试用例跑多轮计算差异率延迟与成本单次回答耗时、token消耗是否可接受API调用日志统计设置告警阈值其中事实一致性和可追溯性是衡量RAG系统是否合格的底线指标。4.2 可追溯性是工程化AI问答的关键可追溯性指的是用户能看出回答中的关键结论来源于哪份资料。有了可追溯性即使模型回答有误人工也能快速定位错误源头而不是从头到尾再查一遍。实现可追溯性的做法是在知识库切片阶段为每一条片段保留唯一编号和来源描述
返回列表