66"""
77
88import json
9- from datetime import datetime , timedelta
9+ from datetime import UTC , datetime , timedelta
1010from pathlib import Path
1111from typing import Any
1212
1818class GroqModelDiscovery :
1919 """Discovers and caches Groq model capabilities dynamically."""
2020
21- # Cache file location
22- CACHE_FILE = Path (__file__ ).parent / ".groq_models_cache.json"
21+ # Cache file location - use local cache directory within models
22+ CACHE_FILE = Path (__file__ ).parent / ".cache" / " groq_models_cache.json"
2323 CACHE_DURATION = timedelta (hours = 24 ) # Refresh cache every 24 hours
2424
2525 # Models to skip from LLM list (audio, TTS, guards)
@@ -92,7 +92,7 @@ def get_models(self, *, force_refresh: bool = False) -> dict[str, dict[str, Any]
9292 "provider" : self ._get_provider_name (model_id ),
9393 "tool_calling" : supports_tools ,
9494 "preview" : "preview" in model_id .lower () or "/" in model_id ,
95- "last_tested" : datetime .now ().isoformat (),
95+ "last_tested" : datetime .now (UTC ).isoformat (),
9696 }
9797 logger .debug (f"{ model_id } : tool_calling={ supports_tools } " )
9898
@@ -102,17 +102,17 @@ def get_models(self, *, force_refresh: bool = False) -> dict[str, dict[str, Any]
102102 "name" : model_id ,
103103 "provider" : self ._get_provider_name (model_id ),
104104 "not_supported" : True ,
105- "last_tested" : datetime .now ().isoformat (),
105+ "last_tested" : datetime .now (UTC ).isoformat (),
106106 }
107107
108108 # Save to cache
109109 self ._save_cache (models_metadata )
110110
111- return models_metadata
112-
113- except Exception as e :
111+ except (requests .RequestException , KeyError , ValueError , ImportError ) as e :
114112 logger .exception (f"Error discovering models: { e } " )
115113 return self ._get_fallback_models ()
114+ else :
115+ return models_metadata
116116
117117 def _fetch_available_models (self ) -> list [str ]:
118118 """Fetch list of available models from Groq API."""
@@ -158,20 +158,20 @@ def _test_tool_calling(self, model_id: str) -> bool:
158158 messages = [{"role" : "user" , "content" : "test" }]
159159
160160 # Try to make a request with tools
161- response = client .chat .completions .create (
161+ client .chat .completions .create (
162162 model = model_id , messages = messages , tools = tools , tool_choice = "auto" , max_tokens = 10
163163 )
164164
165- return True
166-
167- except Exception as e :
165+ except (ImportError , AttributeError , TypeError , ValueError , RuntimeError , KeyError ) as e :
168166 error_msg = str (e ).lower ()
169167 # If error mentions tool calling, model doesn't support it
170168 if "tool" in error_msg :
171169 return False
172170 # Other errors might be rate limits, etc - be conservative
173171 logger .warning (f"Error testing { model_id } : { e } " )
174172 return False
173+ else :
174+ return True
175175
176176 def _get_provider_name (self , model_id : str ) -> str :
177177 """Extract provider name from model ID."""
@@ -202,12 +202,12 @@ def _load_cache(self) -> dict[str, dict] | None:
202202 return None
203203
204204 try :
205- with open ( self .CACHE_FILE ) as f :
205+ with self .CACHE_FILE . open ( ) as f :
206206 cache_data = json .load (f )
207207
208208 # Check cache age
209209 cache_time = datetime .fromisoformat (cache_data ["cached_at" ])
210- if datetime .now () - cache_time > self .CACHE_DURATION :
210+ if datetime .now (UTC ) - cache_time > self .CACHE_DURATION :
211211 logger .info ("Cache expired, will fetch fresh data" )
212212 return None
213213
@@ -220,15 +220,15 @@ def _load_cache(self) -> dict[str, dict] | None:
220220 def _save_cache (self , models_metadata : dict [str , dict ]) -> None :
221221 """Save model metadata to cache."""
222222 try :
223- cache_data = {"cached_at" : datetime .now ().isoformat (), "models" : models_metadata }
223+ cache_data = {"cached_at" : datetime .now (UTC ).isoformat (), "models" : models_metadata }
224224
225225 self .CACHE_FILE .parent .mkdir (parents = True , exist_ok = True )
226- with open ( self .CACHE_FILE , "w" ) as f :
226+ with self .CACHE_FILE . open ( "w" ) as f :
227227 json .dump (cache_data , f , indent = 2 )
228228
229229 logger .info (f"Cached { len (models_metadata )} models to { self .CACHE_FILE } " )
230230
231- except Exception as e :
231+ except ( OSError , TypeError , ValueError ) as e :
232232 logger .warning (f"Failed to save cache: { e } " )
233233
234234 def _get_fallback_models (self ) -> dict [str , dict ]:
0 commit comments