From d4fbc258975cbb3b20734d540d132c6bd1031ac2 Mon Sep 17 00:00:00 2001 From: Younes Abouelnagah Date: Tue, 5 May 2026 10:39:57 -0400 Subject: [PATCH] fix: relax service_tier validation for OpenRouter responses OpenRouter returns service_tier: "standard" which falls outside the OpenAI SDK's Literal["auto","default","flex","scale","priority"]. any-llm-sdk inherits this strict type and revalidates responses, causing propose_truth to fail with a Pydantic ValidationError. Monkey-patch ChatCompletion.service_tier to accept str | None at module load. Includes a regression test. Co-Authored-By: Claude Opus 4.6 --- src/fava_trails/llm/client.py | 10 ++++++++++ tests/test_llm_client.py | 21 +++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/fava_trails/llm/client.py b/src/fava_trails/llm/client.py index c226867..91bec6c 100644 --- a/src/fava_trails/llm/client.py +++ b/src/fava_trails/llm/client.py @@ -15,6 +15,16 @@ # Enable unified exception hierarchy across all providers os.environ.setdefault("ANY_LLM_UNIFIED_EXCEPTIONS", "1") +# Relax service_tier validation. OpenRouter may return values outside the +# OpenAI SDK Literal set, e.g. "standard", and any-llm revalidates the response +# against this model before returning it. +from any_llm.types.completion import ChatCompletion as _ChatCompletion + +_service_tier = _ChatCompletion.model_fields.get("service_tier") +if _service_tier is not None: + _service_tier.annotation = str | None + _ChatCompletion.model_rebuild(force=True) + logger = logging.getLogger(__name__) diff --git a/tests/test_llm_client.py b/tests/test_llm_client.py index d22b16d..cdc240d 100644 --- a/tests/test_llm_client.py +++ b/tests/test_llm_client.py @@ -4,6 +4,7 @@ import pytest from any_llm.exceptions import AuthenticationError, RateLimitError +from any_llm.types.completion import ChatCompletion from fava_trails.llm.client import LLMClient, LLMError, LLMResponse @@ -165,3 +166,23 @@ async def test_api_key_passed_to_acompletion(client): call_kwargs = mock_acompletion.call_args.kwargs assert call_kwargs["api_key"] == "or-key" assert call_kwargs["provider"] == "openrouter" + + +def test_chatcompletion_accepts_nonstandard_service_tier(): + """Importing fava_trails.llm.client patches ChatCompletion to accept any service_tier string.""" + data = { + "id": "gen-test", + "choices": [ + { + "finish_reason": "stop", + "index": 0, + "message": {"role": "assistant", "content": "ok"}, + } + ], + "created": 1000000, + "model": "google/gemini-2.5-flash", + "object": "chat.completion", + "service_tier": "standard", + } + obj = ChatCompletion.model_validate(data) + assert obj.service_tier == "standard"