AI 产品拆解案例:Manus、Cursor、DeepSeek 与 Character.AI

困难 🔴AI 学习
7 个标签
预计阅读时间:18 分钟
ManusCursorDeepSeekCharacter.AI上下文工程MoEKV Cache

AI 产品拆解案例:从 Manus、Cursor、DeepSeek 到 Character.AI

AI 产品的竞争力,早就不只取决于"用了哪个大模型"。同一个基座模型,不同团队做出来的产品体验可以有数量级的差距——差距往往藏在看不见的工程细节里:怎么组织上下文、怎么检索代码、怎么榨干每一分算力、怎么把推理成本压到极限。很多人以为做 AI 产品就是"选个好模型 + 写个好提示词",但当任务变成长达上百步的 Agent 流程、几十万行的代码库、千亿参数的训练、亿级用户的并发对话时,真正拉开差距的往往是模型调用之外的那一整套系统设计。本文选取 Manus、Cursor、DeepSeek、Character.AI 四个公开分享过工程实践的产品/团队,逐一拆解它们真正要解决的问题和背后的技术思路,帮助我们跳出"调 API"的视角,理解顶尖 AI 产品是怎么被"工程"出来的。

🧭 Manus 拆解:顶尖 Agent 的上下文工程

核心工程挑战

Manus 是一个通用 Agent 产品,需要完成"订机票""做研究报告""写代码"这类需要几十甚至上百步工具调用的长任务。团队面临一个直接的选择:要不要为 Agent 场景专门训练或微调一个模型?据公开分享,Manus 团队判断基座模型的迭代速度远快于自研模型的速度——押注在自研模型上,很可能"模型一升级,之前的努力就作废"。于是他们把工程重心放在了如何把现成的大模型用到极致,这套方法论后来被称为"上下文工程"(Context Engineering):不改模型参数,只是让传给模型的上下文(系统提示、历史记录、工具结果、外部记忆)组织得足够好,同样可以做出体验一流的 Agent。

技术思路:让上下文为长任务服务

1. 保持上下文前缀稳定,把 KV Cache 命中率当第一指标

Agent 每一步都要把此前所有历史重新喂给模型,上下文会随任务推进越来越长。如果每一步 prompt 的前缀发生哪怕很小的变化(比如往系统提示里插入当前时间戳),都会让推理引擎的前缀缓存失效,导致该请求要重新计算全部上下文——延迟和成本都会显著上升。所以一个朴素但极其重要的原则是:系统提示尽量只做"追加",不做"编辑";序列化 JSON 时保证字段顺序稳定;能不放进前缀的动态信息(如时间戳)就不要放。

textCode
反例:每一步都在 system prompt 里塞入当前时间
"当前时间: 2026-07-02 10:23:11..." → 前缀每步都变 → 缓存命中率归零

正例:把时间戳放进普通消息或工具返回结果里
system prompt 保持完全不变 → 前缀持续命中缓存 → 单步延迟和成本大幅下降

2. 把长期状态写到外部文件系统,而不是塞满上下文窗口

长任务的中间产物(网页抓取结果、代码文件、日志)体积很大,如果全部塞进上下文,很快会超出窗口上限,还会拖慢推理、稀释模型的注意力。比较可行的做法是让文件系统本身成为"外部记忆":Agent 把大段内容写入文件,上下文里只保留文件路径和摘要,需要时再读回来。这相当于把"几乎无限的记忆"下放给了廉价的存储,而不是昂贵又有限的上下文窗口。

3. 让工具调用的失败信息留在上下文里,而不是悄悄擦掉重试

很多实现出于"美观"会把失败的工具调用从历史里删掉,只保留成功的部分。但这样做的代价是模型会反复犯同样的错误——因为它根本看不到失败的证据。把报错信息、异常堆栈原样保留在上下文中,其实是在给模型提供负样本,让它有机会在后续步骤里"看到教训并绕开它",这是一种隐式的在线学习信号。

4. 用"屏蔽"而不是"删除"来管理工具集

随着 Agent 可用工具越来越多,动态增删工具定义同样会破坏上下文前缀的稳定性(工具定义通常出现在提示靠前的位置)。比较稳妥的做法是让工具定义本身保持不变,通过模型输出层面的掩码来限制当前步骤可选的工具子集,而不是在提示里反复增删工具描述。

5. 故意保留一些多样性,避免陷入"复读"式的模式坍缩

如果上下文里全是高度相似、模板化的历史动作,模型容易陷入模仿最近动作的惯性,即使当前情境已经不再适用。适度在历史记录的表述上引入变化,有助于防止这种"少样本模仿"带来的僵化和跑偏。

6. 把系统提示拆成"稳定层"和"易变层"

一个常见的误区是把整个系统提示当成一整块随意拼接的文本。更稳健的做法是把它拆成两层:一层是几乎不变的"身份与工具说明"(模型是谁、能用哪些工具、输出格式约定),放在最前面,长期保持字节级不变,最大化命中前缀缓存;另一层是随任务推进而变化的"当前状态"(已完成的步骤、当前子目标、最新的观察结果),放在提示的尾部,只在这一层做更新。这样即使任务状态频繁变化,前面几千 token 的稳定部分依然可以持续复用缓存。

textCode
[稳定层:身份、工具schema、输出格式约定]   ← 几乎不变,长期命中缓存
--------------------------------------
[易变层:当前任务状态、最近观察、下一步计划]  ← 每步都可能更新

7. 让计划显式地留在上下文里,对抗长任务的"注意力漂移"

任务步数一多,模型容易忘记最初的目标,或者被中间某一步的细节带偏。把当前的整体计划、已完成事项、待办事项显式地写成一小段结构化文本,反复出现在提示中,相当于不断地把模型的注意力"拉回"到主线任务上,减少长任务中期跑题的概率。

8. 小结:上下文工程的通用原则清单

把以上做法抽象一下,可以归纳出一份适用于绝大多数 Agent 产品的通用原则清单:

优先保证上下文前缀的稳定性,把缓存命中率当作和准确率同等重要的指标;
长期状态尽量外置到文件系统或数据库,上下文里只保留引用和摘要;
工具调用失败的痕迹要留下来,它是模型免费的纠错样本;
工具集的变化用掩码控制,而不是频繁编辑提示本身;
历史记录保留适度多样性,防止模型陷入机械模仿;
系统提示分层设计,稳定部分和易变部分物理隔离;
长任务中显式维护并反复呈现当前计划,对抗注意力漂移。

这些原则并不依赖某个具体模型的私有能力,任何团队在调用公开的大模型 API 构建自己的 Agent 产品时,都可以直接照搬这套思路——它本质上是一套"如何跟大模型高效协作"的工程规范,而不是某个厂商独有的秘密武器。

对我们的启发

不是所有产品竞争力都要靠"自研更强的模型"来获得;把现有模型的上下文组织好——缓存友好、记忆外置、保留错误信号、结构稳定——本身就是一种可以被系统化、可以被持续打磨的工程能力,甚至是决定 Agent 产品体验上限的关键变量。

💻 Cursor 拆解:AI 怎么读懂你的整个代码库

核心工程挑战

写代码时,模型只有理解了整个项目的架构、跨文件的调用关系、团队约定的写法,给出的建议才靠谱。但一个中大型代码库随便就是几十万行,远远超出任何大模型的上下文窗口;即使窗口足够大,把整个仓库塞进去成本也高得不现实,而且真正相关的信息往往只是仓库中很小的一部分。更棘手的是,编程助手不像离线的文档问答工具,它要嵌入在编辑器里实时响应用户的每一次按键和每一次提问,对"新鲜度"和"延迟"都有很高要求——代码改了一秒钟前,助手就应该知道;用户按下 Tab 键,补全建议不能让人等出割裂感。真正的挑战不是"模型够不够聪明",而是"怎么在几十万行代码里,又快又准地把当前任务真正相关的那几百行找出来,并且延迟要低到能跟得上手速"。

技术思路

1. 代码版 RAG:对代码库做语义索引和检索

和文档 RAG 类似的思路被搬到了代码场景:把代码库按函数、类、文件等粒度切分,构建语义向量索引;编辑或提问时先检索出相关的代码片段,再把这些片段和用户的当前上下文一起喂给大模型。区别在于代码有更强的结构性——检索不能只看文本相似度,还要能捕捉"这个函数调用了谁""这个类型在哪里被引用"这类关系,否则很容易检索到字面相似但语义无关的片段。另外,通用文本的嵌入模型并不天然适合代码——变量命名、缩进、语言关键字的分布规律和自然语言差异很大,因此专门针对代码语料训练或微调嵌入模型,往往能显著提升检索的准确率。

2. 用自研小模型处理延迟敏感的子任务

不是所有环节都要调用最强的大模型。像"光标处该补全什么代码"这种任务,用户对延迟极其敏感(几百毫秒的等待就会打断心流),如果每次都请求一个慢而贵的大模型并不划算。比较现实的路径是针对这类高频、模式相对固定的子任务,训练或蒸馏一个专用的小模型,让它在低延迟链路上完成,把大模型留给真正需要深度推理的场景,比如多文件重构、复杂需求理解。

textCode
用户操作                      处理方式
-------------------------  ----------------------------
输入下一个 token 的补全       延迟敏感 → 轻量小模型,就近部署
"帮我重构这个模块"            复杂度高 → 大模型 + 代码检索上下文
"这个报错是什么原因"           需要跨文件定位 → 检索 + 大模型综合分析

3. 结合静态分析和 AST,让检索"懂代码"而不只是"懂文本"

纯文本向量检索容易被变量名、注释这类表层信号误导,抓不住"谁调用了谁""这个符号定义在哪"这种结构信息。把静态分析、抽象语法树(AST)解析和语义索引结合起来,可以让检索系统理解代码的调用图、类型关系、作用域,从而在补全和问答时提供更贴合项目实际结构的上下文,而不是简单的字符串相似匹配。

4. 增量索引:编辑一行代码,不必重新扫描整个仓库

真实开发场景中,代码库几乎每分钟都在变化。如果每次改动都要重新对全仓库做一遍语义索引,成本和延迟都无法接受。更实际的做法是做增量索引:只对发生变化的文件或函数重新计算向量、更新索引条目,未改动的部分继续复用已有索引。索引系统的更新速度,直接决定了 AI 编程助手"感知"到最新代码的时效性。

5. 检索结果的排序与上下文预算分配

即使检索系统召回了一批相关代码片段,也不能不加选择地全部塞进提示——上下文窗口本身是有限资源,还要给对话历史、当前文件内容留出空间。需要有一层排序和裁剪逻辑:综合语义相关性、代码调用距离、文件的新旧程度等信号给候选片段打分,按预算截断,优先保留信息密度最高的片段,而不是简单按相似度分数一刀切。

6. 多信号融合:光有向量检索还不够

只依赖向量相似度的检索,遇到"函数名完全一致但语义描述不同"或者"用户直接引用了某个符号名"这类情况时,效果反而不如传统的关键词匹配。更成熟的系统会把向量检索、关键词检索、最近编辑过的文件、当前打开的标签页等多种信号融合起来做综合排序,而不是单一依赖某一种检索方式,这也是为什么"看起来简单的代码搜索"背后往往是一套相当复杂的融合排序系统。

7. 护城河不只在模型本身,也在工程系统设计

不同 AI 编程工具背后可能用的是同一批基座大模型,但体验差距很大——差距往往来自索引更新是否够快(改一行代码要不要重建全库索引)、检索排序是否精准、延迟敏感任务有没有专门优化、和编辑器的交互设计是否顺手。这些都不是"换个更强的模型"能直接解决的问题,而是纯粹的系统工程能力,这也是为什么简单封装模型接口和真正做深工程的产品,体验差距会越拉越大。

对我们的启发

面对"上下文太大装不下"的问题,答案往往不是等更大的窗口,而是构建一套检索加结构分析的系统,把无限的信息裁剪成模型真正需要的那一小部分;同时要做好任务分层——不是每个任务都值得用最贵的模型去处理,索引和检索系统的实时性往往比模型本身的能力上限更影响日常体验。

🧮 DeepSeek 拆解:用几分之一的钱训出顶尖模型

核心工程挑战

训练和运行千亿甚至万亿参数级别的大模型,算力和显存都是巨大的硬约束。行业里长期存在一种朴素假设:模型效果基本由"堆了多少算力、用了多少数据"决定,资源越多的团队天然占优。据公开分享,DeepSeek 团队在算力资源相对受限的条件下,依然要做出能对标一线水准的模型,问题就变成了:能不能通过架构和训练方法上的系统性创新,用远低于"堆算力"路线的资源投入,换到接近甚至持平的模型能力?这要求团队不能只在某一个环节做优化,而是要把模型架构、注意力机制、数值精度、训练范式当作一个整体来协同设计,任何一个环节的浪费都会被资源约束放大。

技术思路

1. MoE(混合专家架构):参数量大,但每次只激活一部分

传统稠密模型每次前向传播要用到全部参数,参数越多,算力开销越大。MoE 把网络中的前馈层换成多个"专家"子网络,每个 token 只经过一个路由器挑选出的少数几个专家,而不是全部专家参与计算。这样模型总参数量可以做得很大、表达能力强,但实际参与计算的参数量只是其中一小部分,从而用远低于同等规模稠密模型的算力开销,获得接近大模型的效果。

textCode
稠密模型:  输入 → 全部参数参与计算 → 输出   (参数量 = 计算量)
MoE 模型:  输入 → 路由器 → 激活少数专家 → 输出 (参数量 >> 实际计算量)

2. MLA(多头潜在注意力):压缩 KV Cache,省显存

标准多头注意力在推理时需要为每个 token 缓存所有注意力头的 Key/Value,序列越长、并发越多,显存占用越夸张。MLA 的思路是先把 Key/Value 投影到一个低维的"潜在空间"再进行缓存,需要时再还原展开,用一次低维压缩换取显著更小的缓存体积,从而在同样的显存预算下支持更长的上下文或更高的并发。可以把它类比成把一份高分辨率图片先压缩成一个小体积的文件存起来,等真正需要显示的时候再解压还原——存储的是压缩后的紧凑表示,而不是原始的完整数据,只要压缩和解压的映射设计得当,效果损失可以控制在很小的范围内。

3. FP8 低精度训练:用更粗的数值精度换更高的训练吞吐

训练时数值精度越高,单次计算的硬件开销越大。把关键计算路径从常见的 16 位精度进一步降到 8 位浮点(FP8),单位时间能处理的计算量明显提升,训练同样规模的模型所需的时间和资源随之下降。低精度最大的风险是数值溢出或梯度不稳定,因此需要配合精细的缩放策略和混合精度设计,在关键的敏感环节保留更高精度,来保证训练稳定收敛,而不是简单粗暴地把所有数字都截断成 8 位。

4. 纯强化学习训练推理能力:绕开海量人工标注的推理链

让模型学会"一步步推理",传统做法依赖大量人工标注的详细解题过程。据公开分享,DeepSeek 探索了一条更依赖强化学习、较少依赖人工标注推理过程的路径:让模型通过大量"是否得到正确答案"这类可验证的奖励信号自主探索、自我改进推理策略,而不必先由人类手把手示范每一步该怎么想。这大幅降低了对昂贵的人工标注推理数据的依赖。

textCode
传统路径:人工标注详细解题步骤 → 监督微调 → 模型模仿标注的推理过程
RL 路径: 只提供"答案对不对"的奖励信号 → 模型自主探索 → 逐步学会有效的推理策略

5. 知识蒸馏:把大模型的推理能力"教"给小模型

在用强化学习训练出具备较强推理能力的大模型之后,还可以把这类大模型生成的高质量推理过程作为训练数据,去蒸馏训练参数量小得多的模型。这样一来,小模型也能在特定任务上表现出接近大模型的推理水平,同时保留小模型部署成本低、推理速度快的优势,形成"大模型负责探索出好的推理路径,小模型负责低成本地复用这些路径"的分工。

对我们的启发

DeepSeek 这几项技术看似分散——架构、注意力机制、数值精度、训练范式,但共同的主线是同一个思路:当硬件或预算不是你的优势时,就把每一处能够"用系统工程弥补差距"的环节都做到极致,不是单点突破,而是从架构设计到训练策略的全链路协同优化。对于资源有限的团队,这个案例的价值不在于照搬某个具体架构,而在于它示范了一种思维方式:先搞清楚成本主要花在哪几个环节,再逐一寻找该环节里"用工程手段换资源"的空间。

💬 Character.AI 拆解:海量陪聊的成本怎么压下来

核心工程挑战

陪聊类产品的典型特征是:用户数量巨大、对话轮次很长、并发规模高,而且用户对"角色记得住之前聊过什么"有很强的期待,这意味着单次对话的上下文往往比一般问答场景长得多。这类场景推理成本的真正瓶颈,往往不是"算力不够",而是显存里堆积的 KV Cache——每一路对话都要为已经生成过的所有 token 保留 Key/Value 缓存,对话越长、并发用户越多,缓存占用就越大,超过显存容量后要么拒绝新请求,要么被迫压缩批量大小、拖慢整体吞吐。单纯增加 GPU 数量只能线性提升算力,却无法从根本上改变"每路对话占用的缓存随长度线性增长"这个结构性问题。据公开分享,Character.AI 在这个方向上做了大量压缩 KV Cache 的工程优化,目标就是在同样的硬件上撑起数量级更大的并发对话。

技术思路

1. MQA/GQA:让多个注意力头共享 Key/Value

标准多头注意力(MHA)里每个头都有自己独立的 Key/Value,头数越多缓存越大。多查询注意力(MQA)让所有头共享同一份 Key/Value,只有 Query 保持独立;分组查询注意力(GQA)是介于两者之间的折中方案——把头分成若干组,组内共享一份 Key/Value。这样在几乎不损失效果的前提下,把 KV Cache 体积压缩到原来的几分之一甚至十几分之一。

textCode
MHA: 头1(K1,V1) 头2(K2,V2) 头3(K3,V3) 头4(K4,V4)   → 缓存 = 4 份 KV
GQA: [头1,头2]共享KV_A   [头3,头4]共享KV_B          → 缓存 = 2 份 KV
MQA: 头1,头2,头3,头4 共享同一份 KV                   → 缓存 = 1 份 KV

2. 滑动窗口注意力:只保留最近一段上下文的缓存

陪聊场景里,很多时候模型真正需要"精确记住"的只是最近若干轮对话,而不是从会话开始的全部历史。滑动窗口注意力只在一个固定大小的窗口内做完整的注意力计算和缓存,超出窗口的旧 token 被丢弃或降级处理,缓存大小不再随对话长度无限增长,而是被限制在一个可控的常数范围内。

3. 跨层共享 KV Cache:多层复用同一份缓存

Transformer 通常每一层都有自己独立的 Key/Value 缓存,层数越多、总缓存量越大。让相邻的多个层共享同一份 KV Cache,可以在增加模型深度的同时,不让缓存体积随层数线性膨胀,用较小的额外显存代价获得更深的网络。

4. 量化与连续批处理:从缓存体积到整体吞吐的全链路优化

除了从注意力结构层面压缩缓存,把 KV Cache 本身用更低精度(比如 int8 甚至更低)存储,也能在几乎不影响回复质量的前提下进一步减少显存占用。与此同时,服务层面常见的连续批处理(continuous batching)让不同用户的请求可以在生成过程中动态加入或退出同一批次,而不必等一整批都生成完才能处理下一批,从而把显存和算力的利用率维持在高位。缓存压缩解决"能不能装下更多对话",连续批处理解决"能不能把资源用满",两者结合才能真正把单位成本打下来。

5. 长期记忆与会话窗口的取舍

对陪聊场景而言,用户往往希望"角色记得住我",这和滑动窗口"只保留最近上下文"存在天然张力。工程上的折中思路是把两者分层:短期的、逐字精确的上下文交给注意力机制和 KV Cache 处理,而跨会话的长期记忆(用户的偏好、过往关键事实)则单独抽取、总结后存放到外部存储中,在新会话开始时以精简摘要的形式重新注入,而不是让原始的长对话历史一直占用宝贵的缓存空间。

对我们的启发

面向"海量并发、长对话"的产品,推理优化的重点应该先看 KV Cache 这个瓶颈,而不是一味追求更快的芯片或更大的批量;注意力机制层面的共享和裁剪(GQA、滑动窗口、跨层共享)往往比单纯堆硬件更划算,也更能直接决定产品能不能在成本可控的前提下撑住用户规模。

🌟 总结:四个案例的共同主线

这四个拆解看似分属不同领域——Agent、编程助手、基座模型训练、对话产品,但可以看到同一条主线:顶尖 AI 产品的竞争力,很大一部分来自"模型之外"的系统工程能力。Manus 把功夫下在上下文组织上,Cursor 把功夫下在代码检索和任务分层上,DeepSeek 把功夫下在架构和训练效率上,Character.AI 把功夫下在推理阶段的缓存压缩上。四者面对的约束不同——有限的上下文窗口、有限的检索延迟、有限的算力预算、有限的显存容量,但解法的思路是相通的:先精确定位真正的瓶颈在哪里,再针对瓶颈设计专门的系统,而不是简单地寄希望于"换一个更强的模型"就能一劳永逸。理解这些原理,比单纯记住"调哪个 API"更能帮助我们判断一个 AI 产品的真实工程含金量,也更能指导我们在做自己的 AI 应用时,把有限的资源投入到真正决定体验和成本的地方。