news 2026/9/15 16:37:23

LangChain4j 集成 Jina Embedding 模型实战指南:文本/多模态嵌入、query/passage 非对称检索与监听器配置

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LangChain4j 集成 Jina Embedding 模型实战指南:文本/多模态嵌入、query/passage 非对称检索与监听器配置

LangChain4j 集成 Jina Embedding 模型实战指南:文本/多模态嵌入、query/passage 非对称检索与监听器配置

【免费下载链接】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 的langchain4j-jina集成模块为 JVM 开发者提供了访问 Jina Embeddings API 的统一入口,通过JinaEmbeddingModel一个类即可完成文本嵌入、多模态(文本+图片)嵌入、面向检索的非对称 query/passage 编码以及嵌入请求监听等能力。本文基于仓库中的官方集成文档与源码实现,完整讲解依赖引入、Builder 参数、多模态与输入类型(task)的自动检测机制、RAG 场景接入方式,并给出可直接复制运行的 Java 示例。

模块概览:langchain4j-jina

langchain4j-jina是 LangChain4j 官方提供的一个独立 Maven 模块,位于仓库 langchain4j-jina 目录下。其核心公开 API 只有一个类:JinaEmbeddingModel(位于 JinaEmbeddingModel.java),它实现了 LangChain4j 核心模块中的EmbeddingModel接口(dev.langchain4j.model.embedding.EmbeddingModel),因此可以无缝用于 RAG 流水线、EmbeddingStore写入与检索等场景。

从模块的 pom.xml 可以看到,它仅依赖langchain4j-corelangchain4j-http-client(运行时默认携带langchain4j-http-client-jdk作为 HTTP 客户端实现),模块轻量、无外部服务端依赖,只有调用 Jina API 时需要网络与 API Key。

引入 Maven 依赖

在项目的pom.xml中添加如下依赖即可开始使用:

<dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-jina</artifactId> <version>1.20.0-beta30</version> </dependency>

说明:当前仓库快照版本为1.21.0-beta31-SNAPSHOT(见 langchain4j-jina/pom.xml),正式发布版以 Maven Central 上最新的稳定版本为准。由于该模块依赖langchain4j-core,建议通过 LangChain4j 官方 BOM(langchain4j-bom)统一管理版本,避免核心库与集成模块版本不一致。

构建 JinaEmbeddingModel:Builder 全参数解析

JinaEmbeddingModel通过流式 Builder 构建(源码见 JinaEmbeddingModel.java),最小配置只需要apiKeymodelName

import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.model.jina.JinaEmbeddingModel; EmbeddingModel model = JinaEmbeddingModel.builder() .apiKey(System.getenv("JINA_API_KEY")) .modelName("jina-embeddings-v3") .build();

Builder 支持的全部配置项及其默认值如下表(默认值均来自源码构造函数):

配置项类型默认值说明
apiKeyString无(必填)Jina API Key,可通过环境变量注入
modelNameString无(必填)模型名称,如jina-embeddings-v3jina-embeddings-v4jina-clip-v2
baseUrlStringhttps://api.jina.ai/Jina API 服务地址,一般无需修改(见源码DEFAULT_BASE_URL
timeoutDuration60 秒HTTP 请求超时时间
maxRetriesInteger2失败自动重试次数(配合RetryUtils.withRetryMappingExceptions实现)
lateChunkingBooleanfalse是否启用 Jina 的 late chunking 特性(见下文)
logRequestsBooleanfalse是否记录请求日志
logResponsesBooleanfalse是否记录响应日志(嵌入向量数据量大,测试代码中特意建议关闭)
loggerorg.slf4j.Logger默认 Logger自定义请求/响应日志的 Logger
httpClientBuilderHttpClientBuilder默认自定义底层 HTTP 客户端(超时、代理等精细控制)
listenersList<EmbeddingModelListener>空列表嵌入模型监听器(见"监听器"一节)

其中lateChunking是 Jina 的特色参数。仓库测试 JinaEmbeddingModelIT.java 验证了开启lateChunking(true)后,对同一批文本片段产生的向量与关闭时显著不同(余弦相似度数值、token 统计均发生变化),说明该参数会实质影响嵌入结果,适合对整篇长文档先整体编码、再按块检索的场景。

文本嵌入:embed 与 embedAll

单条文本嵌入

import dev.langchain4j.model.output.Response; import dev.langchain4j.data.embedding.Embedding; Response<Embedding> response = model.embed("hello"); Embedding embedding = response.content(); System.out.println("维度: " + embedding.dimension()); // jina-embeddings-v3 为 1024 System.out.println("Token 使用: " + response.tokenUsage()); // totalTokenCount = 4

批量文本嵌入

import dev.langchain4j.data.segment.TextSegment; import java.util.List; Response<List<Embedding>> response = model.embedAll(List.of( TextSegment.from("hello"), TextSegment.from("hi"), TextSegment.from("there")));

从 JinaEmbeddingModelIT.java 的断言可以确认以下实现事实:

  • jina-embeddings-v3返回的向量维度为1024
  • 每个输入项对应一个嵌入,批量输入返回结果顺序与输入一致;
  • 语义相近的文本("hello" / "hi")余弦相似度大于 0.85(关闭 late chunking 时)或大于 0.9(开启时);
  • TokenUsageoutputTokenCount恒为 0,totalTokenCount等于输入 token 数(源码 JinaEmbeddingModel.java 将 Jina 响应的usage.promptTokensusage.totalTokens映射为 LangChain4j 的输入 token 数)。

底层请求/响应结构

文本嵌入走JinaEmbeddingRequest(见 JinaEmbeddingRequest.java),请求体包含四个字段:modeltask(可选,见下文输入类型)、lateChunkinginput(字符串数组)。响应JinaEmbeddingResponse则包含modeldata(嵌入列表)与usagepromptTokens/totalTokens),由 JinaEmbeddingModel.doEmbed 统一映射为 LangChain4j 的EmbeddingResponse

多模态嵌入:文本与图片

langchain4j-jina支持多模态嵌入,但仅限特定模型。源码中的模型能力自动检测逻辑如下(见 JinaEmbeddingModel.java):

private static boolean isMultimodalModel(String modelName) { return modelName != null && (modelName.contains("clip") || modelName.contains("embeddings-v4")); }

即模型名包含clip(如jina-clip-v2)或embeddings-v4(如jina-embeddings-v4)时,supportedContentTypes()返回TEXTIMAGE两种内容类型;其余模型(如jina-embeddings-v3)仅支持文本。

多模态请求通过JinaMultimodalEmbeddingRequest发送(见 JinaMultimodalEmbeddingRequest.java),每个输入项只能是单个文本或单张图片JinaMultimodalInput.text(...)/JinaMultimodalInput.image(...))。

重要限制:Jina 不融合交错图文

与部分多模态模型不同,Jina 每个输入项只嵌入一种模态,不会把一段文本和一张图片融合进同一个向量。源码 toMultimodalInput 明确做了两处校验并抛出UnsupportedFeatureException

  1. 一个输入项中出现多张图片 → "Jina embeds one image per input"(每输入仅一张图片);
  2. 同一输入项中同时出现文本和图片 → "Jina embeds a single text or image per input; interleaved text+image is not supported"(不支持交错图文)。

因此,向EmbeddingRequest传输入时,每个输入项只能是单独的TextContent单独的ImageContent。图片支持两种形式:

  • URLImageContent.from(url),直接传图片 URL;
  • Base64:源码会将 base64 数据编码为data:<mimeType>;base64,<data>形式的 data URI 发送(mimeType 默认image/png)。

使用方式示例(通过EmbeddingRequest显式构造多模态输入):

import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.model.embedding.request.EmbeddingRequest; import dev.langchain4j.model.embedding.request.EmbeddingInput; import dev.langchain4j.data.message.ImageContent; import dev.langchain4j.data.message.TextContent; import dev.langchain4j.model.output.Response; import dev.langchain4j.data.embedding.Embedding; EmbeddingModel multimodalModel = JinaEmbeddingModel.builder() .apiKey(System.getenv("JINA_API_KEY")) .modelName("jina-clip-v2") .build(); // 每个输入只放一个 TextContent 或一个 ImageContent EmbeddingRequest request = EmbeddingRequest.builder() .input(TextContent.from("A red car on the highway")) .input(ImageContent.from("https://example.com/car.jpg")) // URL 形式 .input(ImageContent.from(base64Bytes, "image/jpeg")) // base64 形式 .build(); Response<Embedding> response = multimodalModel.embed(request);

关于 LangChain4j 的请求/响应 API 与多模态用法的完整说明,可参考仓库教程文档 rag.md。

输入类型(Input Type):query 与 document 非对称编码

这是 Jina 提升检索质量的关键能力。jina-embeddings-v3jina-embeddings-v4jina-embeddings-v5这几个模型会把"搜索查询"和"被检索的文档"用不同的方式编码(即非对称编码,canonical RAG 中的 query vs passage),通常能显著改善检索效果。

能力自动检测

源码 isTaskAwareModel 按模型名自动判断是否支持输入类型参数:

private static boolean isTaskAwareModel(String modelName) { return modelName != null && (modelName.contains("embeddings-v3") || modelName.contains("embeddings-v4") || modelName.contains("embeddings-v5")); }
  • 支持的模型:jina-embeddings-v3 / v4 / v5supportedParameters()返回INPUT_TYPE
  • 不支持的模型(如jina-clip-v2)会直接拒绝该参数而不是静默忽略——这是supportedParameters()声明机制的作用,调用方可以在发送前通过能力探测避免请求失败。

枚举值与 Jina task 的映射

LangChain4j 核心定义了统一的EmbeddingInputType枚举(见 EmbeddingInputType.java,自 1.18.0 引入,标注为@Experimental),仅包含两个值:QUERY(搜索查询)与DOCUMENT(待索引检索的文档/段落)。JinaEmbeddingModel通过 toJinaTask 将其映射为 Jina API 的task参数:

EmbeddingInputTypeJina task 值用途
QUERYretrieval.query编码查询侧文本
DOCUMENTretrieval.passage编码文档/段落侧文本
未设置(null)省略 task 字段由 Jina 应用其默认行为

在 EmbeddingRequest 中按调用设置

import dev.langchain4j.model.embedding.request.EmbeddingInputType; // 文档侧:写入 EmbeddingStore 时标记为 DOCUMENT EmbeddingRequest docRequest = EmbeddingRequest.builder() .input("LangChain4j is a Java library for LLM-powered applications.") .inputType(EmbeddingInputType.DOCUMENT) .build(); Response<Embedding> docResponse = model.embed(docRequest); // 查询侧:检索时标记为 QUERY EmbeddingRequest queryRequest = EmbeddingRequest.builder() .input("Java LLM library") .inputType(EmbeddingInputType.QUERY) .build(); Response<Embedding> queryResponse = model.embed(queryRequest);

在 RAG 检索器中设置

如果使用 LangChain4j 的EmbeddingStoreContentRetriever做 RAG 检索,可以通过embeddingInputType(...)直接配置(该配置项定义于 EmbeddingStoreContentRetriever.java):

import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever; import dev.langchain4j.model.embedding.request.EmbeddingInputType; EmbeddingStoreContentRetriever retriever = EmbeddingStoreContentRetriever.builder() .embeddingStore(embeddingStore) .embeddingModel(model) .embeddingInputType(EmbeddingInputType.QUERY) // 检索查询按 QUERY 编码 .maxResults(5) .build();

测试验证

仓库中的公共嵌入测试基类AbstractEmbeddingModelIT包含should_embed_query_and_document_differently用例,它通过 JinaV3EmbeddingModelIT.java 在jina-embeddings-v3上实际运行,验证同一文本作为 QUERY 与作为 DOCUMENT 编码会得到不同向量。同时该测试类明确标注了两个能力边界:

  • supportsImageInput() = falsejina-embeddings-v3纯文本,多模态需用jina-clip-v2/jina-embeddings-v4
  • supportsDimensionsParameter() = falseJinaEmbeddingModel目前尚未映射 Jina 的 Matryoshkadimensions参数(即暂不支持在请求中自定义输出维度)。

监听器(Listeners)

JinaEmbeddingModel支持通过 Builder 配置EmbeddingModelListener,用于观测嵌入请求的发起、成功与失败事件:

import dev.langchain4j.model.embedding.listener.EmbeddingModelListener; import java.util.List; EmbeddingModel model = JinaEmbeddingModel.builder() .apiKey(System.getenv("JINA_API_KEY")) .modelName("jina-embeddings-v3") .listeners(List.of(myListener)) .build();

从 JinaV3EmbeddingModelIT.java 可以看到监听器在成功请求与失败请求(使用无效 Key、maxRetries(0)关闭重试)两种路径下都会被触发,可用于指标采集、日志记录或链路追踪。监听器列表在构造时经copy(builder.listeners)保存,模型实例构建后不可变更。

完整可运行示例

下面把以上能力整合为一个完整的、可直接运行的 Java 示例(需要环境变量JINA_API_KEY):

import dev.langchain4j.data.embedding.Embedding; import dev.langchain4j.data.segment.TextSegment; import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.model.embedding.request.EmbeddingInputType; import dev.langchain4j.model.embedding.request.EmbeddingRequest; import dev.langchain4j.model.jina.JinaEmbeddingModel; import dev.langchain4j.model.output.Response; import java.util.List; public class JinaEmbeddingExample { public static void main(String[] args) { // 1) 文本嵌入模型(jina-embeddings-v3:text-only、支持 input type) EmbeddingModel textModel = JinaEmbeddingModel.builder() .apiKey(System.getenv("JINA_API_KEY")) .modelName("jina-embeddings-v3") .maxRetries(2) .timeout(java.time.Duration.ofSeconds(60)) .logRequests(true) .logResponses(false) // 嵌入向量很大,避免日志爆炸 .build(); // 2) 批量文本嵌入(写入 EmbeddingStore 的文档侧) Response<List<Embedding>> docResponse = textModel.embed( EmbeddingRequest.builder() .inputs(List.of( TextSegment.from("LangChain4j makes RAG easy in Java."), TextSegment.from("Jina embeddings support query/passage asymmetry."))) .inputType(EmbeddingInputType.DOCUMENT) .build()); System.out.println("文档嵌入数量: " + docResponse.content().size()); System.out.println("向量维度: " + docResponse.content().get(0).dimension()); // 3) 查询侧嵌入(检索时使用 QUERY 类型) Response<Embedding> queryResponse = textModel.embed( EmbeddingRequest.builder() .input("Java RAG framework") .inputType(EmbeddingInputType.QUERY) .build()); System.out.println("查询向量维度: " + queryResponse.content().dimension()); System.out.println("Token 使用: " + queryResponse.tokenUsage()); // 4) 多模态嵌入(jina-clip-v2 / jina-embeddings-v4:支持文本与图片) EmbeddingModel multimodalModel = JinaEmbeddingModel.builder() .apiKey(System.getenv("JINA_API_KEY")) .modelName("jina-clip-v2") .build(); Response<Embedding> imageResponse = multimodalModel.embed( EmbeddingRequest.builder() .input(dev.langchain4j.data.message.ImageContent.from("https://example.com/car.jpg")) .build()); System.out.println("图片嵌入维度: " + imageResponse.content().dimension()); } }

使用注意事项与边界

综合文档与源码,使用JinaEmbeddingModel时有几点需要特别留意:

  1. 多模态不融合交错图文:每个输入项只能是一个TextContent或一个ImageContent,混用会抛UnsupportedFeatureException;每输入最多一张图片;
  2. 输入类型的能力边界:只有jina-embeddings-v3/v4/v5接受INPUT_TYPE参数,jina-clip-v2等模型会拒绝该参数,建议依赖supportedParameters()能力探测而不是硬编码;
  3. 维度参数暂未映射:Jina 的 Matryoshkadimensions参数尚未在JinaEmbeddingModel中实现(见 JinaV3EmbeddingModelIT.java),因此输出维度由模型决定(如jina-embeddings-v3为 1024);
  4. Token 统计口径outputTokenCount恒为 0,总 token 数以 Jina 返回的 prompt/total tokens 为准;集成测试中还注释了 Jina 侧输入 token 统计疑似存在偏差的观察(见 JinaEmbeddingModelIT.java);
  5. 自定义 HTTP 客户端:如需代理、TLS 等精细控制,可通过httpClientBuilder(...)注入自定义的HttpClientBuilder

参考与深入阅读

  • 集成文档原文:jina.md
  • 核心实现:JinaEmbeddingModel.java
  • 请求/响应 DTO:internal/api
  • HTTP 客户端封装:JinaClient.java
  • 集成测试:JinaEmbeddingModelIT.java、JinaV3EmbeddingModelIT.java
  • RAG 教程(请求/响应 API 与多模态用法):rag.md
  • 核心枚举与请求模型:EmbeddingInputType.java、EmbeddingRequest.java

【免费下载链接】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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 16:36:52

VeraCrypt 加密卷恢复指南:卷头修复与救援盘实操全流程

VeraCrypt 加密卷恢复指南&#xff1a;卷头修复与救援盘实操全流程 【免费下载链接】VeraCrypt Disk encryption with strong security based on TrueCrypt 项目地址: https://gitcode.com/GitHub_Trending/ve/VeraCrypt VeraCrypt 是一款开源磁盘加密工具&#xff0c;当…

作者头像 李华
网站建设 2026/9/15 16:36:23

避坑指南:选专注微商推广的网站要注意什么?

避坑指南:选专注微商推广的网站要注意什么? 改个需求建站公司拖一周,这行当里谁没被坑过?尤其是做微商推广的,页面得改得勤,图得换得快,稍微卡壳,客户就跑了。很多老板找外包,光看报价低,没搞懂底层逻辑,结果上线后想加个表单、换个后台,对方要么加钱要么拖延。选【专注微商推广的网站】,核心不在多花哨,而在…

作者头像 李华
网站建设 2026/9/15 16:36:07

企业微信H5授权登录:获取code到用户身份验证的完整实战指南

在企业微信H5应用开发里&#xff0c;“获取code”这四个字&#xff0c;卡住了不知道多少新入坑的开发者。代码写完了、页面能开了、接口也通了&#xff0c;结果一看回调URL上的参数&#xff0c;code要么没拿到&#xff0c;要么拿到了换不出用户信息&#xff0c;最后只能对着文档…

作者头像 李华
网站建设 2026/9/15 16:34:08

Postman无法定位程序输入点KERNEL32.dll?一文讲清原因与解决步骤

Postman 升级后弹窗报“无法定位程序输入点 SetDefaultDllDirectories于动态链接库KERNEL32.dll 上”&#xff0c;这段时间碰上的人不少。我群里好几个做接口测试的朋友都被卡在这&#xff0c;第一反应都是“KERNEL32.dll 坏了&#xff1f;是不是得去下载一个补上”。我每次都拦…

作者头像 李华
网站建设 2026/9/15 16:33:21

从零手写前馈神经网络:Numpy实现XOR异或分类全解析

XOR异或问题&#xff0c;几乎是我见过最适合用来理解前馈神经网络和反向传播的小实验了。网上教程一抓一大把&#xff0c;但真到自己动手写代码时&#xff0c;很多人会卡在同一个地方&#xff1a;单层感知机学不了XOR&#xff0c;换成两层网络又不知道权重怎么初始化、激活函数…

作者头像 李华