How data moves
- Embed the question and three records, mapping each response back to its input using
index. - Normalize vectors and retrieve two candidates by cosine similarity.
- If a rerank model is configured, send candidate text to
/rerank. Its returnedindexrefers to the candidate array in that request, not the original knowledge base. - Send candidate IDs and text to the chat model and accept only a complete JSON answer.
- Validate citation IDs against the candidates sent to the model, then build the source list from application-owned records.
Prepare and run
Follow the Python SDK guide to install dependencies and setAPI_BASE_URL (including /v1) and API_KEY. You need a text embedding model and a chat model supporting Chat Completions and system messages. A rerank model is optional. They may have different model IDs, but each must be available through your deployment.
Save the code below as rag.py. Explicitly clear API_RERANK_MODEL when reranking is disabled so that an old shell setting cannot enable it:
API_RERANK_MODEL to a rerank model ID provided by your deployment and run again. The flow sends three requests with reranking, otherwise two. Each request uses a 60-second timeout and no automatic retries; this is not a single deadline for the whole pipeline. Documents are embedded again on every run, which is suitable only for a small demonstration.
The embedding model must allow the same encoding method for questions and documents. If it requires different prefixes or query/document task types, adapt the encoding before combining inputs. All model IDs are placeholders; a chat model cannot substitute for an embedding or rerank model.
Complete Python example
Output and failure behavior
A successful result is a JSON object with ananswer and sources containing validated record IDs and original text. Wording and ranking depend on the model. The example does not set response_format, so it does not require channel support for JSON Schema mode. Plain text generation can still return invalid JSON, which the client rejects; a prompt is not a format guarantee. To add model-side constraints, confirm channel support and see structured output.
Source ID validation prevents citations to records that were not supplied; it does not prove the sources support the answer. Prompt instructions cannot eliminate document prompt injection. Treat model output as untrusted text, never execute it directly, and escape it for the target interface. Evaluate factual support, citation accuracy, and abstention separately.
Use your own knowledge base
- This example contains fixed public records and implements no user identity or permission system. A real application must filter documents on the server to those the current user can access before embedding, retrieval, reranking, and generation, so inaccessible content never reaches the model.
- Chunk documents offline and preserve stable document/chunk IDs, provenance, versions, embedding models, and preprocessing settings. At query time, embed only the question. Keep vector spaces compatible and re-evaluate retrieval after changing models.
- Budget the question, candidate text, and output against the target model’s token limits. Selecting two records is only a demonstration policy and does not ensure arbitrary documents fit the context.
- Evaluate answerable and unanswerable questions as well as conflicting records to tune candidate counts, thresholds, and reranking. Do not reuse a universal similarity threshold across models or treat any top-k result as sufficient evidence.
- Rerank failures stop the pipeline by default. If a product allows falling back to vector retrieval alone, record that degraded state and evaluate its quality separately rather than silently changing the behavior.