"""OpenRouter provider โ€” heterogeneous voting slot. Endpoint: https://openrouter.ai/api/v1 (OpenAI-compatible). OpenRouter multiplexes many model families (Anthropic / Google / Qwen / DeepSeek / GLM / Llama) behind a single API; the `:free` model variants are rate-limited but cost $0. Used here to give the self-consistency ensemble a generator from a different family than codestral (Mistral), which is the heterogeneity that plain config F was missing โ€” see `docs/v18_residue_patterns.md` ยง "Patch P4 โ€” CSC merge-revision". Auth: API key from `OPENROUTER_API_KEY` (or `NL_SQL_OPENROUTER_API_KEY`). """ from __future__ import annotations from openai import OpenAI from nl_sql.llm.providers._openai_compat import chat_complete from nl_sql.llm.providers.base import ( GenerateRequest, GenerateResponse, ProviderError, ) class OpenRouterProvider: name: str = "openrouter" def __init__( self, api_key: str, model: str = "deepseek/deepseek-v4-flash:free", base_url: str = "https://openrouter.ai/api/v1", ) -> None: if not api_key: raise ProviderError("OpenRouterProvider requires non-empty api_key") self.model = model self._client = OpenAI(api_key=api_key, base_url=base_url) def generate(self, req: GenerateRequest) -> GenerateResponse: return chat_complete(self._client, self.model, req)