Become a Gold Sponsor
Drizzle | 使用 pgvector 扩展进行向量相似性搜索
This guide assumes familiarity with:
npm
yarn
pnpm
bun
npm i openai
  • 您应该安装 drizzle-orm@0.31.0drizzle-kit@0.22.0 或更高版本。

要在 PostgreSQL 中使用 Drizzle ORM 实现向量相似性搜索,您可以使用 pgvector 扩展。这个扩展提供了一系列函数来处理向量并进行相似性搜索。

目前,Drizzle 并不会自动创建扩展,因此您需要手动创建。创建一个空的迁移文件并添加 SQL 查询:

npx drizzle-kit generate --custom
CREATE EXTENSION vector;

为了进行相似性搜索,您需要创建一个包含向量列的表,并在该列上创建一个 HNSWIVFFlat 索引以提高性能:

schema.ts
migration.sql
import { index, pgTable, serial, text, vector } from 'drizzle-orm/pg-core';

export const guides = pgTable(
  'guides',
  {
    id: serial('id').primaryKey(),
    title: text('title').notNull(),
    description: text('description').notNull(),
    url: text('url').notNull(),
    embedding: vector('embedding', { dimensions: 1536 }),
  },
  (table) => ({
    embeddingIndex: index('embeddingIndex').using('hnsw', table.embedding.op('vector_cosine_ops')),
  }),
);

embedding 列用于存储指南描述的向量嵌入。向量嵌入是一种对某些数据的表示。它将不同类型的数据转换为语言模型可以处理的通用格式(向量)。这使我们能够执行数学运算,例如测量两个向量之间的距离,以确定两个数据项是多么相似或不同。

在此示例中,我们将使用 OpenAI 模型生成描述的 嵌入

import OpenAI from 'openai';

const openai = new OpenAI({
  apiKey: process.env['OPENAI_API_KEY'],
});

export const generateEmbedding = async (value: string): Promise<number[]> => {
  const input = value.replaceAll('\n', ' ');

  const { data } = await openai.embeddings.create({
    model: 'text-embedding-ada-002',
    input,
  });

  return data[0].embedding;
};

要通过嵌入搜索相似的指南,您可以使用 gtsql 操作符与 cosineDistance 函数来计算 embedding 列与生成的嵌入之间的相似性:

import { cosineDistance, desc, gt, sql } from 'drizzle-orm';
import { generateEmbedding } from './embedding';
import { guides } from './schema';

const db = drizzle(...);

const findSimilarGuides = async (description: string) => {
  const embedding = await generateEmbedding(description);

  const similarity = sql<number>`1 - (${cosineDistance(guides.embedding, embedding)})`;

  const similarGuides = await db
    .select({ name: guides.title, url: guides.url, similarity })
    .from(guides)
    .where(gt(similarity, 0.5))
    .orderBy((t) => desc(t.similarity))
    .limit(4);

  return similarGuides;
};
const description = '使用 Drizzle ORM 的各种平台指南';

const similarGuides = await findSimilarGuides(description);
[
  {
    name: 'Drizzle with Turso',
    url: '/docs/tutorials/drizzle-with-turso',
    similarity: 0.8642314333984994
  },
  {
    name: 'Drizzle with Supabase Database',
    url: '/docs/tutorials/drizzle-with-supabase',
    similarity: 0.8593631126014918
  },
  {
    name: 'Drizzle with Neon Postgres',
    url: '/docs/tutorials/drizzle-with-neon',
    similarity: 0.8541051184461372
  },
  {
    name: 'Drizzle with Vercel Edge Functions',
    url: '/docs/tutorials/drizzle-with-vercel-edge-functions',
    similarity: 0.8481551084241092
  }
]