Coverage for app \ llm \ ollama_client.py: 100%
25 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-02-24 13:18 +0530
« prev ^ index » next coverage.py v7.13.4, created at 2026-02-24 13:18 +0530
1import requests
3MAX_PROMPT_CHARS = 8000 # increase limit, phi3:mini can handle this
5def call_ollama(
6 prompt: str,
7 model: str = "phi3:mini",
8 temperature: float = 0.7,
9) -> str:
10 url = "http://localhost:11434/api/chat"
12 # Smart truncation: keep structure, trim only the papers section
13 if len(prompt) > MAX_PROMPT_CHARS:
14 prompt = _smart_truncate(prompt, MAX_PROMPT_CHARS)
16 payload = {
17 "model": model,
18 "messages": [
19 {
20 "role": "system",
21 "content": (
22 "You are a medical AI assistant. "
23 "Answer clearly, concisely, and safely. "
24 "If evidence is insufficient, say so."
25 ),
26 },
27 {
28 "role": "user",
29 "content": prompt,
30 },
31 ],
32 "options": {
33 "temperature": temperature,
34 },
35 "stream": False,
36 }
38 try:
39 response = requests.post(url, json=payload, timeout=560)
41 if response.status_code != 200:
42 return f"Ollama error {response.status_code}: {response.text}"
44 data = response.json()
45 return data["message"]["content"].strip()
47 except requests.exceptions.ConnectionError:
48 return "Error: Ollama is not running."
50 except Exception as e:
51 return f"Error calling Ollama: {e}"
54def _smart_truncate(prompt: str, max_chars: int) -> str:
55 """
56 Truncate only the LITERATURE section to preserve
57 patient, wearables, and medication data.
58 """
59 literature_marker = "RELEVANT MEDICAL LITERATURE"
60 guidelines_marker = "USER QUESTION"
62 if literature_marker in prompt and guidelines_marker in prompt:
63 before_lit = prompt[:prompt.index(literature_marker)]
64 from_question = prompt[prompt.index(guidelines_marker):]
65 # Trim literature, keep everything else intact
66 return before_lit + f"========================\n{literature_marker}\n========================\n[Truncated to fit context window]\n\n" + from_question
68 # Fallback: dumb truncation only if structure not found
69 return prompt[:max_chars]