Langchain4J 向量模型和向量存储(9)
Langchain4J 向量模型和向量存储
向量大模型
介绍
通用文本向量模型: https://help.aliyun.com/zh/model-studio/developer-reference/text-embedding-synchronous-api?spm=a2c4g.11186623.help-menu-2400256.d_2_5_0.592672a3yMJDRq&scm=20140722.H_2712515._.OR_help-T_cn~zh-V_1
text-embedding-v3:阿里云百炼
使用通用文本向量 text-embedding-v3,维度1024,维度越多,对事务的描述越精准,信息检索的精度越高。
模型配置
使用 text-embedding-v3 依然需要添加 langchain4j-community-dashscope 依赖,我们之前已经添加过了。
-
配置向量模型
# 接入阿里百炼平台community:dashscope:embedding-model:api-key: ${ALI_BAILIAN_TOKEN}model-name: text-embedding-v3
测试文本向量化
@SpringBootTest
public class EmbeddingTest {@Resourceprivate EmbeddingModel embeddingModel;@Testpublic void testEmbeddingModel(){Response<Embedding> embed = embeddingModel.embed("你好");System.out.println("向量维度:" + embed.content().vector().length);System.out.println("向量输出:" + embed.toString());}
}
向量存储
Pinecone简介
之前我们使用的是InMemoryEmbeddingStore作为向量存储,但是不建议在生产中使用基于内存的向量存储。因此这里我们使用Pinecone作为向量数据库。
官方网站:The vector database to build knowledgeable AI | Pinecone
访问官方网站、注册、登录、获取apiKey且配置在环境变量中。默认有2GB的免费存储空间
Pinecone的使用
-
得分的含义
在向量检索场景中,当我们把查询文本转换为向量后,会在嵌入存储( EmbeddingStore )里查找与之最相似的向量(这些向量对应着文档片段等内容)。为了衡量查询向量和存储向量之间的相似程度,会使用某种相似度计算方法(例如余弦相似度等)来得出一个数值,这个数值就是得分。得分越高,表明查询向量和存储向量越相似,对应的文档片段与查询文本的相关性也就越高。
-
得分的作用
筛选结果:
通过设置 minScore 阈值,能够过滤掉那些与查询文本相关性较低的结果。在代码
里, minScore(0.8) 意味着只有得分大于等于 0.8 的结果才会被返回,低于这个阈值的结果会被
舍弃。这样可以确保返回的结果是与查询文本高度相关的,提升检索结果的质量。
控制召回率和准确率:
调整 minScore 的值可以在召回率和准确率之间进行权衡。如果把阈值设置得较低,那么更多的结果会被返回,召回率会提高,但可能会包含一些相关性不太强的结果,导致准确率下降;反之,如果把阈值设置得较高,返回的结果数量会减少,准确率会提高,但可能会遗漏一些相关的结果,使得召回率降低。在实际应用中,需要根据具体的业务需求来合理设置minScore 的值。
-
示例说明
假设我们有一个关于水果的文档集合,嵌入存储中存储了这些文档片段的向量。当我们使用 “苹果的营养价值” 作为查询文本时,向量检索会计算查询向量与存储向量的相似度得分。如果 minScore 设置为0.8,那么只有那些与 “苹果的营养价值” 相关性非常高的文档片段才会被返回,而一些只简单提及苹果但没有详细讨论其营养价值的文档片段可能由于得分低于 0.8 而不会被返回。
集成Pinecone
参考文档:Pinecone | LangChain4j
-
添加依赖
<dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-pinecone</artifactId> </dependency>
-
配置向量存储对象
@Configuration public class EmbeddingStoreConfig {@Resourceprivate EmbeddingModel embeddingModel;@Beanpublic EmbeddingStore<TextSegment> embeddingStore() {//创建向量存储EmbeddingStore<TextSegment> embeddingStore = PineconeEmbeddingStore.builder().apiKey(System.getenv("PINECONE_API_KEY")).index("xiaozhi-index")//如果指定的索引不存在,将创建一个新的索引.nameSpace("xiaozhi-namespace") //如果指定的名称空间不存在,将创建一个新的名称 空间.createIndex(PineconeServerlessIndexConfig.builder().cloud("AWS") //指定索引部署在 AWS 云服务上。.region("us-east-1") //指定索引所在的 AWS 区域为 us-east-1。.dimension(embeddingModel.dimension()) //指定索引的向量维度,该维度与 embeddedModel 生成的向量维度相同。.build()).build();return embeddingStore;} }
-
测试向量存储
@Resourceprivate EmbeddingModel embeddingModel;@Resourceprivate EmbeddingStore embeddingStore;/*** 将文本转换成向量,然后存储到pinecone中** 参考:* https://docs.langchain4j.dev/tutorials/embedding-stores*/@Testpublic void testPineconeEmbeded() {//将文本转换成向量TextSegment segment1 = TextSegment.from("我喜欢羽毛球");Embedding embedding1 = embeddingModel.embed(segment1).content();//存入向量数据库embeddingStore.add(embedding1, segment1);TextSegment segment2 = TextSegment.from("今天天气很好");Embedding embedding2 = embeddingModel.embed(segment2).content();embeddingStore.add(embedding2, segment2);}
 {//提问,并将问题转成向量数据Embedding queryEmbedding = embeddingModel.embed("你最喜欢的运动是什么?").content();//创建搜索请求对象EmbeddingSearchRequest searchRequest = EmbeddingSearchRequest.builder().queryEmbedding(queryEmbedding).maxResults(1) //匹配最相似的一条记录//.minScore(0.8).build();//根据搜索请求 searchRequest 在向量存储中进行相似度搜索EmbeddingSearchResult<TextSegment> searchResult = embeddingStore.search(searchRequest);//searchResult.matches():获取搜索结果中的匹配项列表。//.get(0):从匹配项列表中获取第一个匹配项EmbeddingMatch<TextSegment> embeddingMatch = searchResult.matches().get(0);//获取匹配项的相似度得分System.out.println(embeddingMatch.score()); // 0.8568224789886165//返回文本结果System.out.println(embeddingMatch.embedded().text());}