ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

LangChain4j 内存向量存储 InMemoryEmbeddingStore 完全指南:原型开发、持久化与源码剖析

LangChain4j 内存向量存储 InMemoryEmbeddingStore 完全指南:原型开发、持久化与源码剖析 LangChain4j 内存向量存储 InMemoryEmbeddingStore 完全指南原型开发、持久化与源码剖析【免费下载链接】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 提供的InMemoryEmbeddingStore展开它是EmbeddingStore接口最轻量的纯内存实现适用于快速原型验证与数据量较小的场景。读完本文你将掌握如何引入依赖、完成向量的增删查、利用 JSON 序列化实现存储的持久化与恢复并通过源码理解其暴力检索、相关性打分与元数据过滤的底层机制。什么是 InMemoryEmbeddingStoreInMemoryEmbeddingStore是 LangChain4j 内置在核心库langchain4j中的一个EmbeddingStore实现位于包dev.langchain4j.store.embedding.inmemory。它的设计目标非常明确零外部依赖不需要启动任何数据库或向量索引服务开箱即用纯内存存储Embedding向量以及与之关联的TextSegment原文片段全部保存在 JVM 堆内内存内检索相似度搜索同样在内存中完成不产生任何网络 I/O可序列化整个存储可以序列化为 JSON 字符串或文件也可以从 JSON/文件反序列化恢复实现关机不丢数据的轻量持久化。从源码类注释可以看到它采用暴力遍历brute force方式在全部向量中寻找最相似的结果InMemoryEmbeddingStore.java因此当向量数量较大时检索耗时随数据量线性增长。它最典型的应用场景是快速原型fast prototyping、单元测试、演示 Demo 以及数据规模可控通常数万条以内的简单应用。引入 Maven 依赖InMemoryEmbeddingStore并不在独立的模块中而是随核心库一起发布。在pom.xml中加入以下依赖即可使用版本号以你项目实际使用的版本为准本文以仓库当前文档使用的 1.20.0 为例dependency groupIddev.langchain4j/groupId artifactIdlangchain4j/artifactId version1.20.0/version /dependency同时为了把文本真正转成向量你通常还需要一个嵌入模型实现例如仓库内的langchain4j-embeddings-all-minilm-l6-v2-q模块或者调用远程模型的 API。核心 API 一览InMemoryEmbeddingStoreEmbedded是一个泛型类泛型参数Embedded表示被嵌入的原始对象类型典型取值为TextSegment。它实现了定义在 EmbeddingStore.java 中的接口主要能力包括能力方法说明写入add(Embedding)仅存向量自动生成 UUID 作为 ID写入add(Embedding, Embedded)同时保存向量与原始内容如TextSegment批量写入addAll(ListEmbedding, ListEmbedded)批量添加id 自动生成批量写入addAll(ListString ids, ListEmbedding, ListEmbedded)指定 id 批量添加三份列表长度必须一致删除removeAll(CollectionString ids)按 id 删除删除removeAll(Filter filter)按元数据过滤器删除1.20.0 支持删除removeAll()清空全部检索search(EmbeddingSearchRequest)相似度搜索支持过滤与最低分阈值检索searchAsync(EmbeddingSearchRequest)非阻塞搜索1.20.0 新增持久化serializeToJson()/serializeToFile(String/Path)序列化为 JSON 字符串或文件恢复fromJson(String)/fromFile(String/Path)从 JSON 字符串或文件恢复工具size()/isEmpty()/merge(...)查看容量 / 合并多个存储其中merge是InMemoryEmbeddingStore特有的静态方法可以把多个存储合并为一个例如将分片索引的多个内存库合并后进行统一检索。基本使用写入与检索一个完整的增查流程大致如下先用EmbeddingModel把文本嵌入成向量写入存储检索时对查询文本做同样的嵌入再构造EmbeddingSearchRequest发起搜索。// 1. 初始化内存向量存储与嵌入模型 InMemoryEmbeddingStoreTextSegment embeddingStore new InMemoryEmbeddingStore(); EmbeddingModel embeddingModel new AllMiniLmL6V2QuantizedEmbeddingModel(); // 2. 将文档文本嵌入并写入存储 ListTextSegment segments List.of( TextSegment.from(LangChain4j 简化了 Java 中的 LLM 应用开发), TextSegment.from(InMemoryEmbeddingStore 适合快速原型) ); ListEmbedding embeddings embeddingModel.embedAll(segments).content(); embeddingStore.addAll(embeddings, segments); // 3. 检索把查询文本也嵌入构造搜索请求 Embedding queryEmbedding embeddingModel.embed(Java 的 LLM 开发库).content(); EmbeddingSearchRequest request EmbeddingSearchRequest.builder() .queryEmbedding(queryEmbedding) // 必填 .maxResults(3) // 可选默认 3 .minScore(0.5) // 可选默认 0范围 [0, 1] .build(); EmbeddingSearchResultTextSegment result embeddingStore.search(request); // 4. 遍历结果 for (EmbeddingMatchTextSegment match : result.matches()) { System.out.println(score match.score() , text match.embedded().text()); }EmbeddingSearchRequest的四个参数语义定义在 EmbeddingSearchRequest.javaqueryEmbedding作为相似度参照的查询向量必填maxResults最多返回的匹配数默认 3必须大于 0minScore最低相关性分数取值 01含端点只有分数 ≥minScore的结果才会被返回默认 0filter基于TextSegment元数据的过滤器可选默认不过滤。检索原理余弦相似度 相关性分数InMemoryEmbeddingStore.search的内部实现非常直观InMemoryEmbeddingStore.java遍历entries中所有条目先通过matchesFilter判断是否命中元数据过滤器对命中条目计算查询向量与存储向量的余弦相似度CosineSimilarity.between调用RelevanceScore.fromCosineSimilarity把余弦相似度映射为 01 范围内的相关性分数只保留分数 ≥minScore的结果借助小顶堆PriorityQueue维护 Top-K堆大小超过maxResults时淘汰分数最低者最后按分数降序返回EmbeddingMatch列表。这里值得注意两点分数不是余弦相似度本身而是经过RelevanceScore变换后的 01 分数源码见 RelevanceScore.java所以minScore的语义是相关性分数阈值存储内部使用CopyOnWriteArrayListEntryEmbedded保存条目InMemoryEmbeddingStore.java读多写少的场景下并发安全且无锁读与内存检索、快速原型的定位一致。另外1.20.0 起提供的searchAsync是一个对非阻塞 RAG 链路友好的异步版本。由于内存检索是纯 CPU 操作、不会阻塞线程它选择在调用线程上同步完成并返回已完成的CompletableFuture异常则通过failedFuture传递InMemoryEmbeddingStore.java避免了不必要的线程切换。元数据过滤FilterInMemoryEmbeddingStore支持通过Filter对TextSegment的Metadata进行检索前过滤也支持按过滤条件删除。其规则在源码中有明确约定InMemoryEmbeddingStore.java 与 matchesFilter过滤器只作用于嵌入对象为TextSegment的条目过滤条件是作用在TextSegment.metadata()上嵌入对象为null或不是TextSegment的条目在存在过滤器时一律视为不匹配既不会被检索返回也不会被删除不传过滤器时所有条目都可参与检索。// 只检索 metadata 中 userId 42 的片段 Filter filter new Filter.And( new Filter.Equal(userId, 42), new Filter.GreaterThanOrEqualTo(createdAt, 1700000000000L) ); EmbeddingSearchRequest request EmbeddingSearchRequest.builder() .queryEmbedding(queryEmbedding) .filter(filter) .build(); // 按过滤条件批量删除 embeddingStore.removeAll(filter);在添加TextSegment时给片段打上元数据即可配合使用TextSegment segment TextSegment.from(原文内容, Metadata.from(Map.of(userId, 42, createdAt, 1700000000000L)));仓库中的InMemoryEmbeddingStoreFilterRegressionTest与InMemoryEmbeddingStoreRemovalIT等测试见 langchain4j/src/test/java/dev/langchain4j/store/embedding/inmemory/覆盖了过滤与按条件删除的行为可以作为参考用例。持久化与恢复JSON 序列化内存存储最大的短板是进程退出后数据即失。InMemoryEmbeddingStore为此提供了完整的 JSON 序列化/反序列化能力文档中的示例完整覆盖了四种用法InMemoryEmbeddingStoreTextSegment embeddingStore new InMemoryEmbeddingStore(); embeddingStore.addAll(embeddings, embedded); // 1. 序列化为 JSON 字符串再从字符串恢复 String serializedStore embeddingStore.serializeToJson(); InMemoryEmbeddingStoreTextSegment deserializedStore InMemoryEmbeddingStore.fromJson(serializedStore); // 2. 序列化到文件再从文件恢复 String filePath /home/me/store.json; embeddingStore.serializeToFile(filePath); InMemoryEmbeddingStoreTextSegment restoredStore InMemoryEmbeddingStore.fromFile(filePath);几个值得注意的实现细节serializeToFile/fromFile采用流式读写内部使用BufferedOutputStream/BufferedInputStream避免把整个 JSON 文档一次性加载进内存官方注释明确建议在数据量大时优先于serializeToJson使用InMemoryEmbeddingStore.java反序列化得到的存储类型固定为InMemoryEmbeddingStoreTextSegmentJSON 内部结构由 Jackson 负责每个条目包含id、embedding.vectorfloat 数组与embedded.text/embedded.metadata三部分序列化细节见 JacksonInMemoryEmbeddingStoreJsonCodec.java序列化机制是可替换的LangChain4j 通过 SPI 提供了InMemoryEmbeddingStoreJsonCodecFactory扩展点InMemoryEmbeddingStoreJsonCodecFactory.java默认回退到 Jackson 实现Quarkus 集成等场景正是利用该扩展点做原生镜像替换。仓库中的集成测试 InMemoryEmbeddingStoreSerializedIT.java 验证了序列化 → 反序列化 → 之后仍能正确完成带过滤检索这一完整闭环说明持久化恢复后的存储行为与原始存储保持一致。典型应用场景与局限适合使用InMemoryEmbeddingStore的场景快速原型与概念验证几行代码即可跑通嵌入 → 存储 → 检索全链路单元测试与集成测试测试 RAG、工具调用等逻辑时无需依赖外部向量数据库仓库内大量*IT测试均以它为测试存储小规模离线数据例如本地文档问答、一次性数据处理数据量在数万条以内会话级/进程级缓存借助merge可灵活合并多个内存索引。需要留意的局限检索为暴力遍历时间复杂度 O(n)向量规模大时延迟明显上升数据仅存活于 JVM 堆内进程重启后必须显式序列化保存、反序列化恢复序列化产物直接保存在文件系统缺少专门的索引管理、分片与分布式能力。当数据规模增长、需要持久化数据库或分布式检索能力时可平滑迁移到 LangChain4j 提供的其他EmbeddingStore实现如 PGVector、Milvus、Qdrant、Elasticsearch 等对应文档见 docs/docs/integrations/embedding-stores/因为它们在EmbeddingStore接口层与InMemoryEmbeddingStore完全一致业务代码几乎无需改动。【免费下载链接】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),仅供参考
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表