体重日记
25.36MB · 2025-10-27
现代 AI 系统在实际应用中,常常会遇到以下几类与上下文相关的挑战:
大多数大型语言模型都有一个固定的上下文窗口,这意味着我们不能把所有信息都一股脑地塞进去,而必须像挑选和整理信息,只提供最核心、最关键的内容输入进去。
给模型输入的每一个 token 都是有成本的,尤其是在大规模部署或频繁调用时。如果上下文管理不善,成本可能会呈指数级上升。
并不是所有的信息都对当前任务有用。无关或冗余的内容不仅会增加 token消耗,还可能像噪音一样干扰模型的判断,从而削弱其性能。
AI Agent常常需要跨越多个会话来记住用户的偏好、历史交互、上下文线索等。只有这样,它才能在后续对话或任务中保持信息,提供个性化和连贯的体验。
基础上述4点,上下文工程必须成为 AI 系统设计中的一项核心能力。
我们可以将上下文工程归纳为四个基本操作:写入、读取、压缩、隔离。
写入上下文的目标是把关键信息保存在模型当前上下文窗口之外,以便日后检索使用,从而构建Agent的持久化知识。
我们可以将记忆分为几个层次:
# 长期记忆存储示例
user_profile = {
"preferences": {"communication_style": "technical", "expertise": "senior-dev"},
"project_context": {"current_project": "video-editor", "tech_stack": ["React", "RxJS", "PIXI.js"]},
"conversation_history": [
{"session_id": "sess_001", "timestamp": "2023-01-15", "summary": "Discussed initial project setup."},
{"session_id": "sess_002", "timestamp": "2023-03-20", "summary": "Resolved auth issues."}
]
}
# 本次会话的短期状态示例
session_state = {
"current_task": "debug timeline drag-drop",
"open_files": ["timeline.jsx", "dragHandler.js"],
"recent_errors": ["Error: Invalid drop target on line 123", "Warning: Performance bottleneck in render loop"],
"task_progress": {"step_1_completed": True, "step_2_started": False}
}
通过这样分层存储,我们可以确保模型不会被无关信息淹没,也能在必要时重构脉络,保持对全局的理解。
读取上下文是指有策略、有目的地将外部存储的信息拉入当前上下文窗口,以供模型处理。这个环节需要优雅的检索机制和相关性评分,确保我们只读取有用的信息。
上下文来源:
检索策略:
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
# 假设有一个简单的知识库和记忆
knowledge_base = {
"react_docs": "React是一个用于构建用户界面的JavaScript库。它采用组件化。",
"rxjs_docs": "RxJS是一个使用可观测序列进行响应式编程的库。",
"pixi_docs": "PIXI.js是一个2D WebGL渲染引擎,适用于游戏和交互应用。",
"gsap_docs": "GSAP是专业的JavaScript动画库,用于高性能动画。"
}
user_memory = {
"preferences": "用户喜欢技术性、简洁的沟通风格。",
"current_project_summary": "用户正在开发一个React视频编辑器,timeline组件的拖拽功能有问题。"
}
# 文本编码器,用于语义搜索
model = SentenceTransformer('all-MiniLM-L6-v2')
def semantic_search(query, documents, top_k=2):
query_embedding = model.encode(query)
doc_embeddings = model.encode(list(documents.values()))
similarities = cosine_similarity([query_embedding], doc_embeddings)[0]
sorted_indices = np.argsort(similarities)[::-1]
retrieved_docs = []
for i in sorted_indices[:top_k]:
retrieved_docs.append(list(documents.items())[i][1])
return retrieved_docs
def read_context(user_query, session_state):
retrieved_context = []
# 1. 任务过滤和记忆查找
if "timeline" in user_query.lower() or "drag-drop" in user_query.lower():
retrieved_context.append(user_memory["current_project_summary"])
# 可以根据session_state进一步细化
if session_state.get("current_task") == "debug timeline drag-drop":
retrieved_context.append(f"当前任务:{session_state['current_task']},开放文件:{', '.join(session_state['open_files'])}")
# 2. 语义搜索知识库
tech_keywords = ["react", "rxjs", "pixi.js", "gsap"]
relevant_tech_docs = []
for keyword in tech_keywords:
if keyword in user_query.lower():
relevant_tech_docs.extend(semantic_search(user_query, knowledge_base, top_k=1))
break # 简化处理,只检索一个最相关的技术文档
retrieved_context.extend(relevant_tech_docs)
# 3. 用户偏好(长期记忆)
retrieved_context.append(user_memory["preferences"])
return "n".join(set(retrieved_context)) # 用set去重
# 模拟用户查询和会话状态
user_query = "我的视频编辑器 timeline 拖拽功能有问题,它是用React和PIXI.js做的。"
current_session_state = {
"current_task": "debug timeline drag-drop",
"open_files": ["timeline.jsx", "dragHandler.js"]
}
context = read_context(user_query, current_session_state)
print("检索到的上下文:n", context)
只有通过精细的检索,才能保证上下文既精准又高效,不至于让模型在信息的海洋中迷失。
即便检索得到的上下文是相关的,也常常包含冗余、重复或非重点信息。压缩的目的,就是在尽量少用 token 的情况下,把对当前任务最关键的事实、意图、变化抽取出来。
压缩策略:
from transformers import pipeline
# 使用Hugging Face的摘要模型
summarizer = pipeline("summarization", model="facebook/bart-large-cnn")
def hierarchical_summarization(text, max_length=150, min_length=50):
# 第一层摘要
summary_1 = summarizer(text, max_length=max_length, min_length=min_length, do_sample=False)[0]['summary_text']
return summary_1
def entity_extraction(text):
# 模拟实体抽取,更复杂场景需使用NER模型
entities = {
"project": "React 视频编辑器",
"component": "timeline",
"issue": "拖拽功能失效",
"tech_stack": ["React", "PIXI.js", "RxJS", "GSAP"],
"tried_actions": ["事件处理更新", "状态调试"],
"testing_tool": "Chromatic"
}
# 简单匹配,实际应更智能
if "React" in text: entities["tech_stack"].append("React")
if "PIXI.js" in text: entities["tech_stack"].append("PIXI.js")
# ... 其他实体匹配
extracted_summary = f"项目: {entities['project']} + {entities['component']}。核心问题: {entities['issue']}。技术栈: {', '.join(set(entities['tech_stack']))}。已尝试: {', '.join(entities['tried_actions'])}。测试工具: {entities['testing_tool']}。"
return extracted_summary
original_context = """用户正在构建一个基于 React 的视频编辑应用……他们反映 timeline 组件的拖拽功能不正常……使用 PIXI.js 渲染,状态管理采用 RxJS,对动画使用 GSAP,并且集成了 Chromatic 进行视觉回归测试……进行了事件处理更新、状态调试等操作。"""
print("原始上下文长度:", len(original_context))
# 使用摘要模型
compressed_summary = hierarchical_summarization(original_context, max_length=100, min_length=30)
print("n摘要模型压缩后:n", compressed_summary)
print("压缩后长度:", len(compressed_summary))
# 使用实体抽取模拟压缩
entity_compressed = entity_extraction(original_context)
print("n实体抽取模拟压缩后:n", entity_compressed)
print("实体压缩后长度:", len(entity_compressed))
压缩后的文本去掉了冗余细节,但保留了关键线索,能够在上文提示模型核心上下文,极大提升效率和降低成本。
隔离上下文是为了让不同类型或领域的上下文不互相干扰,并支持专门的子流程处理。这在复杂系统、多任务或多Agent架构中尤为重要。
隔离策略:
class Agent:
def __init__(self, name, role, initial_context):
self.name = name
self.role = role
self.context = initial_context # 每个Agent有独立的上下文副本
self.shared_state = {} # 对共享状态的引用
def process_task(self, task_description):
print(f"[{self.name} - {self.role}] 正在处理任务: {task_description}")
print(f"[{self.name}] 当前上下文: {self.context.get('task_specific_info', '无')}")
# 模拟根据角色和上下文处理任务
if self.role == "UI/UX":
self.context['task_specific_info'] = f"设计 {task_description} 的界面。"
self.shared_state['ui_design_draft'] = f"UI草稿 for {task_description}"
elif self.role == "Backend Logic":
self.context['task_specific_info'] = f"编写 {task_description} 的API。"
self.shared_state['backend_api_spec'] = f"API规范 for {task_description}"
elif self.role == "Testing Strategy":
self.context['task_specific_info'] = f"制定 {task_description} 的测试计划。"
self.shared_state['test_plan'] = f"测试计划 for {task_description}"
print(f"[{self.name}] 完成处理。")
# 共享状态
global_shared_state = {}
# 初始化Agent
ui_agent = Agent("UI Agent", "UI/UX", {"project_type": "web app"})
backend_agent = Agent("Backend Agent", "Backend Logic", {"database": "PostgreSQL"})
test_agent = Agent("Test Agent", "Testing Strategy", {"testing_framework": "Jest"})
# 设置共享状态引用
ui_agent.shared_state = global_shared_state
backend_agent.shared_state = global_shared_state
test_agent.shared_state = global_shared_state
# 任务分配
task_1 = "用户登录功能"
ui_agent.process_task(task_1)
backend_agent.process_task(task_1)
test_agent.process_task(task_1)
print("n--- 全局共享状态 ---")
print(global_shared_state)
# 另一个任务
task_2 = "订单支付流程"
ui_agent.process_task(task_2)
backend_agent.process_task(task_2)
test_agent.process_task(task_2)
print("n--- 全局共享状态 ---")
print(global_shared_state)
通过这种隔离策略,我们可以把复杂系统拆分为更清晰、更易于管理的模块,降低耦合度,提高整体系统的健壮性。
一般情况下,我们可以根据使用场景把上下文分成6类,不同的上下文有不同的侧重点。理解不同类别的上下文,有助于我们在设计时有针对性地分层和调用。
上下文在系统运行过程中,是一个动态演化、进化的过程:
为了让上下文处理既高效又经济,推荐如下方法:
惰性加载:非必要内容不预加载,仅在需要时才加载。
上下文缓存:对频繁访问的上下文进行缓存,加速检索速度。这就像浏览器缓存网页一样,下次访问时更快。
增量更新:避免重写整个上下文,只更新改动的部分。这在处理大型状态对象或记忆时尤其有效,可以节省大量计算和 I/O 资源。
上下文修剪:定期剔除过时、无用、低价值的上下文。
良好的上下文管理离不开质量检测与反馈机制,确保Agent始终在正确的运行:
上下文验证:检查检索到的上下文是否符合任务意图,是否存在误导性或不相关的信息。这可以通过人工评估或自动化测试来完成。
反馈回路:根据Agent输出的质量和用户反馈,不断优化上下文选择、压缩和组织策略。
A/B 测试:比较不同上下文配置的效果,以确定最优策略。
在开源社区有不少工具,可以用于AI Agent上下文工程的辅助开发,它们能帮助我们更高效地构建和管理复杂的 AI Agent。
Zep AI:专为 AI Agent设计的高级内存管理系统,支持会话记忆、向量存储等。
Redis:高性能的键值存储,适用于高速缓存和短期记忆。
PostgreSQL + pgvector:强大的关系型数据库,结合 pgvector 扩展后,可以支持向量相似性搜索,存储和检索长期记忆和知识库。
Milvus:专为海量向量相似性搜索设计,适合构建大规模的知识库。
ChromaDB:轻量级且易于使用的向量数据库,适合快速原型开发和中小型项目。
Weaviate:带有内置 ML 模型的向量搜索引擎,支持多模态数据,能进行更智能的知识检索。
CrewAI:一个用于编排多智能体团队的框架,让Agent可以协作完成复杂任务。
LangGraph:基于 LangChain 提供的状态图(state graph)抽象,用于构建复杂、有状态的 LLM 应用。
AutoGen:微软开源的多Agent对话框架,支持自动化工作流和复杂的Agent协作。
LangSmith:LangChain 官方提供的调试、测试和监控工具,用于跟踪 LLM 应用程序的运行。
Weights & Biases:强大的实验追踪和监控平台,可以帮助您可视化、比较和优化模型训练及Agent表现。
这些工具在不同层面支撑上下文的读取、写入、压缩、路由、可视化与调试,是构建复杂 AI Agent时的重要组成部分。
上下文工程是构建高级 AI Agent的基础架构能力。与其一味追求更大模型、更高参数,我们更应该注重如何让模型在有限的上下文中高效工作,这才是让 AI Agent真正走向实用的关键。
上下文工程需要不断地迭代调试和总结经验,简单的方法论无法覆盖其设计的方方面面。本文仅对上下文工程的开发和设计模式进行了阐述,并列举出了一些常见的Agent开发工具,希望对于开发Agent的读者有些启发。