今天和小伙伴们分享一下使用 langchain4j 快速搭建一个 RAG 应用。
前面松哥和大家聊了什么是 RAG,以及 RAG 开发所涉及到的技术栈。
前面几篇文章涉及到技术的,松哥都是使用 Python 来演示的,今天我们回归到自己的大本营,拿出我们的看家本领 Java,一起来简单的玩一下 langchain4j。
大语言模型(如 ChatGPT)的知识储备截止于训练数据,无法主动获取新信息。当遇到以下场景时,我们需要 RAG 技术:
开卷考试式的知识增强。
RAG(检索增强生成) 就像给模型一本“参考书”,在回答问题前自动查找相关知识,再结合这些信息生成答案。这种方法能显著减少模型“瞎编乱造”的问题。
核心流程:


方式 | 原理 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
关键词检索 | 匹配关键词(如百度搜索) | 速度快 | 无法理解语义 | 简单问题 |
向量检索 | 通过语义相似度查找(如找近义词) | 理解深层含义 | 需要算力支持 | 复杂语义问题 |
混合检索 | 结合前两种方式 | 查全率高 | 实现复杂 | 专业领域问答 |
例如问“苹果新品”,关键词检索会找含“苹果”的文档,而向量检索能识别“iPhone发布”相关内容。
维度 | RAG | 微调 |
|---|---|---|
数据时效性 | 实时更新 | 依赖训练数据 |
实施难度 | 较低 | 需要标注数据 |
数据安全 | 知识不外泄 | 需上传数据 |
成本 | 较低 | 训练费用高 |
在企业应用中,我们可以将两者结合:用RAG处理动态知识,微调优化回答风格
RAG 相当于给 AI 装了个“实时知识库”,让它既能保持通用智能,又具备专业领域的精准回答能力。这种技术已应用于智能客服(如银行业务咨询)、医疗问答系统等多个场景。

langchain4j 提供了三种构建 RAG 应用的方案,分别是:
我们分别来介绍下。
bge-small-en-v1.5)
• 内存型向量存储(InMemoryEmbeddingStore)代码示例:
// 加载文档并自动处理
List<Document> docs = FileSystemDocumentLoader.loadDocuments("/Users/youyou/javaboy/doc",new PDFDocumentParser());
EmbeddingStore<TextSegment> store = new InMemoryEmbeddingStore<>();
EmbeddingStoreIngestor.ingest(docs, store); // 自动分块+嵌入
InMemoryEmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>();
EmbeddingStoreIngestor.ingest(docs, embeddingStore);
ChatLanguageModel chatModel = ZhipuAiChatModel.builder()
.apiKey(API_KEY)
.model("glm-4")
.temperature(0.6)
.maxToken(1024)
.maxRetries(1)
.callTimeout(Duration.ofSeconds(60))
.connectTimeout(Duration.ofSeconds(60))
.writeTimeout(Duration.ofSeconds(60))
.readTimeout(Duration.ofSeconds(60))
.build();
Assistant assistant = AiServices.builder(Assistant.class)
.chatLanguageModel(chatModel)
.chatMemory(MessageWindowChatMemory.withMaxMessages(10))
.contentRetriever(EmbeddingStoreContentRetriever.from(embeddingStore))
.build();
String answer = assistant.answer("江南一点雨为什么选择做开发?");
System.out.println("answer = " + answer);
优势:10 分钟内完成部署,适合验证性需求 局限:无法调整分块策略或更换嵌入模型
核心特点:灵活配置各组件,适配中等复杂度需求 适用场景:企业知识库、需定制分块规则的项目 可调参数: • 分块策略(按段落/句子/固定长度) • 嵌入模型(支持本地 ONNX 或云端 API) • 向量存储类型(Redis/Pinecone/Elasticsearch/Milvus 等)
代码示例:
//1.读取文件
AutoDetectParser parser = new AutoDetectParser();
BodyContentHandler bodyContentHandler = new BodyContentHandler();
parser.parse(new FileInputStream("/Users/youyou/Desktop/jianying/松哥/思否有约访谈提纲 - 江南一点雨.docx"), bodyContentHandler, new Metadata());
Document document = Document.from(bodyContentHandler.toString());
//2.文件切分
DocumentByParagraphSplitter splitter = new DocumentByParagraphSplitter(150, 50);
List<TextSegment> textSegments = splitter.split(document);
//3.文件向量化
ZhipuAiEmbeddingModel embeddingModel = ZhipuAiEmbeddingModel.builder()
.apiKey(API_KEY)
.logRequests(true)
.logResponses(true)
.maxRetries(1)
.callTimeout(Duration.ofSeconds(60))
.connectTimeout(Duration.ofSeconds(60))
.writeTimeout(Duration.ofSeconds(60))
.readTimeout(Duration.ofSeconds(60))
.build();
Response<List<Embedding>> embedded = embeddingModel.embedAll(textSegments);
//4.向量存储
MilvusEmbeddingStore store = MilvusEmbeddingStore.builder()
.host("localhost")
.port(19530)
.collectionName("javaboy_collection_data_3")
.dimension(1024)
.indexType(IndexType.FLAT)
.metricType(MetricType.COSINE)
.username("username")
.password("password")
.consistencyLevel(ConsistencyLevelEnum.EVENTUALLY)
.autoFlushOnInsert(true)
.idFieldName("id")
.textFieldName("text")
.metadataFieldName("metadata")
.vectorFieldName("vector")
.build();
store.addAll(embedded.content(), textSegments);
//5. 搜索
ContentRetriever contentRetriever = EmbeddingStoreContentRetriever.builder()
.embeddingStore(store)
.embeddingModel(embeddingModel)
.maxResults(2)
.minScore(0.5)
.build();
ChatMemory chatMemory = MessageWindowChatMemory.withMaxMessages(10);
ChatLanguageModel chatModel = ZhipuAiChatModel.builder()
.apiKey(API_KEY)
.model("glm-4")
.temperature(0.6)
.maxToken(1024)
.maxRetries(1)
.callTimeout(Duration.ofSeconds(60))
.connectTimeout(Duration.ofSeconds(60))
.writeTimeout(Duration.ofSeconds(60))
.readTimeout(Duration.ofSeconds(60))
.build();
Assistant assistant = AiServices.builder(Assistant.class)
.chatLanguageModel(chatModel)
.contentRetriever(contentRetriever)
.chatMemory(chatMemory)
.build();
String answer = assistant.answer("江南一点雨为什么选择做开发?");
System.out.println("answer = " + answer);
优势:支持优化分块策略(如医疗报告按章节拆分) 局限:需自行管理组件兼容性
从上面的代码大家可以看出,Easy RAG 主要是简化了 Native RAG 中的 2、3、4 三个步骤。
来看下面一张图:

这个工作流程就像图书馆管理员帮你查资料的过程:
整个过程就像有个智能图书管理员,既会拆解复杂问题,又会多途径查资料,最后请专家基于资料写答案。这种方式比直接问专家更可靠,因为专家是看着真实资料作答的。
核心特点:支持复杂检索逻辑(混合搜索+重排序)
适用场景:金融风控、法律咨询等高精度需求场景 高级功能:
优势:召回率提升 30% 以上 局限:开发复杂度高,需理解检索算法原理
召回率表示 “系统实际检索到的相关文档数” 占 “数据库中所有相关文档总数” 的比例。 召回率的公式为:召回率 = 检索到的相关文档数(TP) / 所有相关文档总数(TP + FN) 其中:
例如医疗诊断场景中,若实际有 100 个病例需检测,系统正确识别 70 个但漏掉 30 个,召回率为 70%。
Advanced RAG 这块涉及到的内容比较多,松哥后面再单独开文章和大家讲。

三 选型建议
• 测试 Demo 或内部工具 → Easy RAG • 企业知识库系统 → Native RAG • 金融/法律专业问答 → Advanced RAG
通过这种分层设计,LangChain4j 既能满足快速试错需求,又能支撑企业级复杂系统构建。开发者可根据项目阶段选择合适方案,后期也可从 Easy RAG 平滑升级到 Advanced RAG。