Skip to main content

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 the QDRANT_COLLECTION.
  • llm-gateway: LLM provider abstraction.
  • OpenAI-compatible embedding provider for query embeddings.
  • docs-service: generates time-limited document download links when the assistant tool get_document_download_link is selected.

Environment Variables

  • DATA_SERVICE_URL: data-service base URL, default http://data-service:3003.
  • LLM_GATEWAY_URL: llm-gateway base URL, default http://llm-gateway:3005.
  • QDRANT_URL: Qdrant URL, default http://qdrant:6333.
  • QDRANT_API_KEY: optional Qdrant API key.
  • QDRANT_COLLECTION: collection name, default rental_documents.
  • QDRANT_MIN_SCORE: minimum similarity score, default 0.
  • ASSISTANT_QDRANT_DEBUG_SEARCH: when true, runs diagnostic relaxed searches if the filtered search returns no chunks.
  • ASSISTANT_CONTINUE_ON_QDRANT_ERROR_WITH_CONTEXT: when true, the assistant can answer from structured context if Qdrant search fails.
  • DEFAULT_TOP_K: default number of chunks to retrieve, default 8.
  • MAX_TOP_K: maximum accepted topK, default 20.
  • EMBEDDING_PROVIDER: currently openai.
  • EMBEDDING_MODEL: embedding model, default text-embedding-3-small.
  • EMBEDDING_DIMENSIONS: expected vector dimension, default 1536.
  • OPENAI_API_KEY: required for OpenAI embeddings.
  • OPENAI_BASE_URL: optional OpenAI-compatible base URL.
  • LLM_PROVIDER: provider passed to llm-gateway, default openai.
  • LLM_MODEL: model passed to llm-gateway, default gpt-4.1-mini.
  • LLM_TEMPERATURE: default 0.1.
  • LLM_MAX_OUTPUT_TOKENS: default 900.
  • LLM_TIMEOUT_MS: default 120000.
  • ASSISTANT_HTTP_TIMEOUT_MS: timeout for data-service and embedding calls, default 15000.
  • STRUCTURED_CONTEXT_MAX_CHARS: max structured context sent to LLM, default 5000.
  • RAG_CHUNKS_MAX_CHARS: max document excerpt context sent to LLM, default 9000.

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.