1

上传文件、建向量库并用 file_search 提问

按官方步骤:createFile → vectorStores.create → files.create → 轮询 completed → responses.create 挂载 file_search,核对 citations。

图文22 分钟ChatGPT 官方文档 ↗

课程目录1 / 2

学习位置仅保存在当前浏览器,有效期 180 天。

01 / 图文教材

图文讲义

来源:OpenAI API Docs · File search。本讲义为中文跟做整理,非原文搬运。相关:Retrieval

你将得到什么

  • 一个可用的 Vector Store(知识库),里面至少有一份已索引完成的文件
  • 一次带 file_search 工具的 Responses API 调用
  • 能在输出里看到:file_search_call(检索调用)与带 file_citation 注解的回答正文

File Search 是 托管工具:模型决定何时检索时,平台自动执行搜索并写回结果,你不必自己实现检索循环。

开始前准备

  1. 导出环境变量(把密钥换成你自己的,勿提交到仓库):
export OPENAI_API_KEY="sk-..."
python -c "import openai; print('openai', openai.__version__)"

对照结果:应打印已安装的 openai 版本号;若 ModuleNotFoundError,先执行 pip install -U openai

  1. 本课默认用官方示例 PDF:https://cdn.openai.com/API/docs/deep_research_blog.pdf(也可换成本地 .pdf / .txt / .md 等,见第 2 课支持格式表)。
  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)

对照结果(结构与官方示例一致,字段顺序可能略有差异):

  1. output 里通常先有一项 "type": "file_search_call",含 idstatus(如 completed)、queries(模型实际检索问句)。
  2. 另有一项 "type": "message"content[].typeoutput_text,正文回答问题。
  3. 正文的 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_...
向量库文件 statuscompleted
响应里有 file_search_call有,且 status=completed
回答带 file_citation至少一条指向你上传的文件名

若只有空泛回答、没有任何 citation:确认 vector_store_ids 填对、文件已 completed,并换一句更贴文档的问题重试。

下一课:限制返回条数、把检索片段本身打进响应,以及 metadata 过滤。

本课资料

适用环境

  • 网页
  • iOS
  • Android
  • API
  • macOS

官方文档

ChatGPT