当前位置: 首页 > news >正文

Agent开发理解

何为Agent开发

普通的大模型调用很简单,发起一次简单的LLM Api调用即可。Agent区分于普通的LLM Api调用,其关键在于让无状态的LLM Api调用能好用,不仅能够像有状态一样有记忆,还能分析思考,正确执行。
与之延伸而来就有所谓的「记忆(历史会话)管理」「工具调用(Mcp)」Agent开发范式reactplan&excute等),让LLM Api调用能够拆解问题,多次请求,共享会话,最终实现目标。
想要模型能够结合实时知识,进而又出现RAG。基本能力开发好了,想节省token成本,需要利用好LLM 的qv cache,增大缓存占比,就要在「记忆管理」的基础上加上分层管理,区分长短期记忆,将系统提示词、工具列表、长期记忆(claude.md)等不改动的放到提示词前面,以便命中前缀缓存;还有后续在MCP的基础上提出的「Skill」概念,通过渐进式加载的方式减少工具调用token长度。
随着对LLM的进一步利用,单一的Agent可能无法完成协作任务,于是又开始聚焦于 Muti-Agent 开发,引申出了A2A协议以便多Agent间的通信,并基于此区分各种模式(主从、顺序、协作等)…

Agent开发框架核心抽象

Agent开发框架,就是方便开发者去实现上述Agent开发过程中涉及的相关场景的。从22年的chatGPT出现到现在的cursor、claude、codex广泛普及,AI的发展太迅速了,成熟的Agent开发框架也已经出现了不少,如langchainlanggraphspring-AI等,作为一个站在巨人肩膀的AI应用开发,时常抱着学习态度去了解这些开发框架的实现代码,抛开不同框架间的语言差异不谈,会发现各个框架的核心抽象都基本一致。

Model

最基本的,一次LLM调用需要明确模型厂商的providerbaseUrl等信息,所以需要抽象出Model类,各家厂商模型协议不同,只在Model类中抽象出call方法,上层不关心具体实现。

Message / Prompt

模型调用需要输入,输入可以是提示词,也可以是模型上一轮输出,提示词又可以进行分层,因此对Message/Prompt抽象,包含

  • SystemMessage(系统提示词)
  • UserMessage(用户提示词)
  • AssistantMessage(模型回复)
  • ToolMessage(工具执行结果)
  • PromptTemplate(提示词组装scheme),

Prompt 不是一段文本,而是一组可组合、可追踪、可插入上下文的结构化消息。

Tool

模型不只是聊天,它要能做事,所以出现了ToolMcp/Skill本质上就是一种Tool,模型通过function calling/tool calling选择工具,框架负责解析参数、执行工具、把结果塞回对话。

interfaceTool{name:stringdescription:stringschema:JSONSchemacall(input:unknown):Promise<unknown>}

Chain / Runnable

实际场景往往不是一次模型调用就能解决问题的,通常需要多个步骤,所以需要把步骤串起来。于是出现了Chain/RunnableRunnable把各种执行组件都统一成:

input -> invoke/stream/batch -> output

把 AI 应用从“写业务代码调用模型”变成“声明一条数据处理管线”,类似于工作流,只适用于流程相对固定的场景,还算不上Agent。

Agent

Agent = Model + Prompt + Tools + Loop。Agent 的关键是一个循环:

观察当前状态
-> 让模型决定下一步
-> 如果要调用工具,执行工具
-> 把工具结果加入上下文
-> 再让模型判断
-> 直到完成

经典 ReAct 范式就是:Thought -> Action -> Observation -> Thought -> Final Answer:

classAgentExecutor{model:ChatModel tools:Tool[]memory:Memoryasyncrun(input){while(!done){constresponse=awaitmodel.call(messages)if(response.toolCalls){constresults=awaitrunTools(response.toolCalls)messages.push(results)}else{returnresponse}}}}

RAG

接着为了引入实时外部知识实现RAG,又出现了Document/Retriever/VectorStore,具体过程涉及文档加载(DocumentLoader)、分隔(TextSplitter)、向量化(EmbeddingModel)、向量存储(VectorStore)、向量检索(Retriever)、重排序(Reranker)等。其中的Retriever的抽象很重要,因为上层 Agent 不应该知道底层是MilvusPGVectorElasticsearchRedisChroma,还是普通 SQL。

interfaceRetriever{retrieve(query:string):Promise<Document[]>}

Graph/Node

在复杂场景下,可以将复杂任务拆解成子任务,由多个Agent串行/并行实现,因而基于此提出图(Graph)的概念。Graph每个节点(Node)是一个Agent(当然也可以是Agent之下更小的运行组件),如规划节点、检索节点、代码执行节点、审核节点、人类确认节点、总结节点、失败重试节点、分支路由节点等。

Checkpoint

每个节点的状态记录通过Checkpoint存储,Checkpoint保存的是图执行状态快照,如当前thread id、当前graph step、当前state values、各channel version、下一步待执行节点、历史状态等,让每个具体节点状态都变得可观测。

State

节点间的共享元数据使用State维护(所有节点共享同一份),每个节点读取State,每返回State的增量更新。一个通用的State定义通常包含:

typeAgentState={messages:Message[]taskId:stringplan?:string[]currentStep?:numberretrievedDocs?:Document[]toolResults?:ToolResult[]finalAnswer?:string}

Memory

想要保存跨轮次、跨任务、跨会话的记忆信息,又引申出MemoryMemory可以细分出很多类型,如长期记忆、短期记忆、规则/流程记忆等。

Hooks/Advisor

同时节点执行前、执行后可以添加一下Hooks/Advisor拦截操作,例如通过这些Hooks来进行人工确认。
实际代码编写过程中,通常是先建出各个节点,然后再建图,添加边,把一个节点到下一个节点作为一条边,例如我参与开源项目spring-ai-aibaba中的一个例子:

/** * 示例 1: 添加短期内存 */publicstaticvoidaddShortTermMemory(ChatClient.BuilderchatClientBuilder)throwsGraphStateException{// 创建内存检查点器MemorySavercheckpointer=newMemorySaver();SaverConfigsaverConfig=SaverConfig.builder().register(checkpointer).build();// 定义状态策略KeyStrategyFactorykeyStrategyFactory=()->{Map<String,KeyStrategy>keyStrategyMap=newHashMap<>();keyStrategyMap.put("messages",newAppendStrategy());returnkeyStrategyMap;};// 创建聊天节点varchatNode=node_async(state->{List<Map<String,String>>messages=(List<Map<String,String>>)state.value("messages").orElse(List.of());// 使用 ChatClient 调用 AI 模型ChatClientchatClient=chatClientBuilder.build();Stringresponse=chatClient.prompt().user(messages.get(messages.size()-1).get("content")).call().content();returnMap.of("messages",List.of(Map.of("role","assistant","content",response)));});// 构建图StateGraphstateGraph=newStateGraph(keyStrategyFactory).addNode("chat",chatNode).addEdge(START,"chat").addEdge("chat",END);// 编译图CompiledGraphgraph=stateGraph.compile(CompileConfig.builder().saverConfig(saverConfig).build());// 第一轮对话RunnableConfigconfig=RunnableConfig.builder().threadId("conversation-1").build();graph.invoke(Map.of("messages",List.of(Map.of("role","user","content","你好!我是 Bob"))),config);// 第二轮对话(使用相同的 threadId)graph.invoke(Map.of("messages",List.of(Map.of("role","user","content","我的名字是什么?"))),config);// AI 将能够记住之前的对话,回答 "Bob"System.out.println("Short-term memory example executed");}

A2A

如果说Tool 是 Agent 调用函数,那么A2A是 Agent 调用另一个 Agent。一个具有多Agent节点的Graph可以理解为本地的A2A调用,当然也可以通过httprpc实现远程A2A调用,例如配合nacos注册中心进行Agent级别的服务注册、发现。

http://www.cnnetsun.cn/news/2776156.html

相关文章:

  • CC Switch + codex + code link安装(自用)
  • 赋能智慧农业, 虹科Owasys边缘计算网关为农机装上更加可靠的智能通信中枢
  • 021、YOLO 整体架构鸟瞰:Backbone Neck Head 三大模块的分工与数据流
  • 【Springboot毕设全套源码+文档】基于Javaweb的家常菜烹饪学习管理系统的设计与实现(丰富项目+远程调试+讲解+定制)
  • 别再到处找图标了!Flutter内置的Material Icons到底有多好用?附完整图标清单
  • 用WordPress建外贸站,香港轻量云服务器2核2G配置能扛住多少并发?
  • Testsigma深度解析:AI驱动的无代码自动化测试实战指南
  • LF35x系列JFET运放:从核心原理到实战应用全解析
  • MATLAB说话人识别实战包:从语音读取到GMM身份判别全流程代码
  • java分片上传/合并
  • AI智能体与领域模型微调建设项目
  • 【国家级智慧社区认证必过清单】:AI工具合法性、隐私计算合规性、实时响应SLA三重校验表(附可下载模板)
  • Python信用评分卡终极指南:从零开始构建专业风险模型
  • 拥抱 Vibe Coding:重构一个现代化智能语音助手 (ClearVoice-ASR)
  • AI大佬跨阵营联合呼吁:美国立法强制筛查合成DNA订单,防范生物安全风险
  • PoE网络变压器中共模扼流圈(CMC)的放置与磁饱和问题解析
  • 反激电源同步整流改造实战:基于BM1R001xxF的完整设计与调试指南
  • MASA模组全家桶汉化包:中文玩家的终极解决方案
  • 深圳艾景特科技:开发者猫叔如何打造面向中国市场的 AI 投研产品
  • AirDisk NAS Viewer 通过 HTTP 服务或 Windows 网络驱动器
  • 如何免费搭建专业数字标牌系统?LibreSignage开源方案终极指南
  • Kotlin MVVM 实战入门:从分层到状态闭环
  • 黑洞冕区湍流等离子体特性与粒子加速机制研究
  • 从网表文件到仿真曲线:HSPICE新手入门,手把手教你跑通第一个TFT仿真
  • 【AI工具TCO精准压降术】:从License拆分、用量归因到跨平台套利,实测年省$186,400
  • 用OpenCV3.14复现经典Snake算法:从能量函数到代码实现的保姆级教程
  • NanaZip:重新定义Windows文件压缩体验的7个突破性功能
  • 硬件设计避坑:为什么你算的基极电阻总让三极管关不断?从MMBT3904实测曲线说起
  • spaCy实战指南:构建稳定可解释的NLP生产流水线
  • Delta Lake删除向量(Deletion Vectors)原理与实战指南