diff --git a/src/inputs/input.txt b/src/inputs/input.txt index faa55cd..e68385c 100644 --- a/src/inputs/input.txt +++ b/src/inputs/input.txt @@ -1 +1,10 @@ -Officer Voldemort here, at an incident reported at 456 Oak Street. Two victims, Mark Smith and Jane Doe. Medical aid rendered for minor lacerations. Handed off to Sheriff's Deputy Alvarez. End of transmission. +UC Vaccine Declination Statement + +Name/SID: Sarah Johnson, SID 4527891 +Job Title: Research Scientist +Department: Microbiology +Phone Number: 831-555-0142 +Email: sjohnson@ucsc.edu +Date: 03/15/2026 + +Signature: ________________________ \ No newline at end of file diff --git a/src/llm.py b/src/llm.py index 70937f9..7fcfa46 100644 --- a/src/llm.py +++ b/src/llm.py @@ -60,19 +60,36 @@ def main_loop(self): } try: - response = requests.post(ollama_url, json=payload) + response = requests.post(ollama_url, json=payload, timeout=30) response.raise_for_status() + json_data = response.json() except requests.exceptions.ConnectionError: raise ConnectionError( f"Could not connect to Ollama at {ollama_url}. " "Please ensure Ollama is running and accessible." ) + except requests.exceptions.Timeout as e: + raise TimeoutError( + f"Request to Ollama timed out for field '{field}' at {ollama_url}: {e}" + ) from e except requests.exceptions.HTTPError as e: - raise RuntimeError(f"Ollama returned an error: {e}") + raise RuntimeError( + f"Ollama returned an HTTP error for field '{field}': {e}" + ) + except requests.exceptions.RequestException as e: + raise RuntimeError( + f"Ollama request failed for field '{field}': {e}" + ) + except ValueError as e: + raise ValueError( + f"Invalid JSON response from Ollama for field '{field}': {e}" + ) - # parse response - json_data = response.json() - parsed_response = json_data["response"] + parsed_response = json_data.get("response") + if parsed_response is None: + raise ValueError( + f"Ollama response missing 'response' key for field '{field}'." + ) # print(parsed_response) self.add_response_to_json(field, parsed_response) diff --git a/src/test/test_llm_reliability.py b/src/test/test_llm_reliability.py new file mode 100644 index 0000000..065901a --- /dev/null +++ b/src/test/test_llm_reliability.py @@ -0,0 +1,66 @@ +import pytest +import requests + +from src.llm import LLM + + +class DummyResponse: + def __init__(self, status_error=None, json_data=None, json_error=None): + self._status_error = status_error + self._json_data = json_data + self._json_error = json_error + + def raise_for_status(self): + if self._status_error: + raise self._status_error + + def json(self): + if self._json_error: + raise self._json_error + return self._json_data + + +def make_llm(): + return LLM(transcript_text="incident text", target_fields={"name": "string"}) + + +def test_llm_timeout_raises_timeouterror(monkeypatch): + def fake_post(*args, **kwargs): + raise requests.exceptions.Timeout("timed out") + + monkeypatch.setattr(requests, "post", fake_post) + + with pytest.raises(TimeoutError, match="timed out"): + make_llm().main_loop() + + +def test_llm_http_error_raises_runtimeerror(monkeypatch): + http_error = requests.exceptions.HTTPError("500 Server Error") + + def fake_post(*args, **kwargs): + return DummyResponse(status_error=http_error) + + monkeypatch.setattr(requests, "post", fake_post) + + with pytest.raises(RuntimeError, match="HTTP error"): + make_llm().main_loop() + + +def test_llm_invalid_json_raises_valueerror(monkeypatch): + def fake_post(*args, **kwargs): + return DummyResponse(json_error=ValueError("bad json")) + + monkeypatch.setattr(requests, "post", fake_post) + + with pytest.raises(ValueError, match="Invalid JSON response"): + make_llm().main_loop() + + +def test_llm_missing_response_key_raises_valueerror(monkeypatch): + def fake_post(*args, **kwargs): + return DummyResponse(json_data={"other": "value"}) + + monkeypatch.setattr(requests, "post", fake_post) + + with pytest.raises(ValueError, match="missing 'response' key"): + make_llm().main_loop()