你有大量内部文档、产品手册或知识库,想让 AI 基于这些资料回答问题?RAG(检索增强生成) 就是最佳方案。本文手把手教你用 Embeddings API + 向量检索构建一个完整的 RAG 问答系统。

RAG 架构概览

RAG 的核心思路很简单:先检索,再生成

用户提问 → 向量检索相关文档 → 将文档 + 问题发送给 LLM → 生成回答

这比直接让 AI 回答要好得多 — AI 不再"编造",而是基于你的真实数据作答。

Step 1:文档切分(Chunking)

将原始文档切分为适当大小的文本块:

def chunk_text(text, chunk_size=500, overlap=50):
    """将文本切分为重叠的文本块"""
    chunks = []
    start = 0
    while start < len(text):
        end = start + chunk_size
        chunk = text[start:end]
        chunks.append(chunk)
        start = end - overlap  # 重叠部分避免语义断裂
    return chunks

# 示例:切分一篇产品文档
with open("product_manual.txt", "r") as f:
    text = f.read()

chunks = chunk_text(text)
print(f"切分为 {len(chunks)} 个文本块")

Step 2:生成 Embeddings 向量

from openai import OpenAI

client = OpenAI(
    api_key="sk-你的密钥",
    base_url="https://api2everything.xyz/v1"
)

def get_embeddings(texts, model="text-embedding-3-small"):
    """批量获取文本的 embedding 向量"""
    response = client.embeddings.create(
        model=model,
        input=texts
    )
    return [item.embedding for item in response.data]

# 为所有文本块生成向量
embeddings = get_embeddings(chunks)
print(f"生成了 {len(embeddings)} 个向量,维度:{len(embeddings[0])}")

Step 3:向量存储与检索

这里用 numpy 实现简单的向量检索。生产环境推荐使用 ChromaDB、Pinecone 或 Milvus:

import numpy as np

class SimpleVectorStore:
    def __init__(self):
        self.vectors = []
        self.texts = []

    def add(self, texts, embeddings):
        self.texts.extend(texts)
        self.vectors.extend(embeddings)

    def search(self, query_embedding, top_k=3):
        """余弦相似度检索"""
        query = np.array(query_embedding)
        scores = []
        for vec in self.vectors:
            v = np.array(vec)
            score = np.dot(query, v) / (np.linalg.norm(query) * np.linalg.norm(v))
            scores.append(score)
        top_indices = np.argsort(scores)[-top_k:][::-1]
        return [(self.texts[i], scores[i]) for i in top_indices]

# 构建向量库
store = SimpleVectorStore()
store.add(chunks, embeddings)

Step 4:RAG 问答

def rag_query(question, model="claude-sonnet-4-6-20250514"):
    """RAG 问答:检索 + 生成"""
    # 1. 将问题转为向量
    q_embedding = get_embeddings([question])[0]

    # 2. 检索最相关的文本块
    results = store.search(q_embedding, top_k=3)
    context = "\n\n---\n\n".join([text for text, score in results])

    # 3. 生成回答
    response = client.chat.completions.create(
        model=model,
        messages=[
            {"role": "system", "content": f"基于以下参考资料回答用户问题。如果资料中没有相关信息,请如实说明。\n\n参考资料:\n{context}"},
            {"role": "user", "content": question}
        ]
    )
    return response.choices[0].message.content

# 测试
answer = rag_query("这个产品支持哪些支付方式?")
print(answer)

Embeddings 模型对比

模型维度特点价格(中转后)
text-embedding-3-small1536性价比最高,速度快≈¥0.0002/1K tokens
text-embedding-3-large3072精度最高,适合复杂检索≈¥0.001/1K tokens
text-embedding-ada-0021536上一代,兼容性好≈¥0.001/1K tokens

生产环境优化建议

  1. 使用专业向量数据库 — ChromaDB(轻量)、Milvus(分布式)、Pinecone(托管)
  2. 混合检索 — 结合关键词搜索 + 向量检索,提升召回率
  3. Reranking — 检索后用 Rerank 模型对结果二次排序
  4. 智能分块 — 按段落、标题、语义边界切分,而不是固定字数
  5. 元数据过滤 — 为每个 chunk 添加来源、日期等元数据,支持精确过滤
  6. 评估与迭代 — 用 RAGAS 等框架评估问答质量,持续优化

常见问题

RAG 和直接把文档放进 prompt 有什么区别?

模型的上下文窗口有限(如 128K tokens),且长文本会增加成本和延迟。RAG 只检索最相关的片段(通常 3-5 个),既节省 token 又提高准确率。

中文文档的效果好吗?

text-embedding-3 系列对中文支持很好。建议切分时按句子或段落边界切分,避免中文语义被截断。

需要多大的向量数据库?

1 万个文本块约占 100MB 存储空间(1536维向量)。中小企业知识库通常在这个量级,ChromaDB 本地部署即可。

开始构建你的 RAG 知识库

注册即送免费额度 · 支持 Embeddings + Chat 全系列模型 · 国内直连无需翻墙

免费注册 →