登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  科技周边 >  人工智能

file search 怎样设置检索过滤

来源:17golang原创

时间:2026-10-25 12:13:28 420浏览 收藏

我第一次给知识库加“只查中文资料”的条件时,误以为 file_search 会像数据库的 WHERE 子句一样直接过滤正文。结果是条件看起来写对了,返回内容却仍然混进了不该出现的文件。真正的关键是:过滤对象是 vector store 中文件对象的 attributes,它会先缩小候选文件,再进行语义和关键词检索。

官方地址:https://developers.openai.com/api/docs/guides/tools-file-search

本文只讨论这个文件级边界。示例使用 Python SDK,过滤条件中的值、字段名和组合关系都需要与你上传文件时写入的属性保持一致。

影响面:过滤错一层,召回结果就会变杂

OpenAI 的 file search 建立在 vector store 上。文件被加入后会被切分、嵌入并建立索引;可过滤的是 vector_store.file 关联的属性,而不是把正文当成结构化字段查询。比如给每个文件补上 region、category 和 Unix 时间戳 date,再让 file_search 按这些属性限定候选范围。

上传文件、vector_store.file、attributes 与 file_search 的静态关系说明图
图1:文件属性过滤的结构说明图,重点看 attributes 与 file_search 之间的文件级边界;这不是截图或运行证据。

时间线:先写属性,再把过滤条件交给工具

我后来把排查拆成两个动作。第一步是在文件进入 vector store 时写入稳定属性;第二步是在 Responses API 的工具配置里使用 filters。属性名不是文件名的自动别名,想按文件名过滤也要显式写入一个自定义属性。

from openai import OpenAI

client = OpenAI()

# 给 vector_store.file 写入可筛选的文件级属性;date 使用 Unix 时间戳。
client.vector_stores.files.create(
    vector_store_id="vs_123",
    file_id="file_123",
    attributes={
        "region": "cn",
        "category": "guide",
        "date": 1761868800,
    },
)

这些属性最多 16 个键,键和值都要保持稳定。日期、版本或租户编号最好统一类型,否则后面的 gte、lte 比较会很难排查。

触发条件:单条件能用,组合条件开始失控

单条件最容易确认。比较过滤使用 eq、ne、gt、gte、lt、lte、in 或 nin;多条件则用 and 或 or 包起来。它表达的是“哪些文件可以进入检索”,不是“正文必须出现哪些词”。

from openai import OpenAI

client = OpenAI()

# 先限定区域和日期,再允许两类文档进入候选集。
response = client.responses.create(
    model="gpt-6-astra",
    input="请找出最近的部署指南,并说明回滚条件。",
    tools=[{
        "type": "file_search",
        "vector_store_ids": ["vs_123"],
        "filters": {
            "type": "and",
            "filters": [
                {"type": "eq", "key": "region", "value": "cn"},
                {"type": "gte", "key": "date", "value": 1761868800},
                {
                    "type": "or",
                    "filters": [
                        {"type": "eq", "key": "category", "value": "guide"},
                        {"type": "eq", "key": "category", "value": "runbook"},
                    ],
                },
            ],
        },
        "max_num_results": 10,
    }],
)

# 需要排查召回内容时,可在请求中加入 include="file_search_call.results"。
print(response)
file search 的 and、or 复合过滤与候选文件集合关系说明图
图2:复合 filters 的静态关系图,重点看条件表达式与候选文件集合的关系;这不是执行流程截图。

根因:看似“过滤不生效”,通常是属性契约不一致

这类问题我最后归成三种。第一,上传时根本没有写属性,查询自然没有可比较的字段。第二,属性键写成了 lang,过滤却使用 language;字段名不一致不会自动猜测。第三,把日期写成字符串,却用数字范围比较,或者把 in 的数组值写成了一个逗号分隔字符串。

另一个容易误判的点是:过滤完成后仍然要做语义检索。如果候选文件本来就很少,问题不一定是 filters 错了,也可能是用户问题与剩余文件内容的相关性不足。官方检索文档还提供了 max_num_results、rewrite_query、score_threshold 等检索参数,它们解决的是召回和排序,不替代属性过滤。

修复动作:把属性契约写成一张小表

字段示例值适合的过滤注意点
regioncneq统一枚举,不混用中文名
categoryguideeq/in多类别用数组给 in
dateUnix 时间戳gte/lte所有文件使用同一类型

我会先取一份属性命名表,再把“上传端”和“检索端”放在同一份配置里维护。遇到 0 条结果时,先临时去掉一个条件定位是哪一层收窄过度,然后恢复条件,不要立即改写用户问题。这样才能区分“没有文件符合条件”和“语义检索没有命中”。

防复发:用可观察的请求参数保留排查线索

正式接入时建议固定三件事:属性键使用小写和稳定枚举;日期全部用数字时间戳;需要审查召回内容时,在开发环境把 file_search_call.results 加到 include。结果数量默认最多返回 10 条,当前文档允许通过 max_num_results 调到 50 条以内。不要把 API 密钥、真实用户标识或内部路径写进文章示例。

我对 file search 的结论是:filters 负责“哪些文件有资格被检索”,语义查询负责“这些文件里哪段内容最相关”。前者是文件属性契约,后者是内容相关性;把两层拆开,检索过滤就不会再变成一场盲目调 prompt 的排障。

相关问题

file search 能直接按正文中的关键词过滤吗?

filters 针对文件属性。正文关键词仍由检索过程处理,不能把任意正文片段当成结构化属性键。

为什么设置了 in 还是没有结果?

先确认该属性确实写在每个 vector_store.file 上,再确认 value 是数组,并且数组元素的类型和值与属性完全一致。

组合条件应该用 and 还是 or?

所有条件都必须满足时用 and;允许多个候选值时可在内部使用 or,并注意嵌套结构是否把候选集收得过窄。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>