【万字深度长文】深入浅出解析大模型的上下文工程

系列文章

1. 一文读懂RAG和KAG:AI知识增强的两大“利器”
2. 探秘检索增强生成:上下文检索、混合搜索与密集检索全解析
3. LangChain与LlamaIndex,RAG框架该怎么选?
4. 2W8000字深度剖析25种RAG变体:全网最全~没有之一
5. 探秘RAG:查询优化全解析,解锁大语言模型新潜能
6. 2W8000字揭秘RAG:从基础到高级的逆袭,彻底重塑大模型!
7. 1W8000 字 探秘 RAG 应用搜索:从语义搜索到评估指标的深度解析
8. 万字解析非结构化文档中的隐藏价值:多模态检索增强生成(RAG)的前景
9. 从 0 到 1 挑选 RAG 评估工具,这份指南请查收 
10. 利用Transformer、DPR、FAISS和BART对检索增强生成(RAG)进行深入技术探索
11. 【2万字深度长文】深入浅出RAG详解:语言模型的“开卷考试”——让模型答案锚定现实的外部“记忆”

第1章:语言模型的隐藏操作系统

从理论上讲,你刚刚部署的大语言模型是最先进的。它由GPT-4o驱动,连接到向量数据库,甚至还有一个暂存区并能使用各种工具。但总感觉哪里不对劲。

你注意到智能体忘记了用户三轮对话之前说的话,从无关文档中生成虚假答案,一直在反复解释它本应已经“知道”的事情。

然后你突然意识到:模型没有问题,是你的上下文有问题

在本文,我们不仅会探索什么是上下文,还会像系统工程师一样拆解它:如何构建、隔离、存储、检索、压缩上下文,并随着时间推移塑造它。

什么是上下文工程?

将大型语言模型(LLM)想象成一位世界级的思想家,但患有短期记忆丧失。除非你在每次调用时提供上下文——提示词、聊天历史、文档、示例、工具结果和暂存区内容——否则它一无所知。

受限于令牌窗口的上下文是LLM感知到的唯一“世界”。这意味着你的系统必须:

  • 构建进入上下文的内容

  • 过滤排除无关内容

  • 精确且一致地格式化所有内容

上下文工程是管理这一过程的工艺:如何填充、组织、存储、压缩、检索和隔离每次交互中传递给LLM的信息。

做好上下文工程,将带来:

  • 减少令牌使用和延迟

  • 准确的多轮记忆

  • 使用工具的智能体的推理行为

  • 更清晰的答案,更少幻觉

若做得不好,则会导致混乱:臃肿的提示词、无关的记忆,以及模型自相矛盾或偏离主题。

AI应用中的上下文类型

要智能地设计系统,必须区分上下文类型及其所属位置。

1. 短暂上下文(每轮记忆)

包括当前用户消息、最近几轮聊天历史和活跃的思考或工具调用。它随请求而变化,除非显式保存,否则不会保留。
示例

  • “用户:果阿的天气如何?”

  • 上一次函数调用:get_weather("Goa")

  • 当前暂存区:“规划度假行程…”

2. 持久上下文(长期记忆)

跨会话、任务甚至智能体仍应可访问的事实。可以是结构化的(如图表或关系表)或非结构化的(如笔记、文件、嵌入)。
示例

  • “用户偏好素食选项。”

  • “公司政策禁止食用贝类。”

  • “上次航班预订于12月10日。”

3. 运行时任务上下文(工作状态)

解决复杂任务时存储的临时信息,就像子智能体书写中间步骤和结果的白板。
示例

  • “步骤1:提取位置实体”

  • “知识库查询结果”

  • “工具输出:‘未找到航班’”

现实问题:记忆墙

做个快速练习:问你的智能体:“我之前说过喜欢哪些餐厅?”如果系统不使用长期记忆或未智能存储用户偏好,智能体要么:

  • 猜测(产生幻觉)

  • 道歉(中断流程)

  • 要求用户重复(糟糕的用户体验)

问题不在于模型,而是缺乏经过设计的上下文

第2章:构建航海家——一个经过上下文工程设计的大语言模型智能体

我们将打造航海家(Voyager),这是一款旅行助手大语言模型智能体,旨在记住你的偏好,实时获取信息,并在多轮任务中保持敏锐。与那些忘记上下文或陷入提示膨胀困境的基础聊天机器人不同,“航海家”使用结构化记忆来清晰思考。

技术栈

为正确实现,我们将结合四个强大组件:

角色

工具/技术

短暂聊天记忆

LangChain的ConversationSummaryBufferMemory

持久长期记忆

Neo4j图数据库(结构化)

上下文文档获取

LlamaIndex与向量存储

LLM推理

GPT-4o(通过Azure OpenAI)

这种架构使我们能够清晰地划分内存,高效管理提示窗口,并通过检索参考资料减少幻觉。

分步实现

步骤1:初始化LLM和短期记忆
from langchain.chat_models import ChatOpenAI
from langchain.memory import ConversationSummaryBufferMemory

llm = ChatOpenAI(
    model="gpt-4o", 
    temperature=0,
    openai_api_key="your-azure-openai-key"
)
short_mem = ConversationSummaryBufferMemory(
    llm=llm,
    max_token_limit=1200  # 防止内存膨胀
)

这将保留最近几次交互并自动总结其余部分,确保随时间推移提示词保持简洁。

步骤2:使用LlamaIndex加载旅行文档
from llama_index import SimpleDirectoryReader, VectorStoreIndex

docs = SimpleDirectoryReader("data/travel_guides").load_data()
vec_index = VectorStoreIndex.from_documents(docs)

这些是本地(或云端)存储的Markdown或纯文本文件,当用户询问目的地、酒店、签证信息等时,提供动态的事实依据。

步骤3:为长期知识设置Neo4j
from neo4j import GraphDatabase
import os

graph = GraphDatabase.driver(
    os.getenv("NEO4J_URI"),
    auth=(os.getenv("NEO4J_USER"), os.getenv("NEO4J_PASS"))
)

def add_fact(subject, relation, obj):
    with graph.session() as s:
        s.run("MERGE (a:Entity {name:$s})"
              "MERGE (b:Entity {name:$o})"
              "MERGE (a)-[r:"+relation+"]->(b)",
              s=subject, o=obj)

# 示例:从之前对话中已知的事实
add_fact("Aisha", "ALLERGIC_TO", "Shellfish")
add_fact("Aisha", "FAV_DEST", "Goa")

这作为持久的结构化记忆。与嵌入不同,它提供精确、无歧义的回忆,非常适合用户资料、偏好和关系感知推理。

步骤4:智能组装上下文
def build_context(user_query):
    history = short_mem.load_memory_variables({})["history"]
    
    with graph.session() as s:
        facts = s.run("MATCH (u:Entity {name:'Aisha'})-->(b) RETURN b.name AS fact")
        facts_text = "; ".join([r["fact"] for r in facts])

    retriever = vec_index.as_retriever(similarity_top_k=2)
    docs_txt = "\n\n".join([d.page_content for d in retriever.retrieve(user_query)])
    
    return f"""
You are Voyager, a travel planner for Aisha.
Known facts:
{facts_text}
Summary of chat so far:
{history}
Reference knowledge:
{docs_txt}
User input:
{user_query}
"""

这确保只将最相关的上下文片段——最近的聊天、已知事实和实时参考信息——交给LLM。

步骤5:运行智能体循环
while True:
    user = input("Aisha: ")
    ctx = build_context(user)
    resp = llm.invoke(ctx)
    print("Voyager:", resp.content)
    short_mem.save_context({"input": user}, {"output": resp.content})

这是完整的循环架构:智能提示组装、动态记忆和最小化令牌使用。

解决的问题

  • ✅ 通过摘要减少提示词大小

  • ✅ 通过结构化图记忆保持身份

  • ✅ 通过检索参考资料避免幻觉

  • ✅ 支持长期任务执行且不偏离目标

第3章:多智能体上下文——隔离、共享与扩展

在单个LLM智能体能力有限的世界里,多智能体架构正成为应对更复杂工作流程的解决方案。但一旦将两个智能体放在同一环境中(如规划者研究者),就会意识到共享上下文并非易事:一个智能体可能意外覆盖记忆,另一个可能因无关的过往上下文产生幻觉。你需要一个有范围界定、可读且可组合的记忆系统。

目标

我们希望构建一个系统:

  • 每个智能体(规划器、检索器、执行器)都有独立的作用域上下文

  • 智能体可以向共享便笺本写入并从中读取信息

  • 除非显式调用,否则长期记忆保持不变

  • 通过控制每个智能体可见内容,保持令牌使用效率

可以将其想象成云函数:小型、独立、有内存感知的单元,通过结构化接口通信,而不是共享上下文块。

构建:具有作用域上下文的多智能体任务规划

我们将构建一个包含3个智能体的度假规划助手

  • PlannerAgent:将用户查询分解为子任务

  • ResearchAgent:从RAG和记忆中获取信息

  • ExecutorAgent:合成并提供最终答案

每个智能体都有自己的LLM实例和上下文作用域。

设置:共享任务状态与内存注册表
class TaskState:
    def __init__(self):
        self.scratchpad = []
        self.subtasks = []
        self.context_registry = {}
    
    def write(self, agent_name, data):
        self.scratchpad.append({"from": agent_name, "data": data})
        self.context_registry[agent_name] = data
    
    def read(self):
        return self.scratchpad[-3:]  # 仅保留最近相关步骤
PlannerAgent:分解为子任务
class PlannerAgent:
    def __init__(self, llm):
        self.llm = llm
        self.name = "Planner"
    
    def plan(self, query, state):
        prompt = f"You are a task planner. Break this request into subtasks: {query}"
        response = self.llm.invoke(prompt).content
        subtasks = response.split("\n")
        state.subtasks = subtasks
        state.write(self.name, f"Planned subtasks: {subtasks}")
ResearchAgent:通过RAG+图获取信息
class ResearchAgent:
    def __init__(self, llm, retriever, graph):
        self.llm = llm
        self.retriever = retriever
        self.graph = graph
        self.name = "Researcher"
    
    def research(self, task, state):
        facts = get_facts_from_graph()
        docs = self.retriever.retrieve(task)
        merged = "\n\n".join([d.page_content for d in docs])
        prompt = f"""
Task: {task}
Known facts: {facts}
Documents: {merged}
Answer concisely for this step.
"""
        result = self.llm.invoke(prompt).content
        state.write(self.name, f"{task} → {result}")
执行流程
state = TaskState()
planner = PlannerAgent(llm)
researcher = ResearchAgent(llm, retriever=vec_index.as_retriever(), graph=graph)
executor = ExecutorAgent(llm)

query = "Plan me a 5-day beach vacation under ₹80,000 in July."
planner.plan(query, state)

for sub in state.subtasks:
    researcher.research(sub, state)
    
result = executor.execute(state)
print("🚀 Recommendation:\n", result)

为何有效

  • 每个智能体只看到所需内容,减少令牌膨胀

  • 共享内存显式且可控,无隐藏副作用

  • 智能体可独立替换、并行化或调试

  • 若一个智能体失败,其状态可追溯和恢复

第4章:基准测试上下文策略——智能记忆vs长窗口

现在你可能会问:“如果Claude 3.5或Gemini 1.5提供100万令牌,为何还要费这么大劲?”

因为长上下文≠智能上下文。没有工程规范:

  • 仍需为延迟和成本过度付费

  • 模型会被无关令牌干扰

  • 维护任务边界变得困难

我们需要的是智能上下文,而不仅仅是大上下文。

智能上下文(限定范围的多智能体+结构化记忆)

架构

  • 规划器→检索器→执行器智能体

  • 短期记忆缓冲区(LangChain)

  • 图内存(Neo4j)

  • 上下文窗口从未超过5K令牌

性能

  • 提供连贯、详细且筛选条件正确的行程安排

  • 在各智能体间保留过敏限制条件

  • 成本:低(单个GPT-4o实例+轻度摘要)

  • 延迟:约6秒

  • 令牌使用量:平均3980个

标准RAG(单智能体+向量检索)

架构

  • 平铺式提示:用户查询+前3个相关文档(通过嵌入搜索)

  • 除非在提示中手动添加,否则不记忆偏好

性能

  • 虚构了一个以海鲜为主题的度假村

  • 途中丢失饮食偏好

  • 仍生成行程,但缺乏个性化

  • 延迟:约5秒

  • 令牌使用量:平均6200个

长上下文LLM(Claude 3.5,200k提示词)

架构

  • 提示转储完整的10万份文档+用户查询+所有过往偏好

  • 无筛选,无智能体模块化

性能

  • 由于上下文足够大,无幻觉

  • 包含无关细节(天气模式、邮轮套餐)

  • 高延迟和成本

  • 延迟:约17秒(Claude 3.5)

  • 令牌成本:约为Voyager的8倍

结果总结

指标

多智能体+作用域内存

标准RAG

长上下文(Claude)

准确性

✅ 高(正确、限定范围)

⚠️ 中等

✅ 高

个性化

✅ 优秀

❌ 弱

⚠️ 通用

令牌效率

✅ 高效(~4k)

⚠️ 中等(~6k)

❌ 昂贵(~25k+)

延迟

✅ 快

✅ 快

❌ 慢

幻觉风险

✅ 低

⚠️ 中等

✅ 低

模块化与控制

✅ 高(智能体&内存)

❌ 低

❌ 无

结论:智能上下文制胜

虽然像Claude 3.5这样的长上下文模型是出色的工具,但它们并不能消除良好的上下文工程的必要性。它们使检索更容易,但:

  • 仍需要有选择地总结

  • 仍然难以分离无关信息

  • 成本高昂、速度缓慢,且缺乏任务特定的模块化

智能体——借助图记忆、作用域提示和运行时便签本——提供了一条更可靠、可复用且经济高效的前进路径

第5章:融合图、向量与结构——可扩展的内存架构

1. 图检索增强生成(Graph-RAG):为何单纯的向量搜索不够

向量数据库(如FAISS、Qdrant、Weaviate)能提供很好的语义匹配,但缺乏推理结构。假设用户提问:“果阿附近有哪三家素食度假村支持家庭入住,且每晚费用低于15000卢比?”向量RAG可能会检索出10条半相关的段落,其中有些重复,然后指望GPT-4o神奇地整合出答案。

而理想的系统应:

  • 检索高相似度文档

  • 使用图查询(budgetdietlocation)反复核对约束条件

  • 仅将结构化结果输入LLM

这就是图检索增强生成(Graph-RAG)

实现:混合图+向量检索
def graph_query(user_prefs):
    with graph.session() as s:
        results = s.run("""
        MATCH (r:Resort)
        WHERE r.veg_friendly = true AND r.price < 15000 AND r.location CONTAINS 'Goa'
        RETURN r.name AS name, r.rating AS rating, r.price AS price
        LIMIT 3
        """)
        return [dict(r) for r in results]

# 同时,为答案添加语义丰富性
retriever = vec_index.as_retriever(similarity_top_k=3)
sem_docs = retriever.retrieve("Best veg-friendly family beach resorts in Goa")

# 最终上下文
structured_facts = graph_query(user_prefs)
sem_text = "\n\n".join([d.page_content for d in sem_docs])

final_prompt = f"""
Structured filters:
{structured_facts}

Additional references:
{sem_text}

Compose a list of 3 resorts with reasoning.
"""

这种方法兼具精确性和丰富性,是确定性与模糊性语境的完美融合。

2. 结构化+语义记忆融合

想象你正在追踪:

  • 结构化数据:过往预订记录、预算趋势、航空公司会员等级

  • 非结构化数据:电子邮件往来、酒店评论、用户笔记

你需要一个能够将表格、图表和嵌入内容合并到统一上下文界面的系统,该界面可根据任务动态选择。这就是记忆融合技术的用武之地:

  • 对表格事实使用关系查询(SQL/Postgres)

  • 使用图形数据库(Neo4j)处理关系

  • 使用向量数据库(Qdrant)进行开放文本洞察

  • 使用提示组合器合并并格式化LLM输入

🧠 3. DSPy:内存感知提示编译

DSPy 是斯坦福大学开发的框架,旨在编译LLM应用程序(类似编译器构建二进制文件)。它:

  • 分析哪些输入重要

  • 优化检索哪些记忆

  • 随时间学习最有效的提示格式

核心特性:
  • 声明式模块(GenerateSelectChain

  • 自动编译+自我调试

  • 与OpenAI、Claude等集成

from dsp.modules.generate import Generate
from dsp.program import DSPyProgram

class ResortRecommender(DSPyProgram):
    def __init__(self):
        self.step = Generate(
            instructions="Recommend resorts using structured data and retrieved context.",
            inputs=["facts", "retrieved"],
            outputs=["recommendation"]
        )
    
    def forward(self, facts, retrieved):
        return self.step(facts=facts, retrieved=retrieved)

在实际示例上运行.compile(),DSPy会优化:

  • 使用哪种记忆

  • 如何构建提示

  • 每个部分分配多少令牌

DSPy不仅有助于上下文工程,还能学习如何为你完成这项工作

4. 架构:统一内存栈

最终的记忆感知LLM架构如下:

┌────────────────────┐
                        │   User Query       │
                        └────────┬───────────┘
                                 │
                ┌────────────────────────────────────────┐
                │     Context Engineering Layer          │
                │  - Prompt Builders                     │
                │  - DSPy Compiler                       │
                └────────┬────────────┬──────────────────┘
                         │            │      ┌──────────────────┘
            └─────────────┐      ▼                                             ▼
┌────────────┐                               ┌──────────────┐
│ Vector RAG │  ←→ semantic search           │  Graph DB    │ ←→ relationships
└────────────┘                               └──────────────┘
      ▼                                             ▼
┌────────────────┐                        ┌────────────────────┐
│ LLM Context    │  ←─ prompt composed ─  │ Structured (SQL)   │
└────────────────┘                        └────────────────────┘

所有内容都流入精确、模块化、令牌高效的上下文窗口

总结:智能扩展内存

智能AI的关键不在于更大的模型,而在于更智能的上下文。我们已证明:

  • 为何图+向量比单纯嵌入更优

  • 结构化记忆与语义记忆如何共存

  • DSPy等工具如何自动化上下文优化

  • 如何构建低延迟、个性化、无幻觉的系统

第6章:多智能体LLM系统中的共享vs隔离内存

随着基于LLM的系统从单个机器人发展为协作智能体团队,我们面临新问题:智能体如何管理共享知识?

它们应该:

  • 共享单一全局内存(黑板模型)?

  • 每个角色维护完全隔离的内存(作用域上下文)?

  • 像系统线程一样异步同步内存?

这是多智能体上下文编排的核心。

权衡:共享上下文vs限定作用域的上下文

类型

优点

缺点

共享内存

协调简单,全局知识

令牌膨胀风险,上下文干扰

隔离内存

封装逻辑,模块化智能体

协调难度大,需要消息传递

智能系统需兼顾两者:独立的局部上下文+共享的全局便签,如同人类既保留个人笔记,又维护项目文档。

构建:具有共享内存的CrewAI风格团队

我们将实现类似CrewAI架构的简化版本,其中智能体:

  • 拥有个人角色

  • 共享黑板暂存区

  • 通过结构化状态更新通信

class TeamBlackboard:
    def __init__(self):
        self.entries = []
    
    def post(self, agent, msg):
        self.entries.append(f"{agent}: {msg}")
    
    def view(self, limit=4):
        return "\n".join(self.entries[-limit:])
定义智能体角色
class PlannerAgent:
    def __init__(self, llm): self.llm = llm
    
    def act(self, goal, board):
        prompt = f"""
You are a planning agent. Goal: {goal}
Blackboard so far:
{board.view()}
Plan the steps needed and post them.
"""
        plan = self.llm.invoke(prompt).content
        board.post("Planner", plan)

class ResearcherAgent:
    def __init__(self, llm, retriever):
        self.llm = llm
        self.retriever = retriever
    
    def act(self, goal, board):
        prompt = f"""
You are a research agent. Goal: {goal}
Recent updates:
{board.view()}
Search and summarize relevant findings.
"""
        docs = self.retriever.retrieve(goal)
        content = "\n\n".join([d.page_content for d in docs])
        summary = self.llm.invoke(f"Summarize:\n{content}").content
        board.post("Researcher", summary)
最终执行者
class ExecutorAgent:
    def __init__(self, llm): self.llm = llm
    
    def act(self, board):
        context = board.view()
        prompt = f"""
You are the final agent. Here's the shared memory:
{context}
Compose a final report or action.
"""
        output = self.llm.invoke(prompt).content
        board.post("Executor", output)
        return output
团队执行
board = TeamBlackboard()
goal = "Find and plan a vegetarian family trip to Goa under ₹80,000"

planner = PlannerAgent(llm)
researcher = ResearcherAgent(llm, retriever=vec_index.as_retriever())
executor = ExecutorAgent(llm)

planner.act(goal, board)
researcher.act(goal, board)
final_output = executor.act(board)

print("🚀 Final Output:\n", final_output)

作用域内存:智能体何时不应看到所有信息

在某些任务中,智能体需要隔离记忆

  • 自主发展思维链的智能体

  • 安全系统(如法务智能体无法查看财务数据)

  • 需要向前滚动内存的长流程

LangGraphAutoGen等框架支持作用域内存,可定义哪些内存流向哪个智能体。

LangGraph风格的作用域上下文(概念性)
nodes:
  planner:
    reads: global_mem
    writes: plan_mem
  researcher:
    reads: [plan_mem, doc_vector_db]
    writes: research_mem
  executor:
    reads: [plan_mem, research_mem]
    writes: final_output

此图展示上下文如何在作用域通道间清晰移动——每个智能体只看到所需内容。

总结:构建团队记忆架构

用例

最佳实践

共享上下文(CrewAI)

黑板内存

作用域上下文(LangGraph)

定向记忆图

混合(AutoGen)

本地内存+共享通道

真正的工作从上下文开始

我们常将LLM视为神奇的智能引擎,但没有合适的上下文,即使最智能的模型也只是在盲目猜测。

本文中,我们了解到上下文工程不仅是将文本塞进令牌窗口,更关乎知识结构化、记忆管理,以及设计能像人类一样推理、适应和协作的系统。

上下文工程是LLM从“智能工具”进化为“智能伙伴”的关键桥梁——而这,才是AI开发真正的前沿。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值