ARTICLE DETAIL

资讯详情

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

AI能力边界:从幻觉产生到评测落地的工程实践指南

AI能力边界:从幻觉产生到评测落地的工程实践指南 先说明一点这里的“AI overlords”并没有贬低大模型的意思。相反只有把 AI 当成一个“能力很强、但会犯错”的协作者我们在做 AI 应用、Agent 开发、模型部署时才不会盲目相信输出也才知道该在哪些环节加校验、兜底和人工确认。这篇文章我会围绕“AI 能力边界”展开先聊清楚大模型为什么会一本正经地胡说八道再给出可落地的评估方法、代码示例以及 AI 编程和 Agent 开发中最常见的坑。内容偏工程实践适合正在做 AI 应用落地、或准备把大模型接入业务系统的开发者。1. AI 不是全知全能先认清能力边界再谈工程落地1.1 “AI 全能”的说法为什么经不起推敲过去两年大模型的发展速度确实快从文本对话到代码生成、从 Agent 自动化到多模态理解几乎每个月都有新能力出现。于是很多文章开始用“AI 颠覆一切”“大模型无所不能”这类标题吸引眼球。但在真实开发中你会发现大模型的表现远没有宣传中那么稳定。比如同一个 Prompt今天回答正确明天换了模型版本就答错同一个逻辑问题换个问法结果完全不同让它写一段 Python 代码看着逻辑通顺实际上引用了不存在的库让它总结一份文档它能把文档里没有的内容“脑补”进去。这些不是偶发问题而是大模型基于概率生成文本的天然缺陷。所以在工程层面我们首先要接受一个事实强大的 AI 能力不等于可靠的 AI 能力。把“能力”变成“可靠性”需要额外的评测、约束、校验和兜底设计这正是 AI 工程化最核心的部分。1.2 AI 能力强项与弱项的对比从实际使用体验来看大模型的能力分布很不均匀。我整理了一个粗略对比任务类型AI 表现原因文案改写、摘要、翻译很好语言分布覆盖广生成流畅代码片段生成、正则表达式较好训练数据中代码占比高模式清晰数学计算、精确数值较差概率生成不适合精确计算多跳推理、长链路逻辑不稳定注意力会被中间错误带偏实时信息、私有数据较差知识有截止日期且无法访问内部数据创造性写作、头脑风暴很好概率采样天然有发散性代码运行结果预测容易翻车变量状态、依赖版本影响大这个表格想说明的是AI 适合“生成候选内容”不适合“保证结果正确”。在工程落地时我们要把 AI 放在生成候选的位置用规则、测试、人工审核来保证最终正确性。1.3 正确看待 AI从“替代”到“辅助”很多团队引入 AI 时会有一种预期让 AI 替代某个岗位节省人力。但现实是AI 更适合做“辅助放大器”而不是“独立执行者”。一个比较合理的人机协作模式是AI 生成初稿或候选方案。人工或规则系统进行校验。校验不通过时AI 根据反馈修正。修正后仍然不通过则交给人工处理。这套模式看起来简单但在实际开发中很多失败案例都是因为跳过了第二步和第四步直接把 AI 输出当成最终结果。理解了这一点接下来我们看看大模型最容易出问题的“幻觉”现象以及如何在工程上应对。2. AI 幻觉是怎么产生的从概率生成看不确定性2.1 什么是 AI 幻觉AI 幻觉是指模型输出看似合理、语法通顺但实际上与事实不符、逻辑矛盾或完全没有依据的内容。早期 GPT-3 时代幻觉问题主要表现为编造历史人物、虚构论文引用。到了 GPT-4 和国内主流大模型时代幻觉形式更隐蔽比如编造不存在的 API 接口和参数。在代码题中混入错误的函数名。对业务数据进行错误推导。甚至会在 Agent 多次调用工具后自己“脑补”一个不存在的工具返回结果。这里需要区分的是幻觉不完全是“胡说八道”更多时候是模型在“流畅性优先”和“真实性优先”之间选择了前者。2.2 幻觉产生的核心原因从技术角度看幻觉产生有以下几个原因。第一个原因是模型本质是概率预测器。大模型的核心任务是预测“下一个 token 是什么”它并不具备真正的事实校验能力。当训练数据中某个知识点出现频率高时模型能准确重复当知识点稀有或被多种相互矛盾的信息覆盖时模型就会自行“推理”而这个推理过程没有事实锚点。第二个原因是上下文冲突。当你给模型输入一段上下文其中包含 A 信息但模型训练时学到的知识更倾向于 B模型可能会选择训练知识而忽略你提供的上下文。这也是为什么某些场景下需要反复强调“请只根据上文内容回答”。第三个原因是数据截止日期。所有大模型训练数据都有截止日期截止日期之后发生的事件、发布的新版本库、新接口模型根本没有见过。让它回答这些问题它只能靠猜测补全而猜测的结果往往是“看起来像那么回事”。第四个原因是 Agent 任务中的错误累积。在多轮工具调用中如果第一轮模型的判断就错了后面的所有步骤都可能在错误基础上继续生成最终结果偏离得越来越远。2.3 如何识别和验证 AI 输出工程中不能只靠“人工看”来识别幻觉尤其是处理大量文本时。更可落地的思路是建立验证机制。常用的验证方式包括事实性验证让 AI 输出内容附带引用来源再由程序验证来源是否真实存在。逻辑性验证通过规则或第二个模型对结果进行一致性检查。程序化验证AI 生成的代码必须跑测试用例AI 生成的 SQL 必须在测试库执行AI 生成的 JSON 必须通过 schema 校验。工具结果优先在 Agent 场景中AI 的“记忆”不可靠工具返回的结果才可信。当模型描述的工具结果与真实工具结果不一致时应以真实工具结果为准。理解了幻觉机制后接下来我们用代码构建一个轻量级评测工具量化评估一个模型的真实能力。3. 实战搭建一个轻量级 AI 能力评测工具3.1 评测需求与方案设计在很多团队中选择哪个大模型、哪个版本往往靠“拍脑袋”或看几个 demo 决定。这很容易出问题因为 demo 通常只展示模型最擅长的场景而业务实际场景千差万别。更理性的做法是准备一组与业务场景高度相关的评测题集让候选模型依次回答再统计正确率、格式合规率、失败率等指标。这就是大模型评测的基本思路。本文我们设计一个轻量级评测工具包含四类任务数学计算验证基础算术能力。代码生成生成指定函数的代码。逻辑推理回答简单的逻辑问题。事实问答回答需要精确知识的问题。工具采用 Python 编写通过 HTTP 接口调用任意兼容 OpenAI 格式的大模型服务既可以用 OpenAI 官方 API也可以用本地部署的模型如 vLLM、Ollama 启动的服务。3.2 评测集的准备评测集使用 JSON 格式存储每个样本包含任务类型、问题和参考答案。[ { task: math, question: 一个长方形的长是 12.5 米宽是 8.2 米面积是多少平方米, reference: 102.5 }, { task: code, question: 写一个 Python 函数输入一个字符串列表返回按字符串长度升序排序后的新列表。, reference: sorted(input_list, keylen) }, { task: logic, question: 如果所有的 A 都是 B所有的 B 都是 C那么以下哪个一定正确1. 所有 C 都是 A 2. 所有 A 都是 C 3. 有些 C 不是 B, reference: 2 }, { task: fact, question: Python 3.11 中新增的用于捕获异常组的内置语法是什么, reference: except* } ]评测集文件命名为eval_set.json和评测脚本放在同一目录。3.3 评测脚本实现下面实现一个评测脚本evaluate_llm.py。# 文件路径evaluate_llm.py import json import re import sys import time import requests class LLMEvaluator: def __init__(self, api_url, api_key, model, temperature0.0): self.api_url api_url self.api_key api_key self.model model self.temperature temperature def chat(self, messages, max_tokens512): headers { Content-Type: application/json, Authorization: fBearer {self.api_key} } payload { model: self.model, messages: messages, temperature: self.temperature, max_tokens: max_tokens } resp requests.post( f{self.api_url}/chat/completions, jsonpayload, headersheaders, timeout60 ) resp.raise_for_status() data resp.json() return data[choices][0][message][content].strip() def single_eval(self, item): task item[task] question item[question] reference item[reference] prompt self._build_prompt(task, question) try: answer self.chat([{role: user, content: prompt}]) except Exception as exc: return { task: task, question: question, reference: reference, output: fERROR: {exc}, pass: False } passed self._check(task, answer, reference) return { task: task, question: question, reference: reference, output: answer, pass: passed } def _build_prompt(self, task, question): if task math: return f请计算下面数学题的答案只输出最终数字不要输出过程。\n{question} if task code: return f请生成解决以下问题的 Python 代码直接输出完整代码不要额外解释。\n{question} if task logic: return f请回答以下逻辑题只输出选项编号。\n{question} if task fact: return f请回答以下技术问题要求准确如果不确定就说不知道。\n{question} return question def _check(self, task, answer, reference): answer_clean answer.strip().lower() reference_clean reference.strip().lower() if task code: return sorted( in answer_clean and keylen in answer_clean if task math: return reference_clean in answer_clean if task logic: return reference_clean in answer_clean if task fact: return reference_clean in answer_clean return False def run(self, eval_data): results [] for item in eval_data: result self.single_eval(item) results.append(result) status PASS if result[pass] else FAIL print(f[{status}] [{result[task]}] {result[question][:40]}) time.sleep(0.5) return results def load_eval_data(path): with open(path, r, encodingutf-8) as f: return json.load(f) def report(results): total len(results) passed sum(1 for r in results if r[pass]) accuracy passed / total if total else 0 print(\n 评测结果汇总 ) print(f总样本数: {total}) print(f通过数: {passed}) print(f正确率: {accuracy:.2%}) for task in [math, code, logic, fact]: task_results [r for r in results if r[task] task] if not task_results: continue task_passed sum(1 for r in task_results if r[pass]) print(f{task}: {task_passed}/{len(task_results)} ({task_passed / len(task_results):.2%})) with open(eval_result.json, w, encodingutf-8) as f: json.dump(results, f, ensure_asciiFalse, indent2) if __name__ __main__: api_url sys.argv[1] if len(sys.argv) 1 else http://localhost:8000/v1 api_key sys.argv[2] if len(sys.argv) 2 else EMPTY model sys.argv[3] if len(sys.argv) 3 else qwen2.5-7b-instruct evaluator LLMEvaluator(api_urlapi_url, api_keyapi_key, modelmodel) data load_eval_data(eval_set.json) results evaluator.run(data) report(results)这个脚本的_check方法写得比较简单实际项目中可以用更精确的匹配规则也可以让另一个更强大的模型做裁判判断当前答案是否通过。这里的重点是先跑通评测链路。3.4 运行与结果分析假设你本地用 vLLM 部署了一个模型服务地址为http://localhost:8000/v1则运行命令如下python evaluate_llm.py http://localhost:8000/v1 EMPTY qwen2.5-7b-instruct如果只是测试 OpenAI 官方模型python evaluate_llm.py https://api.openai.com/v1 sk-你的密钥 gpt-4o-mini运行结束后会看到每个样本的 PASS/FAIL 状态最后汇总整体正确率并生成eval_result.json结果文件。需要注意的是这个工具只能作为横向对比的参考不能代表模型在真实业务场景中的表现。真实业务评测还需要加入业务专属数据、错误样本、边界输入等并且要持续更新。4. AI 编程实践让大模型写代码的正确姿势4.1 AI 编程工具能做什么不能做什么AI 编程是目前最热门的应用方向之一像 Cursor、Copilot、通义灵码等工具确实能提升开发效率。但我们要清楚边界。AI 编程擅长的是生成模板代码、Boilerplate。实现数据结构与算法题。编写正则表达式、SQL 查询。快速完成 API 调用示例。代码翻译从 Python 转 Java 等。AI 编程不擅长的是修改大型项目中的复杂业务逻辑。理解项目里隐式的业务约束。保证生成代码没有安全漏洞。正确处理版本兼容和依赖冲突。最典型的例子是你让 AI 生成一段读取 Excel 并写入数据库的代码它通常能写得“像模像样”。但这段代码在真实项目里运行时可能因为缺少事务处理、没有处理空行、数据库字段长度不一致等原因直接报错。问题不在于 AI 不会写而在于它不理解你的真实环境。4.2 让 AI 生成高质量代码的 Prompt 技巧同样是让 AI 写代码Prompt 的详细程度直接影响结果质量。你可以对比下面两种写法。低质量写法写一个Python爬虫高质量写法写一个 Python 爬虫要求如下 1. 使用 requests 和 BeautifulSoup 库目标网站为 https://example.com 2. 抓取页面中所有 class 为 title 的 a 标签的 href 和文本 3. 输出结果为 JSON 列表 4. 需要设置 User-Agent 和 3 秒超时 5. 对每个请求做异常捕获失败时打印错误并跳过 6. 不要使用 selenium不要使用多线程高质量 Prompt 的关键是给足约束条件。编写 Prompt 时建议包含以下要素使用的语言和第三方库。输入输出的数据格式。异常处理要求。禁止使用的方案。代码风格要求。运行环境版本信息。4.3 代码审查清单与案例AI 生成的代码在合入项目前建议逐项检查以下几点检查项说明依赖导入是否正确AI 经常会写不存在的包或版本变量是否被正确定义漏初始化、命名冲突边界条件是否处理空列表、空字符串、None异常是否充分捕获网络请求、文件读写、数据库操作安全性SQL 注入、路径穿越、敏感信息硬编码性能是否有多余循环、重复数据库查询可读性是否有难以理解的命名和逻辑看一个真实案例。AI 生成的代码如下# AI 生成的代码片段 import os import sqlite3 def save_user(name, email): conn sqlite3.connect(users.db) cur conn.cursor() cur.execute(fINSERT INTO users (name, email) VALUES ({name}, {email})) conn.commit() conn.close()这段代码能运行但存在两个明显问题一是使用了 f-string 拼接 SQL存在 SQL 注入风险二是没有使用 with 语句管理连接异常时连接可能不会关闭。修正后的代码# 修正后的代码 import sqlite3 def save_user(name, email): conn sqlite3.connect(users.db) try: with conn: conn.execute( INSERT INTO users (name, email) VALUES (?, ?), (name, email) ) finally: conn.close()这个例子说明AI 代码的“正确性”是浅层的正确性深层的安全、健壮性需要开发者把关。4.4 AI 生成代码的落地流程在实际项目中我推荐下面的 AI 辅助开发流程把复杂需求拆解成多个小函数。对每个小函数编写清晰的 Prompt。AI 生成代码后先用静态检查工具扫描。编写单元测试覆盖正常输入和边界输入。代码评审人重点检查安全性和业务逻辑。合入前跑完整测试集。这个流程的核心是AI 负责生成人负责验收。只有把验收环节做实AI 才能成为加速器而不是事故源。5. AI Agent 开发中的坑点与排查思路5.1 Agent 结构拆解AI Agent 是当前 AI 工程实践中最复杂也最容易出问题的一类应用。一个典型 Agent 通常包含四个部分大模型LLM负责理解任务、规划步骤、生成回复。工具层Tools比如搜索、计算器、数据库查询、HTTP 请求。记忆模块Memory保存对话历史和中间状态。执行流程Orchestration控制 Agent 循环执行。从工程角度看Agent 的稳定性比普通对话应用差很多因为每一步都可能出错且错误会沿着链路传播。5.2 常见失败模式下面列举几个最常见的 Agent 失败模式。模式一工具调用参数错误模型生成了工具调用但参数值不对。比如模型要查询用户订单却把用户 ID 传成了订单号。这种错误通常要靠工具层的参数校验来拦截。模式二上下文过长导致信息丢失Agent 多轮交互后历史消息越来越长。超出模型上下文窗口后早期关键信息会被截断或压缩模型可能忘记用户最初的需求。解决方法是做上下文裁剪或摘要。模式三模型虚构工具返回结果这是最隐蔽的一类问题。模型可能没有收到工具返回结果却“脑补”了一个合理的结果继续往下走。避免方法是在 Agent 框架层面强制要求只有真实的工具返回消息才能进入下一轮。模式四循环不终止模型一直在“思考-调用工具-再思考”之间循环直到触发最大步数限制。原因是模型没有足够的信息判断任务已经完成。解决办法是设置最大步数并给模型增加“任务完成”的判定信号。5.3 调试 Agent 的日志设计排查 Agent 问题不能只看最终输出必须能看到完整的思考轨迹。我建议在 Agent 中加入结构化日志记录每一步的输入和输出。下面是一个最小 Agent 示例包含基础日志功能。# 文件路径simple_agent.py import json import logging logging.basicConfig(levellogging.INFO, format%(asctime)s [%(levelname)s] %(message)s) logger logging.getLogger(__name__) class SimpleAgent: def __init__(self, llm_func, tool_funcs, max_steps5): self.llm_func llm_func self.tool_funcs tool_funcs self.max_steps max_steps self.history [] def run(self, user_message): self.history.append({role: user, content: user_message}) for step in range(self.max_steps): logger.info(Step %d: 调用大模型生成下一动作, step) response self.llm_func(self.history) logger.info(模型返回: %s, json.dumps(response, ensure_asciiFalse)) if response.get(type) final: logger.info(任务完成最终答案是: %s, response.get(content)) return response.get(content) if response.get(type) tool_call: tool_name response.get(tool_name) tool_args response.get(tool_args, {}) logger.info(调用工具 %s, 参数: %s, tool_name, tool_args) if tool_name not in self.tool_funcs: logger.error(工具 %s 不存在, tool_name) return ERROR: 未知工具 tool_result self.tool_funcs[tool_name](**tool_args) logger.info(工具返回: %s, tool_result) self.history.append({ role: tool, content: json.dumps(tool_result, ensure_asciiFalse) }) continue logger.warning(模型返回了无法识别的动作类型: %s, response.get(type)) return ERROR: 无法识别的动作 logger.error(超过最大步数 %d任务未完成, self.max_steps) return ERROR: 超过最大步数这个示例的核心是每一步都记录日志工具返回结果和大模型生成内容分开存储。这样当 Agent 出错时你可以通过日志精确定位是哪一步、哪一个工具出了问题。5.4 提升 Agent 稳定性的手段从工程角度提升 Agent 稳定性可以从下面几个方向入手工具参数校验在工具函数入口做类型检查和枚举校验。结果缓存对相同参数的工具调用做缓存避免重复调用和不确定输出。重试机制大模型 API 偶发超时时增加指数退避重试。人机确认涉及删除、修改、付款等高风险操作时增加人工确认环节。过程可视化把 Agent 当前步骤展示给用户让用户能感知进度。这些手段不一定都要上但至少要把“参数校验”和“人机确认”纳入设计。6. 常见问题与排查思路速查表下面整理一份 AI 应用开发中常见问题速查表方便开发时对照排查。问题现象常见原因排查思路解决建议模型回答与事实不符模型幻觉、知识截止日期检查上下文是否提供了足够信息增加检索增强RAG强制引用来源同一问题多次回答不同温度参数过高检查 temperature 设置事实性任务设为 0创意任务可提高AI 生成的代码无法运行依赖版本错误、API 拼写错误先静态检查、立即跑测试建立代码验证流水线Agent 反复调用工具不结束缺少完成条件、上下文信息不足查看日志中每一步模型输出设置最大步数、增加完成判断指令上下文太长导致效果变差超出窗口、早期信息丢失检查消息 token 数做历史摘要、滑动窗口裁剪工具返回结果没有被模型使用提示词没有强调工具结果优先级检查工具结果是否注入正确位置使用明确的 system 指令约束模型响应格式不稳定没有指定输出格式检查 Prompt 中格式要求使用 JSON Schema 或 few-shot 示例API 调用频繁超时服务端负载高、网络问题查看服务端日志和监控增加超时重试、限流降级本地部署模型显存不足模型参数量太大查看显存占用换小模型、量化、增加批处理限制排查问题时建议顺序是先看日志再复现再改 Prompt最后改代码。不要一上来就换模型那样排查效率很低。7. AI 工程化落地的最佳实践7.1 数据与提示词管理Prompt 不只是“一段文字”它和代码一样需要版本管理。推荐做法所有 Prompt 放在独立目录用 Git 管理。Prompt 模板与业务代码分离方便修改。每次修改 Prompt记录变更原因。对核心 Prompt 做回归评测避免“修好一个场景、弄坏另一个场景”。project/ ├── prompts/ │ ├── summarize_v1.txt │ ├── summarize_v2.txt │ └── agent_system_v1.md ├── eval/ │ ├── eval_set.json │ └── evaluate_llm.py ├── src/ │ └── app.py └── logs/7.2 评测回归机制AI 应用上线后评测集要持续扩充。每次模型升级、Prompt 修改、Agent 流程调整都要跑一遍回归评测。扩充实测集时可以关注线上用户高频问题。之前失败的 case。边界输入空值、超长文本、特殊字符。安全相关输入提示注入、非法指令。7.3 降级与兜底策略大模型不是 7×24 小时稳定运行的 SLA 组件业务系统必须有降级方案。几种常见的兜底策略大模型超时或不可用时返回预设的兜底话术。对关键操作增加规则引擎校验不通过时拒绝执行。对于 Agent 高风险动作要求人工确认后才执行。对用户请求做敏感信息检测命中敏感内容时不发给大模型。7.4 合规、安全与隐私这一部分在工程落地中不能忽视。需要注意几点涉及用户隐私数据时先做脱敏再调用大模型。对话日志要脱敏存储且控制访问权限。不要直接把数据库连接串、API Key 写进 Prompt。对大模型输出内容做内容安全过滤。在合规要求高的场景优先选择私有化部署方案。私有化部署时要关注模型许可证、训练数据来源、部署环境的合规要求。这些因素会影响你能否合法地将模型用于商业场景。7.5 性能与成本控制大模型 API 的成本通常按 token 计算Agent 应用调用频繁时成本会快速上升。建议做以下优化使用模型路由简单请求用小模型复杂请求用大模型。减少不必要的历史消息每条消息都占 token精简后可降低成本。对工具返回结果做截断或摘要避免长文本反复传入。对可缓存的响应做 KV Cache 或结果缓存。考虑使用量化模型进行本地部署降低单次调用成本。8. 总结与“不那么全能的 AI”协作的正确方式回到文章开头的问题为什么说 AI 是“not so competent AI overlords”因为大模型确实在很多任务上表现惊艳但它并不具备可靠的事实校验能力、也不理解真实世界中的业务约束。它的强大是“生成能力”的强大而不是“保证正确”的强大。在做 AI 应用时我们需要做的不是崇拜或否定而是用工程手段补齐它的短板。具体来说记住这几条第一不要直接信任输出要加验证环节。代码就跑测试SQL 就在测试库执行事实性答案就查来源。第二用评测数据说话。给候选模型建立评测集量化对比后再决定用哪个模型、哪个 Prompt。第三Agent 要留日志、加约束、设置上限。每一步都可以追溯才不会变成黑盒灾难。第四设计降级方案。AI 不可用时系统还能以可接受的方式运行。如果你正在做 AI 应用落地建议先从一个很小的功能开始把评测、日志、兜底这套基础设施搭好再逐步扩大 AI 的使用范围。AI 的边界与可靠性不是靠更强大的模型自动解决的而是靠工程实践一点点打磨出来的。
返回列表