wauldo 0.4.0 → 0.6.0
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.
- package/README.md +140 -72
- package/dist/index.d.mts +81 -1
- package/dist/index.d.ts +81 -1
- package/dist/index.js +175 -0
- package/dist/index.mjs +175 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,82 +1,152 @@
|
|
|
1
|
-
|
|
1
|
+
<h1 align="center">Wauldo TypeScript SDK</h1>
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
[](./LICENSE)
|
|
3
|
+
<p align="center">
|
|
4
|
+
<strong>Verified AI answers from your documents — or no answer at all.</strong>
|
|
5
|
+
</p>
|
|
7
6
|
|
|
8
|
-
>
|
|
7
|
+
<p align="center">
|
|
8
|
+
Most RAG APIs guess. Wauldo verifies.
|
|
9
|
+
</p>
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
<p align="center">
|
|
12
|
+
<b>0% hallucination</b> | 83% accuracy | 61 eval tasks | 14 LLMs tested
|
|
13
|
+
</p>
|
|
11
14
|
|
|
12
|
-
|
|
15
|
+
<p align="center">
|
|
16
|
+
<a href="https://npmjs.com/package/wauldo"><img src="https://img.shields.io/npm/v/wauldo.svg" alt="npm" /></a>
|
|
17
|
+
<a href="https://npmjs.com/package/wauldo"><img src="https://img.shields.io/npm/dm/wauldo.svg" alt="Downloads" /></a>
|
|
18
|
+
<img src="https://img.shields.io/badge/TypeScript-5.0+-blue.svg" alt="TypeScript" />
|
|
19
|
+
<img src="https://img.shields.io/badge/License-MIT-green.svg" alt="MIT" />
|
|
20
|
+
</p>
|
|
13
21
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
<p align="center">
|
|
23
|
+
<a href="https://wauldo.com/demo">Demo</a> •
|
|
24
|
+
<a href="https://wauldo.com/docs">Docs</a> •
|
|
25
|
+
<a href="https://rapidapi.com/binnewzzin/api/smart-rag-api">Free API Key</a> •
|
|
26
|
+
<a href="https://dev.to/wauldo/how-we-achieved-0-hallucination-rate-in-our-rag-api-with-benchmarks-4g54">Benchmarks</a>
|
|
27
|
+
</p>
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Try it locally (no server needed)
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install wauldo
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { MockHttpClient } from 'wauldo';
|
|
39
|
+
|
|
40
|
+
const client = new MockHttpClient();
|
|
41
|
+
|
|
42
|
+
// Upload, query, fact-check — all offline
|
|
43
|
+
await client.ragUpload('Refund policy allows returns within 60 days.', 'policy.txt');
|
|
44
|
+
const result = await client.ragQuery('What is the refund policy?');
|
|
45
|
+
console.log(result.answer); // "Mock answer for: What is the refund policy?"
|
|
46
|
+
|
|
47
|
+
const check = await client.factCheck({
|
|
48
|
+
text: 'Returns accepted within 30 days.',
|
|
49
|
+
source_context: 'Refund policy allows returns within 60 days.',
|
|
50
|
+
});
|
|
51
|
+
console.log(check.verdict); // "rejected"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Run the full quickstart: `npx tsx examples/quickstart.ts`
|
|
55
|
+
|
|
56
|
+
---
|
|
23
57
|
|
|
24
|
-
##
|
|
58
|
+
## Quickstart with real API
|
|
25
59
|
|
|
26
60
|
```typescript
|
|
27
61
|
import { HttpClient } from 'wauldo';
|
|
28
62
|
|
|
29
63
|
const client = new HttpClient({ baseUrl: 'https://api.wauldo.com', apiKey: 'YOUR_API_KEY' });
|
|
30
64
|
|
|
31
|
-
|
|
32
|
-
|
|
65
|
+
// Upload a document
|
|
66
|
+
await client.ragUpload('Our refund policy allows returns within 60 days...', 'policy.txt');
|
|
67
|
+
|
|
68
|
+
// Ask a question — answer is verified against the source
|
|
69
|
+
const result = await client.ragQuery('What is the refund policy?');
|
|
70
|
+
console.log(result.answer);
|
|
71
|
+
console.log(result.sources);
|
|
33
72
|
```
|
|
34
73
|
|
|
35
|
-
|
|
74
|
+
```
|
|
75
|
+
Output:
|
|
76
|
+
Answer: Returns are accepted within 60 days of purchase.
|
|
77
|
+
Sources: policy.txt — "Our refund policy allows returns within 60 days"
|
|
78
|
+
Grounded: true | Confidence: 0.92
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
[Try the demo](https://wauldo.com/demo) | [Get a free API key](https://rapidapi.com/binnewzzin/api/smart-rag-api)
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Why Wauldo (and not standard RAG)
|
|
86
|
+
|
|
87
|
+
**Typical RAG pipeline**
|
|
36
88
|
|
|
37
|
-
```
|
|
38
|
-
|
|
89
|
+
```
|
|
90
|
+
retrieve → generate → hope it's correct
|
|
39
91
|
```
|
|
40
92
|
|
|
41
|
-
**
|
|
93
|
+
**Wauldo pipeline**
|
|
42
94
|
|
|
43
|
-
|
|
95
|
+
```
|
|
96
|
+
retrieve → extract facts → generate → verify → return or refuse
|
|
97
|
+
```
|
|
44
98
|
|
|
45
|
-
|
|
99
|
+
If the answer can't be verified, it returns **"insufficient evidence"** instead of guessing.
|
|
46
100
|
|
|
47
|
-
|
|
48
|
-
import { HttpClient } from 'wauldo';
|
|
101
|
+
### See the difference
|
|
49
102
|
|
|
50
|
-
|
|
103
|
+
```
|
|
104
|
+
Document: "Refunds are processed within 60 days"
|
|
51
105
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
{ role: 'system', content: 'You are a helpful assistant.' },
|
|
56
|
-
{ role: 'user', content: 'Explain async/await in TypeScript' },
|
|
57
|
-
],
|
|
58
|
-
});
|
|
59
|
-
console.log(response.choices[0]?.message?.content);
|
|
106
|
+
Typical RAG: "Refunds are processed within 30 days" ← wrong
|
|
107
|
+
Wauldo: "Refunds are processed within 60 days" ← verified
|
|
108
|
+
or "insufficient evidence" if unclear ← safe
|
|
60
109
|
```
|
|
61
110
|
|
|
62
|
-
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Examples
|
|
114
|
+
|
|
115
|
+
### Upload a PDF and ask questions
|
|
63
116
|
|
|
64
117
|
```typescript
|
|
65
|
-
// Upload
|
|
66
|
-
const upload = await client.
|
|
67
|
-
console.log(`
|
|
118
|
+
// Upload — text extraction + quality scoring happens server-side
|
|
119
|
+
const upload = await client.uploadFile(filePath, { title: 'Q3 Contract' });
|
|
120
|
+
console.log(`Extracted ${upload.chunks_count} chunks, quality: ${upload.quality_label}`);
|
|
68
121
|
|
|
69
|
-
// Query
|
|
122
|
+
// Query
|
|
70
123
|
const result = await client.ragQuery('What are the payment terms?');
|
|
71
124
|
console.log(`Answer: ${result.answer}`);
|
|
72
125
|
console.log(`Confidence: ${Math.round(result.audit.confidence * 100)}%`);
|
|
73
126
|
console.log(`Grounded: ${result.audit.grounded}`);
|
|
74
|
-
for (const source of result.sources) {
|
|
75
|
-
console.log(` Source (${Math.round(source.score * 100)}%): ${source.content}`);
|
|
76
|
-
}
|
|
77
127
|
```
|
|
78
128
|
|
|
79
|
-
###
|
|
129
|
+
### Fact-check any LLM output
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
const result = await client.factCheck({
|
|
133
|
+
text: 'Returns are accepted within 60 days.',
|
|
134
|
+
sourceContext: 'Our policy allows returns within 14 days.',
|
|
135
|
+
mode: 'lexical',
|
|
136
|
+
});
|
|
137
|
+
console.log(result.verdict); // "rejected"
|
|
138
|
+
console.log(result.action); // "block"
|
|
139
|
+
console.log(result.claims[0].reason); // "numerical_mismatch"
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Chat (OpenAI-compatible)
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
const reply = await client.chatSimple('auto', 'Explain async/await in TypeScript');
|
|
146
|
+
console.log(reply);
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Streaming
|
|
80
150
|
|
|
81
151
|
```typescript
|
|
82
152
|
const stream = client.chatStream({
|
|
@@ -88,7 +158,7 @@ for await (const chunk of stream) {
|
|
|
88
158
|
}
|
|
89
159
|
```
|
|
90
160
|
|
|
91
|
-
### Conversation
|
|
161
|
+
### Conversation
|
|
92
162
|
|
|
93
163
|
```typescript
|
|
94
164
|
const conv = client.conversation({ system: 'You are an expert on TypeScript.', model: 'auto' });
|
|
@@ -96,18 +166,21 @@ const reply = await conv.say('What are generics?');
|
|
|
96
166
|
const followUp = await conv.say('Give me an example');
|
|
97
167
|
```
|
|
98
168
|
|
|
99
|
-
|
|
169
|
+
---
|
|
100
170
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
171
|
+
## Features
|
|
172
|
+
|
|
173
|
+
- **Pre-generation fact extraction** — numbers, dates, limits injected as constraints
|
|
174
|
+
- **Post-generation grounding check** — every answer verified against sources
|
|
175
|
+
- **Citation validation** — detects phantom references
|
|
176
|
+
- **Analytics & Insights** — track token savings, cache performance, cost per hour, and per-tenant traffic
|
|
177
|
+
- **Fact-check API** — verify any claim against any source (3 modes)
|
|
178
|
+
- **Native PDF/DOCX upload** — server-side extraction with quality scoring
|
|
179
|
+
- **Smart model routing** — auto-selects cheapest model that meets quality
|
|
180
|
+
- **OpenAI-compatible** — swap your `baseUrl`, keep your existing code
|
|
181
|
+
- **Zero dependencies** — uses Node 18+ built-in APIs (fetch, ReadableStream)
|
|
182
|
+
|
|
183
|
+
---
|
|
111
184
|
|
|
112
185
|
## Error Handling
|
|
113
186
|
|
|
@@ -115,19 +188,16 @@ result.claims.forEach(c => console.log(`${c.text} → ${c.verdict} (${c.reason})
|
|
|
115
188
|
import { HttpClient, ServerError } from 'wauldo';
|
|
116
189
|
|
|
117
190
|
try {
|
|
118
|
-
const response = await client.chat({
|
|
119
|
-
model: 'auto',
|
|
120
|
-
messages: [{ role: 'user', content: 'Hello' }],
|
|
121
|
-
});
|
|
191
|
+
const response = await client.chat({ model: 'auto', messages: [{ role: 'user', content: 'Hello' }] });
|
|
122
192
|
} catch (error) {
|
|
123
193
|
if (error instanceof ServerError) {
|
|
124
194
|
console.error(`Server error [${error.code}]: ${error.message}`);
|
|
125
|
-
} else {
|
|
126
|
-
console.error('Unknown error:', error);
|
|
127
195
|
}
|
|
128
196
|
}
|
|
129
197
|
```
|
|
130
198
|
|
|
199
|
+
---
|
|
200
|
+
|
|
131
201
|
## RapidAPI
|
|
132
202
|
|
|
133
203
|
```typescript
|
|
@@ -140,19 +210,17 @@ const client = new HttpClient({
|
|
|
140
210
|
});
|
|
141
211
|
```
|
|
142
212
|
|
|
143
|
-
|
|
213
|
+
Free tier (300 req/month): [RapidAPI](https://rapidapi.com/binnewzzin/api/smart-rag-api)
|
|
144
214
|
|
|
145
|
-
|
|
215
|
+
---
|
|
146
216
|
|
|
147
|
-
|
|
148
|
-
- [Documentation](https://wauldo.com/docs)
|
|
149
|
-
- [Live Demo](https://api.wauldo.com/demo)
|
|
150
|
-
- [Cost Calculator](https://wauldo.com/calculator)
|
|
151
|
-
- [Status](https://wauldo.com/status)
|
|
217
|
+
[Website](https://wauldo.com) | [Docs](https://wauldo.com/docs) | [Demo](https://wauldo.com/demo) | [Benchmarks](https://dev.to/wauldo/how-we-achieved-0-hallucination-rate-in-our-rag-api-with-benchmarks-4g54)
|
|
152
218
|
|
|
153
219
|
## Contributing
|
|
154
220
|
|
|
155
|
-
|
|
221
|
+
PRs welcome! See [CONTRIBUTING.md](./CONTRIBUTING.md) for setup instructions and guidelines.
|
|
222
|
+
|
|
223
|
+
Check the [good first issues](https://github.com/wauldo/wauldo-sdk-js/labels/good%20first%20issue) to get started.
|
|
156
224
|
|
|
157
225
|
## License
|
|
158
226
|
|
package/dist/index.d.mts
CHANGED
|
@@ -380,6 +380,58 @@ interface VerifyCitationResponse {
|
|
|
380
380
|
phantom_count?: number;
|
|
381
381
|
processing_time_ms: number;
|
|
382
382
|
}
|
|
383
|
+
interface GuardResult {
|
|
384
|
+
safe: boolean;
|
|
385
|
+
verdict: string;
|
|
386
|
+
action: string;
|
|
387
|
+
reason: string | null;
|
|
388
|
+
confidence: number;
|
|
389
|
+
}
|
|
390
|
+
interface InsightsResponse {
|
|
391
|
+
tig_key: string;
|
|
392
|
+
total_requests: number;
|
|
393
|
+
intelligence_requests: number;
|
|
394
|
+
fallback_requests: number;
|
|
395
|
+
tokens: {
|
|
396
|
+
baseline_total: number;
|
|
397
|
+
real_total: number;
|
|
398
|
+
saved_total: number;
|
|
399
|
+
saved_percent_avg: number;
|
|
400
|
+
};
|
|
401
|
+
cost: {
|
|
402
|
+
estimated_usd_saved: number;
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
interface AnalyticsResponse {
|
|
406
|
+
cache: {
|
|
407
|
+
total_requests: number;
|
|
408
|
+
cache_hit_rate: number;
|
|
409
|
+
avg_latency_ms: number;
|
|
410
|
+
p95_latency_ms: number;
|
|
411
|
+
};
|
|
412
|
+
tokens: {
|
|
413
|
+
total_baseline: number;
|
|
414
|
+
total_real: number;
|
|
415
|
+
total_saved: number;
|
|
416
|
+
avg_savings_percent: number;
|
|
417
|
+
};
|
|
418
|
+
uptime_secs: number;
|
|
419
|
+
}
|
|
420
|
+
interface TrafficSummary {
|
|
421
|
+
total_requests_today: number;
|
|
422
|
+
total_tokens_today: number;
|
|
423
|
+
top_tenants: Array<{
|
|
424
|
+
tenant_id: string;
|
|
425
|
+
requests_today: number;
|
|
426
|
+
tokens_used: number;
|
|
427
|
+
success_rate: number;
|
|
428
|
+
avg_latency_ms: number;
|
|
429
|
+
}>;
|
|
430
|
+
error_rate: number;
|
|
431
|
+
avg_latency_ms: number;
|
|
432
|
+
p95_latency_ms: number;
|
|
433
|
+
uptime_secs: number;
|
|
434
|
+
}
|
|
383
435
|
/** Minimal interface required by Conversation — implemented by both HttpClient and MockHttpClient */
|
|
384
436
|
interface ChatClientLike {
|
|
385
437
|
chat(request: ChatRequest, options?: RequestOptions): Promise<ChatResponse>;
|
|
@@ -580,6 +632,23 @@ declare class HttpClient {
|
|
|
580
632
|
* ```
|
|
581
633
|
*/
|
|
582
634
|
verifyCitation(request: VerifyCitationRequest): Promise<VerifyCitationResponse>;
|
|
635
|
+
/**
|
|
636
|
+
* Verify an LLM output against a source document.
|
|
637
|
+
* Convenience wrapper around factCheck(). Returns a simple safe/unsafe result.
|
|
638
|
+
*/
|
|
639
|
+
guard(text: string, source: string, mode?: 'lexical' | 'hybrid' | 'semantic'): Promise<GuardResult>;
|
|
640
|
+
/**
|
|
641
|
+
* GET /v1/insights — ROI metrics for your API key
|
|
642
|
+
*/
|
|
643
|
+
getInsights(): Promise<InsightsResponse>;
|
|
644
|
+
/**
|
|
645
|
+
* GET /v1/analytics — Usage analytics and cache performance
|
|
646
|
+
*/
|
|
647
|
+
getAnalytics(minutes?: number): Promise<AnalyticsResponse>;
|
|
648
|
+
/**
|
|
649
|
+
* GET /v1/analytics/traffic — Per-tenant traffic monitoring
|
|
650
|
+
*/
|
|
651
|
+
getAnalyticsTraffic(): Promise<TrafficSummary>;
|
|
583
652
|
}
|
|
584
653
|
|
|
585
654
|
/**
|
|
@@ -650,6 +719,17 @@ declare class MockHttpClient {
|
|
|
650
719
|
system?: string;
|
|
651
720
|
model?: string;
|
|
652
721
|
}): Conversation;
|
|
722
|
+
uploadFile(_file: Uint8Array | Buffer, filename: string, options?: {
|
|
723
|
+
title?: string;
|
|
724
|
+
tags?: string;
|
|
725
|
+
timeoutMs?: number;
|
|
726
|
+
}): Promise<UploadFileResponse>;
|
|
727
|
+
factCheck(request: FactCheckRequest): Promise<FactCheckResponse>;
|
|
728
|
+
guard(text: string, source: string, mode?: string): Promise<GuardResult>;
|
|
729
|
+
verifyCitation(request: VerifyCitationRequest): Promise<VerifyCitationResponse>;
|
|
730
|
+
getInsights(): Promise<InsightsResponse>;
|
|
731
|
+
getAnalytics(minutes?: number): Promise<AnalyticsResponse>;
|
|
732
|
+
getAnalyticsTraffic(): Promise<TrafficSummary>;
|
|
653
733
|
ragAsk(question: string, text: string, source?: string): Promise<string>;
|
|
654
734
|
private record;
|
|
655
735
|
}
|
|
@@ -700,4 +780,4 @@ declare class ToolNotFoundError extends WauldoError {
|
|
|
700
780
|
constructor(toolName: string);
|
|
701
781
|
}
|
|
702
782
|
|
|
703
|
-
export { AgentClient, type CallToolResponse, type ChatChoice, type ChatClientLike, type ChatMessage, type ChatRequest, type ChatResponse, type ChatUsage, type Chunk, type ChunkResult, type CitationDetail, type ClaimResult, type ClientOptions, type Concept, type ConceptResult, ConnectionError, Conversation, type DetailLevel, type DocumentQuality, type EmbeddingData, type EmbeddingResponse, type EmbeddingUsage, type FactCheckRequest, type FactCheckResponse, type GraphNode, HttpClient, type HttpClientConfig, type KnowledgeGraphResult, type LogLevel, MockHttpClient, type ModelInfo, type ModelList, type OrchestratorResponse, type PlanOptions, type PlanResult, type PlanStep, type RagAuditInfo, type RagQueryResponse, type RagSource, type RagUploadResponse, type ReasoningOptions, type ReasoningResult, type RequestOptions, type RetrievalResult, ServerError, type SourceChunk, type SourceType, TimeoutError, type ToolContent, type ToolDefinition, ToolNotFoundError, type UploadFileResponse, ValidationError, type VerifyCitationRequest, type VerifyCitationResponse, WauldoError, chatContent };
|
|
783
|
+
export { AgentClient, type AnalyticsResponse, type CallToolResponse, type ChatChoice, type ChatClientLike, type ChatMessage, type ChatRequest, type ChatResponse, type ChatUsage, type Chunk, type ChunkResult, type CitationDetail, type ClaimResult, type ClientOptions, type Concept, type ConceptResult, ConnectionError, Conversation, type DetailLevel, type DocumentQuality, type EmbeddingData, type EmbeddingResponse, type EmbeddingUsage, type FactCheckRequest, type FactCheckResponse, type GraphNode, type GuardResult, HttpClient, type HttpClientConfig, type InsightsResponse, type KnowledgeGraphResult, type LogLevel, MockHttpClient, type ModelInfo, type ModelList, type OrchestratorResponse, type PlanOptions, type PlanResult, type PlanStep, type RagAuditInfo, type RagQueryResponse, type RagSource, type RagUploadResponse, type ReasoningOptions, type ReasoningResult, type RequestOptions, type RetrievalResult, ServerError, type SourceChunk, type SourceType, TimeoutError, type ToolContent, type ToolDefinition, ToolNotFoundError, type TrafficSummary, type UploadFileResponse, ValidationError, type VerifyCitationRequest, type VerifyCitationResponse, WauldoError, chatContent };
|
package/dist/index.d.ts
CHANGED
|
@@ -380,6 +380,58 @@ interface VerifyCitationResponse {
|
|
|
380
380
|
phantom_count?: number;
|
|
381
381
|
processing_time_ms: number;
|
|
382
382
|
}
|
|
383
|
+
interface GuardResult {
|
|
384
|
+
safe: boolean;
|
|
385
|
+
verdict: string;
|
|
386
|
+
action: string;
|
|
387
|
+
reason: string | null;
|
|
388
|
+
confidence: number;
|
|
389
|
+
}
|
|
390
|
+
interface InsightsResponse {
|
|
391
|
+
tig_key: string;
|
|
392
|
+
total_requests: number;
|
|
393
|
+
intelligence_requests: number;
|
|
394
|
+
fallback_requests: number;
|
|
395
|
+
tokens: {
|
|
396
|
+
baseline_total: number;
|
|
397
|
+
real_total: number;
|
|
398
|
+
saved_total: number;
|
|
399
|
+
saved_percent_avg: number;
|
|
400
|
+
};
|
|
401
|
+
cost: {
|
|
402
|
+
estimated_usd_saved: number;
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
interface AnalyticsResponse {
|
|
406
|
+
cache: {
|
|
407
|
+
total_requests: number;
|
|
408
|
+
cache_hit_rate: number;
|
|
409
|
+
avg_latency_ms: number;
|
|
410
|
+
p95_latency_ms: number;
|
|
411
|
+
};
|
|
412
|
+
tokens: {
|
|
413
|
+
total_baseline: number;
|
|
414
|
+
total_real: number;
|
|
415
|
+
total_saved: number;
|
|
416
|
+
avg_savings_percent: number;
|
|
417
|
+
};
|
|
418
|
+
uptime_secs: number;
|
|
419
|
+
}
|
|
420
|
+
interface TrafficSummary {
|
|
421
|
+
total_requests_today: number;
|
|
422
|
+
total_tokens_today: number;
|
|
423
|
+
top_tenants: Array<{
|
|
424
|
+
tenant_id: string;
|
|
425
|
+
requests_today: number;
|
|
426
|
+
tokens_used: number;
|
|
427
|
+
success_rate: number;
|
|
428
|
+
avg_latency_ms: number;
|
|
429
|
+
}>;
|
|
430
|
+
error_rate: number;
|
|
431
|
+
avg_latency_ms: number;
|
|
432
|
+
p95_latency_ms: number;
|
|
433
|
+
uptime_secs: number;
|
|
434
|
+
}
|
|
383
435
|
/** Minimal interface required by Conversation — implemented by both HttpClient and MockHttpClient */
|
|
384
436
|
interface ChatClientLike {
|
|
385
437
|
chat(request: ChatRequest, options?: RequestOptions): Promise<ChatResponse>;
|
|
@@ -580,6 +632,23 @@ declare class HttpClient {
|
|
|
580
632
|
* ```
|
|
581
633
|
*/
|
|
582
634
|
verifyCitation(request: VerifyCitationRequest): Promise<VerifyCitationResponse>;
|
|
635
|
+
/**
|
|
636
|
+
* Verify an LLM output against a source document.
|
|
637
|
+
* Convenience wrapper around factCheck(). Returns a simple safe/unsafe result.
|
|
638
|
+
*/
|
|
639
|
+
guard(text: string, source: string, mode?: 'lexical' | 'hybrid' | 'semantic'): Promise<GuardResult>;
|
|
640
|
+
/**
|
|
641
|
+
* GET /v1/insights — ROI metrics for your API key
|
|
642
|
+
*/
|
|
643
|
+
getInsights(): Promise<InsightsResponse>;
|
|
644
|
+
/**
|
|
645
|
+
* GET /v1/analytics — Usage analytics and cache performance
|
|
646
|
+
*/
|
|
647
|
+
getAnalytics(minutes?: number): Promise<AnalyticsResponse>;
|
|
648
|
+
/**
|
|
649
|
+
* GET /v1/analytics/traffic — Per-tenant traffic monitoring
|
|
650
|
+
*/
|
|
651
|
+
getAnalyticsTraffic(): Promise<TrafficSummary>;
|
|
583
652
|
}
|
|
584
653
|
|
|
585
654
|
/**
|
|
@@ -650,6 +719,17 @@ declare class MockHttpClient {
|
|
|
650
719
|
system?: string;
|
|
651
720
|
model?: string;
|
|
652
721
|
}): Conversation;
|
|
722
|
+
uploadFile(_file: Uint8Array | Buffer, filename: string, options?: {
|
|
723
|
+
title?: string;
|
|
724
|
+
tags?: string;
|
|
725
|
+
timeoutMs?: number;
|
|
726
|
+
}): Promise<UploadFileResponse>;
|
|
727
|
+
factCheck(request: FactCheckRequest): Promise<FactCheckResponse>;
|
|
728
|
+
guard(text: string, source: string, mode?: string): Promise<GuardResult>;
|
|
729
|
+
verifyCitation(request: VerifyCitationRequest): Promise<VerifyCitationResponse>;
|
|
730
|
+
getInsights(): Promise<InsightsResponse>;
|
|
731
|
+
getAnalytics(minutes?: number): Promise<AnalyticsResponse>;
|
|
732
|
+
getAnalyticsTraffic(): Promise<TrafficSummary>;
|
|
653
733
|
ragAsk(question: string, text: string, source?: string): Promise<string>;
|
|
654
734
|
private record;
|
|
655
735
|
}
|
|
@@ -700,4 +780,4 @@ declare class ToolNotFoundError extends WauldoError {
|
|
|
700
780
|
constructor(toolName: string);
|
|
701
781
|
}
|
|
702
782
|
|
|
703
|
-
export { AgentClient, type CallToolResponse, type ChatChoice, type ChatClientLike, type ChatMessage, type ChatRequest, type ChatResponse, type ChatUsage, type Chunk, type ChunkResult, type CitationDetail, type ClaimResult, type ClientOptions, type Concept, type ConceptResult, ConnectionError, Conversation, type DetailLevel, type DocumentQuality, type EmbeddingData, type EmbeddingResponse, type EmbeddingUsage, type FactCheckRequest, type FactCheckResponse, type GraphNode, HttpClient, type HttpClientConfig, type KnowledgeGraphResult, type LogLevel, MockHttpClient, type ModelInfo, type ModelList, type OrchestratorResponse, type PlanOptions, type PlanResult, type PlanStep, type RagAuditInfo, type RagQueryResponse, type RagSource, type RagUploadResponse, type ReasoningOptions, type ReasoningResult, type RequestOptions, type RetrievalResult, ServerError, type SourceChunk, type SourceType, TimeoutError, type ToolContent, type ToolDefinition, ToolNotFoundError, type UploadFileResponse, ValidationError, type VerifyCitationRequest, type VerifyCitationResponse, WauldoError, chatContent };
|
|
783
|
+
export { AgentClient, type AnalyticsResponse, type CallToolResponse, type ChatChoice, type ChatClientLike, type ChatMessage, type ChatRequest, type ChatResponse, type ChatUsage, type Chunk, type ChunkResult, type CitationDetail, type ClaimResult, type ClientOptions, type Concept, type ConceptResult, ConnectionError, Conversation, type DetailLevel, type DocumentQuality, type EmbeddingData, type EmbeddingResponse, type EmbeddingUsage, type FactCheckRequest, type FactCheckResponse, type GraphNode, type GuardResult, HttpClient, type HttpClientConfig, type InsightsResponse, type KnowledgeGraphResult, type LogLevel, MockHttpClient, type ModelInfo, type ModelList, type OrchestratorResponse, type PlanOptions, type PlanResult, type PlanStep, type RagAuditInfo, type RagQueryResponse, type RagSource, type RagUploadResponse, type ReasoningOptions, type ReasoningResult, type RequestOptions, type RetrievalResult, ServerError, type SourceChunk, type SourceType, TimeoutError, type ToolContent, type ToolDefinition, ToolNotFoundError, type TrafficSummary, type UploadFileResponse, ValidationError, type VerifyCitationRequest, type VerifyCitationResponse, WauldoError, chatContent };
|
package/dist/index.js
CHANGED
|
@@ -1199,6 +1199,55 @@ ${options.tags}\r
|
|
|
1199
1199
|
);
|
|
1200
1200
|
return validateResponse(data, "VerifyCitationResponse");
|
|
1201
1201
|
}
|
|
1202
|
+
/**
|
|
1203
|
+
* Verify an LLM output against a source document.
|
|
1204
|
+
* Convenience wrapper around factCheck(). Returns a simple safe/unsafe result.
|
|
1205
|
+
*/
|
|
1206
|
+
async guard(text, source, mode = "lexical") {
|
|
1207
|
+
const result = await this.factCheck({ text, source_context: source, mode });
|
|
1208
|
+
const claim = result.claims?.[0];
|
|
1209
|
+
return {
|
|
1210
|
+
safe: claim?.verdict === "verified",
|
|
1211
|
+
verdict: claim?.verdict ?? "rejected",
|
|
1212
|
+
action: claim?.action ?? "block",
|
|
1213
|
+
reason: claim?.reason ?? "no_claims",
|
|
1214
|
+
confidence: claim?.confidence ?? 0
|
|
1215
|
+
};
|
|
1216
|
+
}
|
|
1217
|
+
// ── Analytics & Insights endpoints ───────────────────────────────────
|
|
1218
|
+
/**
|
|
1219
|
+
* GET /v1/insights — ROI metrics for your API key
|
|
1220
|
+
*/
|
|
1221
|
+
async getInsights() {
|
|
1222
|
+
const data = await fetchWithRetry(
|
|
1223
|
+
this.retryConfig,
|
|
1224
|
+
"GET",
|
|
1225
|
+
"/v1/insights"
|
|
1226
|
+
);
|
|
1227
|
+
return validateResponse(data, "InsightsResponse");
|
|
1228
|
+
}
|
|
1229
|
+
/**
|
|
1230
|
+
* GET /v1/analytics — Usage analytics and cache performance
|
|
1231
|
+
*/
|
|
1232
|
+
async getAnalytics(minutes = 60) {
|
|
1233
|
+
const data = await fetchWithRetry(
|
|
1234
|
+
this.retryConfig,
|
|
1235
|
+
"GET",
|
|
1236
|
+
`/v1/analytics?minutes=${minutes}`
|
|
1237
|
+
);
|
|
1238
|
+
return validateResponse(data, "AnalyticsResponse");
|
|
1239
|
+
}
|
|
1240
|
+
/**
|
|
1241
|
+
* GET /v1/analytics/traffic — Per-tenant traffic monitoring
|
|
1242
|
+
*/
|
|
1243
|
+
async getAnalyticsTraffic() {
|
|
1244
|
+
const data = await fetchWithRetry(
|
|
1245
|
+
this.retryConfig,
|
|
1246
|
+
"GET",
|
|
1247
|
+
"/v1/analytics/traffic"
|
|
1248
|
+
);
|
|
1249
|
+
return validateResponse(data, "TrafficSummary");
|
|
1250
|
+
}
|
|
1202
1251
|
};
|
|
1203
1252
|
|
|
1204
1253
|
// src/mock_client.ts
|
|
@@ -1302,6 +1351,132 @@ var MockHttpClient = class {
|
|
|
1302
1351
|
this.record("conversation", options);
|
|
1303
1352
|
return new Conversation(this, options);
|
|
1304
1353
|
}
|
|
1354
|
+
async uploadFile(_file, filename, options) {
|
|
1355
|
+
this.record("uploadFile", filename, options);
|
|
1356
|
+
return {
|
|
1357
|
+
document_id: "mock-doc-file-1",
|
|
1358
|
+
chunks_count: 5,
|
|
1359
|
+
indexed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1360
|
+
content_type: "application/pdf",
|
|
1361
|
+
trace_id: "mock-trace-1",
|
|
1362
|
+
quality: {
|
|
1363
|
+
score: 0.85,
|
|
1364
|
+
label: "good",
|
|
1365
|
+
word_count: 1200,
|
|
1366
|
+
line_density: 8.5,
|
|
1367
|
+
avg_line_length: 72,
|
|
1368
|
+
paragraph_count: 15
|
|
1369
|
+
}
|
|
1370
|
+
};
|
|
1371
|
+
}
|
|
1372
|
+
async factCheck(request) {
|
|
1373
|
+
this.record("factCheck", request);
|
|
1374
|
+
const hasConflict = request.text !== request.source_context;
|
|
1375
|
+
return {
|
|
1376
|
+
verdict: hasConflict ? "rejected" : "verified",
|
|
1377
|
+
action: hasConflict ? "block" : "allow",
|
|
1378
|
+
hallucination_rate: hasConflict ? 1 : 0,
|
|
1379
|
+
mode: request.mode ?? "lexical",
|
|
1380
|
+
total_claims: 1,
|
|
1381
|
+
supported_claims: hasConflict ? 0 : 1,
|
|
1382
|
+
confidence: hasConflict ? 0.25 : 0.92,
|
|
1383
|
+
claims: [{
|
|
1384
|
+
text: request.text,
|
|
1385
|
+
claim_type: "factual",
|
|
1386
|
+
supported: !hasConflict,
|
|
1387
|
+
confidence: hasConflict ? 0.25 : 0.92,
|
|
1388
|
+
confidence_label: hasConflict ? "low" : "high",
|
|
1389
|
+
verdict: hasConflict ? "rejected" : "verified",
|
|
1390
|
+
action: hasConflict ? "block" : "allow",
|
|
1391
|
+
reason: hasConflict ? "numerical_mismatch" : null,
|
|
1392
|
+
evidence: request.source_context
|
|
1393
|
+
}],
|
|
1394
|
+
processing_time_ms: 1
|
|
1395
|
+
};
|
|
1396
|
+
}
|
|
1397
|
+
async guard(text, source, mode = "lexical") {
|
|
1398
|
+
this.record("guard", text, source, mode);
|
|
1399
|
+
return {
|
|
1400
|
+
safe: true,
|
|
1401
|
+
verdict: "verified",
|
|
1402
|
+
action: "allow",
|
|
1403
|
+
reason: null,
|
|
1404
|
+
confidence: 0.95
|
|
1405
|
+
};
|
|
1406
|
+
}
|
|
1407
|
+
async verifyCitation(request) {
|
|
1408
|
+
this.record("verifyCitation", request);
|
|
1409
|
+
const citations = request.text.match(/\[(?:Source:\s*[^\]]+|\d+|Ref:\s*[^\]]+)\]/g) ?? [];
|
|
1410
|
+
const sentences = request.text.split(/[.!?]+/).filter((s) => s.trim().length > 0);
|
|
1411
|
+
const citedSentences = sentences.filter((s) => /\[(?:Source:\s*[^\]]+|\d+|Ref:\s*[^\]]+)\]/.test(s));
|
|
1412
|
+
const ratio = sentences.length > 0 ? citedSentences.length / sentences.length : 0;
|
|
1413
|
+
return {
|
|
1414
|
+
citation_ratio: ratio,
|
|
1415
|
+
has_sufficient_citations: ratio >= (request.threshold ?? 0.5),
|
|
1416
|
+
sentence_count: sentences.length,
|
|
1417
|
+
citation_count: citations.length,
|
|
1418
|
+
uncited_sentences: sentences.filter((s) => !/\[(?:Source:\s*[^\]]+|\d+|Ref:\s*[^\]]+)\]/.test(s)).map((s) => s.trim()),
|
|
1419
|
+
citations: citations.map((c) => ({
|
|
1420
|
+
citation: c,
|
|
1421
|
+
source_name: c.replace(/[\[\]]/g, "").replace("Source: ", ""),
|
|
1422
|
+
is_valid: (request.sources ?? []).some((src) => c.includes(src.name))
|
|
1423
|
+
})),
|
|
1424
|
+
phantom_count: 0,
|
|
1425
|
+
processing_time_ms: 1
|
|
1426
|
+
};
|
|
1427
|
+
}
|
|
1428
|
+
async getInsights() {
|
|
1429
|
+
this.record("getInsights");
|
|
1430
|
+
return {
|
|
1431
|
+
tig_key: "mock-tig-key",
|
|
1432
|
+
total_requests: 1250,
|
|
1433
|
+
intelligence_requests: 980,
|
|
1434
|
+
fallback_requests: 270,
|
|
1435
|
+
tokens: {
|
|
1436
|
+
baseline_total: 5e5,
|
|
1437
|
+
real_total: 325e3,
|
|
1438
|
+
saved_total: 175e3,
|
|
1439
|
+
saved_percent_avg: 35
|
|
1440
|
+
},
|
|
1441
|
+
cost: {
|
|
1442
|
+
estimated_usd_saved: 12.5
|
|
1443
|
+
}
|
|
1444
|
+
};
|
|
1445
|
+
}
|
|
1446
|
+
async getAnalytics(minutes = 60) {
|
|
1447
|
+
this.record("getAnalytics", minutes);
|
|
1448
|
+
return {
|
|
1449
|
+
cache: {
|
|
1450
|
+
total_requests: 450,
|
|
1451
|
+
cache_hit_rate: 0.42,
|
|
1452
|
+
avg_latency_ms: 180,
|
|
1453
|
+
p95_latency_ms: 850
|
|
1454
|
+
},
|
|
1455
|
+
tokens: {
|
|
1456
|
+
total_baseline: 12e4,
|
|
1457
|
+
total_real: 78e3,
|
|
1458
|
+
total_saved: 42e3,
|
|
1459
|
+
avg_savings_percent: 35
|
|
1460
|
+
},
|
|
1461
|
+
uptime_secs: 86400
|
|
1462
|
+
};
|
|
1463
|
+
}
|
|
1464
|
+
async getAnalyticsTraffic() {
|
|
1465
|
+
this.record("getAnalyticsTraffic");
|
|
1466
|
+
return {
|
|
1467
|
+
total_requests_today: 3200,
|
|
1468
|
+
total_tokens_today: 15e5,
|
|
1469
|
+
top_tenants: [
|
|
1470
|
+
{ tenant_id: "tenant-alpha", requests_today: 1200, tokens_used: 58e4, success_rate: 0.98, avg_latency_ms: 220 },
|
|
1471
|
+
{ tenant_id: "tenant-beta", requests_today: 850, tokens_used: 42e4, success_rate: 0.96, avg_latency_ms: 310 },
|
|
1472
|
+
{ tenant_id: "tenant-gamma", requests_today: 600, tokens_used: 28e4, success_rate: 0.99, avg_latency_ms: 150 }
|
|
1473
|
+
],
|
|
1474
|
+
error_rate: 0.02,
|
|
1475
|
+
avg_latency_ms: 240,
|
|
1476
|
+
p95_latency_ms: 890,
|
|
1477
|
+
uptime_secs: 86400
|
|
1478
|
+
};
|
|
1479
|
+
}
|
|
1305
1480
|
async ragAsk(question, text, source = "document") {
|
|
1306
1481
|
this.record("ragAsk", question, text, source);
|
|
1307
1482
|
await this.ragUpload(text, source);
|
package/dist/index.mjs
CHANGED
|
@@ -1163,6 +1163,55 @@ ${options.tags}\r
|
|
|
1163
1163
|
);
|
|
1164
1164
|
return validateResponse(data, "VerifyCitationResponse");
|
|
1165
1165
|
}
|
|
1166
|
+
/**
|
|
1167
|
+
* Verify an LLM output against a source document.
|
|
1168
|
+
* Convenience wrapper around factCheck(). Returns a simple safe/unsafe result.
|
|
1169
|
+
*/
|
|
1170
|
+
async guard(text, source, mode = "lexical") {
|
|
1171
|
+
const result = await this.factCheck({ text, source_context: source, mode });
|
|
1172
|
+
const claim = result.claims?.[0];
|
|
1173
|
+
return {
|
|
1174
|
+
safe: claim?.verdict === "verified",
|
|
1175
|
+
verdict: claim?.verdict ?? "rejected",
|
|
1176
|
+
action: claim?.action ?? "block",
|
|
1177
|
+
reason: claim?.reason ?? "no_claims",
|
|
1178
|
+
confidence: claim?.confidence ?? 0
|
|
1179
|
+
};
|
|
1180
|
+
}
|
|
1181
|
+
// ── Analytics & Insights endpoints ───────────────────────────────────
|
|
1182
|
+
/**
|
|
1183
|
+
* GET /v1/insights — ROI metrics for your API key
|
|
1184
|
+
*/
|
|
1185
|
+
async getInsights() {
|
|
1186
|
+
const data = await fetchWithRetry(
|
|
1187
|
+
this.retryConfig,
|
|
1188
|
+
"GET",
|
|
1189
|
+
"/v1/insights"
|
|
1190
|
+
);
|
|
1191
|
+
return validateResponse(data, "InsightsResponse");
|
|
1192
|
+
}
|
|
1193
|
+
/**
|
|
1194
|
+
* GET /v1/analytics — Usage analytics and cache performance
|
|
1195
|
+
*/
|
|
1196
|
+
async getAnalytics(minutes = 60) {
|
|
1197
|
+
const data = await fetchWithRetry(
|
|
1198
|
+
this.retryConfig,
|
|
1199
|
+
"GET",
|
|
1200
|
+
`/v1/analytics?minutes=${minutes}`
|
|
1201
|
+
);
|
|
1202
|
+
return validateResponse(data, "AnalyticsResponse");
|
|
1203
|
+
}
|
|
1204
|
+
/**
|
|
1205
|
+
* GET /v1/analytics/traffic — Per-tenant traffic monitoring
|
|
1206
|
+
*/
|
|
1207
|
+
async getAnalyticsTraffic() {
|
|
1208
|
+
const data = await fetchWithRetry(
|
|
1209
|
+
this.retryConfig,
|
|
1210
|
+
"GET",
|
|
1211
|
+
"/v1/analytics/traffic"
|
|
1212
|
+
);
|
|
1213
|
+
return validateResponse(data, "TrafficSummary");
|
|
1214
|
+
}
|
|
1166
1215
|
};
|
|
1167
1216
|
|
|
1168
1217
|
// src/mock_client.ts
|
|
@@ -1266,6 +1315,132 @@ var MockHttpClient = class {
|
|
|
1266
1315
|
this.record("conversation", options);
|
|
1267
1316
|
return new Conversation(this, options);
|
|
1268
1317
|
}
|
|
1318
|
+
async uploadFile(_file, filename, options) {
|
|
1319
|
+
this.record("uploadFile", filename, options);
|
|
1320
|
+
return {
|
|
1321
|
+
document_id: "mock-doc-file-1",
|
|
1322
|
+
chunks_count: 5,
|
|
1323
|
+
indexed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1324
|
+
content_type: "application/pdf",
|
|
1325
|
+
trace_id: "mock-trace-1",
|
|
1326
|
+
quality: {
|
|
1327
|
+
score: 0.85,
|
|
1328
|
+
label: "good",
|
|
1329
|
+
word_count: 1200,
|
|
1330
|
+
line_density: 8.5,
|
|
1331
|
+
avg_line_length: 72,
|
|
1332
|
+
paragraph_count: 15
|
|
1333
|
+
}
|
|
1334
|
+
};
|
|
1335
|
+
}
|
|
1336
|
+
async factCheck(request) {
|
|
1337
|
+
this.record("factCheck", request);
|
|
1338
|
+
const hasConflict = request.text !== request.source_context;
|
|
1339
|
+
return {
|
|
1340
|
+
verdict: hasConflict ? "rejected" : "verified",
|
|
1341
|
+
action: hasConflict ? "block" : "allow",
|
|
1342
|
+
hallucination_rate: hasConflict ? 1 : 0,
|
|
1343
|
+
mode: request.mode ?? "lexical",
|
|
1344
|
+
total_claims: 1,
|
|
1345
|
+
supported_claims: hasConflict ? 0 : 1,
|
|
1346
|
+
confidence: hasConflict ? 0.25 : 0.92,
|
|
1347
|
+
claims: [{
|
|
1348
|
+
text: request.text,
|
|
1349
|
+
claim_type: "factual",
|
|
1350
|
+
supported: !hasConflict,
|
|
1351
|
+
confidence: hasConflict ? 0.25 : 0.92,
|
|
1352
|
+
confidence_label: hasConflict ? "low" : "high",
|
|
1353
|
+
verdict: hasConflict ? "rejected" : "verified",
|
|
1354
|
+
action: hasConflict ? "block" : "allow",
|
|
1355
|
+
reason: hasConflict ? "numerical_mismatch" : null,
|
|
1356
|
+
evidence: request.source_context
|
|
1357
|
+
}],
|
|
1358
|
+
processing_time_ms: 1
|
|
1359
|
+
};
|
|
1360
|
+
}
|
|
1361
|
+
async guard(text, source, mode = "lexical") {
|
|
1362
|
+
this.record("guard", text, source, mode);
|
|
1363
|
+
return {
|
|
1364
|
+
safe: true,
|
|
1365
|
+
verdict: "verified",
|
|
1366
|
+
action: "allow",
|
|
1367
|
+
reason: null,
|
|
1368
|
+
confidence: 0.95
|
|
1369
|
+
};
|
|
1370
|
+
}
|
|
1371
|
+
async verifyCitation(request) {
|
|
1372
|
+
this.record("verifyCitation", request);
|
|
1373
|
+
const citations = request.text.match(/\[(?:Source:\s*[^\]]+|\d+|Ref:\s*[^\]]+)\]/g) ?? [];
|
|
1374
|
+
const sentences = request.text.split(/[.!?]+/).filter((s) => s.trim().length > 0);
|
|
1375
|
+
const citedSentences = sentences.filter((s) => /\[(?:Source:\s*[^\]]+|\d+|Ref:\s*[^\]]+)\]/.test(s));
|
|
1376
|
+
const ratio = sentences.length > 0 ? citedSentences.length / sentences.length : 0;
|
|
1377
|
+
return {
|
|
1378
|
+
citation_ratio: ratio,
|
|
1379
|
+
has_sufficient_citations: ratio >= (request.threshold ?? 0.5),
|
|
1380
|
+
sentence_count: sentences.length,
|
|
1381
|
+
citation_count: citations.length,
|
|
1382
|
+
uncited_sentences: sentences.filter((s) => !/\[(?:Source:\s*[^\]]+|\d+|Ref:\s*[^\]]+)\]/.test(s)).map((s) => s.trim()),
|
|
1383
|
+
citations: citations.map((c) => ({
|
|
1384
|
+
citation: c,
|
|
1385
|
+
source_name: c.replace(/[\[\]]/g, "").replace("Source: ", ""),
|
|
1386
|
+
is_valid: (request.sources ?? []).some((src) => c.includes(src.name))
|
|
1387
|
+
})),
|
|
1388
|
+
phantom_count: 0,
|
|
1389
|
+
processing_time_ms: 1
|
|
1390
|
+
};
|
|
1391
|
+
}
|
|
1392
|
+
async getInsights() {
|
|
1393
|
+
this.record("getInsights");
|
|
1394
|
+
return {
|
|
1395
|
+
tig_key: "mock-tig-key",
|
|
1396
|
+
total_requests: 1250,
|
|
1397
|
+
intelligence_requests: 980,
|
|
1398
|
+
fallback_requests: 270,
|
|
1399
|
+
tokens: {
|
|
1400
|
+
baseline_total: 5e5,
|
|
1401
|
+
real_total: 325e3,
|
|
1402
|
+
saved_total: 175e3,
|
|
1403
|
+
saved_percent_avg: 35
|
|
1404
|
+
},
|
|
1405
|
+
cost: {
|
|
1406
|
+
estimated_usd_saved: 12.5
|
|
1407
|
+
}
|
|
1408
|
+
};
|
|
1409
|
+
}
|
|
1410
|
+
async getAnalytics(minutes = 60) {
|
|
1411
|
+
this.record("getAnalytics", minutes);
|
|
1412
|
+
return {
|
|
1413
|
+
cache: {
|
|
1414
|
+
total_requests: 450,
|
|
1415
|
+
cache_hit_rate: 0.42,
|
|
1416
|
+
avg_latency_ms: 180,
|
|
1417
|
+
p95_latency_ms: 850
|
|
1418
|
+
},
|
|
1419
|
+
tokens: {
|
|
1420
|
+
total_baseline: 12e4,
|
|
1421
|
+
total_real: 78e3,
|
|
1422
|
+
total_saved: 42e3,
|
|
1423
|
+
avg_savings_percent: 35
|
|
1424
|
+
},
|
|
1425
|
+
uptime_secs: 86400
|
|
1426
|
+
};
|
|
1427
|
+
}
|
|
1428
|
+
async getAnalyticsTraffic() {
|
|
1429
|
+
this.record("getAnalyticsTraffic");
|
|
1430
|
+
return {
|
|
1431
|
+
total_requests_today: 3200,
|
|
1432
|
+
total_tokens_today: 15e5,
|
|
1433
|
+
top_tenants: [
|
|
1434
|
+
{ tenant_id: "tenant-alpha", requests_today: 1200, tokens_used: 58e4, success_rate: 0.98, avg_latency_ms: 220 },
|
|
1435
|
+
{ tenant_id: "tenant-beta", requests_today: 850, tokens_used: 42e4, success_rate: 0.96, avg_latency_ms: 310 },
|
|
1436
|
+
{ tenant_id: "tenant-gamma", requests_today: 600, tokens_used: 28e4, success_rate: 0.99, avg_latency_ms: 150 }
|
|
1437
|
+
],
|
|
1438
|
+
error_rate: 0.02,
|
|
1439
|
+
avg_latency_ms: 240,
|
|
1440
|
+
p95_latency_ms: 890,
|
|
1441
|
+
uptime_secs: 86400
|
|
1442
|
+
};
|
|
1443
|
+
}
|
|
1269
1444
|
async ragAsk(question, text, source = "document") {
|
|
1270
1445
|
this.record("ragAsk", question, text, source);
|
|
1271
1446
|
await this.ragUpload(text, source);
|