diff --git a/src/audita/framework/llm.py b/src/audita/framework/llm.py index 0350915..f2d88b9 100644 --- a/src/audita/framework/llm.py +++ b/src/audita/framework/llm.py @@ -6,6 +6,8 @@ from typing import Any, Optional, Sequence, Tuple from audita.core.config import AuditaConfig, DEFAULT_BASE_URL from audita.core.errors import AuditaLLMError +_NO_KEY_PLACEHOLDER = "audita-no-key-required" + class OpenAICompatibleStructuredLLMClient: def __init__(self) -> None: @@ -60,7 +62,7 @@ class OpenAICompatibleStructuredLLMClient: ) from exc openai_client = OpenAI( - api_key=config.api_key, + api_key=_client_api_key(config), base_url=config.base_url, timeout=config.llm_timeout_seconds, ) @@ -92,5 +94,15 @@ def _requires_api_key(config: AuditaConfig) -> bool: return _normalized_base_url(config.base_url) == _normalized_base_url(DEFAULT_BASE_URL) +def _client_api_key(config: AuditaConfig) -> str: + if config.api_key: + return config.api_key + if _requires_api_key(config): + raise AuditaLLMError( + "OpenRouter credentials are required but missing for the configured endpoint." + ) + return _NO_KEY_PLACEHOLDER + + def _normalized_base_url(base_url: str) -> str: return base_url.rstrip("/") diff --git a/tests/test_framework_llm.py b/tests/test_framework_llm.py index 0f34279..80f2402 100644 --- a/tests/test_framework_llm.py +++ b/tests/test_framework_llm.py @@ -223,7 +223,7 @@ def test_missing_api_key_is_allowed_for_nondefault_endpoint(monkeypatch): ), ) - assert openai_inits == [{"api_key": None, "base_url": "http://localhost:8000/v1", "timeout": 600}] + assert openai_inits == [{"api_key": "audita-no-key-required", "base_url": "http://localhost:8000/v1", "timeout": 600}] assert create_calls == [ { "model": "meta-llama/Llama-3.1-8B-Instruct",