diff --git a/src/multi_swarm/llm/client.py b/src/multi_swarm/llm/client.py index 0af6913..1ea0183 100644 --- a/src/multi_swarm/llm/client.py +++ b/src/multi_swarm/llm/client.py @@ -1,6 +1,7 @@ from __future__ import annotations from dataclasses import dataclass +from typing import Any import openai from openai import OpenAI @@ -44,6 +45,10 @@ class CompletionResult: class LLMClient: + # Provider OpenRouter da escludere di default. Novita rifiuta /completions + # endpoint per modelli Qwen 2.x — vedi bug 2026-05-12. + DEFAULT_PROVIDER_IGNORE: tuple[str, ...] = ("Novita",) + def __init__( self, openrouter_api_key: str, @@ -53,6 +58,7 @@ class LLMClient: model_tier_c: str = MODEL_TIER_C, model_tier_d: str = MODEL_TIER_D, openrouter_base_url: str = OPENROUTER_BASE_URL, + provider_ignore: tuple[str, ...] | None = None, ) -> None: self.model_tier_s = model_tier_s self.model_tier_a = model_tier_a @@ -60,6 +66,9 @@ class LLMClient: self.model_tier_c = model_tier_c self.model_tier_d = model_tier_d self.openrouter_base_url = openrouter_base_url + self._provider_ignore = ( + provider_ignore if provider_ignore is not None else self.DEFAULT_PROVIDER_IGNORE + ) self._tier_models: dict[ModelTier, str] = { ModelTier.S: model_tier_s, ModelTier.A: model_tier_a, @@ -83,6 +92,9 @@ class LLMClient: max_tokens: int = 2000, ) -> CompletionResult: model = self._tier_models[genome.model_tier] + extra_body: dict[str, Any] = {} + if self._provider_ignore: + extra_body["provider"] = {"ignore": list(self._provider_ignore)} resp = self._client.chat.completions.create( model=model, messages=[ @@ -92,6 +104,7 @@ class LLMClient: temperature=genome.temperature, top_p=genome.top_p, max_tokens=max_tokens, + extra_body=extra_body or None, ) if not resp.choices or resp.choices[0].message.content is None: raise EmptyCompletionError(f"empty response from {model}")