前几章简单测试了一下LangChain4J的特性, 本章使用SpringBoot快速集成LangChain4J, 实现丝滑调用大模型, 往期内容传送门
LangChain4J官方提供了SpringBoot Starter, 本章就使用Starter进行快速集成.
使用SDK版本信息如下:
|
1 2 3 4 5 6 7 |
Java: 21 SpringBoot: 3.4.5 LangChain4j: 1.0.1 LLM: (使用在线的百炼(阿里)平台) embedding模型: text-embedding-v3 chat模型: qwen-plus PGVector(postgresql版本的向量数据库, 文章最后有相关的docker-compose): 0.8.0-pg17 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.4.5</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.ldx</groupId> <artifactId>langchain-test</artifactId> <version>0.0.1-SNAPSHOT</version> <name>langchain-test</name> <description>langchain-test</description> <properties> <java.version>21</java.version> <guava.version>33.0.0-jre</guava.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-bom</artifactId> <version>1.0.1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 这里使用的是OpenAI Starter, 因为百炼平台的模型支持OpenAI, 如果本地使用Ollama部署的模型, 导入其对应的Starter即可 --> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-open-ai-spring-boot-starter</artifactId> </dependency> <!-- 该包实现了AI Services的自动注入, 如果想自己声明AI Services去掉该依赖即可 --> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-open-ai</artifactId> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>${guava.version}</version> </dependency> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-reactor</artifactId> </dependency> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-pgvector</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build> </project> |
通过在配置文件中声明模型信息 即可实现对应模型的自动注入
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
langchain4j: open-ai: # 普通聊天模型 chat-model: api-key: ${LLM_API_KEY} model-name: qwen-plus base-url: https://dashscope.aliyuncs.com/compatible-mode/v1 # 流式相应模型 streaming-chat-model: api-key: ${LLM_API_KEY} model-name: qwen-plus base-url: https://dashscope.aliyuncs.com/compatible-mode/v1 # 向量模型 embedding-model: api-key: ${LLM_API_KEY} model-name: text-embedding-v3 base-url: https://dashscope.aliyuncs.com/compatible-mode/v1 |
主要声明了
- 聊天记忆提供类, 关联了记忆存储对象
- 向量存储对象,这里使用的是pgvector
- 内容检索器(RAG-检索实现)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
package com.ldx.langchaintest.config; import com.ldx.langchaintest.service.PersistentChatMemoryStore; import dev.langchain4j.data.segment.TextSegment; import dev.langchain4j.memory.chat.ChatMemoryProvider; import dev.langchain4j.memory.chat.MessageWindowChatMemory; import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.rag.content.retriever.ContentRetriever; import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever; import dev.langchain4j.store.embedding.EmbeddingStore; import dev.langchain4j.store.embedding.pgvector.DefaultMetadataStorageConfig; import dev.langchain4j.store.embedding.pgvector.PgVectorEmbeddingStore; import dev.langchain4j.store.memory.chat.InMemoryChatMemoryStore; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * config * * @author ludangxin * @date 2025/5/15 */ @Configuration public class AiConfiguration { /** * 聊天记忆 提供者 * * @param persistentChatMemoryStore 对话内容持久化对象 * @return 对话记忆 provider */ @Bean public ChatMemoryProvider jdbcChatMemoryProvider(PersistentChatMemoryStore persistentChatMemoryStore) { return memoryId -> MessageWindowChatMemory .builder() .id(memoryId) // 这里使用了自定义的会话存储对象, 可以通过其实现对话过程内容的持久化 // 本地测试的话可以使用 InMemoryChatMemoryStore对象实现内存存储 .chatMemoryStore(persistentChatMemoryStore) .maxMessages(5) .build(); } /** * 向量存储对象 * * @param embeddingModel 向量模型 * @return 向量存储对象 */ public EmbeddingStore<TextSegment> embeddingStore(EmbeddingModel embeddingModel) { return PgVectorEmbeddingStore .builder() .host("localhost") // 必需:PostgresSQL 实例的主机 .port(5431) // 必需:PostgresSQL 实例的端口 .database("postgres") // 必需:数据库名称 .user("root") // 必需:数据库用户 .password("123456") // 必需:数据库密码 .table("my_embeddings") // 必需:存储嵌入的表名 .dimension(embeddingModel.dimension()) // 必需:嵌入的维度 .metadataStorageConfig(DefaultMetadataStorageConfig.defaultConfig()) // 元数据存储配置 .build(); } /** * 内容检索器 * * @param embeddingModel 向量模型 * @return 内容检索器 */ @Bean public ContentRetriever contentRetriever(EmbeddingModel embeddingModel) { return EmbeddingStoreContentRetriever .builder() .embeddingStore(this.embeddingStore(embeddingModel)) .embeddingModel(embeddingModel) .maxResults(10) .minScore(0.65) .build(); } } |
实现了ChatMemoryStore接口, 这里测试使用的是map存储的, 生产环境中可以持久化到数据库中
chat过程中消息会通过ChatMemory调用ChatMemoryStore对聊天内容进行持久化/获取
@AiService 将实现AiService的自动注入
wiringMode = EXPLICIT: 用户自己指定相关的bean 缺省:
wiringMode = AUTOMATIC: 项目启动时自动在环境中找对应的对象实现注入,如果有多个(比如:chatModel),启动报错这里举了几种典型的场景 如
- 普通聊天 chat()
- 聊天记忆&流式输出 chatWithStream()
- 提取指定内容并将结果结构化 extractPerson()
- 提示词占位替换 mockUsername()
- rag text-sql chatWithSql()
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
package com.ldx.langchaintest.service; import com.ldx.langchaintest.domain.Person; import dev.langchain4j.service.MemoryId; import dev.langchain4j.service.SystemMessage; import dev.langchain4j.service.UserMessage; import dev.langchain4j.service.V; import dev.langchain4j.service.spring.AiService; import reactor.core.publisher.Flux; import java.util.List; import static dev.langchain4j.service.spring.AiServiceWiringMode.EXPLICIT; /** * ai svc * * @author ludangxin * @date 2025/5/16 */ @AiService(wiringMode = EXPLICIT, chatModel = "openAiChatModel", streamingChatModel = "openAiStreamingChatModel", chatMemoryProvider = "chatMemoryProvider", contentRetriever = "contentRetriever", tools = {"sysTools"}) public interface AiSqlAssistantService { String chat(String message); @SystemMessage("👉 将文本改写成类似小红书的 Emoji 风格") Flux<String> chatWithStream(@MemoryId String memoryId, @UserMessage String message); @SystemMessage("请在用户提供的文本中提取出人员信息") Person extractPerson(@UserMessage String message); @UserMessage("需要你帮我mock人员姓名, 帮我生成{{total}}个") List<String> mockUsername(@V("total") Integer total); @SystemMessage("你是一名sql分析专家 我会将sql相关的ddl给你, 需要你根据ddl生成合理且可执行的sql语句并返回") String chatWithSql(@MemoryId String memoryId, @UserMessage String message); } |
第一次会话:
后端日志如下
第二次会话:
数据库中信息如下:
本章通过使用SpringBoot实现快速集成LangChain4J, 通过简单的配置实现了AI的调用, 总体使用感受还不错, 虽然是刚发布的正式版但是整体的集成、方法调用都挺丝滑的, 到这里这关于LangChain4J的全部内容已经完结了, 后续会出个SpringAI正式版的体验对比,感兴趣的可以关注下.
测试过程中的代码已全部上传至github, 欢迎点赞收藏 仓库地址: https://github.com/ludangxin/langchain4j-test
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
version: '3' services: pgvector: container_name: pgvector restart: "no" image: pgvector/pgvector:0.8.0-pg17 privileged: true ports: - 5431:5432 environment: POSTGRES_USER: root POSTGRES_PASSWORD: 123456 PGDATA: /var/lib/postgresql/data/ volumes: - ./data:/var/lib/postgresql/data/ |