RAG products
You're shipping a customer-facing feature backed by uploaded files. Doc Q&A, internal knowledge search, support over a manual, contract review. The hard parts of that build are rarely the embedding call. They're parsing the open MIME surface customers actually upload (PDFs scanned crooked, slide decks with text-on-image, spreadsheets, audio transcripts), keeping each customer's index isolated from the rest, watching empty-result rates when a customer reports retrieval is bad, and re-embedding everyone's docs when a better model lands six months from now. Ringside ships the four as one managed product.
Why Ringside
- · Managed vector stores. OpenAI-compat
/v1/vector_stores. One store per customer, true tenant isolation, cross-tenant reads return 404 by default. - · 25+ file types parsed in tokens. PDFs, Word, slides, images with text, audio for transcription, CSV tables as row-narratives. You pay parse tokens for what the parser actually ran, no per-file flat fee.
- · file_search inside Assistants. Drop the tool config into any run, get citations back in the response. The wire shape is OpenAI's, the underlying embedding model is your call across nine options.
- · No-downtime model migrations. Switch embedding models in the dashboard; we re-embed from the cached parses in the background and swap the index atomically. 7-day rollback window if the new model regresses.
- · Per-customer observability. Each store has its own query log: top-K scores, latency p95, empty-result rate, daily embedding cost. When a customer says retrieval is bad, you can show them why.
Architecture
In code
# 1. Create one vector store per customer
store = client.vector_stores.create(
name=f"acme-{customer_id}",
embedding_model="text-embedding-3-small",
)
# 2. Upload a file (any of 25+ MIME types: pdf, docx, pptx, png, mp3, ...)
file = client.files.create(
file=open("handbook.pdf","rb"),
purpose="attachments",
)
client.vector_stores.files.create(
vector_store_id=store.id,
file_id=file.id,
)
# 3. Query via file_search inside an Assistants run
run = client.beta.threads.runs.create_and_poll(
thread_id=thread_id,
assistant_id=assistant_id,
tools=[{
"type": "file_search",
"file_search": {"vector_store_ids": [store.id]},
}],
extra_headers={"FC-Customer": customer_id},
)
# Ringside handled: parsing, chunking, embedding, retrieval,
# citation extraction, per-customer cost attribution.