在上一篇文章中,我们了解了什么是 LangChain4j 以及如何使用:
- 与法律硕士进行讨论,实施
ChatLanguageModel和ChatMemory - 在记忆中保留聊天记录,以便回忆起之前与一位法律硕士讨论的背景情况
本博文将介绍如何
- 根据文本示例创建向量嵌入
- 将向量嵌入存储在 Elasticsearch 嵌入存储中
- 搜索类似载体
创建嵌入
要创建嵌入式,我们需要定义一个EmbeddingModel 。例如,我们可以使用上一篇文章中使用过的相同的 mistral 模型。它和奥拉马一起跑:
模型能够从文本中生成向量。在这里,我们可以检查模型生成的维数:
要从文本中生成向量,我们可以使用
或者,如果我们还想提供元数据,以便对文本、价格、发布日期等内容进行筛选,我们可以使用Metadata.from().NET。例如,我们在这里添加游戏名称作为元数据字段:
如果您想运行这段代码,请查看Step5EmbedddingsTest.java类。
添加 Elasticsearch 来存储向量
LangChain4j 提供内存嵌入存储。这对运行简单测试非常有用:
但是,这显然不能用于更大的数据集,因为该数据存储将所有内容都存储在内存中,而我们的服务器上没有无限的内存。因此,我们可以将嵌入式数据存储到 Elasticsearch 中,根据定义,Elasticsearch 是"elastic" ,可以随着数据的扩展而扩展。为此,让我们在项目中添加 Elasticsearch:
正如你所注意到的,我们还在项目中添加了 Elasticsearch TestContainers 模块,这样我们就可以从测试中启动 Elasticsearch 实例:
要将 Elasticsearch 用作嵌入式存储,"," ,就必须从 LangChain4j 内存数据存储切换到 Elasticsearch 数据存储:
这将在 Elasticsearch 中以default 索引的形式存储向量。您还可以将索引名称改为更有意义的名称:
如果您想运行此代码,请查看Step6ElasticsearchEmbedddingsTest.java类。
搜索类似载体
要搜索相似向量,我们首先需要使用之前使用过的相同模型,将问题转换为向量表示。我们已经做到了,所以再做一次并不难。请注意,在这种情况下我们不需要元数据:
我们可以用问题的这种表示法建立一个搜索请求,并要求嵌入式存储空间找出最前面的向量:
现在,我们可以遍历结果并打印一些信息,如来自元数据的游戏名称和得分:
正如我们所预料的那样,"Out Run" 作为第一击:

如果您想运行这段代码,请查看Step7SearchForVectorsTest.java类。
幕后花絮
Elasticsearch 嵌入存储的默认配置是在后台使用近似 kNN 查询。
但这可以通过向嵌入存储区提供默认配置 (ElasticsearchConfigurationKnn) 以外的另一种配置 (ElasticsearchConfigurationScript) 来改变:
ElasticsearchConfigurationScriptscript_score执行程序使用cosineSimilarity 函数 在后台运行 查询 。
基本上,打电话时
现在呼叫
在这种情况下,结果并不会因为"order" 而发生变化,只是分数会有所调整,因为cosineSimilarity 调用并不使用任何近似值,而是计算每个匹配向量的余弦值:
如果您想运行这段代码,请查看Step7SearchForVectorsTest.java类。
结论
我们已经介绍了如何从文本中轻松生成嵌入,以及如何使用两种不同的方法在 Elasticsearch 中存储和搜索近邻:
- 使用
ElasticsearchConfigurationKnn默认选项进行近似和快速knn查询 - 使用
ElasticsearchConfigurationScript选项进行精确但较慢的script_score查询
下一步将根据我们在这里学到的知识,构建一个完整的 RAG 应用程序。




