RAG (Files & Search)

View as Markdown

RAG (Retrieval-Augmented Generation)

Upload documents, generate embeddings, and query them semantically — all through client.rag.

Quick upload

The upload_file convenience method handles both the init call and the PUT to the signed URL in one step:

1from meshapi import MeshAPI
2
3client = MeshAPI(base_url="https://api.meshapi.ai", token="rsk_...")
4
5with open("handbook.pdf", "rb") as f:
6 upload = client.rag.upload_file(
7 file_name="handbook.pdf",
8 mime_type="application/pdf",
9 content=f.read(),
10 )
11
12print("File ID:", upload.file_id)

Async

1from meshapi import AsyncMeshAPI
2
3async with AsyncMeshAPI(base_url="https://api.meshapi.ai", token="rsk_...") as client:
4 with open("handbook.pdf", "rb") as f:
5 upload = await client.rag.upload_file(
6 file_name="handbook.pdf",
7 mime_type="application/pdf",
8 content=f.read(),
9 )

Two-step upload

Use init_upload when you want to control the PUT yourself:

1from meshapi._types import InitUploadRequest
2import httpx
3
4upload = client.rag.init_upload(
5 InitUploadRequest(file_name="handbook.pdf", mime_type="application/pdf", embed=False)
6)
7
8# PUT bytes directly to the signed URL (no auth header needed)
9httpx.put(upload.signed_url, content=pdf_bytes, headers={"Content-Type": "application/pdf"}).raise_for_status()

Trigger embedding

1from meshapi._types import BulkEmbedRequest
2
3resp = client.rag.embed(BulkEmbedRequest(file_ids=[upload.file_id]))
4for r in resp.results:
5 print(r.file_id, r.embedding_status)

Poll until ready

1import time
2
3while True:
4 status = client.rag.get(upload.file_id)
5 if status.embedding_status == "ready":
6 break
7 if status.embedding_status == "failed":
8 raise RuntimeError(f"Embedding failed: {status.last_error_code}")
9 time.sleep(3)
1from meshapi._types import SearchRequest
2
3results = client.rag.search(
4 SearchRequest(
5 query="What is the refund policy?",
6 top_k=5,
7 file_ids=[upload.file_id], # omit to search all files
8 )
9)
10
11for r in results.results:
12 print(f"[{r.score:.3f}] {r.text}")

Search options

FieldTypeNotes
querystrPlain-language question
top_kintResults to return (1–50, default 5)
file_idslist[str]Restrict to specific files
filterdictMatch on metadata key-value pairs
date_fromintUnix timestamp — only chunks created after
date_tointUnix timestamp — only chunks created before

List files

1page = client.rag.list(limit=50)
2print(f"{page.total} total files")
3for f in page.files:
4 print(f.file_id, f.upload_status, f.embedding_status)

RAG chat

Combine search results with a chat completion:

1from meshapi import ChatCompletionParams, ChatMessage
2
3results = client.rag.search(SearchRequest(query="What is the refund policy?", top_k=3))
4context = "\n\n".join(r.text for r in results.results)
5
6reply = client.chat.completions.create(
7 ChatCompletionParams(
8 model="openai/gpt-4o-mini",
9 messages=[
10 ChatMessage(role="system", content=f"Answer using only the context below.\n\n{context}"),
11 ChatMessage(role="user", content="What is the refund policy?"),
12 ],
13 )
14)
15print(reply.choices[0].message.content)