Drizzle | 使用 pgvector 扩展进行向量相似度搜索
本指南假定您熟悉
npm
yarn
pnpm
bun
npm i openai

要在 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) => [
    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 = 'Guides on using Drizzle ORM with different platforms';

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
  }
]