GuidesRAG
用 Responses API File Search 检索 PDF 知识库
上传一个 PDF 到 OpenAI Vector Store,再用 Responses API 的 file_search 基于这份文件回答问题。
基于 OpenAI Cookbook 整理 · 官方资料 ↗
很多 RAG 教程一上来就让你自己处理整条链路:解析 PDF、切 chunk、做 embedding、建向量库,再自己写 retrieval。这条路适合你要深度定制检索策略的时候,但对很多真实需求来说过重了。
如果你现在只是想做到一件事——让模型根据一批 PDF 回答问题——OpenAI File Search 已经把其中大部分检索基础设施托管掉了。你不用自己维护向量库,也不用先手写检索再拼 prompt。
这篇就完成一个具体任务:上传一个 PDF,然后让 Responses API 基于这个 PDF 回答问题,并确认答案真的引用了你的文件。
File Search 到底替你做了什么
可以把整条链路理解成:PDF → File → Vector Store → file_search → Responses API。
你把本地 PDF 上传成 OpenAI 的 File,再把它放进 Vector Store。OpenAI 会负责后续的索引与检索。提问时,你不是先自己搜一段文字塞进 prompt,而是在 Responses API 的 tools 里声明 file_search,并告诉它去哪个 Vector Store 里找。
模型决定需要查资料时,会调用这个工具;命中的内容再进入回答过程。对你来说,最重要的工作变成两件:把正确的文件放进去,以及在响应里确认它真的用了这些文件。
准备一个 PDF
先准备最小环境。你需要 Python、可用的 OPENAI_API_KEY,以及至少一个本地 PDF。Cookbook 还会用到 PyPDF2、pandas、tqdm;这篇先走最小可运行路径,依赖按官方示例安装即可。
- Python 3.10+ 与虚拟环境
- 环境变量 OPENAI_API_KEY
- 至少一个本地 PDF(例如放到 openai_blog_pdfs/)
- 网络可访问 OpenAI API
安装依赖(与官方 Cookbook 一致)
pip install openai PyPDF2 pandas tqdm创建客户端,并指定 PDF 目录
from openai import OpenAI
import os
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
dir_pdfs = "openai_blog_pdfs" # 放入你的 PDF创建 Vector Store
Vector Store 是这批文件的检索容器。先创建一个,后面上传和提问都会用到它的 id。
vector_store = client.vector_stores.create(name="openai_blog_store")
print(vector_store.id)把 PDF 放进去
上传分两步:先用 files.create 把本地文件交上去,再用 vector_stores.files.create 把它关联到刚才的 Vector Store。Cookbook 里可以并行上传多个 PDF;这里先用一个文件把链路跑通。
file_path = "openai_blog_pdfs/sample.pdf"
file_response = client.files.create(
file=open(file_path, "rb"),
purpose="assistants",
)
client.vector_stores.files.create(
vector_store_id=vector_store.id,
file_id=file_response.id,
)
print("uploaded", file_response.id)注意 purpose 要用 "assistants"。文件刚关联进去时,索引可能还需要一点时间;如果立刻提问却完全不引用内容,先确认文件已经处理完成。
让 Responses API 搜索这个 PDF
接下来真正提问。关键点是在 tools 里声明 type 为 file_search,并把 vector_store_ids 指到你刚才创建的 store。Cookbook 用 gpt-4o-mini 演示。
query = "What's Deep Research?"
response = client.responses.create(
input=query,
model="gpt-4o-mini",
tools=[{
"type": "file_search",
"vector_store_ids": [vector_store.id],
}],
)
message = response.output[1].content[0]
print(message.text)
print({a.filename for a in message.annotations})如果问题本身就出现在 PDF 里,你应该能看到相关回答。下一步比“有没有回答”更重要:确认它引用了你的文件。
怎么确认答案真的来自你的文件
不要只看自然语言是否“像那么回事”。打印 annotations,检查里面有没有命中的 filename。这是这条链路最直接的验证信号。
- vector_stores.create 返回了带 id 的对象
- 上传后能在 Vector Store 文件列表中看到 PDF
- responses.create 返回与 PDF 相关的答案
- annotations 中能看到命中的 filename
如果 response.output 的下标和示例不一致,先把整个 output 打印出来。Cookbook 的下标假设了特定返回顺序;真实响应里 message 和 file_search_call 的位置可能不同。
什么情况下适合用 File Search
File Search 适合你想尽快验证“基于这些 PDF 能不能答得起来”的场景。它把切块、嵌入和向量存储托管在 OpenAI 一侧,你主要负责上传与提问。
如果你需要精细控制切块策略、本地向量库、复杂权限隔离,或者检索必须完全跑在自己的基础设施里,那就要回到自建 RAG。先用 File Search 证明问题成立,再决定要不要上更重的方案,通常更省时间。
最容易踩的几个坑
上传失败或 purpose 报错
确认文件可读,并使用 purpose="assistants";同时检查 API Key 权限与配额。
问答完全不引用 PDF
确认 vector_store_ids 正确,且文件已经处理完成;换一个 PDF 内明确出现过的问题再试。
response.output 下标与示例不一致
先打印 response.output,按实际 message / file_search_call 项取值,不要死记 Cookbook 里的固定下标。
官方资料
OpenAI Cookbook
Doing RAG on PDFs using File Search in the Responses API ↗