深入浅出 RAG:万物皆可向量化 (Embedding) 与 Spring AI + pgvector 实战
文章目录一、 引言计算机如何“理解”人类语言1.1 从传统搜索到语义搜索的进化1.2 什么是向量化 (Embedding)万物皆可坐标化二、 核心原理解析如何在茫茫人海中找到那个“它”2.1 距离的度量余弦相似度 (Cosine)2.2 经典概念什么是 Top-K 召回三、 为什么选择 PostgreSQL pgvector3.1 关系型数据库的复兴3.2 pgvector 简介及核心优势3.3 扒开底层看 SQLpgvector 究竟怎么存和查四、 Spring AI 代码实战打通 Embeding 与 pgvector 检索4.1 环境准备4.2 Embedding 模型的调用 (把文字变数组)4.3 数据入库与相似度检索 (Top-K)五、 总结给大模型装上真正的“外接硬盘”从语义检索原理到 Spring Boot 工程落地在 RAG检索增强生成系列的前两篇文章中我们聊了为什么需要 RAG也详细讲解了如何通过 Chunking 策略把长文档“切碎”。今天我们要啃下一块不可或缺的硬骨头这些切碎的文本系统到底是怎么理解并检索出来的这其中的核心魔法就是向量化Embedding与向量检索。本文将带你从底层原理出发结合业界当红炸子鸡PostgreSQL pgvector在 Spring AI 语境下完成一次完美的“语义搜索”实战。一、 引言计算机如何“理解”人类语言1.1 从传统搜索到语义搜索的进化传统的搜索如 Elasticsearch 早期的纯文本匹配或 MySQL 的LIKE是基于关键字的。你搜“苹果”它只会返回包含“苹果”这两个字的内容。如果你搜“研发 iPhone 的公司”传统搜索可能会傻眼因为字面上毫无重合。为了让计算机真正“理解”语义而不是机械地比对字符Embedding 技术诞生了。1.2 什么是向量化 (Embedding)万物皆可坐标化简单来说Embedding 就是把人类的文字词语、句子、甚至图像翻译成计算机能懂的一长串数字数组。这串数字在数学上就叫作“向量”。我们可以把向量在这个多维空间里想象成一个具体的“坐标”。语义相近的词比如“高兴”和“开心”它们在空间中的坐标离得非常近。语义无关的词比如“高兴”和“水杯”它们在空间中的坐标离得很远。这就实现了极其降维打击的能力我们不再匹配字面而是匹配“意思”。二、 核心原理解析如何在茫茫人海中找到那个“它”当所有切碎的文档块和用户的“问题”都被转换成高维空间里的“坐标点”后检索的过程就变成了纯粹的几何题。2.1 距离的度量余弦相似度 (Cosine)在几十上百维的空间里我们怎么判断两个点离得近不近最常用的数学工具是余弦相似度Cosine Similarity。它不去量两个点之间的绝对直线距离而是看这两个点连线所在的“夹角”。夹角越小趋近于0度余弦值越接近 1代表在语义方向上极其相似。夹角越大代表语义方向偏离毫无关联。2.2 经典概念什么是 Top-K 召回这就是我们在 RAG 架构图中经常看到的词。假设你的知识库被切分成了 100 万个文档块得到了 100 万个向量。当用户问了一个问题转换为 1 个向量系统的任务就是在空间里算出和这个问题夹角最小余弦相似度最高的前 K 个文档块。这挑选出来的前 K 个最相关的段落就叫做Top-K 召回。它们将被作为 Prompt 的参考资料喂给大模型。三、 为什么选择 PostgreSQL pgvector理解了原理我们要用什么“数据库”来存这些坐标并且能飞快地算出余弦相似度呢3.1 关系型数据库的复兴早几年独立向量数据库如 Pinecone、Milvus大行其道。但随着技术发展大家发现专门维护一个只有向量的数据库运维成本太高了。业务系统里原有的关系型数据怎么办于是最强大的开源关系型数据库 PostgreSQL 站了出来。3.2 pgvector 简介及核心优势pgvector是 PG 的一个开源扩展插件让 PG 原生支持了向量数据类型以及各种向量相似度计算余弦、欧氏距离、内积等。统一技术栈你可以把业务数据如用户的年龄、订单号和向量数据存放在同一个库甚至同一张表里。无缝 Metadata 过滤结合我们上一篇讲的元数据在 SQL 里加一句WHERE department HR就能直接缩小向量计算的范围性能无敌。3.3 扒开底层看 SQLpgvector 究竟怎么存和查为了让你不仅知其然还知其所以然。在接入框架之前我们先看看原生的 PostgreSQL (安装了 pgvector 后) 是怎么写 SQL 的1. 创建带有向量字段的表CREATEEXTENSIONIFNOTEXISTSvector;CREATETABLEdocument_chunks(id bigserialPRIMARYKEY,contenttext,-- 存文本内容metadata jsonb,-- 存元数据 (如部门、时间等)embedding vector(1536)-- 存 1536 维的向量坐标);2. 插入向量数据-- 实际开发中[0.1, 0.2...] 这串数组是大模型 API 算出来后返回给你的INSERTINTOdocument_chunks(content,metadata,embedding)VALUES(苹果不仅仅是水果...,{department: HR},[0.11, 0.22, 0.33...]);3. 核心余弦相似度检索 (Top-K)-- 在 pgvector 中 操作符就代表计算“余弦距离 / 余弦相似度”-- ORDER BY 距离 ASC就是找出“夹角最小、最相似”的数据SELECTcontent,metadataFROMdocument_chunksWHEREmetadata-departmentHR-- 绝赞的业务 Metadata 过滤ORDERBYembedding[0.14, 0.55, 0.43...]-- 这串数字是你“问题”的向量LIMIT4;-- 这就是大名鼎鼎的 Top-K (K4)看到这里是不是有一种豁然开朗的感觉所谓高大上的向量数据库在 SQL 层面其实就是多了一个排序。四、 Spring AI 代码实战打通 Embeding 与 pgvector 检索让我们回到熟悉的 Spring Boot 工程中看看 Spring AI 是如何把上述原理优雅封装的。4.1 环境准备在pom.xml中引入 Spring AI 核心包以及 pgvector 启动器以 PostgreSQL 为例dependencies!-- 其他 Spring Boot 依赖... --!-- Spring AI pgvector store 启动器 --dependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-pgvector-store-spring-boot-starter/artifactId/dependency/dependencies配置application.yml连接到装了 pgvector 插件的 PG 数据库spring:datasource:url:jdbc:postgresql://localhost:5432/rag_dbusername:myuserpassword:mypasswordai:vectorstore:pgvector:index-type:HNSWdistance-type:COSINE_DISTANCE# 指定使用余弦相似度dimensions:1536# 根据你使用的 Embedding 模型维度决定4.2 Embedding 模型的调用 (把文字变数组)在 Spring AI 中负责处理向量化的接口是EmbeddingModel。它可以无缝对接 OpenAI、通义千问、Ollama 等各家大厂的 Embedding API。importorg.springframework.ai.embedding.EmbeddingModel;importorg.springframework.ai.embedding.EmbeddingResponse;importjava.util.List;RestControllerpublicclassEmbeddingController{privatefinalEmbeddingModelembeddingModel;publicEmbeddingController(EmbeddingModelembeddingModel){this.embeddingModelembeddingModel;}GetMapping(/embed)publicListDoubleembedMyText(){// 调用底层大厂模型一键将文字转为 Float/Double 数组returnthis.embeddingModel.embed(苹果不仅仅是水果还是一家科技公司。);}}4.3 数据入库与相似度检索 (Top-K)在实际开发中我们不需要手动去算余弦夹角Spring AI 的VectorStore接口直接帮我们办妥了一切。配合上篇讲过的 Chunkingimportorg.springframework.ai.document.Document;importorg.springframework.ai.vectorstore.VectorStore;importorg.springframework.ai.vectorstore.SearchRequest;ServicepublicclassRagService{privatefinalVectorStorevectorStore;// 这里由于引入了 Starter底层实现已经是 PgVectorStorepublicRagService(VectorStorevectorStore){this.vectorStorevectorStore;}// 1. 存入经过 Chunking 处理的文档块publicvoidingestData(ListDocumentchunks){// 底层会自动调用 EmbeddingModel 将 content 变成向量并以原生 SQL 方式存入 PostgreSQLvectorStore.add(chunks);}// 2. 根据用户问题进行 Top-K 召回检索publicListDocumentsearchTopK(StringuserQuestion){// SearchRequest 就是在做余弦相似度计算returnvectorStore.similaritySearch(SearchRequest.query(userQuestion).withTopK(4)// 我们只要夹角最小(最相似)的前 4 个段落);}}五、 总结今天我们拔掉了 RAG 中最硬核的钉子我们明白了计算机是通过向量 (Embedding)和余弦相似度 (Cosine Similarity)来真正理解语义并“大海捞针”的。我们学习了Top-K 召回的概念本质。结合Spring AI与极具性价比的PostgreSQL (pgvector)我们仅仅用了几行代码就搭建起了一个工业级的向量知识检索底层。