第 1 课
上传文件、建向量库并用 file_search 提问
按官方步骤:createFile → vectorStores.create → files.create → 轮询 completed → responses.create 挂载 file_search,核对 citations。
学习位置仅保存在当前浏览器,有效期 180 天。
图文讲义
来源:OpenAI API Docs · File search。本讲义为中文跟做整理,非原文搬运。相关:Retrieval。
你将得到什么
- 一个可用的 Vector Store(知识库),里面至少有一份已索引完成的文件
- 一次带
file_search工具的 Responses API 调用 - 能在输出里看到:
file_search_call(检索调用)与带file_citation注解的回答正文
File Search 是 托管工具:模型决定何时检索时,平台自动执行搜索并写回结果,你不必自己实现检索循环。
开始前准备
- 导出环境变量(把密钥换成你自己的,勿提交到仓库):
export OPENAI_API_KEY="sk-..."
python -c "import openai; print('openai', openai.__version__)"
对照结果:应打印已安装的 openai 版本号;若 ModuleNotFoundError,先执行 pip install -U openai。
- 本课默认用官方示例 PDF:
https://cdn.openai.com/API/docs/deep_research_blog.pdf(也可换成本地.pdf/.txt/.md等,见第 2 课支持格式表)。 - 文档示例里的
model字段会随官方页面更新(例如页面上可能写当前可用的模型 ID)。以你账号可用、且支持 tools 的模型为准;若示例模型报错,到 Models 换一个再跑,其余参数不变。
步骤 1:上传文件,拿到 file_id
把下面整段保存为 01_upload_file.py 后运行(与官方 Python 示例同构):
from io import BytesIO
import requests
from openai import OpenAI
client = OpenAI()
def create_file(client, file_path: str) -> str:
if file_path.startswith(("http://", "https://")):
response = requests.get(file_path, timeout=30)
response.raise_for_status()
file_content = BytesIO(response.content)
file_name = file_path.rsplit("/", 1)[-1]
result = client.files.create(
file=(file_name, file_content),
purpose="assistants",
)
else:
with open(file_path, "rb") as file_content:
result = client.files.create(
file=file_content,
purpose="assistants",
)
return result.id
file_id = create_file(
client,
"https://cdn.openai.com/API/docs/deep_research_blog.pdf",
)
print(file_id)
pip install requests
python 01_upload_file.py
对照结果:终端打印形如 file-... 的 ID。记下它,下一步要用。
步骤 2:创建 Vector Store
from openai import OpenAI
client = OpenAI()
vector_store = client.vector_stores.create(name="knowledge_base")
print(vector_store.id)
对照结果:打印形如 vs_... 的 ID。这就是后面 vector_store_ids 要填的值。
步骤 3:把文件挂进向量库
把上两步的 ID 填进去:
from openai import OpenAI
client = OpenAI()
vector_store_id = "vs_..." # 步骤 2
file_id = "file-..." # 步骤 1
result = client.vector_stores.files.create(
vector_store_id=vector_store_id,
file_id=file_id,
)
print(result)
步骤 4:等到索引 status=completed
官方要求:在文件就绪(status 为 completed)之前不要提问。可循环列出向量库内文件:
from openai import OpenAI
import time
client = OpenAI()
vector_store_id = "vs_..."
while True:
page = client.vector_stores.files.list(vector_store_id=vector_store_id)
statuses = [(f.id, f.status) for f in page.data]
print(statuses)
if statuses and all(s == "completed" for _, s in statuses):
break
if any(s == "failed" for _, s in statuses):
raise SystemExit("indexing failed")
time.sleep(2)
print("ready")
对照结果:最终某一行里对应文件的 status 为 completed,并打印 ready。若长期停在 in_progress,检查文件是否损坏或格式不在支持列表。
步骤 5:用 Responses API + file_search 提问
from openai import OpenAI
client = OpenAI()
vector_store_id = "vs_..."
response = client.responses.create(
model="gpt-4.1-mini", # 若不可用,换成你账号支持 tools 的模型 ID
input="What is deep research by OpenAI?",
tools=[
{
"type": "file_search",
"vector_store_ids": [vector_store_id],
}
],
)
print(response)
对照结果(结构与官方示例一致,字段顺序可能略有差异):
output里通常先有一项"type": "file_search_call",含id、status(如completed)、queries(模型实际检索问句)。- 另有一项
"type": "message",content[].type为output_text,正文回答问题。 - 正文的
annotations里会出现"type": "file_citation",带file_id/filename(示例里常见deep_research_blog.pdf)。
可快速抽正文:
for item in response.output:
if getattr(item, "type", None) == "message":
for c in item.content:
if getattr(c, "type", None) == "output_text":
print(c.text)
print("citations:", getattr(c, "annotations", None))
步骤 6:自检清单
| 检查项 | 期望 |
|---|---|
file_id / vs_id | 分别为 file-... / vs_... |
| 向量库文件 status | completed |
响应里有 file_search_call | 有,且 status=completed |
回答带 file_citation | 至少一条指向你上传的文件名 |
若只有空泛回答、没有任何 citation:确认 vector_store_ids 填对、文件已 completed,并换一句更贴文档的问题重试。
下一课:限制返回条数、把检索片段本身打进响应,以及 metadata 过滤。
