LangChain4j 集成 Voyage 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
导读
本指南基于 LangChain4j 官方集成文档 docs/docs/integrations/embedding-models/voyage-ai.md,系统讲解如何在 JVM 项目中通过 LangChain4j 使用 Voyage AI 嵌入(Embedding)模型:从 Maven 依赖引入、VoyageAiEmbeddingModel的完整 Builder 配置,到文本嵌入、批量嵌入、多模态(文本 + 图片)融合嵌入的实际用法。读完本文,你将能够把 Voyage AI 的向量化能力无缝接入 LangChain4j 的 RAG 检索链路与向量存储体系,并理解其底层请求/响应处理与路由机制。
一、Voyage AI 集成概览
Voyage AI 是提供文本与多模态嵌入(Embedding)服务的模型提供商。LangChain4j 通过独立模块langchain4j-voyage-ai将其封装为标准的 EmbeddingModel 实现,使上层 RAG、向量检索代码完全复用 LangChain4j 统一的模型抽象,无需关心 Voyage 的 HTTP API 细节。
本模块的核心能力由官方文档与源码共同确认:
- 核心 API:
VoyageAiEmbeddingModel(实现类位于 VoyageAiEmbeddingModel.java); - 多模态支持:
voyage-multimodal-3、voyage-multimodal-3.5可将交错排列的文本与图片融合为单一向量(从模型名自动检测); - 按调用参数:支持
input_type(query/document),用于优化检索场景的向量质量; - 可观测性:支持通过
listeners(...)配置EmbeddingModelListener,接入 LangChain4j 的观测体系。
该模块依赖langchain4j-core与langchain4j-http-client,运行时默认使用 JDK 自带 HTTP 客户端(langchain4j-http-client-jdk),可参考 langchain4j-voyage-ai/pom.xml。
二、添加 Maven 依赖
在你的pom.xml中引入如下依赖:
<dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-voyage-ai</artifactId> <version>1.20.0-beta30</version> </dependency>说明:上述版本来自官方集成文档。当前仓库主分支的模块版本为
1.21.0-beta31-SNAPSHOT(见 langchain4j-voyage-ai/pom.xml),实际使用时请根据你的发布渠道选择正式发布的版本号。
三、API 与构建方式:VoyageAiEmbeddingModel
VoyageAiEmbeddingModel是DimensionAwareEmbeddingModel的实现(后者在 langchain4j-core 中提供维度感知能力),它封装了 Voyage AI 的 Embedding API,并通过链式 Builder 提供全部配置项。
最简创建方式(与集成测试 VoyageAiEmbeddingModelIT.java 中的用法一致):
import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.model.voyageai.VoyageAiEmbeddingModel; import dev.langchain4j.model.voyageai.VoyageAiEmbeddingModelName; EmbeddingModel model = VoyageAiEmbeddingModel.builder() .apiKey(System.getenv("VOYAGE_API_KEY")) // 必填:Voyage AI API Key .modelName(VoyageAiEmbeddingModelName.VOYAGE_3_LITE) .build();modelName既支持枚举VoyageAiEmbeddingModelName,也支持任意字符串(便于使用仓库枚举未收录的新模型名),见 VoyageAiEmbeddingModel.java。
Builder 配置项全解(默认值来自源码)
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
apiKey | String | 无(必填) | Voyage AI 的 API Key,用于Authorization: Bearer <apiKey>请求头 |
modelName | VoyageAiEmbeddingModelName/String | 无(必填) | 模型名,见下文模型清单 |
baseUrl | String | https://api.voyageai.com/v1/ | API 基地址,见 VoyageAiClient.java |
timeout | Duration | 60 秒 | HTTP 连接/读取超时;源码中同时将连接超时兜底为 15 秒 |
maxRetries | Integer | 2 | 对瞬时错误的最大重试次数,通过withRetryMappingExceptions实现 |
inputType | String | null | query/document/ null,见下文专门说明 |
truncation | Boolean | true | 超长文本是否截断以适配上下文长度;false 时超长会直接报错 |
encodingFormat | String | null | 向量编码格式:null(浮点数列表)或base64(压缩为 Base64) |
maxSegmentsPerBatch | Integer | 128 | 单次批量请求最多包含的文本段数量,超出自动分批 |
multimodal | Boolean | 从模型名自动推断 | 强制开启多模态路由(命名含multimodal时自动为 true) |
logRequests/logResponses | Boolean | false | 调试日志:打印请求/响应体 |
logger | org.slf4j.Logger | 默认 Logger | 自定义请求/响应日志所用 Logger |
httpClientBuilder | HttpClientBuilder | SPI 加载 | 自定义 HTTP 客户端(超时、代理等) |
customHeaders | Map/Supplier<Map> | 无 | 每次请求附加的自定义 Header;Supplier 形式每次请求前调用,适合动态令牌(如 OAuth2 刷新) |
listeners | List<EmbeddingModelListener> | 空列表 | 嵌入模型监听器,用于观测与追踪 |
以上默认值均可从 VoyageAiEmbeddingModel.java 的构造逻辑核实。
内置模型清单与向量维度
VoyageAiEmbeddingModelName.java 定义了仓库已知的模型与维度,供knownDimension()做维度校验:
| 枚举值 | 模型名 | 输出维度 |
|---|---|---|
VOYAGE_3 | voyage-3 | 1024 |
VOYAGE_3_LITE | voyage-3-lite | 512 |
VOYAGE_3_LARGE | voyage-3-large | 1024 |
VOYAGE_FINANCE_2 | voyage-finance-2 | 1024 |
VOYAGE_MULTILINGUAL_2 | voyage-multilingual-2 | 1024 |
VOYAGE_LAW_2 | voyage-law-2 | 1024 |
VOYAGE_CODE_2 | voyage-code-2 | 1536 |
VOYAGE_CODE_3 | voyage-code-3 | 1024 |
四、文本嵌入:单条与批量
单条文本嵌入
import dev.langchain4j.model.output.Response; import dev.langchain4j.data.embedding.Embedding; Response<Embedding> response = model.embed("Hello World"); int dimension = response.content().dimension(); // 与模型维度一致批量文本段嵌入
embedAll接收TextSegment列表,返回值与输入顺序一一对应:
import dev.langchain4j.data.segment.TextSegment; import java.util.List; import static java.util.Arrays.asList; TextSegment segment1 = TextSegment.from("hello"); TextSegment segment2 = TextSegment.from("hi"); Response<List<Embedding>> response = model.embedAll(asList(segment1, segment2));从源码 doEmbed 可以看到内部处理逻辑:
- 分批:按
maxSegmentsPerBatch(默认 128)将输入切分为多个批次,避免单请求过大; - 并发串行请求:逐批调用 Voyage API,最后合并全部向量结果;
- 响应排序:按响应的
index字段排序,保证输出与输入顺序一致(见 EmbeddingResponse.java); - Token 统计:汇总每批的
total_tokens,以TokenUsage形式随响应返回。
集成测试 VoyageAiEmbeddingModelIT.java 验证了 97 个文本段(超过默认批大小 128 的一半场景用maxSegmentsPerBatch(96)强制分批)依然能全部正确返回;测试还断言了"hello"与"hi"两个段的余弦相似度大于 0.8(使用CosineSimilarity),可用于验证语义相关性的基本合理性。
提示:集成测试需要环境变量
VOYAGE_API_KEY,且测试类标注了@EnabledIfEnvironmentVariable(named = "VOYAGE_API_KEY", matches = ".+"),未配置时自动跳过。
五、input_type:检索场景的优化参数
Voyage AI 支持通过input_type参数对嵌入做检索场景优化,LangChain4j 将其映射为EmbeddingInputType枚举(QUERY/DOCUMENT),映射逻辑见 VoyageAiEmbeddingModel.java:
| 取值 | 语义(来自源码 Javadoc) |
|---|---|
query | 用于搜索或检索的查询文本。Voyage AI 会在嵌入前为查询场景前置优化提示(prepend a prompt) |
document | 用于希望被检索到的文档/内容。Voyage AI 会为文档场景前置优化提示 |
| null(默认) | 直接编码原始文本,不附加任何额外提示 |
两种设置方式
方式一:全局配置(构建时固定)
VoyageAiEmbeddingModel model = VoyageAiEmbeddingModel.builder() .apiKey(System.getenv("VOYAGE_API_KEY")) .modelName(VoyageAiEmbeddingModelName.VOYAGE_3_LITE) .inputType("query") // 所有请求统一使用 query 模式 .build();方式二:按请求配置(per-call)
LangChain4j 的嵌入请求支持按调用传入参数。VoyageAiEmbeddingModel.supportedParameters()声明支持EmbeddingRequestParameters.INPUT_TYPE(见 VoyageAiEmbeddingModel.java),这也是官方文档强调的“Per-call parameters”能力:
import dev.langchain4j.model.embedding.request.EmbeddingInputType; import dev.langchain4j.model.embedding.request.EmbeddingRequest; model.embed(EmbeddingRequest.builder() .input("LangChain4j 是什么?") .inputType(EmbeddingInputType.QUERY) // 本次请求按查询处理 .build());请求级参数优先于模型级配置——源码中getOrDefault(toVoyageInputType(request.inputType()), inputType)正是“先取请求参数、缺省时回退到 Builder 配置”的实现。
典型用法:RAG 系统中,入库文档用DOCUMENT,检索查询用QUERY,两者在各自优化空间内编码,可显著提升召回质量。
六、多模态嵌入:文本 + 图片融合为单一向量
官方文档明确指出:voyage-multimodal-3与voyage-multimodal-3.5可将文本和图片嵌入到共享向量空间,且交错排列的文本 + 图片会被融合为一个嵌入向量。图片输入通过EmbeddingRequest中的ImageContent(URL 或 Base64)提供。
自动检测与路由机制
从源码 isMultimodalModel 可见:模型名包含子串multimodal即自动判定为多模态,例如voyage-multimodal-3.5。此时:
supportedContentTypes()返回TEXT+IMAGE(纯文本模型仅返回TEXT);- 内部请求路由到
/multimodalembeddings端点;否则走/embeddings端点(见 VoyageAiClient.java)。
路由测试 VoyageAiMultimodalRoutingTest.java 验证了以下关键行为:
voyage-multimodal-3/voyage-multimodal-3.5自动启用图文支持;voyage-3纯文本模型请求图片会快速失败(抛出UnsupportedFeatureException,消息含IMAGE);voyage-multilingual-2不会被误判为多模态(避免multilingual与multimodal混淆);- 显式设置
.multimodal(true)可覆盖自动检测(例如使用自定义代理模型名时); VideoContent输入同样会快速失败(消息含VIDEO)。
图文混合嵌入示例
import dev.langchain4j.data.message.TextContent; import dev.langchain4j.data.message.ImageContent; Response<Embedding> response = model.embed(EmbeddingRequest.builder() .input( TextContent.from("a photo of a cat"), // 文本块 ImageContent.from("https://example.com/cat.png")) // 图片 URL .inputType(EmbeddingInputType.QUERY) .build());图片输入的两种形式
图片使用ImageContent.from(...)创建,常用重载(见 ImageContent.java):
1. URL 形式:
ImageContent image = ImageContent.from("https://example.com/cat.png");底层序列化为image_url内容块,请求体会包含"image_url"与 URL。
2. Base64 形式:
ImageContent image = ImageContent.from("aGVsbG8=", "image/png"); // Base64 数据 + MIME 类型源码 toContentBlock 会将其拼装为data:<mimeType>;base64,<data>的 Data URL 发送,MIME 缺省时默认为image/png。路由测试确认请求体形如data:image/png;base64,aGVsbG8=。
注意:图片内容必须提供 URL 或 Base64 数据二者之一,否则抛出
UnsupportedFeatureException(消息为 "ImageContent must have either a URL or base64 data")。
多模态请求的底层结构
多模态请求体由 MultimodalEmbeddingRequest.java 定义:每个输入包含一个有序的内容块列表(text/image_url/image_base64三种类型),这些内容块被融合为单个嵌入向量。响应侧仍复用标准EmbeddingResponse,可从中取回向量、模型名与 Token 用量。
七、响应结构:向量、Token 用量与 Base64 解码
Response<Embedding>/Response<List<Embedding>>中除向量本身外,还包含:
tokenUsage():Voyage 返回的total_tokens(注意集成测试中的备注:Voyage 有时会返回totalTokens=0,属正常现象);outputTokenCount为 null(嵌入无输出 token);finishReason():嵌入请求为 null;metadata().modelName():实际响应模型名。
encodingFormat("base64") 的底层解码
当设置encodingFormat("base64")时,Voyage 会以小端(little-endian)浮点字节的 Base64 字符串返回向量。响应解析器 EmbeddingResponse.java 负责透明解码:
VoyageAiEmbeddingModel model = VoyageAiEmbeddingModel.builder() .apiKey(System.getenv("VOYAGE_API_KEY")) .modelName(VoyageAiEmbeddingModelName.VOYAGE_3_LITE) .encodingFormat("base64") // 服务端压缩返回,减少传输体积 .build();对使用者而言,response.content().vector()拿到的始终是float[]形式,无需关心底层是否 Base64 编码——解码细节已被封装。
八、监听器与观测(Listeners)
官方文档强调可通过VoyageAiEmbeddingModel.builder().listeners(...)配置监听器。EmbeddingModelListener是 LangChain4j 观测体系的一部分,可在嵌入请求发起前后、成功/失败时获得回调,用于日志、指标与链路追踪。
import dev.langchain4j.model.embedding.listener.EmbeddingModelListener; EmbeddingModelListener listener = new EmbeddingModelListener() { @Override public void onRequest(EmbeddingModelRequestContext context) { System.out.println("请求模型: " + context.request().modelName()); } // 其余回调按需覆写 }; VoyageAiEmbeddingModel model = VoyageAiEmbeddingModel.builder() .apiKey(System.getenv("VOYAGE_API_KEY")) .modelName("voyage-multimodal-3.5") .listeners(List.of(listener)) .build();公共集成测试 common/VoyageAiEmbeddingModelIT.java 继承AbstractEmbeddingModelIT,对监听器场景做了完整覆盖(包括使用错误 API Key"banana"且maxRetries(0)构造失败模型的监听器回调验证)。
九、错误处理与调试
- 瞬时错误重试:默认
maxRetries = 2,由withRetryMappingExceptions统一处理(源码 VoyageAiEmbeddingModel.java); - 快速失败:对不支持的内容类型(如图片喂给纯文本模型、视频内容)在本地立即抛出
UnsupportedFeatureException,避免无效的网络请求; - 请求/响应日志:
logRequests(true)打印请求体;logResponses(true)打印响应体——注意向量体积巨大,集成测试中特别注释"embeddings are huge in logs",生产环境建议关闭响应日志或谨慎使用; - 自定义 HTTP 客户端:通过
httpClientBuilder(...)注入自定义实现(如代理、连接池配置),模块默认通过 SPI 加载HttpClientBuilder,并在 pom 中提供langchain4j-http-client-jdk作为运行时实现。
十、与 LangChain4j RAG / 向量存储的衔接
VoyageAiEmbeddingModel实现了统一的 EmbeddingModel 接口,因此可以无缝替换 LangChain4j RAG 流程中的任意嵌入模型位置。典型接入方式:
- 使用
TextSegment将文档切分为文本段; - 调用
embedAll(...)批量向量化; - 将向量写入 LangChain4j 支持的向量存储(如 langchain4j-pgvector、langchain4j-milvus 等模块);
- 检索时用
embed(EmbeddingRequest.builder().input(query).inputType(EmbeddingInputType.QUERY).build())生成查询向量,配合DOCUMENT入库向量做相似度检索。
关于请求/响应 API 与多模态用法的更多通用说明,可参考官方教程 Embedding Model 中的 embedding-model 章节。
十一、参考资源(仓库内)
- 官方集成文档:voyage-ai.md
- 核心实现:VoyageAiEmbeddingModel.java
- 模型与维度定义:VoyageAiEmbeddingModelName.java
- HTTP 客户端封装:VoyageAiClient.java
- 多模态请求模型:MultimodalEmbeddingRequest.java
- 实时集成测试(需
VOYAGE_API_KEY):VoyageAiEmbeddingModelIT.java - 多模态路由单元测试:VoyageAiMultimodalRoutingTest.java
- 模块依赖定义:langchain4j-voyage-ai/pom.xml
【免费下载链接】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),仅供参考