基于Langchain4j的Pgvector EmbeddingStore复用已有向量数据问题咨询
Langchain4j RAG避免重复存储数据的解决方案
核心思路
要避免重复存储,关键是让对话服务直接复用文档服务已存入PostgreSQL(pgvector)的向量数据,无需手动重新存储;同时支持像Python中chain.run那样直接传入文档列表调用AI。
步骤1:配置PgVectorEmbeddingStore复用已有数据库表
将对话服务中的InMemoryEmbeddingStore替换为PgVectorEmbeddingStore,指定已有的向量表结构,避免创建新表:
@Bean public EmbeddingStore<TextSegment> embeddingStore(DataSource dataSource) { return PgVectorEmbeddingStore.builder() .dataSource(dataSource) // 注入和文档服务相同的数据源 .tableName("your_existing_vector_table") // 替换为文档服务创建的向量表名 .idColumnName("id") // 表中的主键列名 .vectorColumnName("embedding") // 存储向量的列名 .contentColumnName("content") // 存储文本片段的列名 .metadataColumnName("metadata") // 若有元数据列,按需配置(无则可省略) .vectorDimension(1536) // 需与文档服务生成向量的维度一致(如Titan Embeddings的维度) .build(); }
步骤2:移除重复存储的业务逻辑
删除原代码中手动将查询结果存入EmbeddingStore的步骤,让AiAgent通过配置好的ContentRetriever自动从PostgreSQL检索数据:
原重复存储代码:
List<String> documentTexts = getDocumentTextsFromUserQuestion(promptDto); List<TextSegment> textSegments = getTextSegments(documentTexts); embeddingStore.addAll(embedComponent.getEmbeddingsFromTextSegments(textSegments), textSegments); // 此步骤删除 return new PromptDTO(aiAgent.answer(documentTexts, promptDto.getText()));
修改后代码:
// 直接让AiAgent自动检索已有数据生成回答 return new PromptDTO(aiAgent.answer(promptDto.getText()));
步骤3:实现手动传入文档调用AI(类似Python的chain.run)
如果需要像Python中那样手动传入已查询到的文档列表,可通过定义AiAgent接口的自定义方法实现:
1. 定义AiAgent接口
public interface ErekyAiAgent { // 自动检索数据库数据的方法 String answer(String question); // 手动传入文档的方法 String answerWithDocuments(List<String> documents, String question); }
2. 业务逻辑中调用手动方法
List<String> documentTexts = getDocumentTextsFromUserQuestion(promptDto); // 直接传入文档列表和问题,无需存入EmbeddingStore return new PromptDTO(aiAgent.answerWithDocuments(documentTexts, promptDto.getText()));
Langchain4j会自动将传入的documents作为上下文注入到AI的Prompt中,生成基于该上下文的回答。
注意事项
- 确保对话服务与文档服务使用同一个数据库连接配置,否则对话服务无法访问已存储的向量数据。
- 验证
PgVectorEmbeddingStore的表结构配置(列名、向量维度)与文档服务创建的表完全一致,否则会导致检索失败或创建新表。 - 若使用元数据过滤,需在
ContentRetriever中配置对应的过滤条件,确保检索到的是目标文档。
内容的提问来源于stack exchange,提问作者Caos Develop
相关产品推荐
相关产品推荐

