1. 从一次“翻车”问答说起DeepSeek 事实性幻觉到底怎么测前阵子我在做一个金融科技方向的问答小工具用户问“某家银行 2024 年第三季度的资本充足率是多少”DeepSeek 给了一个看起来非常专业的数字还配了百分比和同比变化。我差点就信了结果去查监管披露文件发现那个数字根本对不上。这就是典型的 AI 幻觉模型不是“不知道”而是用统计概率拼出了一个“合理但错误”的答案。清华大学第五版《DeepSeek 与 AI 幻觉》把这件事讲得很透。它把幻觉分成两大类事实性幻觉指输出与可验证事实不一致忠实性幻觉指输出与用户指令或上下文不一致。前者是“说错话”后者是“没听话”。在事实性问答场景里事实性幻觉最要命因为它看起来太像真的了。那怎么测报告里给了通用性测试和事实性测试两条路。通用性测试靠人工标注成本高事实性测试更适合工程化复现核心思路是准备一批有标准答案的问题让模型回答再用规则或另一个模型去比对答案最后算幻觉率。听起来简单但真做起来第一个坑就是 API Key 管理。你要对比 DeepSeek V3、R1 等多个模型如果每个模型都单独申请 Key、单独改环境变量脚本会变得非常难维护。我试过用 TaoToken 的统一 Key 来管这件事。它把多个模型的调用入口收敛到一个 Base URL 和一把 Key 上切换模型只需要改一个 Model ID 参数。这样复现幻觉检测实验时我可以把精力放在评测逻辑上而不是在 Key 和配置文件之间来回折腾。下面我就把整套可复制的流程拆开讲包括配置、调用、验证和排错。2. TaoToken 统一 Key 前置准备一次配置多模型切换在开始写幻觉检测脚本之前先把调用通道搭好。TaoToken 的定位是统一模型接入层你不需要为每个模型单独维护一套鉴权逻辑。官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 地址是 https://taotoken.net/api 注意 API 地址后面不加 UTM 参数直接写就行。第一步去控制台创建 API Key。打开 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 登录后进入 API Keys 页面点新建复制生成的 Key。这个 Key 就是后面所有模型调用的统一凭证。建议把它存到环境变量里不要硬编码在脚本中。第二步确认你要用的模型 ID。幻觉检测实验里我一般会选 DeepSeek 系列的对话模型比如 deepseek-chat 或 deepseek-reasoner。具体可用的 Model ID 以文档为准文档地址是 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。如果你还想做交叉验证也可以把其他模型加进来统一 Key 的好处就在这里换模型只改一个字符串。第三步设置环境变量。Linux/macOS 下可以这样写export TAOTOKEN_API_KEYsk-你的Key export TAOTOKEN_BASE_URLhttps://taotoken.net/apiWindows PowerShell 下$env:TAOTOKEN_API_KEYsk-你的Key $env:TAOTOKEN_BASE_URLhttps://taotoken.net/api如果你用 Python 脚本也可以直接在代码里读环境变量避免 Key 泄露。这里有个细节Base URL 末尾不要带斜杠很多 SDK 会自动拼接 /v1/chat/completions多一个斜杠会导致 404。我踩过这个坑排查了半天才发现是 URL 拼接问题。另外如果你打算长期跑评测任务建议了解一下 Coding Plan它更适合高频调用场景入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。不过对于一次性的幻觉检测实验按量调用就够用了。配置完成后你可以先用模型对话页面快速验证 Key 是否可用 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。在页面里选一个 DeepSeek 模型发一句“你好”如果能正常回复说明 Key 和网络都没问题。这一步看似简单但能帮你排除掉大部分低级错误。3. 可复制配置JSON/TOML/settings 片段与 DeepSeek 调用参数这一节直接给可复制的配置片段。不管你用哪种工具链核心三件套都是 Base URL、API Key、Model ID。下面我按几种常见场景分别写。3.1 通用 JSON 配置适用于大多数 HTTP 客户端{ base_url: https://taotoken.net/api, api_key: sk-你的Key, model: deepseek-chat, temperature: 0.2, max_tokens: 1024, top_p: 0.9 }这里 temperature 设成 0.2 是为了降低随机性。幻觉检测实验里我们希望模型尽量稳定输出而不是每次都给不同答案。top_p 设 0.9 也是类似目的。max_tokens 根据你的问题长度调整一般 1024 够用。3.2 TOML 配置适用于 Codex 类工具如果你用 Codex 风格的配置文件可以这样写[model] base_url https://taotoken.net/api api_key sk-你的Key model_id deepseek-chat temperature 0.2 max_tokens 1024注意 model_id 这个字段名有些工具叫 model有些叫 model_id以你实际使用的工具文档为准。TaoToken 的文档里会给出标准字段名建议对照一下。3.3 Claude Code 的 settings 片段如果你在 Claude Code 环境里做实验settings 文件可以这样配{ anthropic_base_url: https://taotoken.net/api, anthropic_api_key: sk-你的Key, model: deepseek-chat }这里要说明一下Claude Code 默认走 Anthropic 协议TaoToken 的 API 地址兼容这种调用方式。如果你遇到 OAuth 相关报错检查一下是不是把 base_url 写成了带 /v1 的路径。正确的写法是只写到 https://taotoken.net/api 后面的路径由 SDK 自己拼。3.4 Python 调用示例下面是一段可以直接跑的 Python 代码用 requests 库调用 DeepSeek 模型import os import requests import json API_KEY os.getenv(TAOTOKEN_API_KEY) BASE_URL os.getenv(TAOTOKEN_BASE_URL, https://taotoken.net/api) def ask_deepseek(question, modeldeepseek-chat): url f{BASE_URL}/v1/chat/completions headers { Authorization: fBearer {API_KEY}, Content-Type: application/json } payload { model: model, messages: [ {role: system, content: 你是一个严谨的事实性问答助手不确定时请回答不知道。}, {role: user, content: question} ], temperature: 0.2, max_tokens: 512 } resp requests.post(url, headersheaders, jsonpayload, timeout60) resp.raise_for_status() data resp.json() return data[choices][0][message][content] if __name__ __main__: answer ask_deepseek(珠穆朗玛峰的海拔是多少米) print(answer)这段代码里system prompt 加了一句“不确定时请回答不知道”这是缓解幻觉的提示词工程手段之一。报告里提到的“知识锚定法”和“对抗性提示”也可以在这里加进去后面我会展开。3.5 幻觉检测脚本的完整结构光能调用还不够我们要的是可复现的评测流程。下面是一个幻觉检测脚本的骨架import json import re # 测试集问题 标准答案关键词 test_cases [ {q: 珠穆朗玛峰的海拔是多少米, keywords: [8848, 8844]}, {q: 水的化学式是什么, keywords: [H2O]}, {q: 2024年诺贝尔物理学奖颁给了谁, keywords: [Hinton, Hopfield]}, # 更多事实性问题... ] def check_hallucination(answer, keywords): for kw in keywords: if kw.lower() in answer.lower(): return False # 命中标准答案不算幻觉 return True # 没命中判定为幻觉 def run_eval(model_id): results [] for case in test_cases: ans ask_deepseek(case[q], modelmodel_id) is_halluc check_hallucination(ans, case[keywords]) results.append({ question: case[q], answer: ans, hallucination: is_halluc }) total len(results) halluc_count sum(1 for r in results if r[hallucination]) rate halluc_count / total if total else 0 return results, rate if __name__ __main__: for model in [deepseek-chat, deepseek-reasoner]: res, rate run_eval(model) print(f模型 {model} 幻觉率: {rate:.2%})这个脚本的核心逻辑是关键词匹配。实际做实验时你可以把关键词匹配换成更严格的语义比对或者用另一个模型做裁判。但关键词匹配的好处是快、可解释、不依赖额外模型。4. 验证请求与成功结果跑通第一个幻觉检测用例配置写好了接下来跑一个最小验证。先确认 API 能通再跑完整评测。第一步用 curl 发一个请求curl -X POST https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d { model: deepseek-chat, messages: [{role: user, content: 珠穆朗玛峰的海拔是多少米}], temperature: 0.2 }如果返回 JSON 里有 choices 字段并且 message.content 里有“8848”或“8844”说明调用成功。如果返回 401检查 Key 是否正确如果返回 404检查 URL 是否多写了 /v1 或少了 /v1。第二步跑 Python 脚本。把上面的 ask_deepseek 函数和测试集放到一个文件里执行python hallucination_eval.py预期输出类似模型 deepseek-chat 幻觉率: 12.50% 模型 deepseek-reasoner 幻觉率: 8.33%这个数字不是绝对的因为测试集大小和问题难度会影响结果。但你可以用它做相对比较同一个测试集下哪个模型幻觉率更低哪个提示词策略更有效。第三步做交叉验证。报告里提到“双 AI 交叉验证”是用户应对策略之一。你可以让 DeepSeek 先回答再让另一个模型判断这个回答是否与事实一致。代码结构如下def cross_check(question, answer): prompt f请判断以下回答是否与事实一致只输出一致或不一致\n问题{question}\n回答{answer} verdict ask_deepseek(prompt, modeldeepseek-chat) return 不一致 in verdict这样你就有了一套可复现的评测流程单模型幻觉率 交叉验证幻觉率。实测下来交叉验证能抓出一些关键词匹配漏掉的幻觉比如模型用同义词替换了标准答案但事实仍然错误。第四步记录结果。建议把每次实验的模型 ID、temperature、提示词版本、幻觉率都存到 CSV 里。这样当你调整提示词或换模型时能清楚看到变化趋势。我一般用 pandas 直接存import pandas as pd df pd.DataFrame(results) df.to_csv(feval_{model_id}.csv, indexFalse)5. 常见报错排查401、local proxy failed、reading choices、OAuth做实验过程中报错是难免的。下面这几个是我实际遇到过的按出现频率排序。5.1 401 Unauthorized报错信息通常是{error: {message: Invalid API key, type: invalid_request_error}}原因很简单Key 不对。检查三件事环境变量是否真的被读到了用echo $TAOTOKEN_API_KEY确认Key 是否复制完整有没有多余空格Key 是否已经过期或被删除。如果都没问题去控制台重新生成一个 Key 试试。5.2 local proxy failed报错信息类似Error: local proxy failed to connect这个通常出现在你本地设置了网络代理但代理没有正常工作时。TaoToken 的 API 地址是直连的不需要额外代理。检查你的环境变量里有没有 HTTP_PROXY 或 HTTPS_PROXY如果有临时取消掉unset HTTP_PROXY unset HTTPS_PROXY然后重新跑脚本。如果你在公司内网可能需要检查防火墙是否放行了 taotoken.net 的域名。5.3 reading choices 报错报错信息KeyError: choices或者TypeError: NoneType object is not subscriptable这说明返回的 JSON 里没有 choices 字段。常见原因有三个一是请求体格式不对比如 messages 写成了字符串而不是数组二是模型 ID 写错了服务端返回了错误信息而不是正常回复三是 max_tokens 设得太小导致返回被截断。排查方法先把 resp.json() 打印出来看看完整返回是什么。如果是错误信息里面会有具体原因。5.4 OAuth 相关报错如果你在 Claude Code 或类似工具里看到 OAuth 报错比如OAuth token exchange failed这通常是因为工具默认走 OAuth 流程而你用的是 API Key 鉴权。解决办法是在配置里显式指定 API Key 模式或者把 base_url 改成 TaoToken 的 API 地址。具体配置参考第 3 节的 settings 片段。如果工具同时支持 OAuth 和 API Key优先选 API Key因为更稳定、更容易排查。5.5 模型返回空内容有时候请求成功了但 content 是空字符串。这可能是模型在“思考”但没输出或者触发了内容安全策略。检查一下你的 prompt 里有没有敏感词或者把 temperature 调高一点再试。如果还是空换一个模型 ID 试试。5.6 幻觉率异常高如果你发现某个模型的幻觉率突然飙升到 80% 以上先别急着下结论。检查测试集的关键词是否写得太严格比如标准答案是“8848.86”你只写了“8848”模型回答“约 8848 米”可能被误判。另外temperature 太高也会导致模型自由发挥。把 temperature 降到 0.1 再跑一次看看结果是否稳定。6. 从检测到缓解提示词工程与 RAG 的实操建议测出幻觉率只是第一步更重要的是怎么缓解。报告里给了技术方案和用户策略两条路。技术方案包括 RAG 框架、外部知识库结合、精细训练与评估工具用户策略包括联网搜索验证、双 AI 交叉验证、提示词工程。我这里重点讲提示词工程因为它最容易落地不需要额外基础设施。6.1 时间锚定法很多幻觉是因为模型的知识截止日期和当前时间不匹配。比如你问“2025 年某公司 CEO 是谁”模型可能用 2023 年的数据回答。时间锚定法就是在 prompt 里明确时间范围请基于 2024 年 12 月之前的信息回答如果不确定请说明“该信息可能已过时”。这样模型会更谨慎减少“用旧知识回答新问题”的情况。6.2 知识锚定法把已知事实作为上下文传给模型让它基于给定信息回答而不是依赖参数化记忆已知信息珠穆朗玛峰的海拔为 8848.86 米。 问题珠穆朗玛峰的海拔是多少米 请仅基于上述已知信息回答。这种方法在 RAG 场景里很常见。你可以把外部知识库的检索结果拼到 prompt 里模型就不容易胡编了。6.3 对抗性提示让模型自己检查答案请回答以下问题然后自我检查你的回答是否有事实依据如果有不确定的地方请标注出来。这种“自我反思”能降低一部分幻觉但也不是万能的。实测下来对抗性提示对逻辑陷阱类问题效果较好对纯事实错误效果一般。6.4 RAG 框架的简化实现如果你不想引入完整的 RAG 系统可以用一个简化版把本地知识库做成关键词检索把检索结果拼到 prompt 里。代码结构如下def rag_answer(question, knowledge_base): # 简单关键词检索 relevant [doc for doc in knowledge_base if any(kw in doc for kw in question.split())] context \n.join(relevant[:3]) prompt f基于以下信息回答问题\n{context}\n\n问题{question} return ask_deepseek(prompt)这个简化版虽然粗糙但能明显降低事实性幻觉。你可以先用它跑一轮评测看看幻觉率下降多少再决定要不要上更复杂的向量检索。6.5 评测结果对比的注意事项报告里对比了 DeepSeek V3、R1、Qianwen2.5-Max、豆包等模型。你在自己复现时要注意控制变量同一个测试集、同一个 temperature、同一个提示词模板。否则对比结果没有意义。另外模型版本会更新今天的评测结果明天可能就变了所以建议在报告里记录评测日期和模型版本号。最后说一个实用技巧把幻觉检测脚本做成定时任务每周跑一次。这样你能持续监控模型表现而不是只做一次实验。长期来看这比单次评测更有价值。如果你需要更稳定的调用配额可以看看 Coding Plan它适合这种周期性评测场景。模型对话页面也可以用来快速抽查单个问题不用每次都跑脚本。