一次往向量库塞了 200 个 PDF,轮询两小时 file_counts 里 in_progress 一直占一半以上,库的 status 也不转 completed,检索时永远只命中最早那几份。
一开始怀疑是「文件还没到 processed 就发起检索,命中的只是已完成部分」,查了一圈,方向不对。
真正麻烦的地方在于,几个原因的现象几乎一样。单个库的索引并发有配额,一次性提交太多文件只能排队。少数情况下是单个文件有体积和 token 上限,超限的文件会静默失败。
还有一种情况,轮询的是另一个同名空库,真实的库在别的项目下。
动手时先看这个库的文件计数分布
curl -s https://api.openai.com/v1/vector_stores/vs_abc -H "Authorization: Bearer $OPENAI_API_KEY" | jq '.file_counts'
接着分页列出每个文件的状态与错误码
curl -s "https://api.openai.com/v1/vector_stores/vs_abc/files?limit=100" -H "Authorization: Bearer $OPENAI_API_KEY" | jq -r '.data[]|"\(.status) \(.last_error.code)"'
然后把失败的文件单独重新挂一次
curl https://api.openai.com/v1/vector_stores/vs_abc/files -H "Authorization: Bearer $OPENAI_API_KEY" -H "Content-Type: application/json" -d '{"file_id":"file_abc"}'
等前面都确认过,再用 SDK 的 create_and_poll 等库建完
python -c "from openai import OpenAI;vs=OpenAI().beta.vector_stores.create_and_poll(name='kb');print(vs.status,vs.file_counts)"
改完先别撤,确认这几项。库详情里 status 是 completed,file_counts 的 completed 等于上传数,failed 为零,检索同一个问题能命中最近上传的文件。
提醒一点。索引是异步的,200 个文件不等于 200 个并发,分批提交并把失败文件重挂,比一次性重传全部要省额度也快。这类问题最好一次改到位,反复小改反而容易把原因搅混。