adaptive-memory-multi-model-router 2.15.0 → 2.15.2
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 +145 -262
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,160 +1,69 @@
|
|
|
1
1
|
# A3M Router
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Universal LLM routing gateway — routes requests to the cheapest capable provider across 47+ models.**
|
|
4
4
|
|
|
5
|
-
A3M Router is a stateless proxy
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Results
|
|
10
|
-
|
|
11
|
-
### RouterArena (ICLR 2025)
|
|
12
|
-
|
|
13
|
-
RouterArena evaluates LLM routers on query-level routing decisions against ground-truth model selections. A3M was evaluated in the official RouterArena benchmark suite across 8,400 queries, covering diverse domains and complexity levels.
|
|
14
|
-
|
|
15
|
-
| Metric | Value |
|
|
16
|
-
|--------|-------|
|
|
17
|
-
| Score | 0.9404 |
|
|
18
|
-
| Accuracy | 96.77% |
|
|
19
|
-
| Avg Cost / 1K tokens | $0.0768 |
|
|
20
|
-
| Robustness | 1.0000 |
|
|
21
|
-
| Abnormal entries | 0 |
|
|
22
|
-
| Total queries evaluated | 8,400 |
|
|
23
|
-
|
|
24
|
-
**Score** is RouterArena's composite metric combining routing accuracy, robustness, and cost efficiency. **Robustness = 1.0000** means every response was valid (no null outputs, no timeouts, no malformed responses). **Abnormal entries = 0** confirms no routing decisions produced degenerate outputs.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
**Reference:** RouteWorks/RouterArena#144 (merged, premium-tier evaluation)
|
|
28
|
-
|
|
29
|
-
#### RouterArena Leaderboard
|
|
30
|
-
|
|
31
|
-

|
|
32
|
-
|
|
33
|
-
### MMR-Bench (ArXiv 2026)
|
|
34
|
-
|
|
35
|
-
MMR-Bench evaluates multimodal routing performance across diverse LLM tasks. A3M was adopted as an official baseline.
|
|
36
|
-
|
|
37
|
-
| Metric | Value |
|
|
38
|
-
|--------|-------|
|
|
39
|
-
| Exact tier match | 67% |
|
|
40
|
-
| Cost savings vs all-premium | 63.5% |
|
|
41
|
-
| Robustness | 0.86 |
|
|
42
|
-
|
|
43
|
-
**Reference:** Hunter-Wrynn/MMR-Bench#4 (merged)
|
|
44
|
-
|
|
45
|
-
### Local Evaluation (n=200, no API key required)
|
|
46
|
-
|
|
47
|
-
The local benchmark uses a held-out set of 200 queries labeled by complexity tier (free / cheap / mid / premium). Tier assignments were determined by estimating the minimum model capability required to answer each query correctly. Routing decisions are compared against these ground-truth labels.
|
|
48
|
-
|
|
49
|
-
| Metric | Value |
|
|
50
|
-
|--------|-------|
|
|
51
|
-
| Exact tier match | 67% (134/200) |
|
|
52
|
-
| Within 1 tier | 96% (192/200) |
|
|
53
|
-
| Cost savings vs all-premium | 62.9% |
|
|
54
|
-
|
|
55
|
-
#### Tier Accuracy Breakdown
|
|
56
|
-
|
|
57
|
-
| Tier | Exact match | Errors | Primary error pattern |
|
|
58
|
-
|------|-------------|--------|---------------------|
|
|
59
|
-
| Free (n=50) | 96% (48/50) | 2 | Upward to cheap (2) |
|
|
60
|
-
| Cheap (n=60) | 75% (45/60) | 15 | Upward to free (13) |
|
|
61
|
-
| Mid (n=50) | 36% (18/50) | 32 | Downward to cheap (22) |
|
|
62
|
-
| Premium (n=40) | 57.5% (23/40) | 17 | Downward to mid (11) |
|
|
63
|
-
|
|
64
|
-
Mid-tier queries are the primary source of errors. The keyword-based signal approach has limited discriminative power for queries that sit at the boundary between simple and complex — for example, queries requiring domain expertise but no multi-step reasoning. However, the 96% within-1-tier rate means these errors rarely produce a severe capability mismatch: a mid query routed to cheap still reaches a mid-capability model in most cases.
|
|
65
|
-
|
|
66
|
-

|
|
67
|
-
|
|
68
|
-

|
|
69
|
-
|
|
70
|
-
#### Cost and Latency
|
|
71
|
-
|
|
72
|
-
| Metric | Value |
|
|
73
|
-
|--------|-------|
|
|
74
|
-
| Cost per 1K tokens (RouterArena) | $0.0768 |
|
|
75
|
-
| Cost savings vs all-premium (MMR-Bench) | 63.5% |
|
|
76
|
-
| A3M Auto routing overhead vs direct | +236ms |
|
|
77
|
-
| A3M Forced routing overhead vs direct | +96ms |
|
|
78
|
-
|
|
79
|
-
The +236ms overhead for auto routing is dominated by the routing decision itself (+140ms) and proxy forwarding (+96ms), not network latency to the target provider. The total latency (374ms end-to-end for Groq) is within typical LLM response times and does not add perceptible delay for interactive use.
|
|
80
|
-
|
|
81
|
-

|
|
82
|
-
|
|
83
|
-

|
|
5
|
+
A3M Router is a stateless proxy between your application and 47+ LLM providers. It inspects each request, estimates how complex it is, and routes it to the cheapest capable provider — without retraining a model or managing GPU infrastructure.
|
|
84
6
|
|
|
7
|
+
The API uses the OpenAI format (same endpoints, same request/response shapes), so existing SDKs and prompts work without changes. But it routes across any provider you configure, not just OpenAI.
|
|
85
8
|
|
|
86
9
|
---
|
|
87
10
|
|
|
88
|
-
|
|
11
|
+
## Quick Start
|
|
89
12
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
| RouterEval (EMNLP 2025) | Baseline merged | MilkThink-Lab/RouterEval#4 |
|
|
95
|
-
| RouterArena free tier (ICLR 2025) | Submitted | RouteWorks/RouterArena#152 |
|
|
96
|
-
| LLMRouterBench (ACL 2026) | Submitted | ynulihao/LLMRouterBench#3 |
|
|
13
|
+
```bash
|
|
14
|
+
npm install adaptive-memory-multi-model-router
|
|
15
|
+
npx a3m-router serve
|
|
16
|
+
```
|
|
97
17
|
|
|
18
|
+
```python
|
|
19
|
+
from openai import OpenAI
|
|
98
20
|
|
|
99
|
-
|
|
21
|
+
client = OpenAI(base_url="http://localhost:8787/v1", api_key="not-needed")
|
|
100
22
|
|
|
101
|
-
|
|
23
|
+
response = client.chat.completions.create(
|
|
24
|
+
model="auto", # "auto" = heuristic routing
|
|
25
|
+
messages=[{"role": "user", "content": "Explain quantum computing in 3 bullets"}]
|
|
26
|
+
)
|
|
27
|
+
```
|
|
102
28
|
|
|
103
|
-
|
|
29
|
+
That's it. `model="auto"` triggers routing. All other OpenAI SDK calls work unchanged.
|
|
104
30
|
|
|
105
|
-
|
|
31
|
+
---
|
|
106
32
|
|
|
107
|
-
|
|
108
|
-
2. **Cache lookup** — Semantic cache using embedding similarity. Hit rate is workload-dependent; 30%+ observed on repeated-query workloads.
|
|
109
|
-
3. **Routing decision** — Multi-signal heuristic scoring assigns a complexity score (0.0–1.0) to the query. The score maps to a provider tier. The router selects the cheapest available provider in that tier.
|
|
110
|
-
4. **Execution** — The LLM call is issued to the selected provider. Results are returned with routing metadata.
|
|
33
|
+
## How Routing Works
|
|
111
34
|
|
|
112
|
-
|
|
35
|
+
For every request, A3M Router scores complexity across five signals:
|
|
113
36
|
|
|
114
|
-
|
|
37
|
+
| Signal | What it detects |
|
|
38
|
+
|--------|----------------|
|
|
39
|
+
| **Domain** | Legal, medical, code, finance, ML keywords |
|
|
40
|
+
| **Task type** | Code generation, translation, analysis, creative |
|
|
41
|
+
| **Query structure** | Clause count, length, qualifier words |
|
|
42
|
+
| **Verb intensity** | "design/architect" → complex, "what/who" → simple |
|
|
43
|
+
| **Multi-step** | Explicit step markers (first...then, step 1/2/3) |
|
|
115
44
|
|
|
116
|
-
|
|
117
|
-
src/server/
|
|
118
|
-
├── proxyServer.ts # Entry point + route registration
|
|
119
|
-
├── router.ts # Route registry + request handler factory
|
|
120
|
-
├── state.ts # Shared request logs + cost tracking
|
|
121
|
-
├── metrics.ts # Prometheus-compatible metrics
|
|
122
|
-
├── modelMapper.ts # Model resolution + provider selection
|
|
123
|
-
└── handlers/
|
|
124
|
-
├── chatHandler.ts # POST /v1/chat/completions
|
|
125
|
-
├── completionsHandler.ts # POST /v1/completions
|
|
126
|
-
├── embeddingsHandler.ts # POST /v1/embeddings
|
|
127
|
-
├── modelsHandler.ts # GET /v1/models
|
|
128
|
-
├── healthHandler.ts # GET /health
|
|
129
|
-
└── metricsHandler.ts # GET /metrics
|
|
130
|
-
```
|
|
45
|
+
The combined score maps to a tier (free → cheap → mid → premium). Within that tier, A3M picks the cheapest available provider with a passing health score.
|
|
131
46
|
|
|
132
|
-
|
|
47
|
+
This is the same approach other routing systems use — the key differences between implementations are:
|
|
133
48
|
|
|
134
|
-
|
|
49
|
+
- **Signal weights** — how much each dimension contributes
|
|
50
|
+
- **Provider tiers** — which models live in which tier
|
|
51
|
+
- **Health scoring** — how failures and latency affect provider selection
|
|
52
|
+
- **Fallback behavior** — what happens when the preferred provider is down
|
|
135
53
|
|
|
136
|
-
|
|
54
|
+
A3M stores no training data, requires no GPU, and routes in ~140ms overhead.
|
|
137
55
|
|
|
138
|
-
|
|
139
|
-
|-----------|----------|--------|
|
|
140
|
-
| Domain detection | +0.35 | Keyword matching (legal, medical, security, finance, code, ML) |
|
|
141
|
-
| Task indicators | +0.25 | Keyword matching (code, math, translate, creative) |
|
|
142
|
-
| Query structure | +0.20 | Clause count, length, qualifier presence |
|
|
143
|
-
| Action verb intensity | +0.20 | Expert (design/architect) +0.20, mid (analyze/review) +0.10, simple (what/who) −0.10 |
|
|
144
|
-
| Multi-step detection | +0.15 | Explicit step markers (first...then, step 1/2/3) |
|
|
56
|
+
---
|
|
145
57
|
|
|
146
|
-
|
|
58
|
+
## Why Not Just Use LiteLLM?
|
|
147
59
|
|
|
148
|
-
|
|
149
|
-
|-----------|------|------------------|
|
|
150
|
-
| 0.00–0.19 | free | taste-1 ($0) |
|
|
151
|
-
| 0.20–0.44 | cheap | llama-3.3-70b ($0.20/M) |
|
|
152
|
-
| 0.45–0.69 | mid | gpt-4o-mini ($0.60/M) |
|
|
153
|
-
| 0.70–1.00 | premium | gpt-4o, claude-3.5-sonnet ($2.50/M) |
|
|
60
|
+
LiteLLM is the dominant open-source AI gateway (54K stars). It handles unified API access well. A3M Router adds two capabilities LiteLLM doesn't have built-in:
|
|
154
61
|
|
|
155
|
-
###
|
|
62
|
+
### 1. Heuristic Routing
|
|
63
|
+
LiteLLM routes by model name or requires you to specify which model to call. A3M's `model="auto"` mode analyzes the query content and picks the cheapest capable provider automatically. This is useful when you want cost efficiency without writing routing logic.
|
|
156
64
|
|
|
157
|
-
|
|
65
|
+
### 2. Parallel Ensemble Execution
|
|
66
|
+
Sometimes you want the best answer regardless of cost. A3M can call multiple providers in parallel, score each response, and return the best one — with full provenance of which provider won and why.
|
|
158
67
|
|
|
159
68
|
```typescript
|
|
160
69
|
import { executeEnsemble } from 'adaptive-memory-multi-model-router/ensemble';
|
|
@@ -163,114 +72,44 @@ const result = await executeEnsemble(
|
|
|
163
72
|
"Explain how vector databases work",
|
|
164
73
|
systemPrompt,
|
|
165
74
|
context,
|
|
166
|
-
{
|
|
167
|
-
{ providers: ['
|
|
75
|
+
{ groq: callGroq, openai: callOpenAI, nvidia: callNvidia },
|
|
76
|
+
{ providers: ['groq', 'openai', 'nvidia'], timeoutMs: 30000 }
|
|
168
77
|
);
|
|
169
|
-
// result.winner
|
|
170
|
-
// result.scores
|
|
171
|
-
// result.
|
|
172
|
-
// result.allResults — map of all provider responses (preserved)
|
|
78
|
+
// result.winner — which provider gave the best response
|
|
79
|
+
// result.scores — per-provider quality scores
|
|
80
|
+
// result.allResults — all responses preserved
|
|
173
81
|
```
|
|
174
82
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
### Guardrails
|
|
83
|
+
### What A3M doesn't do (LiteLLM does)
|
|
84
|
+
- Virtual keys, spend limits per team/user
|
|
85
|
+
- Admin dashboard, UI
|
|
86
|
+
- OAuth/SSO integration
|
|
87
|
+
- LangChain/LlamaIndex first-class integrations
|
|
88
|
+
- Enterprise SLA and support contracts
|
|
182
89
|
|
|
183
|
-
|
|
90
|
+
A3M is a routing engine. LiteLLM is an enterprise platform. Use the right tool for your stage.
|
|
184
91
|
|
|
185
|
-
###
|
|
186
|
-
|
|
187
|
-
Model quality scores update online via exponential moving average (alpha=0.2) after each real LLM call. Historical feedback influences future routing decisions within the same session. No retraining is required. Memory state is not persisted across sessions in the base configuration.
|
|
188
|
-
|
|
189
|
-
---
|
|
190
|
-
|
|
191
|
-
## Provider Coverage
|
|
192
|
-
|
|
193
|
-
| Provider | Tier Support | Notes |
|
|
194
|
-
|----------|-------------|-------|
|
|
195
|
-
| OpenAI | premium, mid | gpt-4o, gpt-4o-mini, gpt-4o-2024-08-06 |
|
|
196
|
-
| Anthropic | premium, mid | claude-3.5-sonnet, claude-3-haiku |
|
|
197
|
-
| Google | premium, mid | gemini-1.5-pro, gemini-1.5-flash |
|
|
198
|
-
| Groq | cheap | llama-3.3-70b, llama-3.1-8b |
|
|
199
|
-
| DeepSeek | cheap, mid | deepseek-chat, deepseek-coder |
|
|
200
|
-
| Mistral | cheap, mid | mistral-large, mistral-small |
|
|
201
|
-
| NVIDIA | premium | nvidia/llama-3.1-nemotron |
|
|
202
|
-
| OpenRouter | all tiers | aggregated provider access |
|
|
203
|
-
| Kimi | cheap | moonshot-v1 |
|
|
204
|
-
| Qwen | cheap, mid | qwen-turbo, qwen-plus |
|
|
205
|
-
| Zhipu | cheap | glm-4 |
|
|
206
|
-
| Yi | cheap | yi-large |
|
|
207
|
-
| Azure OpenAI | premium, mid | via OpenAI-compatible endpoint |
|
|
208
|
-
| AWS Bedrock | premium, mid | via OpenAI-compatible endpoint |
|
|
209
|
-
| Local Ollama | all tiers | configurable model discovery |
|
|
210
|
-
| Local vLLM | all tiers | OpenAI-compatible server |
|
|
211
|
-
|
|
212
|
-
Total: 47+ providers. Provider availability is dynamic and checked at runtime via health scoring.
|
|
92
|
+
### OpenAI-Compatible API
|
|
93
|
+
The API format is OpenAI-compatible — same `/v1/chat/completions` endpoints, same request/response shapes — so any OpenAI-compatible SDK or proxy tool works with A3M without code changes. This is useful for switching providers behind an existing integration or for tooling that only supports the OpenAI format.
|
|
213
94
|
|
|
214
95
|
---
|
|
215
96
|
|
|
216
|
-
##
|
|
217
|
-
|
|
218
|
-
### Installation
|
|
219
|
-
|
|
220
|
-
```bash
|
|
221
|
-
npm install adaptive-memory-multi-model-router
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
Python bindings:
|
|
225
|
-
|
|
226
|
-
```bash
|
|
227
|
-
pip install a3m-router
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
### Start Proxy
|
|
97
|
+
## Architecture
|
|
231
98
|
|
|
232
|
-
```bash
|
|
233
|
-
npx a3m-router serve
|
|
234
|
-
# Proxy available at http://localhost:8787
|
|
235
99
|
```
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
from openai import OpenAI
|
|
241
|
-
|
|
242
|
-
client = OpenAI(base_url="http://localhost:8787/v1", api_key="not-needed")
|
|
243
|
-
|
|
244
|
-
response = client.chat.completions.create(
|
|
245
|
-
model="auto",
|
|
246
|
-
messages=[{"role": "user", "content": "Explain quantum computing in 3 bullets"}]
|
|
247
|
-
)
|
|
248
|
-
print(response.choices[0].message.content)
|
|
100
|
+
Request → Guardrails → Cache → Router → Provider → Response
|
|
101
|
+
↓
|
|
102
|
+
Cost tracking
|
|
103
|
+
Metrics
|
|
249
104
|
```
|
|
250
105
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
### TypeScript SDK
|
|
254
|
-
|
|
255
|
-
```typescript
|
|
256
|
-
import { A3MRouter } from 'adaptive-memory-multi-model-router/sdk';
|
|
257
|
-
|
|
258
|
-
const router = new A3MRouter();
|
|
259
|
-
|
|
260
|
-
const decision = router.route("Write a Python function to sort an array");
|
|
261
|
-
// → { model: 'groq/llama-3.3-70b', tier: 'cheap', cost: 0.0004, complexity: 0.33 }
|
|
106
|
+
**Guardrails** — Runs before any provider call: prompt injection detection, PII detection, content filtering. Rejects or sanitizes dangerous input.
|
|
262
107
|
|
|
263
|
-
|
|
264
|
-
// → { detectedDomain: 'legal', domainScore: 0.35, complexity: 0.87 }
|
|
265
|
-
```
|
|
108
|
+
**Semantic Cache** — Optional. Uses embedding similarity to return cached responses for repeated queries. Cache hit = instant response, zero provider cost.
|
|
266
109
|
|
|
267
|
-
|
|
110
|
+
**Router** — Scores the query, selects tier, picks the cheapest healthy provider in that tier. Model quality scores update online via exponential moving average after each real call — no retraining.
|
|
268
111
|
|
|
269
|
-
|
|
270
|
-
npx a3m-router route "Explain quantum computing" # returns routing decision and tier
|
|
271
|
-
npx a3m-router benchmark # run local accuracy test (n=200)
|
|
272
|
-
npx a3m-router health # provider health status and latency
|
|
273
|
-
```
|
|
112
|
+
**Ensemble** — Optional. Calls multiple providers in parallel, scores responses on specificity and structure, returns the winner.
|
|
274
113
|
|
|
275
114
|
---
|
|
276
115
|
|
|
@@ -279,35 +118,45 @@ npx a3m-router health # provider health status and lat
|
|
|
279
118
|
| Method | Endpoint | Description |
|
|
280
119
|
|--------|----------|-------------|
|
|
281
120
|
| POST | `/v1/chat/completions` | OpenAI-compatible chat (streaming + non-streaming) |
|
|
282
|
-
| POST | `/v1/completions` | OpenAI
|
|
283
|
-
| POST | `/v1/embeddings` |
|
|
284
|
-
| POST | `/v1/route` |
|
|
285
|
-
| GET | `/v1/models` | Available models
|
|
286
|
-
| GET | `/health` |
|
|
121
|
+
| POST | `/v1/completions` | OpenAI completions |
|
|
122
|
+
| POST | `/v1/embeddings` | Text embeddings |
|
|
123
|
+
| POST | `/v1/route` | Get routing decision without calling an LLM |
|
|
124
|
+
| GET | `/v1/models` | Available models and pricing |
|
|
125
|
+
| GET | `/health` | Provider health, recent requests, cost totals |
|
|
287
126
|
| GET | `/metrics` | Prometheus-compatible metrics |
|
|
288
127
|
|
|
289
|
-
|
|
128
|
+
### CLI
|
|
290
129
|
|
|
291
|
-
|
|
130
|
+
```bash
|
|
131
|
+
npx a3m-router serve # start proxy on port 8787
|
|
132
|
+
npx a3m-router route "query" # see routing decision for a query
|
|
133
|
+
npx a3m-router health # provider latency and availability
|
|
134
|
+
npx a3m-router benchmark # run local accuracy test (n=200)
|
|
135
|
+
```
|
|
292
136
|
|
|
293
|
-
|
|
137
|
+
### Configuration
|
|
294
138
|
|
|
295
|
-
|
|
139
|
+
**Environment variables** — API keys for each provider:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
export OPENAI_API_KEY=sk-...
|
|
143
|
+
export ANTHROPIC_API_KEY=sk-ant-...
|
|
144
|
+
export GROQ_API_KEY=gsk_...
|
|
145
|
+
# No key needed for free tier providers
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**Budget enforcement:**
|
|
296
149
|
|
|
297
150
|
```typescript
|
|
298
151
|
import { BudgetManager } from 'adaptive-memory-multi-model-router/billing';
|
|
299
152
|
|
|
300
153
|
const budgets = new BudgetManager({
|
|
301
154
|
monthlyLimit: 500,
|
|
302
|
-
alerts: [0.5, 0.8, 1.0],
|
|
303
|
-
perTeamLimits: {
|
|
304
|
-
'engineering': 200,
|
|
305
|
-
'product': 150,
|
|
306
|
-
},
|
|
155
|
+
alerts: [0.5, 0.8, 1.0],
|
|
307
156
|
});
|
|
308
157
|
```
|
|
309
158
|
|
|
310
|
-
|
|
159
|
+
**Provider retry with backoff:**
|
|
311
160
|
|
|
312
161
|
```typescript
|
|
313
162
|
import { RetryManager } from 'adaptive-memory-multi-model-router/retry';
|
|
@@ -316,47 +165,81 @@ const retry = new RetryManager({
|
|
|
316
165
|
providers: {
|
|
317
166
|
'openai': { timeout: 30000, maxRetries: 3, baseDelay: 1000 },
|
|
318
167
|
'groq': { timeout: 15000, maxRetries: 2, baseDelay: 500 },
|
|
319
|
-
'kimi': { timeout: 20000, maxRetries: 3, baseDelay: 2000 },
|
|
320
168
|
},
|
|
321
|
-
backoffMultiplier: 2,
|
|
322
|
-
jitter: 0.3,
|
|
323
|
-
rateLimitHandling: 'retry-after',
|
|
324
169
|
});
|
|
325
170
|
```
|
|
326
171
|
|
|
327
|
-
|
|
172
|
+
**Circuit breaker:**
|
|
328
173
|
|
|
329
174
|
```typescript
|
|
330
175
|
import { CircuitBreaker } from 'adaptive-memory-multi-model-router/failover';
|
|
331
176
|
|
|
332
177
|
const cb = new CircuitBreaker({
|
|
333
|
-
failureThreshold: 3,
|
|
334
|
-
cooldownMs: 60000,
|
|
178
|
+
failureThreshold: 3,
|
|
179
|
+
cooldownMs: 60000,
|
|
335
180
|
fallbackChain: ['groq', 'deepseek', 'openai'],
|
|
336
181
|
});
|
|
337
182
|
```
|
|
338
183
|
|
|
339
184
|
---
|
|
340
185
|
|
|
341
|
-
##
|
|
186
|
+
## Provider Coverage
|
|
187
|
+
|
|
188
|
+
| Provider | Tiers | Notes |
|
|
189
|
+
|----------|-------|-------|
|
|
190
|
+
| OpenAI | premium, mid | gpt-4o, gpt-4o-mini |
|
|
191
|
+
| Anthropic | premium, mid | claude-3.5-sonnet, claude-3-haiku |
|
|
192
|
+
| Google | premium, mid | gemini-1.5-pro, gemini-1.5-flash |
|
|
193
|
+
| Groq | cheap | llama-3.3-70b, llama-3.1-8b |
|
|
194
|
+
| DeepSeek | cheap, mid | deepseek-chat, deepseek-coder |
|
|
195
|
+
| Mistral | cheap, mid | mistral-large, mistral-small |
|
|
196
|
+
| NVIDIA | premium | nvidia/llama-3.1-nemotron |
|
|
197
|
+
| OpenRouter | all | aggregated access |
|
|
198
|
+
| Ollama | all | self-hosted models |
|
|
199
|
+
| vLLM | all | self-hosted OpenAI-compatible servers |
|
|
200
|
+
| Azure OpenAI | premium, mid | enterprise |
|
|
201
|
+
| AWS Bedrock | premium, mid | enterprise |
|
|
202
|
+
|
|
203
|
+
47+ providers total. Availability is checked at runtime.
|
|
204
|
+
|
|
205
|
+
---
|
|
342
206
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
207
|
+
## Adding a New Endpoint
|
|
208
|
+
|
|
209
|
+
The server uses a route-based architecture. To add a new endpoint:
|
|
210
|
+
|
|
211
|
+
**1. Create the handler** `src/server/handlers/myHandler.ts`:
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
import { RouteContext } from '../router';
|
|
215
|
+
|
|
216
|
+
export async function handleMyEndpoint(ctx: RouteContext): Promise<void> {
|
|
217
|
+
ctx.json(200, { hello: 'world' });
|
|
350
218
|
}
|
|
351
219
|
```
|
|
352
220
|
|
|
221
|
+
**2. Register the route** in `proxyServer.ts`:
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
import { handleMyEndpoint } from './handlers/myHandler';
|
|
225
|
+
|
|
226
|
+
// In createProxyServer():
|
|
227
|
+
registerRoute('GET', /^\/v1\/my-endpoint$/, handleMyEndpoint, 'GET /v1/my-endpoint');
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Two lines total.
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Project Stats
|
|
235
|
+
|
|
236
|
+
- **Stars**: 10
|
|
237
|
+
- **npm downloads/month**: ~5,000
|
|
238
|
+
- **Providers**: 47+
|
|
239
|
+
- **License**: MIT
|
|
240
|
+
|
|
353
241
|
---
|
|
354
242
|
|
|
355
|
-
##
|
|
243
|
+
## License
|
|
356
244
|
|
|
357
|
-
|
|
358
|
-
- MilkThink-Lab/RouterEval. EMNLP 2025 benchmark. https://github.com/MilkThink-Lab/RouterEval
|
|
359
|
-
- Hunter-Wrynn/MMR-Bench. ArXiv 2026 multimodal routing benchmark. https://github.com/Hunter-Wrynn/MMR-Bench
|
|
360
|
-
- ynulihao/LLMRouterBench. ACL 2026 benchmark. https://github.com/ynulihao/LLMRouterBench
|
|
361
|
-
- Lin et al. "RouteLLM: Efficiently Routing Across Language Models." arXiv:2404.06035, 2024.
|
|
362
|
-
- Zhong et al. "RadixAttention: Prefix Caching for Interleaved Medium-Length Contexts." arXiv:2412.15115, 2024.
|
|
245
|
+
MIT. See [LICENSE](LICENSE).
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adaptive-memory-multi-model-router",
|
|
3
|
-
"version": "2.15.
|
|
3
|
+
"version": "2.15.2",
|
|
4
4
|
"shortName": "A3M Router",
|
|
5
5
|
"displayName": "A3M Router - Adaptive Memory Multi-Model Router",
|
|
6
|
-
"description": "
|
|
6
|
+
"description": "Universal LLM routing gateway. Routes requests to cheapest capable provider across 47+ models. Heuristic routing, parallel ensemble, semantic cache.",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"bin": {
|
|
9
9
|
"a3m-router": "dist/cli.js",
|
|
@@ -195,13 +195,13 @@
|
|
|
195
195
|
},
|
|
196
196
|
"dependencies": {
|
|
197
197
|
"blessed": "^0.1.81",
|
|
198
|
-
"nanoid": "^
|
|
198
|
+
"nanoid": "^6.0.0"
|
|
199
199
|
},
|
|
200
200
|
"devDependencies": {
|
|
201
201
|
"@types/express": "^5.0.6",
|
|
202
|
-
"@types/node": "^
|
|
202
|
+
"@types/node": "^26.1.1",
|
|
203
203
|
"esbuild": "^0.28.1",
|
|
204
|
-
"typescript": "^
|
|
204
|
+
"typescript": "^7.0.2",
|
|
205
205
|
"vitest": "^4.1.9"
|
|
206
206
|
},
|
|
207
207
|
"types": "dist/index.d.ts"
|