diff --git a/promptlens/providers/http.py b/promptlens/providers/http.py index f1828e2..be7033d 100644 --- a/promptlens/providers/http.py +++ b/promptlens/providers/http.py @@ -5,6 +5,7 @@ from typing import Any, Dict, List, Optional import aiohttp +from aiohttp import ContentTypeError from promptlens.models.config import ProviderConfig from promptlens.models.result import ModelResponse @@ -59,6 +60,11 @@ def _extract_content(data: Dict[str, Any]) -> str: return "" + @staticmethod + def _extract_content_from_text_response(text: str) -> str: + """Extract usable content from plain-text HTTP responses.""" + return text.strip() + def __init__(self, config: ProviderConfig) -> None: """Initialize the HTTP provider. @@ -119,10 +125,14 @@ async def _make_request() -> ModelResponse: timeout=aiohttp.ClientTimeout(total=self.config.timeout), ) as response: response.raise_for_status() - data = await response.json() - - # Extract content (try common response formats) - content = self._extract_content(data) + try: + data = await response.json() + content = self._extract_content(data) + except ContentTypeError: + text = await response.text() + content = self._extract_content_from_text_response(text) + + # Extracted content from JSON shape or plain text body. # Local models typically don't provide token counts or cost return ModelResponse( diff --git a/tests/test_http_provider_response_parsing.py b/tests/test_http_provider_response_parsing.py index 0949b6e..8d82f20 100644 --- a/tests/test_http_provider_response_parsing.py +++ b/tests/test_http_provider_response_parsing.py @@ -57,3 +57,9 @@ def test_extract_content_returns_empty_for_unknown_shape() -> None: provider = _provider() assert provider._extract_content({"foo": "bar"}) == "" + + +def test_extract_content_from_text_response_strips_whitespace() -> None: + provider = _provider() + + assert provider._extract_content_from_text_response(" hello world\n") == "hello world"