OpenAI Agents SDK #27:让 Agent 拥有私有知识库,FileSearchTool 一行代码搞定
本期深拆 FileSearchTool——OpenAI Agents SDK HostedTool 家族第二名成员。文章完整解析 5 个 dataclass 参数(vector_store_ids、max_num_results、include_search_results、ranking_options、filters),重点展开 RankingOptions 的 ranker 版本(default-2024-11-15)、score_threshold 调优逻辑、RRF hybrid_search 权重配置,以及 Filters 的 ComparisonFilter/CompoundFilter 两类过滤结构。同步提供 Vector Store 四步工作流(上传 → 创建 → 绑定 → 调用)完整代码,并对 WebSearchTool / FileSearchTool / HostedMCPTool 三类 HostedTool 做 6 维度选型矩阵对比。中文社区对 FileSearchTool 至今处于原创真空,本期为中文首发深度解读,结尾附 3 条生产级实践建议。
리서치 브리프
自己搭 RAG,绕不过这几步:选向量数据库、写 embedding 管线、实现检索逻辑、处理结果重排……光是跑通 hello world 就要大半天。
FileSearchTool 把这些全托管了。你把文件上传到 OpenAI Vector Store,把 Store ID 传给工具,Agent 就能直接在你的私有文档里做语义检索——OpenAI 在服务器端处理分片、embedding、检索和重排,不需要你本地写一行向量逻辑。1
FileSearchTool 是什么
FileSearchTool 是 OpenAI Agents Python SDK 的托管工具(HostedTool),HostedTool 家族第二名成员,排在 WebSearchTool 之后。2官方 docstring 说得很直白:
3"A hosted tool that lets the LLM search through a vector store. Currently only supported with OpenAI models, using the Responses API."「一个让 LLM 搜索向量存储的托管工具。目前仅支持 OpenAI 模型,使用 Responses API。」
三个核心约束:
- 运行在 OpenAI 服务器:检索执行全程在 OpenAI 基础设施内,开发者不需要实现任何本地检索逻辑
- 仅支持
OpenAIResponsesModel:不兼容 Chat Completions 后端,换模型时必须注意这一点 - wire name 固定:工具名称在协议层是
"file_search",SDK 层导入:from agents import FileSearchTool
5 个参数全景
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
vector_store_ids | list[str] | —(必填) | 要搜索的 Vector Store ID 列表 |
max_num_results | int | None | None | 返回结果数上限;API 层限制 1-50,不设时由 API 决定(通常 10) |
include_search_results | bool | False | 是否在 LLM 输出中包含搜索结果的详细元数据 |
ranking_options | RankingOptions | None | None | 排序与相关性调优选项 |
filters | Filters | None | None | 基于文件属性的过滤条件 |
最简用法:
from agents import Agent, FileSearchTool
agent = Agent(
name="knowledge_agent",
instructions="用户问你问题时,请搜索知识库回答。",
tools=[
FileSearchTool(
vector_store_ids=["vs_abc123"],
max_num_results=5,
)
],
)include_search_results=True 是个调试利器——开启后 LLM 的输出里会附带检索命中的原始片段和分数,方便排查「为什么没搜到」或「为什么搜到了错的」。RankingOptions 与 Filters 深潜
这两个参数的类型来自
openai SDK 包(openai.types.responses.file_search_tool_param)而非 agents SDK 本身——属于跨包类型引用,IDE 自动补全时要注意导入路径。5RankingOptions
from openai.types.responses.file_search_tool_param import RankingOptions
ranking = RankingOptions(
ranker="default-2024-11-15", # 或 "auto"
score_threshold=0.7, # 0-1,越高越严格
hybrid_search={
"embedding_weight": 0.7, # 语义匹配权重
"text_weight": 0.3, # 关键词匹配权重
}
)三个子字段说明:
ranker:排序器版本,两个合法值——"auto"(API 自动选最优)和 "default-2024-11-15"(固定版本,可复现)。注意这里不是 "default-2024-08-21"——SDK 源码确认是 "default-2024-11-15"。score_threshold:相关性得分阈值,范围 0 到 1。调高可以剔除低质量命中,但会减少返回数量。官方建议:「如果你发现文件搜索结果相关性不足,可以调整 ranking_options 来提升响应质量」6——调高 score_threshold 是第一步。hybrid_search:RRF(Reciprocal Rank Fusion,倒数排名融合)权重配置。embedding_weight 控制语义相似度的权重,text_weight 控制关键词重叠的权重。至少一个大于 0。文档类内容(关键词精确匹配重要)可以调高 text_weight;语义理解类问答偏向调高 embedding_weight。Filters
Filters 是 ComparisonFilter 或 CompoundFilter 的 Union 类型:from openai.types.responses.file_search_tool_param import ComparisonFilter, CompoundFilter
# 按属性过滤:只搜 region='us' 的文档
single_filter = ComparisonFilter(
type="eq",
key="region",
value="us"
)
# 日期范围过滤:2024 年的文档
date_filter = CompoundFilter(
type="and",
filters=[
ComparisonFilter(type="gte", key="created_at", value=20240101),
ComparisonFilter(type="lte", key="created_at", value=20241231),
]
)
# 按文件名 in-list 过滤
filename_filter = ComparisonFilter(
type="in",
property="filename",
value=["policy_v2.pdf", "handbook.pdf"]
)ComparisonFilter 支持 8 种比较操作:eq、ne、gt、gte、lt、lte、in、nin。CompoundFilter 支持 and / or 嵌套,可以组合任意层级的过滤条件。Vector Store 四步工作流
使用
FileSearchTool 前需要先准备好 Vector Store。完整流程四步:1from openai import OpenAI
client = OpenAI()
# Step 1:上传文件到 Files API
with open("company_handbook.pdf", "rb") as f:
uploaded_file = client.files.create(
file=f,
purpose="assistants"
)
# Step 2:创建 Vector Store
vector_store = client.vector_stores.create(
name="Company Knowledge Base"
)
# Step 3:将文件添加到 Vector Store(自动等待处理完成)
vs_file = client.vector_stores.files.create_and_poll(
vector_store_id=vector_store.id,
file_id=uploaded_file.id
)
# Step 4:检查状态
print(vs_file.status) # completed 则可用几个需要知道的细节:
处理状态机:文件进入 Vector Store 后经历
pending → processing → completed(或 error)。create_and_poll 会自动轮询等到 completed;如果不用 poll 版本,就需要手动 client.vector_stores.files.list(vector_store_id=...) 检查状态,status == "completed" 才能搜索。支持格式:
.pdf、.md、.txt、.docx、.html、.json、.py、.ts 等 19 种格式。text/* 类型文件编码须是 utf-8 / utf-16 / ascii。6定价:所有 Vector Store 总计 ≤1GB 免费,超出 $0.10/GB/天。1
速率限制:每个
vector_store_id 300 请求/分钟,与文件批处理操作共享配额。批量上传大量文件时要控制并发。绑定到 Agent 只需一行:
tools=[FileSearchTool(vector_store_ids=[vector_store.id])]HostedTool 三兄弟怎么选
FileSearchTool 和 WebSearchTool、HostedMCPTool 同属 HostedTool 家族,三者均运行在 OpenAI 服务器端,均需要 OpenAIResponsesModel,但适用场景完全不同。2| WebSearchTool | FileSearchTool | HostedMCPTool | |
|---|---|---|---|
| 数据来源 | 实时公开互联网 | 你的私有 Vector Store | 远程 MCP 服务器 |
| 必填参数 | 无(全默认可用) | vector_store_ids | tool_config(含 server_url) |
| 外部依赖 | 无 | 提前创建 Vector Store + 上传文件 | 外部 MCP 服务器在运行 |
| 延迟特性 | 网络往返 + 搜索引擎 | OpenAI 基础设施内检索,低延迟 | 取决于 MCP 服务器位置 |
| 适合场景 | 最新信息、实时新闻、公开内容 | 企业知识库、产品文档、RAG | 外部工具生态、结构化 API |
| 高级功能 | search_context_size 控制上下文量 | ranking_options + filters 精准召回 | defer_loading + ToolSearchTool |
三者可以在同一个 Agent 里混用。官方文档示例里就有同时挂
WebSearchTool() 和 FileSearchTool(max_num_results=3, vector_store_ids=[...]) 的写法——互联网 + 私有文档两路信息源同时覆盖。官方
research_bot 示例目前只用了 WebSearchTool,但 README 把「加入 FileSearchTool 支持」列为第一个建议改进项7:「Retrieval: Add support for fetching relevant information from a vector store. You could use the File Search tool for this.」——这意味着官方自己也认为 FileSearchTool 是 research_bot 的自然延伸。中文社区现状:微信公众号生态对「文件搜索工具」的搜索结果几乎全部指向 Windows 桌面搜索工具,OpenAI Agents SDK 的
FileSearchTool 完全缺席。知乎有数篇文章涉及 FileSearchTool,但均为官方文档翻译,无独立教程、配置指南或实战案例。8 全中文网络目前处于原创真空状态,本期是中文首发深度解读。3 条生产级建议
1.
max_num_results 控制在 3-5,先跑质量测试再加默认不设时 API 通常返回 10 条,全部塞进 context 会增加噪声,模型反而容易被低质量命中干扰。建议先从
max_num_results=3 起步:给 Agent 发几条真实问题,用 include_search_results=True 看命中内容,确认质量后再根据场景调大。内容密度高的场景(产品手册、合同文本)可以保持 3-5;需要广覆盖的场景(FAQ、知识库)可以到 8-10。2.
score_threshold 宁高勿低,用 include_search_results 诊断低阈值(如 0.3)会让大量不相关片段进入 context,高阈值(如 0.8)则可能返回空。推荐做法:先用
include_search_results=True 拿到命中分数分布,找到你的「相关/不相关」分界线,再把 score_threshold 设在该分界线附近。分数分布集中在 0.6 以下说明文档切片质量有问题,需要重新处理文件(换 chunk 大小或清理噪声文档)而不是靠调阈值蒙混。3. Vector Store 多个,按主题分库而不是一锅炖
vector_store_ids 接受列表,但不等于应该把所有文档塞进一个 Store。按主题分库有两个好处:一是可以对不同 Agent 配不同的知识库(客服 Agent 只能访问产品文档,内部 Agent 才能访问合同库);二是可以在 filters 里按 vector_store_id 范围缩小搜索范围,在多 Store 场景下精准定位。一个实用分法:产品文档一库、操作手册一库、历史记录一库,用 CompoundFilter 的 and 组合文件属性做跨库检索。下期预告:
#28 进入 HostedMCPTool——HostedTool 家族第三名成员,让 Agent 直接调用远程 MCP 服务器上的工具,defer_loading + ToolSearchTool 组合怎么玩。
이 콘텐츠를 둘러싼 관점이나 맥락을 계속 보강해 보세요.