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 动态任务自动执行。 img_6.png

AI智能体AI助理聊天机器人
用途自主、主动地执行任务协助用户执行任务自动执行简单任务或对话
功能可执行复杂多步骤操作;学习和适应;独立做决策响应请求/提示,提供信息并完成简单任务;可推荐操作,但决策由用户做遵循预定义规则;有限学习能力;基本互动
交互主动;以目标为导向被动;响应用户请求被动;响应触发器或命令

系统设计

img_18.png

  • 以 ChatClient 为中心,设置;Ai模型、对话预热、规划模式、顾问、工具,完成 LLM ChatClient 构建。这些注入的元素属性,驱动着 Agent 功能的实现。
  • 会话时,从输入端到输出端,可以顺序执行多个 ChatClient。通过这样的方式,让不同配置的 ChatClient 发挥自身作用,驱动最终目标的完成。
  • 对话预设;这个节点在 ChatModel 中添加,可以设置对话的 AI 模型,也可以设置 MCP。ChatModel 可以支持流式对话。还可以把 ChatModel 注入到 ChatClient 中使用。
  • 规划模式;为预设的关键词,让一个步骤流程知道以哪些关键信息进行运行。
  • 顾问角色;在 Spring AI 中提供了一种更加优雅的访问外部元素信息的方式,顾问访问。通过顾问功能,增强对话。包括;上下文记忆、知识库、日志等。
  • 工具加载;这里我们主要使用 MCP,也是目前市面最为流行的方式。本项目中用到的 MCP 就包括 AI 课程中第2阶段实现的 MCP 服务。

功能流程img_7.png库表设计img_8.png

  • 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

多数据源设计优势

  1. 数据隔离性: 业务数据和向量数据完全分离,互不影响,提升系统稳定性
  2. 性能优化: 针对不同数据类型和访问模式优化连接池参数
  3. 技术栈适配: MySQL使用MyBatis ORM,PgVector使用JdbcTemplate,各取所长
  4. 扩展性强: 可以轻松添加更多类型的数据源,如Redis、MongoDB等
  5. 配置灵活: 支持外部配置文件,便于不同环境的参数调整
  6. 故障隔离: 一个数据源的问题不会影响另一个数据源的正常使用

根据 Ai Agent 案例,设计库表

img_17.png 如图,为对应的Ai Agent 案例代码,映射出要拆分的库表设计; img_9.png 首先,整个代码构建的整个 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 编码工具处理。不过对于新人学习来说,更建议在这个阶段,通过手动的方式进行配置编写,这样可以更熟悉库表的设计和字段的理解。尤其是报错后,还可以基于报错排查错误增加编程经验。 img_10.png

  • 首先,为了让应用程序具备多数据源链接,则需要增加一个扩展的 DataSourceConfig 配置类,来自己实现数据源的加载。这部分会替代原本配置到 yml 文件中,由 Spring 加载数据源的过程。
  • 之后,根据不同类型的数据源,注入到 AI 向量库使用场景和 MyBatis 业务使用场景中。

引入hikari连接池的池化技术,可以一次性初始化多个连接,谁使用就拿去,用完放回来,可以提高数据库的吞吐量。不需要每次都建立新连接。

数据加载模型设计

在关于 Ai Agent 的功能实现中,有一个非常重要处理步骤,就是要想办法动态的实例化来自于用户配置的API、对话模型、MCP、顾问角色以及提示词等。 还要思考怎么让程序来加载和实例化 Ai Agent 所需的各项组件。如,客户端的实例化、对话模型的实例化等。 通过责任链和规则树实现(集成到了通用组件项目中)。 img_11.png

  • 首先,整个 Ai Agent 的实例化过程,就是各项组件的创建和组装的过程。那么,为了让整体的实现代码更易于维护,我们可以把这样的创建过程,通过规则树的方式进行串联实现。
  • 之后,本节我们先把目标缩小到关于数据加载部分,因为后续所有的 Ai Agent 组件实例化的过程,都是需要基础数据的提供。所以组装数据就显得尤为重要了

img_19.png

  • 整个agent领域就是为了动态化的加载各个模块
  • adapter:适配层用于完成数据的获取,整个agent需要什么样的数据结构,就定义对应的接口方法,之后由基础设施层实现,通过pom引入domain领域层。之后实现适配接口,用dao、redis、http等方式完成数据的组装,返回给domain领域层。 好处是适配和防腐,如果将来基础领域层有变动,也不会影响到领域层的服务方法。
  • model:领域对象层,为了满足service服务创建的对象。一整个服务的实现,数据需要通过领域对象来传递。基本你需要什么对象,就在这部分创建。
  • service:服务实现层,完成具体的逻辑服务实现,本节重点是数据的加载策略。

类关系img_12.png

  • 首先,抽取后的类的关系结构。以 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 构建也就都可以看懂了。 img_13.png

  • 整个 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对象还能封装简单的领域行为

img_23.png

动态实例化对话模型

整个 ChatModel 对话模型,所需的元素包括;ai api、tool mcp 两块内容。那么本节我们就分别通过不同的 Node 节点实现这些元素的实例化和 ChatModel 构建。 img_14.png

  • 首先,如图 RootNode 负责数据加载,将构建节点元素的数据依次加载到内存中(写入到上下文里)
  • 之后,除了上一节完成的 API 节点处理后,开始创建 MCP 服务的创建,之后是 ChatModel 对话模块的创建。因为 ChatModel 创建的时候会需要用到的 api、mcp 两个元素。

重写了 beanName 方法,为每个顾问对象生成唯一的 Bean 名称。

实例化对话客户端

本节我们要进行 advisor 顾问角色的实例化,之后进行 ChatClient 对话客户端的实例化。 img_15.png

  • 首先,以构建 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 服务处理。 img_16.png Ai Agent 的处理过程也是分为几类的,用于适应不同的场景使用;

  1. 固定N个步骤,这类的一般是配置工作流的,提高任务执行的准确性。如,一些检索资料、发送帖子、处理通知等。
  2. 顺序循环调用,配置 Agent 要执行的多个 Client 端,以此顺序执行。适合一些简单的任务关系,并已经分配好的动作,类似于1的方式。
  3. 智能动态决策,这类是目前市面提供给大家使用的 Agent 比较常见的实现方式,它会动态的规划执行动作,完成行动步骤,观察执行结果,判断完成状态和步骤。并最终给出结果。

Agent执行链路设计

针对Ai Agent 执行链路的分析,使用规则树设计可执行链路节点。

AI Agent动态多轮执行策略流程图img_24.png

  • 给入口保留一个多策略选择,以适应不同场景的多类型Agent选择使用,后续会在 agent 配置表增加策略选择属性来区分调用。本节我们先处理一个 AutoAgent 的实现。
  • 之后,进入到关键地方,在上一节 AutoAgentTest 章节,设计了一套自动化 Agent 执行方法,通过 for 循环处理。这里我们通过规则树,分多个多个节点步骤执行,节点间可循环调用,增强整体的灵活性。
  • 最后,以用户提问到所有的步骤执行完成后,进入到结束环节,产生结果。

RootNode:数据加载节点,加载数据。并把数据填充到上下文中。

Step1AnalyzerNode:任务分析节点,

Step2PrecisionExecutorNode:精准执行节点,执行具体的任务步骤操作

Step3QualitySupervisorNode:质量监督节点,检测整个过程生成的内容质量是否可靠的。 注意:router 做完路由后,要判断是走到最终节点,还是继续回到 step1AnalyzerNode 继续执行,这个过程是根据生成内容是否完成目标来决定的(也包括是否超过最大步骤)。

Step4LogExecutionSummaryNode:执行总结节点,

Agent服务接口和UI对接(第一版AutoAgent效果)

从Agent服务的装配到接口调用和响应的关系图 img_25.png

  • 以程序启动为开始,进行自动化装配。这个过程我们先把一些想预先启动的数据库中的 agent 配置所需的 client 客户端进行服务初始化。之后写入到 Spring 容器,方便在执行 Agent 时进行使用。
  • 客户端(UI),进行 POST 接口请求,这个过程需要封装一个 SSE 流式响应的接口,让 Step 1~4 各个执行步骤,把过程信息写入到流式接口。这里要注意,需要给接口返回的对象 添加上对应的类型(什么步骤、什么节点、什么过程),以便于反馈给用户 Agent 在做什么。

img_26.png

  1. 首先,在 api 层下定义 Agent 服务接口,之后由 trigger 层实现接口。api 层是一个统一对外的服务接口标准,单独定义更好管理,也适用于 rpc 对外提供 jar 的使用方式。
  2. 之后,app 层,程序启动时,进行自动装配。装配的数据(客户端),配置到 application-dev.yml 中。
  3. 最后,就是 trigger 层的接口,调用 domain 领域层的自动 agent 策略了。trigger 接口是 SSE 的异步流式响应接口,所以要渗透到 domain 领域层增加 ResponseBodyEmitter 发送各个阶段的数据。

Agent-ELK日志分析场景

增加 Agent-ELK 日志分析的实际应用场景,通过 Agent 根据用户诉求,自主分析、规划、执行和输出结果,来帮助我们对日志检索的提效。 ELK(或自研) 是各个互联网公司中都有的一套分布式日志设备,以便于研发在遇到线上系统报警和运营反馈事故问题时,快速检索日志。但往往这种检索的日志的方式都是非常耗时的,所以增加 Agent 方式来辅助提效是非常有必要的。 img_27.png

  • 虚线框内为模拟的系统的应用日志,部署一套 ELK 之后通过脚本把日志数据写入到 ELK。
  • 为这套场景增加一套新的 Ai Agent 描述话术,在执行 ELK 日志分析的时候,我们先手动选择出要使用的 Ai Agent 服务。这样它就可以以 ELK 对应的 Prompt 话术分析方式使用了。

ELK 使用教程采集系统日志 Elasticsearch、Logstash、Kibanaopen in new window

检索到大营销的运行日志,进行分析。

Agent-Prometheus监控分析场景

扩展增加 Prometheus(普罗米修斯监控) 监控系统,让 Ai Agent 具备智能监控问题分析场景。基于的是 Ai MCP Prometheus + Agent Prompt(分阶段提示词),来完成自动化分析、规划、执行、检测、输出的智能监控系统。 img_28.png

Docker部署grafana,Prometheus + Grafana 监控,验证 Hystrix 超时熔断open in new window

如果业务系统也配置了该监控,就可以监控业务系统的数据进行分析。 img_29.png