☰
Spring Boot 3 + LangChain4j 构建AI应用生成平台:微服务全栈实战
2026/10/2 17:42:29 网站建设 项目流程

简介:面向企业级 AI 应用开发者与微服务学习者的全栈项目源码,基于 Spring Boot 3 与 LangChain4j 构建大厂级 AI 应用生成平台,覆盖 Agent 智能体编排、RAG 检索增强、多模型接入等核心能力。压缩包共 387 个文件、约 618KB,包含 287 个 Java 服务端微服务源码、21 个 TypeScript 与 17 个 Vue 构成的前端界面、15 个 XML 配置、15 个 TXT 说明文档以及 YAML/JSON 等环境配置,前后端工程结构完整清晰。平台内置 ReAct、Plan-and-Execute 等多种 Agent 运行时,支持工具插件动态加载、知识库文档解析、向量检索与流式输出,并整合 Nacos、Seata、Gateway 等微服务组件,完整呈现生产级 AI 平台的落地路径。代码遵循 Clean Architecture 分层规范,配套架构设计、接口契约、Agent 开发指南、模型接入、安全加固与性能压测等文档。已有 25 人学习,适合中高级开发者从中获取模块划分、接口契约、部署配置与模型适配等一手可复用内容,沉淀大模型应用平台的设计与编码经验。

1. 编程导航 AI + 微服务全栈新项目:Spring Boot 3 + LangChain4j 到底要做成什么样

2025 年很多做 Java 的人都被一个朴素的焦虑困住:学会 Redis、MySQL、RabbitMQ,能写 CRUD,但投履历时总觉得缺一个「别人没做过、但你做过的」项目。而这条标题给的方向恰好把三类稀缺元素叠在一起——微服务架构、Spring Boot 3 新特性、以及 Java 接大模型时的正统姿势 LangChain4j。所谓「大厂 AI 应用生成平台」,不是让你从零写一个大模型,而是做一个「让业务方用表单拖拽就能生成一个 AI 应用」的配置化平台:输入提示词、选模型、配知识库、设流程,平台自动生成一个能对话、能检索、能调工具的 Web 应用。适合正在补 Java 全栈学习路线、想拿微服务项目做主力作品、以及想搞懂 Spring Boot 3 和 LangChain4j 到底怎么配合的人;这篇文章会把我实际落地这个方向时的拆分思路、核心代码和最关键的那几个坑完整铺开。

2. 微服务拆分的实战思考:这个 AI 应用生成平台到底该拆成几块

2.1 为什么这种项目天然适合微服务而不是单体

做 AI 应用生成平台和做普通后台管理系统一个最大的差别:一个普通系统里所有模块的负载是均匀的、长尾的,而这里「生成应用」这个动作是瞬时高 CPU + 高内存 + 高外部 API 延迟的。一个用户的生成操作可能包含:组装 Prompt → 调大模型 → 解析返回的结构化结果 → 生成配置 → 写入数据库 → 调用部署模块把产物发布出去。整条链路里大模型调用可能是 3~10 秒,而其他模块只需要几毫秒。如果把生成和大模型流量都塞进同一个单体进程,一次慢调用就可能拖垮整个应用的管理页面。

所以按实际的负载特征来拆,比「按菜单拆微服务」靠谱得多。我通常把这种项目拆成 5 个服务:

服务名核心职责关键技术点
gateway统一入口、路由、Token 鉴权Spring Cloud Gateway + JWT
auth登录、用户体系、权限Spring Security + OAuth2
app-manager应用模板管理、生成记录、发布流程MyBatis-Plus + 状态机
ai-enginePrompt 组装、模型调用、流式输出、RAGSpring Boot 3 + LangChain4j
file-service文件上传、镜像管理、产物存储MinIO + 异步任务

spring boot、spring、spring cloud 之间很多人一直搞混;按我的理解,Spring Boot 3 是基础框架,Spring Cloud 负责解决微服务里的服务发现和配置管理,而 LangChain4j 是在 Spring Boot 3 之上接大模型的组件,三者是叠加关系不是替代关系。

2.2 服务间调用怎么设计:同步还是异步

服务拆完之后的第一个问题是:ai-engine 调用大模型很慢,app-manager 要不要同步等它?

很多人第一次做微服务会直接把 Feign 调用放在链路上,结果一个生成操作让网关线程挂半分钟。可落地做法是:

  • 同步调用只保留在小链路里,比如校验 Token、查模板详情;
  • 真正的生成操作走异步任务:app-manager 收到请求后立刻返回「生成中」,同时把任务 ID 推给 ai-engine,ai-engine 完成后再回调结果;
  • 回调失败要有补偿,我一般用一张生成任务表存状态,由定时任务去捞超时未完成的记录。
// 生成任务状态表的关键结构 public class GenerateTask { private String taskId; private String templateId; private String userId; private Integer status; // 0: 待执行 1: 执行中 2: 成功 3: 失败 private String extraParams; private LocalDateTime createTime; private LocalDateTime finishTime; }

这里要注意:把状态放在独立表里,而不是靠消息队列的重试来保证推进。消息队列适合通知「该干活了」,但最终状态必须落库,因为数据库是恢复现场的唯一依据。我见过有人把任务状态只存在 Redis 里,服务一重启全部任务丢失,只能人工后台改数据,这就是典型的「把微服务做重、把一致性做没了」。

2.3 Spring Boot 3 在这套架构里真正用到了什么

Spring Boot 3 相比 2.x 最大的变化是 Java 17 基线 + Jakarta EE。除此之外,在这个项目里我最常用的是:

  • Spring Boot 3 的 Native Image 配置(虽然实际很少人直接把整个微服务打成 native,因为 LangChain4j 的反射类太多);
  • spring-boot-starter-webflux与 WebMVC 的选择。ai-engine 这侧为了流式输出,我会单独用 WebFlux,因为 SSE 场景下 WebFlux 天然支持异步非阻塞;其他服务继续用 WebMVC,避免团队心智负担过大。LangChain4j 在 Spring Boot 3 上同时支持阻塞和流式两个分支,选 WebFlux 时要记得引入 reactor 的依赖。
<dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-spring-boot-starter</artifactId> <version>1.0.0-beta1</version> </dependency> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-open-ai</artifactId> <version>1.0.0-beta1</version> </dependency>

具体的版本号建议以 Spring Boot 3.2 以上为基础来搭。LangChain4j 的启动器会自动注册ChatLanguageModel、EmbeddingModel和ChatMemory这类 Bean,不用你自己手写工厂,但后面我会讲为什么自动配置恰恰是坑的来源。version 参数别乱升到最新,如果你用的模型接口是 OpenAI 兼容格式,那么langchain4j-open-ai就够;如果你要接国内模型,记得确认它是不是走/v1/chat/completions标准协议,不是的话要换langchain4j-http或自定义请求。

3. 用 LangChain4j 把 AI 应用生成平台的推理引擎搭出来

3.1 LangChain4j 是什么,以及和 Spring AI 怎么选

LangChain4j 是 Java 版的 LangChain,核心目标就是「让 LLM 接入 Java 应用变成和操作数据库一样自然」。它不是 Spring 官方的,但依赖层面做得非常好:可以把 OpenAI、通义千问、Ollama 都抽象成统一的ChatLanguageModel接口,这样业务代码里不用写具体厂商 SDK。Spring AI 是 Spring 官方的方案,起步晚一点,生态不够 LangChain4j 稳,尤其在 RAG 组件和回调钩子上,LangChain4j 明显更成熟。

在 AI 应用生成平台里,LangChain4j 主要承担四个能力:

  • 用模板生成对话应用的 Prompt;
  • 支持流式响应,把大模型返回逐字推给前端;
  • 做 RAG,给 AI 应用挂知识库,让模型基于用户导入的文档回答;
  • 调工具,比如让模型根据用户输入查询天气预报、查库存。

最关键的是第一点。你写生成器,核心逻辑就是把用户配置的表单数据组装成一个完整的 AI 应用定义,这个组装过程本身就是「Prompt Engineering」。

3.2 组装一个可运行的对话应用:把表单变成可编程的 AI 服务

通常用户在平台上创建一个 AI 应用只需要填:应用名称、系统提示词、选择模型、温度、是否开启知识库、是否开启联网。这些字段存进 template 表,生成时再由 ai-engine 组装出真正的运行时配置。下面是核心的 Prompt 模板组装代码:

public ChatRequest buildGenerateRequest(AiAppConfig config) { String systemPrompt = """ 你是一个 AI 应用生成器。 用户想创建一个名为 "%s" 的应用,定位是:%s。 请根据以下要求生成该应用的系统提示词: 1. 不要出现"你是AI助手"这类空话,直接以业务角色进入; 2. 输出必须包含:角色、能力边界、输出格式、禁止事项; 3. 控制在 200 字以内。 """.formatted(config.getAppName(), config.getDescription()); return ChatRequest.builder() .messages(singletonList(SystemMessage.from(systemPrompt))) .temperature(config.getTemperature()) .maxTokens(800) .build(); }

这段代码的意图不是直接生成业务答案,而是生成「能让另一个模型高质量工作的系统提示词」——这是生成平台的本质。temperature 在这里要保守一点,如果填了 0.8 以上,生成出的 Prompt 会发散,导致业务方拿到的应用「每次都换一个风格」。所以平台侧我会做一层限制:生成器内部用的温度固定在 0.2~0.4,业务方配置的温度只作用于最终生成的运行时应用。

maxTokens 也不是越大越好。生成 Prompt 到 800 token 足够,如果设到 2000,响应变慢、成本变高,而且很多模型对超长输出的尾部质量会急剧下降。一般我会在测试里压出三个档位:600、800、1200,比较生成结果的稳定性和耗时,再决定默认值。

3.3 流式输出怎么做:让生成过程肉眼可见

AI 应用生成平台和一个传统后台最大的体验差异在「生成过程要有响应」。用户点完生成按钮,界面如果白屏 8 秒,基本会被直接判定为系统卡死。LangChain4j 的StreamingChatLanguageModel就是干这个的。

@PostMapping(value = "/generate/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public SseEmitter streamGenerate(@RequestBody GenerateRequest req) { SseEmitter emitter = new SseEmitter(60_000L); executor.execute(() -> { try { streamingModel.chat(messages) .onPartialResponse(token -> { emitter.send(SseEmitter.event().name("message").data(token)); }) .onCompleteResponse(resp -> { emitter.send(SseEmitter.event().name("done").data(resp.aiMessage().text())); emitter.complete(); }) .onError(error -> { emitter.completeWithError(error); }) .start(); } catch (Exception e) { emitter.completeWithError(e); } }); return emitter; }

用 SseEmitter 时尤其注意超时参数的设置。默认的SseEmitter()超时是 30 秒,如果你的模型经常跑 40 秒,前端会在 30 秒就收到一个超时中断,所以初始化时显式传 60_000L。

这里的 onPartialResponse 是 LangChain4j 的流式回调,后端每收到一段 token 就推给前端,前端用 EventSource 接收并拼到界面上。拼接顺序、断线重连、以及「用户中途取消生成」这三个问题,要单独处理:用户取消时调用emitter.complete()还不够,还要在内存里维护一个 taskId -> CancellationToken 的 Map,才能真正打断模型那边的请求,否则内存里的响应还在继续,浪费外部 API 额度。

3.4 给一个 AI 应用挂上知识库:RAG 链路的最小实现

一个完整的 AI 应用通常要能回答业务方私有文档里的问题,这就要 RAG。LangChain4j 的 RAG 链路由三块组成:Embedding 模型、向量存储、以及检索器的参数调优。

首先往项目里引入文本嵌入模型,我用的是一套兼容 OpenAI 协议的 embedding 接口:

langchain4j: open-ai: chat-model: base-url: ${MODEL_BASE_URL} api-key: ${MODEL_API_KEY} model-name: gpt-4o-mini embedding-model: base-url: ${MODEL_BASE_URL} api-key: ${MODEL_API_KEY} model-name: text-embedding-3-small

导入知识库的文档后,需要把文本切成块再向量化,LangChain4j 提供了DocumentSplitter:

public void importDocument(String content, String knowledgeBaseId) { Document document = Document.from(content); List<TextSegment> segments = DocumentSplitter.recursive(500, 100) .split(document); List<Embedding> embeddings = embeddingModel.embedAll(segments).content(); List<String> segmentIds = embeddingStore.addAll(embeddings, segments); knowledgeBaseRelService.batchAdd(knowledgeBaseId, segmentIds); }

这里recursive(500, 100)是参数调整的第一站:数表示每个片段最多 500 字符、重叠部分 100 字符。片段切的太小,检索到的上下文不完整;切得太大,一次塞给模型会稀释关键信息。我跑过很长一段时间的业务问答,最后发现 500 字左右、重叠 100 字是最稳的组合。如果一个文档本身是高度结构化的表格,我会换成DocumentSplitter.recursive(200, 20),让模型聚焦在更小粒度的上下文里。

检索的时候默认的EmbeddingStoreRetriever参数是 topK=3。实际效果是,业务方提出的问题往往包含多个条件,topK=3 容易漏掉关键文档。比较稳的做法是 topK 取 5~7,然后让模型对检索结果做一次相关性过滤再回答,而不是只量一次相似度就下结论。

4. LangChain4j + Spring Boot 3 避坑实录:现象、原因与解决办法

4.1 流式响应一直报「Async request timed out」,前端收到 504

现象:SSE 接口在 Postman 里能通,一走网关就超时,控制台打Async request timed out。原因:Spring Cloud Gateway 默认的响应超时是 30 秒,而大模型流式输出通常十几秒才返回第一帧,客户端早断了。解决:在 gateway 的配置里单独放宽这条路由的读超时。

spring: cloud: gateway: httpclient: response-timeout: 120000

注意response-timeout是整个 httpclient 的全局配置,不是某条路由单独设。如果你不想全局放宽,可以在路由 predicate 里加Metadata,或者在过滤器里为生成流接口单独创建新的 WebClient 实例,把连接和响应超时都拉长。流式输出属于长连接,不是每条请求都要 120 秒,所以我对普通接口仍然保留默认 10 秒,只对/api/ai-engine/generate/**做长超时。

4.2 LangChain4j 自动配置的 ChatModel 和你配置的 API Key 对不上

现象:本地跑得好好的,部署上去之后模型返回 401 或模型名不存在。原因:langchain4j-spring-boot-starter会自动从application.yml读langchain4j.open-ai.chat-model.api-key,但如果你同时在代码里手动 new 了一个OpenAiChatModel,代码里的实例会覆盖自动装配的 Bean,于是你改 yml 永远不生效。解决:统一入口,只在 yml 里配模型,代码里始终用@Autowired注入ChatLanguageModel,不要手动 new;如果一定要多模型并存,把每个模型定义成单独的@Bean,并给名字带上业务前缀,注入时用@Qualifier("codeReviewModel")区分。

4.3 大模型返回 JSON 时偶尔多一个「json」前缀或丢失后括号

现象:让模型返回结构化 JSON 交给前端渲染,十个请求里有三个解析失败,日志里全是JSONDecodeException,查看原始返回值发现开头是json或者结尾少了一个}。原因:LLM 本身对输出格式的控制不稳定,尤其是中文系统提示词很长时,模型有可能把「输出 JSON 格式」误解成「输出一个 Markdown 代码块」。解决:三层兜底。第一层,提示词末尾强制加「不要输出任何解释,不要包含代码块标记,只输出 JSON 本身」。第二层,解析前清洗字符串:

public String sanitizeModelOutput(String raw) { String cleaned = raw.trim(); // 去掉 ```json 这种围栏 if (cleaned.startsWith("```")) { cleaned = cleaned.replaceAll("^```[a-zA-Z]*\\n", "") .replaceAll("\\n```$", ""); } // 去掉模型偶尔画蛇添足的前缀 int firstBrace = cleaned.indexOf('{'); int lastBrace = cleaned.lastIndexOf('}'); if (firstBrace >= 0 && lastBrace > firstBrace) { return cleaned.substring(firstBrace, lastBrace + 1); } return cleaned; }

第三层最重要:提示词里用「用 Markdown JSON 代码块包裹」这种说法,反而会诱导模型输出围栏。更可靠的做法是直接告诉模型「你的输出会被程序解析,非法 JSON 将导致用户损失,务必只输出原始 JSON」。加一句责任描述比任何格式强调都有效。

4.4 微服务里 RabbitMQ 消费 AI 生成结果时,消息体太大直接被丢弃

现象:生成任务详情里明明有 PDF 转出的长文本,但 ai-engine 收到消息后内容被截断,或者消费端抛java.lang.IllegalArgumentException: body exceeds 1MB。原因:RabbitMQ 默认 max frame 是 1MB,很多团队把文档转出来的 Markdown 全塞进消息体,它当然会超。解决:消息只传任务 ID,文档内容让 ai-engine 回查 app-manager 的文件服务接口,同时把 yml 里的spring.rabbitmq.connection-timeout调大一点;如果必须传大 body,就在 RabbitMQ 管理后台把 frame_max 调大,但这会增大集群内存压力,不推荐。我一般会在上传文档时就把内容落到 MinIO,消息里只存fileId。

4.5 热更新 Prompt 模版不生效,感觉黑匣子一样

现象:运营同学后台改了「生成应用的系统提示词」,保存成功,但重新生成还是原来的效果。原因:ai-engine 服务本地 JVM 缓存了模板类,且没有做版本号变更通知。解决:模板表里加version字段,每次修改version+1;ai-engine 启动时加载模板到 ConcurrentHashMap,再提供一个刷新接口,由 RabbitMQ 广播模板变更事件,ai-engine 收到消息后重新查库、更新本地缓存。

@Component public class PromptTemplateHolder { private volatile Map<String, PromptTemplate> cache = new ConcurrentHashMap<>(); public void reload(String templateCode) { PromptTemplate fresh = mapper.findByCode(templateCode); this.cache.put(templateCode, fresh); } public PromptTemplate get(String templateCode) { return cache.get(templateCode); } }

这个坑的根源是把「模板」当静态资源,而不是当一份随时可修改的业务数据。只要模板需要被运营后台变更,就必须有版本管理和刷新机制。很多团队在线下拿同一个模板测两三次没问题,一到线上发现改不动,就是这个细节没做。

5. 全栈工程化:从 AI 应用生成到用户能直接用的完整链路

5.1 前端页面怎么和流式接口对接

整个项目跑通之前,前后端最容易出现「各说各话」。前端用 EventSource 接收 SSE,但 EventSource 不支持 POST,浏览器原生 API 只能发 GET,而生成接口需要带 body,这是第一个不匹配点。

两个可落地的解:一个是把生成参数编码到 GET 的 query string,但 body 里可能夹带长 Prompt,URL 长度容易炸;另一个是用 fetch + ReadableStream 读取 SSE 格式的响应,前端手动按行解析。第二种是我的默认做法:

const response = await fetch('/api/ai-engine/generate/stream', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); const reader = response.body.getReader(); const decoder = new TextDecoder('utf-8'); let buffer = ''; while (true) { const { value, done } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split('\n'); buffer = lines.pop(); lines.forEach(line => { if (line.startsWith('data:')) { const eventData = JSON.parse(line.slice(5).trim()); renderStreamToken(eventData.token); } }); }

这段代码的关键是对每行以data:开头的 SSE 报文做 JSON 解析,而读取流必须分块拼接,因为网络包不一定正好在换行符处断开。Buffer 拼接这里我吃过亏:最开始直接用value变量去判断,发现中文经常被截成半个字符乱码,后面改成保留本 chunk 尾部剩余字节再拼接才稳定。

5.2 「无代码/低代码」生成应用的核心:结构化配置的本质

AI 应用生成平台的「生成」其实不是运行时才动态判断业务逻辑,而是把用户配置翻译成 AI 应用的「定义文件」。这个文件建议设计成 JSON Schema 而不是直接生成代码,因为 JSON 可持久化、可版本比对、可做权限控制;如果直接生成 Java 代码再编译部署,整个平台的交付链路会变得极其重,而且越到后面越难维护。

常见的做法是定义 runtime-config 表:每条记录对应一个应用 ID,存一个 JSON,含 model、temperature、systemPrompt、knowledgeBaseId、tools 列表。ai-engine 在应用创建时把这个 JSON 落库,应用详情页直接读 JSON 渲染表单。这样做的好处是,所有 AI 应用本质上都是同一套 ChatModel + Prompt + Retriever 的组装,只不过参数不同,平台不需要为每个应用单独部署一个服务。

5.3 AI 应用生成平台里的 Agent 和 Tool 调用怎么嵌入

如果标题里的「AI 应用」只支持对话和知识库问答,竞争力明显不够。一线团队做到后面都会加上「让应用调用外部工具」的能力:比如让 AI 应用查今日天气、查快递、或在内部系统里建工单。LangChain4j 的工具调用需要声明参数结构,然后注册给模型。

@Tool("根据城市名查询当前天气") public String getWeather(@ToolParam("城市名称") String city) { WeatherClient client = new WeatherClient(); return client.query(city); }

把这段代码所在的 Bean 注入给AiServices,模型就会在需要时触发这个工具。这里最容易踩的坑是 @Tool 方法不要抛出受检异常,模型在 Tool 执行失败时只能得到一个异常文本,它很容易开始编造答案;正确做法是方法内部 catch 所有异常,返回一个「接口暂不可用」这样的字符串,让模型如实告诉用户,而不是替用户编一个假天气。

5.4 部署与联调:整套微服务怎么在本地先跑起来

哪怕只在自己电脑上要跑通整个平台,我一般也会配docker-compose,把 MySQL、Redis、RabbitMQ、MinIO 四件套拉起来,然后逐个启动服务的main方法。顺序有讲究:先启 auth,再启 file、app-manager、ai-engine,最后是 gateway。因为 gateway 依赖服务发现,而 ai-engine 的启动又依赖 RabbitMQ 存在;如果顺序颠倒,控制台会出现一堆连接拒绝的噪音,虽然不影响最终启动,但会干扰排查真正的问题。

services: mysql: image: mysql:8.4 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: ai_platform ports: - "3306:3306" redis: image: redis:7-alpine ports: - "6379:6379" rabbitmq: image: rabbitmq:3.13-management ports: - "5672:5672" - "15672:15672" minio: image: minio/minio command: server /data --console-address ":9001" ports: - "9000:9000" - "9001:9001"

联调时最实用的排查技巧是「从前端到后端逐层关防火墙」:先在浏览器 DevTools 里确认请求确实发到了 gateway,再在 gateway 日志里看路由有没有匹配,再到服务日志里看 Feign 调用有没有到下游。这个顺序能过滤掉大部分「明明代码 OK 但网络不通」的玄学。另外记得所有服务统一时区,Spring Boot 3 启动类里加一行TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai")),否则生成任务的时间戳会差 8 小时,排查起来非常痛苦。

6. 进阶验证方法与可复用的调优习惯

项目做到能跑只是第一关,真正能成为「简历亮点」的是你对细节的掌控力。我把最后这一章的篇幅留给三个我自己验证过、能显著提升项目完成度的动作。

第一个是给 ai-engine 服务写一个「准生产压测」脚本。不需要引入复杂工具,就用 jmeter 或 go-wrk 打流式接口,把并发从 1 升到 20,观察两个指标:首 token 延迟和生成完整响应时间。你会发现大模型接口在 10 并发以后首 token 延迟变化不大,但完整响应时间会大幅上升,因为服务端输出带宽被占满。这个数据可以用来向面试官解释为什么要在网关层做限流,而不是无限加大容器数。

第二个是做一个可录屏的「平台自举」演示:在 AI 应用生成平台上创建一个专门用来写 Prompt 的 AI 应用,让它在 3 分钟内生成一套促销话术,再把这套话术配到另一个应用里做客服。录一段 30 秒短视频放在作品 README 里。这个演示能让读者或面试官直接理解「生成平台」不是概念,是真实可用的产品闭环。任何项目说明文字都比不上一段真实的屏幕录制有说服力。

第三个是我个人会做、但很多人忽略的细节:把生成任务表做成一个可观测面板,统计每个模板的「生成成功率」「平均生成时长」「Prompt 平均 token 数」。上线两周后调一次模板内容,这比任何代码评审都能提升系统质量。因为模型和模板的变化是不可解释的,数据是唯一能说服自己「这次改动真的变好了」的后悔药。

如果你要沿这个方向自己搭一套,我的建议是别把摊子铺得太大。第一次版本只保留 app-manager + ai-engine + gateway 三个服务,知识库用 JSON 文件临时存向量,跑通整个生成闭环再逐步引入 RabbitMQ 和 MinIO。微服务架构的复杂度是必要成本,但没必要在最开始一口气全上;把 AI 应用生成、流式输出、动态模板这三件事做到位,这个项目就有足够的区分度了。

我希望这篇基于 Spring Boot 3 + LangChain4j 的大厂方向 AI 应用生成平台拆解能帮到你,也希望你在搭的时候减少一些我当年踩过的时间损耗。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询