# SpringBoot+Langchain4J+SpringAI **Repository Path**: zhuodewen/4.-langchain4-j--spring-ai ## Basic Information - **Project Name**: SpringBoot+Langchain4J+SpringAI - **Description**: 4.SpringBoot集成了Langchain4J、SpringAI两个AI框架,并集成了扣子工作流的API接口 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 11 - **Forks**: 3 - **Created**: 2025-04-21 - **Last Updated**: 2025-09-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: AI, SpringAI, langchain4j, Java ## README ## 1)说明 本项目集成了SpringAI和Langchain4J两个JAVA的AI框架,另外还集成了扣子的工作流,项目仅供学习和参考。 AI相关的框架更新迭代太快了,我这个项目编写于2025年年初,使用的依赖在当时是最新的,但现在已经不是最新版本,后续会考虑慢慢替换为最新的。 ## 2)依赖版本 ### [1]SpringBoot相关 3.4.4 ### [2]langchain4j相关 1.3.0-beta9 ### [3]SpringAI相关 1.0.0-M6 1.0.1 (MCP) ### [4]扣子相关 LATEST(最新版本) ## 3)特殊说明 在集成的时候,由于两个AI框架的Bean名称冲突,所以Langchain4J的Bean我是额外处理的,实际项目中只使用其中一个即可,不需要额外处理。 此时,使用Langchain4J不需要LangChain4JProvider、LangChain4JOpenAIConfig、LangChain4JOllamaConfig这几个配置,直接在代码中使用即可,示例: ``` @RestController @RequestMapping(value = "langchain4j") @Slf4j public class LangChain4JController { // openai(deepseek)对话模型 @Autowired private OpenAiChatModel openAiChatModel; @Autowired private OpenAiStreamingChatModel openAiStreamingChatModel; // ollama对话模型 @Autowired private OllamaChatModel ollamaChatModel; @Autowired private OllamaStreamingChatModel ollamaStreamingChatModel; // embedding模型 @Autowired private OllamaEmbeddingModel ollamaEmbeddingModel; // 图像多模态模型 @Autowired private OpenAiImageModel openAiImageModel; /** * deepseek对话 * * @param message * @return */ @PostMapping("deepseek/chat") public JSONResult deepSeekChat(@RequestParam(value = "message") String message) { String callback = openAiChatModel.chat(message); return new JSONResult().markSuccess(CommonConstants.RESULT_SUCCESS_MSG, callback); } /** * deepseek对话-流式响应 * * @param message * @return */ @PostMapping(value = "deepseek/streamingChat", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux deepSeekStreamingChat(@RequestParam(value = "message") String message) { return Flux.create(fluxSink -> { openAiStreamingChatModel.chat(message, new StreamingChatResponseHandler() { @Override public void onPartialResponse(String callback) { // 将部分响应写入 Flux fluxSink.next(callback); } @Override public void onCompleteResponse(ChatResponse chatResponse) { // 处理完成响应 System.out.println("onCompleteResponse: " + chatResponse); fluxSink.complete(); } @Override public void onError(Throwable throwable) { fluxSink.error(throwable); } }); }); } /** * ollama对话(本地模型) * * @param message * @return */ @PostMapping("ollama/chat") public JSONResult ollamaChat(@RequestParam(value = "message") String message) { String callback = ollamaChatModel.chat(message); return new JSONResult().markSuccess(CommonConstants.RESULT_SUCCESS_MSG, callback); } /** * deepseek对话(本地模型)-流式响应 * * @param message * @return */ @PostMapping(value = "ollama/streamingChat", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux ollamaStreamingChat(@RequestParam(value = "message") String message) { return Flux.create(fluxSink -> { ollamaStreamingChatModel.chat(message, new StreamingChatResponseHandler() { @Override public void onPartialResponse(String callback) { // 将部分响应写入 Flux fluxSink.next(callback); } @Override public void onCompleteResponse(ChatResponse chatResponse) { // 处理完成响应 System.out.println("onCompleteResponse: " + chatResponse); fluxSink.complete(); } @Override public void onError(Throwable throwable) { fluxSink.error(throwable); } }); }); } /** * 加载知识库-使用本地内存方式 * * @param message * @return */ @PostMapping("ragTest") public JSONResult ragTest(@RequestParam(value = "message") String message) { // 1.加载知识库 // [1]从当前目录下加载知识库 // List documents = FileSystemDocumentLoader.loadDocuments("/home/langchain4j/documentation"); List documents = FileSystemDocumentLoader.loadDocuments("D:/卓德文/其他/AI知识库/知识库"); // [2]从当前目录下所有子目录加载知识库 // List documents = FileSystemDocumentLoader.loadDocumentsRecursively("D:/卓德文/其他/AI知识库/知识库"); // [3]过滤文档 // PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher("glob:*.pdf"); // List documents = FileSystemDocumentLoader.loadDocuments("D:/卓德文/其他/AI知识库/知识库", pathMatcher); // 2.将知识库文件存入向量数据库 // [1]直接解析 InMemoryEmbeddingStore embeddingStore = new InMemoryEmbeddingStore<>(); EmbeddingStoreIngestor.ingest(documents, embeddingStore); // [2]自定义解析(ollama本地Embedding模型) -> 报错:向量长度不一致,待解决 // EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder() // .embeddingModel(langChain4JProvider.getOllamaEmbeddingModel()) // .embeddingStore(embeddingStore) // .build(); // ingestor.ingest(documents); // 3.创建Assistant和知识库检索器 LangChain4JAssistant langChain4JAssistant = AiServices.builder(LangChain4JAssistant.class) .chatLanguageModel(ollamaChatModel) .chatMemory(MessageWindowChatMemory.withMaxMessages(10)) .contentRetriever(EmbeddingStoreContentRetriever.from(embeddingStore)) .build(); // 4.知识库检索 String chat = langChain4JAssistant.chat(message); log.info("知识库检索内容:{},检索结果:{}", message, chat); return new JSONResult().markSuccess(CommonConstants.RESULT_SUCCESS_MSG, chat); } /** * 工具调用 * * @param message * @return */ @PostMapping("toolTest") public JSONResult toolTest(@RequestParam(value = "message") String message) { LangChain4JAiService langChain4JAiService = AiServices.builder(LangChain4JAiService.class) .chatLanguageModel(openAiChatModel) .tools(new LangChain4JTool()) .build(); String answer = langChain4JAiService.ask(message); return new JSONResult().markSuccess(CommonConstants.RESULT_SUCCESS_MSG, answer); } /** * 多模态-图片生成(暂不支持国内常见的多模态) * * @param message * @return */ @PostMapping("imageTest") public JSONResult imageTest(@RequestParam(value = "message") String message) { Response response = openAiImageModel.generate(message); log.info("图片生成结果:{}", response); return new JSONResult().markSuccess(CommonConstants.RESULT_SUCCESS_MSG, response.content().url()); } } ```