在 AI 热潮里,我们经常听到“大模型正在取代开发者”“AI Agent 即将接管一切”的说法。但真正把手头的业务接到大模型上之后,很多人会发现:AI 并没有想象中那么“全能”——它会一本正经地编造不存在的 API,会在代码审查时漏掉明显的安全漏洞,会在上下文稍微变长之后忘记最初的指令,甚至会在本地部署时把 GPU 显存吃穿。这篇文章就围绕 “Not so competent AI overlords”(并不那么能干的 AI 霸主)这个主题,聊聊大模型的能力边界、幻觉问题、编码助手的“伪正确”,以及如何用工程手段把 AI 驯服成靠谱的生产工具。文章会包含完整的项目实战、本地部署资源评估、常见问题排查和工程化最佳实践,适合正在做 AI 应用开发、AI Agent 落地或本地模型部署的开发者。
1. AI“霸主”迷思:为什么大模型看起来很强,落地却很脆弱
1.1 什么是“Not so competent AI overlords”
“Not so competent AI overlords”这个说法,其实是对“AI 即将统治一切”这种论调的一种冷静回应。它想表达的是:大模型在单点任务上确实很强,比如文本总结、代码补全、自然语言转 SQL;但只要把它放到真实业务系统中,它就会暴露出各种不靠谱的地方——会撒谎、会遗忘、会过度自信、会重复劳动,而且很难被传统测试手段覆盖。
打个比方,大模型像是一个知识面极广但是行动力毛躁的实习生。你问它一个概念,它能给出比大多数员工都完整的回答;但如果你让它独立负责一条业务线,它会经常因为“记错接口”“擅自发挥”“忽略边界条件”而把事情搞砸。我们需要做的,不是期望 AI 变成全知全能的霸主,而是把它当成一个需要严格约束、校验、审计的“高智商组件”来设计系统。
1.2 为什么会高估 AI 的能力
高估 AI 能力的原因,大致可以归结为三点。
第一,演示效果和真实场景之间存在巨大差距。大多数 AI 产品的宣传视频里,模型处理的都是精心设计的 prompt,背景知识完整、问题明确、预期答案唯一。但真实业务中,输入数据可能是脏的、需求可能是模糊的、多个系统之间的状态可能是矛盾的,这些都会让模型崩溃。
第二,语言流畅度会掩盖逻辑错误。大模型生成的文字往往语法通顺、结构完整,这让非技术背景的人很难判断内容是否真的正确。即便对一个经验丰富的程序员来说,一段 AI 生成的代码能通过编译,也不代表它没有并发问题或安全漏洞。
第三,人们容易把“知识面广”等同于“判断力强”。大模型训练时见过大量资料,所以它能“说出”很多东西,但它并不真正理解这些知识之间的因果关联。当需要对不确定信息做推理、对风险做权衡时,模型的表现会明显下降。
1.3 这篇教程的边界与收益
这篇文章不是讨论“AI 是否有意识”“AI 会不会取代人类”这类形而上的问题,而是站在工程落地的视角,关注下面几个具体问题:
- 大模型的幻觉是怎么产生的,如何用系统设计来缓解。
- AI 编程助手生成的代码为什么“看起来对”但“用起来错”,以及如何审查。
- 如何构建一个带输出校验和人工审核的 AI 辅助工具,让 AI 真正可控。
- 本地部署大模型需要多少资源,应该怎么评估选型。
- 生产环境中,提示词工程、输出校验、可观测性、灰度发布怎么做。
读完这篇文章,你应该能对大模型应用产生一个更理性的判断:AI 是一个很强但并不可靠的工具,工程化的目标不是让 AI 代替人做决策,而是让 AI 的每一次输出都经过校验、约束和审计。
2. AI 幻觉:一本正经地胡说八道
2.1 什么是 AI 幻觉
AI 幻觉(Hallucination)指的是大模型生成的内容与事实不符、与用户指令相悖、或与自身已有的上下文矛盾,但模型在表达时依然非常自信。换句话说,模型不是在承认“我不知道”,而是在一本正经地生成一段看起来合理但实际错误的内容。
举几个典型场景:
- 你问“某个 Python 库有没有
get_data_async方法”,模型回答“有,它的参数是timeout和retry”,但实际上这个库根本没有这个方法。 - 你让模型根据一段日志总结线上故障原因,模型会把“连接超时”脑补成“数据库死锁”,因为它看到日志里有
lock和timeout字样。 - 你让模型生成一个正则表达式,模型给出一个能够通过测试用例、但在真实数据上会漏匹配的版本。
幻觉不是偶发 bug,而是大模型概率生成机制下的固有属性。只要模型在生成下一个 token,就存在偏离事实的可能,只是概率高低不同。
2.2 幻觉产生的根本原因
从技术角度看,幻觉主要来自三个层面。
一是训练目标决定了模型“编造”是内生的。大模型本质是一个超大规模的条件概率模型,目标是预测下一个 token 的概率分布。它没有内置的“事实数据库”,只有训练时学到的统计关联。当某个知识点在训练数据中出现次数较少、或者出现形式互相矛盾时,模型就会用概率最高但未必正确的表达来填补。
二是训练数据的噪声与过时。互联网语料本身包含大量错误信息、营销内容、过期文档。模型把这些内容学进去之后,就会在推理时输出类似的错误。这也是为什么模型的知识截止日期越久,回答过时问题的概率越高。
三是解码策略会加剧幻觉。在实际使用时,如果 temperature 设置过高、top_p 设置过大,模型会更倾向于选择低概率但“更有创意”的 token,这直接增加了幻觉率。
2.3 缓解幻觉的工程手段
幻觉无法被彻底消除,但可以通过系统设计大幅降低影响。常用的手段包括:
| 手段 | 做法 | 适用场景 |
|---|---|---|
| RAG 检索增强 | 先从向量数据库中检索相关资料,再拼接进 prompt 让模型基于资料回答 | 企业知识库问答、文档辅助 |
| 工具调用约束 | 让模型调用真实 API 获取数据,而不是凭记忆回答 | 天气、库存、订单查询 |
| 输出校验 | 对模型输出的 JSON、SQL、代码进行语法或规则校验 | 结构化输出场景 |
| 自我一致性采样 | 同一个问题生成多次,取最一致的结果 | 高风险推理场景 |
| 人工审核 | 加入人工审批环节,模型输出只作为草稿 | 生产变更、对外文案 |
这五种手段不是互斥的,实际生产系统往往是组合使用。例如在客服工单摘要场景中,先用 RAG 检索业务知识,再让模型生成摘要,最后接一个关键词校验规则,不满足规则的内容自动转人工。
2.4 一个简单的幻觉自检示例
下面这个示例展示如何让模型在回答的同时给出“置信度自评”,并通过简单阈值把低置信度结果转入人工处理。需要说明的是,大模型的置信度自评并不完全可靠,但作为一个前置过滤手段仍然有价值。
# 文件路径:hallucination_check.py from openai import OpenAI client = OpenAI(api_key="your-api-key") def ask_with_confidence(question: str) -> dict: SYSTEM_PROMPT = """你是一个严谨的问答助手。 如果你对某个问题不确定,请在回答中明确写出“不确定”, 并在 confidence 字段中给出 0 到 1 的分数。 只有你确定答案来自可靠知识时,confidence 才允许高于 0.8。 """ response = client.chat.completions.create( model="gpt-4o-mini", temperature=0.2, messages=[ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": question}, ], response_format={"type": "json_object"}, ) content = response.choices[0].message.content return json.loads(content) if __name__ == "__main__": question = "Python 3.12 中哪个内置函数可以获取对象的哈希值?" result = ask_with_confidence(question) print("模型回答:", result.get("answer")) print("置信度:", result.get("confidence")) if float(result.get("confidence", 0)) < 0.7: print(">>> 置信度过低,建议转人工处理")这个例子的核心思路是:不要直接信任模型的“答案”,而是通过 prompt 约束模型给出答案的同时暴露不确定性,再用代码判断是否进入自动流程还是人工流程。实际工程中,还可以把置信度评分和规则校验、RAG 检索得分综合起来做决策。
3. AI 编码助手的“伪正确”:代码能跑不代表可靠
3.1 AI 编程工具为什么会生成不存在的 API
以 Cursor、GitHub Copilot 为代表的 AI 编程助手已经非常普及,很多开发者的日常编码效率确实明显提升。但这类工具有一个非常典型的坑:它会生成“看起来存在但实际上不存在”的 API。
原因在于,大模型是基于训练语料中的代码片段做概率生成的。如果某个方法在训练数据中反复出现,模型就会在预测时强烈倾向于输出它,甚至不管当前项目使用的版本是否包含该方法。比如你用的是 Spring Boot 2.7,模型可能基于 Spring Boot 3.x 的语法生成配置,导致启动直接报错。
下面是一个很常见的错误示例:模型为 Java 项目生成一个并不存在的工具方法调用。
// 错误示例:FileUtils 的 getExtension 方法在部分版本中并不存在 // 这段代码看起来合理,但编译时会报错 import org.apache.commons.io.FileUtils; public class FileNameHelper { public static String getFileExtension(String fileName) { return FileUtils.getExtension(fileName); } }很多人第一眼看到这段代码会觉得没问题,因为getExtension这个命名非常自然。但如果项目引入的 commons-io 版本较老,这个方法不一定可用。正确的做法是先查官方文档或反编译 jar 包确认 API 是否存在,而不是直接复制。
3.2 更隐蔽的风险:代码能跑,但逻辑有漏洞
比起“编译失败”这种显性错误,更危险的是 AI 生成的代码能正常运行,但存在并发问题、安全漏洞或边界条件缺陷。
举例来说,你让 AI 写一个“用户上传文件后保存并返回 URL”的接口,它可能会生成下面这种代码:
// 文件路径:src/main/java/com/example/demo/controller/FileController.java @PostMapping("/upload") public String upload(@RequestParam("file") MultipartFile file) { String originalFilename = file.getOriginalFilename(); String savedPath = "/data/uploads/" + originalFilename; file.transferTo(new File(savedPath)); return "https://cdn.example.com/" + originalFilename; }这段代码在功能上“能用”,但至少存在三个问题:
- 路径穿越漏洞:
originalFilename可能包含../,攻击者可以把文件写到任意目录。 - 文件名冲突:不同用户上传同名文件时会被覆盖。
- 文件类型与大小未校验:恶意用户可能上传可执行脚本或超大文件。
这些漏洞不是语法错误,编译器和基础测试都发现不了。如果你把 AI 生成的代码当作“审查过的代码”直接合入主干,风险非常大。
3.3 正确使用 AI 编程助手的姿势
总结下来,AI 编程助手适合做“提效工具”,而不是“代码作者”。推荐的落地姿势如下:
- 任务拆分后再生成。把一个大需求拆成多个小函数,让 AI 逐个生成,比一次性生成一个完整模块更容易控制质量。
- 必须要求测试覆盖。让 AI 同时生成单元测试,并手动补充边界测试用例。
- 代码审查不可省略。AI 生成的代码必须走人工 review,重点关注安全、并发、事务、权限控制。
- 用静态分析工具兜底。使用 SonarQube、CodeQL、SpotBugs 等工具扫描 AI 生成的代码,用规则引擎弥补人工审查的盲区。
- 依赖版本锁定。AI 经常默认使用最新版本的依赖 API,实际项目应该以 pom.xml 或 requirements.txt 中锁定的版本为准。
4. 实战:构建一个带校验与人工审核的 AI 辅助工具
4.1 需求背景
假设我们要做一个内部工单系统,希望用大模型自动提取工单中的关键信息,例如“问题类型”“影响范围”“紧急程度”“建议处理人”。这些信息会直接进入下游流程,所以不能盲目信任模型的输出。我们设计一个带输出校验和人工审核的流程:
- 用户提交工单文本。
- 调用大模型,提取结构化 JSON。
- 用 Pydantic 校验 JSON 字段是否完整、类型是否正确。
- 用枚举校验字段值是否在允许范围内。
- 审核状态为
pending的记录进入人工审核列表。 - 审核人确认后,才写入正式工单表。
4.2 项目结构
ai-assistant-demo/ ├── requirements.txt ├── main.py ├── schemas.py ├── ai_extract.py ├── audit.py └── README.md4.3 依赖准备
依赖文件如下:
# 文件路径:requirements.txt openai>=1.0.0 pydantic>=2.0.0 fastapi>=0.100.0 uvicorn>=0.23.0使用pip install -r requirements.txt安装依赖。
4.4 定义数据结构
用 Pydantic 定义模型输出结构和校验规则。对于枚举字段,这里使用Literal类型约束具体取值。
# 文件路径:schemas.py from typing import Literal from pydantic import BaseModel, Field class TicketInfo(BaseModel): problem_type: Literal["crash", "performance", "network", "security", "other"] impact_scope: Literal["single_user", "partial", "global"] urgency: Literal["low", "medium", "high", "critical"] suggested_owner: str = Field(description="建议处理人,必须来自运维团队名单") summary: str = Field(description="问题摘要,不超过 50 个字")这里的关键点在于:Literal类型约束输出字段只能取指定枚举值,不符合时 Pydantic 会直接抛出校验异常,从代码层面拦截模型的“自由发挥”。
4.5 调用大模型并做校验
# 文件路径:ai_extract.py import json from openai import OpenAI from pydantic import ValidationError from schemas import TicketInfo client = OpenAI(api_key="your-api-key") EXTRACTION_PROMPT = """你是一个工单信息提取助手。 请从用户提供的工单文本中提取以下字段: - problem_type:取值只能是 crash、performance、network、security、other 之一 - impact_scope:取值只能是 single_user、partial、global 之一 - urgency:取值只能是 low、medium、high、critical 之一 - suggested_owner:建议处理人,必须是运维团队名单中的人 - summary:一句话摘要,不超过 50 字 只输出 JSON,不要输出其他内容。""" def extract_ticket_info(text: str) -> TicketInfo: response = client.chat.completions.create( model="gpt-4o-mini", temperature=0.1, messages=[ {"role": "system", "content": EXTRACTION_PROMPT}, {"role": "user", "content": text}, ], response_format={"type": "json_object"}, ) content = response.choices[0].message.content try: data = json.loads(content) ticket = TicketInfo(**data) return ticket except (json.JSONDecodeError, ValidationError) as e: # 到这里说明模型输出不合法,记录日志后走人工处理 raise ValueError(f"模型输出校验失败: {e}") from e这里的response_format只是让模型尽可能输出 JSON,并不能保证 JSON 内容一定合法。真正兜底的是 Pydantic 校验,当problem_type输出为bug而不是crash时,校验就会失败。
4.6 人工审核流程
生产环境里,模型输出校验失败或置信度偏低的内容不能直接丢弃,而应该进入人工审核队列。
# 文件路径:audit.py from dataclasses import dataclass, field from datetime import datetime @dataclass class AuditRecord: raw_text: str model_output: dict status: str = "pending" created_at: datetime = field(default_factory=datetime.now) reviewed_by: str | None = None final_decision: str | None = None class AuditQueue: def __init__(self): self._records: list[AuditRecord] = [] def add(self, record: AuditRecord): self._records.append(record) def get_pending(self): return [r for r in self._records if r.status == "pending"] def review(self, record_id: int, reviewer: str, approved: bool): record = self._records[record_id] record.status = "approved" if approved else "rejected" record.reviewed_by = reviewer record.final_decision = "approved" if approved else "rejected"在生产系统中,这个审核队列可以使用 PostgreSQL 表来存储,字段包括raw_text、model_output_json、status、reviewer、review_time、final_decision。关键点是必须有完整的审计日志,后续可以反查模型在哪些场景下产生了错误输出。
4.7 运行与验证
启动一个 FastAPI 服务来验证整个流程:
# 文件路径:main.py from fastapi import FastAPI, HTTPException from pydantic import BaseModel from ai_extract import extract_ticket_info from audit import AuditQueue, AuditRecord app = FastAPI() audit_queue = AuditQueue() class TicketRequest(BaseModel): text: str class TicketResponse(BaseModel): ticket_id: int status: str @app.post("/api/v1/tickets", response_model=TicketResponse) def create_ticket(request: TicketRequest): try: ticket = extract_ticket_info(request.text) except ValueError: # 校验失败时进入人工审核队列 record = AuditRecord( raw_text=request.text, model_output={"error": "validation_failed"}, ) audit_queue.add(record) return TicketResponse(ticket_id=id(record), status="manual_review") record = AuditRecord( raw_text=request.text, model_output=ticket.model_dump(), ) audit_queue.add(record) return TicketResponse(ticket_id=id(record), status="auto_extracted") if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)使用下面的命令启动:
uvicorn main:app --reload --port 8000然后用 curl 测试:
curl -X POST http://localhost:8000/api/v1/tickets \ -H "Content-Type: application/json" \ -d '{"text": "用户张三反馈登录页面报错,接口响应时间超过3秒,当前所有用户都受影响,需要紧急处理"}'如果模型输出正常,会返回status: auto_extracted;如果模型输出了类似urgent这样的未定义枚举值,就会返回status: manual_review。这背后体现的设计思路是:AI 的输出只是“候选结果”,系统必须用自己的规则来确认是否采信。
4.8 扩展方向
这个示例可以继续扩展的点包括:
- 接入真实的消息队列(如 Kafka、RabbitMQ),让审核任务异步流转。
- 把模型输出、校验结果、审核结果埋点到监控系统,统计“自动通过率”“模型失败趋势”。
- 对校验失败的数据做周期性抽样,用来做模型微调或 prompt 迭代的数据集。
5. 本地部署 AI 模型的资源账与工程代价
5.1 为什么有人坚持本地部署
在线调用大模型 API 很方便,但很多企业出于数据安全、合规要求、网络隔离等原因,会选择把模型部署在私有化环境。实际场景包括:金融行业的核心业务数据不能出内网、政府项目要求国产化环境、制造企业需要在车间无外网环境下做质检。
本地部署并不便宜,也不是“拿一台 4090 就能跑起来”这么简单。它涉及 GPU 资源、推理框架、并发控制、模型管理、监控告警等一系列工程问题。
5.2 模型选型与资源估算
不同规模的模型对显存和算力的需求差异非常大,下面是常见开源模型的资源档位参考(具体显存占用取决于量化方式和上下文长度,实际部署前请先验证):
| 模型规模 | 常见量化方式 | 建议显存 | 适合场景 |
|---|---|---|---|
| 1B - 3B | 全精度或 int8 | 4GB - 8GB | 文本分类、实体抽取、简单问答 |
| 7B - 8B | int8 或 int4 | 8GB - 16GB | 代码补全、中等难度对话 |
| 13B - 14B | int4 | 16GB - 24GB | 复杂推理、长文本理解 |
| 30B - 70B | int4 | 24GB - 80GB | 代码生成、高难度任务 |
这里需要特别强调:显存只是最低门槛,实际部署还要考虑推理延迟。7B 模型在单张消费级显卡上运行,生成速度可能只有每秒 20 - 40 个 token;如果业务要求支持 50 个并发用户,就需要多卡或部署多副本。
5.3 推理框架与部署方式
目前常见的本地推理方案包括 vLLM、Ollama、LMDeploy、TensorRT-LLM 等。下面以 vLLM 为例,展示代码补全场景的部署命令。
# 安装 vLLM(以 CUDA 版本为准) pip install vllm # 启动 OpenAI 兼容的推理服务 python -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-7B-Instruct \ --tensor-parallel-size 1 \ --max-model-len 8192 \ --gpu-memory-utilization 0.9 \ --port 8001启动之后,可以通过 OpenAI 兼容接口访问:
curl http://localhost:8001/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "Qwen/Qwen2.5-7B-Instruct", "messages": [{"role": "user", "content": "用 Python 写一个快速排序"}], "temperature": 0.2 }'vLLM 的优点是吞吐量高,适合并发请求较多的场景。它的核心思路是 PagedAttention,能够更高效地管理 KV Cache 显存,避免显存碎片化。如果你只是个人学习或小规模测试,可以先从 Ollama 这类部署门槛更低的工具入手。
5.4 本地部署 vs 云端 API 怎么选
这个决策不能只看价格,要从下面几个维度综合评估:
- 数据敏感性:数据是否允许离开自己的网络边界。
- 延迟要求:如果业务要求首 token 延迟低于 200ms,在线 API 的网络开销可能成为瓶颈。
- 成本结构:云端 API 按 token 计费,对波峰波谷明显的业务更友好;本地部署是固定成本,需要长期高利用率才能摊薄。
- 维护复杂度:本地部署需要 GPU 运维、模型版本管理、显存监控和扩容方案,对团队要求更高。
在不涉及敏感数据的前提下,建议开发阶段先使用云端 API 快速验证效果,等到业务形态稳定、调用量足够大之后,再评估本地部署的性价比。
6. 常见问题与排查思路
| 问题现象 | 可能原因 | 解决思路 |
|---|---|---|
| 模型回答与事实不符 | 训练数据过时、检索上下文缺失 | 加入 RAG 检索,提示模型“仅基于提供资料回答” |
| 模型输出 JSON 格式错误 | 模型解码不稳定、response_format 未生效 | 使用 Pydantic/JSON Schema 校验,解析失败时重试或转人工 |
| 模型重复生成相同内容 | temperature 过低、模型陷入局部最优 | 适当调高 temperature 到 0.7,或切换采样策略 |
| 上下文越长,回答质量越差 | 超出模型的注意力有效范围,信息被稀释 | 压缩上下文、提炼摘要、使用滑动窗口 |
| 本地推理速度慢,GPU 利用率低 | 并发数不足、未做连续批处理 | 使用 vLLM 等推理框架,开启 continuous batching |
| 显存不足导致 OOM | 模型太大、上下文太长 | 降低 max-model-len、使用 int4 量化、多卡分片 |
| AI 生成代码编译通过但运行时出现并发问题 | 模型未考虑竞态条件 | 代码审查必须包含并发安全审查,补压力测试 |
| 模型在敏感数据上“乱编” | 没有做输出过滤和权限控制 | 增加输出校验规则,敏感字段强制走人工审核 |
6.1 详细排查:模型上下文被截断怎么办
很多 AI Agent 应用会随着对话轮次增加,出现“早期指令被遗忘”的问题。原因是模型输入有最大长度限制,超出部分会按策略截断。你的 system prompt 可能排在前面,但被截断后模型就看不到约束了。
推荐做法是把最关键的指令放在 system prompt 末尾,或者对历史对话做摘要压缩。每次请求前,检查输入 token 数量,超过阈值时先压缩历史消息,而不是简单截断。
6.2 详细排查:模型输出校验失败率很高怎么办
如果你的系统频繁进入人工审核分支,不要急着换大模型,先检查 prompt 是否足够明确。比如枚举值在 prompt 里只写“other”,但在输出约束里写“必须是 crash、performance、network、security、other 之一”,模型会更稳定。还可以在结构化输出时提供 few-shot 示例,让模型参考示例的输出格式。
如果调整 prompt 后仍不稳定,可以在代码里增加“重试一次”的逻辑:解析失败时,把错误信息拼回 prompt,让模型基于错误信息重新生成。对于重试两次仍失败的请求,直接进入人工审核。
7. 最佳实践与工程建议
7.1 提示词工程:把约束写进系统里
提示词不是随便写一段话,而是系统设计的一部分。推荐在生产 Prompt 中明确以下内容:
- 角色定义:模型扮演什么角色,回答的边界在哪。
- 输出格式:要求输出 JSON 并给出字段说明。
- 取值约束:枚举值必须严格限制,不存在的值不要输出。
- 兜底策略:不确定时应该怎么表达,是输出“不确定”还是调用工具。
一个好的做法是给系统 prompt 维护版本号,每次修改都作为新版本发布,并对比线上效果。不要直接在线上 prompt 里东改一句西改一句,否则出了线上事故很难回溯。
7.2 输出校验:永远不要相信裸输出
无论使用哪个大模型,都建议在模型和业务逻辑之间加一层校验代码。校验内容包括:
- 字段完整性:必填字段是否存在。
- 类型正确性:字符串、数字、布尔值是否匹配。
- 取值合法性:枚举值是否在白名单内。
- 业务规则:例如金额不能为负数、日期不能早于创建时间。
- 敏感信息:输出中是否包含手机号、身份证等敏感数据,命中则拦截。
校验失败时的策略也很重要:不是直接报错,而是进入降级流程,比如重试、转人工、返回默认值。
7.3 人工审核与灰度发布
在关键业务中,AI 的输出应当默认视为“草稿”,经过人工确认后才生效。即使是自动化的 AI Agent,也应该保留人工中断和回滚入口。
灰度发布策略可以这样设计:先让 AI 输出和人工输出同时跑,对比 1 - 2 周的准确率;当自动输出的准确率超过阈值后,再把流量逐步切换到 AI 侧。切换比例建议从 10% 开始,观察线上反馈后再逐步提升。
7.4 可观测性与成本控制
AI 应用的可观测性不只是“看日志”,至少需要记录:
- 每次请求的输入输出 token 数。
- 模型名称和 prompt 版本。
- 输出校验是否通过。
- 校验失败的错误类型。
- 人工审核的通过率。
- 端到端延迟和首 token 延迟。
这些数据不仅用于排障,更是判断“模型是否变差”“prompt 修改是否有效”的核心依据。成本控制方面,可以使用模型路由策略:简单任务用小型模型,复杂任务才调用大型模型,从架构上降低整体调用成本。
8. 结语
回看“Not so competent AI overlords”这个标题,它提醒我们:不要让“AI 无所不能”的叙事遮蔽了工程细节。大模型确实在很多任务上表现惊艳,但它依然是一个概率系统,会幻觉、会过时、会生成有漏洞的代码、会在资源评估不足时拖垮整个服务。真正的 AI 工程能力,体现在能否为模型的每一次输出设计好校验、兜底、审核和回滚机制。希望这篇文章里的排查思路、代码示例和部署经验,能帮你更理性地使用 AI,把它从“不靠谱的天才”改造成“可控的智能助手”。如果文中涉及的技术细节和你实际项目的版本不一致,请以官方文档为准,先做小规模验证再上线。