adaptive-memory-multi-model-router 2.15.0 → 2.15.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/README.md +143 -263
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,160 +1,69 @@
|
|
|
1
1
|
# A3M Router
|
|
2
2
|
|
|
3
|
-
**OpenAI-compatible LLM routing gateway
|
|
3
|
+
**OpenAI-compatible LLM routing gateway — routes requests to the cheapest capable provider per query.**
|
|
4
4
|
|
|
5
|
-
A3M Router is a stateless proxy that
|
|
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 that sits between your application and 47+ LLM providers. It inspects each request, estimates how complex it is, and routes it to the cheapest provider that can handle it — without retraining a model or managing GPU infrastructure.
|
|
84
6
|
|
|
7
|
+
Drop-in replacement for OpenAI API calls. Switch providers or add new ones without changing application code.
|
|
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,41 @@ 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
|
-
|
|
184
|
-
|
|
185
|
-
### Adaptive Memory
|
|
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.
|
|
90
|
+
A3M is a routing engine. LiteLLM is an enterprise platform. Use the right tool for your stage.
|
|
213
91
|
|
|
214
92
|
---
|
|
215
93
|
|
|
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
|
|
94
|
+
## Architecture
|
|
231
95
|
|
|
232
|
-
```bash
|
|
233
|
-
npx a3m-router serve
|
|
234
|
-
# Proxy available at http://localhost:8787
|
|
235
96
|
```
|
|
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)
|
|
97
|
+
Request → Guardrails → Cache → Router → Provider → Response
|
|
98
|
+
↓
|
|
99
|
+
Cost tracking
|
|
100
|
+
Metrics
|
|
249
101
|
```
|
|
250
102
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
### TypeScript SDK
|
|
254
|
-
|
|
255
|
-
```typescript
|
|
256
|
-
import { A3MRouter } from 'adaptive-memory-multi-model-router/sdk';
|
|
257
|
-
|
|
258
|
-
const router = new A3MRouter();
|
|
103
|
+
**Guardrails** — Runs before any provider call: prompt injection detection, PII detection, content filtering. Rejects or sanitizes dangerous input.
|
|
259
104
|
|
|
260
|
-
|
|
261
|
-
// → { model: 'groq/llama-3.3-70b', tier: 'cheap', cost: 0.0004, complexity: 0.33 }
|
|
105
|
+
**Semantic Cache** — Optional. Uses embedding similarity to return cached responses for repeated queries. Cache hit = instant response, zero provider cost.
|
|
262
106
|
|
|
263
|
-
|
|
264
|
-
// → { detectedDomain: 'legal', domainScore: 0.35, complexity: 0.87 }
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
### CLI
|
|
107
|
+
**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
108
|
|
|
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
|
-
```
|
|
109
|
+
**Ensemble** — Optional. Calls multiple providers in parallel, scores responses on specificity and structure, returns the winner.
|
|
274
110
|
|
|
275
111
|
---
|
|
276
112
|
|
|
@@ -279,35 +115,45 @@ npx a3m-router health # provider health status and lat
|
|
|
279
115
|
| Method | Endpoint | Description |
|
|
280
116
|
|--------|----------|-------------|
|
|
281
117
|
| 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` |
|
|
118
|
+
| POST | `/v1/completions` | OpenAI completions |
|
|
119
|
+
| POST | `/v1/embeddings` | Text embeddings |
|
|
120
|
+
| POST | `/v1/route` | Get routing decision without calling an LLM |
|
|
121
|
+
| GET | `/v1/models` | Available models and pricing |
|
|
122
|
+
| GET | `/health` | Provider health, recent requests, cost totals |
|
|
287
123
|
| GET | `/metrics` | Prometheus-compatible metrics |
|
|
288
124
|
|
|
289
|
-
|
|
125
|
+
### CLI
|
|
290
126
|
|
|
291
|
-
|
|
127
|
+
```bash
|
|
128
|
+
npx a3m-router serve # start proxy on port 8787
|
|
129
|
+
npx a3m-router route "query" # see routing decision for a query
|
|
130
|
+
npx a3m-router health # provider latency and availability
|
|
131
|
+
npx a3m-router benchmark # run local accuracy test (n=200)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Configuration
|
|
292
135
|
|
|
293
|
-
|
|
136
|
+
**Environment variables** — API keys for each provider:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
export OPENAI_API_KEY=sk-...
|
|
140
|
+
export ANTHROPIC_API_KEY=sk-ant-...
|
|
141
|
+
export GROQ_API_KEY=gsk_...
|
|
142
|
+
# No key needed for free tier providers
|
|
143
|
+
```
|
|
294
144
|
|
|
295
|
-
|
|
145
|
+
**Budget enforcement:**
|
|
296
146
|
|
|
297
147
|
```typescript
|
|
298
148
|
import { BudgetManager } from 'adaptive-memory-multi-model-router/billing';
|
|
299
149
|
|
|
300
150
|
const budgets = new BudgetManager({
|
|
301
151
|
monthlyLimit: 500,
|
|
302
|
-
alerts: [0.5, 0.8, 1.0],
|
|
303
|
-
perTeamLimits: {
|
|
304
|
-
'engineering': 200,
|
|
305
|
-
'product': 150,
|
|
306
|
-
},
|
|
152
|
+
alerts: [0.5, 0.8, 1.0],
|
|
307
153
|
});
|
|
308
154
|
```
|
|
309
155
|
|
|
310
|
-
|
|
156
|
+
**Provider retry with backoff:**
|
|
311
157
|
|
|
312
158
|
```typescript
|
|
313
159
|
import { RetryManager } from 'adaptive-memory-multi-model-router/retry';
|
|
@@ -316,47 +162,81 @@ const retry = new RetryManager({
|
|
|
316
162
|
providers: {
|
|
317
163
|
'openai': { timeout: 30000, maxRetries: 3, baseDelay: 1000 },
|
|
318
164
|
'groq': { timeout: 15000, maxRetries: 2, baseDelay: 500 },
|
|
319
|
-
'kimi': { timeout: 20000, maxRetries: 3, baseDelay: 2000 },
|
|
320
165
|
},
|
|
321
|
-
backoffMultiplier: 2,
|
|
322
|
-
jitter: 0.3,
|
|
323
|
-
rateLimitHandling: 'retry-after',
|
|
324
166
|
});
|
|
325
167
|
```
|
|
326
168
|
|
|
327
|
-
|
|
169
|
+
**Circuit breaker:**
|
|
328
170
|
|
|
329
171
|
```typescript
|
|
330
172
|
import { CircuitBreaker } from 'adaptive-memory-multi-model-router/failover';
|
|
331
173
|
|
|
332
174
|
const cb = new CircuitBreaker({
|
|
333
|
-
failureThreshold: 3,
|
|
334
|
-
cooldownMs: 60000,
|
|
175
|
+
failureThreshold: 3,
|
|
176
|
+
cooldownMs: 60000,
|
|
335
177
|
fallbackChain: ['groq', 'deepseek', 'openai'],
|
|
336
178
|
});
|
|
337
179
|
```
|
|
338
180
|
|
|
339
181
|
---
|
|
340
182
|
|
|
341
|
-
##
|
|
183
|
+
## Provider Coverage
|
|
184
|
+
|
|
185
|
+
| Provider | Tiers | Notes |
|
|
186
|
+
|----------|-------|-------|
|
|
187
|
+
| OpenAI | premium, mid | gpt-4o, gpt-4o-mini |
|
|
188
|
+
| Anthropic | premium, mid | claude-3.5-sonnet, claude-3-haiku |
|
|
189
|
+
| Google | premium, mid | gemini-1.5-pro, gemini-1.5-flash |
|
|
190
|
+
| Groq | cheap | llama-3.3-70b, llama-3.1-8b |
|
|
191
|
+
| DeepSeek | cheap, mid | deepseek-chat, deepseek-coder |
|
|
192
|
+
| Mistral | cheap, mid | mistral-large, mistral-small |
|
|
193
|
+
| NVIDIA | premium | nvidia/llama-3.1-nemotron |
|
|
194
|
+
| OpenRouter | all | aggregated access |
|
|
195
|
+
| Ollama | all | self-hosted models |
|
|
196
|
+
| vLLM | all | self-hosted OpenAI-compatible servers |
|
|
197
|
+
| Azure OpenAI | premium, mid | enterprise |
|
|
198
|
+
| AWS Bedrock | premium, mid | enterprise |
|
|
199
|
+
|
|
200
|
+
47+ providers total. Availability is checked at runtime.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Adding a New Endpoint
|
|
205
|
+
|
|
206
|
+
The server uses a route-based architecture. To add a new endpoint:
|
|
207
|
+
|
|
208
|
+
**1. Create the handler** `src/server/handlers/myHandler.ts`:
|
|
342
209
|
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
url = {https://github.com/Das-rebel/a3m-router},
|
|
349
|
-
note = {RouterArena evaluated: 96.77% accuracy, \$0.0768/1K, 1.0000 robustness}
|
|
210
|
+
```typescript
|
|
211
|
+
import { RouteContext } from '../router';
|
|
212
|
+
|
|
213
|
+
export async function handleMyEndpoint(ctx: RouteContext): Promise<void> {
|
|
214
|
+
ctx.json(200, { hello: 'world' });
|
|
350
215
|
}
|
|
351
216
|
```
|
|
352
217
|
|
|
218
|
+
**2. Register the route** in `proxyServer.ts`:
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
import { handleMyEndpoint } from './handlers/myHandler';
|
|
222
|
+
|
|
223
|
+
// In createProxyServer():
|
|
224
|
+
registerRoute('GET', /^\/v1\/my-endpoint$/, handleMyEndpoint, 'GET /v1/my-endpoint');
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Two lines total.
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## Project Stats
|
|
232
|
+
|
|
233
|
+
- **Stars**: 10
|
|
234
|
+
- **npm downloads/month**: ~5,000
|
|
235
|
+
- **Providers**: 47+
|
|
236
|
+
- **License**: MIT
|
|
237
|
+
|
|
353
238
|
---
|
|
354
239
|
|
|
355
|
-
##
|
|
240
|
+
## License
|
|
356
241
|
|
|
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.
|
|
242
|
+
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.1",
|
|
4
4
|
"shortName": "A3M Router",
|
|
5
5
|
"displayName": "A3M Router - Adaptive Memory Multi-Model Router",
|
|
6
|
-
"description": "
|
|
6
|
+
"description": "OpenAI-compatible LLM routing gateway. Routes requests to cheapest capable provider across 47+ providers. Heuristic routing, parallel ensemble, semantic cache. Drop-in for OpenAI SDK.",
|
|
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"
|