RAG, auto-tune and saved presets
RAG and auto-tune are part of the shared surface — identical routes on both tiers — but both are licence-gated, not tier-gated: whether they respond depends on the connected instance’s licence entitlement, not on whether it is Enterprise or Pro. A licence without the entitlement gets a normal authorization error, not a tier error.
Saved presets
Section titled “Saved presets”A saved preset is a project-scoped, user-authored extraction configuration, distinct from the
curated read-only presets presets()/presets/Presets lists. The two tiers spell the route
differently — /v1/saved_presets on Enterprise, /v1/saved-presets on Pro — but all three clients
resolve that for you.
created = client.create_saved_preset({"name": "invoices", "extraction_config": {"preset": "invoice"}})preset = client.get_saved_preset(created.id)client.update_saved_preset(created.id, {"name": "invoices-v2", "extraction_config": {"preset": "invoice"}})client.delete_saved_preset(created.id)const created = await client.createSavedPreset({ name: "invoices", extraction_config: { preset: "invoice" } });const preset = await client.getSavedPreset(created.id);await client.deleteSavedPreset(created.id);created, err := client.CreateSavedPreset(ctx, xberg.CreateSavedPresetRequest{Name: "invoices"})preset, err := client.GetSavedPreset(ctx, created.Id.String())err = client.DeleteSavedPreset(ctx, created.Id.String())Reference a saved preset from an extraction with options.saved_preset_id; it is mutually
exclusive with options.preset (a curated preset id).
Auto-tune
Section titled “Auto-tune”Auto-tune searches for an extraction configuration that best matches ground truth you supply,
across a set of sample documents. Submit is multipart: a JSON request part (the documents and
their ground truth, plus optional budget/search/routing) alongside one file part per
document, matched by filename.
from pathlib import Path
job = client.submit_auto_tune( { "documents": [ { "filename": "invoice.pdf", "ground_truth_kind": "structured", "ground_truth": '{"schema": {...}, "expected": {...}}', }, ], }, files=[Path("invoice.pdf")],)status = client.get_auto_tune_status(job.auto_tune_job_id)const job = await client.submitAutoTune({ request: { documents: [ { filename: "invoice.pdf", ground_truth_kind: "structured", ground_truth: groundTruthJson }, ], }, files: [{ name: "invoice.pdf", data: invoiceBytes, mimeType: "application/pdf" }],});const status = await client.getAutoTuneStatus(job.auto_tune_job_id);job, err := client.SubmitAutoTune(ctx, xberg.CreateAutoTuneJobRequest{ Documents: []xberg.AutoTuneDocumentInput{ {Filename: "invoice.pdf", GroundTruthKind: xberg.GroundTruthKind("structured"), GroundTruth: groundTruthJSON}, },}, []xberg.FileSource{{Name: "invoice.pdf", Reader: invoiceFile}})status, err := client.GetAutoTuneStatus(ctx, job.AutoTuneJobId)ground_truth_kind is one of markdown, plaintext or structured. For structured,
ground_truth is a JSON string encoding {"schema": ..., "expected": ...} — both the schema
and the expected output are required.
Poll with get_auto_tune_status/getAutoTuneStatus/GetAutoTuneStatus until the job completes,
then fetch the leaderboard and winning configuration:
result = client.get_auto_tune_result(job.auto_tune_job_id)profile = client.promote_auto_tune_profile(job.auto_tune_job_id, {"name": "invoices-tuned"})Promoting writes a named, reusable tuning profile — list and manage those with
list_tuning_profiles/get_tuning_profile/delete_tuning_profile (and their TypeScript/Go
equivalents). get_auto_tune_capabilities/getAutoTuneCapabilities/GetAutoTuneCapabilities
reports which OCR backends and knobs the connected deployment can search over — check it before
building a search config the deployment cannot honor.
The RAG surface manages vector collections, ingests documents into them, and retrieves chunks.
All three clients return the decoded response body untyped (Any in Python, unknown in
TypeScript, json.RawMessage in Go) — the schemas are still converging across tiers, so decode
against whichever fields you need.
client.create_rag_collection({"name": "policies", "embedding_dim": 384})client.add_rag_documents("policies", {"documents": [{"id": "doc-1", "text": "..."}]})hits = client.rag_retrieve("policies", {"query": "refund window", "top_k": 5})client.delete_rag_collection("policies")await client.createRagCollection({ name: "policies", embedding_dim: 384 });await client.addRagDocuments("policies", { documents: [{ id: "doc-1", text: "..." }] });const hits = await client.ragRetrieve("policies", { query: "refund window", top_k: 5 });await client.deleteRagCollection("policies");_, err := client.CreateRagCollection(ctx, map[string]any{"name": "policies", "embedding_dim": 384})_, err = client.AddRagDocuments(ctx, "policies", map[string]any{ "documents": []map[string]any{{"id": "doc-1", "text": "..."}},})hits, err := client.RagRetrieve(ctx, "policies", map[string]any{"query": "refund window", "top_k": 5})err = client.DeleteRagCollection(ctx, "policies")retrieve’s mode defaults to hybrid; pass "vector", "full_text" or a BYO query_vector
matching the collection’s embedding_dim. top_k is 1..=200 (default 10); rerank is
three-state — omit it for the collection default, set it to null to disable reranking for this
call, or supply a RerankerSpec to override it.
Long-running collection operations — ingest, reindex, embedding migration — return a job you poll
with get_rag_job/getRagJob/GetRagJob (or, for migrations specifically,
get_rag_migration_job/getRagMigrationJob/GetRagMigrationJob), the same terminal-status
contract as extraction jobs.
Pro also exposes a per-project RAG default via get_rag_config/set_rag_config — see
the control plane guide.