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

1import requests 

2 

3MAX_PROMPT_CHARS = 8000 # increase limit, phi3:mini can handle this 

4 

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" 

11 

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) 

15 

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 } 

37 

38 try: 

39 response = requests.post(url, json=payload, timeout=560) 

40 

41 if response.status_code != 200: 

42 return f"Ollama error {response.status_code}: {response.text}" 

43 

44 data = response.json() 

45 return data["message"]["content"].strip() 

46 

47 except requests.exceptions.ConnectionError: 

48 return "Error: Ollama is not running." 

49 

50 except Exception as e: 

51 return f"Error calling Ollama: {e}" 

52 

53 

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" 

61 

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 

67 

68 # Fallback: dumb truncation only if structure not found 

69 return prompt[:max_chars]