AI-Agent 智能体-开发日志2
AI 智能体是使用 AI 来实现目标并代表用户完成任务的软件系统。其表现出了推理、规划和记忆能力,并且具有一定的自主性,能够自主学习、适应和做出决定。
这些功能在很大程度上得益于生成式 AI 和 AI 基础模型的多模态功能。AI 智能体可以同时处理文本、语音、视频、音频、代码等多模态信息;可以进行对话、推理、学习和决策。 它们可以随着时间的推移不断学习,并简化事务和业务流程。智能体可以与其他智能体协作,来协调和执行更复杂的工作流。
Agent类型 | 描述 | 示例 |
---|---|---|
简单反射Agents | 根据预定义的规则执行即时操作。 | 旅行 Agent 解释电子邮件的上下文并将旅行投诉转发给客户服务。 |
基于模型的反射Agents | 根据世界模型和该模型的更改执行操作。 | 旅行 Agent 根据对历史定价数据的访问,优先考虑价格发生重大变化的路线。 |
基于目标的Agents | 通过解释目标并确定实现目标的行动来制定实现特定目标的计划。 | 旅行 Agent 通过确定从当前位置到目的地的必要旅行安排(汽车、公共交通、航班)来预订旅程。 |
基于效用的Agents | 考虑偏好并以数字方式权衡取舍,以确定如何实现目标。 | 旅行 Agent 在预订旅行时权衡便利性与成本,从而最大化效用。 |
学习Agents | 通过响应反馈并相应地调整行动来不断改进。 | 旅行 Agent 通过使用旅行后调查中的客户反馈来改进未来的预订。 |
分层Agents | 在分层系统中具有多个 Agents,高级 Agents 将任务分解为子任务,供低级 Agents 完成。 | 旅行 Agent 通过将任务划分为子任务(例如,取消特定预订)并让低级 Agents 完成这些子任务,然后向高级 Agent 报告,从而取消行程。 |
多Agent系统(MAS) | Agents 独立完成任务,可以是合作的,也可以是竞争的。 | 合作:多个 Agents 预订特定的旅行服务,如酒店、航班和娱乐。竞争:多个 Agents 管理并竞争共享的酒店预订日历,以便为客户预订酒店。 |
以通过数据库表动态配置的手段,完成相关物料的加载,包括;模型(gpt-4.1/deepseek)、客户端、对话预设、执行规划(Planning)、顾问(记忆、RAG、日志)、工具(MCP)等,在把单个 Client 串联,完成整个 Agent 调用链。这样一个 Agent 调用链可以以对话形式使用或通过 Agent 动态任务自动执行。
AI智能体 | AI助理 | 聊天机器人 | |
---|---|---|---|
用途 | 自主、主动地执行任务 | 协助用户执行任务 | 自动执行简单任务或对话 |
功能 | 可执行复杂多步骤操作;学习和适应;独立做决策 | 响应请求/提示,提供信息并完成简单任务;可推荐操作,但决策由用户做 | 遵循预定义规则;有限学习能力;基本互动 |
交互 | 主动;以目标为导向 | 被动;响应用户请求 | 被动;响应触发器或命令 |
系统设计
- 以 ChatClient 为中心,设置;Ai模型、对话预热、规划模式、顾问、工具,完成 LLM ChatClient 构建。这些注入的元素属性,驱动着 Agent 功能的实现。
- 会话时,从输入端到输出端,可以顺序执行多个 ChatClient。通过这样的方式,让不同配置的 ChatClient 发挥自身作用,驱动最终目标的完成。
- 对话预设;这个节点在 ChatModel 中添加,可以设置对话的 AI 模型,也可以设置 MCP。ChatModel 可以支持流式对话。还可以把 ChatModel 注入到 ChatClient 中使用。
- 规划模式;为预设的关键词,让一个步骤流程知道以哪些关键信息进行运行。
- 顾问角色;在 Spring AI 中提供了一种更加优雅的访问外部元素信息的方式,顾问访问。通过顾问功能,增强对话。包括;上下文记忆、知识库、日志等。
- 工具加载;这里我们主要使用 MCP,也是目前市面最为流行的方式。本项目中用到的 MCP 就包括 AI 课程中第2阶段实现的 MCP 服务。
功能流程库表设计
- ai_agent_task_schedule,智能体任务调度配置表
- ai_agent,AI智能体配置表
- ai_agent_client,智能体-客户端关联表
- ai_client,AI客户端配置表
- 模型配置组;ai_client_model、ai_client_model_config、ai_client_model_tool_config
- 工具配置组;ai_client_tool_config、ai_client_tool_mcp
- 顾问配置组;ai_client_advisor、ai_client_advisor_config
- 提示词配置;ai_client_system_prompt、ai_client_system_prompt_config
- 知识库配置;ai_rag_order
多数据源设计优势
- 数据隔离性: 业务数据和向量数据完全分离,互不影响,提升系统稳定性
- 性能优化: 针对不同数据类型和访问模式优化连接池参数
- 技术栈适配: MySQL使用MyBatis ORM,PgVector使用JdbcTemplate,各取所长
- 扩展性强: 可以轻松添加更多类型的数据源,如Redis、MongoDB等
- 配置灵活: 支持外部配置文件,便于不同环境的参数调整
- 故障隔离: 一个数据源的问题不会影响另一个数据源的正常使用
根据 Ai Agent 案例,设计库表
如图,为对应的Ai Agent 案例代码,映射出要拆分的库表设计;
首先,整个代码构建的整个 Ai Agent 最小化单元服务,我们可以根据这样的服务信息设计出库表结构。
- 第一步,从上到下,OpenAiApi 是最基础单元结构,可以被多个 OpenAiChatModel 使用,它可以被拆分出第一张表。
- 第二步,构建 OpenAiChatModel,这个阶段,需要 openAiApi、model对话模型、tool mcp 工具。其中model对话模型时一种固定固定资源,可以直接放到 ai_client_model 模型中,而 openAiApi、mcp 工具,都属于复杂配置,则需要额外的外部关联来衔接。也就是后面的 ai_client_config 配置,用于配置衔接关系。
- 第三步,ChatClient 对话客户端,这部分的实例化过程都是和外部其他的资源关联,本身表设计只要有一个客户端的唯一id和客户端的描述介绍即可。
- 第四步,给 mcp 增加一个表,mcp 服务是非常重要的,有 mcp 才有 agent 服务。mcp 的启动有 stido、sse 两种方式,每种方式都有对应的配置文件 json 数据。
- 第五步,defaultSystem 系统提示词,需要单独拆分出来。提示词等于智能体的大脑,也有人说,其实 Ai Agent 就是 prompt 的堆叠,所以写提示词是很重要的。
- 第六步,advisor 顾问角色,在 Spring Ai 框架中,以顾问的方式,访问记忆上下文,知识库资源,所以这部分也要单独设计库表。
- 第七步,设计一个 ai_client_config,用于配置;api、model、client、prompt、mcp、advisor的衔接关系。
- 第八步,设计 ai_agent、ai_agent_flow_config,也就是一个 ai agent,是可以连续调用多个 ai client 客户端的。
- 第九步,设计 ai_agent_stask_schedule 任务,这是一种触达手段,可以把配置好的任务,让 task 定时执行,如自动发帖、系统异常巡检、舆情风险检测、系统配置变更、运营活动报表等。
- 第十步,ai_client_rag_order,是知识库表,用于上传知识库做一个记录,这样顾问角色就可以访问知识库内容了。
注意;chat_client 客户端的初始化过程中,也可以增加 mcp 服务,这部分在 chat_model 模型构建中,也可以增加 mcp,选择在 chat_model 增加即可。
多数据源和Mapper配置
为应用程序配置pgvector(向量库)、mysql(业务库)两套数据源,同时基于库表,编写基础设施层 Mapper 操作。 对于数据库表的 Mapper 编写,是一种固定的结构化代码,可以通过 MyBatis 工具生成,也可以使用 AI 编码工具处理。不过对于新人学习来说,更建议在这个阶段,通过手动的方式进行配置编写,这样可以更熟悉库表的设计和字段的理解。尤其是报错后,还可以基于报错排查错误增加编程经验。
- 首先,为了让应用程序具备多数据源链接,则需要增加一个扩展的 DataSourceConfig 配置类,来自己实现数据源的加载。这部分会替代原本配置到 yml 文件中,由 Spring 加载数据源的过程。
- 之后,根据不同类型的数据源,注入到 AI 向量库使用场景和 MyBatis 业务使用场景中。
引入hikari连接池的池化技术,可以一次性初始化多个连接,谁使用就拿去,用完放回来,可以提高数据库的吞吐量。不需要每次都建立新连接。
数据加载模型设计
在关于 Ai Agent 的功能实现中,有一个非常重要处理步骤,就是要想办法动态的实例化来自于用户配置的API、对话模型、MCP、顾问角色以及提示词等。 还要思考怎么让程序来加载和实例化 Ai Agent 所需的各项组件。如,客户端的实例化、对话模型的实例化等。 通过责任链和规则树实现(集成到了通用组件项目中)。
- 首先,整个 Ai Agent 的实例化过程,就是各项组件的创建和组装的过程。那么,为了让整体的实现代码更易于维护,我们可以把这样的创建过程,通过规则树的方式进行串联实现。
- 之后,本节我们先把目标缩小到关于数据加载部分,因为后续所有的 Ai Agent 组件实例化的过程,都是需要基础数据的提供。所以组装数据就显得尤为重要了
- 整个agent领域就是为了动态化的加载各个模块
- adapter:适配层用于完成数据的获取,整个agent需要什么样的数据结构,就定义对应的接口方法,之后由基础设施层实现,通过pom引入domain领域层。之后实现适配接口,用dao、redis、http等方式完成数据的组装,返回给domain领域层。 好处是适配和防腐,如果将来基础领域层有变动,也不会影响到领域层的服务方法。
- model:领域对象层,为了满足service服务创建的对象。一整个服务的实现,数据需要通过领域对象来传递。基本你需要什么对象,就在这部分创建。
- service:服务实现层,完成具体的逻辑服务实现,本节重点是数据的加载策略。
类关系
- 首先,抽取后的类的关系结构。以 AbstractArmorySupport 为扩展支撑类,实现第一个 RootNode 节点。
- 之后,本身 Node 的用途是为了加载数据,但加载数据本身又有很多种类,所以这里要做一个数据加载策略。以 ILoadDataStrategy 接口实现多个数据加载实现类。目前只体现了2个,后续随着功能的开发,再继续增加。
- 最后,整个数据的加载都是从基础设施层实现类,AgentRepository 通过 dao 操作,完成各项数据的加载。
- ArmoryCommandEntity:对象用于请求加载数据策略。因为我们本身加载数据,无非就是告诉策略,你要加载哪类的数据策略,之后给一个ID集合。
- AiClientLoadDataStrategy:Client 数据策略,一个 client 加载,要顺序的加载所有的资源。
- AiClientModelLoadDataStrategy:Mode 数据策略,
- doApply 处理逻辑,get 获取下个节点。
- 注册对象AbstractArmorySupport.registerBean提供注册Bean到Spring容器的方法。getBean这个获取已经注册好的bean的方法(这里能自动转换类型)。
- 在项⽬中路由抽象⽅法是
public abstract class AbstractArmorySupport extends AbstractMultiThreadStrategyRouter<AiAgentEngineStarterEntity, DefaultArmoryStrategyFactory.DynamicContext, String>
上述为代码分支的结果
动态实例化客户端API
完善数据加载操作,动态实例化客户端API(ai_client_api)并注册到 Spring 容器。
这是整个 armory 动态装配 Ai Agent 节点的第一步,涉及到了数据的获取,对象的创建和 Spring 容器的 Bean 对象注册。能看懂本节的操作,基本后续一直到整个 Ai Agent 构建也就都可以看懂了。
- 整个 AI Agent 的实例化过程,就是各项组件的创建和组装的过程。为了让整体的实现代码更易于维护,我们把这样的创建过程,通过 规则树的方式 进行串联实现。这种设计模式的优势在于:模块化设计、易于扩展、代码复用度高。
- 从开始节点看,依次执行,数据构建节点、API构建节点。在 API 构建的过程中,会检查上下文中是否存在已经从数据库获取的数据,之后依次循环构建并注册到 Spring 容器。
AbstractArmorySupport:Spring Bean 容器,提供registerBean和getBean方法,具体流程
- 第一步:获取Bean工厂,DefaultListableBeanFactory 是Spring容器的核心实现类。通过它可以动态管理Bean的生命周期。 强转是因为applicationContext返回的是接口, 转换成DefaultListableBeanFactory来使用高级功能。
- 第二步:构建Bean定义,使用 BeanDefinitionBuilder 创建Bean定义。genericBeanDefinition(beanClass, () -> beanInstance) 指定Bean类型和实例供应商。设置作用域为单例模式( SCOPE_SINGLETON )
- 第三步:处理Bean冲突,检查是否已存在同名Bean,如果存在,先移除旧的Bean定义,确保新Bean能够正确注册。
- 第四步:注册新Bean,将新的Bean定义注册到Spring容器。
AiClientApiNode:节点构建
- doApply 是处理业务流程的方法区,在这里首先通过上下文获取加载的 AIClientApi 数据。如果数据为空则返回为null。后续这块也可以处理为路由到下一个节点继续处理其他节点实例化。
- 接下来,for循环的过程,就是不断的创建 OpenAiApi 对象,之后注册到 Spring 容器中。完成后,执行 router 路由到下一个节点。
- router 执行后,会走到 get 方法,目前设置的是 defaultStrategyHandler,也就是不执行下一个节点。后续会随着功能开发来修改。
RootNode:节点路由
- RootNode 节点的要修改 get 方法,路由到 aiClientApiNode。也就是数据加载完成后,要走到下一个节点进行 api 构建操作。
- router 的操作是在设计模式模板类里,可以到上一层的方法中查看具体的路由操作。
multiThread方法
从大的框架上来说就是创建了一批要查询的任务,然后异步多线程同时执行查询,并在执行完查询后,将值存入dynamicContext中。 其中每个repository中的查询方法, 其实可以简单看作就是填充好VO对象的一个过程, 调用多个dao层接口, 组装数据库中的数据成实际的业务中会使用的VO对象。
为什么需要转化成VO对象? 某些地方能直接使用po对象但是还是多此一举的创建了一个几乎一模一样的VO对象?
VO和Entity对象是业务中实际上使用的对象, 也是实际上在各个方法之间传递, 是"业务实体", 而持久化对象是面向库表的, 是我们从库表中读取出来的结构, 往往不会是和我们要的业务实体是一样的形式, 因为库表之间往往会进行解耦比如通过范式约束设计, 最后呈现出来的形式并不是和业务直接对应的
创建一个一样的VO对象是因为我们这里的业务实体刚好和PO对象相差无几, 一方面是为了保持编码风格的统一, 另一方面是为了保证以后的拓展性, 如果这里的业务发生了什么变化, 我们修改VO对象就行, 总不能修改PO对象吧
VO(及其所在的聚合根Entity)是承载核心业务规则和逻辑的地方。直接使用PO会导致业务规则无法内聚在合适的对象中,散落在服务层或更糟的地方,违反高内聚原则。
同时使用VO对象还能封装简单的领域行为
动态实例化对话模型
整个 ChatModel 对话模型,所需的元素包括;ai api、tool mcp 两块内容。那么本节我们就分别通过不同的 Node 节点实现这些元素的实例化和 ChatModel 构建。
- 首先,如图 RootNode 负责数据加载,将构建节点元素的数据依次加载到内存中(写入到上下文里)
- 之后,除了上一节完成的 API 节点处理后,开始创建 MCP 服务的创建,之后是 ChatModel 对话模块的创建。因为 ChatModel 创建的时候会需要用到的 api、mcp 两个元素。
重写了 beanName 方法,为每个顾问对象生成唯一的 Bean 名称。
实例化对话客户端
本节我们要进行 advisor 顾问角色的实例化,之后进行 ChatClient 对话客户端的实例化。
首先,以构建 AiClientNode 的对话客户端为目的,已经完成了相关的元素实例化步骤。本节这里要处理的是,顾问角色的构建,以及构建 AiClientNode 节点。
之后,AiClientNode 的构建,是关联了其他各项元素的,所以在构建时,需要在 AiClientNode 节点,从 Spring 容器通过 getBean 的方式,检索到对应的各项元素。
注意,ai_client_system_prompt 系统提示词,需要修改为 Map 结构数据。这样更方便我们从数据里获取,哪些是属于当前 AiClientNode 构建时所需的元素。
增加 AiClientAdvisorNode 节点,获取多线程加载数据 AiClientAdvisorVO 并根据顾问角色类型,ChatMemory、RagAnswer 分别构建不同的顾问类型。
- AiClientAdvisorNode继承自 AbstractArmorySupport ,而 AbstractArmorySupport 又继承自 AbstractMultiThreadStrategyRouter ,这一继承体系为其提供了多线程路由和 Spring Bean 管理能力。
AiClientVO 客户端节点的构建,则需要把所有关联到的元素,依次按照Bean的名称,从 Spring 容器获取。
链接处理 :AiClientModelNode -> AiClientAdvisorNode -> AiClientNode。每个节点构建完成后,就开始关联到下一个节点。
Agent执行链路分析
通过现有实现的动态化构建 Ai API、Model、Client、Tool(MCP)、Advisor(记忆、RAG)、Prompt,完成 Ai Agent 服务处理。 Ai Agent 的处理过程也是分为几类的,用于适应不同的场景使用;
- 固定N个步骤,这类的一般是配置工作流的,提高任务执行的准确性。如,一些检索资料、发送帖子、处理通知等。
- 顺序循环调用,配置 Agent 要执行的多个 Client 端,以此顺序执行。适合一些简单的任务关系,并已经分配好的动作,类似于1的方式。
- 智能动态决策,这类是目前市面提供给大家使用的 Agent 比较常见的实现方式,它会动态的规划执行动作,完成行动步骤,观察执行结果,判断完成状态和步骤。并最终给出结果。
Agent执行链路设计
针对Ai Agent 执行链路的分析,使用规则树设计可执行链路节点。
AI Agent动态多轮执行策略流程图
- 给入口保留一个多策略选择,以适应不同场景的多类型Agent选择使用,后续会在 agent 配置表增加策略选择属性来区分调用。本节我们先处理一个 AutoAgent 的实现。
- 之后,进入到关键地方,在上一节 AutoAgentTest 章节,设计了一套自动化 Agent 执行方法,通过 for 循环处理。这里我们通过规则树,分多个多个节点步骤执行,节点间可循环调用,增强整体的灵活性。
- 最后,以用户提问到所有的步骤执行完成后,进入到结束环节,产生结果。
RootNode:数据加载节点,加载数据。并把数据填充到上下文中。
Step1AnalyzerNode:任务分析节点,
Step2PrecisionExecutorNode:精准执行节点,执行具体的任务步骤操作
Step3QualitySupervisorNode:质量监督节点,检测整个过程生成的内容质量是否可靠的。 注意:router 做完路由后,要判断是走到最终节点,还是继续回到 step1AnalyzerNode 继续执行,这个过程是根据生成内容是否完成目标来决定的(也包括是否超过最大步骤)。
Step4LogExecutionSummaryNode:执行总结节点,
Agent服务接口和UI对接(第一版AutoAgent效果)
从Agent服务的装配到接口调用和响应的关系图
- 以程序启动为开始,进行自动化装配。这个过程我们先把一些想预先启动的数据库中的 agent 配置所需的 client 客户端进行服务初始化。之后写入到 Spring 容器,方便在执行 Agent 时进行使用。
- 客户端(UI),进行 POST 接口请求,这个过程需要封装一个 SSE 流式响应的接口,让 Step 1~4 各个执行步骤,把过程信息写入到流式接口。这里要注意,需要给接口返回的对象 添加上对应的类型(什么步骤、什么节点、什么过程),以便于反馈给用户 Agent 在做什么。
- 首先,在 api 层下定义 Agent 服务接口,之后由 trigger 层实现接口。api 层是一个统一对外的服务接口标准,单独定义更好管理,也适用于 rpc 对外提供 jar 的使用方式。
- 之后,app 层,程序启动时,进行自动装配。装配的数据(客户端),配置到 application-dev.yml 中。
- 最后,就是 trigger 层的接口,调用 domain 领域层的自动 agent 策略了。trigger 接口是 SSE 的异步流式响应接口,所以要渗透到 domain 领域层增加 ResponseBodyEmitter 发送各个阶段的数据。
Agent-ELK日志分析场景
增加 Agent-ELK 日志分析的实际应用场景,通过 Agent 根据用户诉求,自主分析、规划、执行和输出结果,来帮助我们对日志检索的提效。 ELK(或自研) 是各个互联网公司中都有的一套分布式日志设备,以便于研发在遇到线上系统报警和运营反馈事故问题时,快速检索日志。但往往这种检索的日志的方式都是非常耗时的,所以增加 Agent 方式来辅助提效是非常有必要的。
- 虚线框内为模拟的系统的应用日志,部署一套 ELK 之后通过脚本把日志数据写入到 ELK。
- 为这套场景增加一套新的 Ai Agent 描述话术,在执行 ELK 日志分析的时候,我们先手动选择出要使用的 Ai Agent 服务。这样它就可以以 ELK 对应的 Prompt 话术分析方式使用了。
ELK 使用教程采集系统日志 Elasticsearch、Logstash、Kibana
检索到大营销的运行日志,进行分析。
Agent-Prometheus监控分析场景
扩展增加 Prometheus(普罗米修斯监控) 监控系统,让 Ai Agent 具备智能监控问题分析场景。基于的是 Ai MCP Prometheus + Agent Prompt(分阶段提示词),来完成自动化分析、规划、执行、检测、输出的智能监控系统。
Docker部署grafana,Prometheus + Grafana 监控,验证 Hystrix 超时熔断
如果业务系统也配置了该监控,就可以监控业务系统的数据进行分析。