上下文工程:含记忆系统与 RAG 全栈选型

位置:LLM 应用工程四层演进的第二层 调研日期:2026-05-01


Executive Summary

Context Engineering(上下文工程) 在 2024 下半年由 Karpathy 在 YC AI School 演讲中正式命名,被 Anthropic [6] 定位为”提示词工程的自然演进”。其核心观察是:在 100K-1M 上下文窗口和 Agent 时代,决定模型表现的不再是”那一句 prompt”,而是 模型在推理这一刻能看到的全部信息——system prompt、对话历史、工具定义、检索文档、记忆、规划状态。

本章覆盖:

关键转折:生产级 LLM 应用的核心难度从”写 prompt”迁移到了”管 context”——这是 Agent(03)和驾驭工程(04)的前提。


2.1 定义与起源

“Context Engineering”(上下文工程)这个词在 2024 年下半年开始在社区流传,普遍归功于 Karpathy 在 YC AI School 的 Software Is Changing (Again) 演讲 [5]。他给的定义后来被反复引用:

“In every industrial-strength LLM app, context engineering is the delicate art and science of filling the context window with just the right information for the next step.” (在每一个工业级 LLM 应用里,上下文工程是把恰好正确的信息填进上下文窗口、为下一步推理做准备的精细艺术与科学。)

Anthropic 在 2025 年发布的官方文章 Effective Context Engineering for AI Agents [6] 进一步把它定位为”提示词工程的自然演进”:

「prompt engineering 关心的是你给模型说的那句话;context engineering 关心的是模型在推理那一刻能看到的所有信息——system prompt、对话历史、工具定义、检索到的文档、记忆、规划状态、约束与策略。」

LangChain 团队在 Context Engineering for Agents 博客 [7] 里给了一个常被引用的工程定义:

“Context Engineering 是设计动态系统的学科,这些系统在正确的时间、以正确的格式,向 LLM 提供正确的信息和工具,让模型有完成任务所需的一切。”

为什么”提示词工程”不够了?三个根本变化:

  1. 窗口扩张:从 GPT-3.5 的 4K 一路涨到 Gemini 2.5 Pro 的 1M、Claude Opus 4.7 的 1M。能塞进窗口的信息从”几段文字”变成了”一整本书”。决定塞什么变得比写好那一句话重要得多
  2. Agent 兴起:单轮 prompt 是孤立交易,agent 是持续状态机。每一步推理的 context 都来自上一步的输出 + 工具返回 + 检索 + 记忆,“prompt”已经不是用户写的那句话,而是 agent 框架动态拼装的产物
  3. 多模态 + 工具调用:context 不再只是文本,还有图像、表格、代码、tool schema、retrieved chunks、structured memory、scratchpad。把这些异构信息组织好是工程问题

到 2026 年初,业界共识是:生产级 LLM 应用的核心难度从”写 prompt”迁移到了”管 context”。


2.2 长上下文的物理学

要理解为什么”塞满窗口”是个坏主意,必须先理解上下文的三个物理约束:

2.2.1 O(N²) 成本

回到 prompt-engineering.md §1.1:标准 attention 是 N² 复杂度。上下文从 32K 翻到 128K,注意力计算量是 16 倍而非 4 倍。对推理服务来说这意味着两件事:

2.2.2 KV Cache 显存

每个 attention 层在推理时要维护 K 和 V 的缓存(避免重复计算)。一个 70B 模型在 128K 上下文时,KV cache 占用可达 40+ GB,比模型权重本身还大。这就是为什么 vLLM 的 PagedAttention 和 SGLang 的 RadixAttention 这类”管 KV cache”的技术成为推理服务器的核心竞争力(详见 harness-engineering.md §3.9.2)。

2.2.3 Lost-in-the-Middle

Liu 等人 2024 TACL 论文 Lost in the Middle: How Language Models Use Long Contexts [2] 系统验证了一个反直觉现象:把关键信息放在 prompt 开头或结尾,模型能很好地利用;放在中间,模型常常视而不见。召回率随位置呈 U 型曲线——开头有 primacy bias、结尾有 recency bias、中间是黑洞。

这条曲线在 GPT-3.5 / GPT-4 / Claude 上都验证过。即便 2025 年的 Gemini 1.5 Pro 在简单的 needle-in-a-haystack 测试上能拿到 99.7% 召回,但当任务变成”在 1M token 里找出 8 个相关事实并综合”,平均召回率掉到 ~60% [41]。


2.3 RULER 与 1M 上下文的真实能力

NVIDIA 等机构 2024 年发布的 RULER 基准 [12](What’s the Real Context Size of Your Long-Context Language Models?)把”长上下文能力”从 needle-in-a-haystack 的玩具测试升级为”折磨套件”:

RULER 暴露出的真相:几乎所有声称 100K+ 上下文的模型,在 RULER 上的”有效上下文”远小于宣称值。比如某模型宣称支持 200K,但 RULER 上 50K 后准确率就掉到 80% 以下,128K 时已经接近 random。

这把行业拉回了现实:long context 不是 RAG 的替代,而是补充。

长上下文 vs RAG 决策框架

Tianpan 在 Long-Context Models vs RAG: When the 1M-Token Window Is the Wrong Tool [41] 给了一个 2026 主流的决策框架:

维度 1M 上下文模型 RAG
延迟 30-60 倍慢(必须 prefill 整个窗口) 检索 + 生成两阶段,但生成阶段输入小
每查询成本 ~1250 倍贵 检索几乎免费,生成成本随相关 chunk 数
数据更新 每次查询都要重传 索引更新一次,所有查询受益
可解释性 黑箱 检索结果可审计、可引用
多事实召回 ~60%(实战) 配合 reranker 可达 90%+
真正适合长上下文的场景 单次深度分析(“读完这篇 200 页的 PDF 总结洞察”) 知识库问答、客服、文档检索

实战指引:90% 的”知识检索”场景应该用 RAG,10% 的”深度分析单文档”才用长上下文。


2.4 RAG 全栈选型

RAG(Retrieval-Augmented Generation)是上下文工程最成熟的一支,已演进出完整的子学科。2025-2026 年的状态可以用四代演进概括 [43]:

下面按 RAG 流水线顺序拆解 2026 年的选型空间。

2.4.1 文档解析(Parsing & Layout)

现实世界的文档是 PDF、PPT、扫描件、Excel、HTML 而不是纯文本。这一步常被忽略但影响极大:

最佳实践:至少跑两套 parser 对比,再决定用哪个。表格 / 公式必须特别处理(转 markdown / LaTeX)。

chunking">2.4.2 切分策略(Chunking)

切分策略对召回质量影响远大于嵌入模型的选择:

通用建议:chunk size 256-512 token、overlap 50-100 token,是大多数任务的 sweet spot。

2.4.3 嵌入模型(Embedding Models)

2026 年 4 月 MTEB(Massive Text Embedding Benchmark)榜单 [13] 主要选手:

模型 MTEB 维度 价格 / 1M tok 特点
OpenAI text-embedding-3-large 64.6 3072(可截短) $0.13 老牌稳定
Cohere embed-v4 65.2 1536 $0.10 当前 MTEB 第一
Voyage 3 large ~66 1024/2048 $0.18 平均比 OpenAI 高 ~10%
Google Gemini Embedding 2 64+ 3072 $0.006 多模态原生(文本/图/视频/音频/PDF),100+ 语言
BGE-M3(BAAI) 64+ 1024 免费(开源) 同模型支持 dense / sparse / multi-vector 三种检索
Jina v5-text-small 71.7(v2 榜) 512 免费(Apache 2.0) 677M 参数,最佳质量 / 体积比

2026 年的两个关键趋势:

  1. Matryoshka Representation Learning(套娃表示):同一个 embedding 在不同截断长度(128 / 256 / 512 / 1024 / 3072)都能用,索引时存全长,检索时按需截短。Gemini 2 / Voyage 4 / Cohere v4 / OpenAI text-3-* / Jina v5 / Microsoft Harrier / Nomic v1.5 都支持。可以让”先粗筛后精排”在 embedding 层就实现
  2. 多模态原生:Gemini Embedding 2 把图像 / 视频 / 音频 / PDF 编进同一个语义空间,多模态 RAG 的索引复杂度从”分模态建索引 + 跨模态对齐”降到”统一索引”

中文场景实测:BGE-M3 是免费第一(开源 + 多语言强 + 同模型支持稀疏/稠密),Voyage 3 large 是付费第一(中文召回普遍比 OpenAI 高 10%+)。

向量数据库vector-database">2.4.4 向量数据库(Vector Database)

2026 年生产部署的五大主流 [14]:pgvector / Qdrant / Weaviate / Milvus / LanceDB。

性能基准(2026,128 维 embedding,1M 向量量级)[14]:

数据库 p99 延迟 QPS(单节点) 备注
Qdrant 2 ms 12,000 Rust 实现,元数据过滤最强
FAISS(in-memory) 3 ms 15,000 单机性能王,无服务化能力
Milvus 5 ms 8,000 分布式 + 高可用,2.5 版本混合检索 30x 快于 ES
Pinecone 8 ms 5,000 全托管,运维零负担
Weaviate 10 ms 4,000 内置 GraphQL 与知识图能力

选型决策:

2.4.5 检索:稀疏 + 稠密 + 后期交互

向量检索(稠密)擅长语义相似度但不擅长精确关键词匹配(产品 ID、专有名词、错别字容忍)。生产级 RAG 几乎都是 hybrid search:

混合策略:用 RRF(Reciprocal Rank Fusion)合并稀疏与稠密的结果列表。简单且无需调参。

RRF 公式:

\[ \text{RRF}(d) = \sum_{r \in R} \frac{1}{k + r(d)} \]

其中 R 是各路检索器,r(d) 是文档 d 在该路检索器里的排名(1, 2, 3...),k 是平滑常数(默认 60,Cormack 等 2009)。直觉:排名越靠前贡献越大,但因为是倒数,差距收敛快,避免某一路霸榜。

RRF 调权(生产实践):默认 RRF 把所有检索器等权对待。如果想给稠密 / 稀疏不同权重:

def weighted_rrf(results_dict, weights, k=60):
    # results_dict = {"dense": [doc1, doc2, ...], "sparse": [docA, docB, ...]}
    # weights = {"dense": 0.7, "sparse": 0.3}
    scores = defaultdict(float)
    for retriever, docs in results_dict.items():
        w = weights[retriever]
        for rank, doc in enumerate(docs, start=1):
            scores[doc.id] += w / (k + rank)
    return sorted(scores.items(), key=lambda x: -x[1])

RRF vs 其他融合:

方法 是否需调参 跨检索器分数对齐 何时用
RRF 否(k=60 几乎万能) 用 rank 不用 score,天然对齐 默认首选
CombSUM / Linear 是(要归一化分数) 难(BM25 vs cosine 量纲不同) 不推荐,除非已有校准
WAND(Weighted AND) 中 在 sparse 内部用,不跨融合 Lucene / Elasticsearch 加速倒排
Convex Combination + ML 高(要 learning-to-rank) 训练对齐 大规模、有点击数据时最优

实证:hybrid search + reranker 比 semantic-only 提升 +9.3 个百分点 MRR,配合 Cohere Rerank 准确率可以到 90%+。

2.4.6 重排(Reranker)

第一阶段检索(embedding / BM25)召回 top-100 后,用更贵但更准的 cross-encoder 模型对 query-doc 对重排,取 top-5 给 LLM。这一步的 ROI 极高:

Reranker 类型 ELO 备注
Zerank 2 API 1638 当前榜首
Cohere Rerank v4 Pro API 1629 老牌
Cohere Rerank 3 Nimble API — 速度优化版本
BGE-reranker-v2-m3 自托管 — 开源,效果接近 Cohere
FlashRank 自托管 — 极轻量,毫秒级
ColBERT v2 自托管 — 后期交互架构
RankLLM(用 LLM 直接 rerank) LLM — 最贵但解释性最好

top rerankers 比纯 embedding 提升 15-40% 精确率。如果只允许加一项 RAG 优化,加 reranker 通常 ROI 第一。

2.4.7 查询改写(Query Rewriting / Expansion)

用户问的”今天天气咋样”和文档里写的”current weather conditions”语义相同但词汇不重叠。Query rewriting 在检索前先对 query 做处理:

怎么选(按 query 形态决策):

query 形态 推荐方法 原因
短查询 / 关键词缺失 HyDE / Query2Doc 短 query 与文档 chunk 长度不匹配,扩成假文档可拉近 embedding 距离
多义词 / 同义词问题 Multi-Query 改写覆盖不同措辞,提升召回
涉及背景知识的窄问题 Step-Back 先检索宏观知识再聚焦细节
复合 / 比较 / 多跳 Sub-Query Decomposition 单次检索无法覆盖多个子主题
通用对话 + 代码 / 数字 不要重写 LLM 重写可能改变关键术语 / 数字,反而召回掉

陷阱:

  1. Query rewriting 增加 1 次额外 LLM 调用(latency +500-1500 ms),高 QPS 场景需评估
  2. 如果原 query 已经精确(“OpenAI 2025 年 Q3 收入”),重写可能引入噪声,建议加一个 “is_specific” 分类先判断
  3. HyDE 在 冷门 / 长尾 / 专业领域 反而效果差 —— LLM 假想的伪文档与真实文档措辞偏差大

2.4.8 GraphRAG

Microsoft GraphRAG(2024 开源)和 LightRAG / Nano-GraphRAG 等社区变体把检索从”向量相似”扩展到”知识图遍历”:

GraphRAG 在某些场景把检索精度推到 99%(金融合规、法律、医疗等关系密集的领域)[43]。

2.4.9 Self-RAG / CRAG / Agentic RAG

三者横向对比:

维度 Self-RAG CRAG Agentic RAG
决定何时检索 模型自己(特殊 token [Retrieve]) 始终检索 Agent 控制器决定
检索结果评判 模型自己([IsRel] 反思 token) 独立 retrieval evaluator(小模型,分高/中/低) LLM judge 或工具
失败兜底 不再检索 + 提示不确定 触发 web search 重检索 改写 query / 换数据源 / 多轮迭代
训练成本 高(需对反思 token 做 SFT) 低(plug-and-play) 0(运行时编排)
延迟 中(一次推理多输出 token) 高(始终检索 + 评估 + 可能 web) 最高(可能多轮 loop)
适用 自带知识充足的通用问答 知识库时新性差、需要 web 兜底 多跳推理、研究型问答、Deep Research
2026 主流落地 OpenAI gpt-4o web search 模式 Perplexity / You.com 内部架构 Claude / Cursor / Devin 的研究 agent

实证:Self-RAG 在生产部署中能减少 25-40% 的”不必要检索”——因为模型学会了对自己已有知识的事情不去检索。Agentic RAG 在多跳问答(HotpotQA / MuSiQue)准确率比 vanilla RAG +15-25 个点,但 token 成本翻 3-10 倍。

详见 agent-engineering.md §2 范式演进、§5 框架对比。

2.4.10 多模态 RAG

图像 + 文本混合的索引方案:

Layout-aware chunking(关键工程点,被低估):

传统 RecursiveCharacterTextSplitter 对 PDF / Word 这类有版式的文档效果差 —— 表格被劈成两半、figure caption 与图分离、目录与正文混合。生产级方案:

工具 路线 强项
Unstructured.io 规则 + ML 元素分类 通用,HTML/PDF/PPT/Email 全覆盖
LlamaParse LlamaIndex 自家 LLM 解析 Markdown 输出,表格保真度高
PyMuPDF + pdfplumber 底层 PDF SDK 自定义 layout 规则,保留 bbox 坐标
Docling(IBM 2024) 开源结构化文档解析 表格 / 公式 / 图像 caption 关联
MinerU(OpenDataLab 2024) 中文 PDF 友好 中文学术论文 / 教材效果好

多模态 RAG 选型决策:

陷阱:多模态 embedding 在跨模态检索(用文字找图)效果远好于跨模态对齐(图与文字到底说的是不是一件事),生成阶段仍需 VLM 二次确认相关性。

2.4.11 完整 RAG pipeline 代码骨架

把上面 10 个子节串起来,一个生产级 RAG pipeline 的最小可运行骨架:

# 1. 文档解析
from llama_parse import LlamaParse
parser = LlamaParse(result_type="markdown")
docs = parser.load_data("./knowledge_base/")

# 2. 切分
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
    chunk_size=512, chunk_overlap=80,
    separators=["\n\n", "\n", "。", "!", "?", ".", " "]
)
chunks = splitter.split_documents(docs)

# 3. 嵌入 + 入向量库
from langchain_community.embeddings import HuggingFaceBgeEmbeddings
from langchain_qdrant import QdrantVectorStore

embeddings = HuggingFaceBgeEmbeddings(model_name="BAAI/bge-m3")
vectorstore = QdrantVectorStore.from_documents(
    chunks, embeddings, url="http://localhost:6333", collection_name="kb"
)

# 4. 混合检索(dense + sparse + RRF)
from langchain.retrievers import EnsembleRetriever, BM25Retriever
bm25_retriever = BM25Retriever.from_documents(chunks); bm25_retriever.k = 20
dense_retriever = vectorstore.as_retriever(search_kwargs={"k": 20})
hybrid_retriever = EnsembleRetriever(
    retrievers=[bm25_retriever, dense_retriever], weights=[0.4, 0.6]
)

# 5. 查询改写(multi-query + step-back)
from langchain.retrievers.multi_query import MultiQueryRetriever
from langchain_anthropic import ChatAnthropic
llm = ChatAnthropic(model="claude-sonnet-4-6")
multi_q_retriever = MultiQueryRetriever.from_llm(retriever=hybrid_retriever, llm=llm)

# 6. 重排(Cohere Rerank 或 BGE-reranker)
from langchain.retrievers import ContextualCompressionRetriever
from langchain_cohere import CohereRerank
reranker = CohereRerank(model="rerank-v3.5", top_n=5)
final_retriever = ContextualCompressionRetriever(
    base_retriever=multi_q_retriever, base_compressor=reranker
)

# 7. 生成(带 citation)
from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个严谨的助手。仅根据给定 context 回答,每条事实必须标注 [doc_id]。"),
    ("human", "Context:\n{context}\n\n问题: {input}"),
])
combine_chain = create_stuff_documents_chain(llm, prompt)
rag_chain = create_retrieval_chain(final_retriever, combine_chain)

answer = rag_chain.invoke({"input": "Transformer 的 attention 复杂度是多少?"})

这个骨架覆盖了 RAG 的 7 个核心步骤。生产化还需要加:

2.4.12 GitHub 系统化学习资源(RAG 专题)

资源 类型 推荐用法
NirDiamant/RAG_Techniques 高级技术 notebook 集 30+ 种 RAG 高级技术每个都有可跑 notebook,最全
infiniflow/ragflow 开源 RAG 引擎 想要”开箱即用”的企业级 RAG 平台
HKUDS/LightRAG EMNLP 2025 论文 + 实现 简洁高效的 RAG 范式参考
Danielskry/Awesome-RAG awesome list 找特定主题资源时的入口
lehoanglong95/rag-all-in-one 全栈指南 想要按组件对照工具时
pguso/rag-from-scratch 从零实现 想搞清”黑盒里到底发生了什么”
microsoft/graphrag GraphRAG 官方 实体关系图 RAG 的参考实现
abhinav-kimothi/A-Simple-Guide-to-RAG 入门书配套 完全新手入门

2.5 记忆系统:完整工程指南

如果 RAG 解决”外部知识库怎么塞进 context”,记忆系统解决”agent 自身经验怎么塞进 context”。这两件事在工程上有相似的部分(都是检索 + 注入 prompt),但有本质差异:

维度 RAG 记忆系统
数据来源 外部静态文档(公司 wiki、PDF) 历史对话、agent 行为、用户偏好
写入触发 索引时一次性 每次交互都可能触发增量写入
数据生命周期 跟着源文档走 有独立的”过期 / 淘汰 / 摘要”逻辑
隔离粒度 全局或部门级 必须 per-user / per-agent / per-session
时效性 通常分钟到天 可能秒级(“用户刚才说的”)
一致性 强(一份 ground truth) 弱(事实会变、有矛盾)

2.5.1 为什么仅靠 context window 不够

“上下文窗口已经 1 M 了,还需要记忆系统吗?” 是个真实问题。三个理由:

  1. 成本与延迟:1M context 一次推理比同等任务的 RAG 显著更慢更贵(按 [41] 单一来源估算约 30-60× 慢、~1000× 贵,具体倍率因模型和任务差异很大,建议在自家场景实测)
  2. Lost-in-the-Middle:把所有历史塞进 context,关键事实被中间黑洞吞掉(U 形召回)
  3. 跨 session 持久化:context window 是单次推理生命周期,session 结束即销毁;记忆系统要跨天、跨周、跨设备

记忆系统本质上是 “把过去的全部经验变成一个可检索的小数据库,每次推理只检索最相关的几条注入 context”——把”全部输入到模型”换成”模型按需检索”。

2.5.2 记忆类型的工程映射

借自认知心理学的分类,每一类对应不同的工程实现:

记忆类型 认知含义 工程实现 存储后端 写入时机 检索时机
Working Memory(工作) 当前任务的”草稿纸” 当前 context window LLM 内部 KV cache 每个 token 每个 token
Short-term(短期) 最近 N 轮对话 滚动 message buffer 内存 / Redis 每轮 每轮全注入
Episodic(情景) “什么时候发生了什么” 带时间戳的对话片段 向量库 + 时间索引 会话结束 / 重要事件 按主题 + 时间窗
Semantic(语义) 关于世界 / 用户的稳定事实 KV pair 或图节点 图库 / KV 库 / SQL 抽取出新事实时 按实体名
Procedural(程序) “这类任务怎么做” 可执行 skill / 流程脚本 文件系统 / skill registry 任务成功后总结 按任务类型
Long-term(长期) 跨 session 的所有上述类型 上面几种的合集 通常多种后端组合 异步 / 后台 worker 按需

关键洞察:一个生产级 agent 的”记忆”通常不是单一系统,而是上面 6 类的不同子集组合。Letta(MemGPT)把短期 + 语义放 in-context(Core Memory),把情景放向量库(Recall Memory),把外部知识放另一个向量库(Archival Memory)——这是 OS-inspired 设计的经典三层。

2.5.3 记忆系统的核心架构组件

任何记忆系统拆开都是这 5 个组件:

                    ┌──────────────────────────┐
                    │  Conversation / Action   │
                    │  (raw events)            │
                    └────────────┬─────────────┘
                                 │
           ┌─────────────────────▼──────────────────────┐
           │  ① Extractor(抽取器)                    │
           │  LLM 把原始事件抽成结构化"记忆事实"       │
           │  e.g. "用户偏好暗色主题"                  │
           └─────────────────────┬──────────────────────┘
                                 │
           ┌─────────────────────▼──────────────────────┐
           │  ② Writer(写入器)                       │
           │  去重 / merge / conflict resolution        │
           │  embed + 入库                             │
           └─────────────────────┬──────────────────────┘
                                 │
                       ┌─────────▼─────────┐
                       │  Storage Backend  │
                       │  vector / graph / │
                       │  KV / SQL / file  │
                       └─────────┬─────────┘
                                 │
           ┌─────────────────────▼──────────────────────┐
           │  ③ Retriever(检索器)                   │
           │  query → top-K 相关记忆                  │
           │  hybrid: semantic + keyword + graph       │
           └─────────────────────┬──────────────────────┘
                                 │
           ┌─────────────────────▼──────────────────────┐
           │  ④ Forgetter(遗忘器)                   │
           │  按 LRU / 重要性 / 时间衰减 淘汰          │
           └─────────────────────┬──────────────────────┘
                                 │
           ┌─────────────────────▼──────────────────────┐
           │  ⑤ Compressor(压缩器)                  │
           │  老记忆摘要、冲突合并、知识图重建          │
           └────────────────────────────────────────────┘

每个组件都有独立的工程决策点。下面 §2.5.4-2.5.8 逐个展开。

2.5.4 存储后端选型

记忆系统的存储后端不是”选一个”而是”选哪几个组合”。常见选项:

后端 强项 弱项 典型用法
向量库(Qdrant / Weaviate / Pinecone / pgvector) 语义相似检索 不擅长精确匹配 / 关系查询 情景记忆主存储
图库(Neo4j / FalkorDB / Memgraph) 实体关系 / 多跳查询 / 时序 部署复杂 / 检索慢 语义记忆 + 关系 + 时序
KV 库(Redis / DynamoDB) 极低延迟 / 简单 无语义检索 短期 working memory + 缓存
关系型(Postgres + pgvector / Tiger Data) 事务性 / SQL filter / 一站式 大规模向量索引调优麻烦 中小规模一体化
文件系统(Anthropic Memory Tool) 简单 / 可审计 / agent 自管 检索能力依赖 agent 自己 grep Claude 生态原生
专用记忆 SaaS(Mem0 Cloud / Zep Cloud / Supermemory) 零运维 锁定 / 数据出域 创业 MVP

选型决策树

你的记忆主体是什么?
│
├─ 主要是用户偏好 / 实体事实 → 语义记忆为主
│   ├─ 关系密集("A 是 B 的同事"、"X 公司 2024 收购 Y")→ Zep(Graphiti 图)
│   └─ 关系简单 → Mem0(vector + 可选 graph)
│
├─ 主要是对话历史 + 长跑任务 → 情景记忆为主 + agent 自管
│   └─ → Letta(Core + Recall + Archival 三层)
│
├─ 主要是 agent 行为可审计 / 可回滚
│   └─ → Anthropic Memory Tool(filesystem,可 git 管理)
│
└─ 已用 Redis / Postgres,不想加新栈
    ├─ 用 Redis Agent Memory Server
    └─ 用 Postgres + pgvector + Tiger

实测性能(2026)

2.5.5 写入流程:抽取 + 去重 + 关联

记忆不是简单地把对话原文存下来,而是经过 LLM 抽取的”事实”。Mem0 v2 的写入算法(论文 [19])拆解:

1. Retrieve 相关记忆(top-10 semantically similar)
2. LLM 单次调用抽取新事实(Add-only, 不 Update / Delete)
   └─ Prompt: "Given new conversation + existing memories,
              extract NEW facts that should be remembered.
              Return JSON list."
3. Embed + MD5 hash 去重
4. 实体抽取 + 链接(用于 graph memory)
5. 批量写入 vector store + entity collection

关键设计选择:

写入伪代码(自实现版):

def write_memory(user_id, conversation_chunk):
    # 1. 检索相关历史
    relevant = vector_store.search(
        embed(conversation_chunk), filter={"user_id": user_id}, k=10
    )

    # 2. LLM 抽取
    extracted = llm.extract_facts(
        prompt=f"对话:{conversation_chunk}\n现有记忆:{relevant}\n新事实?",
        schema={"facts": [{"text": str, "category": str, "confidence": float}]},
    )

    # 3. 过滤低置信度
    facts = [f for f in extracted["facts"] if f["confidence"] > 0.7]

    # 4. 去重
    new_facts = []
    for f in facts:
        h = hashlib.md5(f["text"].encode()).hexdigest()
        if not vector_store.exists(hash=h, user_id=user_id):
            new_facts.append({**f, "hash": h, "user_id": user_id, "ts": now()})

    # 5. 写入
    vector_store.add_batch(new_facts)

2.5.6 检索流程:多信号融合

仅用 embedding 检索召回会漏,2026 年生产级记忆系统都用 multi-signal fusion——和 RAG 的混合检索是同一思路。Mem0 v2 的检索:

Query → preprocess(lemmatize + entity 抽取)
      ↓
   ┌──┴──────────────────────────┬────────────────────────┐
   ▼                             ▼                        ▼
Semantic(vector cosine)    BM25 keyword             Entity match
   │                             │                        │
   └──────────────┬──────────────┴────────────────────────┘
                  ▼
            Score Fusion (RRF or weighted)
                  ▼
           Top-K Memories → 注入 system prompt

进阶技术:

2.5.7 淘汰策略:6 种 Forgetting Policies

记忆爆炸是真实问题。MaRS 架构(arXiv 2603.07670)形式化了 6 种主流淘汰策略:

策略 公式 / 规则 适用
FIFO 按插入时间 最简单,几乎不用(删了重要老事实)
LRU 按最后访问时间 desktop agent 默认起点
Priority Decay score = w₁·prior + w₂·recency + w₃·frequency 通用最佳 baseline
Reflection-Summary 老的 N 条 → LLM 摘要成 1 条 配合 LRU 用,长跑 agent 必备
Random-Drop 随机删 仅作 baseline 对比
Hybrid LRU + Priority Decay + Summary 联用 生产推荐

实战配方(Letta 与 Mem0 都接近这个思路):

def evict_if_needed(memories, max_count=10000):
    if len(memories) <= max_count:
        return memories

    # 1. 计算每条记忆的"保留分数"
    for m in memories:
        m.keep_score = (
            m.importance * 0.4              # 写入时打的重要性
            + recency_score(m.last_access) * 0.3   # 越近越高
            + access_frequency(m) * 0.2     # 被引用次数
            - age_penalty(m.created) * 0.1  # 越老越低
        )

    # 2. 按分数排序,淘汰末尾 N 条
    memories.sort(key=lambda m: m.keep_score, reverse=True)
    to_evict = memories[max_count:]

    # 3. 老记忆不直接删,先尝试摘要
    summary_chunks = group_by_topic(to_evict, n=10)  # 10 条一组
    for chunk in summary_chunks:
        summary = llm.summarize(chunk)
        memories.append(Memory(
            text=summary, importance=avg([m.importance for m in chunk]),
            ts=min([m.created for m in chunk]),
            sources=[m.id for m in chunk],
        ))

    # 4. 真正删除原始 N 条
    delete_batch([m.id for m in to_evict])

    return memories

经验法则:

2.5.8 四大主流系统深度剖析

A. Mem0 — 通用记忆层(最易接入)

架构:5 个支柱(论文 [19] 与 Mem0 docs 总结):

  1. LLM-Powered Fact Extraction:单 LLM 调用把对话转结构化事实
  2. Vector Storage:默认 Qdrant,可换 24+ 后端(Chroma / Pinecone / pgvector / MongoDB / Weaviate / OpenSearch / 等)
  3. Graph Storage(可选):Neo4j / Neptune / FalkorDB / Memgraph,存实体关系
  4. Hybrid Retrieval:semantic + BM25 + entity matching 并行打分 + RRF 融合
  5. Production Infrastructure:批处理、MD5 去重、用户/会话/agent 三层 hierarchy

注:上述 5 项是按工程职责整理的检查清单,不是 Mem0 / Letta / Zep 任何一家的官方架构图。Mem0 论文实际描述的是 Add/Update/Delete/NoOp 四种操作 + LLM 抽取 pipeline;Letta 用 Core/Recall/Archival 三层;Zep 用 Episodic/Entity/Edge 三类节点。

性能(v2 算法,按 Mem0 论文 arXiv:2504.19413 报告口径):在 LoCoMo / LongMemEval 等长对话记忆 benchmark 上显著优于 RAG / full-context baseline(具体提升幅度按子任务和指标维度差异较大,详见原论文表 4-5);抽取延迟降一半。

完整代码示例:

from mem0 import Memory

# 初始化(用 Qdrant + Neo4j + OpenAI)
config = {
    "vector_store": {
        "provider": "qdrant",
        "config": {"host": "localhost", "port": 6333},
    },
    "graph_store": {  # 可选
        "provider": "neo4j",
        "config": {"url": "bolt://localhost:7687",
                   "username": "neo4j", "password": "..."},
    },
    "llm": {
        "provider": "openai",
        "config": {"model": "gpt-4o-mini"},
    },
    "embedder": {
        "provider": "openai",
        "config": {"model": "text-embedding-3-small"},
    },
}
m = Memory.from_config(config)

# 写入:从对话自动抽事实
m.add(
    messages=[
        {"role": "user", "content": "我是 Liang,住北京,做 AI 工程师,我喜欢冷咖啡"},
        {"role": "assistant", "content": "记下了"},
    ],
    user_id="liang_001",
)
# Mem0 自动:提取 ["用户名是 Liang", "住北京", "职业 AI 工程师", "偏好冷咖啡"]

# 检索
memories = m.search(query="他喝什么咖啡?", user_id="liang_001", limit=3)
# [{"memory": "用户偏好冷咖啡", "score": 0.89}, ...]

# 注入下次 prompt
context = "\n".join([f"- {m['memory']}" for m in memories])
prompt = f"已知用户信息:\n{context}\n\n用户:今天给我推荐什么饮料?"

AWS 推荐生产架构:Mem0 + ElastiCache for Valkey(短期 + 缓存)+ Neptune Analytics(图)+ OpenSearch(向量)。

适合:通用 chatbot、客服、个人助手——“5 行代码加记忆”的场景。

B. Letta(前 MemGPT)— OS-Inspired,Agent 自管

架构:把 LLM 当 OS,记忆分三层(核心创新):

层 名称 位置 容量 谁能改
L1 Core Memory(核心) In-context(system prompt 里) 固定(如 4 KB) agent 自己用 tool
L2 Recall Memory(回忆) 外部 DB 完整对话历史 自动
L3 Archival Memory(档案) 向量库 无限 agent 自己用 tool

Core Memory 是关键创新——它不是数据库而是system prompt 的一部分。Agent 可以用 core_memory_append / core_memory_replace 工具像编辑文件一样改它,下一次推理这些内容自动出现在 context 头部。这等价于让 agent “持续编辑自己的人设”。

6 个内置工具(agent 自管内存):

工具 作用
send_message 给用户发消息
core_memory_append 往 in-context 内存追加新 fact
core_memory_replace 替换 in-context 内存(修正错误 / 更新偏好)
conversation_search 搜历史对话(recall memory)
archival_memory_insert 写入长期档案
archival_memory_search 检索长期档案

完整代码:

from letta_client import Letta

client = Letta(base_url="http://localhost:8283")  # 自托管 server

# 创建 agent,定义 core memory blocks
agent = client.agents.create(
    name="my_assistant",
    memory_blocks=[
        {"label": "human", "value": "用户的名字、偏好、当前正在做的事"},
        {"label": "persona", "value": "你是一个简洁、礼貌的助理"},
    ],
    model="anthropic/claude-sonnet-4-6",
    embedding="openai/text-embedding-3-small",
)

# 对话(多轮,每次 Letta 自动管理 context)
response = client.agents.messages.create(
    agent_id=agent.id,
    messages=[{"role": "user", "content": "我叫 Liang,下周要面试"}],
)
# Letta 内部:agent 调用 core_memory_append("human", "用户叫 Liang,下周面试")

# 关掉、重启、明天继续——agent 还记得 Liang 与他的面试
response = client.agents.messages.create(
    agent_id=agent.id,
    messages=[{"role": "user", "content": "帮我准备一下"}],
)
# agent 看 core memory → 知道 Liang 要面试 → 自动反馈

适合:长跑 agent(数天 / 数周)、需要”持久身份”的产品(个性化助理 / AI 教练)、Anthropic Memory Tool 之外的 OSS 替代。

C. Zep(Graphiti)— Temporal Knowledge Graph

核心创新:每条事实带 双时间轴:

架构:3 类节点 + 边

┌────────────────┐  rel  ┌────────────────┐
│  Entity Node   │◀─────▶│  Entity Node   │
│  Alice         │  edge │  TechCorp      │
└───────┬────────┘       └────────────────┘
        │ source                    ▲
        ▼                           │ joined
┌────────────────┐                  │
│ Episodic Node  │──────────────────┘
│ "对话片段"     │  derives
│ T=2024-03-15   │
└────────────────┘

关键能力:当事实变化时(“Alice 2024-06 离职”),Zep 不删除老事实,而是给老 edge 标 valid_to=2024-06,新 edge 标 valid_from=2024-06。查询时可问:

Hybrid 检索:semantic embedding + BM25 + 直接图遍历——无需 LLM 调用,纯索引和图查询,延迟 100-500 ms。

最小代码(Graphiti SDK):

from graphiti_core import Graphiti
from graphiti_core.nodes import EpisodeType

g = Graphiti(uri="bolt://localhost:7687", user="neo4j", password="...")
await g.build_indices_and_constraints()

# 写入(episode = 一段对话或事件)
await g.add_episode(
    name="meeting_2026_03",
    episode_body="Alice 离开 TechCorp,加入 Anthropic 做 research engineer",
    source=EpisodeType.message,
    reference_time=datetime.now(),
)
# Graphiti 自动:抽 entities → 建 nodes → 抽 relations → 建 edges → invalid 旧 edges

# 查询
results = await g.search(query="Alice 现在在哪工作?", limit=5)
# [{"fact": "Alice 现在在 Anthropic", "valid_from": "2026-03", "valid_to": None}, ...]

适合:用户状态会变的场景——CRM、客服、医疗病史、合规审计、法律事实库。

D. Anthropic Memory Tool — Filesystem-as-Memory

2026-04-23 公测发布。设计哲学:把记忆当文件,让 Claude 用熟悉的 bash + code execution 工具读写。

架构:

Claude Agent
    │
    ├─ tool: bash (read/write/grep files)
    ├─ tool: code execution
    └─ tool: memory (mount filesystem)
                │
                ▼
        ┌───────────────────┐
        │  /memories/       │
        │   ├ liang.md      │ ← user profile
        │   ├ tasks/        │
        │   │   ├ today.md  │
        │   │   └ done.md   │
        │   └ playbooks/    │
        │       └ deploy.md │ ← procedural
        └───────────────────┘
            (any backend:
             local fs, S3,
             encrypted, ...)

完整代码(Python SDK,public beta):

from anthropic import Anthropic
from anthropic.lib.tools import BetaAbstractMemoryTool

# 选项 1:默认本地 filesystem 后端
client = Anthropic()
response = client.beta.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=4096,
    tools=[
        {"type": "memory_2026_04_23", "name": "memory"},
        {"type": "bash_2026_04_23", "name": "bash"},
    ],
    messages=[{"role": "user", "content": "记一下:我下周三要去机场,记得提醒我提前 3 小时出发"}],
    extra_headers={"anthropic-beta": "memory-2026-04-23"},
)
# Claude 自动:bash > echo "trip_2026_03_20 ..." > /memories/calendar.md

# 选项 2:自定义后端(S3 / 加密 / 数据库)
class S3MemoryTool(BetaAbstractMemoryTool):
    def __init__(self, bucket):
        self.bucket = bucket
    async def list_files(self, path: str) -> list[str]:
        return list_s3_keys(self.bucket, path)
    async def read_file(self, path: str) -> str:
        return s3_get(self.bucket, path)
    async def write_file(self, path: str, content: str):
        s3_put(self.bucket, path, content)
    # ... delete / move / search 等

早期客户案例(Anthropic 官方公布):

适合:已绑 Claude 生态、需要”agent 像程序员一样管自己的笔记本”、需要审计/版本控制(memory 文件可入 git)的场景。

E. 其他值得关注

横向对比矩阵(2026)

维度 Mem0 Letta Zep / Graphiti Anthropic Memory Tool
数据模型 facts (vector + graph) core / recall / archival temporal KG filesystem
Agent 主动性 passive(auto extract) agent 自管 tool passive agent 自管 tool
多模型支持 16+ LLM 任意 任意 仅 Claude
后端选择 24+ vector + graph Postgres / 内置 Neo4j / FalkorDB filesystem 任意
时序追踪 弱(基于 timestamp) 弱 强(双时间轴) 文件 mtime
关系建模 中(可选 graph) 弱 强(图原生) 弱
上手成本 5 行 50 行 30 行 10 行
开源 ✓ ✓ ✓(Graphiti) ×
中文支持 配中文 embedder 即可 同 同 原生
论文 / 数字 LoCoMo +20pt MemGPT 论文 arXiv 2501.13956 Netflix 错误率 -97%

2.5.9 多租户隔离:生产必修课

绝大多数 SaaS 必踩的坑:记忆系统跨用户泄露。两层防御:

层 1:写入与查询都强制 user_id

# 错误示范(会跨用户混)
m.add(messages=msgs)  # ❌ 没 user_id

# 正确:强制 user_id 必填
m.add(messages=msgs, user_id=request.user.id)
m.search(query=q, user_id=request.user.id, ...)  # 检索也必须带

# 强制约束(包一层):
class TenantSafeMemory:
    def __init__(self, m, user_id):
        self.m = m; self.uid = user_id
    def add(self, messages, **kw):
        return self.m.add(messages=messages, user_id=self.uid, **kw)
    def search(self, query, **kw):
        return self.m.search(query=query, user_id=self.uid, **kw)

层 2:存储后端层 namespace / collection / DB 隔离

方案 隔离强度 性能 适合规模
共享 collection + user_id filter 弱(依赖应用层) 好 < 1k 用户
每用户一个 collection 强 中(collection 数有上限) 1k - 10k
每用户一个 namespace(Pinecone / Turbopuffer) 强 好 10k - 1M+
每租户一个独立 DB instance 最强(物理隔离) 中 大客户 / 合规

Turbopuffer 等专门为多租户设计的向量库可以撑百万 namespace,单租户内部数据严格隔离。

层 3:审计 + GDPR 合规

# 审计:所有跨用户的访问立刻报警
@audit_log(level="critical")
def admin_search_all(query):
    return vector_store.search(query=query, no_user_filter=True)

# GDPR "被遗忘权"
def forget_user(user_id):
    vector_store.delete_all(user_id=user_id)
    graph_store.delete_subgraph(user_id=user_id)
    redis.delete_pattern(f"user:{user_id}:*")
    audit_log(f"user {user_id} memory wiped at {now()}")

2.5.10 记忆 vs RAG:边界与协同

实战中记忆和 RAG 经常并存,不冲突:

User Query
    │
    ├──▶ RAG(公司文档 / 产品手册 / 政策) → 通用知识
    │
    └──▶ Memory(用户偏好 / 历史交互 / agent 经验) → 个性化

       两路检索结果合并 → 注入 system prompt → LLM

典型生产 prompt 结构:

你是 ACME 公司客服。

# 用户档案(来自 Memory)
- 姓名:Liang
- 历史订单:3 单(2 单已完成)
- 偏好:电邮通知优先

# 相关知识(来自 RAG)
[政策片段] 30 天内可全额退款
[FAQ 片段] 退款流程通常 3-5 工作日

# 当前对话
用户:我想退订单 #12345

2.5.10.5 Progress File:长跑 Agent 的”git memory”

vector memory / KV memory 解决”事实”,但长跑 coding agent / research agent 还需要一种结构化、人类可读、可 diff 的”工作进度”记忆 —— 这就是 progress file(Augment Code、Claude Code、Devin 都在用的事实标准)。

典型 schema(Markdown,常见命名 PROGRESS.md / CONTEXT.md / .agent/state.md):

---
task_id: refactor-auth-2026-05-03
started: 2026-05-03T09:12Z
last_update: 2026-05-03T11:48Z
status: in_progress
parent_branch: main
worktree: /Users/x/dev/repo/.worktrees/refactor-auth
---

## Goal
迁移 session-based auth 到 JWT,保持向前兼容 30 天

## Decisions made
- [2026-05-03 09:30] 采用 RS256 而非 HS256(多服务部署需要公钥分发)— 见 ADR-007
- [2026-05-03 10:15] 旧 session cookie 保留 30 天,双写策略

## Files touched
- `src/auth/jwt.ts` (new)
- `src/auth/middleware.ts` (modified, +120/-45)
- `src/auth/session.ts` (deprecated, kept for 30d)

## Open questions
- [ ] refresh token 是否需要黑名单?需问 @security-team
- [ ] mobile 客户端最低支持版本是否覆盖 JWT 解析?

## Next steps
1. 写 jwt.test.ts 单元测试覆盖签 / 验 / 过期 / tampering
2. 在 staging 跑 24h 双写,看 metric
3. 文档 docs/auth-migration.md

为什么这种格式而不是 vector memory:

关键工程点:

  1. 写入时机:每个”决策点”或”工具调用结果”后追加,不要等到 session 结束(断电会丢)
  2. Merge 冲突:多 agent 并发写要用 append-only sections + 时间戳;或拆成 per-agent 子文件
  3. OOM / token 爆炸:定期 compaction —— 把超过 N 天的 decision 折叠成摘要保留在文件头
  4. 与 vector memory 协作:progress file 当 source of truth,vector memory 只索引指向 progress file 的 chunk
  5. 失败恢复 protocol:agent 启动时先 git status + git log -5 + cat PROGRESS.md,三件套是恢复”我是谁、上次到哪、下一步”的最低成本方式

参考:Anthropic Memory Tool、Augment Code 工程博客、Claude Code 的 .claude/ 目录、Cursor 的 .cursorrules、Codename Goose 的 goose hints。

2.5.11 失败模式与对策

失败模式 表象 对策
记忆爆炸 记 1000 条后检索全是噪声 LRU + 摘要(§2.5.7)
过期记忆 “我喜欢冷咖啡”过期但仍生效 Zep 时序 / 写入时检测冲突 / 用户主动覆盖
幻觉记忆 LLM 把没说过的事抽成事实 抽取时加 confidence 阈值 + 用户可审计
跨用户泄露 A 的偏好被注入 B 的 prompt 强制 user_id(§2.5.9)
冷启动 新用户记忆为空,agent 显得”陌生” 显式 onboarding + 通用画像兜底
隐私 / 合规 GDPR / CCPA 要求删除用户数据 forget_user API 全栈级联删除
抽取成本 每轮调 LLM 抽事实,token 成本翻倍 importance gate 跳过无关对话 + 批处理 N 轮
检索召回低 LLM 看不到关键事实 加 BM25 + entity match(§2.5.6 multi-signal)
记忆腐坏(memory corruption) 见下面专栏 定期一致性检查 + ground truth 校准 + ttl

Memory Corruption 深度剖析

”记忆腐坏”是 stateful agent 部署超过几周后必然出现的失败模式,但很少被早期工程团队预防。Anthropic / Letta / Mem0 团队公开过的 4 类典型 corruption:

腐坏类型 例子 根因 防御
过期事实(Stale fact) “用户在杭州” → 三个月后已搬到上海,但旧记忆仍在 top-K 没有 TTL、没有”事实新鲜度”的写入时检测 Zep 风格 valid_from / valid_to;写入时检测同实体的旧事实并标 invalid
矛盾事实(Contradiction) 一条说”用户素食”,另一条说”用户喜欢牛排” 多 session 抽取没有跨 session 一致性检查 写入前跑”该用户已有事实 + 新事实”的矛盾检测 LLM;或定期 reconciliation job
幻觉事实(Hallucinated fact) LLM 抽取时从对话里”推理”出用户没明说的偏好 抽取 prompt 没限定”只抽显式陈述” 抽取时返回 evidence span(原对话引用);无 evidence 不落库
人格漂移(Persona drift) 长期 self-update memory 导致 agent 自我描述与初始 system prompt 严重不一致 agent 自管 memory + 没有 freeze section core memory 区分 immutable / mutable 段;mutable 段定期 reset 到 baseline

防御工程实践(按 ROI 排序):

  1. TTL + 时序字段:每条记忆带 created_at / valid_from / valid_to,检索时按当前时间过滤
  2. 写入时矛盾检测:新事实 vs 同实体已有 top-3 事实,跑一次 LLM”是否矛盾”判断,矛盾时人工或时间戳决胜
  3. Evidence-required 抽取:抽取 prompt 强制返回 (fact, evidence_quote, confidence),confidence < 0.7 不落库
  4. 每周 reconciliation job:随机抽样 1% 记忆跑 LLM 对比真实对话,发现腐坏率超阈值就触发清理
  5. 可解释 + 可审计:用户可以看到”agent 关于我的记忆”原文 + 来源,并一键删错

2.5.12 GitHub 实战资源(记忆系统专题)

资源 类型 推荐用法
mem0ai/mem0 官方仓库 通用记忆层,5 行接入
letta-ai/letta 官方仓库 OS-inspired stateful agent
getzep/graphiti 官方仓库 Temporal KG 引擎(Zep 内核)
getzep/zep 官方仓库 完整 Zep 服务(基于 Graphiti)
redis/agent-memory-server 官方仓库 Redis 一站式 agent memory
topoteretes/cognee 官方仓库 图原生 + ontology
supermemoryai/supermemory 官方仓库 跨厂商记忆 SDK
Anthropic Memory Tool 文档 官方文档 https://platform.claude.com/docs/en/agents-and-tools/tool-use/memory-tool

论文必读:


2.6 上下文管理策略:把 context window 当作稀缺资源

2.6.1 为什么需要”管理”

Context window 即使到了 1M tokens,仍然是稀缺资源——三个原因:

  1. 成本:1 M token prompt 一次 ~$1(Claude Opus),一天调几千次就破产
  2. 延迟:1 M token prefill ~30 秒,用户体验崩塌
  3. 质量:Lost-in-the-Middle,多事实场景召回降到 ~60%(§2.2.3)

所以生产级 agent 不是”塞满 1 M”,而是精打细算:每个 token 都该有理由出现在 prompt 里。

2.6.2 Context 的”分区”模型

把 context window 看作有逻辑分区的固定空间,每个分区有不同优先级和淘汰策略:

┌─────────────────────────────────────────────────────┐
│ ┌─────────────────────────────────────────────────┐ │
│ │ [固定区] System Prompt + Persona                │ │  ← 永不淘汰
│ │   - 人设、约束、风格、角色                       │ │     ~500-2000 tokens
│ └─────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ [可变高优] Memory(注入的用户/agent 记忆)       │ │  ← 检索 + 重排
│ │   - 用户档案、偏好、近期事件                     │ │     ~500-3000 tokens
│ └─────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ [可变高优] RAG 检索结果                          │ │  ← top-K + reranker
│ │   - 公司知识、文档片段                           │ │     ~2000-8000 tokens
│ └─────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ [可变中优] 工具定义 schema                       │ │  ← 仅放当前可能用到的
│ │   - tool descriptions + signatures               │ │     ~500-3000 tokens
│ └─────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ [可变中优] 历史对话                              │ │  ← 滑窗 + 摘要
│ │   - 最近 N 轮 + 早期摘要                         │ │     可变
│ └─────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ [低优 / 易淘汰] 工具调用结果                     │ │  ← 旧的截断或摘要
│ │   - tool outputs,往往最长                       │ │     可变
│ └─────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ [尾部] 当前 user message                         │ │  ← 永远是最后
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
   头部                                          尾部
   ↑ primacy bias                       recency bias ↑
                  Lost-in-the-Middle 黑洞

配额分配建议(按业务类型):

业务类型 System Memory RAG Tools 历史 工具结果 User
客服 chatbot 10% 15% 30% 5% 20% 10% 10%
Coding agent 5% 5% 40% 10% 10% 25% 5%
研究 agent 5% 10% 30% 5% 10% 35% 5%
个人助理 15% 30% 10% 10% 25% 5% 5%

实战经验:任何分区超过 50% 都是设计有问题的信号。

2.6.3 上下文管理的 5 类常见动作(综合 Anthropic / LangChain 实践)

业界两个权威来源给的拆法都不是”5”——Anthropic Effective Context Engineering [6] 给 compaction / structured note-taking / sub-agent architectures 三类策略;LangChain Context Engineering for Agents [7] 给 write / select / compress / isolate 四类。下面 5 个动作是把两家的拆法合并展开,便于工程实施时逐项检查;不是业界标准 taxonomy。

动作 1:优先级排序(Priority Ranking)

利用 primacy + recency bias,把最重要的放头尾,次要的放中间:

def assemble_context(system, memories, rag_chunks, tools, history, current_user_msg):
    return [
        system,                              # 头部:永远在前
        *high_priority(memories),            # 头部 2:用户身份与偏好
        *high_priority(rag_chunks, top=3),   # 头部 3:最相关的 3 个片段
        *medium_priority(history),           # 中部:历史对话(可被中部黑洞稀释)
        *low_priority(rag_chunks, rest=True),# 中部:剩余 RAG 片段
        *truncate(tool_results),             # 尾部 -2:截断的工具结果
        tools_definitions,                    # 尾部 -1:tool schema
        current_user_msg,                    # 尾部:当前消息
    ]

动作 2:动态裁剪(Trimming)

定时检查 token 使用率,超阈值触发:

def trim_if_needed(context, max_tokens=180_000, target=140_000):
    current = count_tokens(context)
    if current < max_tokens: return context

    # 优先淘汰:旧的工具结果
    context = truncate_old_tool_results(context, keep_recent=5)
    if count_tokens(context) <= target: return context

    # 其次:早期对话压缩成摘要
    context = summarize_old_history(context, summary_length=500)
    if count_tokens(context) <= target: return context

    # 再次:删除非 top-K 的 RAG 片段
    context = drop_low_score_rag(context, threshold=0.6)

    return context

动作 3:摘要压缩(Summarization)—— /compact 实现

Claude Code 的 /compact 命令把当前长对话压成摘要 + 关键 facts,回收 token:

def compact(messages, llm):
    # 1. 抽取关键事实(不能丢)
    facts = llm.invoke(f"""
    Extract critical facts from this conversation that MUST be preserved:
    {messages}
    Return as bullet list. Include: user requirements, decisions made, code locations,
    pending tasks, open questions.
    """)

    # 2. 写一段精简摘要
    summary = llm.invoke(f"""
    Summarize this conversation in <500 words. Focus on:
    - What problem we're solving
    - What approach we took
    - Current progress
    {messages}
    """)

    # 3. 重置 context
    new_context = [
        SystemMessage(original_system),
        SystemMessage(f"# Compressed conversation context\n\n{summary}\n\n# Key facts\n{facts}"),
        # 保留最近 3 轮原文(细节在新对话里有用)
        *messages[-3:],
    ]
    return new_context

关键点:摘要必须 LLM 生成(rule-based 抽取会丢上下文),但 LLM 摘要本身要 prompt 明确要求”保留代码位置/数字/决定”等关键信息。

动作 4:Scratchpad 分离

ReAct 等推理 agent 在思考时会产生大量 thought / observation,不应该污染对外 context:

class AgentMemory:
    def __init__(self):
        self.public_messages = []   # 用户和 agent 互发
        self.scratchpad = []        # agent 内部草稿(thought / 中间 tool result)

    def get_llm_context(self):
        # 给 LLM 看的:public + 最近 5 步 scratchpad(防止失忆)
        return self.public_messages + self.scratchpad[-5:]

    def get_user_facing(self):
        # 给用户看的:仅 public
        return self.public_messages

LangGraph 的 state 机制 / Letta 的 core vs recall 都是这个思路的产品化。

动作 5:工具结果裁剪

工具返回的 JSON 经常爆长(比如一次 SQL 查询 1000 行)。两层过滤:

def clip_tool_result(tool_name, result, current_step, total_steps):
    # 1. 大结果直接截断
    s = str(result)
    if len(s) > 4000:
        s = s[:2000] + f"\n... [truncated {len(s)-2000} chars] ...\n" + s[-500:]

    # 2. 老的 tool result(>3 步前)摘要化
    if total_steps - current_step > 3:
        s = summarize_tool_result(s, max_length=300)

    return s

2.6.4 三种”压缩”路径对比

方法 压缩比 信息损失 延迟 适用
简单截断 中 高 0 工具结果 / 兜底
rule-based 抽取(regex / structured) 中 低 0 已知格式(JSON / 表格)
LLM 摘要(/compact) 高 低 1-3 秒 长对话 / 高价值历史
Anchored Iterative Summary(2026 SOTA) 高 最低 3-10 秒 极长任务(数小时 agent)

何时触发 compaction(决策信号)

Compaction 不是”context 满了再压”,否则 LLM 已经被噪声污染。生产实践用多信号触发:

触发信号 阈值(参考) 适用场景
Token 占用率 > 70% max_tokens(如 180K / 256K = 70%) 通用兜底,最常用
历史轮次 > 50 轮对话 长对话客服 / 陪伴产品
工具结果累积 单步 tool result > 4000 tokens 或累积 > 30K coding agent / data agent
质量信号下滑 最近 5 轮 user 满意度 / verifier 通过率下降 有 reward signal 的产品
任务边界 一个子任务完成(agent 自己 declare) 长跑 multi-step agent
时间衰减 历史消息 > 30 分钟无引用 多任务并行 agent
Anthropic Auto-Compact 信号 Claude API usage.context_window_remaining < 20% 用 Claude 的产品直接读官方信号

关键原则(Anthropic Effective Context Engineering 2026):

  1. Compaction 是有损的,能避免就避免(先做 §2.6.3 的动作 1-5)
  2. 永远保留 最后 N 轮原始对话(N=3-5),LLM 需要近端 raw 信号判断”刚刚发生了什么”
  3. 摘要要保留 decision、open question、未完成子任务、代码 / 文件路径 这些”指针”,而不是讲故事
  4. 摘要后立刻 evaluator 跑一遍,确认关键事实没丢;丢了就回滚到 raw + 升级到更强压缩策略
  5. Compaction 本身要被 trace —— 哪些被丢、压缩前后的 token diff、是否触发回滚,都进 observability

2.6.5 实战配方:完整 Context Manager 类

class ContextManager:
    def __init__(self, max_tokens=180_000, target_tokens=140_000):
        self.max = max_tokens
        self.target = target_tokens

    def assemble(self, system, memories, rag, tools, history, user_msg):
        ctx = self._assemble_by_priority(system, memories, rag, tools, history, user_msg)
        if count_tokens(ctx) > self.max:
            ctx = self._compress(ctx)
        return ctx

    def _assemble_by_priority(self, ...):
        # 见 §2.6.3 动作 1

    def _compress(self, ctx):
        # 顺序尝试 5 种压缩,越早越轻:
        for fn in [
            lambda c: drop_low_score_rag(c, threshold=0.6),
            lambda c: clip_tool_results(c, keep_recent=5),
            lambda c: summarize_old_history(c, length=500),
            lambda c: drop_low_priority_memory(c, keep=10),
            lambda c: hard_truncate_history(c, keep_recent=3),
        ]:
            ctx = fn(ctx)
            if count_tokens(ctx) <= self.target:
                return ctx
        return ctx  # 实在压不下,让 LLM 自己拒绝

    def metrics(self, ctx):
        # observability:每次返回 dict 让 dashboard 跟踪每分区占比
        return {
            "total": count_tokens(ctx),
            "system_pct": count_tokens(ctx[0]) / count_tokens(ctx),
            "rag_pct": ...,
            "history_pct": ...,
            "tool_results_pct": ...,
        }

把 metrics() 接进 Langfuse / LangSmith,能在 dashboard 看到”哪类内容在吃 context 配额”——这是诊断 agent 漂移最实用的工具。

2.6.6 Prompt / Context Caching:2026 年最大 cost 杠杆

所有现代 LLM provider 都支持 prompt caching——把”prompt 前缀”在 KV cache 层缓存起来,下次相同前缀复用。这是 2025-2026 年单次最大的 cost 优化机会,最高 90% 折扣。

三大 provider 实现对比

Provider 触发方式 命中折扣 最小命中长度 TTL 写入
Anthropic 显式(cache_control 标记) 90%(cached input $0.30 vs base $3.00 / Sonnet) 1024 tokens(Sonnet)/ 2048(Haiku) 5 min(默认)/ 1h(付费) 1.25× base
OpenAI 自动(≥1024 token prefix 自动缓存) 50-90%(视模型) 1024 tokens 5-10 min 0(免费写)
Google Gemini 隐式(2.5+ 默认开)+ 显式 API 隐式约 50% / 显式约 75% 4096 tokens 默认 1h 按存储付费
AWS Bedrock 全 provider 转译 同各 provider 同 同 同

实证(ProjectDiscovery 公开数据):把 prompt caching 接好后,LLM 月账单降 59-70%。学术研究(arXiv 2601.06007)跑 long-horizon agent 任务,API cost 降 41-80%、TTFT 降 13-31%。

什么 prompt 适合缓存

按”复用频率 × 长度”打分:

内容类型 适合缓存?
System prompt + persona ★★★ 强烈推荐
大量 few-shot examples ★★★
工具定义 schema(10+ tools) ★★★
RAG 检索的固定文档(如 SLA / 政策手册) ★★
会变的对话历史 ✗ 别缓存(缓存击穿)
每次都不同的 user query ✗

经验法则:prefix 重复率 > 50% 的就缓存,否则别。

Anthropic 显式缓存代码

from anthropic import Anthropic

client = Anthropic()

# system + tools + 大段 RAG 都加 cache_control
response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    system=[
        {
            "type": "text",
            "text": "你是 ACME 公司客服,遵循以下规则...",  # 长 system
            "cache_control": {"type": "ephemeral"},          # ★ 标记为可缓存
        },
        {
            "type": "text",
            "text": KB_KNOWLEDGE_BASE,  # 100K token 的知识库
            "cache_control": {"type": "ephemeral"},
        },
    ],
    tools=[
        {"name": "search", "description": "...", "input_schema": {...},
         "cache_control": {"type": "ephemeral"}},
    ],
    messages=[
        {"role": "user", "content": user_query},  # 这部分不缓存
    ],
)

# 看 cache 命中
print(f"Cache read: {response.usage.cache_read_input_tokens}")
print(f"Cache write: {response.usage.cache_creation_input_tokens}")
print(f"Regular input: {response.usage.input_tokens}")

# Cost 计算
cost = (
    response.usage.cache_read_input_tokens * 0.30 / 1e6        # 命中超便宜
    + response.usage.cache_creation_input_tokens * 3.75 / 1e6   # 写入贵 1.25×
    + response.usage.input_tokens * 3.00 / 1e6                  # 普通输入
    + response.usage.output_tokens * 15.00 / 1e6                # 输出
)

Cache 命中的几个关键约束

  1. 必须严格前缀匹配:从开头到 cache_control 标记位置必须完全一致——多一个空格都 miss
  2. 顺序敏感:把固定的(system / tools / RAG)放前,可变的(user message)放后
  3. TTL 短:默认 5 min,意味着 5 分钟内没第二次调用就白缓存了——适合”高 QPS 同一系统 prompt”场景
  4. Cache write 也付费:第一次写入 1.25×,所以至少要被命中 2 次才划算

显式 vs 自动 caching 选型

“Don’t Break the Cache”:agent 长任务的关键

agent 跑 long-horizon 任务时,prompt 是”前缀(系统)+ 不断追加的对话历史”。追加新内容不破坏前缀缓存,所以前缀部分一直命中:

Round 1: [system] [user1]                          → write cache(system)
Round 2: [system] [user1] [bot1] [user2]           → cache HIT 前缀,付钱仅 [bot1][user2]
Round 3: [system] [user1] [bot1] [user2] [bot2] [user3] → cache HIT 更长前缀
...

反面:如果你在中间插入 / 修改 / 删除任何内容(如 RAG 重新检索把不同 chunk 塞进 system),cache 直接失效,下一次又要全付费。

agent 设计的隐藏 best practice:把”会变的内容”放尾部,前缀永远只追加不修改。

监控 cache 效果

# Langfuse 把 cache metrics 也记下来
@observe(metadata={"cache_strategy": "anthropic_explicit"})
def my_agent_call(query):
    response = client.messages.create(...)
    langfuse_context.update_current_observation(
        usage={
            "cache_read": response.usage.cache_read_input_tokens,
            "cache_write": response.usage.cache_creation_input_tokens,
            "regular_input": response.usage.input_tokens,
            "output": response.usage.output_tokens,
        },
    )
    return response

dashboard 关注:


2.7 MCP / A2A 协议生态

2.7.1 为什么需要 MCP:解决”M×N 集成噩梦”

把工具和数据源接入 LLM 长期是脏活:

数学模型:M 个 LLM × N 个工具 = M·N 个适配器。10 个 LLM × 50 个工具 = 500 个集成点。

MCP(Model Context Protocol) [9] 是 Anthropic 2024 年 11 月推出的开放标准,把 M·N 拆成 M+N:

  没有 MCP                       有 MCP
  ┌───┬───┬───┐                ┌───┬───┬───┐
  │GPT│Cld│Gem│                │GPT│Cld│Gem│
  └─┬─┴─┬─┴─┬─┘                └─┬─┴─┬─┴─┬─┘
    │   │   │ × N tools          └───┼───┘
   各连各的 (M·N)                    │  MCP protocol (JSON-RPC 2.0)
                                     │
                              ┌──────┼──────┐
                              │      │      │
                            ┌─┴─┬──┬─┴─┬──┬─┴─┐
                            │GH │DB│Fs │Sl│...│  ← N tools
                            └───┴──┴───┴──┴───┘

类比:USB-C 之前每个手机一根线(M·N);USB-C 之后任意主机接任意外设(M+N)。MCP 是 AI 的 USB-C。

2.7.2 MCP 协议规格

三类原语(Primitives)

MCP server 暴露给 client 的能力分三类:

原语 含义 例子 由谁触发
Tools 可执行函数,有副作用 create_issue、run_sql 模型决定调用
Resources 只读数据,URI 寻址 file:///doc.md、db://table/users 应用预加载
Prompts 用户可调用的模板 /explain-code、/summarize 用户触发

这三类对应 LLM 应用的三种数据流:模型主动调用、应用注入、用户调用。

三种 Transport

Transport 适用 部署
stdio 本地进程间通信(Claude Desktop / Cursor / Cline 默认) 进程子进程,配置在 mcp_servers.json
SSE(Server-Sent Events) 远程服务,单向流 HTTP server,长连接
Streamable HTTP(2025 替代 SSE) 远程服务,双向流,更标准 HTTP server,事实标准

2.7.3 完整 MCP Server 实现示例

Python(FastMCP)

# server.py
from mcp.server.fastmcp import FastMCP
from datetime import datetime

mcp = FastMCP("my-toolkit", version="1.0.0")

# === Tools(有副作用的函数)===
@mcp.tool()
def create_github_issue(repo: str, title: str, body: str) -> dict:
    """在指定 GitHub repo 创建 issue。
    Args:
        repo: owner/name 格式
        title: issue 标题
        body: issue 正文(markdown)
    Returns:
        {"id": int, "url": str}
    """
    # 实际调用 GitHub API
    response = github.create_issue(repo, title, body)
    return {"id": response.id, "url": response.html_url}

@mcp.tool()
async def run_sql(query: str, params: list = None) -> list[dict]:
    """对只读副本执行 SQL 查询。"""
    # 安全:用 parameterized query
    result = await db.fetch_all(query, params or [])
    return [dict(r) for r in result[:1000]]  # 上限 1000 行

# === Resources(只读数据)===
@mcp.resource("docs://{topic}")
def get_docs(topic: str) -> str:
    """获取某主题的内部文档。"""
    return knowledge_base.get(topic)

@mcp.resource("user://{user_id}/profile")
def get_user_profile(user_id: str) -> dict:
    """获取用户档案(仅 PII redacted 版)。"""
    return user_db.get_redacted(user_id)

# === Prompts(用户模板)===
@mcp.prompt()
def code_review(code: str, language: str = "python") -> str:
    """让 AI 做代码审查。"""
    return f"""请对以下 {language} 代码做 code review:
- 找出潜在 bug
- 评估可读性
- 建议优化

```{language}
{code}

““”

if name == “main”: mcp.run(transport=“stdio”) # 或 sse / streamable-http


#### TypeScript(@modelcontextprotocol/sdk)

```typescript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const server = new McpServer({ name: "my-toolkit", version: "1.0.0" });

// Tool
server.tool(
  "create_issue",
  { repo: z.string(), title: z.string(), body: z.string() },
  async ({ repo, title, body }) => {
    const result = await github.createIssue(repo, title, body);
    return { content: [{ type: "text", text: JSON.stringify(result) }] };
  }
);

// Resource
server.resource(
  "user-profile",
  "user://{user_id}/profile",
  async (uri, { user_id }) => ({
    contents: [{ uri: uri.href, mimeType: "application/json",
                 text: JSON.stringify(await userDb.get(user_id)) }],
  })
);

const transport = new StdioServerTransport();
await server.connect(transport);

2.7.4 MCP Client 接入

Claude Desktop / Cursor / Cline 配置

~/.config/claude/mcp_servers.json(Mac/Linux)或 Cursor / Cline 类似配置:

{
  "mcpServers": {
    "my-toolkit": {
      "command": "python",
      "args": ["/abs/path/to/server.py"],
      "env": {"GITHUB_TOKEN": "ghp_..."}
    },
    "github-official": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_..."}
    },
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem",
               "/Users/liang/projects"]
    }
  }
}

重启 client,所有 tools / resources / prompts 自动可用。

在 LangChain / LangGraph 里用

from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.prebuilt import create_react_agent

# 一次连多个 MCP server
async with MultiServerMCPClient({
    "my-toolkit": {"command": "python", "args": ["./server.py"], "transport": "stdio"},
    "github":     {"url": "http://localhost:3000/sse", "transport": "sse"},
}) as client:
    tools = client.get_tools()  # 自动转成 LangChain Tool 列表
    agent = create_react_agent("anthropic:claude-sonnet-4-6", tools)
    result = await agent.ainvoke({"messages": [("user", "在 acme/api repo 开个 bug issue")]})

2.7.5 主流 MCP Server 生态(2026)

按类别选用:

类别 仓库 用途
官方参考实现 modelcontextprotocol/servers 几十个开箱即用:filesystem / git / github / postgres / sqlite / slack / google-drive / brave-search / sequential-thinking
Awesome 列表 punkpeye/awesome-mcp-servers 社区 server 索引(数百个)
数据库 postgres / mysql / sqlite / mongodb / redis 都有官方或社区 MCP
云服务 aws-mcp / gcp-mcp / azure-mcp
DevOps kubernetes / terraform / docker MCP
生产力 notion / linear / jira / confluence MCP
浏览器 playwright-mcp / browserbase-mcp / Puppeteer MCP
企业商用 Zapier MCP(5000+ 集成)

2.7.6 MCP 时间线与采用度

时间 事件
2024-11 Anthropic 发布 MCP 协议
2025-Q1 Cursor / Cline 等 IDE 接入
2025-Q2 OpenAI 宣布支持
2025-Q3 Google / Microsoft / Amazon 跟进
2025-Q4 MCP 治理转入独立 MCP Steering Committee(Anthropic + Block + OpenAI + Microsoft 等共同治理)
2026-02 Python + TypeScript SDK 月下载量破 9700 万
2026-Q1 几乎所有主流 LLM 客户端原生支持

2.7.7 A2A:Agent 之间的协议族

MCP 解决”agent 与工具的沟通”,A2A(Agent-to-Agent) 解决”agent 之间的沟通”。这块仍在多协议竞争:

协议 / 框架 出处 范式 状态
Google A2A Google 2025 HTTP-based agent discovery + task delegation 早期
Microsoft Agent Framework Protocol Microsoft 2026 AutoGen 接班,多 agent 对话标准 推广中
Anthropic Agent Skills Anthropic 2026 Skill 包:可复用 agent 能力单元 早期
MCP for A2A 社区 把”另一个 agent”当作 MCP server 实践中
Letta multi-agent Letta 通过 message passing 框架内

MCP vs A2A 类比:

“MCP 给 agent 一双手(连工具/数据),A2A 让多个 agent 组队干活。MCP 是垂直整合(单 agent ↔︎ 工具栈),A2A 是水平协作(agent ↔︎ agent 网络)。”

2026 春的现状:MCP 已是事实标准,A2A 还在 Cambrian 大爆发期。实战建议:现在做单 agent → 全押 MCP;做多 agent → 用具体框架(LangGraph / Microsoft Agent Framework)的内置协议,等 A2A 标准明朗。

2.7.8 常见 MCP 设计陷阱

陷阱 表现 对策
Tool 太多 50+ tool 让 LLM 决策困难 分组 + 路由(先选类目再选 tool)
Tool description 太短 模型不知道何时用 写”何时用 / 何时不用”+ 1-2 个 example
副作用未声明 模型当只读调用,造成意外修改 description 明确”会修改 X”+ 在 client 侧加 deny-first
超长返回 一次返回 10K rows 撑爆 context server 侧 cap + 分页 + 摘要
同步阻塞 长任务把 client 卡死 用 async transport(streamable-http)
认证混乱 每个 tool 自己处理 token server 侧统一从 env 读,client 侧用 OAuth flow

工具集成在 Agent 实现层面的细节 → agent-engineering.md §3.1 与 §5; LLM 网关 / observability / 推理服务器层面的基础设施 → harness-engineering.md §3.9 附录(注:04 章把这 4 类显式标记为”相关但非 harness 工程”)。


Bibliography

[2] Liu, N. F. et al. (2024). Lost in the Middle: How Language Models Use Long Contexts. TACL. [5] Karpathy, A. Software Is Changing (Again). YC AI School talk. [6] Anthropic. Effective Context Engineering for AI Agents. https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents [7] LangChain. Context Engineering for Agents. https://www.langchain.com/blog/context-engineering-for-agents [9] Wikipedia. Model Context Protocol. https://en.wikipedia.org/wiki/Model_Context_Protocol [12] Hsieh, C. et al. (2024). RULER: What’s the Real Context Size of Your Long-Context Language Models? https://arxiv.org/abs/2404.06654 [13] Cheney Zhang. Embedding Models Benchmark 2026. [14] CallSphere. Vector Database Benchmarks 2026: pgvector / Qdrant / Weaviate / Milvus / LanceDB. [18] Packer, C. et al. (2023). MemGPT: Towards LLMs as Operating Systems. [19] Mem0 Team (2025). Mem0: Building Production-Ready AI Agents with Scalable Long-Term Memory. https://arxiv.org/abs/2504.19413 [21] Anthropic Memory Tool docs. https://docs.anthropic.com [41] TianPan. Long-Context Models vs RAG: When the 1M-Token Window Is the Wrong Tool. [43] Squirro. RAG in 2026: Bridging Knowledge and Generative AI.

补充: - Asai et al. (2023). Self-RAG. - Microsoft GraphRAG. https://github.com/microsoft/graphrag - LightRAG. https://github.com/HKUDS/LightRAG - Edge et al. (2024). From Local to Global: A Graph RAG Approach to Query-Focused Summarization. - BGE-M3. https://huggingface.co/BAAI/bge-m3


章节交叉引用


术语速查表

答案中以 [术语] 标记的概念都可点击跳到本表对应条目并自动展开。本表按 10 个主题分组收录 60+ 高频术语,默认全部收起——遇到不熟的术语再展开看精要解释,避免被信息淹没。

软件工程基础

lint 软件工程 — 静态代码检查工具,扫描源码找潜在 bug 与风格问题

不实际运行代码的情况下分析源码,识别潜在 bug、未使用变量、风格违规、可疑用法。常见工具:

在 Agent 工程中,lint 经常被用作 harness 的硬约束——把 lint 错误反馈给模型重写代码,比单纯在 prompt 里说"请遵守编码规范"可靠得多(Augment Code 把这叫做 Constraint Harness)。

type check / 类型检查 软件工程 — 验证变量、参数、返回值类型是否匹配

确保代码中变量赋值、函数调用的类型一致:

对 Agent:让 agent 写完代码后强制跑 tsc --noEmit / mypy . / cargo check,类型错误作为反馈喂回模型继续修。比让 agent 自己"声明检查过类型"可靠得多——这是 harness 工程的典型做法。

CI/CD 软件工程 — 持续集成 / 持续部署流水线

CI(Continuous Integration):每次代码提交自动跑测试、构建、lint、type check 等校验。
CD(Continuous Deployment):通过校验后自动部署到测试 / 预发 / 生产环境。

常见工具:GitHub Actions、GitLab CI、Jenkins、CircleCI、Buildkite。

在 Agent 工程里,CI 是最重要的 deterministic 反馈源——LLM 自评不可靠,但 CI 通过/失败是 0/1 信号,可以直接作为 ground truth。Hashimoto 的 harness engineering 强调"能不能解决问题强相关于 agent 能不能验证自己的工作"。

sandbox / 沙箱 软件工程 — 隔离的代码执行环境,限制对外部资源的访问

让不可信代码(用户上传、LLM 生成)在受限环境中跑,防止破坏宿主系统。隔离强度从弱到强:

Agent 跑用户/LLM 生成代码必须沙箱,并叠加纵深防御:网络出口白名单 + 文件系统只读 + 时间/内存配额 + 不挂载 host 凭据。

canary / 金丝雀发布 软件工程 — 先给少量流量上新版本,观察无异常再全量

来自煤矿用金丝雀检测毒气的典故。部署流程典型为:shadow(双跑不返回)→ 1% → 5% → 25% → 50% → 100%,每阶段观察核心指标无回归才推进。

对 LLM 应用:新 prompt / 新模型 / 新 agent harness 上线必走 canary,关键指标(解决率、CSAT、refusal 率、p99 延迟、单次成本)任何一个恶化 > 阈值就回滚。LLM 应用的"非确定性"特性让 canary 比传统软件更重要。

A/B test 软件工程 — 对照试验,把流量切成两组分别用新旧版本,比较关键指标差异

按 user_id hash 切流量保证一个用户始终进同一桶(避免体验跳变)。判定要素:

LLM 应用调 prompt / 换模型 / 改 RAG 都应过 A/B;只靠 offline eval 上线常翻车(线上流量分布与黄金集差异大)。

GMV / UV / CSAT / NPS / 转化率 业务指标 — 电商 / 旅行 / 客服业务最常用的几个北极星指标

业务侧验收 Agent 是否上线最看的几个指标:

Agent 工程关注:把模型 / prompt / RAG 改动放进 A/B 看这些业务指标,而非只看离线 benchmark 分数。改动让 benchmark 涨但 GMV / CSAT 跌的情况非常常见。

HITL / human-in-the-loop 软件工程 — 关键决策点引入人工审核 / 确认

Agent 自治走到关键节点时暂停等待人工:

设计原则:"Humans steer. Agents execute."(OpenAI Harness Engineering)。Agent 不是替代人,是放大人的判断——把人放在制定计划、设定约束、审核结果的位置,agent 处理执行。

SLO / SLI / SLA / Error Budget 软件工程 — 服务质量的"目标 / 指标 / 合约 / 预算"四件套,来自 SRE

Google SRE 体系定义的四个术语:

Agent 应用怎么用:

  1. 每个 Agent 场景定 1-3 个 SLO:如"客服 Agent 解决率 SLO = 85%"、"p99 端到端延迟 SLO ≤ 5s"、"单任务平均成本 SLO ≤ $0.05"
  2. 触发告警:实时 SLI 跌破 SLO 80% 警告,跌破 SLO 直接 page oncall
  3. 冻结发布:error budget 烧完了,禁止合并非紧急修复
  4. 业务 SLO vs 技术 SLO:业务 SLO(转化率 / CSAT / GMV)属于产品验收,技术 SLO(延迟 / 错误率 / cost)属于工程兜底,两层都要

经验法则:SLO 不是越严越好——99.99% 比 99.9% 贵 5-10 倍,且大概率超过用户感知阈值。Google 建议"刚刚够用户不抱怨"的水位。

TTL / Time To Live 软件工程 — 数据 / 缓存 / 凭据的有效期

到期自动失效。常见用法:

LLM 基础概念

token LLM 基础 — LLM 的最小输入/输出单位,由 tokenizer 切分得到

经验换算:1000 英文单词 ≈ 1300 token;1000 汉字 ≈ 1500-2000 token。

为什么重要:context window、API 计费、推理速度都按 token 算。控制 token 数 = 控制成本和延迟。Anthropic / OpenAI / Google 各自的 tokenizer 不同,相同文本 token 数差 ±20% 很常见。

embedding LLM 基础 — 把文本/图片映射为高维稠密向量,语义相近的向量距离近

文本 → 神经网络 → 一个 768 / 1024 / 1536 / 3072 维的浮点数向量。同义词 / 同主题文本的向量在空间中距离近(cosine similarity 高)。

主要用途:

主流模型 2026:OpenAI text-embedding-3-large、Cohere v4、Voyage-3、BGE-M3(开源 SOTA,中英双语 + dense/sparse/multi-vector 三合一)。

context window / 上下文窗口 LLM 基础 — 模型单次能处理的 token 上限

包含 system prompt + 历史对话 + 用户输入 + 模型输出,所有都计算在内。2026 主流模型:

注意:宣称窗口 ≠ 有效窗口。RULER 基准显示多数模型在窗口 1/4 之外性能急剧下降(Lost in the Middle)。工程建议把"应当塞入 context"的阈值定在 8-32k,更长走 RAG 或层级摘要。

prefill / decode LLM 基础 — LLM 推理的两阶段:处理输入 → 逐 token 生成

两个阶段瓶颈不同,调优策略也不同——prefill 优化靠并行 / FlashAttention,decode 优化靠 continuous batching / speculative decoding。

KV cache LLM 基础 — 注意力中已计算过的 K (Key) / V (Value) 矩阵缓存

生成第 t 个 token 时需要前面所有 token 的 K/V 参与注意力计算。把它们缓存下来避免每次重算,是 LLM 推理的最基础优化。

显存占用:2 × num_layers × num_heads × head_dim × seq_len × batch × bytes_per_elem。70B 模型上 128k 上下文的 KV cache 可达数十 GB,远超模型权重本身。

进阶优化:

autoregressive / 自回归 LLM 基础 — 一次生成一个 token,下一个 token 的生成依赖前面所有 token

GPT 类 decoder-only 模型的生成方式:P(x_t | x_1, ..., x_{t-1})。每生成一个 token 都要跑一次完整 forward(虽然能复用 KV cache),所以输出长度直接决定延迟。

对比:BERT 是非自回归(masked LM,一次预测所有 mask 位置),扩散模型(diffusion)也是非自回归(一次去噪整段)。

自回归的代价催生了大量加速技术:speculative decoding、parallel decoding、Medusa、EAGLE 等。

logit LLM 基础 — 模型输出的原始未归一化得分,每个词汇表 token 一个值

decoder 最后一层输出 [vocab_size] 维的 logit 向量;过 softmax 后得到下一个 token 的概率分布。

工程上能拿到 logit(或 top-k logprob)的场景:

注意:OpenAI / Anthropic 商用 API 默认只返回采样结果,需显式开 logprobs 选项。

temperature LLM 基础 — 控制采样随机性的超参数,0 = 确定性,>1 = 高随机

P(token) ∝ exp(logit / T):

何时调高:Self-Consistency 需要多样路径、creative writing、brainstorm。
何时调低:代码生成、数学推理、严格格式输出,T=0.1-0.3。

陷阱:T=0 不完全等同 deterministic——浮点 GPU 算子的非确定性 + 并发调度可能让相同 prompt 的输出仍有微差。

attention sink LLM 基础 — 模型把大量注意力集中到序列开头几个 token 的现象

Xiao et al. 2023 发现:长序列推理时,靠后的 token 往往把不成比例多的注意力分给了序列最前面的几个 token(即使它们语义无关)——这些 token 成为"sink",吸收掉 softmax 必须分配的归一化质量。

工程意义:

Transformer 架构

LayerNorm / RMSNorm 架构 — Transformer 主流归一化层,沿 feature 维度对单样本归一化

LayerNorm:y = (x - μ) / σ * g + b,沿 hidden 维度求均值方差。与 batch 无关,天然支持变长序列与单条推理——这是 Transformer 选 LayerNorm 而非 BatchNorm 的原因。

RMSNorm(Zhang & Sennrich 2019):y = x / sqrt(mean(x²)+ε) * g,去掉减均值和 bias。Llama / PaLM / Mistral 等现代 LLM 几乎都改用 RMSNorm,省 7-64% 归一化耗时且效果不降。

Pre-LN vs Post-LN:LN 在残差前做(Pre-LN)训练比放残差后(Post-LN)稳定,可去掉 warmup,GPT-2 起几乎统一用 Pre-LN。

RoPE / Rotary Position Embedding 架构 — 旋转位置编码,把位置信息编码进 Q/K 旋转矩阵

Su et al. 2021。把位置 m 表示为旋转矩阵 R_m 作用在 Q/K 上,使得 <R_m·q, R_n·k> = f(q, k, m-n)——注意力得分只依赖相对距离。

优点:(1) 无额外参数;(2) 天然编码相对位置;(3) 可与线性注意力兼容。已成 Llama / Qwen / Mistral 等绝大多数现代 LLM 的位置编码方案。

外推问题:纯外推 2k→32k 会崩——高频分量旋转角度落入未见区域。缓解:

NTK-aware scaling / YaRN 架构 — RoPE 长度外推方案,让 2k 训练的模型能跑 32k / 128k context

RoPE 纯外推会崩——高频分量在训练上下文外旋转角度落入未见区域。两种工程化方案:

主流应用:

经验数字:YaRN 在 4× 上下文扩展(2k→8k 或 32k→128k)几乎无损;8× 以上仍有性能下降。极致长上下文(1M+)通常需要重训而非仅靠 YaRN。

GQA / MQA 架构 — Grouped/Multi Query Attention,多个 Q 头共享同一组 K/V 头

标准 multi-head attention:H 个头各有独立 Q/K/V。

收益:KV cache 减小到 1/8 ~ 1/H,推理吞吐显著提升,效果几乎无损。Llama-2 70B / Llama-3 / Mistral / Qwen2 等都用 GQA。

MoE / Mixture of Experts 架构 — 混合专家模型,每个 token 只激活部分 expert FFN

把传统 dense FFN 换成 N 个并行的 expert FFN + 一个 router。每个 token 通过 router 选 top-k 个 expert(k 通常 1-2),只激活这部分 expert 计算。

优点:参数量大、算力省。Mixtral 8x7B 总参数 47B,激活参数仅 13B;DeepSeek-V3 671B 总参数,激活仅 37B。同等推理成本下 capacity 远超 dense 模型。

挑战:(1) 训练时负载均衡(防一两个 expert 被过度使用);(2) 显存占用按总参数计而非激活参数;(3) 通信开销大(expert parallelism)。

multi-head attention / 多头注意力 架构 — 把 d_model 拆成 h 份独立投影 Q/K/V,每头学不同子空间的关系

单头注意力对每对 token 只产生一个 attention 分布——一种"关系视角"。多头(h=8/32/64/128)让模型同时学多种关系——句法头关注短距离依赖,语义头关注共指、远程实体。

为什么单头加大维度不行:多头是 h 个低秩注意力的混合,表达能力严格更强;单头是一个高秩注意力,自由度反而少。

进阶变体:GQA / MQA 在 KV 侧减头省显存,Q 侧仍保多头。

推理加速

FlashAttention 推理加速 — 通过 tiling + online softmax 不实例化完整 attention 矩阵的 attention 计算

Dao 2022。标准 attention 显存 O(N²)(要存 N×N 的 attention matrix),长序列瓶颈。FlashAttention 把 Q/K/V 分块加载到 GPU SRAM 计算,不写出完整 attention matrix,显存降到 O(N),速度也快——attention 是 memory-bound,少读 HBM 就快。

演进:

PagedAttention 推理加速 — vLLM 提出,把 KV cache 像 OS 虚拟内存一样切成固定大小 block 管理

Kwon et al. 2023。解决传统推理 KV cache 的三类碎片问题:

机制:KV cache 切成固定大小 block(如 16 token),每个序列维护 block table(逻辑→物理映射)。显存利用率从 ~20% 提到 >96%;同 prompt 多采样共享前缀 block;配合 continuous batching 吞吐相对 HuggingFace TGI 提升 2-4×,相对 FasterTransformer 24×。

vLLM 推理加速 — UC Berkeley 开源的高吞吐 LLM 推理引擎,实现 PagedAttention

2023 年起的事实标准开源推理服务器。核心特性:

对比:TGI(HuggingFace)、TensorRT-LLM(NVIDIA,私有更快)、SGLang(前缀复用更彻底)、LMDeploy(OpenCompass 出品)。

continuous batching 推理加速 — 按 token 级别动态调度,请求结束即退出、新请求随时插入

也叫 in-flight batching,Yu et al. ORCA 2022 提出。对比 static batching(等齐 batch 再一起跑,长短请求混在一起时 GPU 利用率经常 <30%),continuous batching:

vLLM 数据:吞吐相比 static 提升 5-23×。已成所有现代推理引擎的默认。

speculative decoding 推理加速 — 小 draft 模型快速猜 K 个 token,大模型一次 forward 并行验证

Leviathan et al. 2023。流程:

  1. 小 draft model(1-7B)自回归生成 K 个 token(K=5 典型)
  2. 大 target model(70B+)一次 forward 并行验证 K+1 个位置
  3. 前 j 个被接受 + 第 j+1 个拒绝 → 保留前 j 个 + 采样一个新 token

数学上保证输出分布与原模型完全一致(rejection sampling)。

收益条件:(1) draft 与 target 分布相似(接受率 >60%);(2) 大模型受 memory bandwidth 限制,并行验证不增延迟。代码生成接受率 70-90%,开放生成 30-50%。变体:EAGLE-2/3、Medusa、Llama 3.1 self-speculative。

prefix caching 推理加速 — 跨 request 缓存相同前缀的 KV cache,跳过 prefill 重新计算

KV cache 是单 request 内复用;prefix caching 是跨 request 复用——多个 request 共享 system prompt / few-shot / agent 历史时,首次计算后缓存这部分 KV,后续 request 直接命中跳过 prefill。

效果:agent / RAG / 多轮对话场景,system prompt 通常 1-4k token、几乎所有请求共享,TTFT 可下降 10-100×。

实现:vLLM --enable-prefix-caching、SGLang RadixAttention(用 radix tree 自动管理所有历史前缀)、Anthropic prompt caching API(5min TTL,cached 部分 0.1× 价格)。

TTFT / Time to First Token 推理加速 — 从 request 发出到第一个 token 返回的延迟

主要由 prefill 决定(处理 input 所有 token)。计费、监控的核心指标之一。

降低 TTFT 的手段:

伴生指标:TBT(time between tokens,单 token 间隔)— 由 decode 决定。

量化

FP16 / BF16 / FP8 量化 — 低精度浮点格式,省显存省算力

混合精度训练:权重和梯度用 BF16/FP16,optimizer state 仍用 FP32。

INT4 / INT8 / NF4 量化 — 整数量化,把 FP16 权重压到 4/8 bit 整数

部署阶段把权重量化到低 bit 整数,推理时反量化回浮点计算。

INT8 / INT4 量化通常需要校准集(128-512 样本),AWQ 更智能(保护 1% salient 通道)。极致显存场景再用 GGUF(llama.cpp 格式)+ 3-bit / 2-bit 量化跑手机端。

AWQ / Activation-aware Weight Quantization 量化 — 保护 1% salient 通道的 INT4 权重量化

Lin et al. 2023。核心洞察:只需保护 ~1% 的"重要权重通道"(由激活幅值识别)即可保住精度。对这些通道按 per-channel scale 放大再量化。

对比 GPTQ:实现更简单,Llama-2 上困惑度更低,已成 vLLM / TensorRT-LLM 默认。

GPTQ 量化 — 较早的 post-training 4-bit 权重量化

Frantar 2022。用 OBQ 启发的逐层最小化量化误差,需要少量校准集(128 样本)。优点:早、生态全(exllama / vllm / TGI 都支持);缺点:对激活分布敏感,重要通道可能被压坏。

2026 部署选型:H100/H200 → FP8;A100/3090 → AWQ INT4;手机/边缘 → INT4 + GGUF。

微调与对齐

SFT / Supervised Fine-Tuning 微调 — 监督微调,用 (prompt, response) 对数据训练模型

最基础的指令微调方式:把 (输入, 期望输出) 对当做监督学习样本,cross-entropy loss 教模型学指令跟随。

经验数据量:

LIMA 论文:1000 条精选样本即可让 65B base 接近 GPT-4 对话质量——质量 >> 数量。

LoRA / Low-Rank Adaptation 微调 — 冻结原权重,只训练低秩 adapter 矩阵

Hu et al. 2021。把权重更新分解为两个低秩矩阵 ΔW = BA(r=8/16/64),只训练这两个矩阵,可训参数减少 100-10000×。

显存:

优点:可训参数少 / 多个 adapter 可热切换 / 缓解 灾难性遗忘。

QLoRA 微调 — 4-bit 量化冻结权重 + LoRA adapter,单卡 24G 跑 65B 微调

Dettmers et al. 2023。三项关键:

  1. 4-bit NF4 量化冻结权重:7B 从 14GB 压到 ~4GB
  2. Double Quantization:把量化常数也量化,省 ~0.4 bit/param
  3. Paged Optimizer:NVIDIA unified memory,OOM 时溢出到 CPU

65B 模型 QLoRA 约 33GB,单 A100-48G 或双 RTX 3090 可跑。代价:训练慢 30-40%(反量化开销)。

RLHF 对齐 — Reinforcement Learning from Human Feedback,用人类偏好做 RL 训练

三步走:(1) SFT 训出 base policy;(2) 人类标注 (chosen, rejected) 偏好对训出 Reward Model;(3) 用 RM 给 policy 输出打分,PPO/RLOO/REINFORCE 等算法更新 policy。

InstructGPT、ChatGPT 让 RLHF 出圈。三大痛点:

催生了 DPO、GRPO、RLVR 等简化/改良方案。

RM / Reward Model 对齐 — 用人类偏好训出来的"打分模型",给 LLM 输出打分

RLHF 第二步训出。输入:(prompt, response),输出:一个 scalar reward。训练 loss 是 Bradley-Terry:让 RM 在 (chosen, rejected) 对上给 chosen 更高分。

常见弱点:

替代方案:DPO 完全去掉 RM,RLVR 用程序判定 reward。

DPO / Direct Preference Optimization 对齐 — 从数学上证明可以不用 RM、直接监督式优化偏好

Rafailov et al. 2023。证明:在 Bradley-Terry 偏好模型 + KL 约束下,最优 policy 有闭式解,可直接用偏好对 (chosen, rejected) 做监督式损失:

L_DPO = -log σ(β(log π(y_w)/π_ref(y_w) - log π(y_l)/π_ref(y_l)))

优势:(1) 无 RM / 无在线采样 / 无 critic,仅 policy + ref 两个模型;(2) 用 SFT 同样的训练栈;(3) 超参稳定。

劣势:严重依赖偏好数据质量;容易过拟合 chosen 的表面模式;reward hacking 风险大。

Llama-3、Qwen2 后训练主路径都是 DPO 或其变种(IPO、KTO、SimPO)。

PPO / Proximal Policy Optimization 对齐 — RLHF 经典算法,actor-critic + clipped objective

Schulman 2017。Actor 学策略,critic 学 value function 估计 advantage,clip 限制每步策略更新幅度防崩。

RLHF 中需同时载入 actor / ref / critic / reward 四个模型,显存 ≥4× 单模型。超参敏感(KL 系数、clip ratio、advantage 归一化),训练不稳定。

催生了 DPO(去 RL)、GRPO(去 critic)、RLOO(用平均 reward 当 baseline)等简化方案。

GRPO / Group Relative Policy Optimization 对齐 — DeepSeek 提出,去掉 critic,用组内 reward 均值做 baseline

DeepSeek-Math 2024 提出,R1 验证。核心创新:去掉 critic(value 网络),对同一 prompt 采样 G 个 response(典型 G=64),用组内 reward 的均值/标准差做 advantage 归一化:A_i = (r_i - mean(r)) / std(r),再做 PPO-like 的 clipped objective + KL 正则。

效果:

RLVR / RL with Verifiable Rewards 对齐 — 用程序判定的 0/1 reward 做 RL,无需 RM

在数学、代码、形式逻辑等可自动验证的任务上,直接用程序判定 reward:答案匹配、单测通过、定理证明器验证。

优势:

DeepSeek-R1、DAPO(ByteDance 开源 SOTA)都属此类。局限:仅适用可验证任务,开放对话仍需 RLHF / DPO。

catastrophic forgetting / 灾难性遗忘 微调 — 在新任务上微调后,原通用能力显著下降

机制:参数被新任务 loss 拉走,原本编码通用知识的方向被覆盖。

缓解组合(生产推荐):

进阶:EWC(按 Fisher 信息加权 L2 正则)、Model Souping(微调模型与原模型权重平均)、MoE 路由扩展。

提示词与推理范式

CoT / Chain of Thought 提示词 — 让模型先输出推理步骤再给答案

Wei et al. 2022。最简形式:"Let's think step by step"(Kojima 2022 zero-shot CoT)。

为什么有效:(1) 增加有效 compute(更多 forward step);(2) 把"系统 1"直觉答题转成"系统 2"分步推理;(3) 暴露错误推理便于 self-consistency 投票纠正。

是涌现能力,<10B 模型几乎无效。Long CoT(R1 / o1 用 RL 训出,含回溯/自我验证,数千 token 长)是 2025 的新范式。

ToT / Tree of Thoughts 提示词 — 把推理建模为树搜索,每步多候选 + 自评估 + 回溯

Yao et al. 2023。CoT 是线性单链,错了无法回头;ToT 每步生成多个候选 thought,LLM 自评估状态价值(promising / sure / impossible),BFS/DFS 展开可回溯剪枝。

Game of 24 上 GPT-4 CoT 4% vs ToT 74%。代价:LLM 调用数从 1 涨到 50-200。

适合:解空间需显式搜索(puzzle、规划、定理证明),中间状态可评估。不适合:闲聊、摘要、翻译。

ReAct 提示词 — Reasoning + Acting,思考-行动-观察循环

Yao et al. 2022。结构 Thought → Action → Observation 循环:模型先 "Thought: 我需要查 X",输出 "Action: search[X]",工具结果作为 "Observation: ..." 喂回 prompt,再下一轮 Thought。

三大效果:

是现代 agent 框架(Claude tool use、OpenAI function calling、LangChain、AutoGPT)的概念原型。

Reflexion 提示词 — 跨 episode 的"言语强化学习",把失败原因存为 lesson

Shinn et al. 2023。Agent 在一次任务失败后(由外部 verifier 给二元 reward),用 LLM 把失败原因总结成自然语言 lesson 存入 episodic memory,下一次任务时把 lesson 加进 prompt 影响行为。

vs Self-Refine:

HumanEval 上 GPT-4 Reflexion 91%,超过 GPT-4 baseline 80%。

Self-Refine 提示词 — 单任务内迭代:generate → self-feedback → refine 循环

Madaan et al. 2023。在一个 trajectory 里循环 N 轮,无外部 reward、无跨任务记忆。7 个任务平均提升 20%。

陷阱:弱模型自评不准,可能越改越差。生产常组合 Self-Refine(局内)+ Reflexion(跨局)。

self-consistency 提示词 — 对同一问题采样 N 条 CoT,对最终答案做 majority vote

Wang et al. 2022。temperature>0 采样 N 条 CoT 路径,对最终答案投票。GSM8K 上比 greedy CoT 提升 ~17 个百分点(PaLM 55%→74%)。

收益大场景:(1) 答案空间离散(数字、选择题);(2) 模型错误率 <50%;(3) 推理路径多样(temperature 0.7-1.0)。代价:N×(典型 N=5-40),开放生成不适用。

few-shot / zero-shot 提示词 — Prompt 中给/不给示例

何时 few-shot:(1) 任务格式新颖/输出结构复杂(JSON schema、特定 markdown);(2) 分类任务标签多。

何时 zero-shot:通用任务现代模型已饱和(摘要、翻译、QA),加 example 反而引入偏差。

陷阱:example 顺序影响大(recency bias);偶然规律会被学走;example 多了 Lost in the Middle。建议 ≤8 条。

RAG

RAG / Retrieval-Augmented Generation RAG — 检索增强生成:先检索相关文档,再让 LLM 基于上下文回答

标准 pipeline = Ingestion + Retrieval + Generation:

  1. Ingestion:document loader → chunking → embedding → 向量库写入
  2. Retrieval:query rewriting → embedding → vector search → reranker → top-k
  3. Generation:构造 prompt(含 retrieved chunks)→ LLM 生成 → 后处理 + citation

每段都有瓶颈:chunking 切大小、embedding 选型、召回率不足、context 顺序、模型不忠于 context。生产 RAG ≠ "embedding + 向量库 + LLM"——是一个工程系统。

chunking RAG — 把文档切成适合 embedding / 检索的小块

策略:

BM25 RAG — 基于词频 + IDF 的经典稀疏检索算法

Okapi BM25。文档与 query 的相关性按 Σ IDF(qi) · f(qi,d) · (k+1) / (f + k·(1-b+b·|d|/avgdl)) 计算。强项:精确词命中、稀有词高权重、专有名词、数字。短板:同义词不通("医生" vs "doctor")。

与 dense embedding 互补——hybrid search 把两者融合,召回率比单 dense 提升 5-15 个百分点。

reranker / cross-encoder RAG — 把召回 top-N 用更精确(更慢)的模型重新打分

Bi-encoder(embedding):query / doc 分别编码再 cosine 比对,快但无交互。
Cross-encoder(reranker):query + doc 拼接喂 transformer,每层 self-attention 交互,相关性建模能力强 20-40%(NDCG@10),慢 100×。

生产标配:bi-encoder 召回 top-100 → cross-encoder rerank 到 top-10 → 喂 LLM。

主流:Cohere Rerank v3/v4、BGE-reranker-v2-m3(开源 SOTA 中英)、Jina Reranker v2、Mixedbread。

陷阱:召回 top-100 里没有相关文档,rerank 也救不了——reranker 锦上添花,不能替代召回。

主流 embedding 模型选型 RAG — BGE-M3 / Cohere v4 / Voyage-3 / OpenAI text-3-large / Qwen3-Embedding 怎么选

2026 主流 embedding 模型对比:

选型框架:

  1. 中文为主 → BGE-M3 / Voyage-3 / Qwen3-Embedding
  2. 多模态 → Cohere v4
  3. 纯英文 + API → OpenAI text-3-large
  4. 自托管私有部署 → BGE-M3

关键陷阱:

vector DB / 向量数据库 RAG — 专门存 embedding 并支持近似最近邻 (ANN) 检索;Pinecone / Milvus / Qdrant 等

主流:

ANN 算法:HNSW(最常见)、IVF、ScaNN(Google)。索引时间 vs 检索精度 vs 显存有 trade-off。

GraphRAG / Self-RAG / CRAG / Agentic RAG RAG — 朴素 RAG 的 4 个进阶变体,各解决不同短板

朴素 RAG 在多文档跨实体推理、召回质量不稳、多跳查询场景下都会力不从心。四个常见进阶方案:

  1. GraphRAG(微软 2024):先用 LLM 从文档抽 entity + relation 建知识图谱,按社区做层次摘要;query 时既能 vector search 又能图遍历。解决"跨多文档跨实体推理时朴素 RAG 召回不全"。代价:ingestion 成本大涨(每 chunk 一次 LLM 抽取)。
  2. Self-RAG(Asai 2023):训练单一 LM 自己生成 reflection token 决定 (a) 要不要检索 (b) retrieved 是否相关 (c) answer 是否被 context 支撑 (d) 整体 utility。解决"什么时候检索、检索后怎么用"的判断。需训练。
  3. CRAG (Corrective RAG,Yan 2024):retrieved chunks 经 lightweight evaluator 打分,分高直接用、中等触发 web 重新搜索、低退回基础生成。解决"召回质量参差不齐"时盲目使用 retrieved。
  4. Agentic RAG:让 agent 决定 query rewriting → 多轮检索 → 子 agent 分工。解决多跳问题、需迭代检索。DeepResearch 类产品就是这一路。

实战选择:

RAGAS RAG — RAG 评估事实标准,4 大核心指标都用 LLM-as-judge 实现

Es et al. 2023。四大指标:

  1. Faithfulness(忠实度):答案中每个 claim 能否从检索 context 推出。<0.7 = 模型在编造
  2. Context Precision(检索精度):top-K 中真正相关的占比。低 = retriever 召回噪声
  3. Context Recall(检索召回):ground truth 信息是否都被检索到。低 = 召回不全
  4. Answer Relevancy(答案相关性):答案是否真的回答了原问题

生产阈值:4 个指标都 ≥0.7 算合格;Faithfulness < 0.7 优先修;Context Recall < 0.7 调 retriever。

Agent 工程

harness / harness engineering Agent — 包裹 LLM 的代码骨架与工程化体系,让 agent 物理上无法重复犯错

Mitchell Hashimoto 2026 命名:"anytime you find an agent makes a mistake, take the time to engineer a solution such that the agent never makes that mistake again."

不是模型微调,而是工程化环境让模型物理上无法以同样方式再犯错。

两条法则:

  1. 强约束:能用 deterministic 约束(lint / type check / sandbox / CI 硬失败)就不用 prompt
  2. 自愈循环:agent 能从环境拿 ground truth、自我评估、失败可 checkpoint 恢复

OpenAI 公式:Agent = Model + Harness;"Humans steer. Agents execute."

LangChain / LangGraph / LlamaIndex / Haystack Agent — 主流 Agent / LLM 应用开发框架

2024-2026 主流框架对比:

经验:先用 SDK 直调写原型;workflow 模式(routing / parallelization / orchestrator-workers)成熟后再考虑 LangGraph;纯 RAG 场景考虑 LlamaIndex;避免一上来就 LangChain "全家桶"。

MCP / Model Context Protocol Agent — Anthropic 推出的开放协议,让 LLM 客户端用统一接口连接外部工具/数据源

2024-11 推出,2025-Q4 转入独立 Steering Committee(Anthropic / Block / OpenAI / Microsoft)。三种核心原语:

解决"每接一个新工具就要写一遍 adapter"的 N×M 问题。2026 年增速最快的单一技能,97M+ 月下载,已是 Anthropic Applied AI Engineer JD 显式必备。

tool use / function calling Agent — LLM 通过结构化 schema 调用外部函数

模型输出 {"name": "search", "arguments": {"query": "..."}} JSON,runtime 解析后真实执行函数,结果回喂模型。Anthropic Tool Use API、OpenAI function calling 都是同思路。

设计原则(Anthropic 实测:"agent 性能正比于工具描述清晰度"):

Computer Use / Browser Agent Agent — 让模型操作桌面 GUI 或浏览器

Anthropic 2024-Q4 推出 Computer Use。流程:截屏 → LLM 看图 + 推理 → 输出鼠标键盘动作(click X,Y / type text / scroll)→ 系统执行 → 再截屏循环。

Browser Use(开源框架)类似但限于浏览器,基于 Playwright + DOM 增强(把可点击元素加序号叠加到截图)。

实用场景:无 API 网站自动化、桌面软件自动化、端到端 e2e 测试。局限:慢、贵、安全性差、对 canvas 渲染应用支持差。生产建议:能用 API 就别用。

sub-agent Agent — 主 agent 派出的、有独立 context 的子任务 agent

主 agent 把"读 30 个文件做研究"丢给 sub-agent,sub-agent 有自己的独立 context 窗口,只把 final summary 回报给主 agent——主 context 不被中间产物污染。

Claude Code Task 工具、OpenAI Swarm、CrewAI 等都支持。是防止 Loop of Death 和 context 爆炸的关键手段之一。

AGENTS.md / CLAUDE.md Agent — 给 agent 看的项目说明书,写明协议 / 约束 / 启动流程

Agent 进入项目时自动读取。通常包含:

Hashimoto 视角:每行 AGENTS.md ≈ 一次错误的封堵。是 harness engineering 的隐式提示形态。

deny-first Agent — 默认禁止所有工具/命令,显式白名单才允许

Claude Code 采用的权限模型。Bash 命令按 verb + path 粒度授权:

对应安全原则:任一层失守,其他层兜底。配合 sandbox、网络出口白名单、文件系统只读做纵深防御。

progress 文件 / progress.md Agent — 把 agent 任务进度持久化到文件,跨会话续跑

Anthropic Effective Harnesses 给的核心设计:长任务 agent 必然跑爆 context window,纯靠 LLM context 不可能记住"我跑到第几步"。

解法:

下次会话执行 5 步开机协议从断点续跑。核心洞察:context window 是"working memory",文件系统是"long-term memory"。

Loop of Death Agent — Agent 进入无限循环烧 token 直到耗尽

常见模式:

防御纵深:

  1. 硬性 max iteration(5-30 步)
  2. Execution timeout(5-30 分钟)
  3. Token budget(per-task hard cap)
  4. 进度检测(连续 N 步无 diff 强停)
  5. 失败重复检测(同 tool call 失败 3 次跳出)
  6. 成本告警 + HITL
Memory Corruption / 记忆污染 Agent — 错误事实进入长期记忆后污染所有后续决策

例:用户开玩笑"我是亿万富翁"被存进语义记忆,之后 agent 一直按假设推理。

防御:

评估与安全

Trace + Eval 工具栈 评估 — Langfuse / LangSmith / Phoenix / Helicone / Patronus 等可观测平台

LLM 应用 / Agent 的"全链路追踪 + 评估"工具,2026 主流:

核心能力对齐项:

  1. Trace:prompt → tool_call → response → cost / latency 串成完整 trace
  2. Prompt 版本化:每次 prompt 改动一个 hash,可在 dashboard 切换并对比
  3. Eval:CI 上跑黄金集,回归报警
  4. Cost & Cache hit rate:单 trace 成本、cache 命中分布
  5. User feedback / thumb up-down:直接打到 trace 上做 bad case 入库

选型:自建优先 Langfuse;LangChain 重度用户 LangSmith;纯 trace 监控用 Phoenix;安全 / 实时拦截用 Patronus。

主流 LLM eval benchmark 评估 — MMLU / MT-Bench / Chatbot Arena / HumanEval / LiveBench / BFCL 各测什么

按测什么能力分类:

实战:从 2026 视角,单一 benchmark 都已不可信——必须多 benchmark 交叉验证 + 自家黄金集 + Arena 真人盲评三层。

Eval / Evaluation 评估 — LLM 应用 / Agent 的"打分"环节:offline / online / CI 三层评估

LLM / Agent 应用的 eval 不是单一动作,是一套体系。常见层次:

Eval 工具栈分类:

  1. 通用 framework:OpenAI Evals、DeepEval、Promptfoo、Inspect AI——CLI / 库形式跑评估
  2. 集成在可观测平台:Langfuse / LangSmith / Phoenix 都内置 eval framework,与 trace 联动
  3. RAG 专用:RAGAS(faithfulness / context relevancy 等 4 维)
  4. Tool use 专用:BFCL(Berkeley Function-Calling Leaderboard)
  5. 领域专用:每家自家黄金集 + LLM-judge rubric

Eval 类型按打分方式:

经验法则:(1) 没 eval 就改 prompt = 改盲;(2) Eval model 必须 ≥ 被评估 model(判官原则);(3) 黄金集要版本化 + 私有;(4) 每个 bad case 都要回归进黄金集——harness engineering 闭环。

LLM-as-judge 评估 — 用强 LLM 给候选输出打分,替代人工评估

把"评估"建模成 LLM 任务:让 judge 模型读 (prompt, response),输出 0-1 分 / pass/fail / pairwise 谁更好。可大规模并行、便宜、可在 CI 自动化。

三大 bias:

判官原则:judge 模型能力应 ≥ 被评估模型,否则评不出大模型回答好在哪。生产标配三层:自家黄金集 + LLM judge + 人工校准。

Lost in the Middle 评估 — 长上下文 QA 中,关键信息放中间时模型准确率显著下降

Liu et al. 2023 实验:把 gold passage 放 prompt 开头或结尾,模型准确率高;放中间则呈 U 形曲线下降,10+ documents 时中间位置可能低于无上下文 baseline。

工程缓解:

prompt injection 安全 — 用户或外部内容劫持模型行为,绕过 system prompt

OWASP LLM Top 10 的 #1。类型:

Simon Willison 结论:prompt injection 没有 100% 解,必须按"LLM 不可信"做系统设计。dual-LLM 模式 = Planner(看 trusted 决策)+ Executor(看 untrusted 但无工具权限)。

hallucination / 幻觉 评估 — 模型生成看似合理但实际错误的内容

来源:

debug 流程:复现 + 量化触发率 → 归因(RAG 召回 / 模型用 context / 工具调用)→ 修复 → 加 回归 → 生产监控(faithfulness scorer 实时拦截)。

关键认知:hallucination 多数是 prompt / RAG / 上下文工程缺陷,不是"模型病了"。

guardrails 安全 — 围绕 LLM 的输入/输出/工具/对话各环节的安全护栏

NVIDIA NeMo Guardrails 5 类:

  1. Input rails:PII 脱敏、prompt injection 检测、topic 限定
  2. Dialog rails:基于 Colang DSL 控制对话流,硬编码关键决策点
  3. Retrieval rails:剔除低质 / 敏感 / 不可信 chunk
  4. Execution rails:工具调用前参数白名单 / 授权检查
  5. Output rails:幻觉检测 / 敏感数据外泄过滤 / 毒性过滤

关键:rail 不是越多越好,每类挑 1-2 个高 ROI 的开,否则延迟/成本爆炸。

jailbreak / 越狱 安全 — 绕开模型安全训练让它输出有害内容

常见手法:

防御:厂商 RLHF safety training + 应用层 input/output classifier(Llama Guard)+ 限制 max context(对抗 many-shot)+ red team 定期演练。