stratifyai 0.1.2__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.
- api/__init__.py +3 -0
- api/main.py +763 -0
- api/static/index.html +1126 -0
- api/static/models.html +567 -0
- api/static/stratifyai_trans_logo.png +0 -0
- api/static/stratifyai_wide_logo.png +0 -0
- api/static/stratum_logo.png +0 -0
- {stratifyai-0.1.2.dist-info → stratifyai-0.1.3.dist-info}/METADATA +4 -1
- {stratifyai-0.1.2.dist-info → stratifyai-0.1.3.dist-info}/RECORD +13 -6
- {stratifyai-0.1.2.dist-info → stratifyai-0.1.3.dist-info}/top_level.txt +1 -0
- {stratifyai-0.1.2.dist-info → stratifyai-0.1.3.dist-info}/WHEEL +0 -0
- {stratifyai-0.1.2.dist-info → stratifyai-0.1.3.dist-info}/entry_points.txt +0 -0
- {stratifyai-0.1.2.dist-info → stratifyai-0.1.3.dist-info}/licenses/LICENSE +0 -0
api/static/models.html
ADDED
|
@@ -0,0 +1,567 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>StratifyAI - Model Catalog</title>
|
|
7
|
+
<style>
|
|
8
|
+
* {
|
|
9
|
+
margin: 0;
|
|
10
|
+
padding: 0;
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
body {
|
|
15
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
16
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
17
|
+
min-height: 100vh;
|
|
18
|
+
padding: 20px;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.container {
|
|
22
|
+
max-width: 1400px;
|
|
23
|
+
margin: 0 auto;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.header {
|
|
27
|
+
background: white;
|
|
28
|
+
padding: 20px 30px;
|
|
29
|
+
border-radius: 10px;
|
|
30
|
+
margin-bottom: 20px;
|
|
31
|
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
32
|
+
display: flex;
|
|
33
|
+
justify-content: space-between;
|
|
34
|
+
align-items: center;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.header h1 {
|
|
38
|
+
color: #667eea;
|
|
39
|
+
display: flex;
|
|
40
|
+
align-items: center;
|
|
41
|
+
gap: 15px;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.header h1 img {
|
|
45
|
+
height: 40px;
|
|
46
|
+
width: auto;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.back-btn {
|
|
50
|
+
background: #667eea;
|
|
51
|
+
color: white;
|
|
52
|
+
border: none;
|
|
53
|
+
padding: 10px 20px;
|
|
54
|
+
border-radius: 5px;
|
|
55
|
+
cursor: pointer;
|
|
56
|
+
font-weight: 500;
|
|
57
|
+
text-decoration: none;
|
|
58
|
+
transition: background 0.3s;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.back-btn:hover {
|
|
62
|
+
background: #5568d3;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.summary-bar {
|
|
66
|
+
background: white;
|
|
67
|
+
padding: 15px 25px;
|
|
68
|
+
border-radius: 10px;
|
|
69
|
+
margin-bottom: 20px;
|
|
70
|
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
71
|
+
display: flex;
|
|
72
|
+
gap: 30px;
|
|
73
|
+
flex-wrap: wrap;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.summary-item {
|
|
77
|
+
display: flex;
|
|
78
|
+
align-items: center;
|
|
79
|
+
gap: 8px;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.summary-item .label {
|
|
83
|
+
color: #666;
|
|
84
|
+
font-size: 14px;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.summary-item .value {
|
|
88
|
+
font-weight: 600;
|
|
89
|
+
color: #333;
|
|
90
|
+
font-size: 18px;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.filters {
|
|
94
|
+
background: white;
|
|
95
|
+
padding: 15px 25px;
|
|
96
|
+
border-radius: 10px;
|
|
97
|
+
margin-bottom: 20px;
|
|
98
|
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
99
|
+
display: flex;
|
|
100
|
+
gap: 20px;
|
|
101
|
+
align-items: center;
|
|
102
|
+
flex-wrap: wrap;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.filter-group {
|
|
106
|
+
display: flex;
|
|
107
|
+
align-items: center;
|
|
108
|
+
gap: 8px;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.filter-group label {
|
|
112
|
+
color: #666;
|
|
113
|
+
font-size: 14px;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.filter-group select,
|
|
117
|
+
.filter-group input {
|
|
118
|
+
padding: 8px 12px;
|
|
119
|
+
border: 1px solid #ddd;
|
|
120
|
+
border-radius: 5px;
|
|
121
|
+
font-size: 14px;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.filter-group input[type="checkbox"] {
|
|
125
|
+
width: 18px;
|
|
126
|
+
height: 18px;
|
|
127
|
+
cursor: pointer;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.main-content {
|
|
131
|
+
background: white;
|
|
132
|
+
padding: 20px;
|
|
133
|
+
border-radius: 10px;
|
|
134
|
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
135
|
+
overflow-x: auto;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.provider-section {
|
|
139
|
+
margin-bottom: 30px;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.provider-header {
|
|
143
|
+
display: flex;
|
|
144
|
+
align-items: center;
|
|
145
|
+
gap: 15px;
|
|
146
|
+
margin-bottom: 15px;
|
|
147
|
+
padding-bottom: 10px;
|
|
148
|
+
border-bottom: 2px solid #eee;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.provider-name {
|
|
152
|
+
font-size: 20px;
|
|
153
|
+
font-weight: 600;
|
|
154
|
+
color: #333;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.provider-status {
|
|
158
|
+
padding: 4px 12px;
|
|
159
|
+
border-radius: 20px;
|
|
160
|
+
font-size: 12px;
|
|
161
|
+
font-weight: 500;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.provider-status.active {
|
|
165
|
+
background: #dcfce7;
|
|
166
|
+
color: #166534;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.provider-status.inactive {
|
|
170
|
+
background: #fef3c7;
|
|
171
|
+
color: #92400e;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.provider-meta {
|
|
175
|
+
font-size: 13px;
|
|
176
|
+
color: #666;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
table {
|
|
180
|
+
width: 100%;
|
|
181
|
+
border-collapse: collapse;
|
|
182
|
+
font-size: 14px;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
th, td {
|
|
186
|
+
padding: 12px 15px;
|
|
187
|
+
text-align: left;
|
|
188
|
+
border-bottom: 1px solid #eee;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
th {
|
|
192
|
+
background: #f8f9fa;
|
|
193
|
+
font-weight: 600;
|
|
194
|
+
color: #333;
|
|
195
|
+
position: sticky;
|
|
196
|
+
top: 0;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
tr:hover {
|
|
200
|
+
background: #f8f9fa;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.model-name {
|
|
204
|
+
font-weight: 500;
|
|
205
|
+
color: #333;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.cost {
|
|
209
|
+
font-family: 'SFMono-Regular', Consolas, monospace;
|
|
210
|
+
color: #666;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.context {
|
|
214
|
+
font-family: 'SFMono-Regular', Consolas, monospace;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.capability {
|
|
218
|
+
display: inline-block;
|
|
219
|
+
padding: 3px 8px;
|
|
220
|
+
border-radius: 4px;
|
|
221
|
+
font-size: 11px;
|
|
222
|
+
font-weight: 500;
|
|
223
|
+
margin: 2px;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.capability.vision {
|
|
227
|
+
background: #dbeafe;
|
|
228
|
+
color: #1e40af;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.capability.tools {
|
|
232
|
+
background: #fce7f3;
|
|
233
|
+
color: #be185d;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.capability.caching {
|
|
237
|
+
background: #d1fae5;
|
|
238
|
+
color: #047857;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.capability.reasoning {
|
|
242
|
+
background: #fef3c7;
|
|
243
|
+
color: #92400e;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.validated-badge {
|
|
247
|
+
display: inline-block;
|
|
248
|
+
padding: 3px 8px;
|
|
249
|
+
border-radius: 4px;
|
|
250
|
+
font-size: 11px;
|
|
251
|
+
font-weight: 500;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.validated-badge.yes {
|
|
255
|
+
background: #dcfce7;
|
|
256
|
+
color: #166534;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.validated-badge.no {
|
|
260
|
+
background: #fee2e2;
|
|
261
|
+
color: #991b1b;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.loading {
|
|
265
|
+
text-align: center;
|
|
266
|
+
padding: 50px;
|
|
267
|
+
color: #666;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.loading-spinner {
|
|
271
|
+
display: inline-block;
|
|
272
|
+
width: 40px;
|
|
273
|
+
height: 40px;
|
|
274
|
+
border: 4px solid #f3f3f3;
|
|
275
|
+
border-top: 4px solid #667eea;
|
|
276
|
+
border-radius: 50%;
|
|
277
|
+
animation: spin 1s linear infinite;
|
|
278
|
+
margin-bottom: 15px;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
@keyframes spin {
|
|
282
|
+
0% { transform: rotate(0deg); }
|
|
283
|
+
100% { transform: rotate(360deg); }
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.error-message {
|
|
287
|
+
background: #fee2e2;
|
|
288
|
+
color: #991b1b;
|
|
289
|
+
padding: 15px 20px;
|
|
290
|
+
border-radius: 8px;
|
|
291
|
+
margin-bottom: 20px;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.no-models {
|
|
295
|
+
color: #666;
|
|
296
|
+
font-style: italic;
|
|
297
|
+
padding: 20px;
|
|
298
|
+
text-align: center;
|
|
299
|
+
}
|
|
300
|
+
</style>
|
|
301
|
+
</head>
|
|
302
|
+
<body>
|
|
303
|
+
<div class="container">
|
|
304
|
+
<div class="header">
|
|
305
|
+
<h1>
|
|
306
|
+
<img src="/static/stratifyai_wide_logo.png" alt="StratifyAI Logo">
|
|
307
|
+
Model Catalog
|
|
308
|
+
</h1>
|
|
309
|
+
<a href="/" class="back-btn">← Back to Chat</a>
|
|
310
|
+
</div>
|
|
311
|
+
|
|
312
|
+
<div class="summary-bar" id="summary-bar">
|
|
313
|
+
<div class="summary-item">
|
|
314
|
+
<span class="label">Total Models:</span>
|
|
315
|
+
<span class="value" id="total-models">-</span>
|
|
316
|
+
</div>
|
|
317
|
+
<div class="summary-item">
|
|
318
|
+
<span class="label">Providers:</span>
|
|
319
|
+
<span class="value" id="total-providers">-</span>
|
|
320
|
+
</div>
|
|
321
|
+
<div class="summary-item">
|
|
322
|
+
<span class="label">Active Providers:</span>
|
|
323
|
+
<span class="value" id="active-providers">-</span>
|
|
324
|
+
</div>
|
|
325
|
+
</div>
|
|
326
|
+
|
|
327
|
+
<div class="filters">
|
|
328
|
+
<div class="filter-group">
|
|
329
|
+
<label for="provider-filter">Provider:</label>
|
|
330
|
+
<select id="provider-filter">
|
|
331
|
+
<option value="">All Providers</option>
|
|
332
|
+
</select>
|
|
333
|
+
</div>
|
|
334
|
+
<div class="filter-group">
|
|
335
|
+
<label for="capability-filter">Capability:</label>
|
|
336
|
+
<select id="capability-filter">
|
|
337
|
+
<option value="">All Capabilities</option>
|
|
338
|
+
<option value="vision">Vision</option>
|
|
339
|
+
<option value="tools">Tools</option>
|
|
340
|
+
<option value="caching">Caching</option>
|
|
341
|
+
<option value="reasoning">Reasoning</option>
|
|
342
|
+
</select>
|
|
343
|
+
</div>
|
|
344
|
+
<div class="filter-group">
|
|
345
|
+
<input type="checkbox" id="active-only">
|
|
346
|
+
<label for="active-only">Active providers only</label>
|
|
347
|
+
</div>
|
|
348
|
+
<div class="filter-group">
|
|
349
|
+
<input type="checkbox" id="validated-only">
|
|
350
|
+
<label for="validated-only">Validated models only</label>
|
|
351
|
+
</div>
|
|
352
|
+
<div class="filter-group">
|
|
353
|
+
<button id="reset-filters" style="background: #6b7280; color: white; border: none; padding: 8px 16px; border-radius: 5px; cursor: pointer; font-weight: 500;">🔄 Reset Filters</button>
|
|
354
|
+
</div>
|
|
355
|
+
</div>
|
|
356
|
+
|
|
357
|
+
<div class="main-content" id="main-content">
|
|
358
|
+
<div class="loading">
|
|
359
|
+
<div class="loading-spinner"></div>
|
|
360
|
+
<p>Loading model catalog...</p>
|
|
361
|
+
</div>
|
|
362
|
+
</div>
|
|
363
|
+
</div>
|
|
364
|
+
|
|
365
|
+
<script>
|
|
366
|
+
const API_BASE = 'http://localhost:8080';
|
|
367
|
+
let allData = null;
|
|
368
|
+
|
|
369
|
+
// Format cost for display
|
|
370
|
+
function formatCost(cost) {
|
|
371
|
+
if (cost === 0 || cost === null || cost === undefined) return '-';
|
|
372
|
+
if (cost < 0.01) return `$${cost.toFixed(4)}`;
|
|
373
|
+
return `$${cost.toFixed(2)}`;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Format context window for display
|
|
377
|
+
function formatContext(context) {
|
|
378
|
+
if (!context) return '-';
|
|
379
|
+
if (context >= 1000000) return `${(context / 1000000).toFixed(1)}M`;
|
|
380
|
+
if (context >= 1000) return `${(context / 1000).toFixed(0)}K`;
|
|
381
|
+
return context.toString();
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// Capitalize provider name
|
|
385
|
+
function capitalizeProvider(provider) {
|
|
386
|
+
const special = {
|
|
387
|
+
'openai': 'OpenAI',
|
|
388
|
+
'anthropic': 'Anthropic',
|
|
389
|
+
'google': 'Google',
|
|
390
|
+
'deepseek': 'DeepSeek',
|
|
391
|
+
'groq': 'Groq',
|
|
392
|
+
'grok': 'Grok (X.AI)',
|
|
393
|
+
'ollama': 'Ollama',
|
|
394
|
+
'openrouter': 'OpenRouter',
|
|
395
|
+
'bedrock': 'AWS Bedrock'
|
|
396
|
+
};
|
|
397
|
+
return special[provider] || provider.charAt(0).toUpperCase() + provider.slice(1);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Build capabilities badges
|
|
401
|
+
function buildCapabilities(model) {
|
|
402
|
+
let badges = [];
|
|
403
|
+
if (model.supports_vision) badges.push('<span class="capability vision">👁️ Vision</span>');
|
|
404
|
+
if (model.supports_tools) badges.push('<span class="capability tools">🔧 Tools</span>');
|
|
405
|
+
if (model.supports_caching) badges.push('<span class="capability caching">💾 Caching</span>');
|
|
406
|
+
if (model.reasoning_model) badges.push('<span class="capability reasoning">🧠 Reasoning</span>');
|
|
407
|
+
return badges.length > 0 ? badges.join('') : '<span style="color: #999;">-</span>';
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// Render models table
|
|
411
|
+
function renderModels() {
|
|
412
|
+
if (!allData) return;
|
|
413
|
+
|
|
414
|
+
const providerFilter = document.getElementById('provider-filter').value;
|
|
415
|
+
const capabilityFilter = document.getElementById('capability-filter').value;
|
|
416
|
+
const activeOnly = document.getElementById('active-only').checked;
|
|
417
|
+
const validatedOnly = document.getElementById('validated-only').checked;
|
|
418
|
+
|
|
419
|
+
const container = document.getElementById('main-content');
|
|
420
|
+
let html = '';
|
|
421
|
+
|
|
422
|
+
// Get providers in order
|
|
423
|
+
const providerOrder = ['openai', 'anthropic', 'google', 'deepseek', 'groq', 'grok', 'ollama', 'openrouter', 'bedrock'];
|
|
424
|
+
const providers = providerFilter ? [providerFilter] : providerOrder;
|
|
425
|
+
|
|
426
|
+
for (const provider of providers) {
|
|
427
|
+
const providerData = allData.providers[provider];
|
|
428
|
+
if (!providerData) continue;
|
|
429
|
+
|
|
430
|
+
// Filter by active status
|
|
431
|
+
if (activeOnly && !providerData.active) continue;
|
|
432
|
+
|
|
433
|
+
// Filter models
|
|
434
|
+
let models = providerData.models || [];
|
|
435
|
+
|
|
436
|
+
if (capabilityFilter) {
|
|
437
|
+
models = models.filter(m => {
|
|
438
|
+
switch (capabilityFilter) {
|
|
439
|
+
case 'vision': return m.supports_vision;
|
|
440
|
+
case 'tools': return m.supports_tools;
|
|
441
|
+
case 'caching': return m.supports_caching;
|
|
442
|
+
case 'reasoning': return m.reasoning_model;
|
|
443
|
+
default: return true;
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
if (validatedOnly) {
|
|
449
|
+
models = models.filter(m => m.validated);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
if (models.length === 0) continue;
|
|
453
|
+
|
|
454
|
+
// Build provider section
|
|
455
|
+
html += `
|
|
456
|
+
<div class="provider-section">
|
|
457
|
+
<div class="provider-header">
|
|
458
|
+
<span class="provider-name">${capitalizeProvider(provider)}</span>
|
|
459
|
+
<span class="provider-status ${providerData.active ? 'active' : 'inactive'}">
|
|
460
|
+
${providerData.active ? '✓ Active' : '⚠ No API Key'}
|
|
461
|
+
</span>
|
|
462
|
+
<span class="provider-meta">${models.length} model${models.length !== 1 ? 's' : ''}</span>
|
|
463
|
+
${providerData.validation_error ? `<span class="provider-meta" style="color: #dc2626;">⚠ ${providerData.validation_error}</span>` : ''}
|
|
464
|
+
</div>
|
|
465
|
+
<table>
|
|
466
|
+
<thead>
|
|
467
|
+
<tr>
|
|
468
|
+
<th>Model</th>
|
|
469
|
+
<th>Context</th>
|
|
470
|
+
<th>Cost (Input)</th>
|
|
471
|
+
<th>Cost (Output)</th>
|
|
472
|
+
<th>Capabilities</th>
|
|
473
|
+
<th>Validated</th>
|
|
474
|
+
</tr>
|
|
475
|
+
</thead>
|
|
476
|
+
<tbody>
|
|
477
|
+
`;
|
|
478
|
+
|
|
479
|
+
for (const model of models) {
|
|
480
|
+
html += `
|
|
481
|
+
<tr>
|
|
482
|
+
<td class="model-name">${model.id}</td>
|
|
483
|
+
<td class="context">${formatContext(model.context_window)}</td>
|
|
484
|
+
<td class="cost">${formatCost(model.cost_input)}/1M</td>
|
|
485
|
+
<td class="cost">${formatCost(model.cost_output)}/1M</td>
|
|
486
|
+
<td>${buildCapabilities(model)}</td>
|
|
487
|
+
<td>
|
|
488
|
+
<span class="validated-badge ${model.validated ? 'yes' : 'no'}">
|
|
489
|
+
${model.validated ? '✓ Yes' : '✗ No'}
|
|
490
|
+
</span>
|
|
491
|
+
</td>
|
|
492
|
+
</tr>
|
|
493
|
+
`;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
html += `
|
|
497
|
+
</tbody>
|
|
498
|
+
</table>
|
|
499
|
+
</div>
|
|
500
|
+
`;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
if (!html) {
|
|
504
|
+
html = '<div class="no-models">No models match the current filters.</div>';
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
container.innerHTML = html;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// Load data
|
|
511
|
+
async function loadData() {
|
|
512
|
+
try {
|
|
513
|
+
const response = await fetch(`${API_BASE}/api/all-models`);
|
|
514
|
+
if (!response.ok) throw new Error('Failed to load models');
|
|
515
|
+
|
|
516
|
+
allData = await response.json();
|
|
517
|
+
|
|
518
|
+
// Update summary
|
|
519
|
+
document.getElementById('total-models').textContent = allData.summary.total_models;
|
|
520
|
+
document.getElementById('total-providers').textContent = allData.summary.total_providers;
|
|
521
|
+
document.getElementById('active-providers').textContent = allData.summary.active_providers;
|
|
522
|
+
|
|
523
|
+
// Populate provider filter
|
|
524
|
+
const providerFilter = document.getElementById('provider-filter');
|
|
525
|
+
const providerOrder = ['openai', 'anthropic', 'google', 'deepseek', 'groq', 'grok', 'ollama', 'openrouter', 'bedrock'];
|
|
526
|
+
for (const provider of providerOrder) {
|
|
527
|
+
if (allData.providers[provider]) {
|
|
528
|
+
const option = document.createElement('option');
|
|
529
|
+
option.value = provider;
|
|
530
|
+
option.textContent = capitalizeProvider(provider);
|
|
531
|
+
providerFilter.appendChild(option);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// Render models
|
|
536
|
+
renderModels();
|
|
537
|
+
|
|
538
|
+
} catch (error) {
|
|
539
|
+
document.getElementById('main-content').innerHTML = `
|
|
540
|
+
<div class="error-message">
|
|
541
|
+
❌ Error loading model catalog: ${error.message}
|
|
542
|
+
</div>
|
|
543
|
+
`;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// Reset filters
|
|
548
|
+
function resetFilters() {
|
|
549
|
+
document.getElementById('provider-filter').value = '';
|
|
550
|
+
document.getElementById('capability-filter').value = '';
|
|
551
|
+
document.getElementById('active-only').checked = false;
|
|
552
|
+
document.getElementById('validated-only').checked = false;
|
|
553
|
+
renderModels();
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// Event listeners for filters
|
|
557
|
+
document.getElementById('provider-filter').addEventListener('change', renderModels);
|
|
558
|
+
document.getElementById('capability-filter').addEventListener('change', renderModels);
|
|
559
|
+
document.getElementById('active-only').addEventListener('change', renderModels);
|
|
560
|
+
document.getElementById('validated-only').addEventListener('change', renderModels);
|
|
561
|
+
document.getElementById('reset-filters').addEventListener('click', resetFilters);
|
|
562
|
+
|
|
563
|
+
// Initialize
|
|
564
|
+
loadData();
|
|
565
|
+
</script>
|
|
566
|
+
</body>
|
|
567
|
+
</html>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: stratifyai
|
|
3
|
-
Version: 0.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"
|
|
@@ -1,3 +1,10 @@
|
|
|
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
9
|
cli/stratifyai_cli.py,sha256=qdOcLDS3yjOSLJplQkc7PQK4kUDhaBpy8AV7XPh-8_c,111826
|
|
3
10
|
stratifyai/__init__.py,sha256=yjmHcAcorD5txlNZwmamljOnN3nHCosBY2_0CE26TaE,2873
|
|
@@ -49,9 +56,9 @@ stratifyai/utils/log_extractor.py,sha256=Nz2x9xPvRVdp5yk6cTLQ5CHK4Fi5oNKQG2t2k9e
|
|
|
49
56
|
stratifyai/utils/model_selector.py,sha256=xoaJ4rHhsqHTbEUnINeT267AWNziRPEVMdjfBuyykuI,11895
|
|
50
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.
|
|
53
|
-
stratifyai-0.1.
|
|
54
|
-
stratifyai-0.1.
|
|
55
|
-
stratifyai-0.1.
|
|
56
|
-
stratifyai-0.1.
|
|
57
|
-
stratifyai-0.1.
|
|
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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|