初识PostgreSQL
pgsql相比mysql而言,更加的标准和强大。对sql标准的支持度很高,在mysql中偷懒的写法在这里会报错;其次是pgsql的功能丰富,有很多扩展是按需加载的。像是ai需要使用的向量数据库,有现成的pgvecotr扩展可以直接使用就。
认识pgsql
PGvector 是一个为 PostgreSQL 设计的开源扩展,支持存储和检索机器学习生成的嵌入向量。它提供多种功能,让用户既能进行精确最近邻搜索,也能进行近似最近邻搜索。该扩展旨在与 PostgreSQL 的其他特性(包括索引和查询)无缝协作。
集成springboot
在项目中添加 PgVectorStore 启动器依赖:
1 2 3 4 5 6
| <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-vector-store-pgvector</artifactId> <version>2.0.0-M7</version> <scope>compile</scope> </dependency>
|
配置相应的yml文件:
1 2 3 4 5 6 7 8 9
| spring: ai: vectorstore: pgvector: index-type: hnsw distance-type: COSINE_DISTANCE dimensions: 1024 initialize-schema: true remove-existing-vector-store-table: false
|
这段配置告诉 Spring AI 使用 pgvector 作为向量数据库,建 HNSW 索引、用余弦距离、向量维度 1024,启动时自动建表但不删除旧数据。
同时还要添加数据库依赖和springai的依赖:
1 2 3 4 5 6 7 8 9 10
| <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-model-openai</artifactId> <version>2.0.0-M7</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency>
|
然后配置ai和datasource
1 2 3 4 5 6 7 8 9 10 11 12
| spring: datasource: driver-class-name: org.postgresql.Driver url: jdbc:postgresql://localhost:5432/interview_guide username: postgres password: 123456 ai: openai: base-url: https://dashscope.aliyuncs.com/compatible-mode/v1 api-key: ${AI_BAILIAN_API_KEY} embedding: model: text-embedding-v3
|
配置好后,启动springboot程序,去数据中就可以找到vector_store这张表。
将知识向量化并存储
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| private static final int MAX_BATCH_SIZE = 10; @Transactional public void vectorizeAndStore(Long knowledgeBaseId, String content) { log.info("开始向量化知识库: kbId={}, contentLength={}", knowledgeBaseId, content.length()); try { deleteByKnowledgeBaseId(knowledgeBaseId); List<Document> chunks = TokenTextSplitter.builder().build().apply( List.of(new Document(content)) ); log.info("文本分块完成: {} 个chunks", chunks.size()); chunks.forEach(chunk -> chunk.getMetadata().put("kb_id", knowledgeBaseId.toString())); int totalChunks = chunks.size(); int batchCount = (totalChunks + MAX_BATCH_SIZE - 1) / MAX_BATCH_SIZE; log.info("开始分批向量化: 总共 {} 个chunks,分 {} 批处理,每批最多 {} 个", totalChunks, batchCount, MAX_BATCH_SIZE); for (int i = 0; i < batchCount; i++) { int start = i * MAX_BATCH_SIZE; int end = Math.min(start + MAX_BATCH_SIZE, totalChunks); List<Document> batch = chunks.subList(start, end); log.debug("处理第 {}/{} 批: chunks {}-{}", i + 1, batchCount, start + 1, end); vectorStore.add(batch); } log.info("知识库向量化完成: kbId={}, chunks={}, batches={}", knowledgeBaseId, totalChunks, batchCount); } catch (Exception e) { log.error("向量化知识库失败: kbId={}, error={}", knowledgeBaseId, e.getMessage(), e); throw new BusinessException(ErrorCode.KNOWLEDGE_BASE_VECTORIZATION_FAILED, "向量化知识库失败: " + e.getMessage()); } }
|
使用junit执行后,就可以在表vector_store中看到向量化之后的数据了。
基于知识库相似度搜索
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @Test public void query(){ try { SearchRequest.Builder builder = SearchRequest.builder() .query("向量") .topK(Math.max(10, 1));
builder.similarityThreshold(0.6);
List<Document> results = vectorStore.similaritySearch(builder.build());
List<Document> limitedResults = results.stream() .limit(10) .collect(Collectors.toList());
for (Document limitedResult : limitedResults) { System.out.println(limitedResult); }
} catch (Exception e) { e.printStackTrace(); } }
|
参考
https://springdoc.tech/spring-ai/api/vectordbs/pgvector/