LangChain4j 集成 Mistral AI Embedding:Java 语义搜索与 RAG 实战指南
【免费下载链接】langchain4jLangChain4j is an idiomatic, open-source Java library for building LLM-powered applications on the JVM. It offers a unified API over popular LLM providers and vector stores, and makes implementing tool calling (including MCP support), agents and RAG easy. It integrates seamlessly with enterprise Java frameworks like Quarkus and Spring Boot.项目地址: https://gitcode.com/GitHub_Trending/la/langchain4j
LangChain4j 为 JVM 生态提供了统一的 LLM 构建接口,其中langchain4j-mistral-ai模块封装了 Mistral AI 的 Embedding(文本向量化)能力,让你可以用纯 Java 代码将句子编码为向量、构建向量库并完成语义检索。本文将从依赖配置、API Key 管理、端到端语义搜索示例出发,深入MistralAiEmbeddingModel的源码实现,讲解 Builder 各项参数、底层请求/响应模型、token 用量统计与重试机制,并说明如何将 Mistral AI Embedding 与 RAG 流程结合,帮助你快速落地基于语义相似度的检索应用。
项目准备:添加依赖
在开始之前,需要先在你的 Java 项目中引入 LangChain4j 的核心库与 Mistral AI 集成模块。当前仓库中该模块的完整坐标可在 langchain4j-mistral-ai/pom.xml 确认,其内部依赖langchain4j-core、langchain4j-http-client以及运行时使用的langchain4j-http-client-jdk(负责底层 HTTP 通信,默认 JDK HttpClient 实现)。
对于 Maven 项目,在pom.xml中添加:
<dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j</artifactId> <version>1.20.0</version> </dependency> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-mistral-ai</artifactId> <version>1.20.0</version> </dependency>对于 Gradle 项目,在build.gradle中添加:
implementation 'dev.langchain4j:langchain4j:1.20.0' implementation 'dev.langchain4j:langchain4j-mistral-ai:1.20.0'版本说明:上述版本号是发布版的常用写法,当前仓库主线处于
1.21.0-SNAPSHOT开发阶段(见 langchain4j-mistral-ai/pom.xml),实际使用时应替换为你依赖的稳定版本。
API Key 配置
调用 Mistral AI 服务需要有效的 API Key。推荐的做法是将 Key 保存在环境变量中,避免硬编码进代码仓库。
创建一个ApiKeys.java工具类统一管理:
public class ApiKeys { public static final String MISTRALAI_API_KEY = System.getenv("MISTRAL_AI_API_KEY"); }然后在系统中设置环境变量:
export MISTRAL_AI_API_KEY=your-api-key # Unix 系操作系统 SET MISTRAL_AI_API_KEY=your-api-key # Windows 操作系统模块内部的集成测试同样约定读取名为MISTRAL_AI_API_KEY的环境变量,例如 MistralAiEmbeddingModelIT.java 使用@EnabledIfEnvironmentVariable(named = "MISTRAL_AI_API_KEY", matches = ".+")注解,只有当该变量存在时才运行真实 API 测试,这与本文的配置方式完全一致。
快速开始:一句话完成句子向量化
Mistral AI 的 Embedding 模型可以将任意文本映射为高维向量。下面的HelloWorld示例演示了完整流程:构建 Embedding 模型、将文本段编码为向量、存入内存向量库,再对用户查询做语义相似度检索。
import dev.langchain4j.data.embedding.Embedding; import dev.langchain4j.data.segment.TextSegment; import dev.langchain4j.model.mistralai.MistralAiEmbeddingModel; import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.store.embedding.EmbeddingMatch; import dev.langchain4j.store.embedding.EmbeddingStore; import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore; import java.util.List; public class HelloWorld { public static void main(String[] args) { EmbeddingModel embeddingModel = MistralAiEmbeddingModel.builder() .apiKey(System.getenv("MISTRAL_AI_API_KEY")) .modelName("mistral-embed") .build(); // For simplicity, this example uses an in-memory store, but you can choose any external compatible store for production environments. EmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>(); TextSegment segment1 = TextSegment.from("I like football."); Embedding embedding1 = embeddingModel.embed(segment1).content(); embeddingStore.add(embedding1, segment1); TextSegment segment2 = TextSegment.from("The weather is good today."); Embedding embedding2 = embeddingModel.embed(segment2).content(); embeddingStore.add(embedding2, segment2); String userQuery = "What is your favourite sport?"; Embedding queryEmbedding = embeddingModel.embed(userQuery).content(); EmbeddingSearchRequest searchRequest = EmbeddingSearchRequest.builder() .queryEmbedding(queryEmbedding) .maxResults(1) .build(); EmbeddingSearchResult<TextSegment> searchResult = embeddingStore.search(searchRequest); EmbeddingMatch<TextSegment> embeddingMatch = searchResult.matches().get(0); System.out.println("Question: " + userQuery); // What is your favourite sport? System.out.println("Response: " + embeddingMatch.embedded().text()); // I like football. } }示例的输出类似:
Question: What is your favourite sport? Response: I like football.关键点说明:
embed(TextSegment)返回Response<Embedding>,通过.content()取向量;查询字符串可以直接传给embed(String)重载;InMemoryEmbeddingStore是内存向量库,适合原型验证;生产环境可以替换为 LangChain4j 支持的外部向量存储(如langchain4j-pgvector、langchain4j-milvus、langchain4j-elasticsearch等模块);EmbeddingSearchRequest.maxResults(1)控制返回最相似的 1 条结果,由向量库内部完成相似度排序。
上述示例只手工添加了 2 个文本段。实际项目中,LangChain4j 内置了对多种来源的文档加载支持:文件系统、URL、Amazon S3、Azure Blob Storage、GitHub、Tencent COS 等(对应仓库中的document-loaders/目录),并支持解析 text、pdf、doc、xls、ppt 等多种文档格式(见document-parsers/目录),因此可以轻松把真实业务文档灌入向量库。
源码视角:MistralAiEmbeddingModel 如何工作
类继承与核心职责
MistralAiEmbeddingModel继承自DimensionAwareEmbeddingModel(定义于 langchain4j-core/src/main/java/dev/langchain4j/model/embedding/DimensionAwareEmbeddingModel.java),这是一个“维度感知”的抽象基类:
public abstract class DimensionAwareEmbeddingModel implements EmbeddingModel { protected Integer dimension; protected Integer knownDimension() { return null; } @Override public int dimension() { if (dimension != null) return dimension; Integer knownDimension = knownDimension(); this.dimension = Optional.ofNullable(knownDimension) .orElseGet(() -> embed("test").content().dimension()); return this.dimension; } }也就是说,当你调用dimension()时,如果模型名已知维度则直接返回,否则会以embed("test")一次真实调用推断向量维度并缓存。从测试断言可见,mistral-embed生成的向量维度为 1024(见 MistralAiEmbeddingModelIT.java),这有助于你在建表或选择向量存储索引时预先确定维度。
请求构造与响应解析
核心的批量嵌入方法embedAll位于 MistralAiEmbeddingModel.java:
@Override public Response<List<Embedding>> embedAll(List<TextSegment> textSegments) { MistralAiEmbeddingRequest request = MistralAiEmbeddingRequest.builder() .model(modelName) .input(textSegments.stream().map(TextSegment::text).collect(toList())) .encodingFormat(EMBEDDINGS_ENCODING_FORMAT) .build(); MistralAiEmbeddingResponse response = withRetryMappingExceptions(() -> client.embedding(request), maxRetries); List<Embedding> embeddings = response.getData().stream() .map(mistralAiEmbedding -> Embedding.from(mistralAiEmbedding.getEmbedding())) .collect(toList()); return Response.from(embeddings, tokenUsageFrom(response.getUsage())); }从源码可以看到三个关键设计:
- 请求体模型:
MistralAiEmbeddingRequest只包含三个字段——model(模型名)、input(文本列表,因此一次可批量嵌入多段文本)、encodingFormat(编码格式),定义于 MistralAiEmbeddingRequest.java。其中encodingFormat在模型内部被固定为"float"常量(见 MistralAiEmbeddingModel.java),无需用户干预。 - 自动重试:调用被
withRetryMappingExceptions(..., maxRetries)包裹,默认最多重试 2 次,可提升网络抖动场景下的稳定性。 - 响应映射:
MistralAiEmbeddingResponse(见 MistralAiEmbeddingResponse.java)包含id、object、model、data(向量列表)与usage(token 用量),其中usage通过MistralAiMapper.tokenUsageFrom转换为统一的TokenUsage对象(input/output/total 三部分),并随Response一并返回。
模型名枚举
mistral-embed等模型名被封装为枚举MistralAiEmbeddingModelName(见 MistralAiEmbeddingModelName.java)。构建模型时既可以直接传字符串,也可以传入枚举:
MistralAiEmbeddingModel.builder() .modelName(MistralAiEmbeddingModelName.MISTRAL_EMBED) // 等价于 "mistral-embed" .build();Builder 配置参数详解
MistralAiEmbeddingModel.builder()提供了丰富的可配置项(对应 MistralAiEmbeddingModel.java 中的 Builder 类)。下表汇总了各参数及其默认行为:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
apiKey | String | 无(必填) | Mistral AI API 密钥,用于鉴权 |
modelName | String / 枚举 | 无(必填) | 嵌入模型名,如"mistral-embed" |
baseUrl | String | https://api.mistral.ai/v1 | API 基础地址;代理或私有部署时可覆盖(见 MistralAiEmbeddingModel.java) |
timeout | Duration | 60 秒 | 单次 API 请求超时时间(见 MistralAiEmbeddingModel.java) |
maxRetries | Integer | 2 | 请求失败时的最大重试次数(见 MistralAiEmbeddingModel.java) |
logRequests | Boolean | false | 是否在日志中输出请求内容(见 MistralAiEmbeddingModel.java) |
logResponses | Boolean | false | 是否在日志中输出响应内容(见 MistralAiEmbeddingModel.java) |
logger | org.slf4j.Logger | 默认 logger | 自定义请求/响应日志记录器 |
httpClientBuilder | HttpClientBuilder | JDK 默认实现 | 定制底层 HTTP 客户端(连接池、代理等) |
customHeaders | Supplier<Map<String, String>> | 无 | 为每个请求附加自定义 HTTP 头(如透传内部租户 ID) |
一个覆盖更多参数的生产级配置示例:
EmbeddingModel embeddingModel = MistralAiEmbeddingModel.builder() .apiKey(System.getenv("MISTRAL_AI_API_KEY")) .modelName(MistralAiEmbeddingModelName.MISTRAL_EMBED) .baseUrl("https://api.mistral.ai/v1") .timeout(Duration.ofSeconds(30)) .maxRetries(3) .logRequests(true) .logResponses(false) // 嵌入向量在日志中体积较大,响应日志建议关闭 .build();注意:开启logResponses会把完整的向量数组打印到日志,导致日志急剧膨胀。集成测试 MistralAiEmbeddingModelIT.java 中就明确使用了logRequests(true)与logResponses(false)的组合,并注释说明“embeddings are huge in logs”。
结合 RAG 实现检索增强生成
Mistral AI Embedding 最典型的应用场景是 RAG(Retrieval-Augmented Generation,检索增强生成)。典型的流程是:
- Ingestion(文档摄入):用 LangChain4j 的
DocumentLoader从文件系统、URL、S3 等来源加载文档,用DocumentParser解析 text/pdf/doc/xls/ppt 等格式,切分为TextSegment; - Embedding(向量化):调用
MistralAiEmbeddingModel将每个文本段编码为 1024 维向量,连同原始文本一起写入EmbeddingStore; - Retrieval(检索):将用户问题向量化后在向量库中做相似度搜索,取 Top-K 相关片段;
- Generation(生成):把检索到的片段作为上下文交给 Chat 模型生成带依据的回答。
其中的向量化与检索环节正是本文示例所演示的能力。完整的 RAG 摄入、检索与高级检索技术,可以参考官方教程 RAG。
模型参数与进阶调优
本示例中大量参数(如超时时间、模型类型、模型参数)都由 LangChain4j 在幕后设置了合理的默认值。如果你需要显式控制这些参数——例如为 Chat 模型配置temperature、topP等采样参数,或为 HTTP 客户端设置代理——可以参考官方教程 Set Model Parameters。
以重试与超时为例,从 MistralAiEmbeddingModel.java 的构造函数可以看到,timeout与maxRetries会在构建客户端时透传给MistralAiClient,最终作用于每一次 HTTP 调用;logRequests/logResponses则直接控制客户端是否记录网络交互细节,便于联调排错。
质量验证:集成测试揭示的预期行为
仓库中的 MistralAiEmbeddingModelIT.java 是官方集成测试,直接印证了上述行为:
- 单条文本
"Embed this sentence."嵌入后,向量维度为 1024,输入 token 数为 7,输出 token 数为 0,总 token 数为 7; - 两条文本批量嵌入(
embedAll),返回 2 个 1024 维向量,token 用量为两段之和(7 + 8 = 15); - 嵌入响应的
finishReason为null(嵌入任务没有“结束原因”概念)。
这意味着你在生产代码中可以通过Response.tokenUsage()精确计量每次调用的 token 消耗,用于成本核算与限流告警;同时model.embedAll(textSegments)的批量语义也意味着可以将大量文档分片一次性发送给 Mistral AI,降低调用次数。
更多示例
如果你希望查看更多完整的集成示例(包括结合 Chat 模型、其他向量库、更复杂的 RAG 链路),可以查阅 LangChain4j 官方示例工程langchain4j-examples项目中的 Mistral AI 相关代码,那里包含了与本模块配套的可运行示例。
小结
通过langchain4j-mistral-ai模块,Java 开发者可以用寥寥几行代码接入 Mistral AI 的mistral-embed嵌入模型:统一的EmbeddingModel接口屏蔽了 HTTP 细节,DimensionAwareEmbeddingModel自动处理向量维度,maxRetries与timeout提供健壮性保障,Response<TokenUsage>让 token 计量透明可控。无论是构建语义搜索、知识库问答还是完整的 RAG 流水线,本文介绍的模式都可以直接复用。关键源码与测试均可在本仓库的 langchain4j-mistral-ai 模块中查看与验证。
【免费下载链接】langchain4jLangChain4j is an idiomatic, open-source Java library for building LLM-powered applications on the JVM. It offers a unified API over popular LLM providers and vector stores, and makes implementing tool calling (including MCP support), agents and RAG easy. It integrates seamlessly with enterprise Java frameworks like Quarkus and Spring Boot.项目地址: https://gitcode.com/GitHub_Trending/la/langchain4j
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考