你有没有这种需求:把公司几百页产品手册、几十份合同、或者一堆客服记录,喂给一个 AI,让它「只根据这些内容」回答问题?直接把全部文本塞进提示词既超长又费钱,而且模型还是会走神乱答。正确做法是用检索增强生成(RAG):先把文本切成片段、转成向量存进向量数据库,提问时先检索最相关的几段,再让大模型基于这几段作答。
这一步的关键零件就是向量数据库。自建(Milvus、Qdrant、pgvector)要装环境、调参数;而 Pinecone 是托管服务,注册一个 API Key 就能用,不用管服务器。本教程面向完全没接触过向量数据库的新手,六步跑通一个能用的 RAG 最小闭环。
先搞懂:为什么 RAG 离不开向量数据库?
大模型本身只「背」训练时见过的知识,对你的私有文档一无所知。RAG 的思路是:提问时先把问题变成一串数字(向量),去向量库里找「意思最接近」的文档片段,再把片段连同问题一起交给大模型。这样它回答时手边就有依据,准确率明显提升。
| 环节 | 做什么 | 本教程用的工具 |
|---|---|---|
| 切分与嵌入 | 把文本转成向量 | OpenAI text-embedding-3-small |
| 存储与检索 | 存向量、按相似度查询 | Pinecone 托管索引 |
| 生成回答 | 基于检索片段作答 | OpenAI 聊天模型 |
先说清楚边界:Pinecone 只负责「存向量 + 找相似」,它不帮你切文档、也不帮你写提示词。这些活儿由本教程的 Python 脚本承担。本教程聚焦最小可用闭环,生产环境还要考虑分块策略、元数据过滤和重排,文中会点到。
Step 1:注册 Pinecone 并拿到 API Key
Pinecone 有免费档,足够本教程练手。打开官网注册后,进入控制台创建一个 API Key。
1. 浏览器打开:pinecone.io,用邮箱或 GitHub 注册
2. 进入控制台(Console)→ 左侧 API Keys
3. 点 Create API Key,复制那一串以 pc- 开头的密钥
4. 同时记下你账号所在的 Region(如 us-east-1)
注意:免费档有索引数量和向量的额度限制,
本教程的量级完全够用。
Step 2:安装依赖并连接 Pinecone
本教程用 Python。先把 Pinecone 客户端和 OpenAI 客户端装上,再用环境变量里的密钥初始化。
pip install pinecone openai python-dotenv
# 新建 .env 文件,写入(不要提交到公开仓库):
# PINECONE_API_KEY=pc-xxxxxxxx
# OPENAI_API_KEY=sk-xxxxxxxx
下面是一个最小连接脚本,能跑通就说明密钥和环境没问题:
import os
from dotenv import load_dotenv
from pinecone import Pinecone
load_dotenv()
pc = Pinecone(api_key=os.environ["PINECONE_API_KEY"])
# 列出你已有的索引,确认能连上
print(pc.list_indexes().names())
连不上?常见三个原因:① Key 复制时多了空格或换行;② 网络访问 Pinecone 被墙(国内环境可能需要代理);③ 装错包名(是 pinecone,不是 pinecone-client,后者是旧版)。逐个排查即可。
Step 3:创建向量索引(Index)
索引(Index)就是一张「向量表」。创建时要指定维度(取决于嵌入模型)和距离算法。我们用 OpenAI 的 text-embedding-3-small,它输出 1536 维向量,距离用 cosine。
index_name = "rag-demo"
# 避免重复创建
if index_name not in pc.list_indexes().names():
pc.create_index(
name=index_name,
dimension=1536,
metric="cosine",
spec={"serverless": {"cloud": "aws", "region": "us-east-1"}},
)
index = pc.Index(index_name)
版本坑提醒:Pinecone Python SDK 在 2025 年做过一次大改。新版引入了 create_index_for_model 加 embed 参数,可以让索引在写入时自动帮你做嵌入。本教程用更通用、文档更全的旧式写法(dimension + serverless spec)。如果你装到了新版且报错,请以官网当前文档为准,或固定版本 pip install pinecone==3.1.0。
Step 4:用 OpenAI 生成嵌入并把文档入库
把你的资料切成小段,每段调一次嵌入接口得到向量,再连同原文(放进 metadata)一起 upsert 到索引。下面用一段示例文本演示,实际使用时换成你自己的文档即可。
from openai import OpenAI
emb_client = OpenAI()
def embed(text):
r = emb_client.embeddings.create(
model="text-embedding-3-small",
input=text,
)
return r.data[0].embedding
docs = [
"Pinecone 是一个托管的向量数据库,适合做语义检索。",
"RAG 让大模型先检索再回答,能减少编造。",
"OpenAI 的嵌入模型 text-embedding-3-small 输出 1536 维向量。",
]
# 逐条入库:values 是向量,metadata 里放原文便于后续展示
items = []
for i, text in enumerate(docs):
items.append({
"id": "doc-" + str(i),
"values": embed(text),
"metadata": {"text": text},
})
index.upsert(vectors=items)
print("已入库:", index.describe_index_stats())
Step 5:查询最相似的片段
提问时,先把问题嵌入,再查索引取最相似的 3 段。这一步就是 RAG 的「检索」。
question = "怎么减少大模型编造?"
res = index.query(
vector=embed(question),
top_k=3,
include_metadata=True,
)
for m in res.matches:
print(round(m.score, 3), m.metadata["text"])
检索结果不理想? 多半是嵌入模型或分块策略不对,而不是 Pinecone 的锅。先确认问题向量和文档向量用的是同一个嵌入模型(维度必须一致),再调分块和 top_k。Pinecone 支持 metadata 过滤,真多资料时可以用「来源 / 时间 / 标签」先收窄范围再排序。
Step 6:拼出最小可用的 RAG——让大模型基于检索结果回答
把检索到的片段拼进提示词,明确告诉大模型「只依据下面资料作答,资料没有就如实说不知道」。这就闭环了。
def ask(question):
res = index.query(vector=embed(question), top_k=3,
include_metadata=True)
context = "\n".join(m.metadata["text"] for m in res.matches)
prompt = (
"只依据下面的资料回答问题,资料里没有就回答"
"「资料中没有相关信息」。\n\n资料:\n" + context +
"\n\n问题:" + question
)
r = emb_client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
)
return r.choices[0].message.content
print(ask("怎么减少大模型编造?"))
常见问题速查
| 你遇到的现象 | 大概率原因 与 解决 |
|---|---|
| create_index 报维度不匹配 | 嵌入模型和索引 dimension 不一致,确认都用 1536 维 |
| query 返回空 | 索引还没建好或没 upsert 成功,先 describe_index_stats 看计数 |
| 回答还是编造 | 检索片段不相关,检查嵌入模型一致性与分块策略 |
| 国内连不上 Pinecone | 网络需代理;或改用自托管向量库(Qdrant/pgvector) |