assistant-orchestrator-service
Rental-management AI assistant orchestrator.
The service receives a natural-language question, loads compact structured context from data-service, searches indexed document chunks in Qdrant, calls the configured LLM through llm-gateway, and returns a grounded answer with sources.
Endpoint
POST /assistant/ask
{
"userId": "2",
"question": "Qual e l'IBAN su cui pagare l'affitto?",
"propertyId": "10",
"tenantId": "22",
"contractId": "7",
"documentTypes": ["LEASE_CONTRACT"],
"language": "it",
"channel": "TELEGRAM",
"correlationId": "telegram:123456:987",
"llmProvider": "openai",
"topK": 8
}
Response:
{
"answer": "Il contratto indica ... [S1]",
"language": "it",
"sources": [
{
"documentId": "9",
"documentType": "LEASE_CONTRACT",
"sourceFileId": "4_z...",
"sourceFileUrl": null,
"storageKey": "contracts/7/9",
"pageNumber": 2,
"sectionTitle": "Pagamento",
"chunkIndex": 4,
"score": 0.87
}
],
"actions": [
{
"type": "document_download",
"label": "Scarica contratto.pdf",
"url": "https://test.app.rainty.app/docs-service/dl/<token>",
"documentName": "contratto.pdf",
"documentType": "LEASE_CONTRACT",
"expiresIn": 900
}
],
"metadata": {
"propertyId": "10",
"tenantId": "22",
"contractId": "7",
"chunksRetrieved": 5,
"model": "gpt-4.1-mini",
"provider": "openai",
"grounded": true,
"groundingReason": "SUPPORTED_CONTEXT_PRESENT",
"structuredContextLoaded": true,
"channel": "TELEGRAM",
"correlationId": "telegram:123456:987"
}
}
If no structured context and no document chunks are available, the service returns a safe fallback answer instead of invoking the LLM.
Required Dependencies
data-service: structured context with user ownership checks.document-indexer-service: indexes documents before they can be searched.qdrant: vector store containing theQDRANT_COLLECTION.llm-gateway: LLM provider abstraction.- OpenAI-compatible embedding provider for query embeddings.
docs-service: generates time-limited document download links when the assistant toolget_document_download_linkis selected.
Environment Variables
DATA_SERVICE_URL: data-service base URL, defaulthttp://data-service:3003.LLM_GATEWAY_URL: llm-gateway base URL, defaulthttp://llm-gateway:3005.QDRANT_URL: Qdrant URL, defaulthttp://qdrant:6333.QDRANT_API_KEY: optional Qdrant API key.QDRANT_COLLECTION: collection name, defaultrental_documents.QDRANT_MIN_SCORE: minimum similarity score, default0.ASSISTANT_QDRANT_DEBUG_SEARCH: whentrue, runs diagnostic relaxed searches if the filtered search returns no chunks.ASSISTANT_CONTINUE_ON_QDRANT_ERROR_WITH_CONTEXT: whentrue, the assistant can answer from structured context if Qdrant search fails.DEFAULT_TOP_K: default number of chunks to retrieve, default8.MAX_TOP_K: maximum acceptedtopK, default20.EMBEDDING_PROVIDER: currentlyopenai.EMBEDDING_MODEL: embedding model, defaulttext-embedding-3-small.EMBEDDING_DIMENSIONS: expected vector dimension, default1536.OPENAI_API_KEY: required for OpenAI embeddings.OPENAI_BASE_URL: optional OpenAI-compatible base URL.LLM_PROVIDER: provider passed to llm-gateway, defaultopenai.LLM_MODEL: model passed to llm-gateway, defaultgpt-4.1-mini.LLM_TEMPERATURE: default0.1.LLM_MAX_OUTPUT_TOKENS: default900.LLM_TIMEOUT_MS: default120000.ASSISTANT_HTTP_TIMEOUT_MS: timeout for data-service and embedding calls, default15000.STRUCTURED_CONTEXT_MAX_CHARS: max structured context sent to LLM, default5000.RAG_CHUNKS_MAX_CHARS: max document excerpt context sent to LLM, default9000.
Notes
Qdrant searches include the user access scope as metadata filters. Search
results are also rechecked against data-service /documents/:id/access before
chunks are returned to the LLM or used to create a download token.
Document download links are generated by docs-service only after the
access check succeeds. The returned URL points to the public token route
/docs-service/dl/:token; the token is short lived, has a small bounded
number of allowed downloads, and no browser session is required to consume it.
The orchestrator also exposes the link as a top-level actions[] item so
transport gateways do not need to parse the LLM answer text.
Questions about operational bill data, such as the amount, date or status of
the latest gas, electricity, water, internet or supplier bill, are answered via
the structured data-service /reconciliation/utility-bills API through
get_latest_utility_bill. A document download link is generated only when the
user explicitly asks to download, view or receive the document.
For transport-originated requests, callers should pass channel and
correlationId and may also set X-Correlation-Id. The same correlation id is
included in response metadata and propagated to docs-service when a download
token is created.
When the user asks for the latest or most recent document, the orchestrator selects among accessible candidates using document date metadata before falling back to the numeric id.