11"""Ollama client wrapper for LLM interactions."""
22
3+ from __future__ import annotations
4+
35import json
46import logging
57import os
6- from typing import Any
8+ from typing import Any , Literal
79
810try :
911 import ollama
@@ -30,14 +32,15 @@ def __init__(self, model: str | None = None, host: str | None = None):
3032 host: Optional Ollama host URL. Falls back to OLLAMA_HOST env var,
3133 then localhost:11434.
3234 """
33- self .model = model or os .getenv ("OLLAMA_MODEL" , "qwen2.5:7b" )
35+ default_model = os .getenv ("OLLAMA_MODEL" , "qwen2.5:7b" )
36+ self .model : str = model if model else default_model
3437 self .host = host or os .getenv ("OLLAMA_HOST" )
3538
39+ self ._client : ollama .Client | None = None
3640 if OLLAMA_AVAILABLE :
3741 client_kwargs = {"host" : self .host } if self .host else {}
3842 self ._client = ollama .Client (** client_kwargs )
3943 else :
40- self ._client = None
4144 logger .error ("Ollama library not installed. Install with: pip install ollama" )
4245
4346 def chat (
@@ -57,7 +60,7 @@ def chat(
5760 Returns:
5861 Response dict with 'message' containing 'content'
5962 """
60- if not OLLAMA_AVAILABLE :
63+ if not OLLAMA_AVAILABLE or not self . _client :
6164 raise RuntimeError ("Ollama library not available" )
6265
6366 try :
@@ -71,16 +74,13 @@ def chat(
7174 f"[LLM PROMPT] { last_msg .get ('content' , '' )[:500 ]} ..."
7275 ) # Log first 500 chars at debug level
7376
74- kwargs = {
75- "model" : self .model ,
76- "messages" : messages ,
77- "options" : {"temperature" : temperature },
78- }
79-
80- if format_json :
81- kwargs ["format" ] = "json"
82-
83- response = self ._client .chat (** kwargs )
77+ fmt : Literal ["" , "json" ] = "json" if format_json else ""
78+ response = self ._client .chat ( # type: ignore[call-overload]
79+ model = self .model ,
80+ messages = messages ,
81+ format = fmt ,
82+ options = {"temperature" : temperature },
83+ )
8484
8585 # Log the full response
8686 response_content = response .get ("message" , {}).get ("content" , "" )
@@ -93,7 +93,7 @@ def chat(
9393 logger .info ("[LLM RESPONSE CONTENT - END]" )
9494 logger .info ("=" * 80 )
9595
96- return response
96+ return dict ( response )
9797
9898 except Exception as e :
9999 logger .error (f"Error calling Ollama: { e } " )
@@ -122,7 +122,7 @@ def generate_completion(
122122
123123 messages = [{"role" : "user" , "content" : prompt }]
124124 response = self .chat (messages , format_json = format_json , temperature = temperature )
125- return response ["message" ]["content" ]
125+ return str ( response ["message" ]["content" ])
126126
127127 def extract_structured_data (
128128 self ,
@@ -152,7 +152,8 @@ def extract_structured_data(
152152 )
153153
154154 try :
155- return json .loads (response_text )
155+ result : dict [str , Any ] = json .loads (response_text )
156+ return result
156157 except json .JSONDecodeError as e :
157158 logger .error (f"Failed to parse JSON response: { response_text } " )
158159 logger .error (f"JSON error: { e } " )
0 commit comments