当前位置: 首页 > news >正文

使用 PostgreSQL + pgvector 实现 RAG 向量存储与语义检索(Java 实战)

使用 PostgreSQL + pgvector 实现 RAG 向量存储与语义检索(Java 实战)

在 RAG(Retrieval-Augmented Generation)系统中,向量存储与相似度检索是最核心的一环。
本文将使用PostgreSQL + pgvector,结合Java + 阿里百炼 Embedding 模型,实现一个完整、可运行的向量存储与语义检索示例。

本文不仅关注“能跑”,更重点解释为什么这么设计以及RAG 中最容易踩的坑


一、pgvector 是什么?

pgvector是 PostgreSQL 的一个扩展插件,为 PostgreSQL 提供了专门的vector 类型,用于存储高维向量,并支持:

  • 余弦距离(cosine distance)
  • 欧氏距离(L2)
  • 内积(inner product)
  • 向量索引(ivfflat / hnsw)

这使得 PostgreSQL 可以直接作为向量数据库使用,非常适合中小规模 RAG 场景。


二、安装 PostgreSQL 与 pgvector

安装过程不再赘述。

👉 可参考 CSDN 博主进击的女IT的文章:
https://blog.csdn.net/weixin_63908159/article/details/156075242


三、建表与索引设计(非常重要)

1️⃣ 建表语句

CREATETABLEdocument(id BIGSERIALPRIMARYKEY,contentTEXTNOTNULL,embedding vector(1024),create_timeTIMESTAMPDEFAULTnow());

⚠️注意
vector(1024)必须与 Embedding 模型输出的向量维度一致。如果模型输出是 1536 维,这里必须改成vector(1536),否则插入时会报错:expected xxx dimensions

2️⃣ 向量索引(否则数据一多会非常慢)

CREATEINDEXidx_document_embeddingONdocumentUSINGivfflat(embedding vector_cosine_ops)WITH(lists=100);

查询前建议设置:

SETivfflat.probes=10;

四、Java 实体类设计

pgvector在 Java 中无需特殊类型映射,直接使用String承载即可。

@DatapublicclassDocument{privateLongid;privateStringcontent;/** * pgvector 字段 * 使用 String 承载,例如:[0.12,0.34,...] */privateStringembedding;privateLocalDateTimecreateTime;}

五、Embedding 模型配置(阿里百炼)

配置文件 (application.yml):

alibaba:dashscope:key:sk-xxxurl:https://dashscope.aliyuncs.com/compatible-mode/v1/embeddingsmodel:text-embedding-v4

配置类:

@Configuration@ConfigurationProperties(prefix="alibaba.dashscope")@DatapublicclassAlibabaDashscopeConfig{privateStringkey;privateStringurl;privateStringmodel;}

六、文本向量化服务(EmbeddingService)

功能:文本 → 向量 (List<Float>)

@Service@Slf4jpublicclassEmbeddingService{@AutowiredprivateAlibabaDashscopeConfigconfig;publicList<Float>getEmbedding(Stringtext){if(StrUtil.isBlank(text)){returnList.of();}Map<String,Object>body=Map.of("model",config.getModel(),"input",List.of(text));HttpResponseresponse=HttpRequest.post(config.getUrl()).header("Authorization","Bearer "+config.getKey()).header("Content-Type","application/json").body(JSONUtil.toJsonStr(body)).timeout(30000).execute();JSONObjectjson=JSONUtil.parseObj(response.body());JSONArrayembedding=json.getJSONArray("data").getJSONObject(0).getJSONArray("embedding");returnembedding.toList(Float.class);}}

七、向量存储与相似度查询

Mapper

@MapperpublicinterfaceDocumentMapperextendsBaseMapper<Document>{/** * 向量相似度搜索(余弦距离) */@Select(""" SELECT id, content FROM document ORDER BY embedding <=> #{embedding}::vector LIMIT #{limit} """)List<Document>searchByEmbedding(@Param("embedding")Stringembedding,@Param("limit")intlimit);@Insert(""" INSERT INTO document (content, embedding) VALUES (#{content}, #{embedding}::vector) """)voidinsertDocument(@Param("content")Stringcontent,@Param("embedding")Stringembedding);}

Service

@Service@RequiredArgsConstructorpublicclassDocumentService{privatefinalDocumentMappermapper;privatefinalEmbeddingServiceembeddingService;publicvoidaddDocument(Stringcontent){List<Float>vector=embeddingService.getEmbedding(content);StringpgVector=vector.stream().map(String::valueOf).collect(Collectors.joining(",","[","]"));mapper.insertDocument(content,pgVector);}publicList<Document>search(Stringquery,inttopK){List<Float>vector=embeddingService.getEmbedding(query);if(vector.isEmpty()){returnList.of();}StringpgVector=vector.stream().map(String::valueOf).collect(Collectors.joining(",","[","]"));returnmapper.searchByEmbedding(pgVector,topK);}}

八、Controller 接口

@RestController@RequestMapping("/document")@RequiredArgsConstructorpublicclassDocumentController{privatefinalDocumentServiceservice;@GetMapping("/add")publicvoidadd(@RequestParamStringcontent){service.addDocument(content);}@GetMapping("/search")publicList<Document>search(@RequestParamStringquery,@RequestParam(defaultValue="5")inttopK){returnservice.search(query,topK);}}

九、为什么“最近流行什么”查询不到结果?

这是语义检索中最容易被误解的一点:

向量检索 ≠ 关键词匹配

向量检索判断的是语义是否在同一语义空间

示例:

文本语义中心
Java 是一门流行的后端开发语言编程 / 后端
最近流行什么趋势 / 热点

👉 两者在语义空间中的距离很远,因此检索不到是正常且正确的行为。

正确做法:

  1. Query Rewrite(查询重写)
  2. 补充领域上下文

例如:

最近流行的后端开发语言有哪些?


十、总结

  • pgvector可以让 PostgreSQL 直接作为向量数据库使用。
  • 向量检索本质是语义相似度计算
  • RAG 的效果高度依赖于:
    • 文档内容的表达方式
    • Query 是否足够具体
    • 相似度阈值与 TopK 的设计

📌项目完整源码地址(Gitee)
https://gitee.com/tfxing12138/rag-demo.git

http://www.jsqmd.com/news/321701/

相关文章:

  • 闲置分某乐京东e卡回收方式推荐
  • 2026学术英语快速提分机构推荐:精准提分效果显著的优质培训机构全解析
  • 第 5 篇:责任链模式 (Chain of Responsibility) —— 协议栈的流水线
  • 互联网大厂Java面试:从Spring Boot到微服务的技术场景解读
  • 使用递归的穷举搜索
  • 2026厦门装修公司介绍,业主实测靠谱清单,装修避坑必看
  • 如何写出一个完整的测试用例?
  • The 2021 ICPC Asia East Continent Final Contest (EC-Final 2021)
  • 深度测评9个AI论文平台,MBA高效写作必备!
  • Postman 怎么测接口?新手教程
  • 计算机毕业设计之springboot交友APP的设计与实现
  • Modbus RTU(主站) 485通讯主站程序(端口0作主站) 1.西门子224xp或200...
  • 基于微信小程序的个性化漫画阅读推荐系统的设计与实现
  • 计算机毕业设计之jsp考试报名及成绩查询系统
  • 义乌雷硕包装制品有限公司 联系方式: 供应商联系与风险提示参考
  • 微信立减金回收全攻略,普通人也能轻松上手,闲置不浪费
  • 优化SEO效果的长尾关键词策略与应用技巧
  • 计算机毕业设计之springcloud基于微服务的中小企业实习生管理系统设计与开发
  • 义乌雷硕包装制品有限公司 联系方式:核实官方信息与沟通准备建议
  • 基于微信小程序的大学生就业管理系统设计与实现
  • 计算机毕业设计之jsp基于SSM的社区志愿者服务管理系统
  • CH32系列MCU外设使用相关注意事项
  • Pytest实践:使用Pytest进行API测试
  • 2026厦门装修公司口碑排行TOP10|海滨家装避坑指南,选对不踩雷
  • 使用Docker容器化部署微服务,解决环境配置难题
  • 爆火Browser-Use实战:让AI替你操作浏览器,爬虫/自动化填表一行代码搞定
  • 温州AI巨头光景极欧:揭秘行业巨头的崛起之路
  • 闭环伺服步进电机(磁编码器)全套方案 步进电机 闭环控制器 42步进电机 包含说明文档,AD工...
  • 2026表面缺陷检测系统公司技术创新与行业应用分析
  • 服务端性能测试:行业流行性能监控工具介绍