使用 Claude、pgvector 和 FastAPI 在周末构建生产级 RAG 聊天机器人

作者
  • avatar
    姓名
    Nino
    职业
    Senior Tech Editor

检索增强生成 (Retrieval-Augmented Generation, RAG) 已经从一个实验性的技术概念演变为企业级 AI 应用的标准架构。虽然市场上有很多复杂的框架(如 LangChain 或 LlamaIndex),但对于追求性能和可控性的开发者来说,使用基础组件直接构建往往是更好的选择。通过结合 PostgreSQL (配合 pgvector 扩展)、FastAPI 框架以及通过 n1n.ai 接入的 Claude 模型,你可以在一个周末内交付一个真正具备生产水准的聊天机器人。

为什么选择这个技术栈?

RAG 的核心本质其实是一个“带有上下文的数据库查询”。它的工作流程非常清晰:将用户的提问转化为向量,在数据库中匹配最相关的文档片段,然后将这些片段作为背景知识喂给大语言模型 (LLM)。

  • PostgreSQL (pgvector): 绝大多数企业已经在使用 Postgres。通过 pgvector 扩展,你无需引入专门的向量数据库(如 Pinecone 或 Milvus),即可在现有的关系型数据库中实现高性能的向量搜索。这极大地降低了运维成本。
  • FastAPI: 作为 Python 生态中最快的 Web 框架之一,FastAPI 提供了原生异步支持和 Pydantic 类型校验,非常适合处理高并发的 AI 接口请求。
  • Claude 3.5 Sonnet / Haiku: 在逻辑推理和遵循指令方面,Claude 系列模型目前处于行业领先地位。通过 n1n.ai 这样的 API 聚合平台,你可以获得极高的请求成功率和极低的延迟,这对生产环境至关重要。

关键挑战:嵌入模型 (Embeddings) 的选择

一个新手最容易踩的坑是:Claude API 本身并不提供嵌入 (Embeddings) 端点。这意味着你不能直接把一段文字发给 Claude 并要求它返回一个向量。你需要一个独立的嵌入模型。

目前,Voyage AIvoyage-3 模型是 Claude 官方推荐的搭档。它的维度(通常为 1024 维)和语义理解能力与 Claude 的推理风格非常契合。当然,你也可以选择 OpenAI 的嵌入模型或者本地运行的开源模型(如 BGE-M3)。无论选择哪种,请记住:你的数据库 vector 列的维度必须与嵌入模型的输出维度完全一致,且一旦存入数据,不能在同一个表内混用不同模型的向量。

数据库层:配置 pgvector

在 Postgres 中配置向量搜索非常简单。我们推荐使用 HNSW 索引,因为它在处理大规模数据时比 IVFFlat 更快,且不需要提前进行聚类训练。

-- 开启向量扩展
CREATE EXTENSION IF NOT EXISTS vector;

-- 创建存储文档片段的表
CREATE TABLE doc_chunks (
    id        bigserial PRIMARY KEY,
    content   text NOT NULL, -- 文本内容
    embedding vector(1024) NOT NULL, -- 向量,维度需匹配模型
    source_url text -- 元数据示例
);

-- 创建 HNSW 索引以加速余弦相似度搜索
CREATE INDEX ON doc_chunks USING hnsw (embedding vector_cosine_ops);

核心实现:从分块到检索

在生产环境中,文档分块 (Chunking) 的质量直接决定了 RAG 的效果。简单的固定长度切割往往会破坏语义。建议使用带重叠 (Overlap) 的滑动窗口算法,确保上下文的连贯性。

import psycopg
from pgvector.psycopg import register_vector

# 假设你已经有了 get_embedding 函数
def ingest_data(db_url, text_list):
    # 1. 获取向量
    vectors = [get_embedding(t) for t in text_list]

    # 2. 存入数据库
    with psycopg.connect(db_url) as conn:
        register_vector(conn)
        with conn.cursor() as cur:
            for text, vec in zip(text_list, vectors):
                cur.execute(
                    "INSERT INTO doc_chunks (content, embedding) VALUES (%s, %s)",
                    (text, vec)
                )
        conn.commit()

构建 API 服务

有了底层的支持,我们可以使用 FastAPI 快速封装一个接口。在这个环节,n1n.ai 的优势就体现出来了:它能让你在 Claude 3.5 Sonnet 和 Claude 3 Haiku 之间无缝切换,方便你在“高性能”和“低成本”之间寻找平衡。

from fastapi import FastAPI
from pydantic import BaseModel
import anthropic

app = FastAPI()
client = anthropic.Anthropic(api_key="YOUR_N1N_API_KEY")

class ChatRequest(BaseModel):
    question: str

@app.post("/ask")
async def ask_bot(req: ChatRequest):
    # 1. 将问题向量化
    q_vec = get_embedding(req.question)

    # 2. 从 Postgres 检索相似片段
    # 使用 <=> 操作符计算余弦距离
    context = ""
    with psycopg.connect(DB_DSN) as conn:
        register_vector(conn)
        cur = conn.execute(
            "SELECT content FROM doc_chunks ORDER BY embedding &lt;=&gt; %s LIMIT 3",
            (q_vec,)
        )
        context = "\n".join([r[0] for r in cur.fetchall()])

    # 3. 构造 Prompt 并调用 Claude
    prompt = f"基于以下背景知识回答问题:\n{context}\n\n问题:{req.question}"
    response = client.messages.create(
        model="claude-3-5-sonnet-20240620",
        max_tokens=1024,
        messages=[{"role": "user", "content": prompt}]
    )
    return {"answer": response.content[0].text}

生产环境的“进阶指南”

虽然周末可以搭出原型,但要达到真正的“生产级”,你还需要关注以下几点:

  1. 连接池 (Connection Pooling): 不要为每个 HTTP 请求都创建一个新的数据库连接。使用 psycopg_pool 维护一个长连接池,否则在高并发下 Postgres 会迅速耗尽文件描述符。
  2. 系统提示词 (System Prompt) 优化: 优秀的 RAG 机器人需要严谨。在 System Prompt 中加入“如果背景知识中没有答案,请直接回答不知道,不要编造”是防止幻觉的关键。
  3. 流式输出 (Streaming): 为了提升用户体验,你应该实现 Server-Sent Events (SSE) 流式返回。Claude 模型在 n1n.ai 上支持极速的流式响应,能显著降低用户的感知等待时间。
  4. 重排序 (Reranking): 向量检索有时会召回一些语义相关但事实不相关的片段。引入一个 Rerank 模型(如 BGE-Reranker)对检索结果进行二次打分,可以大幅提升回答的准确度。
  5. 监控与评估: 使用像 LangSmith 或自定义的评估脚本来跟踪模型回答的质量。RAG 的优化是一个长期的过程,需要不断调整分块策略和 Prompt。

结语

通过 Postgres、FastAPI 和 Claude 的组合,你构建的不仅是一个聊天机器人,而是一个可扩展的知识智能引擎。这种架构避免了过度设计,将精力集中在最核心的数据质量和推理逻辑上。随着业务的增长,你可以轻松地在 n1n.ai 上升级到更强大的模型,或者在 Postgres 中横向扩展你的存储。

立即在 n1n.ai 获取免费 API 密钥,开启你的 RAG 开发之旅。