从0到1:用 LangChain4j 将 AI Agent 打包成生产级 Web 应用
在很多团队里,AI Agent 项目的第一版通常都不难:一个大模型、几个工具、一个接口,几天就能跑出 Demo。真正困难的部分,是如何把 Demo 演进为生产系统。
生产环境不会只问“模型能不能回答问题”,而会继续追问:
- 高并发下是否还能稳定响应?
- 工具调用失败时会不会把整条链路拖死?
- Prompt、模型、工具、知识库能否独立演进?
- 多租户、多会话、长上下文时如何控制成本?
- 流式响应、审计日志、链路追踪、灰度发布如何落地?
- 当 Agent 从“聊天机器人”变成“业务执行者”后,如何做权限、幂等和风控?
这篇文章的目标,不是再写一个“Hello Agent”,而是从真实业务出发,构建一套基于 LangChain4j + Spring Boot + PostgreSQL/pgvector + Redis + Kafka + Docker/Kubernetes 的生产级 AI Agent Web 应用方案。文中不仅会给出架构设计,也会给出可落地的代码骨架、工程实践和部署方式。
全文围绕一个具体场景展开:电商智能客服与工单协同系统。这个场景同时具备查询类任务、知识问答类任务、工具执行类任务和人工升级类任务,非常适合展示 Agent 在企业业务中的完整价值链。
一、为什么 Demo 很容易,生产很难
先看一个典型 Demo 的实现方式:
- 前端发来一句用户问题。
- 后端把问题直接丢给大模型。
- 大模型决定要不要调用工具。
- 返回一段文本给前端。
这个模型在功能验证阶段没有问题,但一旦进入真实业务,就会暴露四类结构性问题。
1. 单 Agent 过载
很多项目把所有能力都塞进一个 Agent:
- 订单查询
- 商品咨询
- 售后退款
- 投诉升级
- 知识库问答
- 优惠券核销
- 人工客服转接
结果是工具越来越多,系统提示词越来越长,模型的决策边界越来越模糊。它表面上“什么都能做”,实际上“没有一件事做得足够稳定”。
2. 工具调用缺乏工程约束
Demo 里工具函数通常只是普通方法,但生产环境的工具调用本质上是一次“受 LLM 驱动的远程业务执行”,这意味着它必须具备:
- 明确参数约束
- 输入校验
- 权限校验
- 超时控制
- 幂等设计
- 审计日志
- 熔断降级
否则,工具一旦连接的是订单系统、退款系统、CRM 或工单系统,风险会立刻成倍放大。
3. 会话与上下文成本失控
如果把每一轮历史消息都原样拼进 Prompt:
- Token 成本会线性增长
- 响应延迟会明显上升
- 模型注意力会被历史噪音稀释
- 敏感信息更容易在上下文中被“误继承”
因此,生产系统必须将“对话历史”与“工作记忆”区别对待,而不是无限堆上下文。
4. 把模型调用当作普通 HTTP 请求
LLM 调用与传统 CRUD 接口不同,它具有:
- 响应时间波动大
- 第三方依赖强
- 成本高
- 不确定性高
- 重试语义复杂
因此,不能简单按同步 Web 接口思路处理,必须引入削峰、限流、缓存、异步化、回退策略与链路观测。
二、业务场景:电商智能客服与工单协同系统
假设我们要做一个面向电商平台的 AI 客服系统,支持以下三类请求:
- 订单类问题:查询订单状态、物流进度、退款进度
- 商品类问题:查询商品参数、库存、价格、活动、售后政策
- 复杂服务类问题:识别不满、投诉、人工诉求,自动创建工单并升级
这个系统的业务特点非常典型:
- 读多写少,但偶尔包含强事务操作
- 既有知识问答,也有外部工具调用
- 用户希望秒级反馈,但模型推理具有波动性
- 旺季流量高峰明显,必须考虑削峰填谷
- 结果不仅要“像人回答”,还要“符合业务规则”
因此,它天然适合采用“多 Agent + 工具 + RAG + 异步化 + 可观测性”的组合架构。
三、LangChain4j 为什么适合 Java 生产环境
如果团队主技术栈是 Java,LangChain4j 的优势不在于“概念更新”,而在于它能和现有工程体系无缝融合。
1. 对 Java 团队足够友好
LangChain4j 的核心抽象非常贴近 Java 开发者习惯:
ChatModel/StreamingChatModelAiServices@ToolChatMemoryContentRetriever
很多能力可以直接纳入 Spring 容器管理,避免引入第二套 Python 服务体系。
2. 适合作为“Agent 编排层”
对于企业应用来说,LangChain4j 的核心价值不是“替你发明业务架构”,而是提供一层足够轻、足够实用的 Agent 运行时。你可以把它放在已有系统之上,承接:
- 模型调用
- Prompt 组织
- 工具注册
- 检索增强
- 多轮对话
- 流式输出
而业务规则、权限、审计、缓存、消息队列、监控体系仍然交给 Spring 生态处理。
3. 更适合渐进式接入
一个成熟团队通常不会一次性把系统全部 Agent 化。更常见的路径是:
- 先做一个问答入口
- 再接一个安全的查询工具
- 再引入 RAG
- 再引入 Supervisor / Routing
- 最后把异步任务、审计、观测、灰度补齐
LangChain4j 很适合这种渐进式演进方式。
四、生产级总体架构设计
我们先给出系统全貌,再逐层拆解。
┌──────────────────────┐ │ Web Frontend │ │ React/Vue + SSE/WS │ └──────────┬───────────┘ │ ┌──────────▼───────────┐ │ API Gateway │ │ Auth / RateLimit / │ │ Trace / Routing │ └──────────┬───────────┘ │ ┌─────────────────▼──────────────────┐ │ Agent Application (Spring Boot) │ │ │ │ 1. Session & Memory │ │ 2. Intent Router / Supervisor │ │ 3. Tool Invocation Layer │ │ 4. RAG Orchestrator │ │ 5. Stream Response Layer │ │ 6. Audit / Metrics / Trace │ └───────┬───────────────┬────────────┘ │ │ ┌──────────────▼───────┐ ┌──▼────────────────┐ │ Redis │ │ Kafka │ │ Session / Cache / │ │ Async Queue / │ │ RateLimit / Idempotent│ │ Peak Shaving │ └──────────────┬───────┘ └──┬────────────────┘ │ │ ┌──────────────────▼───────┐ ┌──▼─────────────────────────┐ │ PostgreSQL + pgvector │ │ External Business Systems │ │ Orders / Products / │ │ OMS / Inventory / Ticket │ │ Knowledge / Audit │ │ CRM / Coupon / Logistics │ └──────────────────┬───────┘ └────────────────────────────┘ │ ┌────────▼────────┐ │ Model Service │ │ OpenAI API / │ │ vLLM / DashScope │ └──────────────────┘这个架构的核心思想是:让大模型只负责“理解与决策”,让业务系统继续负责“真实执行与状态管理”。
换句话说,Agent 不应该替代业务系统,而应该成为业务系统的“自然语言编排层”。
五、核心设计原则:先定边界,再写 Agent
在落代码之前,先明确五条边界原则。
1. Agent 负责决策,不直接拥有业务真相
比如“订单是否已发货”,真实状态必须来自订单系统,而不是模型猜测。因此:
- 查询类结果必须由工具或检索返回
- 模型只负责把结果组织成用户友好的回答
2. Tool 是能力边界,不是随便暴露的方法
一个生产级 Tool 至少要回答这几个问题:
- 谁可以调用?
- 允许在哪些场景调用?
- 参数是否合法?
- 失败是否可重试?
- 是否会产生副作用?
- 是否需要幂等键?
- 是否要写审计日志?
3. RAG 和 Tool 不要混用职责
很多系统的问题在于“知识问答”和“事务执行”混为一谈。正确做法是:
- RAG:适合回答政策、规则、说明、文档类问题
- Tool:适合执行订单查询、工单创建、库存校验等操作
如果一个问题需要“先查知识、再做动作”,也应该是显式编排,而不是让模型自由发挥。
4. Prompt 不是配置垃圾桶
不要把所有规则都堆进系统提示词。更好的拆法是:
- Prompt 负责角色、目标和回答风格
- 业务约束由代码校验
- 敏感规则由策略层控制
- 动态知识由检索层提供
5. 生产系统必须先考虑失败路径
AI 系统不是“会不会成功”,而是“失败时怎么优雅退化”。因此,所有关键能力都应设计:
- 超时
- 重试
- 降级
- 熔断
- 回退回答
- 人工兜底
六、系统分层:把 Agent 放进标准工程架构
为了可维护性,我们把后端拆成六层。
1. API 接入层
职责:
- 认证鉴权
- SSE/HTTP 接口暴露
- 限流
- TraceId 注入
- 请求参数校验
2. Agent 编排层
职责:
- 意图路由
- Supervisor 调度
- 子 Agent 调用
- 工具调用前后的策略控制
3. 领域服务层
职责:
- 订单领域服务
- 商品领域服务
- 工单领域服务
- 会话领域服务
这一层不依赖 LLM,确保核心业务逻辑可测试、可复用。
4. 基础设施层
职责:
- LLM 客户端
- Redis
- PostgreSQL / pgvector
- Kafka
- 外部 HTTP 客户端
5. 观测与治理层
职责:
- 日志
- 指标
- Trace
- Prompt 审计
- Tool 审计
- 成本统计
6. 前端展示层
职责:
- 聊天式 UI
- 流式输出
- 会话历史
- 工具执行态展示
- 人工升级状态展示
七、核心原理:LangChain4j 在系统里扮演什么角色
很多人第一次接触 LangChain4j,会把它理解成“大模型 SDK + 注解工具”。这没错,但不够完整。
在生产系统中,可以把 LangChain4j 看作三层能力。
1. 模型适配层
负责对接不同模型服务:
- OpenAI 兼容接口
- 本地推理服务
- 云厂商模型服务
这一层解决“如何调模型”。
2. 交互抽象层
包括:
- Prompt
- Message
- Memory
- Tool
- Retriever
这一层解决“如何把业务上下文组织给模型”。
3. 编排运行层
包括:
- 单 Agent
- Router / Supervisor
- 多工具协同
- 流式响应
这一层解决“如何把模型、工具、检索串成一个可执行链路”。
因此,LangChain4j 不只是让你调用模型,而是在 Java 工程里建立一套“可编排的智能交互运行时”。
八、项目结构设计
一个适合生产落地的工程结构示例如下:
ai-agent-webapp/ ├── backend/ │ ├── pom.xml │ └── src/main/java/com/example/agentapp │ ├── AgentApplication.java │ ├── api/ │ │ ├── ChatController.java │ │ └── AdminController.java │ ├── application/ │ │ ├── ChatApplicationService.java │ │ ├── AgentGatewayService.java │ │ └── TicketApplicationService.java │ ├── domain/ │ │ ├── order/ │ │ ├── product/ │ │ ├── ticket/ │ │ └── session/ │ ├── agent/ │ │ ├── CustomerServiceAgentFactory.java │ │ ├── OrderAgent.java │ │ ├── ProductAgent.java │ │ ├── EscalationAgent.java │ │ └── SupervisorAgentService.java │ ├── tool/ │ │ ├── OrderTools.java │ │ ├── ProductTools.java │ │ └── TicketTools.java │ ├── rag/ │ │ ├── KnowledgeIngestionService.java │ │ └── KnowledgeRetriever.java │ ├── infrastructure/ │ │ ├── llm/ │ │ ├── persistence/ │ │ ├── redis/ │ │ ├── kafka/ │ │ └── client/ │ ├── config/ │ └── support/ ├── frontend/ │ ├── package.json │ └── src/ │ ├── App.tsx │ ├── components/ │ └── api/ ├── deploy/ │ ├── docker-compose.yml │ ├── backend.Dockerfile │ ├── frontend.Dockerfile │ └── k8s/ └── docs/这样的结构有两个好处:
- Agent 相关代码不会污染领域层
- 后续想替换模型、替换向量库或增加新 Agent,改动范围可控
九、依赖管理:生产级 pom.xml 应该怎么配
下面给出一个更接近生产的 Maven 依赖组合。
<properties> <java.version>21</java.version> <spring-boot.version>3.3.5</spring-boot.version> <langchain4j.version>1.1.0-beta7</langchain4j.version> <resilience4j.version>2.2.0</resilience4j.version> </properti