聊点实在的。LangChain4j 这个框架,网上的资料确实不少,但很多要么太教条,要么直接甩你一堆官方文档链接。今天这篇不谈空话,就是把自己本地搭建的完整过程掰开揉碎了说,连我掉进去的那些坑都一并扒出来。


一、迈出第一步之前,把“地基”夯实

说真的,本地跑大模型比想象中简单得多。你不需要一台几十万的企业级服务器,只要你手头的电脑配置不太拉跨就行。

硬件到底需要啥? 根据我自己的经历,如果你只是跑个本地 Demo,不需要 GPU,CPU 模式完全够用。我当初用的一台 8 核处理器、16G 内存的 MacBook Pro,跑起来顺畅得很。但如果你想本地跑个大点的模型(比如 7B 参数的 Llama 或者 Qwen),那就得看你的 GPU 了——有个 8G 以上显存的显卡,体验会舒服很多。如果你还在用 4G 显存的入门卡,别灰心,选个 1.5B 到 3B 的小模型,照样能玩转。

软件环境:Java 必须是 JDK 17 或以上版本,这是硬性要求,因为 LangChain4j 依赖了一些 Java 17 的新特性。构建工具我选的是 Maven(个人习惯,Gradle 也行),IDE 用的 IntelliJ IDEA,基本是 Java 开发的标配。

本地大模型怎么选? 我强烈推荐用 Ollama 来部署本地模型。Ollama 是一个专门在本地跑大模型的工具,安装极其简单,一条命令就能把 Llama、Mistral、Qwen 这些模型拉下来跑起来。

安装 Ollama:去 https://ollama.com 下载对应的安装包,双击一路 Next 就行。安装完成后,打开终端,输入这条命令来拉取一个比较轻量的模型:

ollama pull qwen2.5:3b

这条命令会从 Ollama 的模型仓库里下载阿里通义千问 2.5 版本,参数规模 3B。这个模型对中文的支持特别好,而且 3B 的规模普通电脑 CPU 跑起来也毫无压力。下载完成后,可以用 ollama run qwen2.5:3b 先在命令行里测试一下,确保模型能正常对话,再开始下一步。

二、Maven 依赖:版本选不对,后面全是坑

这里我想多唠叨几句。LangChain4j 的版本迭代速度非常快,而且现在主版本已经从之前的 0.x 系列全面升级到了 1.x 系列。如果你在网上搜教程,看到别人用的还是 0.272.0 这种老版本,千万别盲目跟——老版本的 API 和新版可能完全不兼容,跑起来全是编译报错。

根据官方文档,推荐使用 BOM(Bill of Materials)方式来统一管理版本,这样各个模块的版本不会打架:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-bom</artifactId>
            <version>1.3.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <!-- LangChain4j 核心库 -->
    <dependency>
        <groupId>dev.langchain4j</groupId>
        <artifactId>langchain4j</artifactId>
    </dependency>
    <!-- Ollama 集成 -->
    <dependency>
        <groupId>dev.langchain4j</groupId>
        <artifactId>langchain4j-ollama</artifactId>
    </dependency>
    <!-- 本地轻量级 Embedding 模型,用于 RAG -->
    <dependency>
        <groupId>dev.langchain4j</groupId>
        <artifactId>langchain4j-embeddings-all-minilm-l6-v2</artifactId>
    </dependency>
    <!-- 极简版 RAG 依赖,开箱即用 -->
    <dependency>
        <groupId>dev.langchain4j</groupId>
        <artifactId>langchain4j-easy-rag</artifactId>
    </dependency>
</dependencies>

注意这里的 langchain4j-bom 版本号要和你实际使用的版本保持一致。如果你在 Maven 中央仓库查到最新的稳定版是 1.12.x,就用那个版本的 BOM。另外,官方文档里提到 LangChain4j 很多模块目前还是 beta 版,使用时要有心理准备。

三、第一个 Hello World:让 Java 和大模型说上话

依赖配好了,写段代码跑起来试试。

import dev.langchain4j.model.ollama.OllamaChatModel;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.output.Response;

public class FirstAIChat {
    public static void main(String[] args) {
        // 配置 Ollama 模型(注意:模型名要和 ollama pull 时的名字一致)
        ChatLanguageModel model = OllamaChatModel.builder()
            .baseUrl("http://localhost:11434")  // Ollama 默认端口
            .modelName("qwen2.5:3b")            // 你本地拉取的模型名
            .temperature(0.7f)                  // 控制回复的随机性
            .build();
        
        // 简单提问
        String userMessage = "用一句话介绍 Java 的特点";
        Response<String> answer = model.generate(userMessage);
        
        System.out.println("AI 回复:" + answer.content());
    }
}

这段代码里,temperature 是一个挺有意思的参数——数值越低,模型的回复越保守、越固定;数值越高,回复越有“想象力”,但也更容易跑偏。0.7 是个比较折中的值,适合日常对话。

运行之前,千万记得确认一件事:你的 Ollama 服务必须已经启动并且 qwen2.5:3b 模型已经下载完毕。如果 Ollama 没跑起来,这段代码会直接报连接异常,这个坑我当初踩了至少三回。

如果你顺利跑通了,控制台应该会输出类似这样的内容:

AI 回复:Java 是一种跨平台的面向对象编程语言,以其“一次编写,到处运行”的特点而闻名。

看到这个输出,说明你的 Java 项目已经成功和本地大模型对话上了。

四、对话记忆:让 AI 不再“健忘”

上面那个例子,每次调用 generate() 都是独立的,AI 不记得你刚才说过什么。要让对话有上下文,就需要用到 ChatMemory。LangChain4j 提供了好几种记忆实现,最常用的是 MessageWindowChatMemory,它能记住最近的 N 条对话。

import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.ollama.OllamaChatModel;
import dev.langchain4j.model.chat.ChatLanguageModel;

public class ChatWithMemory {
    public static void main(String[] args) {
        ChatLanguageModel model = OllamaChatModel.builder()
            .baseUrl("http://localhost:11434")
            .modelName("qwen2.5:3b")
            .temperature(0.7f)
            .build();
        
        // 创建能记住最近 10 条消息的对话记忆
        ChatMemory chatMemory = MessageWindowChatMemory.withMaxMessages(10);
        
        // 模拟多轮对话
        String[] userMessages = {
            "我叫张三",
            "我刚才说我叫什么来着?",
            "我的名字里第一个字是什么?"
        };
        
        for (String msg : userMessages) {
            chatMemory.add(new UserMessage(msg));
            Response<String> response = model.generate(chatMemory.messages());
            System.out.println("用户:" + msg);
            System.out.println("AI:" + response.content());
            chatMemory.add(new AssistantMessage(response.content()));
            System.out.println("---");
        }
    }
}

跑完这段代码,你会发现 AI 能准确记住你之前说过的名字,这就是 ChatMemory 在背后起的作用。MessageWindowChatMemory.withMaxMessages(10) 表示最多保留最近 10 条消息,超过这个数量会自动丢弃最旧的消息。

五、给 AI 配上“知识库”:极简版 RAG

对话记忆只是让 AI 记住你刚才说了什么,但如果想让 AI 回答关于你公司内部文档、产品说明书之类的私有知识,就需要 RAG(检索增强生成)了。简单说,就是给 AI 配一个“资料库”,让它在回答之前先去资料库里翻一翻。

LangChain4j 有一个极简版的 RAG 实现,开箱即用,最适合快速验证效果。

假设你在项目的 src/main/resources/docs 目录下放了几份技术文档(比如 Java编程学习路线.md常见面试题.md 之类的),用下面这段代码就能让 AI 基于这些文档回答问题:

import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.FileSystemDocumentLoader;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.embedding.onnx.allminilml6v2.AllMiniLmL6V2EmbeddingModel;
import dev.langchain4j.model.ollama.OllamaChatModel;
import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;
import dev.langchain4j.rag.DefaultRetrievalAugmentor;
import dev.langchain4j.rag.RetrievalAugmentor;
import dev.langchain4j.model.chat.ChatLanguageModel;

// 定义 AI Service 接口
interface MyAssistant {
    String chat(String userMessage);
}

public class SimpleRAGDemo {
    public static void main(String[] args) {
        // 1. 加载本地文档
        List<Document> documents = FileSystemDocumentLoader.loadDocuments("src/main/resources/docs");
        
        // 2. 创建 Embedding 模型(将文本转为向量的模型)
        EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel();
        
        // 3. 创建内存向量存储
        EmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>();
        
        // 4. 将文档向量化并存入存储
        EmbeddingStoreIngestor.ingest(documents, embeddingStore);
        
        // 5. 创建 Chat 模型
        ChatLanguageModel chatModel = OllamaChatModel.builder()
            .baseUrl("http://localhost:11434")
            .modelName("qwen2.5:3b")
            .build();
        
        // 6. 构建带 RAG 能力的 AI Service
        MyAssistant assistant = AiServices.builder(MyAssistant.class)
            .chatModel(chatModel)
            .contentRetriever(EmbeddingStoreContentRetriever.from(embeddingStore))
            .build();
        
        // 7. 测试问答
        String question = "Java 里如何实现多线程?";
        String answer = assistant.chat(question);
        System.out.println("问题:" + question);
        System.out.println("回答:" + answer);
    }
}

这段代码的核心逻辑是:先把你的文档向量化存起来,用户提问时,系统先从向量库里检索相关的内容,然后把检索到的内容作为“参考资料”连同问题一起喂给大模型,让模型基于这些资料来回答。

这里特别想提一句,AllMiniLmL6V2EmbeddingModel 是个本地轻量级 Embedding 模型,不需要调用任何外部 API,数据完全在本地处理。如果你对数据安全有要求,或者不方便联网,用这个就对了。

六、别踩这些坑

这几条是我用 LangChain4j 过程中真实踩过的坑,希望能帮你省下好几个小时的 debug 时间。

坑一:版本冲突。 LangChain4j 还在快速迭代中,部分模块目前还是 beta 版本。不同模块之间版本不一致,可能会导致一些奇奇怪怪的方法找不到。解决方案:用上面推荐的 BOM 方式统一版本,千万不要手动分别指定各个模块的版本号。

坑二:官方文档不一定全。 有人吐槽过 LangChain4j 的官方文档“该有的重要内容是一点都不介绍”。比如想把对话记忆持久化到数据库,官方文档几乎没有相关说明,需要自己翻源码。遇到这种情况,去 GitHub 上搜相关的 issue 或者直接看源码可能是更高效的办法。

坑三:模型的 SDK 差异。 有网友分享过一个亲身经历:同样的代码,用阿里百炼模型跑就各种报错,换成 OpenAI 之后就丝般顺滑,最后发现是模型 SDK 的源码 BUG。所以如果你本地跑不通,别死磕一个模型,换 Ollama 上另一个模型试试,说不定问题就解决了。

坑四:Ollama 没启动就调用。 这个坑我踩了好几次。代码写得再漂亮,如果 Ollama 服务没跑起来或者模型没下载完,调用 model.generate() 的时候会直接报 Connection refused 异常。运行前先用 ollama list 确认模型已下载,用 ollama ps 确认服务在运行。

坑五:流式输出的用法差异。 如果你想实现逐字输出的效果(像 ChatGPT 那样一个字一个字蹦出来),不能用普通的 ChatLanguageModel,需要换成 StreamingChatLanguageModel 并配合 langchain4j-reactor 依赖。这个坑在官方文档里说得不够清楚,单独提一下。

七、写在最后

说实话,LangChain4j 这个框架确实不完美。它的官方文档算不上详尽,有些功能还在 beta 阶段,偶尔会遇到一些意想不到的 bug。但话说回来,作为一个 Java 开发者,能有这样一个原生框架帮我们打通和大模型之间的“最后一公里”,已经是一件很值得庆幸的事情了。

我自己的经验是:从最简单的一个 Hello World 开始,先跑通单次对话;然后慢慢引入 ChatMemory 做多轮对话;再试试 RAG 给你的应用加上知识库。一步一步来,每往前走一步,你都会对这个框架的理解更深一点。

希望这篇教程能帮你少走一些弯路。如果你在搭建过程中遇到什么问题,或者有什么好玩的实践想分享,欢迎留言交流——毕竟,Java 圈做大模型应用的人还是少数,咱们更需要互相帮衬。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐