LangChain4j 入门:Java 开发者构建 LLM 应用指南 – wiki大全


LangChain4j 入门:Java 开发者构建 LLM 应用指南

在人工智能时代,大型语言模型(LLM)正以前所未有的速度改变着软件开发的面貌。从智能客服到内容生成,LLM 的应用潜力无限。然而,直接与 LLM 交互并构建复杂的应用往往涉及多步协调、数据处理和外部系统集成。这时,LangChain 框架应运而生,它提供了一套工具、组件和接口,极大地简化了基于 LLM 的应用开发。

虽然 Python 版本的 LangChain 广为人知,但对于广大的 Java 开发者而言,LangChain4j 则是构建 LLM 应用的理想选择。它将 LangChain 的核心概念和功能完美地移植到了 Java 生态系统,让 Java 开发者能够充分利用其强大的工程能力和丰富的工具链。

本文将带领 Java 开发者深入了解 LangChain4j,从核心概念到实战演练,手把手教你如何使用 LangChain4j 构建你的第一个 LLM 应用。

1. 为什么选择 LangChain4j?

在深入技术细节之前,我们先来探讨一下为什么 Java 开发者应该关注并使用 LangChain4j:

  • Java 生态集成: 作为 Java 原生框架,LangChain4j 无缝融入 Spring Boot、Quarkus 等主流 Java 框架,利用现有的构建工具(Maven/Gradle)、依赖管理和开发实践。
  • 企业级应用支持: Java 在企业级应用开发中占据主导地位,LangChain4j 为构建可伸缩、高性能、易于维护的 LLM 驱动型企业级应用提供了坚实的基础。
  • 清晰的抽象: LangChain4j 提供了高级抽象,将 LLM 交互、链式调用、记忆管理、数据检索等复杂逻辑封装起来,让开发者能更专注于业务逻辑。
  • 丰富的集成: 它支持多种主流 LLM 提供商(如 OpenAI, Azure OpenAI, Google Gemini/Vertex AI, Hugging Face 等),以及各种数据存储(向量数据库)和工具。
  • 活跃的社区与持续发展: LangChain4j 社区正在积极发展,功能不断完善,文档和示例也日益丰富。

2. LangChain4j 核心概念

理解 LangChain4j 的核心概念是掌握其使用的关键:

2.1. LLM (Large Language Model)

这是所有 LLM 应用的核心。LangChain4j 提供了统一的接口来与不同的 LLM 提供商进行交互。你可以配置 API 密钥、模型名称、温度等参数。

“`java
// 以 OpenAI 为例
OpenAiChatModel model = OpenAiChatModel.builder()
.apiKey(System.getenv(“OPENAI_API_KEY”))
.modelName(“gpt-4”)
.temperature(0.7)
.build();

String response = model.generate(“请用一句话介绍LangChain4j是什么?”);
System.out.println(response);
“`

2.2. Prompt (提示)

Prompt 是你给 LLM 的指令或问题。LangChain4j 提供了灵活的方式来构建和管理 Prompt,包括模板、变量替换等。

“`java
// 使用 PromptTemplate
PromptTemplate promptTemplate = PromptTemplate.from(“请根据以下信息,用友好的语气为{{name}}写一封欢迎信:{{context}}”);
Map variables = new HashMap<>();
variables.put(“name”, “张三”);
variables.put(“context”, “他刚加入我们的团队,对新技术充满热情。”);
Prompt prompt = promptTemplate.apply(variables);

String response = model.generate(prompt.text());
System.out.println(response);
“`

2.3. Chain (链)

Chain 是 LangChain4j 的核心概念之一,它允许你将多个 LLM 调用或其他处理步骤连接起来,形成一个有序的工作流。这使得构建复杂应用变得更加简单。常见的 Chain 类型包括:

  • SimpleChain: 简单的单步 LLM 调用。
  • RetrievalQaChain: 将检索增强生成(RAG)与问答结合。
  • StuffDocumentsChain: 将多个文档“塞”到一个 Prompt 中进行处理。
  • SequentialChain: 顺序执行多个 Chain,并将一个 Chain 的输出作为下一个 Chain 的输入。

java
// 简单链示例 (Conceptual)
// LLMChain 接收 PromptTemplate 和 LLM,生成回复
// 实际使用可能更复杂,涉及输入/输出解析
// LangChain4j通常直接通过Service或更高级抽象来实现链式调用

2.4. Memory (记忆)

在多轮对话中,LLM 需要记住之前的对话内容才能保持上下文连贯。LangChain4j 提供了多种记忆实现:

  • ChatMemory: 存储对话历史。
  • MessageWindowChatMemory: 限制记忆的消息数量,防止 Prompt 过长。
  • TokenWindowChatMemory: 限制记忆的 token 数量。

“`java
// 对话记忆示例
ChatMemory chatMemory = MessageWindowChatMemory.builder()
.maxMessages(10) // 最多记住10条消息
.build();

// 第一次对话
chatMemory.add(“user”, “你好,我的名字是小明。”);
String response1 = model.generate(chatMemory.messages());
chatMemory.add(“ai”, response1);
System.out.println(“AI: ” + response1);

// 第二次对话,AI可以记住小明是用户
chatMemory.add(“user”, “你记得我的名字吗?”);
String response2 = model.generate(chatMemory.messages());
chatMemory.add(“ai”, response2);
System.out.println(“AI: ” + response2);
“`

2.5. Document Loader & Document Splitter (文档加载器与分割器)

当需要处理大量文本数据时(如文档、网页内容),LangChain4j 提供了工具来加载这些数据,并将其分割成更小的块,以便 LLM 处理和向量存储。

  • DocumentLoader: 从文件、URL 等加载文档。
  • DocumentSplitter: 将长文档分割成指定大小的块。

“`java
// 假设有一个文本文件 “document.txt”
// DocumentLoader documentLoader = new FileSystemDocumentLoader(“document.txt”);
// List documents = documentLoader.load();

// DocumentSplitter splitter = new CharacterTextSplitter(1000, 100); // 块大小1000,重叠100
// List segments = splitter.split(documents);
// System.out.println(“分割成 ” + segments.size() + ” 个文本片段”);
“`

2.6. Embedding Model (嵌入模型) 与 Vector Store (向量存储)

这是构建 RAG(Retrieval-Augmented Generation)应用的关键。嵌入模型将文本转换为数值向量,向量存储则用于高效地存储和检索这些向量。

  • EmbeddingModel: 将文本转换为向量。
  • VectorStore: 存储文本片段及其对应的向量,支持相似度搜索。常见的有 Chroma, Pinecone, Milvus 等,LangChain4j 也提供了本地 In-Memory Vector Store。

“`java
// 嵌入模型
OpenAiEmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder()
.apiKey(System.getenv(“OPENAI_API_KEY”))
.modelName(“text-embedding-ada-002”)
.build();

// 向量存储 (In-Memory 示例)
InMemoryVectorStore vectorStore = new InMemoryVectorStore<>();

// 将文本片段转换为向量并存储
// List embeddings = embeddingModel.embedAll(segments).content();
// vectorStore.addAll(embeddings, segments);

// 检索相似文本
// Embedding queryEmbedding = embeddingModel.embed(“LangChain4j 的主要优点是什么?”).content();
// List> relevantSegments = vectorStore.findRelevant(queryEmbedding, 3);
// relevantSegments.forEach(s -> System.out.println(s.text()));
“`

2.7. Agent (代理) 与 Tool (工具)

Agent 是一个更高级的概念,它能根据用户的指令,自主决定使用哪些工具来完成任务。Tools 则是 Agent 可以调用的外部函数或服务,比如执行计算、查询数据库、调用 API 等。

“`java
// 假设有一个工具
public class Calculator {
public int add(int a, int b) {
return a + b;
}
}

// 代理 (Conceptual)
// 需要结合LLM、Prompt和ToolSpecification来构建一个Agent
// LLMAgent agent = …
// agent.chat(“请计算 123 + 456”);
“`

3. 构建你的第一个 LangChain4j 应用:RAG 问答机器人

我们将创建一个简单的 RAG(Retrieval-Augmented Generation)问答机器人,它能够从提供的文档中检索相关信息,然后利用 LLM 回答用户的问题。

目标: 让机器人能够回答关于 LangChain4j 文档中的问题,即使这些信息不在 LLM 的训练数据中。

3.1. 项目设置

首先,创建一个新的 Maven 或 Gradle 项目。

Maven pom.xml 依赖:

xml
<dependencies>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>0.26.1</version> <!-- 使用最新版本 -->
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>0.26.1</version> <!-- 如果使用OpenAI -->
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.7</version> <!-- 日志框架 -->
</dependency>
</dependencies>

Gradle build.gradle 依赖:

gradle
dependencies {
implementation 'dev.langchain4j:langchain4j:0.26.1' // 使用最新版本
implementation 'dev.langchain4j:langchain4j-open-ai:0.26.1' // 如果使用OpenAI
implementation 'org.slf4j:slf4j-simple:2.0.7' // 日志框架
}

3.2. 准备数据

创建一个名为 document.txt 的文件,包含一些关于 LangChain4j 的信息,例如:

LangChain4j is a Java port of the popular LangChain framework. It allows Java developers to build applications powered by large language models (LLMs).
Key features include:
- Integration with various LLM providers like OpenAI, Azure OpenAI, Google AI.
- Support for different types of Chains to orchestrate LLM calls.
- Memory management for conversational AI.
- Document loaders and splitters for processing unstructured data.
- Embedding models and vector stores for Retrieval-Augmented Generation (RAG).
- Agent capabilities to empower LLMs with external tools.
LangChain4j is designed for enterprise-grade applications, providing a robust and scalable solution for integrating generative AI into Java systems.

3.3. 编写 RAG 问答机器人代码

我们将创建一个 Java 类 RagChatBot

“`java
import dev.langchain4j.chain.ConversationalRetrievalChain;
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.DocumentSplitter;
import dev.langchain4j.data.document.loader.FileSystemDocumentLoader;
import dev.langchain4j.data.document.splitter.DocumentByParagraphSplitter;
import dev.langchain4j.data.embedding.Embedding;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.openai.OpenAiEmbeddingModel;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Scanner;

import static dev.langchain4j.data.document.loader.FileSystemDocumentLoader.loadDocument;
import static dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore.fromMetadata;

public class RagChatBot {

private final ConversationalRetrievalChain chain;
private final ChatMemory chatMemory;

public RagChatBot(String openaiApiKey) {
    // 1. 配置 LLM 和 Embedding Model
    ChatLanguageModel chatModel = OpenAiChatModel.builder()
            .apiKey(openaiApiKey)
            .modelName("gpt-4") // 或 gpt-3.5-turbo
            .temperature(0.7)
            .build();

    EmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder()
            .apiKey(openaiApiKey)
            .modelName("text-embedding-ada-002")
            .build();

    // 2. 加载并处理文档
    Path documentPath = Paths.get("document.txt"); // 确保document.txt在项目根目录
    Document document = loadDocument(documentPath);

    DocumentSplitter splitter = new DocumentByParagraphSplitter(); // 按段落分割
    List<TextSegment> segments = splitter.split(document);

    // 3. 将文档片段嵌入并存储到向量数据库 (这里使用内存实现)
    EmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>();
    List<Embedding> embeddings = embeddingModel.embedAll(segments).content();
    embeddingStore.addAll(embeddings, segments);

    // 4. 配置对话记忆
    chatMemory = MessageWindowChatMemory.builder()
            .maxMessages(10) // 记住最近10条消息
            .build();

    // 5. 构建 ConversationalRetrievalChain
    chain = ConversationalRetrievalChain.builder()
            .chatLanguageModel(chatModel)
            .embeddingModel(embeddingModel) // 用于将用户问题转换为向量
            .embeddingStore(embeddingStore) // 用于检索相关文档
            .chatMemory(chatMemory)
            .build();
}

public String chat(String userMessage) {
    return chain.execute(userMessage);
}

public static void main(String[] args) {
    String openaiApiKey = System.getenv("OPENAI_API_KEY");
    if (openaiApiKey == null || openaiApiKey.isEmpty()) {
        System.err.println("请设置环境变量 OPENAI_API_KEY");
        return;
    }

    RagChatBot bot = new RagChatBot(openaiApiKey);
    Scanner scanner = new Scanner(System.in);

    System.out.println("欢迎使用 LangChain4j RAG 问答机器人!输入 'exit' 退出。");
    while (true) {
        System.out.print("你: ");
        String userMessage = scanner.nextLine();

        if ("exit".equalsIgnoreCase(userMessage)) {
            System.out.println("再见!");
            break;
        }

        String botResponse = bot.chat(userMessage);
        System.out.println("机器人: " + botResponse);
    }
    scanner.close();
}

}
“`

3.4. 运行应用

  1. 设置 OpenAI API Key:
    在运行之前,你需要获取一个 OpenAI API Key,并将其设置为环境变量 OPENAI_API_KEY

    • 在 Linux/macOS: export OPENAI_API_KEY="你的API密钥"
    • 在 Windows PowerShell: $env:OPENAI_API_KEY="你的API密钥"
    • 在 Windows CMD: set OPENAI_API_KEY="你的API密钥"
  2. 编译并运行:
    如果你使用 Maven,可以在项目根目录执行:
    mvn clean install exec:java -Dexec.mainClass="RagChatBot"

    如果你使用 IDE,直接运行 RagChatBotmain 方法。

现在,你可以向机器人提问关于 document.txt 中内容的问题了,例如:

  • LangChain4j 是什么?
  • LangChain4j 有哪些主要特性?
  • LangChain4j 主要用于什么类型的应用?

你会发现机器人能够基于 document.txt 的内容给出准确的回答。

4. 进阶使用与未来方向

  • 更复杂的 Chain: 探索 SequentialChainRouterChain 等,构建多步骤、条件判断的工作流。
  • 持久化向量存储:InMemoryEmbeddingStore 替换为生产级的向量数据库,如 ChromaPineconeWeaviateQdrantMilvus,以支持更大规模的数据和持久化存储。
  • 自定义工具 (Tools): 为你的 Agent 开发自定义工具,使其能够执行特定的业务操作,如查询内部数据库、调用第三方 API、执行计算等。
  • Agent 的使用: 深入学习如何配置和使用 Agent,让 LLM 能够自主决策并使用工具完成复杂任务。
  • Prompt Engineering: 优化 Prompt 模板,使用更有效的指令、Few-shot 示例等,提高 LLM 的输出质量。
  • 评估与监控: 学习如何评估 LLM 应用的性能,并集成监控工具。
  • Web 框架集成: 将 LangChain4j 应用与 Spring Boot、Quarkus 等 Web 框架结合,构建 RESTful API 或 Web 应用。
  • 错误处理与重试机制: 在实际应用中,LLM API 调用可能会失败,需要健壮的错误处理和重试机制。

总结

LangChain4j 为 Java 开发者打开了构建 LLM 驱动应用的全新大门。通过理解其核心概念,如 LLM、Prompt、Chain、Memory、Embedding 和 Vector Store,你就能从零开始构建功能强大的智能应用。RAG 问答机器人仅仅是一个开始,LangChain4j 的灵活性和可扩展性将支持你构建出更复杂、更智能的企业级解决方案。

现在,是时候开始你的 LangChain4j 之旅,用 Java 语言拥抱人工智能的未来了!


滚动至顶部