在Java中集成LangChain使用大模型
LangChain是一个框架,旨在帮助开发人员使用语言模型构建端到端的应用程序。它提供了一套工具、组件和接口,可简化创建由大型语言模型 (LLM) 和聊天模型提供支持的应用程序的过程。LangChain 可以轻松管理与语言模型的交互,将多个组件链接在一起,并集成额外的资源,例如 API 和数据库。
目前Quarkus提供了一些工具包用来集成langchain。可以集成不同的LLM模型,openai或者huggingface上的模型,也能集成不同的向量数据库,例如milvus,pinecone,redis,pgvector等。
这里以redis作为向量数据库为例,参考下图,一个完整的数据流程图。
分步解析如下:
-
将准备好的数据通过LLM转换成向量存入到向量数据库。
-
用户发送问题到应用程序。
-
在redis中查询相关联的数据。
-
将相关联的数据和用户问题一起发送到LLM。
-
由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/
-
导入数据到向量数据库,这里需要指定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是成对出现。
public class RetrieverExample implements Retriever<TextSegment> {
private final EmbeddingStoreRetriever retriever;
RetrieverExample(RedisEmbeddingStore store, EmbeddingModel model) {
retriever = EmbeddingStoreRetriever.from(store, model, 20);
}
public List<TextSegment> findRelevant(String s) {
return retriever.findRelevant(s);
}
}
-
定义模型,这里指定retriever以及prompt。
public interface Bot {
你作为一个AI机器人回答关于财务相关的问题。
你的回答必须要有礼貌,用中文回答问题,并且确保回答的问题是跟财务相关的。
如果你不知道,回答你不知道这个问题的回答,请直接联系客户经理。
用"我是您的智能客服,请问有什么可以帮助到您吗"
""")
String chat( Object session, String question);
}
-
处理用户请求。只需要调用模型中定义的方法即可,这里以ws为例子。
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的集成,最终演示效果如下。