adaptive-memory-multi-model-router 1.9.5 → 2.0.1
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/.github/ISSUE_TEMPLATE/bug_report.md +50 -0
- package/.github/ISSUE_TEMPLATE/config.yml +11 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +37 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +44 -0
- package/.github/workflows/npm-stats-validation.yml +152 -0
- package/.github/workflows/pages.yml +37 -0
- package/CHANGELOG.md +122 -0
- package/CODE_OF_CONDUCT.md +128 -0
- package/CONTRIBUTING.md +110 -0
- package/LAUNCH-PAIN-DRIVEN.md +339 -0
- package/LAUNCH.md +575 -0
- package/POPULARITY_BOOSTERS.md +285 -0
- package/README.md +231 -300
- package/SECURITY.md +69 -0
- package/articles/CONTENT_STRUCTURE.md +292 -0
- package/articles/DEVTO_COST_GUIDE.md +473 -0
- package/articles/DEVTO_FINAL.md +416 -0
- package/articles/DEVTO_MULTI_PROVIDER.md +542 -0
- package/articles/DEVTO_V2_ANNOUNCEMENT.md +160 -0
- package/articles/HN_10X_BETTER.md +430 -0
- package/articles/HN_CHINESE_STYLE.md +308 -0
- package/articles/HN_FINAL.md +199 -0
- package/articles/HN_POSTED_VERSION.md +56 -0
- package/articles/HN_RESEARCH.md +364 -0
- package/articles/PAIN-DRIVEN-devto-v2.md +308 -0
- package/articles/PAIN-DRIVEN-devto-v3.md +268 -0
- package/articles/PAIN-DRIVEN-devto.md +242 -0
- package/articles/PAIN-DRIVEN-hackernews-v2.md +138 -0
- package/articles/PAIN-DRIVEN-hackernews-v3.md +151 -0
- package/articles/PAIN-DRIVEN-hackernews.md +131 -0
- package/articles/PAIN-DRIVEN-reddit-v2.md +301 -0
- package/articles/PAIN-DRIVEN-reddit-v3.md +236 -0
- package/articles/PAIN-DRIVEN-reddit.md +218 -0
- package/articles/PAIN-DRIVEN-twitter-v2.md +110 -0
- package/articles/PAIN-DRIVEN-twitter-v3.md +121 -0
- package/articles/PAIN-DRIVEN-twitter.md +120 -0
- package/articles/PORTKEY_VS_A3M.md +147 -0
- package/articles/REDDIT_FINAL.md +232 -0
- package/articles/TWITTER_FINAL.md +167 -0
- package/articles/WHY_10X_BETTER.md +261 -0
- package/articles/WHY_CHINESE_STYLE_BETTER.md +323 -0
- package/articles/hashnode-llm-cost-optimization.md +125 -0
- package/articles/medium-building-llm-router.md +205 -0
- package/articles/twitter-thread-cost-savings.md +98 -0
- package/articles/youtube-tutorial-script.md +262 -0
- package/assets/banner.svg +109 -0
- package/assets/logo.svg +68 -0
- package/assets/social-preview.svg +64 -0
- package/demo/demo-script.md +53 -0
- package/dist/analytics/costAnalytics.d.ts +77 -0
- package/dist/analytics/costAnalytics.d.ts.map +1 -0
- package/dist/analytics/costAnalytics.js +219 -0
- package/dist/analytics/costAnalytics.js.map +1 -0
- package/dist/cache/semanticCache.d.ts +62 -0
- package/dist/cache/semanticCache.d.ts.map +1 -0
- package/dist/cache/semanticCache.js +176 -0
- package/dist/cache/semanticCache.js.map +1 -0
- package/dist/cli.js +35 -0
- package/dist/index.d.ts +30 -722
- package/dist/index.js +76 -355
- package/dist/index.js.map +1 -1
- package/dist/integrations/langchainAdapter.d.ts +146 -0
- package/dist/integrations/langchainAdapter.d.ts.map +1 -0
- package/dist/integrations/langchainAdapter.js +731 -0
- package/dist/integrations/langchainAdapter.js.map +1 -0
- package/dist/integrations/oauth.d.ts +69 -0
- package/dist/integrations/oauth.d.ts.map +1 -0
- package/dist/integrations/oauth.js +225 -21
- package/dist/integrations/oauth.js.map +1 -0
- package/dist/memory/autoFetch.d.ts +39 -0
- package/dist/memory/autoFetch.d.ts.map +1 -0
- package/dist/memory/autoFetch.js +80 -88
- package/dist/memory/autoFetch.js.map +1 -0
- package/dist/memory/memoryTree.d.ts +76 -0
- package/dist/memory/memoryTree.d.ts.map +1 -0
- package/dist/memory/memoryTree.js +185 -130
- package/dist/memory/memoryTree.js.map +1 -0
- package/dist/memory/obsidianVault.d.ts +71 -0
- package/dist/memory/obsidianVault.d.ts.map +1 -0
- package/dist/memory/obsidianVault.js +207 -22
- package/dist/memory/obsidianVault.js.map +1 -0
- package/dist/providers/providerConfig.d.ts +49 -0
- package/dist/providers/providerConfig.d.ts.map +1 -0
- package/dist/providers/providerConfig.js +806 -401
- package/dist/providers/providerConfig.js.map +1 -0
- package/dist/security/guardrails.d.ts +76 -0
- package/dist/security/guardrails.d.ts.map +1 -0
- package/dist/security/guardrails.js +479 -0
- package/dist/security/guardrails.js.map +1 -0
- package/dist/server/dashboard.d.ts +58 -0
- package/dist/server/dashboard.d.ts.map +1 -0
- package/dist/server/dashboard.js +553 -0
- package/dist/server/dashboard.js.map +1 -0
- package/dist/server/modelMapper.d.ts +43 -0
- package/dist/server/modelMapper.d.ts.map +1 -0
- package/dist/server/modelMapper.js +154 -0
- package/dist/server/modelMapper.js.map +1 -0
- package/dist/server/proxyServer.d.ts +41 -0
- package/dist/server/proxyServer.d.ts.map +1 -0
- package/dist/server/proxyServer.js +932 -0
- package/dist/server/proxyServer.js.map +1 -0
- package/dist/skills/__tests__/skill_manager.test.d.ts +2 -0
- package/dist/skills/__tests__/skill_manager.test.d.ts.map +1 -0
- package/dist/skills/__tests__/skill_manager.test.js +268 -0
- package/dist/skills/__tests__/skill_manager.test.js.map +1 -0
- package/docs-site/index.html +347 -0
- package/package.json +53 -7
- package/playground/README.md +51 -0
- package/playground/codesandbox.json +12 -0
- package/playground/index.js +39 -0
- package/scripts/update-npm-badges.js +158 -0
- package/src/analytics/costAnalytics.ts +304 -0
- package/src/cache/semanticCache.ts +221 -0
- package/src/index.ts +99 -0
- package/src/integrations/langchainAdapter.ts +955 -0
- package/src/providers/providerConfig.ts +923 -0
- package/src/security/guardrails.ts +585 -0
- package/src/server/dashboard.ts +610 -0
- package/src/server/modelMapper.ts +182 -0
- package/src/server/proxyServer.ts +1105 -0
- package/src/types/langchain.d.ts +83 -0
- package/tsconfig.build.json +20 -0
package/assets/logo.svg
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="200" height="200">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="gradient1" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
4
|
+
<stop offset="0%" style="stop-color:#6366f1;stop-opacity:1" />
|
|
5
|
+
<stop offset="50%" style="stop-color:#8b5cf6;stop-opacity:1" />
|
|
6
|
+
<stop offset="100%" style="stop-color:#a855f7;stop-opacity:1" />
|
|
7
|
+
</linearGradient>
|
|
8
|
+
<linearGradient id="gradient2" x1="0%" y1="100%" x2="100%" y2="0%">
|
|
9
|
+
<stop offset="0%" style="stop-color:#3b82f6;stop-opacity:1" />
|
|
10
|
+
<stop offset="100%" style="stop-color:#06b6d4;stop-opacity:1" />
|
|
11
|
+
</linearGradient>
|
|
12
|
+
<filter id="glow">
|
|
13
|
+
<feGaussianBlur stdDeviation="3" result="coloredBlur"/>
|
|
14
|
+
<feMerge>
|
|
15
|
+
<feMergeNode in="coloredBlur"/>
|
|
16
|
+
<feMergeNode in="SourceGraphic"/>
|
|
17
|
+
</feMerge>
|
|
18
|
+
</filter>
|
|
19
|
+
</defs>
|
|
20
|
+
|
|
21
|
+
<!-- Background Circle -->
|
|
22
|
+
<circle cx="100" cy="100" r="90" fill="url(#gradient1)" opacity="0.1"/>
|
|
23
|
+
<circle cx="100" cy="100" r="85" fill="none" stroke="url(#gradient1)" stroke-width="2" opacity="0.3"/>
|
|
24
|
+
|
|
25
|
+
<!-- Central Hub -->
|
|
26
|
+
<circle cx="100" cy="100" r="25" fill="url(#gradient1)" filter="url(#glow)"/>
|
|
27
|
+
|
|
28
|
+
<!-- Orbiting Nodes -->
|
|
29
|
+
<g transform="translate(100, 100)">
|
|
30
|
+
<!-- Node 1 -->
|
|
31
|
+
<circle cx="0" cy="-60" r="12" fill="url(#gradient2)" opacity="0.9">
|
|
32
|
+
<animateTransform attributeName="transform" type="rotate" from="0 0 0" to="360 0 0" dur="8s" repeatCount="indefinite"/>
|
|
33
|
+
</circle>
|
|
34
|
+
|
|
35
|
+
<!-- Node 2 -->
|
|
36
|
+
<circle cx="52" cy="30" r="10" fill="#10b981" opacity="0.9">
|
|
37
|
+
<animateTransform attributeName="transform" type="rotate" from="120 0 0" to="480 0 0" dur="10s" repeatCount="indefinite"/>
|
|
38
|
+
</circle>
|
|
39
|
+
|
|
40
|
+
<!-- Node 3 -->
|
|
41
|
+
<circle cx="-52" cy="30" r="10" fill="#f59e0b" opacity="0.9">
|
|
42
|
+
<animateTransform attributeName="transform" type="rotate" from="240 0 0" to="600 0 0" dur="12s" repeatCount="indefinite"/>
|
|
43
|
+
</circle>
|
|
44
|
+
</g>
|
|
45
|
+
|
|
46
|
+
<!-- Connection Lines -->
|
|
47
|
+
<g stroke="url(#gradient1)" stroke-width="2" opacity="0.6">
|
|
48
|
+
<line x1="100" y1="100" x2="100" y2="40">
|
|
49
|
+
<animate attributeName="y2" values="40;35;40" dur="2s" repeatCount="indefinite"/>
|
|
50
|
+
</line>
|
|
51
|
+
<line x1="100" y1="100" x2="152" y2="130">
|
|
52
|
+
<animate attributeName="x2" values="152;157;152" dur="2.5s" repeatCount="indefinite"/>
|
|
53
|
+
<animate attributeName="y2" values="130;135;130" dur="2.5s" repeatCount="indefinite"/>
|
|
54
|
+
</line>
|
|
55
|
+
<line x1="100" y1="100" x2="48" y2="130">
|
|
56
|
+
<animate attributeName="x2" values="48;43;48" dur="3s" repeatCount="indefinite"/>
|
|
57
|
+
<animate attributeName="y2" values="130;135;130" dur="3s" repeatCount="indefinite"/>
|
|
58
|
+
</line>
|
|
59
|
+
</g>
|
|
60
|
+
|
|
61
|
+
<!-- A3M Text -->
|
|
62
|
+
<text x="100" y="105" font-family="system-ui, -apple-system, sans-serif" font-size="14" font-weight="bold" fill="white" text-anchor="middle">A3M</text>
|
|
63
|
+
|
|
64
|
+
<!-- Outer Ring Animation -->
|
|
65
|
+
<circle cx="100" cy="100" r="75" fill="none" stroke="url(#gradient1)" stroke-width="1" stroke-dasharray="10 5" opacity="0.5">
|
|
66
|
+
<animateTransform attributeName="transform" type="rotate" from="0 100 100" to="360 100 100" dur="20s" repeatCount="indefinite"/>
|
|
67
|
+
</circle>
|
|
68
|
+
</svg>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1280 640" width="1280" height="640">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="spBg" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
4
|
+
<stop offset="0%" style="stop-color:#0f172a"/>
|
|
5
|
+
<stop offset="100%" style="stop-color:#1e1b4b"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
<linearGradient id="spAccent" x1="0%" y1="0%" x2="100%" y2="0%">
|
|
8
|
+
<stop offset="0%" style="stop-color:#6366f1"/>
|
|
9
|
+
<stop offset="100%" style="stop-color:#06b6d4"/>
|
|
10
|
+
</linearGradient>
|
|
11
|
+
<filter id="spGlow">
|
|
12
|
+
<feGaussianBlur stdDeviation="6" result="blur"/>
|
|
13
|
+
<feMerge>
|
|
14
|
+
<feMergeNode in="blur"/>
|
|
15
|
+
<feMergeNode in="SourceGraphic"/>
|
|
16
|
+
</feMerge>
|
|
17
|
+
</filter>
|
|
18
|
+
</defs>
|
|
19
|
+
|
|
20
|
+
<!-- Background -->
|
|
21
|
+
<rect width="1280" height="640" fill="url(#spBg)"/>
|
|
22
|
+
|
|
23
|
+
<!-- Grid Pattern -->
|
|
24
|
+
<pattern id="spGrid" width="60" height="60" patternUnits="userSpaceOnUse">
|
|
25
|
+
<path d="M 60 0 L 0 0 0 60" fill="none" stroke="rgba(99,102,241,0.08)" stroke-width="1"/>
|
|
26
|
+
</pattern>
|
|
27
|
+
<rect width="1280" height="640" fill="url(#spGrid)"/>
|
|
28
|
+
|
|
29
|
+
<!-- Central Logo -->
|
|
30
|
+
<g transform="translate(640, 280)">
|
|
31
|
+
<!-- Outer Rings -->
|
|
32
|
+
<circle cx="0" cy="0" r="180" fill="none" stroke="url(#spAccent)" stroke-width="2" opacity="0.2"/>
|
|
33
|
+
<circle cx="0" cy="0" r="150" fill="none" stroke="url(#spAccent)" stroke-width="1" opacity="0.15" stroke-dasharray="10 5"/>
|
|
34
|
+
|
|
35
|
+
<!-- Main Circle -->
|
|
36
|
+
<circle cx="0" cy="0" r="80" fill="url(#spAccent)" opacity="0.1"/>
|
|
37
|
+
<circle cx="0" cy="0" r="60" fill="url(#spAccent)" filter="url(#spGlow)"/>
|
|
38
|
+
|
|
39
|
+
<!-- Orbiting Dots -->
|
|
40
|
+
<circle cx="0" cy="-120" r="15" fill="#6366f1"/>
|
|
41
|
+
<circle cx="104" cy="60" r="12" fill="#10b981"/>
|
|
42
|
+
<circle cx="-104" cy="60" r="12" fill="#f59e0b"/>
|
|
43
|
+
|
|
44
|
+
<!-- Connection Lines -->
|
|
45
|
+
<line x1="0" y1="0" x2="0" y2="-120" stroke="url(#spAccent)" stroke-width="3" opacity="0.6"/>
|
|
46
|
+
<line x1="0" y1="0" x2="104" y2="60" stroke="url(#spAccent)" stroke-width="3" opacity="0.6"/>
|
|
47
|
+
<line x1="0" y1="0" x2="-104" y2="60" stroke="url(#spAccent)" stroke-width="3" opacity="0.6"/>
|
|
48
|
+
|
|
49
|
+
<!-- Text -->
|
|
50
|
+
<text x="0" y="20" font-family="system-ui, -apple-system, sans-serif" font-size="48" font-weight="bold" fill="white" text-anchor="middle">A3M</text>
|
|
51
|
+
</g>
|
|
52
|
+
|
|
53
|
+
<!-- Title -->
|
|
54
|
+
<text x="640" y="520" font-family="system-ui, -apple-system, sans-serif" font-size="56" font-weight="bold" fill="white" text-anchor="middle">A3M Router</text>
|
|
55
|
+
|
|
56
|
+
<!-- Subtitle -->
|
|
57
|
+
<text x="640" y="580" font-family="system-ui, -apple-system, sans-serif" font-size="28" fill="#94a3b8" text-anchor="middle">Adaptive Memory Multi-Model Router</text>
|
|
58
|
+
|
|
59
|
+
<!-- NPM Badge -->
|
|
60
|
+
<g transform="translate(640, 620)">
|
|
61
|
+
<rect x="-120" y="-15" width="240" height="30" rx="15" fill="rgba(255,255,255,0.1)"/>
|
|
62
|
+
<text x="0" y="5" font-family="system-ui, -apple-system, sans-serif" font-size="14" fill="#cbd5e1" text-anchor="middle">872+ Weekly Downloads on NPM</text>
|
|
63
|
+
</g>
|
|
64
|
+
</svg>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# A3M Router Demo Script for GIF/Video
|
|
2
|
+
|
|
3
|
+
## Scene 1: Installation (5 seconds)
|
|
4
|
+
```bash
|
|
5
|
+
npm install adaptive-memory-multi-model-router
|
|
6
|
+
```
|
|
7
|
+
Show: Fast installation, dependency count (just nanoid)
|
|
8
|
+
|
|
9
|
+
## Scene 2: CLI Providers Command (8 seconds)
|
|
10
|
+
```bash
|
|
11
|
+
npx a3m-router providers
|
|
12
|
+
```
|
|
13
|
+
Show: Table of 9 configured providers with checkmarks
|
|
14
|
+
Highlight: Groq, Cerebras, Mistral, CommandCode, OpenCode
|
|
15
|
+
|
|
16
|
+
## Scene 3: Route Query (10 seconds)
|
|
17
|
+
```bash
|
|
18
|
+
npx a3m-router route "Write Python to sort an array"
|
|
19
|
+
```
|
|
20
|
+
Show: Routing result
|
|
21
|
+
- Primary: groq/llama-3.3-70b
|
|
22
|
+
- Fallbacks: mistral/medium, cerebras/llama
|
|
23
|
+
- Est. Cost: $0.0004
|
|
24
|
+
- Reason: code detected
|
|
25
|
+
|
|
26
|
+
## Scene 4: Compare Providers (12 seconds)
|
|
27
|
+
```bash
|
|
28
|
+
npx a3m-router compare "What is 2+2?"
|
|
29
|
+
```
|
|
30
|
+
Show: Side-by-side comparison
|
|
31
|
+
- Groq: "4" 450ms $0.0001
|
|
32
|
+
- Cerebras: "4" 380ms $0.0001
|
|
33
|
+
- Mistral: "4" 520ms $0.0002
|
|
34
|
+
|
|
35
|
+
## Scene 5: Benchmark All (15 seconds)
|
|
36
|
+
```bash
|
|
37
|
+
npx a3m-router benchmark
|
|
38
|
+
```
|
|
39
|
+
Show: Ranking table
|
|
40
|
+
- Fastest: Cerebras 380ms
|
|
41
|
+
- Cheapest: CommandCode FREE
|
|
42
|
+
- Best Quality: Mistral 96%
|
|
43
|
+
|
|
44
|
+
## Scene 6: Code Example (10 seconds)
|
|
45
|
+
```javascript
|
|
46
|
+
const { createA3MRouter } = require('adaptive-memory-multi-model-router');
|
|
47
|
+
const router = createA3MRouter();
|
|
48
|
+
const result = await router.route("Explain quantum physics");
|
|
49
|
+
console.log(result.primary_model); // "mistral/mistral-large"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Total Duration: ~60 seconds
|
|
53
|
+
## Tools: terminalizer, asciinema, or simple screen recording
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A3M Router - Cost Analytics
|
|
3
|
+
*
|
|
4
|
+
* Advanced cost tracking and analytics:
|
|
5
|
+
* - Record every request with full metadata
|
|
6
|
+
* - Real-time savings vs single premium provider
|
|
7
|
+
* - Monthly/yearly projections
|
|
8
|
+
* - Breakdown by provider and query type
|
|
9
|
+
* - Export to JSON or CSV
|
|
10
|
+
* - In-memory storage with auto-rotation
|
|
11
|
+
*/
|
|
12
|
+
export interface CostRecord {
|
|
13
|
+
timestamp: Date;
|
|
14
|
+
provider: string;
|
|
15
|
+
model: string;
|
|
16
|
+
inputTokens: number;
|
|
17
|
+
outputTokens: number;
|
|
18
|
+
cost: number;
|
|
19
|
+
latency: number;
|
|
20
|
+
queryType: 'simple' | 'code' | 'summary' | 'complex';
|
|
21
|
+
cached: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface CostSummary {
|
|
24
|
+
totalCost: number;
|
|
25
|
+
totalRequests: number;
|
|
26
|
+
totalInputTokens: number;
|
|
27
|
+
totalOutputTokens: number;
|
|
28
|
+
avgLatency: number;
|
|
29
|
+
cacheHitRate: number;
|
|
30
|
+
period: {
|
|
31
|
+
start: Date;
|
|
32
|
+
end: Date;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export interface ProviderStats {
|
|
36
|
+
totalCost: number;
|
|
37
|
+
totalRequests: number;
|
|
38
|
+
avgLatency: number;
|
|
39
|
+
totalInputTokens: number;
|
|
40
|
+
totalOutputTokens: number;
|
|
41
|
+
models: Record<string, {
|
|
42
|
+
cost: number;
|
|
43
|
+
requests: number;
|
|
44
|
+
}>;
|
|
45
|
+
}
|
|
46
|
+
export interface QueryTypeStats {
|
|
47
|
+
totalCost: number;
|
|
48
|
+
totalRequests: number;
|
|
49
|
+
avgLatency: number;
|
|
50
|
+
cachedCount: number;
|
|
51
|
+
cacheHitRate: number;
|
|
52
|
+
}
|
|
53
|
+
export interface SavingsReport {
|
|
54
|
+
totalSaved: number;
|
|
55
|
+
percentageSaved: number;
|
|
56
|
+
byQueryType: Record<string, {
|
|
57
|
+
saved: number;
|
|
58
|
+
percentage: number;
|
|
59
|
+
}>;
|
|
60
|
+
projectedMonthlySavings: number;
|
|
61
|
+
projectedYearlySavings: number;
|
|
62
|
+
}
|
|
63
|
+
export declare class CostAnalytics {
|
|
64
|
+
private records;
|
|
65
|
+
private maxRecords;
|
|
66
|
+
constructor(maxRecords?: number);
|
|
67
|
+
record(data: Omit<CostRecord, 'timestamp'>): void;
|
|
68
|
+
getSummary(period?: 'hour' | 'day' | 'week' | 'month'): CostSummary;
|
|
69
|
+
getByProvider(): Record<string, ProviderStats>;
|
|
70
|
+
getByQueryType(): Record<string, QueryTypeStats>;
|
|
71
|
+
getSavings(baselineProvider?: string): SavingsReport;
|
|
72
|
+
export(format?: 'json' | 'csv'): string;
|
|
73
|
+
reset(): void;
|
|
74
|
+
private filterByPeriod;
|
|
75
|
+
private getDaysCovered;
|
|
76
|
+
}
|
|
77
|
+
export declare function createCostAnalytics(maxRecords?: number): CostAnalytics;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"costAnalytics.d.ts","sourceRoot":"","sources":["../../src/analytics/costAnalytics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;IACrD,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE;QAAE,KAAK,EAAE,IAAI,CAAC;QAAC,GAAG,EAAE,IAAI,CAAA;KAAE,CAAC;CACpC;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnE,uBAAuB,EAAE,MAAM,CAAC;IAChC,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAuBD,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,UAAU,CAAS;gBAEf,UAAU,GAAE,MAAc;IAMtC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,GAAG,IAAI;IAYjD,UAAU,CAAC,MAAM,GAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,OAAe,GAAG,WAAW;IA6B1E,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC;IAkC9C,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC;IA2BhD,UAAU,CAAC,gBAAgB,GAAE,MAAiB,GAAG,aAAa;IAiD9D,MAAM,CAAC,MAAM,GAAE,MAAM,GAAG,KAAc,GAAG,MAAM;IAa/C,KAAK,IAAI,IAAI;IAMb,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,cAAc;CAMvB;AAmBD,wBAAgB,mBAAmB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,aAAa,CAEtE"}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* A3M Router - Cost Analytics
|
|
4
|
+
*
|
|
5
|
+
* Advanced cost tracking and analytics:
|
|
6
|
+
* - Record every request with full metadata
|
|
7
|
+
* - Real-time savings vs single premium provider
|
|
8
|
+
* - Monthly/yearly projections
|
|
9
|
+
* - Breakdown by provider and query type
|
|
10
|
+
* - Export to JSON or CSV
|
|
11
|
+
* - In-memory storage with auto-rotation
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.CostAnalytics = void 0;
|
|
15
|
+
exports.createCostAnalytics = createCostAnalytics;
|
|
16
|
+
// Model costs per 1M tokens (USD) for baseline comparison
|
|
17
|
+
const BASELINE_COSTS = {
|
|
18
|
+
'gpt-4o': { input: 2.50, output: 10.00 },
|
|
19
|
+
'gpt-4-turbo': { input: 10.00, output: 30.00 },
|
|
20
|
+
'claude-3.5-sonnet': { input: 3.00, output: 15.00 },
|
|
21
|
+
'claude-3-opus': { input: 15.00, output: 75.00 },
|
|
22
|
+
'claude-3-haiku': { input: 0.25, output: 1.25 },
|
|
23
|
+
'gpt-3.5-turbo': { input: 0.50, output: 1.50 },
|
|
24
|
+
'gemini-1.5-pro': { input: 1.25, output: 5.00 },
|
|
25
|
+
'gemini-1.5-flash': { input: 0.075, output: 0.30 },
|
|
26
|
+
'groq/llama-3.3-70b': { input: 0.59, output: 0.79 },
|
|
27
|
+
'groq/llama-3.1-8b': { input: 0.05, output: 0.08 },
|
|
28
|
+
'cerebras/llama-3.3-70b': { input: 0.10, output: 0.10 },
|
|
29
|
+
'mistral-large': { input: 2.00, output: 6.00 },
|
|
30
|
+
'mistral-small': { input: 0.20, output: 0.60 },
|
|
31
|
+
};
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// CostAnalytics
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
class CostAnalytics {
|
|
36
|
+
records = [];
|
|
37
|
+
maxRecords;
|
|
38
|
+
constructor(maxRecords = 10000) {
|
|
39
|
+
this.maxRecords = maxRecords;
|
|
40
|
+
}
|
|
41
|
+
// ---- Record ----
|
|
42
|
+
record(data) {
|
|
43
|
+
const entry = { ...data, timestamp: new Date() };
|
|
44
|
+
this.records.push(entry);
|
|
45
|
+
// Auto-rotate
|
|
46
|
+
if (this.records.length > this.maxRecords) {
|
|
47
|
+
this.records = this.records.slice(-this.maxRecords);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// ---- Summary ----
|
|
51
|
+
getSummary(period = 'day') {
|
|
52
|
+
const filtered = this.filterByPeriod(period);
|
|
53
|
+
if (filtered.length === 0) {
|
|
54
|
+
const now = new Date();
|
|
55
|
+
return {
|
|
56
|
+
totalCost: 0, totalRequests: 0, totalInputTokens: 0, totalOutputTokens: 0,
|
|
57
|
+
avgLatency: 0, cacheHitRate: 0,
|
|
58
|
+
period: { start: now, end: now },
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
const totalCost = sum(filtered, (r) => r.cost);
|
|
62
|
+
const cached = filtered.filter((r) => r.cached).length;
|
|
63
|
+
const start = filtered[0].timestamp;
|
|
64
|
+
const end = filtered[filtered.length - 1].timestamp;
|
|
65
|
+
return {
|
|
66
|
+
totalCost: round(totalCost),
|
|
67
|
+
totalRequests: filtered.length,
|
|
68
|
+
totalInputTokens: sum(filtered, (r) => r.inputTokens),
|
|
69
|
+
totalOutputTokens: sum(filtered, (r) => r.outputTokens),
|
|
70
|
+
avgLatency: round(sum(filtered, (r) => r.latency) / filtered.length),
|
|
71
|
+
cacheHitRate: round(cached / filtered.length),
|
|
72
|
+
period: { start, end },
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
// ---- By provider ----
|
|
76
|
+
getByProvider() {
|
|
77
|
+
const result = {};
|
|
78
|
+
for (const r of this.records) {
|
|
79
|
+
if (!result[r.provider]) {
|
|
80
|
+
result[r.provider] = {
|
|
81
|
+
totalCost: 0, totalRequests: 0, avgLatency: 0,
|
|
82
|
+
totalInputTokens: 0, totalOutputTokens: 0, models: {},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
const p = result[r.provider];
|
|
86
|
+
p.totalCost += r.cost;
|
|
87
|
+
p.totalRequests++;
|
|
88
|
+
p.avgLatency += r.latency;
|
|
89
|
+
p.totalInputTokens += r.inputTokens;
|
|
90
|
+
p.totalOutputTokens += r.outputTokens;
|
|
91
|
+
if (!p.models[r.model]) {
|
|
92
|
+
p.models[r.model] = { cost: 0, requests: 0 };
|
|
93
|
+
}
|
|
94
|
+
p.models[r.model].cost += r.cost;
|
|
95
|
+
p.models[r.model].requests++;
|
|
96
|
+
}
|
|
97
|
+
for (const p of Object.values(result)) {
|
|
98
|
+
if (p.totalRequests > 0) {
|
|
99
|
+
p.avgLatency = round(p.avgLatency / p.totalRequests);
|
|
100
|
+
}
|
|
101
|
+
p.totalCost = round(p.totalCost);
|
|
102
|
+
}
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
// ---- By query type ----
|
|
106
|
+
getByQueryType() {
|
|
107
|
+
const result = {};
|
|
108
|
+
for (const r of this.records) {
|
|
109
|
+
if (!result[r.queryType]) {
|
|
110
|
+
result[r.queryType] = {
|
|
111
|
+
totalCost: 0, totalRequests: 0, avgLatency: 0, cachedCount: 0, cacheHitRate: 0,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
const q = result[r.queryType];
|
|
115
|
+
q.totalCost += r.cost;
|
|
116
|
+
q.totalRequests++;
|
|
117
|
+
q.avgLatency += r.latency;
|
|
118
|
+
if (r.cached)
|
|
119
|
+
q.cachedCount++;
|
|
120
|
+
}
|
|
121
|
+
for (const q of Object.values(result)) {
|
|
122
|
+
if (q.totalRequests > 0) {
|
|
123
|
+
q.avgLatency = round(q.avgLatency / q.totalRequests);
|
|
124
|
+
q.cacheHitRate = round(q.cachedCount / q.totalRequests);
|
|
125
|
+
}
|
|
126
|
+
q.totalCost = round(q.totalCost);
|
|
127
|
+
}
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
// ---- Savings ----
|
|
131
|
+
getSavings(baselineProvider = 'gpt-4o') {
|
|
132
|
+
const baseline = BASELINE_COSTS[baselineProvider] || { input: 2.50, output: 10.00 };
|
|
133
|
+
let totalActual = 0;
|
|
134
|
+
let totalBaseline = 0;
|
|
135
|
+
const byQueryType = {};
|
|
136
|
+
for (const r of this.records) {
|
|
137
|
+
const actualCost = r.cost;
|
|
138
|
+
const baselineCost = (r.inputTokens / 1_000_000) * baseline.input +
|
|
139
|
+
(r.outputTokens / 1_000_000) * baseline.output;
|
|
140
|
+
totalActual += actualCost;
|
|
141
|
+
totalBaseline += baselineCost;
|
|
142
|
+
if (!byQueryType[r.queryType]) {
|
|
143
|
+
byQueryType[r.queryType] = { actual: 0, baseline: 0 };
|
|
144
|
+
}
|
|
145
|
+
byQueryType[r.queryType].actual += actualCost;
|
|
146
|
+
byQueryType[r.queryType].baseline += baselineCost;
|
|
147
|
+
}
|
|
148
|
+
const totalSaved = totalBaseline - totalActual;
|
|
149
|
+
const percentageSaved = totalBaseline > 0 ? (totalSaved / totalBaseline) * 100 : 0;
|
|
150
|
+
// Project based on days of data we have
|
|
151
|
+
const daysCovered = this.getDaysCovered();
|
|
152
|
+
const dailySavings = daysCovered > 0 ? totalSaved / daysCovered : 0;
|
|
153
|
+
const queryTypeSavings = {};
|
|
154
|
+
for (const [qt, data] of Object.entries(byQueryType)) {
|
|
155
|
+
const saved = data.baseline - data.actual;
|
|
156
|
+
queryTypeSavings[qt] = {
|
|
157
|
+
saved: round(saved),
|
|
158
|
+
percentage: data.baseline > 0 ? round((saved / data.baseline) * 100) : 0,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
totalSaved: round(totalSaved),
|
|
163
|
+
percentageSaved: round(percentageSaved),
|
|
164
|
+
byQueryType: queryTypeSavings,
|
|
165
|
+
projectedMonthlySavings: round(dailySavings * 30),
|
|
166
|
+
projectedYearlySavings: round(dailySavings * 365),
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
// ---- Export ----
|
|
170
|
+
export(format = 'json') {
|
|
171
|
+
if (format === 'csv') {
|
|
172
|
+
const header = 'timestamp,provider,model,inputTokens,outputTokens,cost,latency,queryType,cached';
|
|
173
|
+
const rows = this.records.map((r) => `${r.timestamp.toISOString()},${r.provider},${r.model},${r.inputTokens},${r.outputTokens},${r.cost},${r.latency},${r.queryType},${r.cached}`);
|
|
174
|
+
return [header, ...rows].join('\n');
|
|
175
|
+
}
|
|
176
|
+
return JSON.stringify(this.records, null, 2);
|
|
177
|
+
}
|
|
178
|
+
// ---- Reset ----
|
|
179
|
+
reset() {
|
|
180
|
+
this.records = [];
|
|
181
|
+
}
|
|
182
|
+
// ---- Internals ----
|
|
183
|
+
filterByPeriod(period) {
|
|
184
|
+
const now = Date.now();
|
|
185
|
+
const ms = {
|
|
186
|
+
hour: 3600_000,
|
|
187
|
+
day: 86400_000,
|
|
188
|
+
week: 604800_000,
|
|
189
|
+
month: 2592000_000,
|
|
190
|
+
};
|
|
191
|
+
const cutoff = now - (ms[period] || ms.day);
|
|
192
|
+
return this.records.filter((r) => r.timestamp.getTime() >= cutoff);
|
|
193
|
+
}
|
|
194
|
+
getDaysCovered() {
|
|
195
|
+
if (this.records.length < 2)
|
|
196
|
+
return 1;
|
|
197
|
+
const first = this.records[0].timestamp.getTime();
|
|
198
|
+
const last = this.records[this.records.length - 1].timestamp.getTime();
|
|
199
|
+
return Math.max(1, (last - first) / 86400_000);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
exports.CostAnalytics = CostAnalytics;
|
|
203
|
+
// ---------------------------------------------------------------------------
|
|
204
|
+
// Helpers
|
|
205
|
+
// ---------------------------------------------------------------------------
|
|
206
|
+
function sum(arr, fn) {
|
|
207
|
+
return arr.reduce((acc, r) => acc + fn(r), 0);
|
|
208
|
+
}
|
|
209
|
+
function round(n, decimals = 4) {
|
|
210
|
+
const factor = Math.pow(10, decimals);
|
|
211
|
+
return Math.round(n * factor) / factor;
|
|
212
|
+
}
|
|
213
|
+
// ---------------------------------------------------------------------------
|
|
214
|
+
// Convenience factory
|
|
215
|
+
// ---------------------------------------------------------------------------
|
|
216
|
+
function createCostAnalytics(maxRecords) {
|
|
217
|
+
return new CostAnalytics(maxRecords);
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=costAnalytics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"costAnalytics.js","sourceRoot":"","sources":["../../src/analytics/costAnalytics.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;AAmSH,kDAEC;AAhPD,0DAA0D;AAC1D,MAAM,cAAc,GAAsD;IACxE,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE;IACxC,aAAa,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE;IAC9C,mBAAmB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE;IACnD,eAAe,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE;IAChD,gBAAgB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;IAC/C,eAAe,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;IAC9C,gBAAgB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;IAC/C,kBAAkB,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE;IAClD,oBAAoB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;IACnD,mBAAmB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;IAClD,wBAAwB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;IACvD,eAAe,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;IAC9C,eAAe,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;CAC/C,CAAC;AAEF,8EAA8E;AAC9E,gBAAgB;AAChB,8EAA8E;AAE9E,MAAa,aAAa;IAChB,OAAO,GAAiB,EAAE,CAAC;IAC3B,UAAU,CAAS;IAE3B,YAAY,aAAqB,KAAK;QACpC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,mBAAmB;IAEnB,MAAM,CAAC,IAAmC;QACxC,MAAM,KAAK,GAAe,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;QAC7D,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEzB,cAAc;QACd,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;YAC1C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAED,oBAAoB;IAEpB,UAAU,CAAC,SAA4C,KAAK;QAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC7C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,OAAO;gBACL,SAAS,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE,iBAAiB,EAAE,CAAC;gBACzE,UAAU,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC;gBAC9B,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;aACjC,CAAC;QACJ,CAAC;QAED,MAAM,SAAS,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;QACvD,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACpC,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;QAEpD,OAAO;YACL,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC;YAC3B,aAAa,EAAE,QAAQ,CAAC,MAAM;YAC9B,gBAAgB,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;YACrD,iBAAiB,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC;YACvD,UAAU,EAAE,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC;YACpE,YAAY,EAAE,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;YAC7C,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE;SACvB,CAAC;IACJ,CAAC;IAED,wBAAwB;IAExB,aAAa;QACX,MAAM,MAAM,GAAkC,EAAE,CAAC;QACjD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC7B,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACxB,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG;oBACnB,SAAS,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC;oBAC7C,gBAAgB,EAAE,CAAC,EAAE,iBAAiB,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE;iBACtD,CAAC;YACJ,CAAC;YACD,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;YAC7B,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,IAAI,CAAC;YACtB,CAAC,CAAC,aAAa,EAAE,CAAC;YAClB,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,OAAO,CAAC;YAC1B,CAAC,CAAC,gBAAgB,IAAI,CAAC,CAAC,WAAW,CAAC;YACpC,CAAC,CAAC,iBAAiB,IAAI,CAAC,CAAC,YAAY,CAAC;YAEtC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;gBACvB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;YAC/C,CAAC;YACD,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC;YACjC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC/B,CAAC;QAED,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;YACtC,IAAI,CAAC,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;gBACxB,CAAC,CAAC,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC;YACvD,CAAC;YACD,CAAC,CAAC,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACnC,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,0BAA0B;IAE1B,cAAc;QACZ,MAAM,MAAM,GAAmC,EAAE,CAAC;QAClD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC7B,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC;gBACzB,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG;oBACpB,SAAS,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC;iBAC/E,CAAC;YACJ,CAAC;YACD,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YAC9B,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,IAAI,CAAC;YACtB,CAAC,CAAC,aAAa,EAAE,CAAC;YAClB,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,OAAO,CAAC;YAC1B,IAAI,CAAC,CAAC,MAAM;gBAAE,CAAC,CAAC,WAAW,EAAE,CAAC;QAChC,CAAC;QAED,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;YACtC,IAAI,CAAC,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;gBACxB,CAAC,CAAC,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC;gBACrD,CAAC,CAAC,YAAY,GAAG,KAAK,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC;YAC1D,CAAC;YACD,CAAC,CAAC,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACnC,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,oBAAoB;IAEpB,UAAU,CAAC,mBAA2B,QAAQ;QAC5C,MAAM,QAAQ,GAAG,cAAc,CAAC,gBAAgB,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QACpF,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,IAAI,aAAa,GAAG,CAAC,CAAC;QACtB,MAAM,WAAW,GAAyD,EAAE,CAAC;QAE7E,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC7B,MAAM,UAAU,GAAG,CAAC,CAAC,IAAI,CAAC;YAC1B,MAAM,YAAY,GAChB,CAAC,CAAC,CAAC,WAAW,GAAG,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK;gBAC5C,CAAC,CAAC,CAAC,YAAY,GAAG,SAAS,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC;YAEjD,WAAW,IAAI,UAAU,CAAC;YAC1B,aAAa,IAAI,YAAY,CAAC;YAE9B,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC9B,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;YACxD,CAAC;YACD,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,IAAI,UAAU,CAAC;YAC9C,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,QAAQ,IAAI,YAAY,CAAC;QACpD,CAAC;QAED,MAAM,UAAU,GAAG,aAAa,GAAG,WAAW,CAAC;QAC/C,MAAM,eAAe,GAAG,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,aAAa,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAEnF,wCAAwC;QACxC,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QAC1C,MAAM,YAAY,GAAG,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;QAEpE,MAAM,gBAAgB,GAA0D,EAAE,CAAC;QACnF,KAAK,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;YACrD,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC;YAC1C,gBAAgB,CAAC,EAAE,CAAC,GAAG;gBACrB,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC;gBACnB,UAAU,EAAE,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;aACzE,CAAC;QACJ,CAAC;QAED,OAAO;YACL,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC;YAC7B,eAAe,EAAE,KAAK,CAAC,eAAe,CAAC;YACvC,WAAW,EAAE,gBAAgB;YAC7B,uBAAuB,EAAE,KAAK,CAAC,YAAY,GAAG,EAAE,CAAC;YACjD,sBAAsB,EAAE,KAAK,CAAC,YAAY,GAAG,GAAG,CAAC;SAClD,CAAC;IACJ,CAAC;IAED,mBAAmB;IAEnB,MAAM,CAAC,SAAyB,MAAM;QACpC,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;YACrB,MAAM,MAAM,GAAG,iFAAiF,CAAC;YACjG,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAClC,GAAG,CAAC,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,MAAM,EAAE,CAC7I,CAAC;YACF,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtC,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC/C,CAAC;IAED,kBAAkB;IAElB,KAAK;QACH,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;IACpB,CAAC;IAED,sBAAsB;IAEd,cAAc,CAAC,MAAyC;QAC9D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,EAAE,GAA2B;YACjC,IAAI,EAAE,QAAQ;YACd,GAAG,EAAE,SAAS;YACd,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,WAAW;SACnB,CAAC;QACF,MAAM,MAAM,GAAG,GAAG,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,MAAM,CAAC,CAAC;IACrE,CAAC;IAEO,cAAc;QACpB,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,CAAC,CAAC;QACtC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;QAClD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;QACvE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,SAAS,CAAC,CAAC;IACjD,CAAC;CACF;AAtMD,sCAsMC;AAED,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,SAAS,GAAG,CAAC,GAAiB,EAAE,EAA6B;IAC3D,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,KAAK,CAAC,CAAS,EAAE,WAAmB,CAAC;IAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;IACtC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC;AACzC,CAAC;AAED,8EAA8E;AAC9E,sBAAsB;AACtB,8EAA8E;AAE9E,SAAgB,mBAAmB,CAAC,UAAmB;IACrD,OAAO,IAAI,aAAa,CAAC,UAAU,CAAC,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A3M Router - Semantic Cache
|
|
3
|
+
*
|
|
4
|
+
* Stores previous query->response pairs and returns cached responses
|
|
5
|
+
* for semantically similar queries using character n-gram Jaccard similarity.
|
|
6
|
+
*
|
|
7
|
+
* No external embedding API needed. Trigram overlap catches paraphrases like:
|
|
8
|
+
* "What is Python?" ≈ "Tell me about Python" ≈ "Explain Python"
|
|
9
|
+
* "Write a sort fn" ≈ "Create a sorting fn" ≈ "How to sort an array"
|
|
10
|
+
*/
|
|
11
|
+
export interface CachedResponse {
|
|
12
|
+
query: string;
|
|
13
|
+
response: string;
|
|
14
|
+
metadata?: any;
|
|
15
|
+
cachedAt: number;
|
|
16
|
+
hitCount: number;
|
|
17
|
+
}
|
|
18
|
+
export interface SemanticCacheOptions {
|
|
19
|
+
maxSize?: number;
|
|
20
|
+
similarityThreshold?: number;
|
|
21
|
+
ttl?: number;
|
|
22
|
+
}
|
|
23
|
+
export interface SemanticCacheStats {
|
|
24
|
+
hits: number;
|
|
25
|
+
misses: number;
|
|
26
|
+
hitRate: number;
|
|
27
|
+
size: number;
|
|
28
|
+
}
|
|
29
|
+
export declare class SemanticCache {
|
|
30
|
+
private entries;
|
|
31
|
+
private maxSize;
|
|
32
|
+
private similarityThreshold;
|
|
33
|
+
private ttl;
|
|
34
|
+
private hits;
|
|
35
|
+
private misses;
|
|
36
|
+
constructor(options?: SemanticCacheOptions);
|
|
37
|
+
/**
|
|
38
|
+
* Get cached response for a semantically similar query.
|
|
39
|
+
* Returns the best match above the similarity threshold, or null.
|
|
40
|
+
*/
|
|
41
|
+
get(query: string): Promise<CachedResponse | null>;
|
|
42
|
+
/**
|
|
43
|
+
* Store a query->response pair in the cache.
|
|
44
|
+
*/
|
|
45
|
+
set(query: string, response: string, metadata?: any): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Clear all cache entries.
|
|
48
|
+
*/
|
|
49
|
+
clear(): void;
|
|
50
|
+
/**
|
|
51
|
+
* Get cache statistics.
|
|
52
|
+
*/
|
|
53
|
+
getStats(): SemanticCacheStats;
|
|
54
|
+
/**
|
|
55
|
+
* Purge expired entries.
|
|
56
|
+
*/
|
|
57
|
+
private evictExpired;
|
|
58
|
+
/**
|
|
59
|
+
* Evict the oldest (by cachedAt) entry.
|
|
60
|
+
*/
|
|
61
|
+
private evictOldest;
|
|
62
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semanticCache.d.ts","sourceRoot":"","sources":["../../src/cache/semanticCache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAOD,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AA+CD,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,MAAM,CAAK;gBAEP,OAAO,CAAC,EAAE,oBAAoB;IAM1C;;;OAGG;IACG,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAkCxD;;OAEG;IACG,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAoCzE;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,QAAQ,IAAI,kBAAkB;IAU9B;;OAEG;IACH,OAAO,CAAC,YAAY;IAKpB;;OAEG;IACH,OAAO,CAAC,WAAW;CAYpB"}
|