跳到主要内容

842 篇博文 含有标签「ai-engineering」

查看所有标签

你的数据 Agent 需要一个统一的营收定义

· 阅读需 10 分钟
Tian Pan
Software Engineer

Text-to-SQL 演示从不会因为语法而失败。模型生成的 SQL 非常流畅 —— 说实话,比大多数初级分析师写得都好 —— 查询可以运行,并且返回了一个数字。演示在三周后的生产环境中宣告失败,因为 CFO 注意到智能体的 “Q2 营收” 与董事会报告不符。这不是因为 SQL 格式错误,而是因为数据仓库中有三种说得通的营收定义 —— 预订额 (bookings)、已确认营收 (recognized) 和扣除退款后的净值 (net-of-refunds) —— 而模型自信地选择了其中一个。恰恰不是财务部门使用的那一个。

这是最关键的失效模式,而且在你见过的每一个基准测试中都是不可见的。解决方案不是更好的模型或更长的提示词。而是一项大多数数据团队已经构建了一半然后放弃的基础设施:语义层 (semantic layer)。你为 BI 仪表板编写的指标定义 —— dbt metrics、LookML、Cube 定义 —— 事实证明是数据智能体缺失的工具契约。交付可靠智能体的团队意识到,构建顺序与大家的假设恰恰相反:语义层优先,智能体随后。

你的设计系统曾是文档,现在它需要成为一个编译器

· 阅读需 11 分钟
Tian Pan
Software Engineer

你的设计系统在过去十年中得以幸存,是因为人类吸收它的速度很慢。新入职的工程师通过 Figma 文件、PR 里的细节纠错,以及那个总能揪出错误灰色阴影的设计师来学习组件变体。这种吸收流水线的吞吐量大约是每位工程师每周几个组件——速度慢到足以让设计团队手动把控边缘情况。

编程智能体刚刚打破了这条流水线。一个智能体集群可以在午饭前生成 50 个稍有偏差的按钮:每一个看起来都挺合理,但每一个使用的十六进制值可能差了两个色阶,内边距可能是 14px 而非你规范中的 16px 阶梯,圆角则是随手捏造的。没有哪个设计师能跟上这种评审速度。而你首先想到的指令——在系统提示词中加入“遵循样式指南”——会像所有其他软性指令一样逐渐失效:随着上下文窗口被填满,它的统计权重会下降,模型会退回到它从数百万个其他代码库中学到的通用 CSS 模式。

解决方案不是写更好的提示词。而是一次类别转变:你的设计系统必须停止作为供人类解读的“文档”,转而成为由机器执行的“契约”。文档只是请求,而编译器则是拒绝。

你的错误信息现在成了 Prompt:为 AI Agent 编写失败输出

· 阅读需 12 分钟
Tian Pan
Software Engineer

统计一下你的堆栈跟踪(stack traces)的阅读者。对于大多数内部工具,过去的答案通常是“偶尔有一位疲惫的工程师”。如今,你的错误输出的最大阅读者几乎肯定是一个处于重试循环中的语言模型。编程智能体(Coding agents)每天成千上万次地阅读你的 linter 警告、CLI 使用说明字符串、API 错误主体以及测试失败信息——频率远高于任何人类。而且与人类不同,智能体会字面理解每一个词。

这改变了错误信息的“本质”。它不再仅仅是失败的文档,而是注入到下一次尝试的上下文窗口中的指令——这是你几个月前编写的提示词,现在正引导着一群你从未见过的智能体集群。一个精确的错误能让循环在一次重试中收敛。而一个模糊或误导性的错误则会让智能体陷入恶性循环:错误的修复、--no-verify 的权宜之计、幻觉出来的参数标识、消耗殆尽的 token。如果你维护着一个工具、一项服务或一个构建系统,你其实已经在进行提示词工程(prompt engineering)了。你只是在错误字符串中进行的,而且很可能是无意为之。

你的微调模型是一个你需要维护的分支

· 阅读需 12 分钟
Tian Pan
Software Engineer

微调项目的预算会议总是估错了重点。团队估算的是数据流水线、训练运行和评估轮次——一项有着明确终点的一次性投资。随后模型发布,准确率图表节节攀升,然后大家就转向下一个项目了。六个月后,一封邮件寄达:你的适配器(adapter)所绑定的基础模型有了退役日期。你的系统本身没有任何变化,但它的根基全变了。

这是没人算进成本的部分:微调不是一个你已经完成的产品。它是别人代码库的一个分叉(fork),而每一次基础模型的发布都是一次你并未计划的上游变基(rebase)。任何曾在快速更迭的开源项目中维护私有补丁(patches)的人都清楚个中滋味——分叉的创建成本很低,但维护成本极高。

护栏也是模型:那个没人放进仪表盘的隐藏依赖

· 阅读需 13 分钟
Tian Pan
Software Engineer

这是一个正在演变成一种典型的故障复盘(postmortem)模式。主模型整晚运行良好。延迟平稳,Token 吞吐量正常,服务商状态页显示正常。然而,整整 40 分钟内,每一个用户请求都失败了——因为位于模型前端的安全分类器(safety classifier)超时了,中间件将该超时封装为一个通用异常,而异常处理程序返回了拒绝响应。你的模型并没有宕机。是你的“门禁”宕机了,而这扇门被一名从未将其视为决策选项的工程师配置成了“故障即关闭”(fail closed)。

令人不安的事实是,大多数团队在生产环境中运行着第二个机器学习系统,却不愿承认。内容审核分类器、越狱检测器、PII 清洗器、主题过滤器——每一个都是模型,拥有各自的延迟分布、错误率、在漂移中悄然腐烂的训练数据假设,以及各自的故障模式。但因为它被称为“护栏”,它就被当作配置文件来对待:设置一次,从不监控,在仪表盘上缺席,也不在值班手册中。你绝不会在没有 SLO 的情况下发布主模型。但大多数团队发布护栏时,甚至连健康检查都没有。

你的内部框架是一种低资源语言

· 阅读需 10 分钟
Tian Pan
Software Engineer

让编程智能体(coding agent)构建一个 React 组件,它第一次尝试就能写出地道的、基于 Hook 的、带有无障碍标注的代码。让同一个智能体使用你公司的内部 ORM —— 那个平台团队维护了六年、拥有出色文档和上百个内部用户的框架 —— 它就会幻觉出不存在的方法,从其他库里发明配置选项,并自信地交付出基于它臆造的 API 编写的代码,而这些代码根本无法通过编译。

这种差异并非源于质量。你的 ORM 可能比模型能完美处理的一半开源库设计得都要好。差异在于训练数据。React 背后有数百万个公开仓库;而你的框架则一个都没有。在自然语言处理(NLP)的术语中,你的内部框架是一种低资源语言(low-resource language) —— NLP 研究人员针对低资源语言记录的每一个后果,现在都适用于你的代码库。

你的模型认为你的技术栈已过时 2 年

· 阅读需 12 分钟
Tian Pan
Software Engineer

有一类 AI 生成的 Bug 几乎每次都能通过代码审查,它既不是幻觉函数,也不是捏造的包。它是完美的地道代码——地道到符合模型训练数据冻结时你的技术栈版本。模型为运行 Tailwind v4 的项目编写 tailwind.config.js,在 Hooks 代码库中调用类组件的生命周期方法,或者调用一个在三个小版本前就被弃用、并在你的 lockfile 实际锁定的版本中已被删除的 API。代码看起来毫无破绽。它看起来就像出自某个备受推崇的教程。只是那个教程来自 2024 年。

称之为“训练截止日期 Bug”:这类缺陷的存在并非因为模型推理能力差,而是因为模型对你依赖项的了解带有时间戳,而你的 lockfile 并不在意。一项 ICSE 2025 对 8 个常用 Python 库、7 个代码模型的研究发现,在看似合理的补全代码中,弃用 API 的使用率高达 25–38%——当周围代码已包含过时模式时,这一比例会攀升至 70–90%。这些并非罕见的边缘情况。它们是要求一个冻结的产物为不断变化的目标编写代码时的默认失败模式。

你的 Prompt 拥有外键

· 阅读需 11 分钟
Tian Pan
Software Engineer

重命名一个数据库列,看看会发生什么。编译器会捕获每一个查询构建器。ORM 迁移会捕获模型类。类型检查器会捕获 API 序列化器。集成测试会捕获通过网络读取该字段的两个服务。该列的每一个消费者都会被标记出来——只有一个除外。你的系统提示词(System Prompt)包含了一份为了“让模型理解数据”而精心格式化的表描述,它仍在自信地描述一个早已不存在的列。没有编译器错误。没有失败的测试。没有弃用警告。只有一个开始针对三个迭代(Sprint)前的架构生成查询的模型,以及一个慢慢被格式错误的 SQL 填满的仪表盘。

提示词中包含外键。它们引用数据库架构、工具签名、枚举值、API 结构,以及从生产数据中复制的 few-shot 示例——而这些引用都不参与重构。你粘贴到提示词中的每一个事实,都是在对一个你的工具链根本不知道其存在的表进行连接(Join)。当被引用的制品(Artifact)发生变化时,没有任何级联反应。提示词只是在那原地腐烂。

你的机密管理器在上下文窗口开始的地方终结

· 阅读需 13 分钟
Tian Pan
Software Engineer

你的 Vault 表现无可挑剔。秘密在静态存储时被加密,访问被记录,轮转是自动化的,没有任何明文会触碰磁盘。接着,你的 Agent 调用了一个调试工具,该工具将环境变量转储打印到标准输出(stdout),框架体贴地将标准输出送入模型的上下文——于是你的数据库凭据现在成了 Prompt 的一部分。从那一刻起,Vault 的保证就成了虚构。该凭据存在于你的可观测性平台捕获的 Trace(追踪)中,存在于你的提供商根据该前缀建立索引的 Prompt 缓存中,存在于你的 Agent 在会话之间写入的内存存储中,存在于某人从生产流量中快照得到的评测固件(eval fixture)中,以及提供商的保留日志中。五个持久化层,你的凭据管理器甚至不知道它们的存在。

这并非假设。一项针对超过 17,000 个已发布的 Agent 技能的大规模研究发现,通过日志导致的信息泄露占所有凭据安全问题的 73.5%——远超占比 18.2% 的硬编码密钥——这正是因为 Agent 框架会将控制台输出直接捕获到 LLM 上下文窗口中。旧的失败模式是开发者将密钥提交到 GitHub。新的失败模式是工具响应将密钥提交到上下文窗口,而上下文窗口没有 git revert

模型停滞不前,用户却在持续偏移

· 阅读需 11 分钟
Tian Pan
Software Engineer

发布六周后,你的质量仪表盘开始下滑。点踩率攀升,任务完成率下降,值班频道里塞满了糟糕回复的截图。团队做了该做的一切:对比 Prompt(未变),检查模型版本(已锁定),审计检索索引(是最新的),并对部署历史进行二分查找(没有任何发布)。大家一致认为模型提供商悄悄降低了模型性能。当然,提供商坚持说没有任何变动。

大家都找错了地方。系统没有任何改变,改变的是用户。

发布周的指标是基于发布周的用户假设的。但人们会在几周内适应一款 AI 产品,而这种适应方式会系统性地破坏你在 Prompt、评估集(Evals)和发布基准测试中预设的假设。你的模型是冻结的,但你的用户不是。两者之间的鸿沟是一种大多数团队根本没有监测到的“漂移”——它产生了一种 AI 工程中最令人困惑的故障模式:在没有部署的情况下指标发生衰减。

模型崩溃始于你自己的数据湖

· 阅读需 11 分钟
Tian Pan
Software Engineer

每个人都在担心模型崩溃,将其视为一个互联网规模的问题:AI 废话充斥网络,下一代基础模型基于这些数据进行训练,导致质量在一个缓慢的文明反馈循环中衰退。这种表述让人感到宽慰,因为它把崩溃变成了别人的问题——这是发生在 OpenAI 和 Anthropic 身上、以年为单位的事情,并且由成群的数据清洗博士负责缓解。

这里有一个令人不安的版本:同样的反馈循环已经在你公司内部运行,而且它的收敛速度比互联网规模的循环快得多。每一个被标记为“黄金示例”的日志补全、每一个进入 RAG 语料库的模型编写文档、每一个通过 LLM 生成答案并由 LLM 评判的评估——每一项都是在利用你自己的“数据废气”进行训练的微小行为。你不需要九代的递归预训练就能感受到它。在一个从自身日志中挖掘少样本示例和微调数据的生产系统中,第二代产品下个季度就会发布。

当流式 Token 遇到屏幕阅读器:生成式 UI 的无障碍债

· 阅读需 12 分钟
Tian Pan
Software Engineer

过去两年中最受赞誉的交互模式——文本逐字显现,仿佛机器正在放声思考——对于屏幕阅读器用户来说,这更像是噪音而非语言。你的模型输出的每一个 Token 都是一次 DOM 变更。如果在这个流中插入一个简单的 aria-live 区域,屏幕阅读器会尝试播报每一次到来的变更,从而产生断断续续、相互重叠的洪流,每秒钟会在句中重置几十次。使你的产品显得充满灵性的功能,恰恰是让那些依赖辅助技术的人无法使用它的元凶。

这就是无障碍债,而生成式 UI 积累这种债务的速度比以往任何界面模式都要快。其原因是结构性的:传统的 Web 内容是静态且可预测的,因此你可以推理一次后即发布。生成式界面在每次交互时都会发生变化——一个提示词返回列表,下一个返回表格,再下一个流式输出 600 字的文章,随后是一个工具调用组件。这里没有可供审计的固定 DOM,没有可验证的稳定 Tab 键顺序,也没有代表“页面”的单一快照。无障碍契约必须在无限的生成输出空间中保持有效,而几乎没有人为此进行测试。