FEATURED · 精选文章

AI不可靠?从评估到兜底的工程实践指南

发布时间 / 2026/8/31 16:44:05
来源 / 创域科博编辑部
栏目 / 资讯中心
AI不可靠?从评估到兜底的工程实践指南 在实际 AI 应用开发中很多团队已经不再纠结于“要不要接入大模型”而是直接进入“怎么接、怎么上线、出错怎么办”的阶段。但真正和模型打过交道的开发者都会有同感AI 并没有那么全能它经常一本正经地给出错误答案或者上一轮表现良好、下一轮完全跑偏。把这类系统比作 “Not so competent AI overlords” 再合适不过——表面上像一个无所不知的统治者实际上是一套概率计算系统需要在工程上被约束、被校验、被兜底。这篇文章围绕一个核心问题展开当 AI 不可靠时我们如何在真实项目中识别失败、量化失败、缓解失败。文章会从大模型的机制边界讲起然后搭建一个可复现的评估环境用最小实验复现幻觉、输出格式不稳定、推理退化等现象最后给出生产环境下的校验、重试、日志和兜底设计。适合正在做 AI 应用开发、AI Agent、模型部署和 AI 工程实践的工程师阅读。1. 先认清 AI 的“全能”是错觉限制来自模型机制本身1.1 大模型为什么会产生“看起来正确但实际错误”的结果大模型的本质不是知识库而是一个基于海量文本训练出来的概率语言模型。它的每个输出都来自下一步 token 的概率预测模型根据当前上下文算出最可能出现的下一个词。这意味着模型追求的是“语义连贯”和“概率合理”而不是“事实为真”。这就是幻觉产生的根源。当模型遇到训练数据里没有出现过、或者出现次数很少的信息时它会用最接近的语言模式去补齐答案。补齐出来的内容往往语法通顺、结构完整但事实可能是凭空捏造的。例如问一个冷门历史人物生卒年模型可能给出一个看起来非常具体、实际上错误的年份。工程上必须接受一个前提大模型没有“知道”和“不知道”的明确状态。它只有“概率高”和“概率低”的连续分布。即使概率很低它也仍然可能输出错误内容。所以把大模型当作可靠知识源来用是很多 AI 应用翻车的根本原因。1.2 上下文窗口、训练数据截止和概率采样是三个硬边界上下文窗口决定了模型一次能“看到”多少内容。超过窗口长度的历史对话或文档会被截断模型可能因此丢失关键信息导致后续回答前言不搭后语。在长文档问答、多轮 Agent 对话场景中这个边界尤其容易被踩到。训练数据截止日期决定了模型的知识新鲜度。模型不可能知道训练结束后发生的事件除非通过检索增强RAG或外部工具补充信息。如果业务场景强依赖最新数据却直接拿模型本身回答那么答案过期几乎是必然的。概率采样则决定了同一个 prompt 可能得到不同结果。temperature 越高输出随机性越大temperature 越低输出越稳定但也不是确定性输出。把 temperature 设成 0 并不等于固定输出只是概率分布更尖锐。生产环境里如果期望完全一致的结果必须在工程层做缓存或做结果重试比对。1.3 在工程上把 AI 当“概率组件”而不是“权威组件”既然 AI 是概率组件工程上就不能沿用传统函数调用的思路。传统函数有明确输入输出契约而大模型输出天然带不确定性。正确的做法是在模型外面加一层工程约束定义输出格式、做校验、失败重试、提供兜底。换一句话说AI 应该被当作一个“能力很强但稳定性不够”的组件。它适合生成初稿、提取信息、拆分任务、做语义匹配但不适合直接充当最终决策者。最终决策应交给确定性的规则、代码逻辑和人工审核。这个认知转变是 AI 工程实践里最重要的一步。2. 搭建一个可复现的 AI 能力评估环境2.1 环境与依赖先把测试基线固定下来评估 AI 之前先要固定环境否则测试结果没有可比性。建议至少固定四样东西模型名称与版本、采样参数、prompt 模板、测试数据集。在本地验证阶段可以使用兼容 OpenAI 接口的本地部署方案例如 Ollama 启动的模型服务。这样不需要担心外部服务波动也比较容易复现问题。生产环境接云端大模型时评估脚本仍然可以复用只需要更换 base_url 和 api_key。环境项推荐配置说明Python 版本3.10 及以上兼容 Pydantic 等校验库模型服务Ollama 本地模型或云端兼容接口统一走 OpenAI 兼容协议更省事依赖库openai、pydantic、jsonschema分别用于调用、结构化校验测试模型固定一个模型标签不要漂移例如 qwen2.5:7b不要今天换一个注意模型标签必须固定。同一个模型名称在不同日期可能对应不同权重版本评测结果会失真。2.2 先准备一组覆盖常见失败模式的测试用例评估用例不是越多越好而是覆盖要全。建议至少包含四类用例事实性问答、指令遵循、多步推理、越界输入。每类用例都要有预期结果或明确的判定标准。事实性问答用来测幻觉。指令遵循用来测输出格式稳定性。多步推理用来测复杂任务退化。越界输入用来测模型是否会拒绝回答、还是会强行编造。用例类型示例输入判定标准事实性问答“鲁迅的原名是什么”答案包含“周树人”指令遵循“只输出 JSON不要解释”输出可被 json.loads 解析多步推理数学应用题最终数字正确越界输入与主题无关的问题模型拒绝或表示无法回答而不是编造2.3 编写评估脚本记录输出、耗时与失败类型评估脚本要做的不是简单打印结果而是把每个用例的输入、输出、耗时、判定结果记录下来。记录字段越完整后面排错越容易。from openai import OpenAI import time import json client OpenAI( base_urlhttp://localhost:11434/v1, api_keylocal ) cases [ { name: fact_lu_xun, prompt: 鲁迅的原名是什么请直接给出姓名。, validator: 周树人在答案中 }, { name: json_format, prompt: 请只输出 JSON内容为 {\name\: \张三\, \age\: 30}不要输出其他内容。, validator: json }, { name: math_reasoning, prompt: 商店里有 5 箱苹果每箱 12 个卖出 8 个还剩多少个请只输出数字。, validator: 52 } ] results [] for case in cases: start time.time() resp client.chat.completions.create( modelqwen2.5:7b, messages[{role: user, content: case[prompt]}], temperature0.2, max_tokens256 ) latency time.time() - start text resp.choices[0].message.content.strip() results.append({ name: case[name], prompt: case[prompt], output: text, latency: round(latency, 2), usage: dict(resp.usage) if resp.usage else {} }) print(case[name], |, text[:80], |, round(latency, 2), s) with open(eval_results.json, w, encodingutf-8) as f: json.dump(results, f, ensure_asciiFalse, indent2)这段脚本的核心价值在于把“感觉模型不行”变成“模型在哪些具体用例上不行”。输出保存成 JSON 后可以后续分析失败类型也可以作为回归基线。后续修改 prompt 或更换模型时再跑一遍同样脚本对比差异即可。3. 用最小实验复现“不靠谱”现象并量化它3.1 实验一事实性任务中的幻觉表现用事实性问答用例反复测试很容易观察到两个现象。第一在模型熟悉的知识范围内答案通常正确第二在冷门或模型不确定的问题上答案可能非常流畅但完全错误。例如问“鲁迅的原名是什么”模型大概率回答“周树人”这是训练语料中的高频知识。但如果问一个冷门历史人物或者一份内部业务文档里的内容模型就会开始“合理编造”。验证方式很简单把同一类未知问题跑 10 次统计有多少次输出包含了模型无法从给定上下文推导出的具体细节。3.2 实验二指令遵循失效与格式不稳定大模型对格式要求的遵循能力往往被高估。测试“只输出 JSON”时模型可能输出带解释的文字、Markdown 代码块或者在 JSON 前后加多余符号。这不是小概率事件在很多开源模型上尤其明显。# 模型常见错误输出示例 好的以下是你要求的 JSON json {name: 张三, age: 30}希望这个回答对你有帮助。这段输出人类能看懂但程序直接执行 json.loads 会报错。生产中这类问题非常常见解决方案不是让 prompt 写得更严厉而是接入结构化输出或做后置清洗。 ### 3.3 实验三多步推理在复杂度升高时的退化 多步推理是另一个容易踩坑的点。简单数学应用题模型通常能答对。但随着步骤增加、条件变多、干扰信息出现正确率会明显下降。原因在于 Transformer 架构的注意力机制在处理长链条逻辑时容易出现中间步骤错误而错误会一路传播到最终结果。 ### 3.4 把实验结果整理成可决策的表格 跑完一组用例后把结果汇总成表格能让问题更直观。 | 用例 | 尝试次数 | 成功次数 | 失败类型 | 平均耗时 | | --- | --- | --- | --- | --- | | 事实性问答 | 10 | 8 | 2 次编造具体细节 | 1.2s | | JSON 格式输出 | 10 | 5 | 5 次带 Markdown 或解释 | 0.9s | | 多步推理 | 10 | 6 | 4 次中间计算错误 | 1.5s | 这类表格的价值在于它提醒团队不要凭印象判断模型能力而是用数据确定哪些环节需要加固。如果 JSON 格式失败率高达 50%那么格式校验和重试就必须做如果事实问答在特定领域失败率高就要考虑接入 RAG 或工具调用。 ## 4. 在真实应用里为 AI 的不可靠性设计防线 ### 4.1 结构化输出加校验而不是直接解析自然语言 生产环境里最忌讳的做法是让模型生成自然语言然后程序用字符串匹配或正则去解析。模型输出稍有变化解析就会崩溃。正确做法是让模型输出结构化格式并在应用层做严格校验。 以 JSON 输出为例可以让模型走 JSON Mode 或 function calling再用 Pydantic 做字段级校验。 python import json from pydantic import BaseModel, ValidationError class UserInfo(BaseModel): name: str age: int def parse_model_output(output: str): # 先去掉可能的 Markdown 代码块标记 cleaned output.strip() if cleaned.startswith(): cleaned cleaned.strip() if cleaned.startswith(json): cleaned cleaned[4:].strip() data json.loads(cleaned) return UserInfo(**data)校验不是可选项。字段类型不对、字段缺失、JSON 语法错误都应该被当成模型调用失败来处理而不是硬着头皮继续往下走。4.2 重试、降级和兜底把失败控制在可接受范围因为模型输出不稳定业务链路里必须设计重试和兜底。重试的对象不是整个业务流程而是模型调用加校验这一段。校验失败就重新调用连续多次失败就进入降级逻辑。def call_with_retry(prompt, max_retries2): last_error None for attempt in range(max_retries 1): try: text call_model(prompt) validated validate_model_output(text) if validated is not None: return validated except Exception as e: last_error e log_event(model_call_retry, attemptattempt, errorstr(e)) log_event(model_call_fallback, errorstr(last_error)) return default_fallback(prompt)注意一个细节重试时是否要变化 prompt。如果失败原因是格式问题可以换一个更强的格式描述重新请求如果失败原因是模型本身生成错误可以降低 temperature 再试。不加区分地盲目重试效果有限。4.3 用缓存和评测沉淀减少重复成本模型调用有成本也有延迟。同一个问题短时间内反复出现时应该做缓存。缓存 key 建议包含模型名称、temperature、prompt 主体、必要的版本号避免不同配置互相污染。同时每个线上失败案例都应该回流到评测集。发现模型在某类 prompt 上表现差就把这个案例记录下来加入回归测试。这样模型版本升级或 prompt 优化时能快速判断改动是进步还是退步。5. 常见问题排查从现象定位到模型还是应用层5.1 现象表与排查顺序遇到 AI 应用表现异常时先别急着改 prompt。按顺序排查先看输入是否完整再看模型参数是否固定然后看输出校验逻辑最后看日志。问题现象常见原因检查方式处理建议答案事实错误模型幻觉对照评测集和知识来源接入 RAG、引入外部检索、降低 temperature输出格式不稳定模型指令遵循能力不足检查原始输出和解析报错使用 JSON Mode增加后置清洗和重试同一问题结果不同采样随机性检查 temperature 和模型版本固定参数必要时做结果一致性缓存请求超时模型负载高或输出过长查看调用耗时和 token 使用量设置超时时间做排队限流剪短输出长文回答被截断达到 max_tokens 限制检查 usage 里的 completion_tokens提高 max_tokens或要求模型分块输出5.2 日志要记录哪些关键字段很多团队排错困难是因为日志里只有一句“调用模型失败”缺少上下文。建议每条模型调用至少记录以下字段。字段说明prompt_version当前 prompt 模板版本方便回溯model_name实际调用的模型名称和版本temperature采样参数request_tokens输入 token 数response_tokens输出 token 数latency_ms本次调用耗时raw_output模型原始输出validated校验是否通过error_type失败分类例如 timeout、json_error、validation_error有了这些字段才能回答“到底是模型不行还是我们的校验逻辑有问题”这个核心问题。5.3 几个典型坑与修复方式第一个典型坑是不固定模型版本。线上和测试环境用的模型不一致导致 prompt 在测试环境表现正常、线上表现异常。解决方式是记录并固定模型版本升级模型时走单独流程。第二个典型坑是忽略 temperature 对结果的影响。生产环境直接把 temperature 调成 0 就以为确定实际上仍可能变化。建议在对一致性要求高的场景做输出缓存或者多次采样取多数结果。第三个典型坑是把所有失败都归因于模型。很多“AI 问题”其实是上下文被截断、prompt 写得太模糊、校验规则写错、甚至业务数据本身有问题。排查时先看输入输出链路再判断模型责任。6. 生产环境的最佳实践与检查清单6.1 学习环境与生产环境的差异学习环境里跑通一个 prompt和生产环境上线一个 AI 功能距离非常远。差异主要体现在对失败的处理上。维度学习环境生产环境模型版本随手切换固定版本灰度升级输出处理人工看结果结构化校验 重试 兜底评测单个用例评测集 回归基线日志可有可无结构化日志 监控告警成本不敏感缓存 token 统计 预算控制安全不关注敏感信息过滤 权限控制本地模型部署可以解决数据出境和成本波动问题但也需要额外处理显存、量化、并发和日志采集。具体选型要结合团队运维能力不要只图省事。6.2 发布前检查清单上线一个 AI 功能之前建议逐项核对以下清单。模型名称、版本、采样参数已固定并记录在配置中心已有至少 20 到 50 条评测用例覆盖正常、边界和越界场景模型输出有明确的格式校验规则校验失败会触发重试重试策略有最大次数限制避免无限循环连续失败时有降级方案用户能收到明确提示每个模型调用都记录日志包含 prompt 版本、token 数量、耗时和校验结果上线前做过影子测试或小流量灰度有成本监控单日调用量和 token 消耗异常时能告警敏感信息不会进入 prompt也不会写入日志6.3 下一步扩展方向如果已经完成了上面的评估和防线建设下一步可以往三个方向深入第一个方向是接入检索增强生成RAG把领域知识交给外部检索而不是让模型硬记第二个方向是引入工具调用和 Agent 能力让模型通过查数据库、调接口来获取准确数据而不是靠记忆生成第三个方向是建立效果回归机制每次模型升级、prompt 调整、RAG 策略变化后都通过评测集自动对比效果。无论是哪个方向原则都是一致的模型负责生成工程负责约束。承认 AI 不是全能统治者才能把它放在正确的位置上让它发挥真正有用的能力。
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻