PROD欧洲主权BaaS平台打开仪表板 →

原生人工智能 · 10 最小读取值

教程:具有 Postgres 和 pgvector 的 RAG 管道

Affane Daylami · Fondateur · 2026年4月13日

返回博客

在 Postgres 上构建 RAG 管道通常需要自己组装几个部分:文本切片器、嵌入调用、pgvector 表、相似性查询。这就是经典的LangChain + PGVectorchain。在 Aurabase 上,该管道已存在于服务器端:两个调用 ragIngest() 和 rag() 替换它,同时依赖标准 PostgreSQL 和 pgvector,无需添加专有向量库。

该英文文本是根据法文原文自动生成的,尚未经过审查。
该页面已自动翻译。英文版具有权威性。

The native RAG is part of thenative AI integrated into the Aurabasebackend, alongside NL2SQL: not a third-party service to be assembled on top of a general base. Prerequisites to follow this tutorial: an existing Aurabase project, a configured LLM provider (OpenAI or Google Gemini for embeddings, one of the three native providers for generation), and a project API key.

要点
  • Aurabase RAG 管道包含两个调用:ragIngest() 用于索引文档,rag() 用于查询并生成响应。分块、嵌入和向量搜索在服务器端进行管理。
  • 在底层,它是标准的 PostgreSQL 和 pgvector:一个 embeddings 表,每个维度类(768、1536、3072)有一个向量列,每个类有一个部分 HNSW 索引。
  • 分块使用真正的分词器 (tiktoken o200k),具有可配置的重叠和大型文档的防爆防护装置。
  • 检索到的内容在注入提示之前会被中和:尝试转义其标签以欺骗系统指令的文档会被明确地化解。
  • 只有 OpenAI 和 Gemini 在 Aurabase 端生成嵌入。 Anthropic/Claude 没有公共嵌入 API,它仍然保留用于生成最终响应。
#
概念

RAG 管道的工作原理

该管道分五个阶段进行。摄取后,文本被分割,每个块被批量矢量化然后存储。查询时,与余弦相似度存储的块进行比较,依次对问题进行向量化,并将最接近的片段注入到发送到生成模型的提示中。

分块(tiktoken)→嵌入(批量)→pg向量存储(HNSW)→相似性搜索→增强生成

在生产中很重要的架构细节:在对嵌入或生成提供程序的网络调用期间不保留 Postgres 连接。 DB 事务在外部调用之前关闭,并在外部调用之后重新打开,以免因第三方网络延迟而阻塞共享 PgBouncer 后端。

#
步骤1

创建项目

与典型的自托管 pgvector 不同,您不需要运行 CREATE EXTENSION vector 或自己为此管道创建表。创建项目时会自动配置项目的 embeddings 架构及其向量列和 HNSW 索引。

terminalbash
# Aurabase 帐户 + CLI
npm i -g @aurabase/cli
aura login

# 创建项目并将其链接到此文件夹
aura projects create mon-assistant --engine postgres
aura link --project-id <uuid-du-projet>

# 检索链接项目的 API 密钥
aura projects api-keys

嵌入提供程序在项目端配置一次(Studio→IA→供应商)。正是这个提供程序决定了向量的有效维度,因此决定了 embeddings表上使用的列。

#
步骤2

使用 ragIngest() 索引您的文档

一次调用就足以索引文档:文本被分成块,每个块被向量化,然后存储在请求的命名空间中。拆分使用真正的分词器(tiktoken,编码 o200k_base),而不是简单的按空格拆分,这在没有空格的文本(如某些亚洲语言)上保持正确。

app/api/ingest/route.tstypescript
import { aura } from '@/lib/aurabase'

export async function POST(req: Request) {
  const { content, metadata } = await req.json()

  const { data, error } = await aura.ai.ragIngest({
    namespace: 'docs-produit',
    content,
    metadata,
  })

  if (error) return Response.json({ error }, { status: 400 })
  return Response.json(data) // { id,块 }
}

在原始 HTTP 中,等效路由是 POST /v1/ai/{project_id}/rag/ingest,由项目的 API 密钥进行身份验证。

terminalbash
curl -X POST https://<votre-gateway>/v1/ai/<project_id>/rag/ingest \
  -H "apikey: <votre-cle-api>" \
  -H "Content-Type: application/json" \
  -d '{
    "namespace": "docs-produit",
    "content": "Le texte complet de votre document ici...",
    "metadata": { "source": "guide-utilisateur.pdf" }
  }'

默认情况下,摄取是幂等的:自动派生文档标识符(内容的 SHA-256 哈希值,或 metadata.document_id 如果您提供)。重新摄取相同的内容会替换其现有的块,而不是复制它们,从而使定期同步作业可以安全地重播。

#
步骤3

实际落在 Postgres 中的是什么

这里没有专有魔法:接收向量的表是一个普通的 Postgres 表,每个维度类有一个 vector 列,每列有一个部分 HNSW 索引(仅在填充它的行上有效)。这是它的真实定义,经过简化:

项目平台图(简化)sql
create table embeddings (
  id               uuid primary key default gen_random_uuid(),
  project_id       text not null,
  namespace        text not null,
  content          text not null,
  embedding_768    vector(768),
  embedding_1536   vector(1536),
  embedding_3072   vector(3072),
  embedding_model  text,
  dims             int,
  metadata         jsonb default '{}'::jsonb,
  created_at       timestamptz not null default now()
);

-- 按维度类别划分的部分 HNSW 索引
create index idx_embeddings_vec_1536 on embeddings
  using hnsw (embedding_1536 vector_cosine_ops)
  where embedding_1536 is not null;

-- 超过 2000 维,HNSW 不支持向量类型:
-- 为 3072 类投入 halfvec
create index idx_embeddings_vec_3072 on embeddings
  using hnsw ((embedding_3072::halfvec(3072)) halfvec_cosine_ops)
  where embedding_3072 is not null;

每次搜索都会将向量与余弦距离运算符 (<=>) 进行比较,余弦距离运算符是索引的 vector_cosine_ops 和 halfvec_cosine_ops 运算符类的目标运算符。有关 HNSW 与 IVFFlat 的召回/延迟权衡的详细信息,请参阅 专门用于 HNSW 索引的文章。对于嵌入维度本身的选择,请参阅 比较 768 vs 1536 vs 3072。

#
步骤4

使用 rag() 查询并生成响应

在查询方面,rag() 将问题的矢量化、命名空间中的相似性搜索、增强提示的构建以及对生成模型的调用链接到客户端的单个网络往返中。

app/api/ask/route.tstypescript
import { aura } from '@/lib/aurabase'

export async function POST(req: Request) {
  const { question } = await req.json()

  const { data, error } = await aura.ai.rag({
    question,
    namespace: 'docs-produit',
  })

  if (error) return Response.json({ error }, { status: 400 })
  return Response.json(data)
}

响应携带生成的响应及其来源,以及实际使用的提供者:

回应(摘录)json
{
  "data": {
    "answer": "D'après la documentation, ...",
    "sources": [
      { "id": "...", "content": "...", "similarity": 0.87 }
    ],
    "model": "claude-3-5-sonnet",
    "tokens": 412,
    "provider": "anthropic",
    "fallback_used": false
  }
}

检索到的内容永远不会原始注入到系统提示符中。这是不可靠的数据(用户上传、索引页面):包含例如结束部分标记和后跟错误指令的文档在组装之前被中和,其尖括号被括号替换,文本被保留但结构被消除。

在另一个模型下索引的语料库

如果 rag() 没有找到任何内容,即使您的命名空间不为空,响应也会带有明确的警告,而不是误导性的沉默:您的语料库可能在另一个模型或另一个嵌入维度下建立了索引。通过 POST /v1/ai/{project_id}/rag/{namespace}/reindex重新索引它。

#
比较

来自 LangChain 和手工制作的 pgvector:发生了什么变化

如果您已经使用 LangChain 在 PostgreSQL 上构建了 RAG 聊天机器人,则每个手动块都有一个服务器端管理的等效项,无需更改底层数据库。

分解文本RecursiveCharacterTextSplitter 自己设置ragIngest():集成tiktoken分块,默认512个token/64个重叠
嵌入手动调用OpenAIEmbeddings,批量限制管理自动批量、内置瞬态重试
矢量存储pgvector表+HNSW索引自行创建和迁移每个项目配置的架构和索引
搜索+提示PGVector.similarity_search() 然后手动组装提示rag():一次调用即可搜索和增强生成
恢复的内容按照提示注入装配前自动中和结构标签

您是否正在使用这种手动组装迁移基于 Supabase 构建的现有项目?后端其余部分(架构、RLS 策略、SDK)的迁移逻辑包含在我们的 Supabase 到 Aurabase 迁移指南中。

#
生产

投入生产前需要注意的设置和限制

三个设置直接影响成本和延迟,全部在 aura-ai服务代码中进行验证。默认情况下,瞬态嵌入调用(网络故障、提供程序错误 429)的尝试次数为 3 次,基本退避时间为 100 毫秒。默认情况下,大型文档嵌入到限制为 2048 个块的子批次中,以尊重供应商的 API 上限,而不会在单个大型文档上失败。护栏(默认情况下为 10,000 个块,可配置)明确拒绝摄取会产生异常数量块的文档。

在搜索方面,HNSW 候选列表的大小会自动调整为 max(64, top_k × 4):您请求的结果越多,索引探索的候选者就越多,以保留召回率。如果您的语料库具有特定的配置文件,则仍然可以通过环境变量获得固定值。

不同模型的向量空间永远不会相互比较:每次搜索仍然仅限于当前的嵌入模型,并且更改模型需要显式重新索引,而不是静默切换,这会破坏结果的一致性。

#
诚实

需要注意的当前限制

嵌入维度必须属于三个受支持的类别之一:768、1536 或 3072。返回另一个维度的提供程序会被拒绝并出现显式错误,并且不会被截断或静默转换。

嵌入生成只能通过 OpenAI 或 Google Gemini 在三个本地提供商中使用:Anthropic/Claude 不公开公共嵌入 API,因此它仅用于在此管道中生成最终响应,从不用于矢量化。

JavaScript SDK 尚未公开 rag() 调用上的 top_k 和 threshold 覆盖:它们仍然可以通过直接 HTTP 访问,分别限制为 [1, 50] 和 [0, 1],但不能像现在一样从 aura.ai.rag() 访问。默认的相似度阈值(0.3)是故意允许的;将其缩小到密集的语料库,以避免提示中出现不相关的来源。

#
走得更远

为了走得更远

RAG 涵盖有关非结构化内容(文档、注释、票据)的问题。对于有关关系数据的问题,Aurabase 的本机 NL2SQL 直接将问题转换为经过验证的 SQL。上面提到的 HNSW 参数和维度类的详细信息,请参见 HNSW 索引 和 嵌入维度比较的文章。完整的 API 参考仍然是 RAG 和 pgvector 文档 和 AI Gateway 文档。

#
常见问题解答

常见问题解答

您必须自己管理 pgvector 扩展和 HNSW 索引吗?+
不会。创建项目时会自动配置嵌入架构、pgvector 扩展和部分 HNSW 索引(每个维度类一个:768、1536、3072)。你直接调用 ragIngest() 然后 rag();如果您的语料库具有特定的配置文件,则可以在服务器端对索引(ef_search、iterative_scan 模式)进行微调。
我应该为我的用例选择哪个嵌入维度?+
Aurabase 根据三个受支持的类别验证供应商返回的维度:768、1536 和 3072。选择取决于配置的嵌入模型(例如 OpenAI 的 text-embedding-3-small 生成 1536 个维度),并涉及召回率、成本和存储大小之间的折衷(在我们专用于嵌入维度的比较中详细介绍)。

准备好部署了吗?

五分钟内完成您的后端。

无需信用卡 · 500 MB 免费 · 50,000 MAU