在Java中集成LangChain使用大模型

软测小生

共 7577字,需浏览 16分钟

 ·

2024-03-26 14:30

LangChain是一个框架,旨在帮助开发人员使用语言模型构建端到端的应用程序。它提供了一套工具、组件和接口,可简化创建由大型语言模型 (LLM) 和聊天模型提供支持的应用程序的过程。LangChain 可以轻松管理与语言模型的交互,将多个组件链接在一起,并集成额外的资源,例如 API 和数据库。

目前Quarkus提供了一些工具包用来集成langchain。可以集成不同的LLM模型,openai或者huggingface上的模型,也能集成不同的向量数据库,例如milvus,pinecone,redis,pgvector等。

这里以redis作为向量数据库为例,参考下图,一个完整的数据流程图。

0b638b57d7a498ffb7f38cce6e161906.webp

分步解析如下:

  1. 将准备好的数据通过LLM转换成向量存入到向量数据库。

  2. 用户发送问题到应用程序。

  3. 在redis中查询相关联的数据。

  4. 将相关联的数据和用户问题一起发送到LLM。

  5. 由LLM进行语义转换返回到用户。

接下来看如何在Java中实现对应的步骤。

  • 引入对应的依赖包,不同的LLM引入不同的依赖,只能引入一个LLM模型,不同的向量数据库选择不同的依赖包,这里用redis为例。

              
                
                  <dependency>
                
              
              
                    <groupId>io.quarkiverse.langchain4j</groupId>
              
              
                    <artifactId>quarkus-langchain4j-openai</artifactId>
              
              
                    <version>0.6.2</version>
              
              
                
                  </dependency>
                
              
              
                
                  <dependency>
                
              
              
                    <groupId>io.quarkiverse.langchain4j</groupId>
              
              
                    <artifactId>quarkus-langchain4j-redis</artifactId>
              
              
                    <version>0.6.2</version>
              
              
                
                  </dependency>
                
              
              
                
                  <!--<dependency>-->
                
              
              
                
                  <!--    <groupId>io.quarkiverse.langchain4j</groupId>-->
                
              
              
                
                  <!--    <artifactId>quarkus-langchain4j-hugging-face</artifactId>-->
                
              
              
                
                  <!--    <version>0.6.2</version>-->
                
              
              
                
                  <!--</dependency>-->
                
              
            
  • 配置修改,Redis 向量数据库需要使用redis stack的版本,这里是以dev模式启动,会创建一个redis的docker container,实际中,你可以修改redis的配置,具体配置查看quarkus官网。使用你的openai的apikey或者huggingface的apikey替换相应的配置,使用huggingface指定的模型URL可以是远程的也可以是本地的。

              
                quarkus.langchain4j.redis.dimension=1536
              
              
                quarkus.redis.devservices.image-name=redis/redis-stack:latest
              
              
                quarkus.langchain4j.openai.api-key=sk-***
              
              
                quarkus.langchain4j.openai.chat-model.temperature=0.5
              
              
                quarkus.langchain4j.openai.timeout=60s
              
              
                quarkus.langchain4j.openai.base-url=https://proxy.openpi.com/v1/
              
              
                
                  #quarkus.langchain4j.huggingface.api-key=hf_***
                
              
              
                
                  #quarkus.langchain4j.huggingface.chat-model.inference-endpoint-url=https://api-inference.huggingface.co/models/google/flan-t5-small
                
              
            
  • 导入数据到向量数据库,这里需要指定Parser以及片区大小,这里会将resource/catalog下的准备好的文件转换成向量存入到redis当中。

              
                public void ingest(@Observes StartupEvent event) {
              
              
                    System.out.printf("Ingesting documents...%n");
              
              
                    List<Document> documents = FileSystemDocumentLoader.loadDocuments(new File("src/main/resources/catalog").toPath(),
              
              
                            new TextDocumentParser());
              
              
                    var ingestor = EmbeddingStoreIngestor.builder()
              
              
                                .embeddingStore(store)
              
              
                                .embeddingModel(embeddingModel)
              
              
                                .documentSplitter(recursive(500, 0))
              
              
                                .build();
              
              
                    ingestor.ingest(documents);
              
              
                    System.out.printf("Ingested %d documents.%n", documents.size());
              
              
                }
              
            
  • 定义Retriever,跟Parser是成对出现。

              
                
                  @ApplicationScoped
                
              
              
                public class RetrieverExample implements Retriever<TextSegment> {
              
              
                
                  
    private final EmbeddingStoreRetriever retriever;
    RetrieverExample(RedisEmbeddingStore store, EmbeddingModel model) { retriever = EmbeddingStoreRetriever.from(store, model, 20); }
    @Override public List<TextSegment> findRelevant(String s) { return retriever.findRelevant(s); } }
  • 定义模型,这里指定retriever以及prompt。

              
                
                  @RegisterAiService(retrieverSupplier = RegisterAiService.BeanRetrieverSupplier.class)
                
              
              
                
                  @Singleton
                
              
              
                public interface Bot {
              
              
                
                  
    @SystemMessage("""
    你作为一个AI机器人回答关于财务相关的问题。
    你的回答必须要有礼貌,用中文回答问题,并且确保回答的问题是跟财务相关的。
    如果你不知道,回答你不知道这个问题的回答,请直接联系客户经理。
                用"我是您的智能客服,请问有什么可以帮助到您吗" """) String chat(@MemoryId Object session, @UserMessage String question); }
  • 处理用户请求。只需要调用模型中定义的方法即可,这里以ws为例子。

              
                
                  @OnMessage
                
              
              
                public void onMessage(String message, Session session) {
              
              
                    managedExecutor.execute(() -> {
              
              
                        String response = bot.chat(session, message);
              
              
                        try {
              
              
                            session.getBasicRemote().sendText(response);
              
              
                        } catch (IOException e) {
              
              
                            throw new RuntimeException(e);
              
              
                        }
              
              
                    });
              
              
                
                  
    }

以上就完成了base on OpenAI的langchain的集成,最终演示效果如下。

809eabe13fe3e038f65e2d4cbdc35ed1.webp


浏览 195
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报