tdfs4ds.serve.openai_router¶
tdfs4ds.serve.openai_router
¶
OpenAI-compatible HTTP surface for the two tdfs4ds agents.
Exposes the minimal slice of the OpenAI API that chat clients (the openai
SDK, Open WebUI, LibreChat, …) need:
GET /v1/models → list the two model ids
POST /v1/chat/completions → run the selected agent
The model field of a chat-completions request selects the agent:
"tdfs4ds-consumer" → consumer_agent() (feature-store RAG)
"tdfs4ds-query-optimizer" → query_optimizer_agent() (SQL EXPLAIN/optimize)
The latest user message becomes the agent's question. For the query
optimizer the user pastes the SQL inline in that message — the optimizer
parses it out of the turn, so no schema extension is needed.
Conversation memory is owned by the agents (LangGraph MemorySaver keyed by
thread_id). A request that wants continuity sets the OpenAI user field
to a stable id; otherwise each request gets a fresh thread_id and is
effectively stateless.
ChatMessage
¶
ChatCompletionRequest
¶
Bases: BaseModel
_latest_user_message
¶
Return the content of the last message with role 'user'.
_thread_id
¶
Stable thread id from the OpenAI user field, else a fresh uuid.
_run_agent
¶
Dispatch to the selected agent. Returns (answer, token_usage).
base_url (e.g. http://host:8000) is used to turn the query
optimizer's relative report_path into a clickable download URL.
_link_report
¶
Rewrite the optimizer's `report_path` reference into a download URL.
node_synthesize renders **Full report:** `{domain}/{file}.md`; here
we turn it into **Full report:** {base_url}/reports/{domain}/{file}.md so
the user can click / curl it. No-op when there is no report path or no base.
_stream_response
¶
Emit the answer as a single OpenAI chat.completion.chunk + [DONE].
The agents return a complete string (not a token stream), so v1 streaming
sends one content chunk. Clients that require stream:true still work.