aiecs 1.2.0__py3-none-any.whl → 1.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of aiecs might be problematic. Click here for more details.
- aiecs/__init__.py +1 -1
- aiecs/aiecs_client.py +1 -1
- aiecs/config/config.py +36 -0
- aiecs/infrastructure/monitoring/__init__.py +22 -0
- aiecs/infrastructure/monitoring/global_metrics_manager.py +207 -0
- aiecs/infrastructure/persistence/file_storage.py +41 -28
- aiecs/llm/__init__.py +44 -7
- aiecs/llm/callbacks/__init__.py +12 -0
- aiecs/llm/{custom_callbacks.py → callbacks/custom_callbacks.py} +1 -1
- aiecs/llm/client_factory.py +23 -6
- aiecs/llm/clients/__init__.py +35 -0
- aiecs/llm/{base_client.py → clients/base_client.py} +73 -1
- aiecs/llm/{googleai_client.py → clients/googleai_client.py} +19 -15
- aiecs/llm/{openai_client.py → clients/openai_client.py} +9 -14
- aiecs/llm/{vertex_client.py → clients/vertex_client.py} +15 -15
- aiecs/llm/{xai_client.py → clients/xai_client.py} +36 -50
- aiecs/llm/config/__init__.py +54 -0
- aiecs/llm/config/config_loader.py +275 -0
- aiecs/llm/config/config_validator.py +237 -0
- aiecs/llm/config/model_config.py +132 -0
- aiecs/llm/utils/__init__.py +11 -0
- aiecs/llm/utils/validate_config.py +91 -0
- aiecs/main.py +32 -2
- aiecs/tools/tool_executor/__init__.py +2 -2
- aiecs/tools/tool_executor/tool_executor.py +3 -3
- {aiecs-1.2.0.dist-info → aiecs-1.2.1.dist-info}/METADATA +1 -1
- {aiecs-1.2.0.dist-info → aiecs-1.2.1.dist-info}/RECORD +31 -22
- {aiecs-1.2.0.dist-info → aiecs-1.2.1.dist-info}/WHEEL +0 -0
- {aiecs-1.2.0.dist-info → aiecs-1.2.1.dist-info}/entry_points.txt +0 -0
- {aiecs-1.2.0.dist-info → aiecs-1.2.1.dist-info}/licenses/LICENSE +0 -0
- {aiecs-1.2.0.dist-info → aiecs-1.2.1.dist-info}/top_level.txt +0 -0
|
@@ -6,6 +6,12 @@ import logging
|
|
|
6
6
|
|
|
7
7
|
logger = logging.getLogger(__name__)
|
|
8
8
|
|
|
9
|
+
# Lazy import to avoid circular dependency
|
|
10
|
+
def _get_config_loader():
|
|
11
|
+
"""Lazy import of config loader to avoid circular dependency"""
|
|
12
|
+
from aiecs.llm.config import get_llm_config_loader
|
|
13
|
+
return get_llm_config_loader()
|
|
14
|
+
|
|
9
15
|
@dataclass
|
|
10
16
|
class LLMMessage:
|
|
11
17
|
role: str # "system", "user", "assistant"
|
|
@@ -93,8 +99,74 @@ class BaseLLMClient(ABC):
|
|
|
93
99
|
return len(text) // 4
|
|
94
100
|
|
|
95
101
|
def _estimate_cost(self, model: str, input_tokens: int, output_tokens: int, token_costs: Dict) -> float:
|
|
96
|
-
"""
|
|
102
|
+
"""
|
|
103
|
+
Estimate the cost of the API call.
|
|
104
|
+
|
|
105
|
+
DEPRECATED: Use _estimate_cost_from_config instead for config-based cost estimation.
|
|
106
|
+
This method is kept for backward compatibility.
|
|
107
|
+
"""
|
|
97
108
|
if model in token_costs:
|
|
98
109
|
costs = token_costs[model]
|
|
99
110
|
return (input_tokens * costs["input"] + output_tokens * costs["output"]) / 1000
|
|
100
111
|
return 0.0
|
|
112
|
+
|
|
113
|
+
def _estimate_cost_from_config(self, model_name: str, input_tokens: int, output_tokens: int) -> float:
|
|
114
|
+
"""
|
|
115
|
+
Estimate the cost using configuration-based pricing.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
model_name: Name of the model
|
|
119
|
+
input_tokens: Number of input tokens
|
|
120
|
+
output_tokens: Number of output tokens
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
Estimated cost in USD
|
|
124
|
+
"""
|
|
125
|
+
try:
|
|
126
|
+
loader = _get_config_loader()
|
|
127
|
+
model_config = loader.get_model_config(self.provider_name, model_name)
|
|
128
|
+
|
|
129
|
+
if model_config and model_config.costs:
|
|
130
|
+
input_cost = (input_tokens * model_config.costs.input) / 1000
|
|
131
|
+
output_cost = (output_tokens * model_config.costs.output) / 1000
|
|
132
|
+
return input_cost + output_cost
|
|
133
|
+
else:
|
|
134
|
+
self.logger.warning(
|
|
135
|
+
f"No cost configuration found for model {model_name} "
|
|
136
|
+
f"in provider {self.provider_name}"
|
|
137
|
+
)
|
|
138
|
+
return 0.0
|
|
139
|
+
except Exception as e:
|
|
140
|
+
self.logger.warning(f"Failed to estimate cost from config: {e}")
|
|
141
|
+
return 0.0
|
|
142
|
+
|
|
143
|
+
def _get_model_config(self, model_name: str):
|
|
144
|
+
"""
|
|
145
|
+
Get model configuration from the config loader.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
model_name: Name of the model
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
ModelConfig if found, None otherwise
|
|
152
|
+
"""
|
|
153
|
+
try:
|
|
154
|
+
loader = _get_config_loader()
|
|
155
|
+
return loader.get_model_config(self.provider_name, model_name)
|
|
156
|
+
except Exception as e:
|
|
157
|
+
self.logger.warning(f"Failed to get model config: {e}")
|
|
158
|
+
return None
|
|
159
|
+
|
|
160
|
+
def _get_default_model(self) -> Optional[str]:
|
|
161
|
+
"""
|
|
162
|
+
Get the default model for this provider from configuration.
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
Default model name if configured, None otherwise
|
|
166
|
+
"""
|
|
167
|
+
try:
|
|
168
|
+
loader = _get_config_loader()
|
|
169
|
+
return loader.get_default_model(self.provider_name)
|
|
170
|
+
except Exception as e:
|
|
171
|
+
self.logger.warning(f"Failed to get default model: {e}")
|
|
172
|
+
return None
|
|
@@ -6,7 +6,7 @@ from typing import Dict, Any, Optional, List, AsyncGenerator
|
|
|
6
6
|
import google.generativeai as genai
|
|
7
7
|
from google.generativeai.types import GenerationConfig, HarmCategory, HarmBlockThreshold
|
|
8
8
|
|
|
9
|
-
from aiecs.llm.base_client import BaseLLMClient, LLMMessage, LLMResponse, ProviderNotAvailableError, RateLimitError
|
|
9
|
+
from aiecs.llm.clients.base_client import BaseLLMClient, LLMMessage, LLMResponse, ProviderNotAvailableError, RateLimitError
|
|
10
10
|
from aiecs.config.config import get_settings
|
|
11
11
|
|
|
12
12
|
logger = logging.getLogger(__name__)
|
|
@@ -20,12 +20,6 @@ class GoogleAIClient(BaseLLMClient):
|
|
|
20
20
|
self._initialized = False
|
|
21
21
|
self.client = None
|
|
22
22
|
|
|
23
|
-
# Token cost estimates for Gemini 2.5 series
|
|
24
|
-
self.token_costs = {
|
|
25
|
-
"gemini-2.5-pro": {"input": 0.00125, "output": 0.00375},
|
|
26
|
-
"gemini-2.5-flash": {"input": 0.000075, "output": 0.0003},
|
|
27
|
-
}
|
|
28
|
-
|
|
29
23
|
def _init_google_ai(self):
|
|
30
24
|
"""Lazy initialization of Google AI SDK"""
|
|
31
25
|
if not self._initialized:
|
|
@@ -50,7 +44,14 @@ class GoogleAIClient(BaseLLMClient):
|
|
|
50
44
|
) -> LLMResponse:
|
|
51
45
|
"""Generate text using Google AI"""
|
|
52
46
|
self._init_google_ai()
|
|
53
|
-
|
|
47
|
+
|
|
48
|
+
# Get model name from config if not provided
|
|
49
|
+
model_name = model or self._get_default_model() or "gemini-2.5-pro"
|
|
50
|
+
|
|
51
|
+
# Get model config for default parameters
|
|
52
|
+
model_config = self._get_model_config(model_name)
|
|
53
|
+
if model_config and max_tokens is None:
|
|
54
|
+
max_tokens = model_config.default_params.max_tokens
|
|
54
55
|
|
|
55
56
|
try:
|
|
56
57
|
model_instance = genai.GenerativeModel(model_name)
|
|
@@ -88,12 +89,8 @@ class GoogleAIClient(BaseLLMClient):
|
|
|
88
89
|
completion_tokens = response.usage_metadata.candidates_token_count
|
|
89
90
|
total_tokens = response.usage_metadata.total_token_count
|
|
90
91
|
|
|
91
|
-
cost
|
|
92
|
-
|
|
93
|
-
prompt_tokens,
|
|
94
|
-
completion_tokens,
|
|
95
|
-
self.token_costs
|
|
96
|
-
)
|
|
92
|
+
# Use config-based cost estimation
|
|
93
|
+
cost = self._estimate_cost_from_config(model_name, prompt_tokens, completion_tokens)
|
|
97
94
|
|
|
98
95
|
return LLMResponse(
|
|
99
96
|
content=content,
|
|
@@ -121,7 +118,14 @@ class GoogleAIClient(BaseLLMClient):
|
|
|
121
118
|
) -> AsyncGenerator[str, None]:
|
|
122
119
|
"""Stream text generation using Google AI"""
|
|
123
120
|
self._init_google_ai()
|
|
124
|
-
|
|
121
|
+
|
|
122
|
+
# Get model name from config if not provided
|
|
123
|
+
model_name = model or self._get_default_model() or "gemini-2.5-pro"
|
|
124
|
+
|
|
125
|
+
# Get model config for default parameters
|
|
126
|
+
model_config = self._get_model_config(model_name)
|
|
127
|
+
if model_config and max_tokens is None:
|
|
128
|
+
max_tokens = model_config.default_params.max_tokens
|
|
125
129
|
|
|
126
130
|
try:
|
|
127
131
|
model_instance = genai.GenerativeModel(model_name)
|
|
@@ -5,7 +5,7 @@ from openai import AsyncOpenAI
|
|
|
5
5
|
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
|
|
6
6
|
import httpx
|
|
7
7
|
|
|
8
|
-
from aiecs.llm.base_client import BaseLLMClient, LLMMessage, LLMResponse, ProviderNotAvailableError, RateLimitError
|
|
8
|
+
from aiecs.llm.clients.base_client import BaseLLMClient, LLMMessage, LLMResponse, ProviderNotAvailableError, RateLimitError
|
|
9
9
|
from aiecs.config.config import get_settings
|
|
10
10
|
|
|
11
11
|
logger = logging.getLogger(__name__)
|
|
@@ -18,15 +18,6 @@ class OpenAIClient(BaseLLMClient):
|
|
|
18
18
|
self.settings = get_settings()
|
|
19
19
|
self._client: Optional[AsyncOpenAI] = None
|
|
20
20
|
|
|
21
|
-
# Token cost estimates (USD per 1K tokens)
|
|
22
|
-
self.token_costs = {
|
|
23
|
-
"gpt-4": {"input": 0.03, "output": 0.06},
|
|
24
|
-
"gpt-4-turbo": {"input": 0.01, "output": 0.03},
|
|
25
|
-
"gpt-3.5-turbo": {"input": 0.0015, "output": 0.002},
|
|
26
|
-
"gpt-4o": {"input": 0.005, "output": 0.015},
|
|
27
|
-
"gpt-4o-mini": {"input": 0.00015, "output": 0.0006},
|
|
28
|
-
}
|
|
29
|
-
|
|
30
21
|
def _get_client(self) -> AsyncOpenAI:
|
|
31
22
|
"""Lazy initialization of OpenAI client"""
|
|
32
23
|
if not self._client:
|
|
@@ -50,7 +41,9 @@ class OpenAIClient(BaseLLMClient):
|
|
|
50
41
|
) -> LLMResponse:
|
|
51
42
|
"""Generate text using OpenAI API"""
|
|
52
43
|
client = self._get_client()
|
|
53
|
-
|
|
44
|
+
|
|
45
|
+
# Get model name from config if not provided
|
|
46
|
+
model = model or self._get_default_model() or "gpt-4-turbo"
|
|
54
47
|
|
|
55
48
|
# Convert to OpenAI message format
|
|
56
49
|
openai_messages = [{"role": msg.role, "content": msg.content} for msg in messages]
|
|
@@ -67,10 +60,10 @@ class OpenAIClient(BaseLLMClient):
|
|
|
67
60
|
content = response.choices[0].message.content
|
|
68
61
|
tokens_used = response.usage.total_tokens if response.usage else None
|
|
69
62
|
|
|
70
|
-
# Estimate cost
|
|
63
|
+
# Estimate cost using config
|
|
71
64
|
input_tokens = response.usage.prompt_tokens if response.usage else 0
|
|
72
65
|
output_tokens = response.usage.completion_tokens if response.usage else 0
|
|
73
|
-
cost = self.
|
|
66
|
+
cost = self._estimate_cost_from_config(model, input_tokens, output_tokens)
|
|
74
67
|
|
|
75
68
|
return LLMResponse(
|
|
76
69
|
content=content,
|
|
@@ -95,7 +88,9 @@ class OpenAIClient(BaseLLMClient):
|
|
|
95
88
|
) -> AsyncGenerator[str, None]:
|
|
96
89
|
"""Stream text using OpenAI API"""
|
|
97
90
|
client = self._get_client()
|
|
98
|
-
|
|
91
|
+
|
|
92
|
+
# Get model name from config if not provided
|
|
93
|
+
model = model or self._get_default_model() or "gpt-4-turbo"
|
|
99
94
|
|
|
100
95
|
openai_messages = [{"role": msg.role, "content": msg.content} for msg in messages]
|
|
101
96
|
|
|
@@ -6,7 +6,7 @@ import vertexai
|
|
|
6
6
|
from vertexai.generative_models import GenerativeModel, HarmCategory, HarmBlockThreshold, GenerationConfig, SafetySetting
|
|
7
7
|
from google.oauth2 import service_account
|
|
8
8
|
|
|
9
|
-
from aiecs.llm.base_client import BaseLLMClient, LLMMessage, LLMResponse, ProviderNotAvailableError, RateLimitError
|
|
9
|
+
from aiecs.llm.clients.base_client import BaseLLMClient, LLMMessage, LLMResponse, ProviderNotAvailableError, RateLimitError
|
|
10
10
|
from aiecs.config.config import get_settings
|
|
11
11
|
|
|
12
12
|
logger = logging.getLogger(__name__)
|
|
@@ -19,12 +19,6 @@ class VertexAIClient(BaseLLMClient):
|
|
|
19
19
|
self.settings = get_settings()
|
|
20
20
|
self._initialized = False
|
|
21
21
|
|
|
22
|
-
# Token cost estimates (USD per 1K tokens)
|
|
23
|
-
self.token_costs = {
|
|
24
|
-
"gemini-2.5-pro": {"input": 0.00125, "output": 0.00375},
|
|
25
|
-
"gemini-2.5-flash": {"input": 0.000075, "output": 0.0003},
|
|
26
|
-
}
|
|
27
|
-
|
|
28
22
|
def _init_vertex_ai(self):
|
|
29
23
|
"""Lazy initialization of Vertex AI with proper authentication"""
|
|
30
24
|
if not self._initialized:
|
|
@@ -71,7 +65,14 @@ class VertexAIClient(BaseLLMClient):
|
|
|
71
65
|
) -> LLMResponse:
|
|
72
66
|
"""Generate text using Vertex AI"""
|
|
73
67
|
self._init_vertex_ai()
|
|
74
|
-
|
|
68
|
+
|
|
69
|
+
# Get model name from config if not provided
|
|
70
|
+
model_name = model or self._get_default_model() or "gemini-2.5-pro"
|
|
71
|
+
|
|
72
|
+
# Get model config for default parameters
|
|
73
|
+
model_config = self._get_model_config(model_name)
|
|
74
|
+
if model_config and max_tokens is None:
|
|
75
|
+
max_tokens = model_config.default_params.max_tokens
|
|
75
76
|
|
|
76
77
|
try:
|
|
77
78
|
# Use the stable Vertex AI API
|
|
@@ -163,13 +164,12 @@ class VertexAIClient(BaseLLMClient):
|
|
|
163
164
|
content = "[Response error: Cannot get the response text. Multiple content parts are not supported.]"
|
|
164
165
|
|
|
165
166
|
# Vertex AI doesn't provide detailed token usage in the response
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
)
|
|
167
|
+
input_tokens = self._count_tokens_estimate(prompt)
|
|
168
|
+
output_tokens = self._count_tokens_estimate(content)
|
|
169
|
+
tokens_used = input_tokens + output_tokens
|
|
170
|
+
|
|
171
|
+
# Use config-based cost estimation
|
|
172
|
+
cost = self._estimate_cost_from_config(model_name, input_tokens, output_tokens)
|
|
173
173
|
|
|
174
174
|
return LLMResponse(
|
|
175
175
|
content=content,
|
|
@@ -2,10 +2,17 @@ import json
|
|
|
2
2
|
import asyncio
|
|
3
3
|
import logging
|
|
4
4
|
from typing import Dict, Any, Optional, List, AsyncGenerator
|
|
5
|
+
|
|
6
|
+
# Lazy import to avoid circular dependency
|
|
7
|
+
def _get_config_loader():
|
|
8
|
+
"""Lazy import of config loader to avoid circular dependency"""
|
|
9
|
+
from aiecs.llm.config import get_llm_config_loader
|
|
10
|
+
return get_llm_config_loader()
|
|
11
|
+
|
|
5
12
|
from openai import AsyncOpenAI
|
|
6
13
|
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
|
|
7
14
|
|
|
8
|
-
from aiecs.llm.base_client import BaseLLMClient, LLMMessage, LLMResponse, ProviderNotAvailableError, RateLimitError
|
|
15
|
+
from aiecs.llm.clients.base_client import BaseLLMClient, LLMMessage, LLMResponse, ProviderNotAvailableError, RateLimitError
|
|
9
16
|
from aiecs.config.config import get_settings
|
|
10
17
|
|
|
11
18
|
logger = logging.getLogger(__name__)
|
|
@@ -17,51 +24,7 @@ class XAIClient(BaseLLMClient):
|
|
|
17
24
|
super().__init__("xAI")
|
|
18
25
|
self.settings = get_settings()
|
|
19
26
|
self._openai_client: Optional[AsyncOpenAI] = None
|
|
20
|
-
|
|
21
|
-
# Enhanced model mapping for all Grok models
|
|
22
|
-
self.model_map = {
|
|
23
|
-
# Legacy Grok models
|
|
24
|
-
"grok-beta": "grok-beta",
|
|
25
|
-
"grok": "grok-beta",
|
|
26
|
-
|
|
27
|
-
# Current Grok models
|
|
28
|
-
"Grok 2": "grok-2",
|
|
29
|
-
"grok-2": "grok-2",
|
|
30
|
-
"Grok 2 Vision": "grok-2-vision",
|
|
31
|
-
"grok-2-vision": "grok-2-vision",
|
|
32
|
-
|
|
33
|
-
# Grok 3 models
|
|
34
|
-
"Grok 3 Normal": "grok-3",
|
|
35
|
-
"grok-3": "grok-3",
|
|
36
|
-
"Grok 3 Fast": "grok-3-fast",
|
|
37
|
-
"grok-3-fast": "grok-3-fast",
|
|
38
|
-
|
|
39
|
-
# Grok 3 Mini models
|
|
40
|
-
"Grok 3 Mini Normal": "grok-3-mini",
|
|
41
|
-
"grok-3-mini": "grok-3-mini",
|
|
42
|
-
"Grok 3 Mini Fast": "grok-3-mini-fast",
|
|
43
|
-
"grok-3-mini-fast": "grok-3-mini-fast",
|
|
44
|
-
|
|
45
|
-
# Grok 3 Reasoning models
|
|
46
|
-
"Grok 3 Reasoning Normal": "grok-3-reasoning",
|
|
47
|
-
"grok-3-reasoning": "grok-3-reasoning",
|
|
48
|
-
"Grok 3 Reasoning Fast": "grok-3-reasoning-fast",
|
|
49
|
-
"grok-3-reasoning-fast": "grok-3-reasoning-fast",
|
|
50
|
-
|
|
51
|
-
# Grok 3 Mini Reasoning models
|
|
52
|
-
"Grok 3 Mini Reasoning Normal": "grok-3-mini-reasoning",
|
|
53
|
-
"grok-3-mini-reasoning": "grok-3-mini-reasoning",
|
|
54
|
-
"Grok 3 Mini Reasoning Fast": "grok-3-mini-reasoning-fast",
|
|
55
|
-
"grok-3-mini-reasoning-fast": "grok-3-mini-reasoning-fast",
|
|
56
|
-
|
|
57
|
-
# Grok 4 models
|
|
58
|
-
"Grok 4 Normal": "grok-4",
|
|
59
|
-
"grok-4": "grok-4",
|
|
60
|
-
"Grok 4 Fast": "grok-4-fast",
|
|
61
|
-
"grok-4-fast": "grok-4-fast",
|
|
62
|
-
"Grok 4 0709": "grok-4-0709",
|
|
63
|
-
"grok-4-0709": "grok-4-0709",
|
|
64
|
-
}
|
|
27
|
+
self._model_map: Optional[Dict[str, str]] = None
|
|
65
28
|
|
|
66
29
|
def _get_openai_client(self) -> AsyncOpenAI:
|
|
67
30
|
"""Lazy initialization of OpenAI client for XAI"""
|
|
@@ -81,6 +44,21 @@ class XAIClient(BaseLLMClient):
|
|
|
81
44
|
if not api_key:
|
|
82
45
|
raise ProviderNotAvailableError("xAI API key not configured")
|
|
83
46
|
return api_key
|
|
47
|
+
|
|
48
|
+
def _get_model_map(self) -> Dict[str, str]:
|
|
49
|
+
"""Get model mappings from configuration"""
|
|
50
|
+
if self._model_map is None:
|
|
51
|
+
try:
|
|
52
|
+
loader = _get_config_loader()
|
|
53
|
+
provider_config = loader.get_provider_config("xAI")
|
|
54
|
+
if provider_config and provider_config.model_mappings:
|
|
55
|
+
self._model_map = provider_config.model_mappings
|
|
56
|
+
else:
|
|
57
|
+
self._model_map = {}
|
|
58
|
+
except Exception as e:
|
|
59
|
+
self.logger.warning(f"Failed to load model mappings from config: {e}")
|
|
60
|
+
self._model_map = {}
|
|
61
|
+
return self._model_map
|
|
84
62
|
|
|
85
63
|
@retry(
|
|
86
64
|
stop=stop_after_attempt(3),
|
|
@@ -103,8 +81,12 @@ class XAIClient(BaseLLMClient):
|
|
|
103
81
|
|
|
104
82
|
client = self._get_openai_client()
|
|
105
83
|
|
|
106
|
-
|
|
107
|
-
|
|
84
|
+
# Get model name from config if not provided
|
|
85
|
+
selected_model = model or self._get_default_model() or "grok-4"
|
|
86
|
+
|
|
87
|
+
# Get model mappings from config
|
|
88
|
+
model_map = self._get_model_map()
|
|
89
|
+
api_model = model_map.get(selected_model, selected_model)
|
|
108
90
|
|
|
109
91
|
# Convert to OpenAI format
|
|
110
92
|
openai_messages = [{"role": msg.role, "content": msg.content} for msg in messages]
|
|
@@ -151,8 +133,12 @@ class XAIClient(BaseLLMClient):
|
|
|
151
133
|
|
|
152
134
|
client = self._get_openai_client()
|
|
153
135
|
|
|
154
|
-
|
|
155
|
-
|
|
136
|
+
# Get model name from config if not provided
|
|
137
|
+
selected_model = model or self._get_default_model() or "grok-4"
|
|
138
|
+
|
|
139
|
+
# Get model mappings from config
|
|
140
|
+
model_map = self._get_model_map()
|
|
141
|
+
api_model = model_map.get(selected_model, selected_model)
|
|
156
142
|
|
|
157
143
|
# Convert to OpenAI format
|
|
158
144
|
openai_messages = [{"role": msg.role, "content": msg.content} for msg in messages]
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""
|
|
2
|
+
LLM Configuration management.
|
|
3
|
+
|
|
4
|
+
This package handles configuration loading, validation, and management
|
|
5
|
+
for all LLM providers and models.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .model_config import (
|
|
9
|
+
ModelCostConfig,
|
|
10
|
+
ModelCapabilities,
|
|
11
|
+
ModelDefaultParams,
|
|
12
|
+
ModelConfig,
|
|
13
|
+
ProviderConfig,
|
|
14
|
+
LLMModelsConfig
|
|
15
|
+
)
|
|
16
|
+
from .config_loader import (
|
|
17
|
+
LLMConfigLoader,
|
|
18
|
+
get_llm_config_loader,
|
|
19
|
+
get_llm_config,
|
|
20
|
+
reload_llm_config
|
|
21
|
+
)
|
|
22
|
+
from .config_validator import (
|
|
23
|
+
ConfigValidationError,
|
|
24
|
+
validate_cost_config,
|
|
25
|
+
validate_model_config,
|
|
26
|
+
validate_provider_config,
|
|
27
|
+
validate_llm_config,
|
|
28
|
+
validate_config_file
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
__all__ = [
|
|
32
|
+
# Configuration models
|
|
33
|
+
"ModelCostConfig",
|
|
34
|
+
"ModelCapabilities",
|
|
35
|
+
"ModelDefaultParams",
|
|
36
|
+
"ModelConfig",
|
|
37
|
+
"ProviderConfig",
|
|
38
|
+
"LLMModelsConfig",
|
|
39
|
+
|
|
40
|
+
# Config loader
|
|
41
|
+
"LLMConfigLoader",
|
|
42
|
+
"get_llm_config_loader",
|
|
43
|
+
"get_llm_config",
|
|
44
|
+
"reload_llm_config",
|
|
45
|
+
|
|
46
|
+
# Validation
|
|
47
|
+
"ConfigValidationError",
|
|
48
|
+
"validate_cost_config",
|
|
49
|
+
"validate_model_config",
|
|
50
|
+
"validate_provider_config",
|
|
51
|
+
"validate_llm_config",
|
|
52
|
+
"validate_config_file",
|
|
53
|
+
]
|
|
54
|
+
|