← 文章 / 未分类
bytebytego 7小时前 · 2026-09-05 11:19:29 · 0 阅读

在按下回车键与输出第一个词之间,AI 聊天机器人内部发生了什么?

Agent 能生成代码,但要让代码符合你的系统架构、团队规范和历史决策,才是真正的难点。结果往往是你在反复纠正的循环中浪费大量时间和 token。

更多的 MCP、规则和更大的上下文窗口能让 Agent 获取信息,却不等于理解。真正跑在前面的团队,都建有一套上下文层,让 Agent 精准拿到当前任务所需的内容。

欢迎参加 9 月 2 日的免费线上研讨会,你将了解:

  • 团队在 AI 成熟度曲线上的常见卡点,以及为什么常规方案不管用

  • 上下文层如何在质量、效率和成本三方面带来提升

  • 现场演示:同一个编码任务,有无上下文层的对比

如果你想最大化 AI Agent 的价值,这场分享值得你抽出时间。

立即报名


当你在 AI 聊天框里输入追问并按下回车后,会有一两秒的安静。紧接着,回答开始一个词接一个词地快速涌现,速度远比最初那几秒的停顿所暗示的要快。

这段停顿并不是空闲时间。在典型的 LLM 中,一条消息要经过大约十几个不同的阶段,回答才会开始出现。背后有两类截然不同的计算工作在支撑这一切。关于这段旅程,有几个关键点:

  • 模型收到的消息并不是你输入时的原样。

  • 它没有对话记忆,屏幕上的聊天记录每一轮都是从头重建的。

  • 它和陌生请求共享同一台机器,被分到哪个批次都可能影响回复。

  • 一旦某个词被生成输出,模型就无法撤回。

本文将详细拆解这整段旅程,内容包括:

  • 模型的输入是如何组装的?

  • 为什么发给模型的每条输入都是相互独立的?

  • 如何对输入执行安全检查

  • 模型是如何理解这些文字的?

  • 模型如何在多个对话间共享?

  • Prefill 与 decode 步骤

  • 缓存已有计算结果

  • 流式输出与安全护栏

  • 模型如何调用各种工具?

免责声明:本文基于各来源公开分享的信息编写,参考文献见文末。如发现任何不准确之处,欢迎留言指出。

输入是如何组装后送入模型的?

首先需要理解的关键点是:你在输入框里打出的那串文字,并不是直接送到模型的内容。实际发送给模型的,是请求发出前围绕这段文字组装而成的一份“文档”。

这份文档包含以下几个组成部分:

  • 系统提示词:由 LLM 提供商编写的一段指令,用于告诉模型在对话中应当如何表现。

  • 可用工具的定义:描述每个工具的功能及其接受的输入参数。

  • 从 earlier sessions 中存储的记忆内容。

  • 在需要检索的场景下,从知识库中拉取的相关文档。

  • 截至目前的全部对话历史。

  • 最后,就是用户刚刚发送的新消息。

决定哪些内容进入这份文档、以何种顺序排列、以及哪些内容被排除在外,是一门独立的 discipline,称为 context engineering。它远非简单地把东西塞进容器了事。模型的注意力预算是有限的,每增加一个 token,预算就会被消耗一分。

随着输入变长,模型的准确率会下降,即便是在相当简单的任务上也是如此。这种衰退是渐进的:更长的提示词不会直接导致崩溃,但底层的精确度会逐渐下滑。

在语境工程这一领域所采用的方法,会导致这样一种情形:两个基于同一底层模型的产品,面对完全相同的提问,却给出不同的回答。模型或许别无二致,但包裹在问题周围的那份文档却并不相同。

不同服务商在何时为文档搜集材料方面也存在差异。有的会一次性预先获取全部内容,有的则只给模型提供轻量级的引用、文件路径或已存储的查询,让模型在处理过程中按需拉取所需内容。前者速度更快,后者则在可能无关的材料上节省更多 token。

为何发送给模型的每条输入消息都是独立的?

这些模型从设计上是无状态的,意味着它们不会在不同消息之间保留任何记忆。每条请求到来时,都不记得之前发生了什么。换句话说,我们在屏幕上看到的对话,每次都会被完整重构并重新发送。

与此相关的数学计算令人相当不适。考虑这样一个产品:系统提示词为一千个 token,每条消息和每条回复大约一百个 token。

  • 第一轮处理约 1,100 个 token。

  • 第二轮处理约 1,300 个。

  • 到第三轮,已达到约 1,500 个。

  • 到第二十轮,可能接近 4,900 个。

虽然输出 token 比输入 token 更贵,但输入量在每一轮都会叠加,而输出大致保持不变。这就是为什么在任何对话产品中,输入通常占据总成本的大头,尽管它的单价更低。

最朴素的做法是把所有内容重新发送一遍,但这仅在短对话中有效。一旦对话超出上下文窗口容量,这种做法就不再可行。有一些改进方案可以提供帮助:

  • 最简单的一种是丢弃最老的几轮。这种方式延迟成本不高,但会丢失被丢弃的内容。

  • 更谨慎一点的做法是先对对话做摘要,然后用摘要重启对话。这样既能保留已做的决定和待解决的问题,又能丢弃那些没人需要看第二遍的东西,比如原始的工具输出。

  • 第三种做法是把材料完全存到上下文窗口之外,等需要用到时再取回来。

长对话会变慢、变贵,因为每一轮都要重新处理之前所有的内容。助手最终会丢失细节,因为有些细节被裁剪或压缩了。另外,编辑早先的一条消息会改写模型所“记得”的对话历史。

对输入执行安全检查

在开始生成回答之前,拼装好的文本会先经过一个单独的、更小的模型,由它判断这个请求是否应该继续处理。可以把它理解为一层安全保障。

这里的关键在于设计上的分离。这层安全机制是一个独立于助手的系统,可以按自己的节奏重新训练、调优和监控,完全不影响主模型。它的功能也不只是放行或拦截,还可以把请求转发到别处、记录日志,或者升级给人工审核。

这种分离是有时间成本的,答案出现前的那个停顿就是明证。某生产系统公布的数字显示,早期一代这类分类器会带来约 24% 的额外计算开销,误拒无害请求的比例也会上升 0.38 个百分点。这两个数字都高到足以限制这种方案的推广范围。

替代方案采用了级联架构:用一个极低成本的验证先筛查所有流量,只有被标记的对话才会送到昂贵的分类器。这样开销降到了 1% 左右,无害查询的误拒率也降到 0.05%。

模型是如何理解文字的?

下一步,文档会被转换成模型能处理的单位。这些单位被称为 token,是一段段通常比单词小、但比字母大的文本片段。常见词往往被整体编码为一个 token,而少见词则会拆成多个片段。

大多数现代系统从原始字节而不是字符出发构建这些 token,从而保证任何书写系统的文本都能被表示。粗略来看,一个 token 大约对应四分之三个英语单词。

这种做法带来两个后果:

  • 其一是费用和处理能力因语言而异。在某次主要机器学习会议上的研究对同一段文本的不同翻译版本进行了测试,发现 token 数量相差可达十五倍。这不只是计费问题。更高的 token 数量还意味着更高的成本、更慢的处理速度,以及在相同上下文窗口内能容纳的内容更少。因此,对于同一份文档,某些语言的用户实际可用的空间明显更少。

  • 其二是涉及字符层面的问题会比较尴尬。统计某个字母在单词中出现的次数,需要深入到 token 内部去查看。

模型如何在多次对话之间共享

模型并不会闲着等请求到来。在典型设置下,token 序列会进入队列,与其他人的请求一起组成批次,在相同的硬件上并行运行。

为什么需要这种批处理?

原因在于,尽管现代加速器拥有巨大的计算能力,但它们的大量显存带宽都花在了加载模型参数上,而不是直接用于处理单个请求的有效计算工作。只需一次性加载参数,同时在多个请求上复用,才能让服务成本变得可承受。

最朴素的批处理方式是收集一批请求,一起运行,并等整批全部完成后再开始下一批。这在所有回复长度相近时可行,但聊天回复的长度并不一致:有的可能只有十几个词就结束了,有的却能长达上千词。于是硬件可能会因为等待最长的那个请求而部分空闲。

更好的做法是在单个生成步骤的粒度上调度请求。一旦某条回复生成完毕,新请求会立刻填补它腾出的位置,而不是等

原始来源: bytebytego

评论 (0)