stratifyai 0.1.1__py3-none-any.whl → 0.1.3__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.
@@ -89,7 +89,28 @@ class OpenAICompatibleProvider(BaseProvider):
89
89
  # Build OpenAI-compatible request parameters
90
90
  messages = []
91
91
  for msg in request.messages:
92
- message_dict = {"role": msg.role, "content": msg.content}
92
+ # Check if message contains an image
93
+ if msg.has_image():
94
+ # Parse vision content
95
+ text_content, (mime_type, base64_data) = msg.parse_vision_content()
96
+
97
+ # Build content array for vision
98
+ content_parts = []
99
+ if text_content:
100
+ content_parts.append({"type": "text", "text": text_content})
101
+
102
+ # Add image in OpenAI format (data URL)
103
+ content_parts.append({
104
+ "type": "image_url",
105
+ "image_url": {
106
+ "url": f"data:{mime_type};base64,{base64_data}"
107
+ }
108
+ })
109
+
110
+ message_dict = {"role": msg.role, "content": content_parts}
111
+ else:
112
+ message_dict = {"role": msg.role, "content": msg.content}
113
+
93
114
  # Add cache_control if present and model supports caching
94
115
  if msg.cache_control and self.supports_caching(request.model):
95
116
  message_dict["cache_control"] = msg.cache_control
@@ -147,14 +168,29 @@ class OpenAICompatibleProvider(BaseProvider):
147
168
  raise InsufficientBalanceError(self.provider_name)
148
169
  elif "invalid_api_key" in error_msg.lower() or "unauthorized" in error_msg.lower() or (hasattr(e, 'status_code') and e.status_code == 401):
149
170
  raise AuthenticationError(self.provider_name)
171
+ # Check for vision-related errors
172
+ elif "image" in error_msg.lower() and ("not supported" in error_msg.lower() or "invalid" in error_msg.lower() or "image_url" in error_msg.lower()):
173
+ raise ProviderAPIError(
174
+ f"Vision not supported: The model '{request.model}' cannot process images. "
175
+ f"Please use a vision-capable model (e.g., gemini-2.5-pro for Google, gpt-4o for OpenAI via OpenRouter).",
176
+ self.provider_name
177
+ )
150
178
  else:
151
179
  raise ProviderAPIError(
152
180
  f"Chat completion failed: {error_msg}",
153
181
  self.provider_name
154
182
  )
155
183
  except Exception as e:
184
+ error_str = str(e)
185
+ # Check for vision-related errors in generic exceptions
186
+ if "image" in error_str.lower() and ("not supported" in error_str.lower() or "invalid" in error_str.lower() or "image_url" in error_str.lower()):
187
+ raise ProviderAPIError(
188
+ f"Vision not supported: The model '{request.model}' cannot process images. "
189
+ f"Please use a vision-capable model.",
190
+ self.provider_name
191
+ )
156
192
  raise ProviderAPIError(
157
- f"Chat completion failed: {str(e)}",
193
+ f"Chat completion failed: {error_str}",
158
194
  self.provider_name
159
195
  )
160
196
 
@@ -186,12 +222,33 @@ class OpenAICompatibleProvider(BaseProvider):
186
222
  )
187
223
 
188
224
  # Build request parameters
225
+ messages = []
226
+ for msg in request.messages:
227
+ # Check if message contains an image
228
+ if msg.has_image():
229
+ # Parse vision content
230
+ text_content, (mime_type, base64_data) = msg.parse_vision_content()
231
+
232
+ # Build content array for vision
233
+ content_parts = []
234
+ if text_content:
235
+ content_parts.append({"type": "text", "text": text_content})
236
+
237
+ # Add image in OpenAI format (data URL)
238
+ content_parts.append({
239
+ "type": "image_url",
240
+ "image_url": {
241
+ "url": f"data:{mime_type};base64,{base64_data}"
242
+ }
243
+ })
244
+
245
+ messages.append({"role": msg.role, "content": content_parts})
246
+ else:
247
+ messages.append({"role": msg.role, "content": msg.content})
248
+
189
249
  openai_params = {
190
250
  "model": request.model,
191
- "messages": [
192
- {"role": msg.role, "content": msg.content}
193
- for msg in request.messages
194
- ],
251
+ "messages": messages,
195
252
  "stream": True,
196
253
  }
197
254
 
@@ -232,14 +289,29 @@ class OpenAICompatibleProvider(BaseProvider):
232
289
  raise InsufficientBalanceError(self.provider_name)
233
290
  elif "invalid_api_key" in error_msg.lower() or "unauthorized" in error_msg.lower() or (hasattr(e, 'status_code') and e.status_code == 401):
234
291
  raise AuthenticationError(self.provider_name)
292
+ # Check for vision-related errors
293
+ elif "image" in error_msg.lower() and ("not supported" in error_msg.lower() or "invalid" in error_msg.lower() or "image_url" in error_msg.lower()):
294
+ raise ProviderAPIError(
295
+ f"Vision not supported: The model '{request.model}' cannot process images. "
296
+ f"Please use a vision-capable model.",
297
+ self.provider_name
298
+ )
235
299
  else:
236
300
  raise ProviderAPIError(
237
301
  f"Streaming chat completion failed: {error_msg}",
238
302
  self.provider_name
239
303
  )
240
304
  except Exception as e:
305
+ error_str = str(e)
306
+ # Check for vision-related errors
307
+ if "image" in error_str.lower() and ("not supported" in error_str.lower() or "invalid" in error_str.lower() or "image_url" in error_str.lower()):
308
+ raise ProviderAPIError(
309
+ f"Vision not supported: The model '{request.model}' cannot process images. "
310
+ f"Please use a vision-capable model.",
311
+ self.provider_name
312
+ )
241
313
  raise ProviderAPIError(
242
- f"Streaming chat completion failed: {str(e)}",
314
+ f"Streaming chat completion failed: {error_str}",
243
315
  self.provider_name
244
316
  )
245
317
 
stratifyai/router.py CHANGED
@@ -74,7 +74,7 @@ class Router:
74
74
  # Anthropic
75
75
  "claude-sonnet-4-5-20250929": 0.94,
76
76
  "claude-3-5-sonnet-20241022": 0.92,
77
- "claude-3-5-haiku-20241022": 0.80,
77
+ "claude-haiku-4-5": 0.82,
78
78
 
79
79
  # Google
80
80
  "gemini-2.5-pro": 0.91,
@@ -117,7 +117,7 @@ class Router:
117
117
  # Anthropic
118
118
  "claude-sonnet-4-5-20250929": 2800,
119
119
  "claude-3-5-sonnet-20241022": 2200,
120
- "claude-3-5-haiku-20241022": 1200,
120
+ "claude-haiku-4-5": 1000,
121
121
 
122
122
  # Google
123
123
  "gemini-2.5-pro": 2000,
@@ -52,8 +52,8 @@ Provide a concise summary that preserves key information."""
52
52
  max_tokens=max_tokens
53
53
  )
54
54
 
55
- # Get summary
56
- response = client.chat_completion(request)
55
+ # Get summary (use sync wrapper since this is called from ThreadPoolExecutor)
56
+ response = client.chat_completion_sync(request)
57
57
  return response.content
58
58
 
59
59
 
@@ -134,6 +134,150 @@ def summarize_chunks_progressive(
134
134
  return combined
135
135
 
136
136
 
137
+ async def summarize_chunk_async(
138
+ chunk: str,
139
+ client: LLMClient,
140
+ model: str = "gpt-4o-mini",
141
+ max_tokens: int = 1000,
142
+ context: Optional[str] = None
143
+ ) -> str:
144
+ """
145
+ Async version: Summarize a single chunk of content.
146
+
147
+ Args:
148
+ chunk: The content chunk to summarize
149
+ client: LLMClient instance
150
+ model: Model to use for summarization
151
+ max_tokens: Maximum tokens for summary
152
+ context: Optional context about the overall document
153
+
154
+ Returns:
155
+ Summary of the chunk
156
+ """
157
+ # Build prompt
158
+ if context:
159
+ prompt = f"""Summarize the following section from a larger document.
160
+
161
+ Context: {context}
162
+
163
+ Section to summarize:
164
+ {chunk}
165
+
166
+ Provide a concise summary that preserves key information."""
167
+ else:
168
+ prompt = f"""Summarize the following text concisely, preserving key information:
169
+
170
+ {chunk}"""
171
+
172
+ # Create request
173
+ request = ChatRequest(
174
+ model=model,
175
+ messages=[Message(role="user", content=prompt)],
176
+ max_tokens=max_tokens
177
+ )
178
+
179
+ # Get summary (async)
180
+ response = await client.chat_completion(request)
181
+ return response.content
182
+
183
+
184
+ async def summarize_chunks_progressive_async(
185
+ chunks: List[str],
186
+ client: LLMClient,
187
+ model: str = "gpt-4o-mini",
188
+ context: Optional[str] = None,
189
+ show_progress: bool = False
190
+ ) -> str:
191
+ """
192
+ Async version: Progressively summarize multiple chunks.
193
+
194
+ Args:
195
+ chunks: List of content chunks
196
+ client: LLMClient instance
197
+ model: Model to use for summarization
198
+ context: Optional context about the overall document
199
+ show_progress: Whether to show progress bar (disabled for async)
200
+
201
+ Returns:
202
+ Combined summary of all chunks
203
+ """
204
+ if not chunks:
205
+ return ""
206
+
207
+ if len(chunks) == 1:
208
+ return await summarize_chunk_async(chunks[0], client, model, context=context)
209
+
210
+ summaries = []
211
+ for i, chunk in enumerate(chunks, 1):
212
+ summary = await summarize_chunk_async(
213
+ chunk,
214
+ client,
215
+ model,
216
+ context=f"{context} (Part {i}/{len(chunks)})" if context else f"Part {i}/{len(chunks)}"
217
+ )
218
+ summaries.append(f"**Part {i}/{len(chunks)}:**\n{summary}")
219
+
220
+ # Combine summaries
221
+ combined = "\n\n".join(summaries)
222
+
223
+ # If combined summaries are still very long, summarize the summaries
224
+ if len(combined) > 10000:
225
+ final_summary = await summarize_chunk_async(
226
+ combined,
227
+ client,
228
+ model,
229
+ context="Combined summaries of document sections"
230
+ )
231
+ return f"**Overall Summary:**\n{final_summary}\n\n**Detailed Summaries:**\n{combined}"
232
+
233
+ return combined
234
+
235
+
236
+ async def summarize_file_async(
237
+ content: str,
238
+ client: LLMClient,
239
+ chunk_size: int = 50000,
240
+ model: str = "gpt-4o-mini",
241
+ context: Optional[str] = None,
242
+ show_progress: bool = False
243
+ ) -> dict:
244
+ """
245
+ Async version: Summarize a large file using progressive chunking.
246
+
247
+ Args:
248
+ content: Full file content
249
+ client: LLMClient instance
250
+ chunk_size: Size of chunks in characters
251
+ model: Model to use for summarization
252
+ context: Optional context about the document
253
+ show_progress: Whether to show progress (disabled for async)
254
+
255
+ Returns:
256
+ Dictionary with summary and metadata
257
+ """
258
+ # Chunk the content
259
+ chunks = chunk_content(content, chunk_size=chunk_size)
260
+ metadata = get_chunk_metadata(chunks)
261
+
262
+ # Summarize chunks
263
+ summary = await summarize_chunks_progressive_async(
264
+ chunks,
265
+ client,
266
+ model=model,
267
+ context=context,
268
+ show_progress=show_progress
269
+ )
270
+
271
+ return {
272
+ "summary": summary,
273
+ "original_length": len(content),
274
+ "summary_length": len(summary),
275
+ "reduction_percentage": round((1 - len(summary) / len(content)) * 100, 1),
276
+ "num_chunks": metadata["num_chunks"],
277
+ "chunk_metadata": metadata
278
+ }
279
+
280
+
137
281
  def summarize_file(
138
282
  content: str,
139
283
  client: LLMClient,
@@ -143,7 +287,7 @@ def summarize_file(
143
287
  show_progress: bool = True
144
288
  ) -> dict:
145
289
  """
146
- Summarize a large file using progressive chunking.
290
+ Sync version: Summarize a large file using progressive chunking.
147
291
 
148
292
  Args:
149
293
  content: Full file content
@@ -64,7 +64,7 @@ class ModelSelector:
64
64
  self.summary_models = [
65
65
  ("google", "gemini-2.5-flash", "Fast and cost-effective"),
66
66
  ("groq", "llama-3.1-70b-versatile", "Very fast inference"),
67
- ("anthropic", "claude-3-5-haiku-20241022", "Quick, quality summaries"),
67
+ ("anthropic", "claude-haiku-4-5", "Quick, quality summaries"),
68
68
  ("openai", "gpt-4.1-mini", "Balanced speed/quality"),
69
69
  ]
70
70
 
@@ -249,7 +249,7 @@ class ModelSelector:
249
249
  # Anthropic
250
250
  "claude-sonnet-4-5-20250929": 0.94,
251
251
  "claude-3-5-sonnet-20241022": 0.92,
252
- "claude-3-5-haiku-20241022": 0.80,
252
+ "claude-haiku-4-5": 0.82,
253
253
 
254
254
  # Google
255
255
  "gemini-2.5-pro": 0.91,
@@ -293,7 +293,7 @@ class ModelSelector:
293
293
  "o1-mini": 3.00,
294
294
  "o3-mini": 1.10,
295
295
  "llama-3.1-70b-versatile": 0.08,
296
- "claude-3-5-haiku-20241022": 1.00,
296
+ "claude-haiku-4-5": 1.00,
297
297
  "gpt-4.1-mini": 0.15,
298
298
  }
299
299
 
@@ -238,11 +238,13 @@ def _validate_groq(model_ids: List[str], api_key: Optional[str] = None) -> Dict[
238
238
 
239
239
  def _validate_grok(model_ids: List[str], api_key: Optional[str] = None) -> Dict[str, Any]:
240
240
  """Validate Grok (X.AI) models using OpenAI-compatible API."""
241
+ # Support both XAI_API_KEY (official) and GROK_API_KEY (legacy)
242
+ key = api_key or os.getenv("XAI_API_KEY") or os.getenv("GROK_API_KEY")
241
243
  return _validate_openai_compatible(
242
244
  model_ids,
243
245
  "https://api.x.ai/v1",
244
- api_key,
245
- "GROK_API_KEY",
246
+ key,
247
+ "XAI_API_KEY",
246
248
  )
247
249
 
248
250
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stratifyai
3
- Version: 0.1.1
3
+ Version: 0.1.3
4
4
  Summary: Unified multi-provider LLM abstraction module with intelligent routing, cost tracking, and caching
5
5
  Author-email: Steven Cotton <cototnbytes@gmail.com>
6
6
  Maintainer-email: Steven Cotton <cototnbytes@gmail.com>
@@ -33,6 +33,9 @@ Requires-Dist: pydantic>=2.0.0
33
33
  Requires-Dist: typing-extensions>=4.0.0
34
34
  Requires-Dist: typer>=0.9.0
35
35
  Requires-Dist: tiktoken>=0.5.0
36
+ Requires-Dist: fastapi>=0.115.0
37
+ Requires-Dist: uvicorn[standard]>=0.34.0
38
+ Requires-Dist: websockets>=14.0
36
39
  Provides-Extra: dev
37
40
  Requires-Dist: pytest>=9.0.0; extra == "dev"
38
41
  Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
@@ -61,9 +64,9 @@ Dynamic: license-file
61
64
 
62
65
  ![Python](https://img.shields.io/badge/python-3.10%2B-blue) ![License](https://img.shields.io/badge/license-MIT-green) ![Tests](https://img.shields.io/badge/tests-300%2B%20passing-brightgreen) ![Providers](https://img.shields.io/badge/providers-9-orange)
63
66
 
64
- **Status:** Phase 7.8 Complete
67
+ **Status:** Phase 7.9 Complete
65
68
  **Providers:** 9 Operational
66
- **Features:** Routing • RAG • Caching • Streaming • CLI • Web UI • Builder Pattern
69
+ **Features:** Routing • RAG • Caching • Streaming • CLI • Web UI • Vision • Smart Chunking
67
70
 
68
71
  StratifyAI is a production‑ready Python framework that provides a unified interface for 9+ LLM providers, including OpenAI, Anthropic, Google, DeepSeek, Groq, Grok, OpenRouter, Ollama, and AWS Bedrock. It eliminates vendor lock‑in, simplifies multi‑model development, and enables intelligent routing, cost tracking, caching, streaming, and RAG workflows.
69
72
 
@@ -85,16 +88,17 @@ StratifyAI is a production‑ready Python framework that provides a unified inte
85
88
  - Capability filtering (vision, tools, reasoning)
86
89
  - Model metadata and context window awareness
87
90
  - **Builder pattern** for fluent configuration
91
+ - **Vision support** for image analysis (GPT-4o, Claude, Gemini, Nova)
88
92
 
89
93
  ### Advanced
90
94
 
91
- - Large‑file handling with chunking and progressive summarization
95
+ - Large‑file handling with **smart chunking** and progressive summarization
92
96
  - File extraction (CSV schema, JSON schema, logs, code structure)
93
97
  - Auto model selection for extraction tasks
94
98
  - RAG pipeline with embeddings + vector DB (ChromaDB)
95
99
  - Semantic search and citation tracking
96
100
  - Rich/Typer CLI with interactive mode
97
- - Optional FastAPI web interface
101
+ - **Web UI** with markdown rendering and syntax highlighting
98
102
 
99
103
  ---
100
104
 
@@ -1,20 +1,27 @@
1
+ api/__init__.py,sha256=g3jSdRogNbCJK7ksKp4tuDTmktckaqXKCmadgRYvfkQ,52
2
+ api/main.py,sha256=4DTOEwpxx3LWTKS82T3WPN3JTX4QCmkbVVGWSg6Tu-c,30349
3
+ api/static/index.html,sha256=1olXOhlrFQZPdSKHxB0ozli5g1o0i6Ci_rnzYBkgTxw,48277
4
+ api/static/models.html,sha256=jjEYoWfNAJd7PrryVaVqHh19C_t21_uJAtVSCsBUoU0,19099
5
+ api/static/stratifyai_trans_logo.png,sha256=icER6lIzQ7uVhSwt7E_plEkpE57B7-6W4GuTgXXMxko,1393542
6
+ api/static/stratifyai_wide_logo.png,sha256=caZsnIxxnSs1_9s72MmUrWK3pbBsKIDZ1cahDXf34X0,88548
7
+ api/static/stratum_logo.png,sha256=XBrXiTE-g9Ku615qMWyD0qCXljfLZq56E_7WLUJUhGg,31093
1
8
  cli/__init__.py,sha256=Bwi6ibJLRbqK0oIP_U0pvypH0nKXUBMbufZPnXMkI2E,96
2
- cli/stratifyai_cli.py,sha256=aliOcAg0qxeSKaM4QZoIydS_YDCUm2Sb9Sv-vXNafRg,82568
9
+ cli/stratifyai_cli.py,sha256=qdOcLDS3yjOSLJplQkc7PQK4kUDhaBpy8AV7XPh-8_c,111826
3
10
  stratifyai/__init__.py,sha256=yjmHcAcorD5txlNZwmamljOnN3nHCosBY2_0CE26TaE,2873
4
- stratifyai/api_key_helper.py,sha256=fkhb1iUGcGg5il-L7KbjbtS27pAm41McNyvEqMW2fVE,12733
11
+ stratifyai/api_key_helper.py,sha256=OyQNBRe1YgS-bI_r8ZjzYDssXQsEb0CvaR5Fm7eq7S0,12770
5
12
  stratifyai/caching.py,sha256=NSm7SA1hruVC4rgg-0MPFNlMYT5i3JNKAkvlexGICiY,8475
6
13
  stratifyai/chunking.py,sha256=vNXPoBwegQmdHQKXnQeGPdk4wwOrNzk2BYk__figEAY,5042
7
14
  stratifyai/client.py,sha256=93uNaXrlxZ02VywJFwPV07P7E0l9NfuS87wgxk5ZtkM,9025
8
- stratifyai/config.py,sha256=cbF10BwWQTOuKm5OPmYlJGaAKyVN_jmjBs7yWGc26kc,36230
15
+ stratifyai/config.py,sha256=t_lM4jhhVQf4D3HquldJl3RgB-LwcIDCwzLiGSyicmg,40370
9
16
  stratifyai/cost_tracker.py,sha256=f8A631iz-OOE16rPkoHDQeqMZcG46LmyCWweLcS6BKg,8774
10
17
  stratifyai/embeddings.py,sha256=FZkApJYVgI7TB0azttan-5qV6SNdg_P8O1bANbkCXK8,7642
11
18
  stratifyai/exceptions.py,sha256=ZfKrgP0ZyVfuETouQRyUxraN3Cy4631m5hXjBvXvNSE,2802
12
- stratifyai/models.py,sha256=6T3V3U2eyZQRGF91QDl9kWB-yC6FdalTIT2XovQb0Yo,1867
19
+ stratifyai/models.py,sha256=aJxnJUg_zdzMn7-E8ryIooDTBKEtsMrWW_BTHwydwOE,3305
13
20
  stratifyai/py.typed,sha256=UlkhTBVJqiS1Epx-KILVobCtCGlhR6YKM79R8vO1HdU,61
14
21
  stratifyai/rag.py,sha256=Yu-u-G5BYvJ-Ac9kuZ3cbMO4yL4NhIP0OZqlfnigv08,12302
15
22
  stratifyai/retry.py,sha256=OqiBuPzDkhRPLyjwRX6E5HFuQ6QbsMh4f-7GSldQoRM,5992
16
- stratifyai/router.py,sha256=qQs58BaKDxKGZ_AIp2_-NGSqpttzB9OrKikmpoFyvlg,23585
17
- stratifyai/summarization.py,sha256=FslLun2fzKqX3dVTAHG-rzAz2DH6D9C_u74rA7tHrYU,5261
23
+ stratifyai/router.py,sha256=GO2_3BVsMmJuaKrOV-52Rk1vJDKruCrnlm0nfaaCU3Q,23567
24
+ stratifyai/summarization.py,sha256=Cyo3XkJGbU1pB2bQLDP_A8m6YfB5CsLUo6smQE3Bz00,9397
18
25
  stratifyai/vectordb.py,sha256=ErLOvk4X82YfZDOkoAkrgHVY3YvukT2KDRhMA02-bqw,10708
19
26
  stratifyai/chat/__init__.py,sha256=foW5mE5OWmBIW0ADURWUzcznJyiyfBl_h11blZIBBSQ,1417
20
27
  stratifyai/chat/builder.py,sha256=W9Rwh64u5uvJlnJH1vi3q_Og6XiXaD8juxcHD5Z3wRE,12962
@@ -28,16 +35,16 @@ stratifyai/chat/stratifyai_ollama.py,sha256=nj-RdOdosmPLixkoI4ceMGHNnBGcDIW8vQIH
28
35
  stratifyai/chat/stratifyai_openai.py,sha256=217C-FnkvNKwJNCsMt5mp_YUkjBmipXbckUmVE7HW1w,6410
29
36
  stratifyai/chat/stratifyai_openrouter.py,sha256=jxAed4mPH26AJF7qhWpbLy83yR-LYlox5mZXTA739y4,6088
30
37
  stratifyai/providers/__init__.py,sha256=huQSk2r1ZEQPxIim6U5VpYvOQi2QfVbImVzbyXYSEHQ,96
31
- stratifyai/providers/anthropic.py,sha256=cogWjpFsoOc2k7wQ6QzEiIi1imU6RgUUdkk7VFL1XDM,11800
38
+ stratifyai/providers/anthropic.py,sha256=ROMPMzf7FAOqOl0kIx15n4vgQ0Ep4daoK4CMKXl5PPw,14873
32
39
  stratifyai/providers/base.py,sha256=WJ6W_HUAcejtqDljRPK37KgUgB4SJtQ-kC6zO0tmnPs,5252
33
- stratifyai/providers/bedrock.py,sha256=GPaRB1enqxmxNzWpiVgX67ubGzt0hnwGXLDU6GIw4HY,24739
40
+ stratifyai/providers/bedrock.py,sha256=uoF1Y2v-bvszmULbCYOm55RdfIynXvzDAlqgxQPsr-w,28973
34
41
  stratifyai/providers/deepseek.py,sha256=Y-ZT_xh2aXBHXEVh5NWXQnANv6pDEmIHcxwplHSlQ24,1145
35
42
  stratifyai/providers/google.py,sha256=fi-8KBMzESTHMe1bmrZfOu8o5mKizIAaPG1puZAiGo4,1142
36
- stratifyai/providers/grok.py,sha256=O0oUGAo3hNZ-B07n0Zh0qWQsqDborLC-b38ItOwo88s,1111
43
+ stratifyai/providers/grok.py,sha256=d9AmhItYvhk33U9uuLtuN_szQE265Z95Ln1sSr68aEc,1253
37
44
  stratifyai/providers/groq.py,sha256=XTGsHwubuSXgCMSTGJBTIddvNQFz6Hg4eIIaxERMXWY,1097
38
45
  stratifyai/providers/ollama.py,sha256=Uvr8K0aAW3TSUckC64-g7chj8WD9qJBzT2ndRllBZEI,1404
39
- stratifyai/providers/openai.py,sha256=Ddm9nDvmRGlAqeG7rSwe7yD42SHyEhho0dVFj5Xh5ww,12831
40
- stratifyai/providers/openai_compatible.py,sha256=TWI81E4NujphNOTCFYZnsYjiWBibs78mdUIt53vXenU,14290
46
+ stratifyai/providers/openai.py,sha256=kX6gnKHPYCD0DxolZUekCj6McgjYX7LteLd0r2HWrfk,15544
47
+ stratifyai/providers/openai_compatible.py,sha256=YbT1WVeYUvZGguPgrcc44-I-PRASb3Z-DqPUKgevUzE,17995
41
48
  stratifyai/providers/openrouter.py,sha256=ESXfH_OpElTj6-Bsqqt2vf6h5ydVtxE7QygxhkXmpHI,1169
42
49
  stratifyai/utils/__init__.py,sha256=ToRceBu1Mx4vNhYP0a_WuONAgfK4gry8j_G8YW6159A,274
43
50
  stratifyai/utils/bedrock_validator.py,sha256=9ZCQWYKCf4b0IqaLrcSJ038WocjXHiiB0qxcrobOssA,4530
@@ -46,12 +53,12 @@ stratifyai/utils/csv_extractor.py,sha256=essTu8ILDHKgBeFeZxVdxr7yFUKPAHcetGbCwR-
46
53
  stratifyai/utils/file_analyzer.py,sha256=Gcps6V8k1P18pf3MZyk6oUkQiIyP7XLxYLChDn6X548,6292
47
54
  stratifyai/utils/json_extractor.py,sha256=WzaloLrlqhoDjAHcRIwYWnmYYu81WqTugNbW1JDRzpg,6720
48
55
  stratifyai/utils/log_extractor.py,sha256=Nz2x9xPvRVdp5yk6cTLQ5CHK4Fi5oNKQG2t2k9eFiRM,8118
49
- stratifyai/utils/model_selector.py,sha256=LSPc23MWiCkX2ikygkjdDgXdujqLctk1ANuMRKMJ-S8,11922
50
- stratifyai/utils/provider_validator.py,sha256=LAB2kljZ3NPlXaMwH9njiFhp0EYzRwvwSX7Pcphj9NQ,14726
56
+ stratifyai/utils/model_selector.py,sha256=xoaJ4rHhsqHTbEUnINeT267AWNziRPEVMdjfBuyykuI,11895
57
+ stratifyai/utils/provider_validator.py,sha256=LUBZebd8MZFXPoUDFOTJ6JxMkJG9CbcrJNHZiK--WCU,14864
51
58
  stratifyai/utils/token_counter.py,sha256=58hkX3q4yObZVwo3lvn7OGPh7puiWNind7yX3Qem_1o,6432
52
- stratifyai-0.1.1.dist-info/licenses/LICENSE,sha256=UEMslgLRhi7sYtDIwMY0IjEppiVEgqgMIdsulgYdb0Q,1068
53
- stratifyai-0.1.1.dist-info/METADATA,sha256=89fOaqvxIeWBpt68rRabcqHF281ay-UVhoD3aCKtmIo,7753
54
- stratifyai-0.1.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
55
- stratifyai-0.1.1.dist-info/entry_points.txt,sha256=aWXYCRBSld8hzAtCPAqsl2NHKJIJkIgc63uQOO2PcUQ,55
56
- stratifyai-0.1.1.dist-info/top_level.txt,sha256=0_JiuYll_AXJr5e4qXzbCs8LYykDxGaEjawwI69vEhM,15
57
- stratifyai-0.1.1.dist-info/RECORD,,
59
+ stratifyai-0.1.3.dist-info/licenses/LICENSE,sha256=UEMslgLRhi7sYtDIwMY0IjEppiVEgqgMIdsulgYdb0Q,1068
60
+ stratifyai-0.1.3.dist-info/METADATA,sha256=brTVzjEx5DXL1hDDdNhDzb4OuyixtKWwHf4EJ6P13tQ,7977
61
+ stratifyai-0.1.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
62
+ stratifyai-0.1.3.dist-info/entry_points.txt,sha256=aWXYCRBSld8hzAtCPAqsl2NHKJIJkIgc63uQOO2PcUQ,55
63
+ stratifyai-0.1.3.dist-info/top_level.txt,sha256=FknIJcC6EUuTJw66TfdXz-tF5VyT5t4HsXXwMDb6Qtw,19
64
+ stratifyai-0.1.3.dist-info/RECORD,,