Vector stores
Index documents too large for the prompt, then search them, or let Olive search them while it answers.
Index a document in a vector store, then search it directly or let Olive search it while it answers.
When to use it
- A long guideline is too large for one file in the prompt.
- A patient's full record or a folder of letters is too large to send whole.
- You want to see which sections a question retrieves before Olive answers.
The SDK samples assume the client from the Quickstart.
Create a store and attach a file
Create the store empty, then attach files one at a time. The attach call returns when indexing is done, so a large file can take minutes.
store = client.vector_stores.create(name="cardiology-guidelines")
file = client.files.create(file=open("acs-guideline.pdf", "rb"), purpose="user_data")
attached = client.vector_stores.files.create(vector_store_id=store.id, file_id=file.id)
print(attached.status) # completed, or failed
if attached.status == "failed":
print(attached.last_error.message)The call returns 200 whether indexing worked or not, so check status. A failed file stays attached, and attaching it again returns the same failure. Detach it before you retry.
Let Olive search
Give the Responses API a file_search tool with the store's ID. Olive decides when to search, reads the sections that match, and answers from them.
curl https://api.avey.ai/llm/responses \
-H "Authorization: Bearer $AVEY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "olive",
"input": "What is the recommended first-line antiplatelet therapy?",
"tools": [{ "type": "file_search", "vector_store_ids": ["vs_..."] }]
}'The Go samples reuse the Quickstart client. Add the imports each sample uses. See Tools for file_search alongside your own functions.
Search the store directly
POST /vector_stores/{id}/search returns the sections that best match a query. It does not run Olive, so you can build your own retrieval, or check what Olive would be given.
results = client.vector_stores.search(
vector_store_id=store.id,
query="first-line antiplatelet therapy",
)
for hit in results.data:
print(hit.file_id, hit.attributes)
print(hit.content[0].text)Each result is one section of one file. attributes.headings holds the headings the section sat under, so you can show a clinician where a passage came from.
Limits
| Limit | Value |
|---|---|
| Attach | One file at a time per store. Parallel attaches can lose files. |
| Batches | POST /vector_stores/{id}/file_batches returns 403. |
| File size | 5 MB, as for files |
| Attaches | Count toward the file limit of 20 per hour. See Rate limits. |
| Stores created | 50 per day, in bursts of up to 10. See Rate limits. |
Errors
An attach that fails still returns 200. The reason is in last_error.message.
| Message | What to do |
|---|---|
file {file_id} is too complex to search; send a smaller file | Split the file. |
file processing is unavailable; retry later | Detach the file, then attach it again. |
no such file: {file_id} | The file does not exist or belongs to another user. |
A file Olive cannot read fails with the same message as in Files.
Things to know
- A search returns sections, not the whole document. Olive answers from the sections that matched. If the passage you need is not among them, the answer will not reflect it. For a high-stakes question, run the search yourself and read the sections.
- When Olive answers from
file_search, its citations come back asfile_citationannotations on the output text. - Only stores you own are searched.
- Deleting a file removes it from every store. To delete a store, detach or delete its files first, so their indexed text goes with them.