rohitsar567 commited on
Commit
b270b1a
Β·
verified Β·
1 Parent(s): 853868a

Deploy: Stack A (NIM brain + Maverick judge + Sarvam voice). D-019.

Browse files
Files changed (2) hide show
  1. 40-data/llm_health.json +132 -132
  2. backend/main.py +34 -1
40-data/llm_health.json CHANGED
@@ -1,22 +1,16 @@
1
  {
2
- "updated_at": "2026-05-15T01:52:30Z",
3
  "models": {
4
  "qwen/qwen3-next-80b-a3b-instruct": {
5
  "model": "qwen/qwen3-next-80b-a3b-instruct",
6
  "status": "healthy",
7
- "last_success_at": "2026-05-15T01:52:30Z",
8
  "last_failure_at": null,
9
  "last_error": null,
10
- "latency_ms": 1208,
11
  "consecutive_failures": 0,
12
- "tested_at": "2026-05-15T01:52:30Z",
13
  "probe_history": [
14
- {
15
- "ok": true,
16
- "latency_ms": 458,
17
- "ts": "2026-05-15T01:38:54Z",
18
- "src": "probe"
19
- },
20
  {
21
  "ok": true,
22
  "latency_ms": 285,
@@ -40,6 +34,12 @@
40
  "latency_ms": 1208,
41
  "ts": "2026-05-15T01:52:30Z",
42
  "src": "probe"
 
 
 
 
 
 
43
  }
44
  ],
45
  "degraded_until_monotonic": 0.0,
@@ -53,18 +53,12 @@
53
  "model": "qwen/qwen3.5-122b-a10b",
54
  "status": "down",
55
  "last_success_at": null,
56
- "last_failure_at": "2026-05-15T01:52:30Z",
57
  "last_error": "timeout",
58
  "latency_ms": null,
59
- "consecutive_failures": 17,
60
- "tested_at": "2026-05-15T01:52:30Z",
61
  "probe_history": [
62
- {
63
- "ok": false,
64
- "latency_ms": 8003,
65
- "ts": "2026-05-15T01:38:54Z",
66
- "src": "probe"
67
- },
68
  {
69
  "ok": false,
70
  "latency_ms": 8001,
@@ -88,6 +82,12 @@
88
  "latency_ms": 8001,
89
  "ts": "2026-05-15T01:52:30Z",
90
  "src": "probe"
 
 
 
 
 
 
91
  }
92
  ],
93
  "degraded_until_monotonic": 0.0,
@@ -101,18 +101,12 @@
101
  "model": "openai/gpt-oss-120b",
102
  "status": "down",
103
  "last_success_at": null,
104
- "last_failure_at": "2026-05-15T01:52:30Z",
105
  "last_error": "empty_content",
106
  "latency_ms": null,
107
- "consecutive_failures": 17,
108
- "tested_at": "2026-05-15T01:52:30Z",
109
  "probe_history": [
110
- {
111
- "ok": false,
112
- "latency_ms": 399,
113
- "ts": "2026-05-15T01:38:54Z",
114
- "src": "probe"
115
- },
116
  {
117
  "ok": false,
118
  "latency_ms": 261,
@@ -136,6 +130,12 @@
136
  "latency_ms": 253,
137
  "ts": "2026-05-15T01:52:30Z",
138
  "src": "probe"
 
 
 
 
 
 
139
  }
140
  ],
141
  "degraded_until_monotonic": 0.0,
@@ -147,20 +147,14 @@
147
  },
148
  "mistralai/mistral-large-3-675b-instruct-2512": {
149
  "model": "mistralai/mistral-large-3-675b-instruct-2512",
150
- "status": "degraded",
151
- "last_success_at": "2026-05-15T01:46:37Z",
152
  "last_failure_at": "2026-05-15T01:52:30Z",
153
- "last_error": "timeout",
154
- "latency_ms": 449,
155
- "consecutive_failures": 1,
156
- "tested_at": "2026-05-15T01:52:30Z",
157
  "probe_history": [
158
- {
159
- "ok": true,
160
- "latency_ms": 709,
161
- "ts": "2026-05-15T01:38:54Z",
162
- "src": "probe"
163
- },
164
  {
165
  "ok": true,
166
  "latency_ms": 782,
@@ -184,6 +178,12 @@
184
  "latency_ms": 8002,
185
  "ts": "2026-05-15T01:52:30Z",
186
  "src": "probe"
 
 
 
 
 
 
187
  }
188
  ],
189
  "degraded_until_monotonic": 0.0,
@@ -195,20 +195,14 @@
195
  },
196
  "nvidia/llama-3.3-nemotron-super-49b-v1.5": {
197
  "model": "nvidia/llama-3.3-nemotron-super-49b-v1.5",
198
- "status": "healthy",
199
- "last_success_at": "2026-05-15T01:52:30Z",
200
  "last_failure_at": "2026-05-15T01:24:45Z",
201
  "last_error": null,
202
- "latency_ms": 349,
203
  "consecutive_failures": 0,
204
- "tested_at": "2026-05-15T01:52:30Z",
205
  "probe_history": [
206
- {
207
- "ok": true,
208
- "latency_ms": 4820,
209
- "ts": "2026-05-15T01:38:54Z",
210
- "src": "probe"
211
- },
212
  {
213
  "ok": true,
214
  "latency_ms": 385,
@@ -232,6 +226,12 @@
232
  "latency_ms": 349,
233
  "ts": "2026-05-15T01:52:30Z",
234
  "src": "probe"
 
 
 
 
 
 
235
  }
236
  ],
237
  "degraded_until_monotonic": 0.0,
@@ -244,19 +244,13 @@
244
  "meta/llama-3.3-70b-instruct": {
245
  "model": "meta/llama-3.3-70b-instruct",
246
  "status": "healthy",
247
- "last_success_at": "2026-05-15T01:52:30Z",
248
  "last_failure_at": "2026-05-15T01:41:07Z",
249
  "last_error": null,
250
- "latency_ms": 212,
251
  "consecutive_failures": 0,
252
- "tested_at": "2026-05-15T01:52:30Z",
253
  "probe_history": [
254
- {
255
- "ok": true,
256
- "latency_ms": 511,
257
- "ts": "2026-05-15T01:38:54Z",
258
- "src": "probe"
259
- },
260
  {
261
  "ok": false,
262
  "latency_ms": 8003,
@@ -280,6 +274,12 @@
280
  "latency_ms": 212,
281
  "ts": "2026-05-15T01:52:30Z",
282
  "src": "probe"
 
 
 
 
 
 
283
  }
284
  ],
285
  "degraded_until_monotonic": 0.0,
@@ -293,18 +293,12 @@
293
  "model": "deepseek-ai/deepseek-v4-pro",
294
  "status": "down",
295
  "last_success_at": null,
296
- "last_failure_at": "2026-05-15T01:52:30Z",
297
  "last_error": "timeout",
298
  "latency_ms": null,
299
- "consecutive_failures": 17,
300
- "tested_at": "2026-05-15T01:52:30Z",
301
  "probe_history": [
302
- {
303
- "ok": false,
304
- "latency_ms": 8002,
305
- "ts": "2026-05-15T01:38:54Z",
306
- "src": "probe"
307
- },
308
  {
309
  "ok": false,
310
  "latency_ms": 8059,
@@ -328,6 +322,12 @@
328
  "latency_ms": 8003,
329
  "ts": "2026-05-15T01:52:30Z",
330
  "src": "probe"
 
 
 
 
 
 
331
  }
332
  ],
333
  "degraded_until_monotonic": 0.0,
@@ -341,18 +341,12 @@
341
  "model": "nvidia/nemotron-3-nano-30b-a3b",
342
  "status": "down",
343
  "last_success_at": null,
344
- "last_failure_at": "2026-05-15T01:52:30Z",
345
  "last_error": "empty_content",
346
  "latency_ms": null,
347
- "consecutive_failures": 17,
348
- "tested_at": "2026-05-15T01:52:30Z",
349
  "probe_history": [
350
- {
351
- "ok": false,
352
- "latency_ms": 267,
353
- "ts": "2026-05-15T01:38:54Z",
354
- "src": "probe"
355
- },
356
  {
357
  "ok": false,
358
  "latency_ms": 271,
@@ -376,6 +370,12 @@
376
  "latency_ms": 263,
377
  "ts": "2026-05-15T01:52:30Z",
378
  "src": "probe"
 
 
 
 
 
 
379
  }
380
  ],
381
  "degraded_until_monotonic": 0.0,
@@ -389,18 +389,12 @@
389
  "model": "deepseek-ai/deepseek-v4-flash",
390
  "status": "down",
391
  "last_success_at": null,
392
- "last_failure_at": "2026-05-15T01:52:30Z",
393
  "last_error": "timeout",
394
  "latency_ms": null,
395
- "consecutive_failures": 17,
396
- "tested_at": "2026-05-15T01:52:30Z",
397
  "probe_history": [
398
- {
399
- "ok": false,
400
- "latency_ms": 8002,
401
- "ts": "2026-05-15T01:38:54Z",
402
- "src": "probe"
403
- },
404
  {
405
  "ok": false,
406
  "latency_ms": 8002,
@@ -424,6 +418,12 @@
424
  "latency_ms": 8004,
425
  "ts": "2026-05-15T01:52:30Z",
426
  "src": "probe"
 
 
 
 
 
 
427
  }
428
  ],
429
  "degraded_until_monotonic": 0.0,
@@ -437,18 +437,12 @@
437
  "model": "moonshotai/kimi-k2-instruct-0905",
438
  "status": "down",
439
  "last_success_at": null,
440
- "last_failure_at": "2026-05-15T01:52:30Z",
441
  "last_error": "http_404",
442
  "latency_ms": null,
443
- "consecutive_failures": 17,
444
- "tested_at": "2026-05-15T01:52:30Z",
445
  "probe_history": [
446
- {
447
- "ok": false,
448
- "latency_ms": 82,
449
- "ts": "2026-05-15T01:38:54Z",
450
- "src": "probe"
451
- },
452
  {
453
  "ok": false,
454
  "latency_ms": 84,
@@ -472,6 +466,12 @@
472
  "latency_ms": 84,
473
  "ts": "2026-05-15T01:52:30Z",
474
  "src": "probe"
 
 
 
 
 
 
475
  }
476
  ],
477
  "degraded_until_monotonic": 0.0,
@@ -485,18 +485,12 @@
485
  "model": "minimaxai/minimax-m2.5",
486
  "status": "down",
487
  "last_success_at": null,
488
- "last_failure_at": "2026-05-15T01:52:30Z",
489
  "last_error": "http_410",
490
  "latency_ms": null,
491
- "consecutive_failures": 17,
492
- "tested_at": "2026-05-15T01:52:30Z",
493
  "probe_history": [
494
- {
495
- "ok": false,
496
- "latency_ms": 30,
497
- "ts": "2026-05-15T01:38:54Z",
498
- "src": "probe"
499
- },
500
  {
501
  "ok": false,
502
  "latency_ms": 32,
@@ -520,6 +514,12 @@
520
  "latency_ms": 29,
521
  "ts": "2026-05-15T01:52:30Z",
522
  "src": "probe"
 
 
 
 
 
 
523
  }
524
  ],
525
  "degraded_until_monotonic": 0.0,
@@ -532,19 +532,13 @@
532
  "meta/llama-4-maverick-17b-128e-instruct": {
533
  "model": "meta/llama-4-maverick-17b-128e-instruct",
534
  "status": "healthy",
535
- "last_success_at": "2026-05-15T01:52:30Z",
536
  "last_failure_at": "2026-05-14T01:03:07Z",
537
  "last_error": null,
538
- "latency_ms": 205,
539
  "consecutive_failures": 0,
540
- "tested_at": "2026-05-15T01:52:30Z",
541
  "probe_history": [
542
- {
543
- "ok": true,
544
- "latency_ms": 282,
545
- "ts": "2026-05-15T01:38:54Z",
546
- "src": "probe"
547
- },
548
  {
549
  "ok": true,
550
  "latency_ms": 313,
@@ -568,6 +562,12 @@
568
  "latency_ms": 205,
569
  "ts": "2026-05-15T01:52:30Z",
570
  "src": "probe"
 
 
 
 
 
 
571
  }
572
  ],
573
  "degraded_until_monotonic": 0.0,
@@ -581,18 +581,12 @@
581
  "model": "openrouter:openai/gpt-oss-120b",
582
  "status": "degraded",
583
  "last_success_at": "2026-05-15T01:46:37Z",
584
- "last_failure_at": "2026-05-15T01:52:30Z",
585
  "last_error": "empty_content",
586
  "latency_ms": 1349,
587
- "consecutive_failures": 1,
588
- "tested_at": "2026-05-15T01:52:30Z",
589
  "probe_history": [
590
- {
591
- "ok": false,
592
- "latency_ms": 891,
593
- "ts": "2026-05-15T01:38:54Z",
594
- "src": "probe"
595
- },
596
  {
597
  "ok": true,
598
  "latency_ms": 4642,
@@ -616,31 +610,31 @@
616
  "latency_ms": 1635,
617
  "ts": "2026-05-15T01:52:30Z",
618
  "src": "probe"
 
 
 
 
 
 
619
  }
620
  ],
621
  "degraded_until_monotonic": 0.0,
622
  "credits_remaining": 0.0,
623
  "credits_unit": "usd_balance",
624
  "credits_reset_at": null,
625
- "credits_observed_at": 5039.664027625,
626
  "credits_low_water": 0.05
627
  },
628
  "groq:llama-3.3-70b-versatile": {
629
  "model": "groq:llama-3.3-70b-versatile",
630
  "status": "healthy",
631
- "last_success_at": "2026-05-15T01:52:30Z",
632
  "last_failure_at": null,
633
  "last_error": null,
634
- "latency_ms": 247,
635
  "consecutive_failures": 0,
636
- "tested_at": "2026-05-15T01:52:30Z",
637
  "probe_history": [
638
- {
639
- "ok": true,
640
- "latency_ms": 154,
641
- "ts": "2026-05-15T01:38:54Z",
642
- "src": "probe"
643
- },
644
  {
645
  "ok": true,
646
  "latency_ms": 285,
@@ -664,6 +658,12 @@
664
  "latency_ms": 247,
665
  "ts": "2026-05-15T01:52:30Z",
666
  "src": "probe"
 
 
 
 
 
 
667
  }
668
  ],
669
  "degraded_until_monotonic": 0.0,
 
1
  {
2
+ "updated_at": "2026-05-15T01:54:30Z",
3
  "models": {
4
  "qwen/qwen3-next-80b-a3b-instruct": {
5
  "model": "qwen/qwen3-next-80b-a3b-instruct",
6
  "status": "healthy",
7
+ "last_success_at": "2026-05-15T01:54:30Z",
8
  "last_failure_at": null,
9
  "last_error": null,
10
+ "latency_ms": 771,
11
  "consecutive_failures": 0,
12
+ "tested_at": "2026-05-15T01:54:30Z",
13
  "probe_history": [
 
 
 
 
 
 
14
  {
15
  "ok": true,
16
  "latency_ms": 285,
 
34
  "latency_ms": 1208,
35
  "ts": "2026-05-15T01:52:30Z",
36
  "src": "probe"
37
+ },
38
+ {
39
+ "ok": true,
40
+ "latency_ms": 771,
41
+ "ts": "2026-05-15T01:54:30Z",
42
+ "src": "probe"
43
  }
44
  ],
45
  "degraded_until_monotonic": 0.0,
 
53
  "model": "qwen/qwen3.5-122b-a10b",
54
  "status": "down",
55
  "last_success_at": null,
56
+ "last_failure_at": "2026-05-15T01:54:30Z",
57
  "last_error": "timeout",
58
  "latency_ms": null,
59
+ "consecutive_failures": 18,
60
+ "tested_at": "2026-05-15T01:54:30Z",
61
  "probe_history": [
 
 
 
 
 
 
62
  {
63
  "ok": false,
64
  "latency_ms": 8001,
 
82
  "latency_ms": 8001,
83
  "ts": "2026-05-15T01:52:30Z",
84
  "src": "probe"
85
+ },
86
+ {
87
+ "ok": false,
88
+ "latency_ms": 8002,
89
+ "ts": "2026-05-15T01:54:30Z",
90
+ "src": "probe"
91
  }
92
  ],
93
  "degraded_until_monotonic": 0.0,
 
101
  "model": "openai/gpt-oss-120b",
102
  "status": "down",
103
  "last_success_at": null,
104
+ "last_failure_at": "2026-05-15T01:54:30Z",
105
  "last_error": "empty_content",
106
  "latency_ms": null,
107
+ "consecutive_failures": 18,
108
+ "tested_at": "2026-05-15T01:54:30Z",
109
  "probe_history": [
 
 
 
 
 
 
110
  {
111
  "ok": false,
112
  "latency_ms": 261,
 
130
  "latency_ms": 253,
131
  "ts": "2026-05-15T01:52:30Z",
132
  "src": "probe"
133
+ },
134
+ {
135
+ "ok": false,
136
+ "latency_ms": 311,
137
+ "ts": "2026-05-15T01:54:30Z",
138
+ "src": "probe"
139
  }
140
  ],
141
  "degraded_until_monotonic": 0.0,
 
147
  },
148
  "mistralai/mistral-large-3-675b-instruct-2512": {
149
  "model": "mistralai/mistral-large-3-675b-instruct-2512",
150
+ "status": "healthy",
151
+ "last_success_at": "2026-05-15T01:54:30Z",
152
  "last_failure_at": "2026-05-15T01:52:30Z",
153
+ "last_error": null,
154
+ "latency_ms": 617,
155
+ "consecutive_failures": 0,
156
+ "tested_at": "2026-05-15T01:54:30Z",
157
  "probe_history": [
 
 
 
 
 
 
158
  {
159
  "ok": true,
160
  "latency_ms": 782,
 
178
  "latency_ms": 8002,
179
  "ts": "2026-05-15T01:52:30Z",
180
  "src": "probe"
181
+ },
182
+ {
183
+ "ok": true,
184
+ "latency_ms": 617,
185
+ "ts": "2026-05-15T01:54:30Z",
186
+ "src": "probe"
187
  }
188
  ],
189
  "degraded_until_monotonic": 0.0,
 
195
  },
196
  "nvidia/llama-3.3-nemotron-super-49b-v1.5": {
197
  "model": "nvidia/llama-3.3-nemotron-super-49b-v1.5",
198
+ "status": "degraded",
199
+ "last_success_at": "2026-05-15T01:54:30Z",
200
  "last_failure_at": "2026-05-15T01:24:45Z",
201
  "last_error": null,
202
+ "latency_ms": 5838,
203
  "consecutive_failures": 0,
204
+ "tested_at": "2026-05-15T01:54:30Z",
205
  "probe_history": [
 
 
 
 
 
 
206
  {
207
  "ok": true,
208
  "latency_ms": 385,
 
226
  "latency_ms": 349,
227
  "ts": "2026-05-15T01:52:30Z",
228
  "src": "probe"
229
+ },
230
+ {
231
+ "ok": true,
232
+ "latency_ms": 5838,
233
+ "ts": "2026-05-15T01:54:30Z",
234
+ "src": "probe"
235
  }
236
  ],
237
  "degraded_until_monotonic": 0.0,
 
244
  "meta/llama-3.3-70b-instruct": {
245
  "model": "meta/llama-3.3-70b-instruct",
246
  "status": "healthy",
247
+ "last_success_at": "2026-05-15T01:54:30Z",
248
  "last_failure_at": "2026-05-15T01:41:07Z",
249
  "last_error": null,
250
+ "latency_ms": 3890,
251
  "consecutive_failures": 0,
252
+ "tested_at": "2026-05-15T01:54:30Z",
253
  "probe_history": [
 
 
 
 
 
 
254
  {
255
  "ok": false,
256
  "latency_ms": 8003,
 
274
  "latency_ms": 212,
275
  "ts": "2026-05-15T01:52:30Z",
276
  "src": "probe"
277
+ },
278
+ {
279
+ "ok": true,
280
+ "latency_ms": 3890,
281
+ "ts": "2026-05-15T01:54:30Z",
282
+ "src": "probe"
283
  }
284
  ],
285
  "degraded_until_monotonic": 0.0,
 
293
  "model": "deepseek-ai/deepseek-v4-pro",
294
  "status": "down",
295
  "last_success_at": null,
296
+ "last_failure_at": "2026-05-15T01:54:30Z",
297
  "last_error": "timeout",
298
  "latency_ms": null,
299
+ "consecutive_failures": 18,
300
+ "tested_at": "2026-05-15T01:54:30Z",
301
  "probe_history": [
 
 
 
 
 
 
302
  {
303
  "ok": false,
304
  "latency_ms": 8059,
 
322
  "latency_ms": 8003,
323
  "ts": "2026-05-15T01:52:30Z",
324
  "src": "probe"
325
+ },
326
+ {
327
+ "ok": false,
328
+ "latency_ms": 8002,
329
+ "ts": "2026-05-15T01:54:30Z",
330
+ "src": "probe"
331
  }
332
  ],
333
  "degraded_until_monotonic": 0.0,
 
341
  "model": "nvidia/nemotron-3-nano-30b-a3b",
342
  "status": "down",
343
  "last_success_at": null,
344
+ "last_failure_at": "2026-05-15T01:54:30Z",
345
  "last_error": "empty_content",
346
  "latency_ms": null,
347
+ "consecutive_failures": 18,
348
+ "tested_at": "2026-05-15T01:54:30Z",
349
  "probe_history": [
 
 
 
 
 
 
350
  {
351
  "ok": false,
352
  "latency_ms": 271,
 
370
  "latency_ms": 263,
371
  "ts": "2026-05-15T01:52:30Z",
372
  "src": "probe"
373
+ },
374
+ {
375
+ "ok": false,
376
+ "latency_ms": 276,
377
+ "ts": "2026-05-15T01:54:30Z",
378
+ "src": "probe"
379
  }
380
  ],
381
  "degraded_until_monotonic": 0.0,
 
389
  "model": "deepseek-ai/deepseek-v4-flash",
390
  "status": "down",
391
  "last_success_at": null,
392
+ "last_failure_at": "2026-05-15T01:54:30Z",
393
  "last_error": "timeout",
394
  "latency_ms": null,
395
+ "consecutive_failures": 18,
396
+ "tested_at": "2026-05-15T01:54:30Z",
397
  "probe_history": [
 
 
 
 
 
 
398
  {
399
  "ok": false,
400
  "latency_ms": 8002,
 
418
  "latency_ms": 8004,
419
  "ts": "2026-05-15T01:52:30Z",
420
  "src": "probe"
421
+ },
422
+ {
423
+ "ok": false,
424
+ "latency_ms": 8003,
425
+ "ts": "2026-05-15T01:54:30Z",
426
+ "src": "probe"
427
  }
428
  ],
429
  "degraded_until_monotonic": 0.0,
 
437
  "model": "moonshotai/kimi-k2-instruct-0905",
438
  "status": "down",
439
  "last_success_at": null,
440
+ "last_failure_at": "2026-05-15T01:54:30Z",
441
  "last_error": "http_404",
442
  "latency_ms": null,
443
+ "consecutive_failures": 18,
444
+ "tested_at": "2026-05-15T01:54:30Z",
445
  "probe_history": [
 
 
 
 
 
 
446
  {
447
  "ok": false,
448
  "latency_ms": 84,
 
466
  "latency_ms": 84,
467
  "ts": "2026-05-15T01:52:30Z",
468
  "src": "probe"
469
+ },
470
+ {
471
+ "ok": false,
472
+ "latency_ms": 81,
473
+ "ts": "2026-05-15T01:54:30Z",
474
+ "src": "probe"
475
  }
476
  ],
477
  "degraded_until_monotonic": 0.0,
 
485
  "model": "minimaxai/minimax-m2.5",
486
  "status": "down",
487
  "last_success_at": null,
488
+ "last_failure_at": "2026-05-15T01:54:30Z",
489
  "last_error": "http_410",
490
  "latency_ms": null,
491
+ "consecutive_failures": 18,
492
+ "tested_at": "2026-05-15T01:54:30Z",
493
  "probe_history": [
 
 
 
 
 
 
494
  {
495
  "ok": false,
496
  "latency_ms": 32,
 
514
  "latency_ms": 29,
515
  "ts": "2026-05-15T01:52:30Z",
516
  "src": "probe"
517
+ },
518
+ {
519
+ "ok": false,
520
+ "latency_ms": 31,
521
+ "ts": "2026-05-15T01:54:30Z",
522
+ "src": "probe"
523
  }
524
  ],
525
  "degraded_until_monotonic": 0.0,
 
532
  "meta/llama-4-maverick-17b-128e-instruct": {
533
  "model": "meta/llama-4-maverick-17b-128e-instruct",
534
  "status": "healthy",
535
+ "last_success_at": "2026-05-15T01:54:30Z",
536
  "last_failure_at": "2026-05-14T01:03:07Z",
537
  "last_error": null,
538
+ "latency_ms": 247,
539
  "consecutive_failures": 0,
540
+ "tested_at": "2026-05-15T01:54:30Z",
541
  "probe_history": [
 
 
 
 
 
 
542
  {
543
  "ok": true,
544
  "latency_ms": 313,
 
562
  "latency_ms": 205,
563
  "ts": "2026-05-15T01:52:30Z",
564
  "src": "probe"
565
+ },
566
+ {
567
+ "ok": true,
568
+ "latency_ms": 247,
569
+ "ts": "2026-05-15T01:54:30Z",
570
+ "src": "probe"
571
  }
572
  ],
573
  "degraded_until_monotonic": 0.0,
 
581
  "model": "openrouter:openai/gpt-oss-120b",
582
  "status": "degraded",
583
  "last_success_at": "2026-05-15T01:46:37Z",
584
+ "last_failure_at": "2026-05-15T01:54:30Z",
585
  "last_error": "empty_content",
586
  "latency_ms": 1349,
587
+ "consecutive_failures": 2,
588
+ "tested_at": "2026-05-15T01:54:30Z",
589
  "probe_history": [
 
 
 
 
 
 
590
  {
591
  "ok": true,
592
  "latency_ms": 4642,
 
610
  "latency_ms": 1635,
611
  "ts": "2026-05-15T01:52:30Z",
612
  "src": "probe"
613
+ },
614
+ {
615
+ "ok": false,
616
+ "latency_ms": 856,
617
+ "ts": "2026-05-15T01:54:30Z",
618
+ "src": "probe"
619
  }
620
  ],
621
  "degraded_until_monotonic": 0.0,
622
  "credits_remaining": 0.0,
623
  "credits_unit": "usd_balance",
624
  "credits_reset_at": null,
625
+ "credits_observed_at": 5158.700559583,
626
  "credits_low_water": 0.05
627
  },
628
  "groq:llama-3.3-70b-versatile": {
629
  "model": "groq:llama-3.3-70b-versatile",
630
  "status": "healthy",
631
+ "last_success_at": "2026-05-15T01:54:30Z",
632
  "last_failure_at": null,
633
  "last_error": null,
634
+ "latency_ms": 261,
635
  "consecutive_failures": 0,
636
+ "tested_at": "2026-05-15T01:54:30Z",
637
  "probe_history": [
 
 
 
 
 
 
638
  {
639
  "ok": true,
640
  "latency_ms": 285,
 
658
  "latency_ms": 247,
659
  "ts": "2026-05-15T01:52:30Z",
660
  "src": "probe"
661
+ },
662
+ {
663
+ "ok": true,
664
+ "latency_ms": 261,
665
+ "ts": "2026-05-15T01:54:30Z",
666
+ "src": "probe"
667
  }
668
  ],
669
  "degraded_until_monotonic": 0.0,
backend/main.py CHANGED
@@ -1201,11 +1201,37 @@ async def policies_all(session_id: Optional[str] = None):
1201
  # JSON that doesn't have an extracted counterpart yet. This way, even
1202
  # policies whose LLM extraction failed still surface in the marketplace
1203
  # with their human-curated data.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1204
  seen_policy_ids: set[str] = set()
1205
  out = []
1206
 
1207
  # Pass 1: existing extracted policies (merged with curated overrides)
1208
- for fp in sorted(settings.EXTRACTED_DIR.glob("*.json")):
1209
  try:
1210
  data = _json.loads(fp.read_text())
1211
  except Exception:
@@ -1220,6 +1246,13 @@ async def policies_all(session_id: Optional[str] = None):
1220
  # in chat answers, they just don't appear as marketplace cards.
1221
  if slug == "regulatory":
1222
  continue
 
 
 
 
 
 
 
1223
  name, home = insurer_meta.get(slug, (slug, ""))
1224
  # Get insurer reviews if available for the scorecard
1225
  ir = None
 
1201
  # JSON that doesn't have an extracted counterpart yet. This way, even
1202
  # policies whose LLM extraction failed still surface in the marketplace
1203
  # with their human-curated data.
1204
+ #
1205
+ # KI-133 (2026-05-15) β€” dedup marketplace cards to ONE per policy product
1206
+ # (not one per PDF document). Previously wordings + brochure + cis of
1207
+ # the same product created three separate cards, ballooning the
1208
+ # marketplace from 138 products to ~209 cards and confusing users who
1209
+ # see "138 POLICIES" in the badge but 209 cards below.
1210
+ #
1211
+ # Algorithm: sort source filenames so the canonical "wordings" variant
1212
+ # is encountered first for each product, then dedup by stripped
1213
+ # policy_id (everything before the trailing __<doctype>).
1214
+ # Doctype preference: wordings > prospectus > cis > brochure > anything
1215
+ # else (alphabetical fallback).
1216
+ _DOCTYPE_RANK = {"wordings": 0, "prospectus": 1, "cis": 2, "brochure": 3}
1217
+ def _doctype_of(stem: str) -> str:
1218
+ return stem.rsplit("__", 1)[1] if "__" in stem else ""
1219
+ def _product_key_of(policy_id: str) -> str:
1220
+ # Strip trailing __<doctype> so wordings/brochure/cis of the same
1221
+ # product collapse to a single key.
1222
+ return policy_id.rsplit("__", 1)[0] if "__" in policy_id else policy_id
1223
+
1224
+ sorted_files = sorted(
1225
+ settings.EXTRACTED_DIR.glob("*.json"),
1226
+ key=lambda fp: (_DOCTYPE_RANK.get(_doctype_of(fp.stem), 99), fp.stem),
1227
+ )
1228
+
1229
+ seen_product_keys: set[str] = set()
1230
  seen_policy_ids: set[str] = set()
1231
  out = []
1232
 
1233
  # Pass 1: existing extracted policies (merged with curated overrides)
1234
+ for fp in sorted_files:
1235
  try:
1236
  data = _json.loads(fp.read_text())
1237
  except Exception:
 
1246
  # in chat answers, they just don't appear as marketplace cards.
1247
  if slug == "regulatory":
1248
  continue
1249
+ # KI-133 (2026-05-15) β€” dedup by product (insurer__product), so the
1250
+ # wordings PDF wins and the brochure/cis variants don't generate
1251
+ # duplicate cards. Pass-1 sort order guarantees wordings comes first.
1252
+ product_key = _product_key_of(policy_id_local)
1253
+ if product_key in seen_product_keys:
1254
+ continue
1255
+ seen_product_keys.add(product_key)
1256
  name, home = insurer_meta.get(slug, (slug, ""))
1257
  # Get insurer reviews if available for the scorecard
1258
  ir = None