返回市场
构建编码代理上下文工程服务器

构建编码代理上下文工程服务器

作者:phodal126 星标更新:2025-10-21

项目介绍

代理架构调查:从提示到上下文工程以构建AI代理

在过去两三年中,我为多家公司的高级开发者进行了代理开发培训;而在上个月,我一直在设计并训练毕业生使用的AI代理。直到本周, 在完成AI集成模拟项目展示后,我终于弄清楚了如何系统地为不同阶段的开发者定制一个代理学习路径。这一过程, 也让我深刻意识到“知识诅咒”的存在——我认为理所当然的知识实际上可能是初学者最大的障碍。

我们可以简单地将学习过程分为四个部分:

  • 结构化提示工程 — 如何设计高效且可复用的提示。
  • 上下文工程与知识检索 — 检索、生成和压缩上下文信息以产生高质量的知识背景。
  • 系统性实用函数设计 — 设计和实现代理可以调用的工具和接口。
  • 代理规划与多代理 — 构建任务规划和执行路径以实现闭环自动化。

在我们开始之前,公平起见,我们需要简要定义一下AI代理,考虑到代理的不同定义——实际例子可以从Anthropic的“构建有效的代理”中参考。

一些客户将其定义为能够长期独立运行并使用多种工具执行复杂任务的完全自主系统,而另一些则将其用于描述遵循预定义工作流的系统。

因此,围绕一个提示的简单任务也可以被视为一个AI代理;同样,涉及多个系统、工具和步骤的复杂任务也是AI代理。

结构化提示工程

尽管“上下文工程”是一个非常流行的术语,掌握如何编写有效的提示仍然是我们开始的关键重点。网上已经有很多关于提示的内容, 但从我的经验来看,我们可以专注于三个部分:

  • 提示的结构化输入和输出
  • 复杂问题的链式和模块化设计
  • 提示路由分配任务

结合一些必要的AI框架或工具,我们可以非常有效地完成我们的任务。

提示的结构化输入和输出

在当前开发代理的过程中,虽然模型可以生成一些提示,但调整这些提示仍然是工作的关键重点。我们希望模型输出的内容可以 与其它代码配合使用的JSON、XML或Java类。

提示用于引导AI模型生成特定输出输入设计是一种艺术和科学。通过精心设计和措辞输入,它可以有效影响和控制模型响应的方向和结果, 让AI生成预期的输出。

我们可以直接查看Spring AI文档中的结构化输出转换器作为示例:

结构化输出转换器

图中的黄色部分代表两个核心:

格式化的输入命令

一般来说,我们需要结构化的提示模板来动态生成提示,使用结构化文本设计输入

  • 动态提示模板(PromptTemplate)。利用经典的模板引擎动态组合上下文,如LangChain和Spring AI中的Jinja2和StringTemplate。这种方法允许在运行时注入上下文、用户输入、系统状态和其他信息,使提示构建更加灵活。
  • 结构化文本格式。为了确保AI输出的可靠性和可解析性,需要以结构化方式设计提示,包括角色定义(Role)、任务描述(Task) 约束、输出格式等。
  • 示例驱动。通过提供示例输入(Few-shots)和期望输出,可以显著提高模型输出的稳定性和一致性。例如,在实现QA时,提供不同场景下的示例实现。

转换模型输出结果

根据不同的场景采用适当的输出格式,并实现相应的解析机制异常场景处理

  • 领域特定的输出格式。根据场景,我们将使用不同的设计,如JSON、XML、YAML或Markdown,以更友好的方式呈现信息。例如: JSON的优势在于可以直接序列化和传输,但它缺乏实时渲染并且不够健壮。另一方面,YAML更好地处理了流问题,并且传输成本更低。
  • 解析实现。从纯文本中提取代码块,然后进行反序列化和对象映射。使用模式验证(JSON Schema、XSD)确保模型输出字段类型和结构符合约定。
  • 异常场景处理。由于模型生成的不确定性,输出可能会有缺失字段、类型错误或不符合约定格式的情况。例如:当某个字段缺失时,可以使用默认值或回退策略,这可能会触发模型重新生成特定字段

当能力适当的时候,可以根据现有数据和其他信息对模型进行微调或训练,以增强其在此领域的性能。

提示路由分配任务

在复杂的AI系统中,特别是在涉及多代理或多模块协作的场景中,单个提示往往无法完成所有任务。因此,我们需要提示路由:

https://www.ibm.com/think/topics/prompt-chaining

提示路由是一种工程方法,它涉及拆分任务、分析输入,并智能地将它们分配给最合适的模型或子任务提示,在多任务、多代理或复杂AI工作流程中。

核心思想是:通过分析输入和上下文,动态确定信息处理路径,使用哪个提示,或者调用哪个工具、子代理,从而实现非线性、条件任务执行。在典型的 以QA场景为例:

  • 非系统相关的问题 → 直接告知用户此类问题不支持
  • 基础知识问题 → 调用文档检索和QA模型
  • 复杂分析问题 → 调用数据分析工具,然后生成摘要

通过提示路由,系统可以根据问题类型智能选择最合适的处理方法,同时保持模块化和可扩展性。在某些AI框架中,如LangChain中的RouterChain 可以提供类似的能力支持,以及诸如基于语义相似性的路由 这样的方式。

复杂问题的链式和模块化设计

有了提示路由,可以通过提示链系统地分解复杂问题,将大型任务划分为多个子任务, 每个子任务对应不同的提示或模型调用,最后整合结果。这种方法非常适合具有固定工作流程的过程,其中某些步骤可以跳过。

https://arxiv.org/pdf/2308.11432

这可以实现更好的模块化 设计:

  • 每个子任务专注于处理特定阶段的任务
  • 子任务可以根据需要重写,添加或替换提示
  • 根据前一阶段的输出动态调整后续提示

以常见的软件需求为例,产品经理提出的思路可以通过提示链分解为:

  1. 思路收集:收集产品思路和初始需求
  2. 明确需求逻辑并优先级排序功能需求
  3. 需求预安排:制定初步需求文档或任务清单
  4. 最终确认需求:确认最终需求并生成正式文档

每一步都可以由不同的提示或子代理处理。例如,创意收集可以借助具有搜索功能的AI代理辅助,而需求逻辑组织可以利用Dify 工具如Copilot 365来完成任务。最终,每一步都以链式过程执行,同时保持模块化设计的灵活性,允许根据需要调整或替换子任务。

上下文工程与知识检索

通常,我们有NoCode和ProCode来支持上下文感知的代理开发。

  • NoCode解决方案(适用于快速验证):使用低代码平台(如Dify、N8N、Coze等)和预配置的RAG管道,通过UI快速配置检索策略。
  • ProCode解决方案(适用于定制需求):使用框架(LangChain、Spring AI)自定义检索过程和优化策略,实现多阶段HyDE +混合检索+重新排名管道。

上下文本身也是提示的一部分。在各种自动化实施之前,我们通常手动将文档内容复制到AI聊天工具中。只有当我们深入研究模型的能力时, 才开始思考如何构建自动化,这意味着从工程角度解决问题。在我们开始之前,仍然需要定义AI代理,这里可以参考Anthropic 《有效上下文工程》的官方定义(因为它既涉及科学又涉及艺术):

上下文工程是精心策划和放置来自不断发展的信息宇宙中最相关的内容到有限的上下文窗口的艺术和科学。

上下文窗口

简而言之:关注在有限的上下文窗口内选择最关键的信息,以使模型的理解和推理更有效。以下是Langchain绘图Drew Breunig总结的六种常见上下文工程技术:

六种常见上下文工程技术

在这里,我将简要总结为:RAG和上下文窗口的工程。完整的上下文窗口(即提示)通常应包括:

  • 系统提示部分:
    • 输入指令上下文:告诉它“你是谁”和“你想做什么”,包括系统提示、用户输入和角色定义。
    • 格式化输出上下文:指定模型输出格式的结构化模式,例如要求返回JSON格式以确保输出的可用性。
  • 函数调用部分:
    • 工具相关的上下文:赋予模型与外部世界交互的能力。包括可用工具或函数的定义以及调用这些工具后返回的响应。
  • 动态上下文部分:
    • 时间和记忆上下文:短期记忆、长期记忆。
    • 外部知识上下文:从文档和数据库等外部信息源检索的事实,帮助模型避免“胡言乱语”错误。
    • 全局状态/暂存区:模型处理复杂任务时的临时存储,相当于它的“工作内存”。
  • 外部知识:使用检索增强生成(RAG)等技术从外部知识库(如文档、数据库)检索的信息,为模型提供事实依据并减少幻觉。

除了固定的系统提示部分,获取外部知识记忆对整个窗口的影响最大,因此二者的设计和优化是上下文工程的首要任务。

知识检索增强生成

Spring AI RAG

RAG(检索增强生成)是构建代理的核心技术之一,通过从外部知识库检索相关信息来增强大型语言模型的生成能力。在代码库问答等复杂场景中,简单的向量检索往往不足以达到精度要求,需要结合多种检索策略来提高准确性。

简单来说,就是通过搜索丰富上下文。根据实现复杂度和场景要求,我们可以将检索策略分为以下几类:

  • 关键词搜索最基本的搜索方法,适用于精确匹配场景。例如,在代码库中搜索特定函数名、类名或变量名时,关键词搜索通常比语义搜索更有效。常见的实现包括:
    • 全文搜索使用Elasticsearch和Solr等搜索引擎,采用BM25和TF-IDF等算法。
    • 正则表达式匹配工具如ripgrep和grep,Cursor采用结合ripgrep和向量搜索的混合方法。
  • 语义搜索通过向量嵌入理解查询的语义意义,而不是字面匹配,对于自然语言查询尤为重要
    • 使用预训练嵌入模型(如OpenAI text-embedding-3-large、Jina embeddings v3)将文本转换为向量
    • 在向量空间中计算查询和文档之间的相似性(通常使用余弦相似度或点积)
  • 基于图的搜索图像检索不仅关注“内容相似性”,还强调关系和上下文依赖性。
    • 在代码场景中:构建代码的调用图和依赖图,使用抽象语法树(AST)提取方法、类和构造函数等结构。
    • 例如:微软的GraphRAGAider的repomap,或Joern和CodeQL等基础设施

在检索之前,为了确保生成的搜索结果的可靠性,需要引入查询改写逐步将用户的模糊意图转化为数据库可以高效执行的精确查询。 修改用户的原始查询以增强其与知识库中文档的相关性,解决自然语言问题与存储数据块之间的“阻抗失配”。

代码上下文中的RAG示例

通常,可以结合多种不同的检索策略来增强检索效果。以下是向量数据库LanceDB提供的一个示例代码库RAG实现

除了在索引阶段使用TreeSitter生成知识检索阶段还将使用:

  • HyDE(假设性文档嵌入):首先让模型根据查询生成一个“假设性”的文档或代码片段,然后使用此生成的内容进行向量搜索,更容易找到语义相关的代码。
  • BM25(关键词搜索):一种传统的关键词搜索算法,擅长查找包含确切术语或API名称的代码,也可以与向量搜索结合使用。
  • 混合搜索:结合BM2-5和语义搜索,实现精确关键词匹配和理解代码语义,通过调整各自的权重来优化结果。
  • 重新排名:在获得初步的向量搜索结果后,使用交叉注意力机制重新排名结果,提高最终答案的相关性和准确性。

当然,在早期的索引阶段,这个示例也会生成元特征数据对于每个元素或代码片段,我们首先生成代码的文字描述,然后将该描述向量化, 以获得代码的所有元特征,这些元特征是由微调的LLM提取的。

上下文窗口的工程

https://docs.claude.com/en/docs/build-with-claude/context-windows

两年前,GitHub Copilot 完成的上下文系统构建是行业领先的 最值得研究的上下文系统(毫无疑问):

  • 连续信号监控。Copilot插件持续监控IDE的一系列信号,以动态调整上下文的优先级,例如插入或删除字符,当前编辑文件和语言的变化,光标移动,滚动位置变化,以及文件的打开和关闭。
  • 上下文来源优先级排序在发送给模型的最终提示中,项目将根据优化级别进行排序和过滤:
    • 最高优先级:光标位置周围的代码,包括光标前后的内容,这是最直接的上下文。
    • 高优先级:当前编辑文件的其余部分。
    • 中等优先级:IDE中打开的其他文件或标签(即“相邻文件”)。
    • 还考虑额外的上下文,包括文件路径、仓库URL、代码中的导入语句以及通过RAG检索的代码信息。
  • 在上下文长度限制下的提示组装。根据上述优先级对每个信息片段进行评分,然后组装最优提示。

这也为我们提供了非常好的参考:

  • 新鲜度优先。最近编辑或访问的内容优先级更高,而过时内容的权重逐渐衰减。
  • 信号融合和动态评分。整合各种编辑信号(如光标移动、文件切换、导入更改等),动态调整上下文权重。
  • 滑动窗口和增量更新。采用滑动窗口机制仅对更改的部分进行增量更新,避免全面重建。
  • 预算意识和自动截断。实时估算令牌使用情况,当接近限制时自动修剪或总结低优先级内容。

当然,这是一个高度复杂的设计,只适用于价值足够高的系统。结合目前流行的Cursor Rule/Spec,建议使用持久记忆如AGENTS.md (记忆系统)跨会话存储关键信息,为后续查询提供长期背景上下文。

代理检索

https://langchain-ai.github.io/langgraph/tutorials/rag/langgraph_agentic_rag/

代理特性是指使AI系统具备自主感知、动态决策和目标导向执行能力的特性,使其能够在任务执行过程中主动优化上下文、生成检索策略并持续自我迭代。

在AI编码领域,如Cursor和Claude Code,我们可以观察到它们的操作过程,本质上是代理执行RAG。与普通RAG相比,它更容易获得 丰富的上下文确保在整个过程中上下文不会丢失。我们可以看到一些相对成熟的AI应用示例:

  • Cursor优化采用file + ripgrep直接搜索代码,当结果不足时,调用向量化检查或与Git历史相关的搜索
  • 在Google DeepResearch的生成过程中,采取类似的方法完成研究:识别主流的上下文工程技术工具,初步了解它们的功能和差异,然后进入下一步:深入探索工具细节

简单来说,对于复杂的搜索,我们可以构建一个代理来决定使用哪些检索工具和策略,当上下文不足时,继续调用带有新参数的工具 以获得足够的上下文。

DeepResearch示例

以下是Langchain AI构建的Open DeepResearch过程示例:

Deep Research Agent展示了更为系统的代理检索方法:

  1. 将任务分为计划阶段(管理代理)和执行阶段(执行代理)
    • 管理代理负责任务理解、子任务分解和检索策略设计
    • 执行代理负责实际搜索、网页或文档爬取及内容解析
  2. 在检索过程中,代理维护主题结构的状态、覆盖的子问题和信息缺口,以确定下一个探索方向
  3. 用户评审可以在关键阶段(HITL模式)插入,以增强控制和准确性
  4. 最终,代理将收集的碎片信息编译成结构化报告,包括引用来源

观察它们的互动和思维过程通常有助于我们更好地理解这一过程。在此基础上,我们还可以看到代理上下文工程如何进一步使LLMs 自主生成、组织和迭代上下文,实现智能和可扩展的上下文管理,从而优化复杂任务的检索和推理效率。

https://www.arxiv.org/pdf/2510.04618

也就是说,基于历史对话或经验优化检索方法,使代理更适合场景。

代理工具系统的工程设计

在构建代理的过程中,工具系统的设计最能体现工程思维。它决定了代理能做什么,做得有多好,以及是否能与外部世界高效协作。 工具可以是任何API,如数据查询(例如数据库访问)、现实操作(例如发送电子邮件、预订会议)或与其他服务协作的接口。正如我们前面提到的,RAG也是在代理下的 一种工具,如LlamaIndex提供的这种显式封装:

  • FunctionTool:轻松将任何Python函数封装成可供代理调用的工具。
  • QueryEngineTool:将任何数据查询引擎(例如向量索引)转换为代理可以对其执行查询和推理的工具

这种以数据为中心的方法可以简化我们对工具的理解。

语义工具:为代理设计的功能接口

工具本质上是一类语义可理解的功能接口。它们不仅包含逻辑执行能力,还携带元数据,使模型能够理解它们