首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >如何判断“啥时候睡觉”和“几点休息”是同一个问题?一文搞懂向量搜索实战

如何判断“啥时候睡觉”和“几点休息”是同一个问题?一文搞懂向量搜索实战

原创
作者头像
全栈开发日记
发布2026-06-29 13:38:48
发布2026-06-29 13:38:48
1183
举报
文章被收录于专栏:全栈开发日记全栈开发日记

背景

在问答系统中判断"啥时候开始睡觉?""开始休息的时间是?"是否属于同一个问题,就不能按照简单字符串匹配去实现了,而是一个语义相似度 + 意图识别的问题。

使用Embedding,把词/句子/文档映射为多维空间中的向量,语义相近的文本在向量空间中距离更近,语义相远的距离更远,通过向量相似度度量(如余弦相似度)来实现"语义相似度"。

Embedding是什么

Embedding中文含义为向量嵌入,在国内高中就会开始学习向量相关的内容,所以其实这些你都学习过。

向量长什么样子?这里以最简单的举例,奶茶的口味主要根据茶味和甜度来控制,使用坐标系表示出来就是下图这样。

蓝色的箭头就是这杯奶茶的向量,你的口味越重长度约长,箭头的方向表示你口味偏好。

你的朋友喝奶茶的口味跟你不太一样,使用向量表示出来是下面这样的。

你和你朋友的口味相似度有多高,通过肉眼就可以分辨,这只是二维向量,在计算机中判断两句话的相似度有很多维度,主流开源的模型大多数是1024维,商用的OpenAI的text-embedding-3-small维度是1536维,Gemini Embedding维度达到了3072维,Qwen3-Embedding-8B的开源系列更是达到了4096维。

在相同训练参数(同模型、同数据、同步数)下,维度增加到某一点会提升表达力,但超过"模型容量适配维度"后收益迅速递减,甚至有害。

PostgreSQL用来干啥

PostgreSQL在保留传统关系型数据库能力的同时,通过扩展支持了“向量相似度检索”,让你可以在一张表里既存业务字段,又存向量,还能一起过滤 + 排序。

PostgreSQL 本身不支持向量计算,但是官方社区扩展了pgvector插件,这个插件支持下面这三种能力。

能力

说明

新增 vector数据类型

能直接存多维度Embedding向量

支持相似度计算

L2 距离、内积、余弦距离

支持向量索引

IVFFlat、HNSW(近似最近邻)

开始实战

安装PostgreSQL

我这里使用的是Docker Compose安装的,如果不会可以先去安装一个DockerDocker Compose

① 创建docker-compose.yml文件,写入如下内容:

代码语言:javascript
复制
version: "3.8"
​
services:
  pgvector:
    image: pgvector/pgvector:pg16
    container_name: pgvector
    # PostgreSQL 共享内存,向量索引构建时建议 ≥512M~1G
    shm_size: 1g
    environment:
      POSTGRES_PASSWORD: 123456
      POSTGRES_DB: vectordb
      PGDATA: /var/lib/postgresql/data/pgdata
    ports:
      - "5432:5432"
    volumes:
      # 数据持久化
      - ./pgdata:/var/lib/postgresql/data
      # 首次初始化时自动执行 CREATE EXTENSION vector;
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro

② 在该文件同级目录下创建pgdata文件夹和init.sql文件,init.sql文件内容如下所示:

代码语言:javascript
复制
-- 自动在 POSTGRES_DB 对应的库中安装 pgvector 扩展
-- 仅在容器【首次初始化】时执行一次
CREATE EXTENSION IF NOT EXISTS vector;
​
-- 问答对嵌入向量表
CREATE TABLE IF NOT EXISTS qa_embedding (
    id UUID PRIMARY KEY,
    question TEXT NOT NULL,
    answer TEXT NOT NULL,
    embedding vector(1024),
    create_time BIGINT,
    update_time BIGINT
);
​
-- 为embedding列创建IVFFlat索引,加速相似度查询
CREATE INDEX IF NOT EXISTS idx_qa_embedding_vector ON qa_embedding USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);

需要注意embedding字段类型应该与你使用的Embedding接口返回的维度相同,我这里用的是腾讯混元的Embedding接口返回的是1024维。

③ 命令行提示符进入当前文件所在路径,执行docker-compose up -d即可完成安装。

项目核心代码

以Spring Boot项目为例。

① 添加pom依赖

代码语言:javascript
复制
<!-- PostgreSQL 驱动 -->
<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>42.7.3</version>
</dependency>
​
<!-- JDBC -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

② 创建数据库表qa_embedding的映射类,这里代码较长,估省略。

③ 使用JDBC执行SQL,也可以使用其他ORM框架执行,我这里只是描述比较通用的方式。

代码语言:javascript
复制
SELECT id, question, answer, 1 - (embedding <=> ?::vector) AS similarity
FROM qa_embedding
WHERE (embedding <=> ?::vector) < 0.5
ORDER BY embedding <=> ?::vector;

注意:

<=>是 pgvector 的余弦距离运算符;

?::vector是 PreparedStatement 的参数占位符,将用户的话转成Embedding向量数组放在这里;

similarity是通过 1 - cosine_distance计算出的余弦相似度。

其中的0.5表示相似度高于这个值时才返回的筛选条件。

怎么转Embedding

只要提供大语言模型API的厂商都会有Embedding接口,因为大语言模型也需要依赖于Embedding。

正好我有腾讯混元的免费额度,这里展示一个腾讯混元Embedding接口返回的Embedding向量值,总共1024维,所以比较长,这里只截局部。

最终效果

实际应用小程序后

参考资料

[1] 3Blue1Brown 风格中文解说. 一杯奶茶教会你什么是向量 | 算法的数学基础01[EB/OL]. (2025)[2026-06-05].https://www.bilibili.com/video/BV1DX9EBMEec.

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • Embedding是什么
  • PostgreSQL用来干啥
  • 开始实战
    • 安装PostgreSQL
    • 项目核心代码
    • 怎么转Embedding
    • 最终效果
  • 参考资料
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档