adaptive-memory-multi-model-router 2.0.9 → 2.1.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 +51 -40
- package/articles/DEVTO_VIRAL_GROWTH.md +4 -4
- package/dist/sdk.js +122 -0
- package/docs/API.md +637 -344
- package/docs/HN_SUBMISSION_FINAL.md +1 -1
- package/package.json +5 -1
- package/python/README.md +102 -0
- package/python/a3m/__init__.py +6 -0
- package/python/a3m/__pycache__/__init__.cpython-312.pyc +0 -0
- package/python/a3m/__pycache__/client.cpython-312.pyc +0 -0
- package/python/a3m/__pycache__/models.cpython-312.pyc +0 -0
- package/python/a3m/__pycache__/sync_client.cpython-312.pyc +0 -0
- package/python/a3m/client.py +190 -0
- package/python/a3m/models.py +40 -0
- package/python/a3m/sync_client.py +61 -0
- package/python/pyproject.toml +23 -0
- package/src/sdk.ts +192 -0
package/docs/API.md
CHANGED
|
@@ -1,562 +1,855 @@
|
|
|
1
|
-
# A3M Router API
|
|
1
|
+
# A3M Router API Reference
|
|
2
|
+
|
|
3
|
+
Complete reference for the A3M Router — TypeScript SDK, Python SDK, CLI, REST API, and integrations.
|
|
4
|
+
|
|
5
|
+
---
|
|
2
6
|
|
|
3
7
|
## Table of Contents
|
|
4
8
|
|
|
5
|
-
- [
|
|
6
|
-
- [
|
|
7
|
-
- [
|
|
8
|
-
- [
|
|
9
|
-
- [
|
|
10
|
-
- [
|
|
11
|
-
- [
|
|
12
|
-
- [
|
|
9
|
+
- [TypeScript SDK](#typescript-sdk)
|
|
10
|
+
- [Python SDK](#python-sdk)
|
|
11
|
+
- [CLI](#cli)
|
|
12
|
+
- [REST API](#rest-api)
|
|
13
|
+
- [OpenAI SDK Compatibility](#openai-sdk-compatibility)
|
|
14
|
+
- [LangChain Integration](#langchain-integration)
|
|
15
|
+
- [Configuration](#configuration)
|
|
16
|
+
- [Error Handling](#error-handling)
|
|
13
17
|
|
|
14
18
|
---
|
|
15
19
|
|
|
16
|
-
##
|
|
20
|
+
## TypeScript SDK
|
|
17
21
|
|
|
18
|
-
###
|
|
22
|
+
### Installation
|
|
19
23
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
```javascript
|
|
23
|
-
import { createA3MRouter } from 'adaptive-memory-multi-model-router';
|
|
24
|
-
|
|
25
|
-
const router = createA3MRouter({
|
|
26
|
-
memory: true, // Enable memory tree
|
|
27
|
-
costBudget: 0.05, // Max cost per request in USD
|
|
28
|
-
providers: ['openai', 'groq', 'anthropic'], // Enabled providers
|
|
29
|
-
maxLatency: 2000, // Max latency in ms
|
|
30
|
-
cacheEnabled: true // Enable caching
|
|
31
|
-
});
|
|
24
|
+
```bash
|
|
25
|
+
npm install adaptive-memory-multi-model-router
|
|
32
26
|
```
|
|
33
27
|
|
|
34
|
-
|
|
28
|
+
### Import
|
|
35
29
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
| `costBudget` | number | `0.10` | Max cost per request |
|
|
40
|
-
| `providers` | string[] | `['openai']` | Enabled providers |
|
|
41
|
-
| `maxLatency` | number | `5000` | Max latency in ms |
|
|
42
|
-
| `cacheEnabled` | boolean | `true` | Enable response cache |
|
|
30
|
+
```typescript
|
|
31
|
+
import { A3MRouter } from 'adaptive-memory-multi-model-router/sdk';
|
|
32
|
+
```
|
|
43
33
|
|
|
44
|
-
|
|
34
|
+
### Constructor
|
|
45
35
|
|
|
46
|
-
|
|
36
|
+
```typescript
|
|
37
|
+
const router = new A3MRouter(config?: A3MRouterConfig);
|
|
38
|
+
```
|
|
47
39
|
|
|
48
|
-
|
|
40
|
+
**A3MRouterConfig:**
|
|
49
41
|
|
|
50
|
-
|
|
42
|
+
| Option | Type | Default | Description |
|
|
43
|
+
|--------|------|---------|-------------|
|
|
44
|
+
| `defaultModel` | `string` | — | Fallback model when routing is ambiguous |
|
|
45
|
+
| `maxCostPerQuery` | `number` | — | Max cost per query in USD |
|
|
46
|
+
| `preferSpeedOverQuality` | `boolean` | `false` | Prefer fast models over higher quality |
|
|
47
|
+
| `providers` | `string[]` | all | Restrict routing to these provider IDs |
|
|
51
48
|
|
|
52
|
-
|
|
53
|
-
const result = await router.route({
|
|
54
|
-
prompt: 'Your prompt here',
|
|
55
|
-
context: {
|
|
56
|
-
type: 'coding', // 'coding', 'analysis', 'creative'
|
|
57
|
-
language: 'python', // Optional language hint
|
|
58
|
-
domain: 'tech' // Optional domain hint
|
|
59
|
-
},
|
|
60
|
-
options: {
|
|
61
|
-
maxCost: 0.02,
|
|
62
|
-
maxLatency: 2000
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
```
|
|
49
|
+
### Methods
|
|
66
50
|
|
|
67
|
-
|
|
51
|
+
#### `route(query: string): RoutingResult`
|
|
68
52
|
|
|
69
|
-
|
|
70
|
-
|------|------|-------------|
|
|
71
|
-
| `prompt` | string | The input prompt |
|
|
72
|
-
| `context` | object | Routing context |
|
|
73
|
-
| `options.maxCost` | number | Max cost for this request |
|
|
74
|
-
| `options.maxLatency` | number | Max latency in ms |
|
|
53
|
+
Route a query to the best available model. Returns the decision without executing the query.
|
|
75
54
|
|
|
76
|
-
|
|
55
|
+
```typescript
|
|
56
|
+
const decision = router.route("Write a Python function to sort a list");
|
|
77
57
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
58
|
+
console.log(decision.model); // "groq/llama-3.3-70b-versatile"
|
|
59
|
+
console.log(decision.tier); // "cheap"
|
|
60
|
+
console.log(decision.cost); // 0.00035
|
|
61
|
+
console.log(decision.complexity); // 0.35
|
|
62
|
+
console.log(decision.reasoning); // "Selected Groq/llama-3.3-70b for code detected"
|
|
63
|
+
console.log(decision.fallbackModels); // ["cerebras/llama-3.3-70b", "mistral/mistral-small"]
|
|
64
|
+
console.log(decision.isFree); // false
|
|
65
|
+
console.log(decision.isExpert); // false
|
|
87
66
|
```
|
|
88
67
|
|
|
89
|
-
|
|
68
|
+
**RoutingResult:**
|
|
90
69
|
|
|
91
|
-
|
|
70
|
+
| Field | Type | Description |
|
|
71
|
+
|-------|------|-------------|
|
|
72
|
+
| `model` | `string` | Selected model identifier |
|
|
73
|
+
| `tier` | `'free' \| 'cheap' \| 'mid' \| 'premium'` | Cost tier |
|
|
74
|
+
| `cost` | `number` | Estimated cost in USD |
|
|
75
|
+
| `complexity` | `number` | Query complexity score (0.0–1.0) |
|
|
76
|
+
| `reasoning` | `string` | Human-readable routing reason |
|
|
77
|
+
| `fallbackModels` | `string[]` | Alternative models in priority order |
|
|
78
|
+
| `isFree` | `boolean` | Whether the selected model is free |
|
|
79
|
+
| `isExpert` | `boolean` | Whether this is an expert-level query |
|
|
92
80
|
|
|
93
|
-
|
|
81
|
+
#### `routeBatch(queries: string[]): RoutingResult[]`
|
|
94
82
|
|
|
95
|
-
|
|
83
|
+
Route multiple queries at once.
|
|
96
84
|
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
85
|
+
```typescript
|
|
86
|
+
const decisions = router.routeBatch([
|
|
87
|
+
"What is 2+2?",
|
|
88
|
+
"Design a distributed database",
|
|
89
|
+
"Translate to French"
|
|
90
|
+
]);
|
|
91
|
+
|
|
92
|
+
decisions.forEach((d, i) => {
|
|
93
|
+
console.log(`Query ${i}: ${d.model} ($${d.cost.toFixed(6)})`);
|
|
94
|
+
});
|
|
101
95
|
```
|
|
102
96
|
|
|
103
|
-
####
|
|
97
|
+
#### `recommend(task: string): RoutingResult`
|
|
104
98
|
|
|
105
|
-
|
|
99
|
+
Get model recommendation for a task category.
|
|
106
100
|
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
|
|
101
|
+
```typescript
|
|
102
|
+
const rec = router.recommend("code generation");
|
|
103
|
+
console.log(rec.model); // "deepseek/deepseek-chat"
|
|
110
104
|
```
|
|
111
105
|
|
|
112
|
-
####
|
|
106
|
+
#### `analyze(query: string): QueryFeatures`
|
|
113
107
|
|
|
114
|
-
|
|
108
|
+
Extract detailed features from a query for debugging.
|
|
115
109
|
|
|
116
|
-
```
|
|
117
|
-
const
|
|
118
|
-
|
|
110
|
+
```typescript
|
|
111
|
+
const features = router.analyze("Design a secure authentication system for a healthcare app");
|
|
112
|
+
|
|
113
|
+
console.log(features.complexity); // 0.72
|
|
114
|
+
console.log(features.has_code); // false
|
|
115
|
+
console.log(features.requires_reasoning); // true
|
|
116
|
+
console.log(features.is_security); // true
|
|
117
|
+
console.log(features.detected_domain); // "security"
|
|
118
|
+
console.log(features.domain_score); // 0.30
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**QueryFeatures:**
|
|
122
|
+
|
|
123
|
+
| Field | Type | Description |
|
|
124
|
+
|-------|------|-------------|
|
|
125
|
+
| `complexity` | `number` | Overall complexity score (0.0–1.0) |
|
|
126
|
+
| `length` | `number` | Word count |
|
|
127
|
+
| `has_code` | `boolean` | Code-related keywords detected |
|
|
128
|
+
| `has_math` | `boolean` | Math-related keywords detected |
|
|
129
|
+
| `is_multilingual` | `boolean` | Non-ASCII characters detected |
|
|
130
|
+
| `is_translation` | `boolean` | Translation request detected |
|
|
131
|
+
| `is_creative` | `boolean` | Creative writing request |
|
|
132
|
+
| `requires_reasoning` | `boolean` | Analytical/reasoning verbs detected |
|
|
133
|
+
| `is_security` | `boolean` | Security domain keywords |
|
|
134
|
+
| `is_devops` | `boolean` | DevOps/infrastructure keywords |
|
|
135
|
+
| `is_data` | `boolean` | Data/ML keywords |
|
|
136
|
+
| `detected_domain` | `string` | Best matching domain (legal, medical, finance, security, architecture, ml_research) |
|
|
137
|
+
| `domain_score` | `number` | Domain match confidence |
|
|
138
|
+
|
|
139
|
+
#### `serve(port?: number): Promise<string>`
|
|
140
|
+
|
|
141
|
+
Start the OpenAI-compatible proxy server.
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
const proxyURL = await router.serve(8787);
|
|
145
|
+
console.log(proxyURL); // "http://localhost:8787/v1"
|
|
146
|
+
|
|
147
|
+
// Now use with any OpenAI SDK
|
|
148
|
+
import OpenAI from 'openai';
|
|
149
|
+
const client = new OpenAI({ baseURL: proxyURL, apiKey: 'not-needed' });
|
|
119
150
|
```
|
|
120
151
|
|
|
121
|
-
####
|
|
152
|
+
#### `proxyURL` (getter)
|
|
122
153
|
|
|
123
|
-
|
|
154
|
+
Returns the proxy URL. Available after `serve()` is called, otherwise returns the default.
|
|
124
155
|
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
//
|
|
156
|
+
```typescript
|
|
157
|
+
router.serve(3000);
|
|
158
|
+
console.log(router.proxyURL); // "http://localhost:3000/v1"
|
|
128
159
|
```
|
|
129
160
|
|
|
130
|
-
|
|
161
|
+
### Tier Classification
|
|
131
162
|
|
|
132
|
-
|
|
163
|
+
Complexity scores map to tiers:
|
|
133
164
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
165
|
+
| Tier | Complexity Range | Typical Models | Cost/1M tokens |
|
|
166
|
+
|------|:----------------:|----------------|:--------------:|
|
|
167
|
+
| `free` | 0.00 – 0.19 | CommandCode, Ollama, LM Studio | $0.00 |
|
|
168
|
+
| `cheap` | 0.20 – 0.44 | Groq Llama, Cerebras, DeepSeek | ~$0.60 |
|
|
169
|
+
| `mid` | 0.45 – 0.64 | Mistral Small, GPT-4o-mini | ~$1.50 |
|
|
170
|
+
| `premium` | 0.65 – 1.00 | GPT-4o, Claude Sonnet, Gemini Pro | $2.50+ |
|
|
138
171
|
|
|
139
|
-
|
|
172
|
+
### Low-Level API
|
|
140
173
|
|
|
141
|
-
|
|
174
|
+
The SDK wraps these lower-level exports, also available directly:
|
|
142
175
|
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
|
|
176
|
+
```typescript
|
|
177
|
+
import {
|
|
178
|
+
routeQuery,
|
|
179
|
+
routeBatch,
|
|
180
|
+
recommendForTask,
|
|
181
|
+
extractQueryFeatures,
|
|
182
|
+
createA3MRouter,
|
|
183
|
+
getAvailableProviders,
|
|
184
|
+
registerProvider,
|
|
185
|
+
createProxyServer,
|
|
186
|
+
} from 'adaptive-memory-multi-model-router';
|
|
187
|
+
|
|
188
|
+
// Direct routing
|
|
189
|
+
const result = routeQuery("What is 2+2?");
|
|
190
|
+
// => { primary_model, fallback_models, confidence, reasoning, estimated_cost, ... }
|
|
191
|
+
|
|
192
|
+
// Router instance (v1 style)
|
|
193
|
+
const router = createA3MRouter();
|
|
194
|
+
const decision = router.route("Hello");
|
|
146
195
|
```
|
|
147
196
|
|
|
148
197
|
---
|
|
149
198
|
|
|
150
|
-
|
|
199
|
+
## Python SDK
|
|
151
200
|
|
|
152
|
-
|
|
201
|
+
### Installation
|
|
153
202
|
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
const memory = new EpisodicMemoryStore();
|
|
203
|
+
```bash
|
|
204
|
+
pip install a3m-router
|
|
158
205
|
```
|
|
159
206
|
|
|
160
|
-
|
|
207
|
+
### Usage
|
|
161
208
|
|
|
162
|
-
|
|
209
|
+
```python
|
|
210
|
+
from a3m import A3MRouter
|
|
163
211
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
provider: 'openai',
|
|
167
|
-
model: 'gpt-4o',
|
|
168
|
-
reasoning: 'Simple query, fast model sufficient'
|
|
169
|
-
});
|
|
170
|
-
```
|
|
212
|
+
# Create router instance
|
|
213
|
+
router = A3MRouter()
|
|
171
214
|
|
|
172
|
-
|
|
215
|
+
# Route a query
|
|
216
|
+
decision = router.route("Write a Python function")
|
|
217
|
+
print(decision.model) # "groq/llama-3.3-70b"
|
|
218
|
+
print(decision.tier) # "cheap"
|
|
219
|
+
print(decision.cost) # 0.0004
|
|
220
|
+
print(decision.complexity) # 0.35
|
|
173
221
|
|
|
174
|
-
|
|
222
|
+
# Chat through the router (auto-selects model)
|
|
223
|
+
response = router.chat("What is 2+2?")
|
|
224
|
+
print(response.content) # "4"
|
|
225
|
+
print(response.model) # "groq/llama-3.3-70b"
|
|
175
226
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
227
|
+
# Analyze query features
|
|
228
|
+
features = router.analyze("Design a microservice architecture")
|
|
229
|
+
print(features.complexity) # 0.58
|
|
230
|
+
print(features.has_code) # False
|
|
231
|
+
print(features.detected_domain) # "architecture"
|
|
179
232
|
```
|
|
180
233
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
### ObsidianVault
|
|
234
|
+
### Async Usage
|
|
184
235
|
|
|
185
|
-
|
|
236
|
+
```python
|
|
237
|
+
import asyncio
|
|
238
|
+
from a3m import A3MRouter
|
|
186
239
|
|
|
187
|
-
|
|
188
|
-
|
|
240
|
+
async def main():
|
|
241
|
+
router = A3MRouter()
|
|
242
|
+
|
|
243
|
+
# Async chat
|
|
244
|
+
response = await router.achat("Explain quantum computing")
|
|
245
|
+
print(response.content)
|
|
246
|
+
|
|
247
|
+
# Batch routing
|
|
248
|
+
decisions = router.route_batch([
|
|
249
|
+
"What is 2+2?",
|
|
250
|
+
"Design a distributed system",
|
|
251
|
+
"Write a poem"
|
|
252
|
+
])
|
|
253
|
+
for d in decisions:
|
|
254
|
+
print(f"{d.model} ({d.tier}) — ${d.cost:.6f}")
|
|
189
255
|
|
|
190
|
-
|
|
256
|
+
asyncio.run(main())
|
|
191
257
|
```
|
|
192
258
|
|
|
193
|
-
|
|
259
|
+
### With OpenAI Python SDK
|
|
194
260
|
|
|
195
|
-
|
|
261
|
+
```python
|
|
262
|
+
from openai import OpenAI
|
|
196
263
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
selectedProvider: 'openai',
|
|
203
|
-
selectedModel: 'gpt-4o',
|
|
204
|
-
reasoning: 'Complex topic, use best model',
|
|
205
|
-
cost: 0.003,
|
|
206
|
-
latency: 1200
|
|
207
|
-
});
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
#### vault.getRecentDecisions(count)
|
|
211
|
-
|
|
212
|
-
Gets recent decisions.
|
|
264
|
+
# Point OpenAI SDK at the A3M proxy
|
|
265
|
+
client = OpenAI(
|
|
266
|
+
base_url="http://localhost:8787/v1",
|
|
267
|
+
api_key="not-needed"
|
|
268
|
+
)
|
|
213
269
|
|
|
214
|
-
|
|
215
|
-
|
|
270
|
+
response = client.chat.completions.create(
|
|
271
|
+
model="auto",
|
|
272
|
+
messages=[{"role": "user", "content": "Hello!"}]
|
|
273
|
+
)
|
|
274
|
+
print(response.choices[0].message.content)
|
|
216
275
|
```
|
|
217
276
|
|
|
218
277
|
---
|
|
219
278
|
|
|
220
|
-
##
|
|
221
|
-
|
|
222
|
-
### EnhancedCompression
|
|
279
|
+
## CLI
|
|
223
280
|
|
|
224
|
-
|
|
281
|
+
### Installation
|
|
225
282
|
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
283
|
+
```bash
|
|
284
|
+
npm install -g adaptive-memory-multi-model-router
|
|
285
|
+
# or use without installing:
|
|
286
|
+
npx a3m-router <command>
|
|
230
287
|
```
|
|
231
288
|
|
|
232
|
-
|
|
289
|
+
### Commands
|
|
233
290
|
|
|
234
|
-
|
|
291
|
+
#### `route` — Route a query
|
|
235
292
|
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
// Returns: '# Hello\n\nURL: very-long-url.com/...'
|
|
293
|
+
```bash
|
|
294
|
+
npx a3m-router route "Your query here"
|
|
239
295
|
```
|
|
240
296
|
|
|
241
|
-
|
|
297
|
+
Output:
|
|
298
|
+
```
|
|
299
|
+
Primary: groq/llama-3.3-70b-versatile
|
|
300
|
+
Fallbacks: cerebras/llama-3.3-70b, mistral/mistral-small
|
|
301
|
+
Est. Cost: $0.000350
|
|
302
|
+
Type: api
|
|
303
|
+
Reason: Selected Groq for code detected, fast tier
|
|
304
|
+
```
|
|
242
305
|
|
|
243
|
-
|
|
306
|
+
#### `serve` — Start proxy server
|
|
244
307
|
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
// { original: 200, compressed: 80, reduction: '60.0%', ratio: '0.40' }
|
|
308
|
+
```bash
|
|
309
|
+
npx a3m-router serve --port 8787
|
|
248
310
|
```
|
|
249
311
|
|
|
250
|
-
|
|
312
|
+
Options:
|
|
313
|
+
- `--port` / `-p` — Port to listen on (default: 8787)
|
|
251
314
|
|
|
252
|
-
|
|
315
|
+
#### `benchmark` — Run routing accuracy benchmark
|
|
253
316
|
|
|
254
|
-
|
|
317
|
+
```bash
|
|
318
|
+
npx a3m-router benchmark
|
|
319
|
+
```
|
|
255
320
|
|
|
256
|
-
|
|
257
|
-
import { isonEncode, isonDecode } from 'adaptive-memory-multi-model-router/utils/compression';
|
|
321
|
+
#### `providers` — List configured providers
|
|
258
322
|
|
|
259
|
-
|
|
260
|
-
|
|
323
|
+
```bash
|
|
324
|
+
npx a3m-router providers
|
|
261
325
|
```
|
|
262
326
|
|
|
263
|
-
|
|
327
|
+
#### `models` — List known models
|
|
264
328
|
|
|
265
|
-
|
|
329
|
+
```bash
|
|
330
|
+
npx a3m-router models
|
|
331
|
+
```
|
|
266
332
|
|
|
267
|
-
|
|
333
|
+
#### `recommend` — Get model recommendation for a task
|
|
268
334
|
|
|
269
|
-
|
|
335
|
+
```bash
|
|
336
|
+
npx a3m-router recommend "code generation"
|
|
337
|
+
```
|
|
270
338
|
|
|
271
|
-
|
|
272
|
-
import { AutoFetch } from 'adaptive-memory-multi-model-router/autofetch';
|
|
339
|
+
#### `cost` — Estimate token cost
|
|
273
340
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
targets: ['github', 'notion', 'slack', 'gmail', 'calendar']
|
|
277
|
-
});
|
|
341
|
+
```bash
|
|
342
|
+
npx a3m-router cost "Your text here"
|
|
278
343
|
```
|
|
279
344
|
|
|
280
|
-
####
|
|
281
|
-
|
|
282
|
-
Starts the sync loop.
|
|
345
|
+
#### `token` — Count tokens
|
|
283
346
|
|
|
284
|
-
```
|
|
285
|
-
|
|
347
|
+
```bash
|
|
348
|
+
npx a3m-router token "Your text here"
|
|
286
349
|
```
|
|
287
350
|
|
|
288
|
-
####
|
|
351
|
+
#### `batch` — Route multiple queries
|
|
289
352
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
```javascript
|
|
293
|
-
const results = await fetcher.syncAll();
|
|
294
|
-
// Returns: Map<target, SyncResult>
|
|
353
|
+
```bash
|
|
354
|
+
npx a3m-router batch "What is 2+2?" "Design a system" "Write a poem"
|
|
295
355
|
```
|
|
296
356
|
|
|
297
|
-
####
|
|
357
|
+
#### `compare` — Compare providers side by side
|
|
298
358
|
|
|
299
|
-
|
|
359
|
+
```bash
|
|
360
|
+
npx a3m-router compare "Your query"
|
|
361
|
+
```
|
|
300
362
|
|
|
301
|
-
|
|
302
|
-
|
|
363
|
+
#### `test` — Test all configured providers
|
|
364
|
+
|
|
365
|
+
```bash
|
|
366
|
+
npx a3m-router test
|
|
303
367
|
```
|
|
304
368
|
|
|
305
|
-
####
|
|
369
|
+
#### `memory` — Memory operations
|
|
306
370
|
|
|
307
|
-
|
|
371
|
+
```bash
|
|
372
|
+
npx a3m-router memory add "key" "value"
|
|
373
|
+
npx a3m-router memory search "query"
|
|
374
|
+
npx a3m-router memory stats
|
|
375
|
+
```
|
|
308
376
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
377
|
+
#### `status` — Show router status
|
|
378
|
+
|
|
379
|
+
```bash
|
|
380
|
+
npx a3m-router status
|
|
312
381
|
```
|
|
313
382
|
|
|
314
383
|
---
|
|
315
384
|
|
|
316
|
-
##
|
|
385
|
+
## REST API
|
|
317
386
|
|
|
318
|
-
|
|
387
|
+
Start the server:
|
|
319
388
|
|
|
320
|
-
|
|
389
|
+
```bash
|
|
390
|
+
npx a3m-router serve --port 8787
|
|
391
|
+
```
|
|
321
392
|
|
|
322
|
-
|
|
323
|
-
import { OAuthManager } from 'adaptive-memory-multi-model-router/oauth';
|
|
393
|
+
Base URL: `http://localhost:8787`
|
|
324
394
|
|
|
325
|
-
|
|
326
|
-
```
|
|
395
|
+
### POST /v1/chat/completions
|
|
327
396
|
|
|
328
|
-
|
|
397
|
+
OpenAI-compatible chat endpoint. Supports both streaming and non-streaming.
|
|
329
398
|
|
|
330
|
-
|
|
399
|
+
**Request:**
|
|
331
400
|
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
401
|
+
```bash
|
|
402
|
+
curl http://localhost:8787/v1/chat/completions \
|
|
403
|
+
-H "Content-Type: application/json" \
|
|
404
|
+
-d '{
|
|
405
|
+
"model": "auto",
|
|
406
|
+
"messages": [
|
|
407
|
+
{"role": "system", "content": "You are a helpful assistant."},
|
|
408
|
+
{"role": "user", "content": "What is 2+2?"}
|
|
409
|
+
],
|
|
410
|
+
"temperature": 0.7,
|
|
411
|
+
"max_tokens": 1024,
|
|
412
|
+
"stream": false
|
|
413
|
+
}'
|
|
338
414
|
```
|
|
339
415
|
|
|
340
|
-
|
|
416
|
+
**Request Body:**
|
|
341
417
|
|
|
342
|
-
|
|
418
|
+
| Field | Type | Default | Description |
|
|
419
|
+
|-------|------|---------|-------------|
|
|
420
|
+
| `model` | `string` | `"auto"` | Model to use. `"auto"` triggers routing. Accepts `provider/model` format. |
|
|
421
|
+
| `messages` | `array` | required | OpenAI-format message array |
|
|
422
|
+
| `temperature` | `number` | provider default | Sampling temperature (0–2) |
|
|
423
|
+
| `max_tokens` | `number` | `1024` | Maximum tokens to generate |
|
|
424
|
+
| `stream` | `boolean` | `false` | Enable SSE streaming |
|
|
425
|
+
| `stop` | `string \| string[]` | — | Stop sequences |
|
|
343
426
|
|
|
344
|
-
|
|
345
|
-
const url = oauth.getAuthUrl('github');
|
|
346
|
-
// Opens OAuth flow
|
|
347
|
-
```
|
|
427
|
+
**Non-streaming response:**
|
|
348
428
|
|
|
349
|
-
|
|
429
|
+
```json
|
|
430
|
+
{
|
|
431
|
+
"id": "chatcmpl-a1b2c3d4",
|
|
432
|
+
"object": "chat.completion",
|
|
433
|
+
"created": 1716000000,
|
|
434
|
+
"model": "llama-3.3-70b-versatile",
|
|
435
|
+
"choices": [
|
|
436
|
+
{
|
|
437
|
+
"index": 0,
|
|
438
|
+
"message": {
|
|
439
|
+
"role": "assistant",
|
|
440
|
+
"content": "2 + 2 = 4"
|
|
441
|
+
},
|
|
442
|
+
"finish_reason": "stop"
|
|
443
|
+
}
|
|
444
|
+
],
|
|
445
|
+
"usage": {
|
|
446
|
+
"prompt_tokens": 24,
|
|
447
|
+
"completion_tokens": 5,
|
|
448
|
+
"total_tokens": 29
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
```
|
|
350
452
|
|
|
351
|
-
|
|
453
|
+
**Streaming response:**
|
|
352
454
|
|
|
353
|
-
```javascript
|
|
354
|
-
const tokens = await oauth.handleCallback('github', code, state);
|
|
355
455
|
```
|
|
456
|
+
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":...,"model":"...","choices":[{"index":0,"delta":{"content":"2"},"finish_reason":null}]}
|
|
356
457
|
|
|
357
|
-
|
|
458
|
+
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":...,"model":"...","choices":[{"index":0,"delta":{"content":" +"},"finish_reason":null}]}
|
|
358
459
|
|
|
359
|
-
|
|
460
|
+
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":...,"model":"...","choices":[{"index":0,"delta":{"content":" 2 = 4"},"finish_reason":null}]}
|
|
360
461
|
|
|
361
|
-
|
|
362
|
-
|
|
462
|
+
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":...,"model":"...","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
|
|
463
|
+
|
|
464
|
+
data: [DONE]
|
|
363
465
|
```
|
|
364
466
|
|
|
365
|
-
|
|
467
|
+
**Model routing:**
|
|
366
468
|
|
|
367
|
-
|
|
469
|
+
| Model value | Behavior |
|
|
470
|
+
|-------------|----------|
|
|
471
|
+
| `"auto"` | Routes based on query complexity (recommended) |
|
|
472
|
+
| `"groq/llama-3.3-70b-versatile"` | Uses specific provider/model |
|
|
473
|
+
| `"gpt-4o"` | Maps to configured OpenAI provider |
|
|
474
|
+
| `"claude-sonnet"` | Maps to configured Anthropic provider |
|
|
368
475
|
|
|
369
|
-
|
|
370
|
-
|
|
476
|
+
### POST /v1/completions
|
|
477
|
+
|
|
478
|
+
OpenAI-compatible text completions endpoint.
|
|
479
|
+
|
|
480
|
+
```bash
|
|
481
|
+
curl http://localhost:8787/v1/completions \
|
|
482
|
+
-H "Content-Type: application/json" \
|
|
483
|
+
-d '{
|
|
484
|
+
"model": "auto",
|
|
485
|
+
"prompt": "The capital of France is",
|
|
486
|
+
"max_tokens": 50
|
|
487
|
+
}'
|
|
371
488
|
```
|
|
372
489
|
|
|
373
|
-
|
|
490
|
+
**Response:**
|
|
374
491
|
|
|
375
|
-
|
|
492
|
+
```json
|
|
493
|
+
{
|
|
494
|
+
"id": "chatcmpl-...",
|
|
495
|
+
"object": "text_completion",
|
|
496
|
+
"created": 1716000000,
|
|
497
|
+
"model": "llama-3.3-70b-versatile",
|
|
498
|
+
"choices": [
|
|
499
|
+
{
|
|
500
|
+
"text": " Paris.",
|
|
501
|
+
"index": 0,
|
|
502
|
+
"finish_reason": "stop"
|
|
503
|
+
}
|
|
504
|
+
],
|
|
505
|
+
"usage": {
|
|
506
|
+
"prompt_tokens": 5,
|
|
507
|
+
"completion_tokens": 2,
|
|
508
|
+
"total_tokens": 7
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
```
|
|
376
512
|
|
|
377
|
-
###
|
|
513
|
+
### POST /v1/route
|
|
378
514
|
|
|
379
|
-
|
|
515
|
+
Route a query without executing it. Returns the routing decision.
|
|
380
516
|
|
|
381
|
-
```
|
|
382
|
-
|
|
517
|
+
```bash
|
|
518
|
+
curl -X POST http://localhost:8787/v1/route \
|
|
519
|
+
-H "Content-Type: application/json" \
|
|
520
|
+
-d '{"query": "Write a Python function to sort a list"}'
|
|
521
|
+
```
|
|
383
522
|
|
|
384
|
-
|
|
523
|
+
**Response:**
|
|
524
|
+
|
|
525
|
+
```json
|
|
526
|
+
{
|
|
527
|
+
"primary_model": "groq/llama-3.3-70b-versatile",
|
|
528
|
+
"fallback_models": ["cerebras/llama-3.3-70b", "mistral/mistral-small"],
|
|
529
|
+
"confidence": 0.82,
|
|
530
|
+
"reasoning": "Selected Groq for code detected, fast tier",
|
|
531
|
+
"estimated_cost": 0.00035,
|
|
532
|
+
"estimated_latency_ms": 800,
|
|
533
|
+
"features": {
|
|
534
|
+
"complexity": 0.35,
|
|
535
|
+
"has_code": true,
|
|
536
|
+
"has_math": false,
|
|
537
|
+
"requires_reasoning": false,
|
|
538
|
+
"detected_domain": ""
|
|
539
|
+
}
|
|
540
|
+
}
|
|
385
541
|
```
|
|
386
542
|
|
|
387
|
-
|
|
543
|
+
### GET /v1/models
|
|
388
544
|
|
|
389
|
-
|
|
545
|
+
List all available models.
|
|
390
546
|
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
// ['openai', 'groq', 'anthropic']
|
|
547
|
+
```bash
|
|
548
|
+
curl http://localhost:8787/v1/models
|
|
394
549
|
```
|
|
395
550
|
|
|
396
|
-
|
|
551
|
+
**Response:**
|
|
397
552
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
553
|
+
```json
|
|
554
|
+
{
|
|
555
|
+
"object": "list",
|
|
556
|
+
"data": [
|
|
557
|
+
{
|
|
558
|
+
"id": "groq/llama-3.3-70b-versatile",
|
|
559
|
+
"object": "model",
|
|
560
|
+
"owned_by": "groq"
|
|
561
|
+
}
|
|
562
|
+
]
|
|
563
|
+
}
|
|
403
564
|
```
|
|
404
565
|
|
|
405
|
-
|
|
566
|
+
### GET /health
|
|
406
567
|
|
|
407
|
-
|
|
568
|
+
Health check with provider status and cost summary.
|
|
408
569
|
|
|
409
|
-
```
|
|
410
|
-
|
|
570
|
+
```bash
|
|
571
|
+
curl http://localhost:8787/health
|
|
411
572
|
```
|
|
412
573
|
|
|
413
|
-
|
|
574
|
+
**Response:**
|
|
414
575
|
|
|
415
|
-
|
|
576
|
+
```json
|
|
577
|
+
{
|
|
578
|
+
"status": "ok",
|
|
579
|
+
"version": "2.1.0",
|
|
580
|
+
"providers": {
|
|
581
|
+
"total": 12,
|
|
582
|
+
"healthy": 8,
|
|
583
|
+
"details": {
|
|
584
|
+
"groq": {
|
|
585
|
+
"name": "Groq",
|
|
586
|
+
"type": "api",
|
|
587
|
+
"models": 3,
|
|
588
|
+
"available": true
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
},
|
|
592
|
+
"cost": {
|
|
593
|
+
"total": 0.0042,
|
|
594
|
+
"requests": 127
|
|
595
|
+
},
|
|
596
|
+
"uptime": 86400.5,
|
|
597
|
+
"recentRequests": []
|
|
598
|
+
}
|
|
599
|
+
```
|
|
416
600
|
|
|
417
|
-
|
|
418
|
-
|
|
601
|
+
### GET /dashboard
|
|
602
|
+
|
|
603
|
+
Interactive web dashboard (if `public/` directory is present).
|
|
604
|
+
|
|
605
|
+
```
|
|
606
|
+
http://localhost:8787/
|
|
419
607
|
```
|
|
420
608
|
|
|
421
609
|
---
|
|
422
610
|
|
|
423
|
-
##
|
|
611
|
+
## OpenAI SDK Compatibility
|
|
424
612
|
|
|
425
|
-
|
|
613
|
+
The A3M Router proxy is fully compatible with the OpenAI SDK. Point the `baseURL` at the proxy and use `model: "auto"` for routing.
|
|
426
614
|
|
|
427
|
-
|
|
615
|
+
### JavaScript/TypeScript
|
|
428
616
|
|
|
429
617
|
```javascript
|
|
430
|
-
import
|
|
618
|
+
import OpenAI from 'openai';
|
|
431
619
|
|
|
432
|
-
const
|
|
433
|
-
|
|
620
|
+
const client = new OpenAI({
|
|
621
|
+
baseURL: 'http://localhost:8787/v1',
|
|
622
|
+
apiKey: 'not-needed'
|
|
623
|
+
});
|
|
434
624
|
|
|
435
|
-
|
|
625
|
+
// Auto-routing
|
|
626
|
+
const response = await client.chat.completions.create({
|
|
627
|
+
model: 'auto',
|
|
628
|
+
messages: [{ role: 'user', content: 'Hello!' }]
|
|
629
|
+
});
|
|
436
630
|
|
|
437
|
-
|
|
631
|
+
// Specific model
|
|
632
|
+
const response2 = await client.chat.completions.create({
|
|
633
|
+
model: 'groq/llama-3.3-70b-versatile',
|
|
634
|
+
messages: [{ role: 'user', content: 'Hello!' }]
|
|
635
|
+
});
|
|
438
636
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
completionTokens: 200,
|
|
445
|
-
cost: 0.003
|
|
637
|
+
// Streaming
|
|
638
|
+
const stream = await client.chat.completions.create({
|
|
639
|
+
model: 'auto',
|
|
640
|
+
messages: [{ role: 'user', content: 'Tell me a story' }],
|
|
641
|
+
stream: true
|
|
446
642
|
});
|
|
643
|
+
for await (const chunk of stream) {
|
|
644
|
+
process.stdout.write(chunk.choices[0]?.delta?.content || '');
|
|
645
|
+
}
|
|
447
646
|
```
|
|
448
647
|
|
|
449
|
-
|
|
648
|
+
### Python
|
|
450
649
|
|
|
451
|
-
|
|
650
|
+
```python
|
|
651
|
+
from openai import OpenAI
|
|
452
652
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
653
|
+
client = OpenAI(
|
|
654
|
+
base_url="http://localhost:8787/v1",
|
|
655
|
+
api_key="not-needed"
|
|
656
|
+
)
|
|
457
657
|
|
|
458
|
-
|
|
658
|
+
response = client.chat.completions.create(
|
|
659
|
+
model="auto",
|
|
660
|
+
messages=[{"role": "user", "content": "Hello!"}]
|
|
661
|
+
)
|
|
662
|
+
print(response.choices[0].message.content)
|
|
663
|
+
```
|
|
459
664
|
|
|
460
|
-
|
|
665
|
+
### cURL
|
|
461
666
|
|
|
462
|
-
```
|
|
463
|
-
|
|
667
|
+
```bash
|
|
668
|
+
curl http://localhost:8787/v1/chat/completions \
|
|
669
|
+
-H "Content-Type: application/json" \
|
|
670
|
+
-d '{"model":"auto","messages":[{"role":"user","content":"Hello!"}]}'
|
|
464
671
|
```
|
|
465
672
|
|
|
466
673
|
---
|
|
467
674
|
|
|
468
|
-
##
|
|
675
|
+
## LangChain Integration
|
|
469
676
|
|
|
470
|
-
|
|
677
|
+
```typescript
|
|
678
|
+
import { A3MChatModel } from 'adaptive-memory-multi-model-router/langchain';
|
|
679
|
+
import { HumanMessage } from '@langchain/core/messages';
|
|
471
680
|
|
|
472
|
-
|
|
681
|
+
const model = new A3MChatModel({
|
|
682
|
+
modelName: 'auto', // or specific model
|
|
683
|
+
temperature: 0.7,
|
|
684
|
+
});
|
|
473
685
|
|
|
474
|
-
|
|
475
|
-
|
|
686
|
+
// Invoke
|
|
687
|
+
const response = await model.invoke([
|
|
688
|
+
new HumanMessage("What is 2+2?")
|
|
689
|
+
]);
|
|
690
|
+
console.log(response.content);
|
|
691
|
+
|
|
692
|
+
// Streaming
|
|
693
|
+
const stream = await model.stream([
|
|
694
|
+
new HumanMessage("Tell me a story")
|
|
695
|
+
]);
|
|
696
|
+
for await (const chunk of stream) {
|
|
697
|
+
process.stdout.write(chunk.content);
|
|
698
|
+
}
|
|
699
|
+
```
|
|
476
700
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
});
|
|
701
|
+
**Prerequisites:**
|
|
702
|
+
|
|
703
|
+
```bash
|
|
704
|
+
npm install @langchain/core @langchain/openai
|
|
482
705
|
```
|
|
483
706
|
|
|
484
|
-
|
|
707
|
+
LangChain is a peer dependency — install it separately.
|
|
485
708
|
|
|
486
|
-
|
|
709
|
+
---
|
|
487
710
|
|
|
488
|
-
|
|
489
|
-
if (breaker.canExecute()) {
|
|
490
|
-
// Proceed with request
|
|
491
|
-
}
|
|
492
|
-
```
|
|
711
|
+
## Configuration
|
|
493
712
|
|
|
494
|
-
|
|
713
|
+
### Environment Variables
|
|
495
714
|
|
|
496
|
-
|
|
715
|
+
| Variable | Description | Default |
|
|
716
|
+
|----------|-------------|---------|
|
|
717
|
+
| `PORT` | Proxy server port | `8787` |
|
|
718
|
+
| `GROQ_API_KEY` | Groq provider API key | — |
|
|
719
|
+
| `CEREBRAS_API_KEY` | Cerebras provider API key | — |
|
|
720
|
+
| `OPENAI_API_KEY` | OpenAI provider API key | — |
|
|
721
|
+
| `ANTHROPIC_API_KEY` | Anthropic provider API key | — |
|
|
722
|
+
| `GOOGLE_API_KEY` | Google/Gemini provider API key | — |
|
|
723
|
+
| `MISTRAL_API_KEY` | Mistral provider API key | — |
|
|
724
|
+
| `DEEPSEEK_API_KEY` | DeepSeek provider API key | — |
|
|
725
|
+
| `OPENROUTER_API_KEY` | OpenRouter provider API key | — |
|
|
497
726
|
|
|
498
|
-
|
|
499
|
-
breaker.recordSuccess();
|
|
500
|
-
```
|
|
727
|
+
### Config File
|
|
501
728
|
|
|
502
|
-
|
|
729
|
+
Provider configuration is stored at `~/.config/a3m-router/providers.json`:
|
|
503
730
|
|
|
504
|
-
|
|
731
|
+
```json
|
|
732
|
+
{
|
|
733
|
+
"providers": {
|
|
734
|
+
"groq": {
|
|
735
|
+
"apiKey": "gsk_...",
|
|
736
|
+
"models": ["llama-3.3-70b-versatile", "mixtral-8x7b"]
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
```
|
|
505
741
|
|
|
506
|
-
|
|
507
|
-
|
|
742
|
+
### Programmatic Provider Registration
|
|
743
|
+
|
|
744
|
+
```typescript
|
|
745
|
+
import { registerProvider } from 'adaptive-memory-multi-model-router';
|
|
746
|
+
|
|
747
|
+
registerProvider('my-provider', {
|
|
748
|
+
name: 'My Provider',
|
|
749
|
+
type: 'api',
|
|
750
|
+
apiKey: 'sk-...',
|
|
751
|
+
baseUrl: 'https://api.my-provider.com/v1/chat/completions',
|
|
752
|
+
models: ['my-model-v1'],
|
|
753
|
+
costPerK: { input: 0.50, output: 1.50 },
|
|
754
|
+
maxTokens: 8192,
|
|
755
|
+
priority: 5,
|
|
756
|
+
});
|
|
508
757
|
```
|
|
509
758
|
|
|
510
759
|
---
|
|
511
760
|
|
|
512
|
-
##
|
|
761
|
+
## Error Handling
|
|
513
762
|
|
|
514
|
-
|
|
515
|
-
|---------|-------------|
|
|
516
|
-
| `a3m-router route "prompt"` | Route to optimal model |
|
|
517
|
-
| `a3m-router parallel "t1" "t2" "t3"` | Parallel execution |
|
|
518
|
-
| `a3m-router compare "prompt"` | Compare models |
|
|
519
|
-
| `a3m-router cost` | Show cost summary |
|
|
520
|
-
| `a3m-router count "text"` | Count tokens |
|
|
521
|
-
| `a3m-router compress "text"` | Compress text |
|
|
522
|
-
| `a3m-router local "prompt"` | Local Ollama |
|
|
523
|
-
| `a3m-router providers` | List providers |
|
|
763
|
+
### HTTP Error Responses
|
|
524
764
|
|
|
525
|
-
|
|
765
|
+
All errors follow the OpenAI error format:
|
|
526
766
|
|
|
527
|
-
|
|
767
|
+
```json
|
|
768
|
+
{
|
|
769
|
+
"error": {
|
|
770
|
+
"message": "No provider available for model \"gpt-4o\". Configure API keys.",
|
|
771
|
+
"type": "server_error",
|
|
772
|
+
"code": 503
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
```
|
|
528
776
|
|
|
529
|
-
|
|
530
|
-
|
|
777
|
+
| Status | Type | Description |
|
|
778
|
+
|--------|------|-------------|
|
|
779
|
+
| 400 | `invalid_request_error` | Malformed request body or missing fields |
|
|
780
|
+
| 404 | `not_found` | Unknown endpoint |
|
|
781
|
+
| 502 | `upstream_error` | Provider returned an error |
|
|
782
|
+
| 503 | `server_error` | No providers available |
|
|
531
783
|
|
|
532
|
-
|
|
784
|
+
### Fallback Behavior
|
|
785
|
+
|
|
786
|
+
When the primary provider fails, the proxy automatically tries alternative providers in order:
|
|
787
|
+
|
|
788
|
+
1. Primary provider (routed or specified)
|
|
789
|
+
2. Other configured API providers
|
|
790
|
+
3. Returns 502 if all providers fail
|
|
791
|
+
|
|
792
|
+
### SDK Error Handling
|
|
793
|
+
|
|
794
|
+
```typescript
|
|
795
|
+
const router = new A3MRouter();
|
|
533
796
|
|
|
534
797
|
try {
|
|
535
|
-
const
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
);
|
|
539
|
-
} catch (error) {
|
|
540
|
-
if (breaker.getState().status === 'open') {
|
|
541
|
-
console.log('Circuit open - using fallback');
|
|
798
|
+
const decision = router.route("Your query");
|
|
799
|
+
if (decision.model === 'unknown') {
|
|
800
|
+
// No providers available
|
|
542
801
|
}
|
|
802
|
+
} catch (err) {
|
|
803
|
+
console.error('Routing failed:', err);
|
|
543
804
|
}
|
|
544
805
|
```
|
|
545
806
|
|
|
546
807
|
---
|
|
547
808
|
|
|
548
|
-
##
|
|
809
|
+
## Provider Support
|
|
549
810
|
|
|
550
|
-
|
|
811
|
+
### Supported Provider Types
|
|
812
|
+
|
|
813
|
+
| Type | Providers | Protocol |
|
|
814
|
+
|------|-----------|----------|
|
|
815
|
+
| **API** | Groq, Cerebras, OpenAI, Anthropic, Google, Mistral, DeepSeek, OpenRouter | REST API |
|
|
816
|
+
| **Local** | Ollama, vLLM, LM Studio | OpenAI-compatible local API |
|
|
817
|
+
| **CLI** | CommandCode, OpenCode | Local CLI tools |
|
|
818
|
+
|
|
819
|
+
### Adding Custom Providers
|
|
551
820
|
|
|
552
821
|
```typescript
|
|
553
|
-
import {
|
|
822
|
+
import { registerProvider } from 'adaptive-memory-multi-model-router';
|
|
823
|
+
|
|
824
|
+
registerProvider('custom', {
|
|
825
|
+
name: 'Custom LLM',
|
|
826
|
+
type: 'api',
|
|
827
|
+
apiKey: process.env.CUSTOM_API_KEY,
|
|
828
|
+
baseUrl: 'https://api.custom.com/v1/chat/completions',
|
|
829
|
+
models: ['custom-v1'],
|
|
830
|
+
costPerK: { input: 1.0, output: 2.0 },
|
|
831
|
+
maxTokens: 4096,
|
|
832
|
+
priority: 5,
|
|
833
|
+
});
|
|
834
|
+
```
|
|
554
835
|
|
|
555
|
-
|
|
556
|
-
memory: true,
|
|
557
|
-
costBudget: 0.05,
|
|
558
|
-
providers: ['openai', 'groq']
|
|
559
|
-
};
|
|
836
|
+
---
|
|
560
837
|
|
|
561
|
-
|
|
838
|
+
## Architecture
|
|
839
|
+
|
|
840
|
+
```
|
|
841
|
+
┌──────────────┐ ┌──────────────────────────────────────────┐
|
|
842
|
+
│ Your Code │────>│ A3M Router │
|
|
843
|
+
│ │ │ │
|
|
844
|
+
│ OpenAI SDK │ │ ┌─────────┐ ┌──────────────────┐ │
|
|
845
|
+
│ LangChain │ │ │ Routing │───>│ Model Selection │ │
|
|
846
|
+
│ Python SDK │ │ │ Engine │ │ (cost/quality) │ │
|
|
847
|
+
│ CLI │ │ └─────────┘ └──────┬───────────┘ │
|
|
848
|
+
│ cURL │ │ │ │
|
|
849
|
+
└──────────────┘ │ ┌─────────────────────▼────────────┐ │
|
|
850
|
+
│ │ Provider Layer │ │
|
|
851
|
+
│ │ Groq | Cerebras | OpenAI | ... │ │
|
|
852
|
+
│ │ Ollama | vLLM | LM Studio │ │
|
|
853
|
+
│ └───────────────────────────────────┘ │
|
|
854
|
+
└──────────────────────────────────────────┘
|
|
562
855
|
```
|