stratifyai 0.1.1__py3-none-any.whl → 0.1.2__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.
- cli/stratifyai_cli.py +574 -73
- stratifyai/api_key_helper.py +1 -1
- stratifyai/config.py +158 -24
- stratifyai/models.py +36 -1
- stratifyai/providers/anthropic.py +65 -5
- stratifyai/providers/bedrock.py +96 -9
- stratifyai/providers/grok.py +3 -2
- stratifyai/providers/openai.py +63 -8
- stratifyai/providers/openai_compatible.py +79 -7
- stratifyai/router.py +2 -2
- stratifyai/summarization.py +147 -3
- stratifyai/utils/model_selector.py +3 -3
- stratifyai/utils/provider_validator.py +4 -2
- {stratifyai-0.1.1.dist-info → stratifyai-0.1.2.dist-info}/METADATA +6 -5
- {stratifyai-0.1.1.dist-info → stratifyai-0.1.2.dist-info}/RECORD +19 -19
- {stratifyai-0.1.1.dist-info → stratifyai-0.1.2.dist-info}/WHEEL +0 -0
- {stratifyai-0.1.1.dist-info → stratifyai-0.1.2.dist-info}/entry_points.txt +0 -0
- {stratifyai-0.1.1.dist-info → stratifyai-0.1.2.dist-info}/licenses/LICENSE +0 -0
- {stratifyai-0.1.1.dist-info → stratifyai-0.1.2.dist-info}/top_level.txt +0 -0
|
@@ -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
|
-
|
|
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: {
|
|
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: {
|
|
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-
|
|
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-
|
|
120
|
+
"claude-haiku-4-5": 1000,
|
|
121
121
|
|
|
122
122
|
# Google
|
|
123
123
|
"gemini-2.5-pro": 2000,
|
stratifyai/summarization.py
CHANGED
|
@@ -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.
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
-
|
|
245
|
-
"
|
|
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.
|
|
3
|
+
Version: 0.1.2
|
|
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>
|
|
@@ -61,9 +61,9 @@ Dynamic: license-file
|
|
|
61
61
|
|
|
62
62
|
   
|
|
63
63
|
|
|
64
|
-
**Status:** Phase 7.
|
|
64
|
+
**Status:** Phase 7.9 Complete
|
|
65
65
|
**Providers:** 9 Operational
|
|
66
|
-
**Features:** Routing • RAG • Caching • Streaming • CLI • Web UI •
|
|
66
|
+
**Features:** Routing • RAG • Caching • Streaming • CLI • Web UI • Vision • Smart Chunking
|
|
67
67
|
|
|
68
68
|
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
69
|
|
|
@@ -85,16 +85,17 @@ StratifyAI is a production‑ready Python framework that provides a unified inte
|
|
|
85
85
|
- Capability filtering (vision, tools, reasoning)
|
|
86
86
|
- Model metadata and context window awareness
|
|
87
87
|
- **Builder pattern** for fluent configuration
|
|
88
|
+
- **Vision support** for image analysis (GPT-4o, Claude, Gemini, Nova)
|
|
88
89
|
|
|
89
90
|
### Advanced
|
|
90
91
|
|
|
91
|
-
- Large‑file handling with chunking and progressive summarization
|
|
92
|
+
- Large‑file handling with **smart chunking** and progressive summarization
|
|
92
93
|
- File extraction (CSV schema, JSON schema, logs, code structure)
|
|
93
94
|
- Auto model selection for extraction tasks
|
|
94
95
|
- RAG pipeline with embeddings + vector DB (ChromaDB)
|
|
95
96
|
- Semantic search and citation tracking
|
|
96
97
|
- Rich/Typer CLI with interactive mode
|
|
97
|
-
-
|
|
98
|
+
- **Web UI** with markdown rendering and syntax highlighting
|
|
98
99
|
|
|
99
100
|
---
|
|
100
101
|
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
cli/__init__.py,sha256=Bwi6ibJLRbqK0oIP_U0pvypH0nKXUBMbufZPnXMkI2E,96
|
|
2
|
-
cli/stratifyai_cli.py,sha256=
|
|
2
|
+
cli/stratifyai_cli.py,sha256=qdOcLDS3yjOSLJplQkc7PQK4kUDhaBpy8AV7XPh-8_c,111826
|
|
3
3
|
stratifyai/__init__.py,sha256=yjmHcAcorD5txlNZwmamljOnN3nHCosBY2_0CE26TaE,2873
|
|
4
|
-
stratifyai/api_key_helper.py,sha256=
|
|
4
|
+
stratifyai/api_key_helper.py,sha256=OyQNBRe1YgS-bI_r8ZjzYDssXQsEb0CvaR5Fm7eq7S0,12770
|
|
5
5
|
stratifyai/caching.py,sha256=NSm7SA1hruVC4rgg-0MPFNlMYT5i3JNKAkvlexGICiY,8475
|
|
6
6
|
stratifyai/chunking.py,sha256=vNXPoBwegQmdHQKXnQeGPdk4wwOrNzk2BYk__figEAY,5042
|
|
7
7
|
stratifyai/client.py,sha256=93uNaXrlxZ02VywJFwPV07P7E0l9NfuS87wgxk5ZtkM,9025
|
|
8
|
-
stratifyai/config.py,sha256=
|
|
8
|
+
stratifyai/config.py,sha256=t_lM4jhhVQf4D3HquldJl3RgB-LwcIDCwzLiGSyicmg,40370
|
|
9
9
|
stratifyai/cost_tracker.py,sha256=f8A631iz-OOE16rPkoHDQeqMZcG46LmyCWweLcS6BKg,8774
|
|
10
10
|
stratifyai/embeddings.py,sha256=FZkApJYVgI7TB0azttan-5qV6SNdg_P8O1bANbkCXK8,7642
|
|
11
11
|
stratifyai/exceptions.py,sha256=ZfKrgP0ZyVfuETouQRyUxraN3Cy4631m5hXjBvXvNSE,2802
|
|
12
|
-
stratifyai/models.py,sha256=
|
|
12
|
+
stratifyai/models.py,sha256=aJxnJUg_zdzMn7-E8ryIooDTBKEtsMrWW_BTHwydwOE,3305
|
|
13
13
|
stratifyai/py.typed,sha256=UlkhTBVJqiS1Epx-KILVobCtCGlhR6YKM79R8vO1HdU,61
|
|
14
14
|
stratifyai/rag.py,sha256=Yu-u-G5BYvJ-Ac9kuZ3cbMO4yL4NhIP0OZqlfnigv08,12302
|
|
15
15
|
stratifyai/retry.py,sha256=OqiBuPzDkhRPLyjwRX6E5HFuQ6QbsMh4f-7GSldQoRM,5992
|
|
16
|
-
stratifyai/router.py,sha256=
|
|
17
|
-
stratifyai/summarization.py,sha256=
|
|
16
|
+
stratifyai/router.py,sha256=GO2_3BVsMmJuaKrOV-52Rk1vJDKruCrnlm0nfaaCU3Q,23567
|
|
17
|
+
stratifyai/summarization.py,sha256=Cyo3XkJGbU1pB2bQLDP_A8m6YfB5CsLUo6smQE3Bz00,9397
|
|
18
18
|
stratifyai/vectordb.py,sha256=ErLOvk4X82YfZDOkoAkrgHVY3YvukT2KDRhMA02-bqw,10708
|
|
19
19
|
stratifyai/chat/__init__.py,sha256=foW5mE5OWmBIW0ADURWUzcznJyiyfBl_h11blZIBBSQ,1417
|
|
20
20
|
stratifyai/chat/builder.py,sha256=W9Rwh64u5uvJlnJH1vi3q_Og6XiXaD8juxcHD5Z3wRE,12962
|
|
@@ -28,16 +28,16 @@ stratifyai/chat/stratifyai_ollama.py,sha256=nj-RdOdosmPLixkoI4ceMGHNnBGcDIW8vQIH
|
|
|
28
28
|
stratifyai/chat/stratifyai_openai.py,sha256=217C-FnkvNKwJNCsMt5mp_YUkjBmipXbckUmVE7HW1w,6410
|
|
29
29
|
stratifyai/chat/stratifyai_openrouter.py,sha256=jxAed4mPH26AJF7qhWpbLy83yR-LYlox5mZXTA739y4,6088
|
|
30
30
|
stratifyai/providers/__init__.py,sha256=huQSk2r1ZEQPxIim6U5VpYvOQi2QfVbImVzbyXYSEHQ,96
|
|
31
|
-
stratifyai/providers/anthropic.py,sha256=
|
|
31
|
+
stratifyai/providers/anthropic.py,sha256=ROMPMzf7FAOqOl0kIx15n4vgQ0Ep4daoK4CMKXl5PPw,14873
|
|
32
32
|
stratifyai/providers/base.py,sha256=WJ6W_HUAcejtqDljRPK37KgUgB4SJtQ-kC6zO0tmnPs,5252
|
|
33
|
-
stratifyai/providers/bedrock.py,sha256=
|
|
33
|
+
stratifyai/providers/bedrock.py,sha256=uoF1Y2v-bvszmULbCYOm55RdfIynXvzDAlqgxQPsr-w,28973
|
|
34
34
|
stratifyai/providers/deepseek.py,sha256=Y-ZT_xh2aXBHXEVh5NWXQnANv6pDEmIHcxwplHSlQ24,1145
|
|
35
35
|
stratifyai/providers/google.py,sha256=fi-8KBMzESTHMe1bmrZfOu8o5mKizIAaPG1puZAiGo4,1142
|
|
36
|
-
stratifyai/providers/grok.py,sha256=
|
|
36
|
+
stratifyai/providers/grok.py,sha256=d9AmhItYvhk33U9uuLtuN_szQE265Z95Ln1sSr68aEc,1253
|
|
37
37
|
stratifyai/providers/groq.py,sha256=XTGsHwubuSXgCMSTGJBTIddvNQFz6Hg4eIIaxERMXWY,1097
|
|
38
38
|
stratifyai/providers/ollama.py,sha256=Uvr8K0aAW3TSUckC64-g7chj8WD9qJBzT2ndRllBZEI,1404
|
|
39
|
-
stratifyai/providers/openai.py,sha256=
|
|
40
|
-
stratifyai/providers/openai_compatible.py,sha256=
|
|
39
|
+
stratifyai/providers/openai.py,sha256=kX6gnKHPYCD0DxolZUekCj6McgjYX7LteLd0r2HWrfk,15544
|
|
40
|
+
stratifyai/providers/openai_compatible.py,sha256=YbT1WVeYUvZGguPgrcc44-I-PRASb3Z-DqPUKgevUzE,17995
|
|
41
41
|
stratifyai/providers/openrouter.py,sha256=ESXfH_OpElTj6-Bsqqt2vf6h5ydVtxE7QygxhkXmpHI,1169
|
|
42
42
|
stratifyai/utils/__init__.py,sha256=ToRceBu1Mx4vNhYP0a_WuONAgfK4gry8j_G8YW6159A,274
|
|
43
43
|
stratifyai/utils/bedrock_validator.py,sha256=9ZCQWYKCf4b0IqaLrcSJ038WocjXHiiB0qxcrobOssA,4530
|
|
@@ -46,12 +46,12 @@ stratifyai/utils/csv_extractor.py,sha256=essTu8ILDHKgBeFeZxVdxr7yFUKPAHcetGbCwR-
|
|
|
46
46
|
stratifyai/utils/file_analyzer.py,sha256=Gcps6V8k1P18pf3MZyk6oUkQiIyP7XLxYLChDn6X548,6292
|
|
47
47
|
stratifyai/utils/json_extractor.py,sha256=WzaloLrlqhoDjAHcRIwYWnmYYu81WqTugNbW1JDRzpg,6720
|
|
48
48
|
stratifyai/utils/log_extractor.py,sha256=Nz2x9xPvRVdp5yk6cTLQ5CHK4Fi5oNKQG2t2k9eFiRM,8118
|
|
49
|
-
stratifyai/utils/model_selector.py,sha256=
|
|
50
|
-
stratifyai/utils/provider_validator.py,sha256=
|
|
49
|
+
stratifyai/utils/model_selector.py,sha256=xoaJ4rHhsqHTbEUnINeT267AWNziRPEVMdjfBuyykuI,11895
|
|
50
|
+
stratifyai/utils/provider_validator.py,sha256=LUBZebd8MZFXPoUDFOTJ6JxMkJG9CbcrJNHZiK--WCU,14864
|
|
51
51
|
stratifyai/utils/token_counter.py,sha256=58hkX3q4yObZVwo3lvn7OGPh7puiWNind7yX3Qem_1o,6432
|
|
52
|
-
stratifyai-0.1.
|
|
53
|
-
stratifyai-0.1.
|
|
54
|
-
stratifyai-0.1.
|
|
55
|
-
stratifyai-0.1.
|
|
56
|
-
stratifyai-0.1.
|
|
57
|
-
stratifyai-0.1.
|
|
52
|
+
stratifyai-0.1.2.dist-info/licenses/LICENSE,sha256=UEMslgLRhi7sYtDIwMY0IjEppiVEgqgMIdsulgYdb0Q,1068
|
|
53
|
+
stratifyai-0.1.2.dist-info/METADATA,sha256=TDiyf0lPvlatnehrAaKHvzOawaqGJ-nXutUalR0xxM4,7872
|
|
54
|
+
stratifyai-0.1.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
55
|
+
stratifyai-0.1.2.dist-info/entry_points.txt,sha256=aWXYCRBSld8hzAtCPAqsl2NHKJIJkIgc63uQOO2PcUQ,55
|
|
56
|
+
stratifyai-0.1.2.dist-info/top_level.txt,sha256=0_JiuYll_AXJr5e4qXzbCs8LYykDxGaEjawwI69vEhM,15
|
|
57
|
+
stratifyai-0.1.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|