<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      4. 使用SpringBoot快速集成LangChain4j, 實現AI的絲滑調用

      1. 簡介

      前幾章簡單測試了一下LangChain4J的特性, 本章使用SpringBoot快速集成LangChain4J, 實現絲滑調用大模型, 往期內容傳送門

      1. LangChain4j 初識,想使用Java開發AI應用?

      2. LangChain4j-AIServices,原來調用AI這么簡單?

      3. LangChain4j-RAG,實現簡單的text-sql功能

      LangChain4J官方提供了SpringBoot Starter, 本章就使用Starter進行快速集成.

      2. 環境信息

      使用SDK版本信息如下:

      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 
      

      3. Maven

      <?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>
      

      4. 配置信息

      4.1 application.yml

      通過在配置文件中聲明模型信息 即可實現對應模型的自動注入

      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
      

      4.2 配置類

      主要聲明了

      1. 聊天記憶提供類, 關聯了記憶存儲對象
      2. 向量存儲對象,這里使用的是pgvector
      3. 內容檢索器(RAG-檢索實現)
      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();
          }
      }
      

      4.3 聊天記憶持久化

      實現了ChatMemoryStore接口, 這里測試使用的是map存儲的, 生產環境中可以持久化到數據庫中

      chat過程中消息會通過ChatMemory調用ChatMemoryStore對聊天內容進行持久化/獲取

      package com.ldx.langchaintest.service;
      
      import com.google.common.collect.ArrayListMultimap;
      import dev.langchain4j.data.message.ChatMessage;
      import dev.langchain4j.store.memory.chat.ChatMemoryStore;
      import org.springframework.stereotype.Service;
      
      import java.util.List;
      
      @Service
      public class PersistentChatMemoryStore implements ChatMemoryStore {
          final ArrayListMultimap<Object, ChatMessage> messagesStore = ArrayListMultimap.create();
      
          @Override
          public List<ChatMessage> getMessages(Object memoryId) {
              return messagesStore.get(memoryId);
          }
      
          @Override
          public void updateMessages(Object memoryId, List<ChatMessage> messages) {
              messagesStore.put(memoryId, messages.getLast());
          }
      
          @Override
          public void deleteMessages(Object memoryId) {
              messagesStore.removeAll(memoryId);
          }
      }
      

      4.4 tools

      package com.ldx.langchaintest.tools;
      
      import dev.langchain4j.agent.tool.P;
      import dev.langchain4j.agent.tool.Tool;
      import lombok.extern.slf4j.Slf4j;
      import org.springframework.stereotype.Component;
      
      /**
       * tools
       *
       * @author ludangxin
       * @date 2025/5/15
       */
      @Slf4j
      @Component
      public class SysTools {
          @Tool("根據用戶的名稱獲取對應的code")
          public String getUserCodeByUsername(@P("用戶名稱") String username) {
              log.info("get user code by username:{}", username);
              if ("張鐵牛".equals(username)) {
                  return "003";
              }
      
              return "000";
          }
      }
      

      5. 核心源碼

      5.1 Ai Services

      @AiService 將實現AiService的自動注入

      ? wiringMode = EXPLICIT: 用戶自己指定相關的bean

      ? 缺省:wiringMode = AUTOMATIC: 項目啟動時自動在環境中找對應的對象實現注入,如果有多個(比如:chatModel),啟動報錯

      這里舉了幾種典型的場景 如

      1. 普通聊天 chat()
      2. 聊天記憶&流式輸出 chatWithStream()
      3. 提取指定內容并將結果結構化 extractPerson()
      4. 提示詞占位替換 mockUsername()
      5. rag text-sql chatWithSql()
      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);
      }
      
      

      5.2 Controller

      package com.ldx.langchaintest.controller;
      
      import com.ldx.langchaintest.domain.Person;
      import com.ldx.langchaintest.service.AiSqlAssistantService;
      import dev.langchain4j.data.document.Document;
      import dev.langchain4j.data.document.DocumentSplitter;
      import dev.langchain4j.data.document.loader.ClassPathDocumentLoader;
      import dev.langchain4j.data.document.splitter.DocumentByRegexSplitter;
      import dev.langchain4j.data.embedding.Embedding;
      import dev.langchain4j.data.segment.TextSegment;
      import dev.langchain4j.model.embedding.EmbeddingModel;
      import dev.langchain4j.model.output.Response;
      import dev.langchain4j.store.embedding.EmbeddingStore;
      import lombok.RequiredArgsConstructor;
      import lombok.extern.slf4j.Slf4j;
      import org.springframework.web.bind.annotation.GetMapping;
      import org.springframework.web.bind.annotation.PathVariable;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RequestParam;
      import org.springframework.web.bind.annotation.RestController;
      import reactor.core.publisher.Flux;
      
      import java.io.IOException;
      import java.util.List;
      
      /**
       * ai controller
       *
       * @author ludangxin
       * @date 2025/5/16
       */
      @Slf4j
      @RestController
      @RequestMapping("/ai/chat")
      @RequiredArgsConstructor
      public class AiServiceController {
          private final EmbeddingModel embeddingModel;
      
          private final EmbeddingStore<TextSegment> embeddingStore;
      
          private final AiSqlAssistantService aiSqlAssistantService;
      
          @GetMapping("/test")
          public String test() {
              return aiSqlAssistantService.chat("你是誰");
          }
        
          @GetMapping
          public String chat(@RequestParam String userMessage) {
              return aiSqlAssistantService.chat(userMessage);
          }
      
          @GetMapping(value = "/{id}/stream/memory", produces = "text/stream;charset=utf-8")
          public Flux<String> streamMemory(@PathVariable String id, @RequestParam String userMessage) {
              final Flux<String> chatResponse = aiSqlAssistantService.chatWithStream(id, userMessage);
              return chatResponse
                      .doOnNext(partial -> log.info("chat stream partial data:{}", partial))
                      .doOnError(e -> log.error("stream output error", e))
                      .doOnComplete(() -> log.info("chat stream complete"));
          }
      
          @GetMapping("/extract/person")
          public Person extractPerson(@RequestParam String userMessage) {
              return aiSqlAssistantService.extractPerson(userMessage);
          }
      
          @GetMapping("/mock/username")
          public List<String> mockUsername(@RequestParam(defaultValue = "0") Integer total) {
              return aiSqlAssistantService.mockUsername(total);
          }
      
          @GetMapping(value = "/embedding")
          public String aiEmbedding() throws IOException {
              final Document document = ClassPathDocumentLoader.loadDocument("student_ddl.sql");
              // 創建 SQL 感知的文檔分割器
              DocumentSplitter splitter = new DocumentByRegexSplitter(";",";",
                      2000,    // 最大片段長度
                      100     // 重疊長度
              );
              final List<TextSegment> textSegments = splitter.split(document);
              final Response<List<Embedding>> embedResult = embeddingModel.embedAll(textSegments);
              final List<Embedding> content = embedResult.content();
              embeddingStore.addAll(content, textSegments);
              return "success";
          }
      
          @GetMapping(value = "/{id}/sql/generate")
          public String aiEmbedding(@PathVariable String id, @RequestParam String userMessage) {
              return aiSqlAssistantService.chatWithSql(id, userMessage);
          }
      }
      

      6. 測試

      6.1 測試chat

      6.2 測試tool

      6.3 測試流式&聊天記憶

      第一次會話:

      后端日志如下

      第二次會話:

      6.4 測試抽取用戶信息

      6.5 測試mock

      6.6 測試embedding

      數據庫中信息如下:

      6.7 測試text2sql

      7. 小結

      本章通過使用SpringBoot實現快速集成LangChain4J, 通過簡單的配置實現了AI的調用, 總體使用感受還不錯, 雖然是剛發布的正式版但是整體的集成、方法調用都挺絲滑的, 到這里這關于LangChain4J的全部內容已經完結了, 后續會出個SpringAI正式版的體驗對比,感興趣的可以關注下.

      8. 源碼

      測試過程中的代碼已全部上傳至github, 歡迎點贊收藏 倉庫地址: https://github.com/ludangxin/langchain4j-test

      PGVector

      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/
      
      posted @ 2025-06-20 00:54  張鐵牛  閱讀(1625)  評論(2)    收藏  舉報
      主站蜘蛛池模板: 丁香五月亚洲综合在线国内自拍| 国产欧美亚洲精品第一页在线| 无码熟妇αⅴ人妻又粗又大| 亚洲国产精品日韩av专区| 无人区码一码二码三码区| 人人妻人人澡人人爽欧美一区双| 亚洲中文字幕国产综合| 国产精品色三级在线观看| 四虎永久免费精品视频| 欧美一区内射最近更新| 国产精品综合色区在线观| 国产精品中文字幕第一区| 日韩精品一区二区三区中文无码| 亚洲日韩性欧美中文字幕| 日韩有码中文字幕国产| 乱妇乱女熟妇熟女网站| 台中市| 九九热爱视频精品视频| 日韩理伦片一区二区三区| 欧美成人精品一级在线观看| 亚洲男人在线天堂| 久久国产精品乱子乱精品| 亚洲欧美日韩国产四季一区二区三区| 国产精品成人中文字幕| 中文毛片无遮挡高潮免费| 日韩伦理片| 亚洲国产欧美日韩另类| 福利一区二区在线播放| 天干天干天啪啪夜爽爽99| 亚洲综合色网一区二区三区| h无码精品3d动漫在线观看| 国产色视频一区二区三区qq号| 激情综合五月丁香亚洲| 精品国产成人国产在线视| 中文字幕日韩精品一区二区三区| 国产美女久久久亚洲综合| 激情视频乱一区二区三区| 久久亚洲精品中文字幕波多野结衣 | 麻豆国产成人AV在线播放| 国产精品天天狠天天看| 亚洲欧美精品aaaaaa片|