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.

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

LimitValue
AttachOne file at a time per store. Parallel attaches can lose files.
BatchesPOST /vector_stores/{id}/file_batches returns 403.
File size5 MB, as for files
AttachesCount toward the file limit of 20 per hour. See Rate limits.
Stores created50 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.

MessageWhat to do
file {file_id} is too complex to search; send a smaller fileSplit the file.
file processing is unavailable; retry laterDetach 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 as file_citation annotations 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.
Last updated