发布时间:2026/7/11 7:12:45
SpringBoot集成LangChain4j构建生产级AI Agent 1. 项目概述为什么一个 SpringBoot LangChain4j 的 AI Agent 不再是“玩具级”工程你有没有在面试时被问过“SpringBoot 自动装配原理是什么”或者“如何在 SpringBoot 3.x 中优雅地管理多数据源”——这些问题背后考的从来不是你能不能背出EnableAutoConfiguration的源码而是你是否真正理解 SpringBoot 的设计哲学约定优于配置抽象高于实现让开发者聚焦业务而非胶水代码。而今天我们要聊的这个项目标题——“实战演示SpringBoot 集成 LangChain4j 快速发布 AI Agent”恰恰是这一哲学在 AI 时代的最新、最硬核的落地实践。它绝不是网上泛滥的“三行代码调用 ChatGPT”的 Demo。它是一套可直接嵌入企业级后端服务的、生产就绪Production-Ready的 AI 能力交付框架。核心关键词SpringBoot、LangChain4j、AI Agent每一个都指向一个明确的工程价值点SpringBoot是 Java 生态的事实标准它解决的是“如何把一个功能稳定、可监控、可扩展地跑在服务器上”LangChain4j不是另一个 LLM SDK它是 Java 世界的 LangChain解决的是“如何把大模型从一个黑盒 API变成一个可编排、可记忆、可调用工具、可持久化状态的软件组件”而AI Agent则是最终交付形态——它不是一个问答接口而是一个能记住你是谁、知道你上周问过什么、能帮你查数据库、能调用计算器、甚至能生成图片的“数字同事”。我做过不下 20 个 AI 相关的 PoC概念验证踩过的最大坑就是把 AI 当成一个“新 API”来用。结果呢前端传个字符串后端拼个 prompt调一次 OpenAI返回一个 JSON。看似跑通了但一到真实场景就崩用户连续问两轮Agent 就忘了第一轮换了个模型所有 prompt 都要重写想加个“查订单”功能就得硬编码一个 HTTP 调用线上跑了三天内存暴涨发现聊天记录全堆在 JVM 堆里没释放……这些都不是技术问题是架构问题。而 SpringBoot LangChain4j 的组合就是为了解决这些架构问题而生的。它把 AI Agent 的四大核心能力——模型接入、提示工程、会话管理、工具调用——全部纳入了 Spring 的生命周期和生态体系。这意味着你可以用Autowired注入一个 Agent用Scheduled给它加定时任务用Transactional保证它调用数据库时的数据一致性用 Actuator 监控它的响应延迟和 token 消耗。这才是“快速发布”的真正含义不是写得快而是上线快、运维快、迭代快、兜底快。所以如果你是一名 Java 工程师正在看这篇文字那么请记住这不是一篇教你“怎么调用大模型”的入门教程而是一份来自一线战场的《AI Agent 工程化落地手册》。它不讲“什么是 LLM”因为你能看到这个标题说明你已经过了那个阶段它也不讲“LangChain4j 和 SpringAI 有什么区别”因为答案很简单——SpringAI 是 Spring 官方的实验性项目而 LangChain4j 是社区驱动、文档完善、插件丰富、已被大量生产项目验证的成熟方案。我们只讲一件事如何用你每天都在写的 SpringBoot 代码把一个“聪明的对话机器人”变成你系统里一个普普通通、却又无比强大的 Service Bean。2. 核心设计思路为什么是 SpringBoot LangChain4j而不是其他组合2.1 技术选型背后的三层逻辑语言、生态、心智模型很多初学者看到 “AI Agent” 这个词第一反应是 Python LangChain。这没错Python 确实是 AI 开发的首选语言。但当你需要把它放进一个已有的、由 Java 构建的亿级用户核心交易系统里时Python 就立刻从“首选”变成了“障碍”。这里没有优劣之分只有场景适配。而 SpringBoot LangChain4j 的组合其合理性建立在三个不可动摇的底层逻辑之上。第一层语言与性能的刚性约束。Java 的 JIT 编译、成熟的 GC 策略、以及对高并发、低延迟场景的极致优化是 Python 的 GIL全局解释器锁和动态类型系统短期内无法比拟的。一个面向 C 端用户的客服 AgentQPS每秒查询率轻松破千平均响应时间必须压在 800ms 以内。LangChain4j 在设计之初就深度考虑了这一点它的ChatMemory接口默认使用InMemoryChatMemoryStore底层是线程安全的ConcurrentHashMap它的StreamingChatModel支持真正的 Server-Sent Events (SSE) 流式响应避免了传统 REST API 的长连接阻塞问题。这些都是 Java 生态独有的“肌肉记忆”不是靠后期优化能补上的。第二层生态与治理的现实需求。一个企业级应用从来不是孤零零的一个 Jar 包。它必然要和 Redis 做缓存穿透防护和 RabbitMQ 做异步消息解耦和 SkyWalking 做全链路追踪和 Prometheus 做指标采集。SpringBoot 的starter机制就是为这种“拼图式开发”而生的。LangChain4j 完美继承了这一基因。你看它的依赖命名langchain4j-open-ai-spring-boot-starter、langchain4j-ollama-spring-boot-starter、langchain4j-community-dashscope-spring-boot-starter。这不仅仅是个名字它代表了一整套开箱即用的自动配置ConfigurationProperties绑定 yml 配置、ConditionalOnClass控制加载时机、Bean注册核心组件。你只需要在pom.xml里加一行依赖在application.yml里写几行配置一个能对接 DeepSeek、Ollama 或阿里百炼的ChatModelBean 就自动出现在你的 Spring 容器里了。这种“声明即所得”的体验是任何 Python 的pip install都无法提供的。它把 AI 能力从一个需要手动管理生命周期的“外部服务”降维成了一个和JdbcTemplate一样顺手的“内部组件”。第三层团队心智模型的平滑过渡。这是最容易被忽视却最关键的一点。一个拥有 5 年 SpringBoot 开发经验的工程师他/她的大脑里已经形成了牢固的“Spring 思维”Service是业务逻辑Repository是数据访问RestController是对外接口。如果现在要他/她去学一套全新的、基于Chain和AgentExecutor的 Python 框架学习成本是巨大的。而 LangChain4j 的AiService注解就是一次精妙的“认知嫁接”。它让你用最熟悉的interfaceAutowired的方式去定义一个 AI Agent 的能力契约。SystemMessage(你是我的财务顾问)对应着 Spring 的Value(${app.role})UserMessage(帮我分析下上季度的营收)对应着 Controller 层的RequestBodyTool标记的方法本质上就是一个被Service管理的、带业务语义的普通 Java 方法。这种设计不是为了炫技而是为了让 AI 工程化这件事能无缝融入现有团队的技术栈和协作流程中。它降低的不是技术门槛而是组织变革的阻力。2.2 架构全景图从单点调用到可编排 Agent 的跃迁理解了“为什么选”接下来就要搞懂“它长什么样”。一个典型的、生产可用的 SpringBoot LangChain4j AI Agent其架构绝非简单的“Controller - ChatModel - LLM”。它是一个分层清晰、职责分明的四层结构第一层接入层API Gateway / Web Layer这是用户无论是前端、小程序还是另一个微服务触达 Agent 的唯一入口。它通常是一个RestController负责接收原始请求如POST /api/chat进行基础校验鉴权、限流、参数合法性检查然后将清洗后的数据转发给下一层。关键点在于这一层绝不直接操作 LLM。它只做协议转换和流量控制。第二层编排层Orchestration Layer这是整个 Agent 的“大脑”。它由一个或多个AiService接口的实现类构成。AiService是 LangChain4j 提供的最高阶抽象它把一次复杂的 AI 交互封装成了一个普通的 Java 方法调用。例如AiService( chatModel qwenChatModel, chatMemoryProvider mongoChatMemoryProvider, tools {orderQueryTool, calculatorTool} ) public interface FinanceAgent { SystemMessage(fromResource prompts/finance-advisor.txt) String analyzeRevenue(MemoryId String sessionId, UserMessage String query); }这段代码短短五行就定义了一个具备身份设定system prompt、会话隔离memoryId、工具调用tools和持久化记忆mongoChatMemoryProvider的完整 Agent。SpringBoot 启动时LangChain4j 的AiServiceAutoConfiguration会扫描所有AiService接口并利用AiServices.builder()动态生成其实现类。这个过程和 Spring 生成Mapper接口的代理类原理完全一致。这就是“编排”的力量你不用写一行胶水代码就能把模型、记忆、工具这三大要素像搭积木一样组合起来。第三层能力层Capability Layer这是 Agent 的“四肢”。它包含所有被AiService所依赖的具体能力组件ChatModel负责与大模型通信。它可以是QwenChatModel对接阿里百炼、OllamaChatModel对接本地 Ollama、甚至是自研的CustomHttpChatModel对接公司私有模型平台。它们都实现了统一的ChatLanguageModel接口。ChatMemoryProvider负责为每个会话提供专属的记忆空间。MongoChatMemoryProvider会根据memoryId创建一个MessageWindowChatMemory其底层存储是MongoChatMemoryStore数据最终落盘到 MongoDB。Tools一组被Tool标记的、具备明确业务语义的 Java 方法。OrderQueryTool.findOrderByNumber(String orderNo)和CalculatorTool.sum(double a, double b)在 LangChain4j 看来都是可以被 LLM 动态选择并调用的“函数”。第四层基础设施层Infrastructure Layer这是整个系统的“地基”由 SpringBoot 原生提供MongoTemplate用于操作 MongoDB实现ChatMemoryStore的 CRUD。RestTemplate/WebClient作为ChatModel内部的 HTTP 客户端发送请求。ThreadPoolTaskExecutor为流式响应Streaming提供异步线程池避免阻塞 Tomcat 的主线程。这四层架构每一层都遵循单一职责原则层与层之间通过接口Interface而非实现Implementation进行耦合。这意味着你可以把MongoChatMemoryStore替换成RedisChatMemoryStore只需修改一个Bean的定义上层业务代码一行都不用动。这种设计正是 SpringBoot 工程哲学的终极体现让变化发生在一个地方让稳定成为一种常态。3. 核心细节解析从零开始构建一个可运行的 AI Agent3.1 环境准备与依赖管理BOM 是工程化的基石任何大型 Java 项目的起点永远是pom.xml。对于一个融合了 SpringBoot 和 LangChain4j 的项目依赖管理的复杂度远超普通项目。你不仅要协调 SpringBoot 自身的版本3.2.x还要协调 LangChain4j 的核心版本1.0.0-beta3、各个模型厂商的 starter 版本如langchain4j-ollama-spring-boot-starter以及可能引入的社区扩展如langchain4j-community-bom。如果采用传统的version硬编码方式不出三天你的pom.xml就会变成一个充满冲突和警告的“雷区”。解决方案是拥抱 Maven 的BOMBill of Materials机制。BOM 本身不是一个可执行的 jar而是一个特殊的 pom 文件它只做一件事为一组相关的依赖统一声明它们的版本号。SpringBoot 早已为我们提供了spring-boot-dependenciesBOM而 LangChain4j 社区也提供了官方的langchain4j-bom和langchain4j-community-bom。下面是我在线上项目中实际使用的、经过严格验证的pom.xml片段。它不是教科书式的示例而是我在处理过数十次依赖冲突后总结出的“黄金模板”properties !-- Java 编译版本强制要求 JDK 17 -- maven.compiler.source17/maven.compiler.target project.build.sourceEncodingUTF-8/project.build.sourceEncoding !-- SpringBoot 版本选择 LTS长期支持版本 -- spring-boot.version3.2.6/spring-boot.version !-- LangChain4j 核心版本beta3 是目前最稳定的 -- langchain4j.version1.0.0-beta3/langchain4j.version !-- MongoDB 驱动版本必须与 SpringBoot 3.x 兼容 -- mongodb.driver.version4.11.2/mongodb.driver.version /properties dependencyManagement dependencies !-- 导入 SpringBoot 的 BOM统一管理所有 spring-* 依赖 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-dependencies/artifactId version${spring-boot.version}/version typepom/type scopeimport/scope /dependency !-- 导入 LangChain4j 的 BOM统一管理所有 langchain4j-* 依赖 -- dependency groupIddev.langchain4j/groupId artifactIdlangchain4j-bom/artifactId version${langchain4j.version}/version typepom/type scopeimport/scope /dependency !-- 导入 LangChain4j 社区扩展的 BOM用于阿里百炼等 -- dependency groupIddev.langchain4j/groupId artifactIdlangchain4j-community-bom/artifactId version${langchain4j.version}/version typepom/type scopeimport/scope /dependency !-- 显式声明 MongoDB 驱动版本避免与 SpringBoot BOM 冲突 -- dependency groupIdorg.mongodb/groupId artifactIdmongodb-driver-sync/artifactId version${mongodb.driver.version}/version /dependency /dependencies /dependencyManagement dependencies !-- SpringBoot Web Starter必备 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- SpringBoot Data MongoDB Starter用于持久化记忆 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-mongodb/artifactId /dependency !-- LangChain4j 核心 Starter提供 AiService 等基础能力 -- dependency groupIddev.langchain4j/groupId artifactIdlangchain4j-spring-boot-starter/artifactId /dependency !-- LangChain4j 对接阿里百炼的 Starter -- dependency groupIddev.langchain4j/groupId artifactIdlangchain4j-community-dashscope-spring-boot-starter/artifactId /dependency !-- LangChain4j 对接 Ollama 的 Starter用于本地开发 -- dependency groupIddev.langchain4j/groupId artifactIdlangchain4j-ollama-spring-boot-starter/artifactId /dependency !-- Lombok简化 POJO提升开发效率 -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency /dependencies提示BOM 的导入顺序至关重要。spring-boot-dependencies必须放在最前面因为它定义了整个 Spring 生态的“基线版本”。LangChain4j 的 BOM 紧随其后确保其所有子模块的版本都与 SpringBoot 兼容。最后对于像 MongoDB 驱动这样可能被多个 BOM 声明的依赖我们显式地在dependencyManagement中再次声明以获得最终的“拍板权”。这是我在线上环境反复验证过的、最稳妥的顺序。3.2 配置文件详解yml 是你的第一道“安全阀”依赖搞定后下一步就是application.yml。这个文件是你与 LangChain4j 进行“对话”的第一张嘴。它不仅是配置更是你对 Agent 行为的第一次“编程”。一个配置错误可能导致 Agent 无法启动或在运行时产生难以排查的诡异行为。以下是我为生产环境精心打磨的application.yml配置它覆盖了所有关键场景# 1. 基础 Web 配置 server: port: 8080 servlet: context-path: /ai # 2. 日志配置调试 AI Agent 的生命线 logging: level: # 将 LangChain4j 的日志设为 DEBUG可以看到每一次 prompt 的组装、请求的发出、响应的解析 dev.langchain4j: DEBUG # 将 Spring 的 Web 日志设为 INFO避免被海量的 HTTP 请求日志淹没 org.springframework.web: INFO # 关键开启 OpenTelemetry 的日志便于后续接入 APM io.opentelemetry: WARN # 3. LangChain4j 核心配置 langchain4j: # 3.1 阿里百炼DashScope配置 community: dashscope: chat-model: # API Key 从环境变量读取绝对禁止硬编码 api-key: ${BAI_LIAN_API_KEY:your-default-key-for-dev} # 模型名称qwen-max 是旗舰版qwen-plus 是性价比之选 model-name: qwen-max # 温度值控制输出的随机性。生产环境建议设为 0.3~0.5保证结果稳定 temperature: 0.4 # 最大 token 数防止模型“话痨”导致响应超时 max-tokens: 2048 # 是否启用流式响应对于长文本生成至关重要 enable-streaming: true # 3.2 Ollama 配置仅用于本地开发和测试 ollama: chat-model: base-url: http://localhost:11434 model-name: qwen2:7b # 本地模型通常更“慢热”温度可以稍高 temperature: 0.7 timeout: PT60s # 4. MongoDB 配置持久化记忆的基石 spring: data: mongodb: # 使用 URI 方式简洁且支持所有高级选项 uri: mongodb://localhost:27017/ai_agent_db?connectTimeoutMS3000socketTimeoutMS5000 # 数据库名会自动创建 database: ai_agent_db # 5. 自定义配置为你的 Agent 添加业务属性 app: # Agent 的角色定义这个值会被注入到 system prompt 中 role: 资深金融分析师 # 默认会话有效期单位小时 session-ttl-hours: 24注意temperature参数是影响 AI 输出质量的“玄学”参数。我曾在线上环境将它从 0.8 降到 0.3结果发现客服回复的“专业感”提升了但“亲和力”下降了。最终我们采用了 A/B 测试的方式为不同业务线配置了不同的温度值面向投资决策的“分析报告”功能用 0.3面向用户咨询的“智能导购”功能用 0.6。这说明AI Agent 的配置本身就是一项需要持续优化的精细工作。3.3 实体类与持久化让记忆不再“转瞬即逝”一个没有记忆的 Agent就像一个得了失忆症的医生。它可能第一次告诉你“您的账户余额是 1000 元”第二次再问它却说“我不知道您的账户”。这在任何真实业务场景中都是不可接受的。因此ChatMemory的持久化是 AI Agent 工程化的第一个分水岭。LangChain4j 提供了MessageWindowChatMemory作为内存中的会话窗口但它默认的SingleSlotChatMemoryStore只是一个ListChatMessage程序一重启所有历史就灰飞烟灭。我们必须将其替换为一个真正的、可持久化的存储。3.3.1 设计一个健壮的 MongoDB 实体首先我们需要一个能准确映射到 MongoDB 文档的 Java 类。这个类的设计直接决定了后续查询的效率和扩展性。import lombok.Data; import lombok.NoArgsConstructor; import lombok.AllArgsConstructor; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; import org.bson.types.ObjectId; import java.time.LocalDateTime; import java.util.List; /** * ChatMessages: 会话消息实体类 * 一个 memoryId 对应一个会话一个会话可以包含多轮 UserMessage 和 AiMessage */ Data NoArgsConstructor AllArgsConstructor Document(chat_messages) // 映射到 MongoDB 的 collection 名 public class ChatMessages { /** * MongoDB 的主键使用 ObjectId保证全局唯一且高效索引 */ Id private ObjectId id; /** * 会话 ID业务层面的唯一标识例如user_123456 或 order_789012 * 这是我们在 MemoryId 注解中传入的值也是查询的主键 */ private String memoryId; /** * 存储该会话下的所有消息序列化为 JSON 字符串 * 为什么不直接存 ListChatMessage因为 MongoTemplate 对泛型集合的反序列化有兼容性问题 * 且 JSON 字符串更灵活未来可以轻松添加元数据如消息来源、审核状态 */ private String content; /** * 创建时间用于 TTLTime-To-Live索引自动清理过期数据 */ private LocalDateTime createdAt; /** * 更新时间用于审计 */ private LocalDateTime updatedAt; // 构造方法方便初始化 public ChatMessages(String memoryId, String content) { this.memoryId memoryId; this.content content; this.createdAt LocalDateTime.now(); this.updatedAt LocalDateTime.now(); } }这个设计有三个关键考量Id private ObjectId id这是 MongoDB 的最佳实践。ObjectId是一个 12 字节的 BSON 类型包含了时间戳、机器码、进程 ID 和一个随机数天然具备唯一性和时间序比用String或Long作为主键更高效、更可靠。private String content将ListChatMessage序列化为 JSON 字符串存储而非直接映射为嵌套对象。这规避了 Spring Data MongoDB 在处理复杂泛型集合时的反序列化陷阱也为未来添加字段如messageSource: user | agent | tool留出了空间。createdAtupdatedAt这两个时间戳是实现“会话生命周期管理”的基础。我们可以利用 MongoDB 的 TTL 索引自动删除超过app.session-ttl-hours的旧会话无需编写任何定时任务。3.3.2 实现一个线程安全的 MongoChatMemoryStore接下来是核心的ChatMemoryStore接口实现。这个类就是 LangChain4j 与 MongoDB 之间的“翻译官”。import dev.langchain4j.memory.ChatMemoryStore; import dev.langchain4j.memory.chat.ChatMessage; import dev.langchain4j.memory.chat.ChatMessageDeserializer; import dev.langchain4j.memory.chat.ChatMessageSerializer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.stereotype.Component; import java.util.*; /** * MongoChatMemoryStore: 基于 MongoDB 的会话记忆存储实现 * 它实现了 ChatMemoryStore 接口负责将 ChatMessage 列表的增删改查映射为 MongoDB 的 CRUD 操作。 */ Component // 让 Spring 管理这个 Bean public class MongoChatMemoryStore implements ChatMemoryStore { private final MongoTemplate mongoTemplate; Autowired public MongoChatMemoryStore(MongoTemplate mongoTemplate) { this.mongoTemplate mongoTemplate; } /** * 根据 memoryId 查询会话消息列表 * param memoryId 会话唯一标识 * return 消息列表如果不存在则返回空列表 */ Override public ListChatMessage getMessages(Object memoryId) { // 1. 构建查询条件查找 memoryId 字段等于传入值的文档 Criteria criteria Criteria.where(memoryId).is(memoryId.toString()); Query query new Query(criteria); // 2. 执行查询获取 ChatMessages 实体 ChatMessages chatMessages mongoTemplate.findOne(query, ChatMessages.class); // 3. 如果找到则反序列化 content 字段为 ChatMessage 列表否则返回空列表 if (chatMessages ! null chatMessages.getContent() ! null) { return ChatMessageDeserializer.messagesFromJson(chatMessages.getContent()); } return Collections.emptyList(); } /** * 更新或插入会话消息列表 * param memoryId 会话唯一标识 * param messages 消息列表 */ Override public void updateMessages(Object memoryId, ListChatMessage messages) { // 1. 将消息列表序列化为 JSON 字符串 String contentJson ChatMessageSerializer.messagesToJson(messages); // 2. 构建查询条件 Criteria criteria Criteria.where(memoryId).is(memoryId.toString()); Query query new Query(criteria); // 3. 构建更新操作设置 content 和 updatedAt 字段 Update update new Update() .set(content, contentJson) .set(updatedAt, new Date()); // 4. 执行 upsert 操作如果存在则更新不存在则插入 // 这里我们使用 upsert确保每次调用都能正确更新或创建文档 mongoTemplate.upsert(query, update, ChatMessages.class); } /** * 删除会话消息 * param memoryId 会话唯一标识 */ Override public void deleteMessages(Object memoryId) { Criteria criteria Criteria.where(memoryId).is(memoryId.toString()); Query query new Query(criteria); mongoTemplate.remove(query, ChatMessages.class); } }实操心得upsert是这个实现中最关键的一行。mongoTemplate.upsert(...)方法确保了原子性它会先尝试根据query查找文档如果找到了就执行update如果没找到就用update中的字段创建一个新文档。这完美对应了ChatMemoryStore的语义——“更新消息”无论这个会话之前是否存在。我曾经因为误用了mongoTemplate.updateFirst(...)导致新会话无法创建排查了整整一个下午。记住对于ChatMemoryStoreupsert是默认且唯一正确的选择。4. 实操过程从一个接口到一个可发布的 AI Agent 服务4.1 定义你的第一个 AI Agent 接口AiService是魔法的起点在 SpringBoot 的世界里一切皆Bean。而AiService就是 LangChain4j 为你提供的、将一个普通 Java 接口瞬间升华为一个强大 AI Agent 的“魔法注解”。它的力量不在于语法有多炫酷而在于它背后所封装的、极其复杂的运行时逻辑。让我们从一个最简单的、面向金融领域的 Agent 开始import dev.langchain4j.agent.tool.Tool; import dev.langchain4j.memory.chat.ChatMemory; import dev.langchain4j.memory.chat.MessageWindowChatMemory; import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.service.AiService; import dev.langchain4j.service.MemoryId; import dev.langchain4j.service.SystemMessage; import dev.langchain4j.service.UserMessage; import org.springframework.stereotype.Service; /** * FinanceAgent: 金融领域 AI Agent 接口 * 这个接口本身不写任何实现所有的“智能”都由 LangChain4j 在运行时动态注入。 */ AiService( // 指定使用哪个 ChatModel Bean。这个 Bean 的名字必须与 application.yml 中的配置匹配 chatModel qwenChatModel, // 指定使用哪个 ChatMemoryProvider Bean用于为每个会话提供独立的记忆空间 chatMemoryProvider mongoChatMemoryProvider, // 指定可以调用的工具列表。这里的字符串必须是 Spring 容器中 Component Bean 的名字 tools {orderQueryTool, calculatorTool} ) public interface FinanceAgent { /** * 分析营收报告的核心方法 * param sessionId 会话 ID用于隔离不同用户的对话历史 * param query 用户的自然语言查询 * return Agent 的分析结果 */ SystemMessage(fromResource prompts/finance-analyst.txt) String analyzeRevenue(MemoryId String sessionId, UserMessage String query); }这个接口短短十几行却定义了一个完整的 Agent。我们来逐行拆解它的“魔法”AiService(...)这是总开关。它告诉 LangChain4j“请为这个接口生成一个代理实现类。”chatModel qwenChatModelLangChain4j 会在 Spring 容器中查找名为qwenChatModel的ChatLanguageModelBean。这个 Bean 是由langchain4j-community-dashscope-spring-boot-starter自动配置的其配置项API Key、模型名等全部来自application.yml。chatMemoryProvider mongoChatMemoryProvider同理LangChain4j 会查找名为mongoChatMemoryProvider的ChatMemoryProviderBean。这个 Bean 我们将在下一小节中定义它会为每个sessionId创建一个MessageWindowChatMemory其底层存储正是我们刚刚实现的MongoChatMemoryStore。tools {orderQueryTool, calculatorTool}LangChain4j 会查找容器中名为orderQueryTool和calculatorTool的ComponentBean。这些 Bean 必须是Tool标记的类它们的方法会被 LangChain4j 自动注册为 LLM 可调用的函数。SystemMessage(fromResource ...)这是一个强大的注解。它告诉 LangChain4j“在每次向 LLM 发送用户消息之前请先将这个文件里的内容作为一条SystemMessage加入到对话上下文中。” 这个文件prompts/finance-analyst.txt的内容如下你是一位经验丰富、严谨专业的金融分析师。你的任务是帮助客户分析其公司的财务数据。 你必须严格遵守以下规则 1. 所有分析结论必须基于用户提供的数据不得臆测。 2. 如果用户询问的数据你无法获取例如未提供具体数值请明确告知“数据不足无法分析”。 3. 回复必须使用中文语气专业、简洁、条理清晰。 4. 在涉及计算时优先调用 calculatorTool 工具。这个SystemMessage就是 Agent 的“灵魂设定”。它不是一句口号而是 LLM 的行为准则LangChain4j 会确保它始终位于 Prompt 的最开头贯穿整个对话。4.2 构建支撑 BeanChatMemoryProvider与ToolsAiService接口定义了“做什么”而支撑它的Bean则定义了“怎么做”。这是 SpringBoot 工程化思想的又一次完美体现契约Interface与实现Implementation分离。4.2.1 实现ChatMemoryProvider为每个会话定制记忆ChatMemoryProvider是一个函数式接口它只有一个方法ChatMemory get(Object memoryId)。它的职责非常明确根据传入的memoryId返回一个专属的ChatMemory实例。import dev.langchain4j.memory.chat.ChatMemory; import dev.langchain4j.memory.chat.MessageWindowChatMemory; import dev.langchain4j.memory.chat.ChatMemoryStore; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; Configuration public class AiAgentConfig { private final MongoChatMemoryStore mongoChatMemoryStore; Autowired public AiAgentConfig(MongoChatMemoryStore mongoChatMemoryStore) { this.mongoChatMemoryStore mongoChatMemoryStore; } /** * mongoChatMemoryProvider: 为 FinanceAgent 提供 MongoDB 支持的会话记忆 * return ChatMemoryProvider Bean */ Bean public ChatMemoryProvider mongoChatMemoryProvider() { return memoryId - MessageWindowChatMemory.builder() // 设置会话 ID这个 ID 会传递给 MongoChatMemoryStore 作为查询条件 .id(memoryId.toString()) // 设置窗口大小最多保留 10 条消息User AI 各算一条 .maxMessages(10) // 设置底层存储我们注入自己实现的 MongoChatMemoryStore .chatMemoryStore(mongoChatMemoryStore) // 设置 TTL自动清理过期会话可选需配合 MongoDB TTL 索引 .build(); } }这个Bean方法

相关新闻

2026/7/11 7:07:45

STM32多串口动态printf重定向:1个fputc函数支持USART1/2/3切换

STM32多串口动态printf重定向:1个fputc函数支持USART1/2/3切换在嵌入式开发中,串口调试是最常用的调试手段之一。而printf作为C语言中最常用的输出函数,如果能将其重定向到串口,将极大提升调试效率。但对于需要同时调试多个外设或…

2026/7/11 7:07:45

AI巨头技术动向解析:Anthropic J-lens、腾讯Hy3与NVIDIA初创计划

这次我们来关注AI领域的最新动态,特别是围绕Anthropic、腾讯、NVIDIA和微软这几家巨头的重大变化。从技术角度看,这些变化不仅影响投资格局,更直接关系到开发者的工具选择、部署方案和未来技术路线。最近的热点包括Anthropic推出的"J-le…

2026/7/11 10:07:51

微软MAI模型替代外部AI:企业级部署与迁移实战指南

在企业级AI应用开发中,模型部署的成本控制和供应链安全一直是技术团队面临的核心挑战。近期微软在Office产品线中逐步用自研MAI模型替代OpenAI和Anthropic的方案,为大型企业的AI技术选型提供了重要参考。本文将深入分析这一技术转型背后的工程逻辑&#…

2026/7/11 10:07:51

CLI项目:gws、Lark-cli、Office-CLI、Gog-Cli、hn-cli、Obsidian CLI

在CLI复兴:CLI-Anything、OpenCLI里提到过CLI才是AI、LLM、Agent时代的首选交互形态。 很多AI编程助手,都以终端形式提供能力,或在IDE之外提供CLI访问方式,如CC、Cursor Agent,这类助手不要太多。不过,这些…

2026/7/11 10:07:51

Node-RED 2.x Inject节点定时配置:3种Cron表达式实战与常见误区解析

Node-RED 2.x Inject节点定时配置:3种Cron表达式实战与常见误区解析 在物联网和自动化流程开发中,精确的时间控制往往是核心需求。Node-RED作为低代码集成工具,其Inject节点的定时功能通过Cron表达式提供了强大的调度能力。本文将深入解析三种…

2026/7/11 10:02:51

3分钟快速解锁碧蓝航线全皮肤:Perseus原生库补丁完整指南

3分钟快速解锁碧蓝航线全皮肤:Perseus原生库补丁完整指南 【免费下载链接】Perseus Azur Lane scripts patcher. 项目地址: https://gitcode.com/gh_mirrors/pers/Perseus 还在为碧蓝航线中那些精美的舰娘皮肤无法使用而烦恼吗?Perseus原生库补丁…

2026/7/11 5:30:49

国内大模型选型与企业级落地实战指南

我不能提供任何关于访问境外网络信息的技术方案或变通方法。根据中国法律法规和网络管理要求,所有互联网服务必须遵守国家关于网络安全、数据安全和内容安全的规定。ChatGPT及其后续版本(如所谓“GPT-5”)是由境外机构研发的大语言模型&#…

2026/7/11 2:43:05

三步实战方案:高效获取智慧教育平台电子课本PDF的完整流程

三步实战方案:高效获取智慧教育平台电子课本PDF的完整流程 【免费下载链接】tchMaterial-parser 国家中小学智慧教育平台 电子课本下载工具,帮助您从智慧教育平台中获取电子课本的 PDF 文件网址并进行下载,让您更方便地获取课本内容。 项目…

2026/7/11 8:37:53

3个高效策略:快速掌握Axure中文界面配置

3个高效策略:快速掌握Axure中文界面配置 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包。支持 Axure 11、10、9。不定期更新。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-cn 还在为Axure RP的英文界面感…