ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Ken Thompson的信任哲学:AI工程的可验证落地指南

Ken Thompson的信任哲学:AI工程的可验证落地指南 Ken Thompson 这个名字在 AI 时代依然值得反复读。作为 Unix 的共同创造者和图灵奖得主他对工具链、系统安全和复杂性的判断正好可以用来审视今天很多 AI 项目的落地方式。很多人以为这位老派程序员和 AI 没关系但实际上只要你在用 AI 编程工具、部署模型、做 Agent 编排他的“先怀疑、再使用”思路就比大多数模型榜单都更实用。这篇文章不打算复述他的生平而是把他对信任和复杂度的理解迁移到 AI 工程实践里给你一套能照着做的最小验证流程。1. 先从 Ken Thompson 身上提取三件对 AI 有用的事1.1 工具链可信度你永远需要知道模型和框架从哪来Ken Thompson 在经典图灵奖演讲《Reflections on Trusting Trust》里讲过一个很精巧的问题一个编译器即使源码看起来完全正常也可能在编译出来的程序里留下后门。原因不是编译器作者一定使坏而是编译过程本身可以形成自我复制。如果你只检查源码不检查编译器可执行文件你根本发现不了问题。这件事放到今天的大模型场景里几乎是一比一对应。你买来或下载的模型权重真的和作者声称的一样吗训练数据里有没有混入脏数据微调过程有没有被中间人替换如果你用的是第三方 API那问题更复杂你连当前跑的是哪个版本都不知道。模型推理结果如果和预期差很多第一反应往往是“模型能力不行”但真正的风险更可能在模型来源和依赖链路。所以我会建议先做三件小事锁定模型版本和依赖版本不要用 latest 这种标签。保存模型文件的哈希值记录它从哪个地址下载、什么时间下载。如果是 API记录接口版本、请求参数、返回结构变化。这些事情看起来和“效果优化”无关但很多生产事故都出在这里。比如某一次依赖升级后模型生成的结果突然变差某一次模型文件被覆盖后输出格式全部改变。没有可追溯的信息你只能靠猜。1.2 简单优于复杂系统复杂度上升失控点只会增加Thompson 参与设计了 Unix后来也参与设计了 Go 语言。他所在的操作系统和编译器圈子有一个非常强烈的偏好系统要尽量简单、组件边界要清晰。复杂本身不是问题但复杂会带来隐藏的交互而交互一旦失控定位成本会指数级上升。AI 项目最容易犯的错就是一上来搭一个 Agent 系统先用 A 模型做意图识别再把结果喂给 B 模型做摘要然后用 C 模型把摘要转成 JSON最后还要调一个工具去执行。这个链路听起来很厉害但每一步都有不确定性。A 模型的输出偏了B 模型会跟着偏B 模型的摘要没按格式走C 模型就会给出一堆乱代码。更稳妥的做法是先验证每一步。我给团队定的流程是先拿一条干净样本单独测 A 模型能不能稳定做意图识别再单独测 B 模型能不能稳定做摘要最后才考虑串起来。单步成功率如果是 90%两步串联就是 81%三步就是 72%。如果每一步还都有随机性生产环境根本没法保证输出质量。控制复杂度不是技术洁癖而是为了让你出错时知道去哪一行日志找问题。组件越少链条越短问题越好定位。1.3 可复现性没有可复现的实验就没有修复的依据做操作系统和编译器的人对 bug 有个习惯不能复现的 bug不值得修。因为不能复现就说明你不知道触发条件改了也可能改错。AI 任务的天然随机性让复现变得困难但这不能成为放弃复现的借口。我每次用模型做实验都会记录下面这些字段记录项说明为什么重要模型名称和版本比如某个开源模型的 7B 或 13B 版本不同版本能力差异很大随机种子固定 seed 可以降低随机性遇到问题能回到同一起点temperature控制输出随机性太大容易跑偏太小容易重复top_p采样范围和 temperature 配合使用max_tokens输出上限过小会截断过大浪费资源提示词版本Prompt 在仓库里的 commit 编号Prompt 改动会导致输出变化输入样本原始输入尽量保留原文方便复盘输出结果模型生成的完整输出判断问题在模型还是规则耗时和 token 数记录资源消耗评估成本和性能有了这些记录你才能回答那个最关键的问题这次结果和上次不一样到底是因为输入变了、提示词变了还是模型参数变了。2. 把“AI 信任边界”拆成三层再决定怎么接入2.1 输入层先确认输入是不是模型理解的格式很多人拿到模型第一件事就是传一条长文本然后抱怨效果差。但很多时候问题根本不在模型而在输入本身。如果你的输入里有乱码、空字符串、超长截断、特殊符号、编码不一致模型再强也处理不好。尤其是中文场景文件编码很常见是 UTF-8但如果用户上传的是 GBK 文件模型读出来就是一堆乱码。这个问题不解决后面所有分析都没有意义。我一般会先选一条最典型的业务输入做最小样例。注意不是只找一条正常输入而是至少覆盖三类正常输入符合业务流程的标准样例。边界输入接近长度上限、接近格式上限的输入。异常输入空值、缺字段、格式错误的输入。用这三个样例跑通一遍你才会知道模型在干净输入下能做什么在异常输入下会怎么失败。如果单条样例都不稳定就不要考虑批量和自动化。输入层还有一个容易被忽略的点上下文长度。很多模型有窗口限制你把一篇超长文档直接塞进去可能会被自动截断。被截断后模型只能看到后半段结果自然不准。这时候要做的不是换更强模型而是先做切片或抽取。2.2 模型层理解置信度、幻觉和工具限制之间的平衡模型层最让人头疼的不是速度而是输出不够稳定。模型经常用很流畅的语气编造一个不存在的事实这就是所谓的 AI 幻觉。它不只在聊天场景出现在抽取、摘要、分类、代码生成里都会出现。要判断一个任务适不适合直接接线上不能只看一次输出。我建议用同一段输入在同样的参数下跑五遍观察结果差异。如果是抽取任务五次结果里关键字段都不一样说明模型在这个任务上不稳定需要换提示词、换模型或加规则校验。调参的时候记住几个方向temperature 调低输出更保守重复率更高适合分类、抽取、代码生成。temperature 调高输出更有变化适合创意写作不适合需要精确结果的任务。top_p 通常配合 temperature 使用但不一定每个模型都支持。max_tokens 不要设得过小否则结果会被截断而且截断后没有任何报错。具体参数要以你用的模型文档为准我这里给的是通用判断思路。核心是模型没有“默认一定正确”的模式你要做的是让它在业务需要的范围内相对稳定。2.3 输出层校验逻辑必须独立于模型Thompson 的编译器例子给我们一个很重要的原则不要只依赖生产者的自我报告。模型说“我完成了”不代表结果可用。你必须在模型之外建一道独立的校验逻辑。如果是结构化输出比如要求返回 JSON可以在代码里用 JSON Schema 校验字段缺失或类型错误直接判失败。如果是摘要任务可以检查关键实体是否出现在摘要里用规则匹配就能做。如果是代码生成任务必须编译、跑单测、做静态检查不能因为代码看起来能跑就认为成功。校验逻辑要成为任务流程的一部分而不是事后抽查。模型输出一旦校验不通过就触发重试或者进入人工队列。这样能拦住大部分异常结果。我在做批量任务时经常会加一层输出检查把结果按必填字段、长度范围、格式类型拆开逐个校验。只有校验通过的结果才会写入最终文件。这样做看起来多了一步但实际能省下大量检查数据的时间。3. AI 工程实践里的 Thompson 式检查清单3.1 模型选择从可追溯性倒推而不是只比分数选模型时很多人只看基准测试分数很少问一句这个模型能不能查清楚来源训练数据是什么微调过程有没有公开说明如果只做个人学习怎么选都行。但如果是生产系统我建议优先选符合这几个条件的模型模型权重来源清晰有稳定的版本号。文档里写明适用场景和已知限制。社区使用量大坑比较透明。可以私有化部署或至少有稳定的 API 版本。出问题时能快速切换不会被单一供应商绑死。可追溯性意味着你在出问题时有地方去查。如果模型来自一个不透明渠道你连问题都很难描述更别说修复。3.2 提示词和上下文当成代码管理Prompt 是 AI 系统的入口但它经常被当成随意写写的东西。我见过很多项目提示词散落在聊天窗口、本地笔记和代码里改来改去没人知道最终版本是什么。更稳妥的做法是把 Prompt 提交到代码仓库和代码一起做版本管理。每次改动都带上 commit 信息。这样你可以清楚地知道“这个版本为什么效果变好或变差”。提示词在设计时要注意几个点把指令和数据分开用固定的分隔符标记输入内容。固定规则放 system 或前置指令变化内容用模板变量。不要把所有背景知识都塞进上下文只留当前任务需要的信息。控制上下文总长度避免模型因为输入过长而遗漏重点。提示词本质上是一种弱规则。它不像代码那样严格但它同样需要版本管理。没有版本管理的提示词会让模型行为变成一匹脱缰的野马。3.3 日志与观测没有日志AI 问题无法定位AI 系统的日志非常关键。普通程序报错可能就是空指针、参数不对AI 系统的失败形式更隐蔽输出格式不对、内容跑偏、请求超时、token 超限、上游 API 限流。我建议在调用模型的前后都打日志。请求时记录 trace_id、模型版本、输入摘要、参数响应时记录输出摘要、耗时、token 数、状态码。如果发生重试还要记录重试次数和退避时间。生产环境里UI 显示异常时第一件事不是看模型而是查日志。你只有知道自己发出去什么、收到什么才能判断问题是出在模型推理还是出在代码解析还是出在用户输入。没有日志AI 问题只能靠猜而猜是排查里最浪费时间的方式。3.4 失败降级默认输出、重试、人工接管不是每一次模型调用都会成功。网络超时、限流、结果校验失败、生成空内容这些都很常见。所以接口设计时一定要定义失败行为。我会按下面的顺序处理设置最大重试次数比如 2 到 3 次。重试之间加退避比如 1 秒、2 秒、4 秒避免把服务打崩。重试仍然失败时返回一个明确错误码而不是抛一个含糊异常。如果业务允许使用默认值兜底。如果业务不允许默认值进入人工处理队列。重试不是无限重试不然批量任务会越堆越多日志里全是同一个请求的重试记录。要区分哪些错误值得重试哪些不值得。网络超时值得重试输入格式错误不值得重试因为重试一万次也一样。4. 本地部署、AI 编程、Agent 落地时最容易忽略的复杂度问题4.1 本地部署低配置能跑不等于适合生产很多开源模型在低配置机器上也能跑出一个结果但这离“可用”还有很长距离。我看过有人用 16G 内存、6G 显存的机器跑一个大模型生成一小段文本要半分钟演示给别人看还能接受一旦接入业务多个用户同时请求系统直接卡死。判断本地部署能不能上生产不要只看单次生成效果要看几个指标并发为 1 时的响应时间。并发为 10 或 20 时的响应时间。显存峰值和内存峰值。请求失败率。排队时间。建议做一个简单压测用同一个脚本模拟 1、5、20 个并发请求记录成功率和平均耗时。如果 20 并发时失败率已经很高那就说明资源不够要么降并发要么加资源要么换更小的量化模型。量化也是一种降低资源占用的方式但要注意量化后模型会有轻微精度损失。如果业务对输出格式要求很高还是要用原模型先验证一遍。4.2 AI 编程工具生成代码必须经过代码审查像 Cursor 这类 AI 编程工具现在已经成为很多人日常开发的一部分。它能快速补全函数、生成测试、重构代码确实能提高效率。但它生成代码有一个共同问题看起来很合理但经常缺少边界处理。我见过 AI 生成一个文件处理函数正常路径跑得很顺但文件不存在时直接抛出异常也见过 AI 生成 SQL 查询完全没有考虑权限过滤还见过生成的正则表达式能处理标准输入但对特殊字符没有转义。这些问题是模型不擅长思考“失败路径”导致的。用 AI 编程时要建立一个习惯把生成代码当作同事提交的 PR必须走 code review。先跑一遍静态检查和单测再自己读一遍关键逻辑重点看输入校验、错误分支、安全风险。能跑通不代表正确更重要的是它不会在异常时把系统搞挂。4.3 Agent 编排把每一步的输出都当作不可信输入Agent 看起来很聪明但它本质是让模型在多步决策中自主执行。风险在于每一步都可能出错而且错误会累积。在做 Agent 编排时我有几个实操习惯让模型输出结构化 JSON而不是自然语言。对 JSON 里的字段做强校验再决定下一步。不要直接把模型输出拼接到命令、路径、SQL 里。每个工具调用都设置 timeout。关键步骤加人工确认。举个例子如果模型要调用一个工具去读取文件程序要先从模型输出里解析出文件路径然后校验这个路径是否符合预期范围再执行读取。如果直接把模型输出拼进命令你无法预判它会生成什么轻则路径错误重则有安全问题。Agent 系统越是灵活越需要外部约束。模型负责做决策但代码负责守边界。5. 遇到问题时按这个顺序排查5.1 报错或空输出先看输入、路径、权限模型报错时很多人第一反应是“模型是不是不支持这个功能”。但实际排查时我建议先看四个基础项输入文本是否完整编码是否正确。文件路径是否存在是不是带中文或特殊字符。当前进程有没有权限读写目标目录。依赖版本有没有和项目要求冲突。这四个问题占了大部分“模型突然不行”的情况。真要查先把错误栈最后几行读完再手动跑一条最小输入看能不能复现。手动跑不通就不要怀疑模型权重。5.2 卡住或速度慢先看资源占用和日志任务卡在“正在生成”时先看 CPU、GPU、内存是不是已经打满。如果资源占用不高大概率不是在推理而是在等网络、等队列或等锁。这时候再去看服务日志确认请求有没有真正进入模型。日志里如果一直没有新输出说明卡在模型外部。此时不要盲目调并发或加超时先把调用链路找出来。是上游 API 超时是本地模型推理慢是解析输出卡住不同阶段处理方式完全不一样。5.3 输出质量差先区分模型问题还是规则问题有时候模型生成的内容业务上觉得“不行”但代码解析却没报错。这时候要把两个层面分开看。先看规则层JSON 能否解析必填字段是否齐全日期格式是否符合预期如果规则层能通过说明模型输出了符合结构的内容。再看业务层内容是否准确逻辑是否完整是否有幻觉如果业务层不行问题在模型能力或提示词如果规则层直接失败问题在输出格式约束。这两种问题的修复方向完全不同。前者要换模型、调提示词、加示例后者要调整输出解析、加 schema 校验、限制输出格式。5.4 批量任务失败先看文件命名、数据格式和失败重试批量任务不是“能跑几条成功”就算稳定。要检查失败明细看失败是不是集中在某些文件或某些数据段。常见原因有三个文件名或路径里有特殊字符导致读写失败。输入数据编码不一致部分文件解析出错。某条数据缺字段模型拿到不完整输入后疯狂生成错误结果。批量任务一定要保留失败记录并且对失败原因分类。能重试的标记为“可重试”比如网络超时不能重试的标记为“输入错误”直接进入排查列表。不要把所有失败都丢到重试队列里那样只会把队列拖垮。典型现象优先排查项顺序建议返回空结果输入编码、模型输出截断先看日志再改参数输出是半截 JSONmax_tokens 不够或生成中断先看输出长度再调 max_tokens速度极慢资源占用、并发排队先看 CPU/显存再压测批量结果不稳定文件命名、编码、失败重试先查失败明细再修批量脚本内容与事实不符提示词缺失、模型幻觉先加校验再换模型6. 最后说几句我的真实感受我做 AI 工程化越久越觉得 Ken Thompson 那些老观点没有过时。他不是 AI 研究者也没有给 AI 留下一套现成答案但他的工程哲学可以迁移到 AI 上先怀疑工具再看工具输出了什么最后才决定要不要信任它。现在大家都很容易被新模型、新功能、新榜单吸引但真正拖住项目的往往不是模型不够聪明而是链路太长、日志太乱、输出不可校验。你自己都说不清一个结果是不是对的又怎么敢放给用户用我个人的建议是别急着追新模型先把“可验证”这条基线建立起来。从一条样本开始跑通输入、输出、校验、日志、失败降级再考虑扩大规模。信任不是靠模型宣传语建立起来的是靠每一步都能被复核建立起来的。如果以后接入 AI 功能你发现它总是出问题可以先向 Thompson 式的问题你信它的依据是什么如果你答不上来那就先从最小样例重新跑一遍。
返回列表