adaptive-memory-multi-model-router 2.15.3 ā 2.15.5
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/workflows/adapters-ci.yml +142 -0
- package/.github/workflows/ci.yml +2 -5
- package/.github/workflows/pypi-publish.yml +102 -0
- package/CHANGELOG.md +7 -1
- package/README.md +260 -137
- package/README_ja.md +2 -2
- package/README_zh.md +1 -1
- package/adapters/README.md +36 -0
- package/adapters/__init__.py +25 -0
- package/adapters/a3m_adapter/__init__.py +51 -0
- package/adapters/a3m_adapter/adapter/__init__.py +22 -0
- package/adapters/a3m_adapter/adapter/autogen.py +169 -0
- package/adapters/a3m_adapter/adapter/config.py +100 -0
- package/adapters/a3m_adapter/adapter/haystack.py +197 -0
- package/adapters/a3m_adapter/adapter/langchain.py +155 -0
- package/adapters/a3m_adapter/adapter/langgraph.py +196 -0
- package/adapters/a3m_adapter/adapter/llamaindex.py +162 -0
- package/adapters/a3m_adapter/adapter/pinecone.py +217 -0
- package/adapters/a3m_adapter/adapter/vercel.py +188 -0
- package/adapters/a3m_adapter/tests/__init__.py +1 -0
- package/adapters/a3m_adapter/tests/test_adapters.py +118 -0
- package/adapters/a3m_adapter/tests/test_integration.py +80 -0
- package/adapters/requirements-dev.txt +6 -0
- package/adapters/requirements.txt +4 -0
- package/adapters/setup.py +23 -0
- package/apps/cost-calculator/README.md +72 -0
- package/apps/cost-calculator/calculator.css +280 -0
- package/apps/cost-calculator/calculator.js +150 -0
- package/apps/cost-calculator/index.html +321 -0
- package/apps/cost-calculator/package.json +13 -0
- package/articles/ANNOUNCEMENT_reddit_ml.md +76 -0
- package/articles/ANNOUNCEMENT_vc/347/244/276/345/214/272.md +71 -0
- package/articles/ANNOUNCEMENT_vercel.md +85 -0
- package/demo.py +251 -0
- package/dist/providers/providerConfig.d.ts +5 -1
- package/dist/providers/providerConfig.js +1006 -1
- package/dist/providers/providerConfig.js.map +1 -1
- package/docker-compose.yml +84 -60
- package/docs/comparison.md +2 -2
- package/docs/llms-full.txt +360 -138
- package/docs/llms.txt +70 -71
- package/docs-site/index.html +9 -9
- package/llms.txt +70 -62
- package/package.json +41 -91
- package/packages/a3m-vercel-ai/README.md +161 -0
- package/packages/a3m-vercel-ai/dist/a3m-language-model.d.ts +12 -0
- package/packages/a3m-vercel-ai/dist/a3m-language-model.d.ts.map +1 -0
- package/packages/a3m-vercel-ai/dist/a3m-language-model.js +289 -0
- package/packages/a3m-vercel-ai/dist/a3m-language-model.js.map +1 -0
- package/packages/a3m-vercel-ai/dist/index.d.ts +82 -0
- package/packages/a3m-vercel-ai/dist/index.d.ts.map +1 -0
- package/packages/a3m-vercel-ai/dist/index.js +79 -0
- package/packages/a3m-vercel-ai/dist/index.js.map +1 -0
- package/packages/a3m-vercel-ai/dist/types.d.ts +97 -0
- package/packages/a3m-vercel-ai/dist/types.d.ts.map +1 -0
- package/packages/a3m-vercel-ai/dist/types.js +5 -0
- package/packages/a3m-vercel-ai/dist/types.js.map +1 -0
- package/packages/a3m-vercel-ai/package-lock.json +969 -0
- package/packages/a3m-vercel-ai/package.json +46 -0
- package/packages/a3m-vercel-ai/src/a3m-language-model.ts +381 -0
- package/packages/a3m-vercel-ai/src/index.ts +104 -0
- package/packages/a3m-vercel-ai/src/types.ts +116 -0
- package/packages/a3m-vercel-ai/tsconfig.json +20 -0
- package/packages/agentkit-adapter/LICENSE +21 -0
- package/packages/agentkit-adapter/README.md +126 -0
- package/packages/agentkit-adapter/examples/agentkit-example.ts +139 -0
- package/packages/agentkit-adapter/package.json +57 -0
- package/packages/agentkit-adapter/src/adapter.ts +381 -0
- package/packages/agentkit-adapter/src/index.ts +36 -0
- package/packages/agentkit-adapter/src/types.ts +105 -0
- package/packages/agentkit-adapter/src/util.ts +13 -0
- package/packages/agentkit-adapter/tsconfig.json +22 -0
- package/prometheus.yml +8 -0
- package/python/README.md +92 -65
- package/python/a3m/__init__.py +32 -3
- package/python/a3m/adapters/__init__.py +21 -0
- package/python/a3m/adapters/langchain.py +190 -0
- package/python/a3m/adapters/llamaindex.py +249 -0
- package/python/a3m/adapters/qdrant.py +240 -0
- package/python/a3m/adapters/weaviate.py +263 -0
- package/python/a3m/client.py +5 -0
- package/python/a3m_router.egg-info/PKG-INFO +172 -0
- package/python/a3m_router.egg-info/SOURCES.txt +17 -0
- package/python/a3m_router.egg-info/dependency_links.txt +1 -0
- package/python/a3m_router.egg-info/requires.txt +24 -0
- package/python/a3m_router.egg-info/top_level.txt +1 -0
- package/python/build_verify.sh +32 -0
- package/python/dist/a3m_router-2.2.1-py3-none-any.whl +0 -0
- package/python/dist/a3m_router-2.2.1.tar.gz +0 -0
- package/python/dist/a3m_router-2.2.2-py3-none-any.whl +0 -0
- package/python/dist/a3m_router-2.2.2.tar.gz +0 -0
- package/python/mcp-server/README.md +172 -0
- package/python/mcp-server/a3m_mcp/__init__.py +15 -0
- package/python/mcp-server/a3m_mcp/__main__.py +15 -0
- package/python/mcp-server/a3m_mcp/server.py +339 -0
- package/python/mcp-server/pyproject.toml +24 -0
- package/python/pyproject.toml +56 -5
- package/python/setup.py +3 -28
- package/src/providers/providerConfig.ts +1053 -1
- package/summary.txt +38 -0
- package/tsconfig.build.json +1 -2
package/demo.py
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
A3M Router Demo - Parallel Ensemble with Multiple LLMs
|
|
4
|
+
|
|
5
|
+
Run this after starting the A3M Router server:
|
|
6
|
+
npx a3m-router serve
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
python demo.py
|
|
10
|
+
|
|
11
|
+
Requirements:
|
|
12
|
+
pip install adaptive-memory-multi-model-router requests
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import json
|
|
16
|
+
import sys
|
|
17
|
+
import time
|
|
18
|
+
from typing import Dict, List, Any
|
|
19
|
+
|
|
20
|
+
# Try to import from the a3m package
|
|
21
|
+
try:
|
|
22
|
+
from a3m.router import A3MRouter
|
|
23
|
+
USING_A3M_SDK = True
|
|
24
|
+
except ImportError:
|
|
25
|
+
USING_A3M_SDK = False
|
|
26
|
+
print("Note: Using HTTP API (install a3m package for SDK access)")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def print_header(text: str) -> None:
|
|
30
|
+
"""Print a section header."""
|
|
31
|
+
print("\n" + "=" * 60)
|
|
32
|
+
print(f" {text}")
|
|
33
|
+
print("=" * 60)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def print_result(result: Any) -> None:
|
|
37
|
+
"""Print a routing result."""
|
|
38
|
+
print(f"\nš¦ Provider: {getattr(result, 'provider', 'unknown')}")
|
|
39
|
+
print(f"ā±ļø Latency: {getattr(result, 'latency_ms', '?')}ms")
|
|
40
|
+
print(f"š° Cost: ${getattr(result, 'cost_usd', 0):.6f}")
|
|
41
|
+
print(f"\nš Response:\n{getattr(result, 'content', str(result))[:500]}")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def demo_simple_routing():
|
|
45
|
+
"""Demo 1: Simple auto-routing."""
|
|
46
|
+
print_header("DEMO 1: Simple Auto-Routing")
|
|
47
|
+
print("Query: 'What is 2+2?'")
|
|
48
|
+
print("Expected: Routes to cheapest provider (Groq/Mistral)")
|
|
49
|
+
|
|
50
|
+
if USING_A3M_SDK:
|
|
51
|
+
router = A3MRouter(model="auto")
|
|
52
|
+
result = router.route(
|
|
53
|
+
messages=[{"role": "user", "content": "What is 2+2?"}]
|
|
54
|
+
)
|
|
55
|
+
print_result(result)
|
|
56
|
+
else:
|
|
57
|
+
import requests
|
|
58
|
+
resp = requests.post(
|
|
59
|
+
"http://localhost:8787/v1/chat/completions",
|
|
60
|
+
json={
|
|
61
|
+
"model": "auto",
|
|
62
|
+
"messages": [{"role": "user", "content": "What is 2+2?"}]
|
|
63
|
+
},
|
|
64
|
+
timeout=30
|
|
65
|
+
)
|
|
66
|
+
data = resp.json()
|
|
67
|
+
print(f"\nš¦ Provider: {data.get('provider', 'unknown')}")
|
|
68
|
+
print(f"š Response: {data['choices'][0]['message']['content']}")
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def demo_parallel_ensemble():
|
|
72
|
+
"""Demo 2: Parallel ensemble with 3 providers."""
|
|
73
|
+
print_header("DEMO 2: Parallel Ensemble (3 Providers)")
|
|
74
|
+
print("Query: 'Explain quantum entanglement in simple terms'")
|
|
75
|
+
print("Providers: Groq + OpenAI + DeepSeek (all called in parallel)")
|
|
76
|
+
print("Expected: Best answer wins, with quality scores for each")
|
|
77
|
+
|
|
78
|
+
if USING_A3M_SDK:
|
|
79
|
+
router = A3MRouter(model="auto", parallel_ensemble=3)
|
|
80
|
+
|
|
81
|
+
start = time.time()
|
|
82
|
+
result = router.route(
|
|
83
|
+
messages=[{"role": "user", "content": "Explain quantum entanglement in simple terms"}],
|
|
84
|
+
ensemble_config={
|
|
85
|
+
"providers": ["groq", "openai", "deepseek"],
|
|
86
|
+
"timeout_ms": 30000,
|
|
87
|
+
"score_weights": {
|
|
88
|
+
"relevance": 0.4,
|
|
89
|
+
"conciseness": 0.3,
|
|
90
|
+
"accuracy": 0.3
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
)
|
|
94
|
+
elapsed = time.time() - start
|
|
95
|
+
|
|
96
|
+
print(f"\nā±ļø Total time: {elapsed:.1f}s")
|
|
97
|
+
print_result(result)
|
|
98
|
+
|
|
99
|
+
# Show all provider scores
|
|
100
|
+
if hasattr(result, 'scores'):
|
|
101
|
+
print("\nš All Provider Scores:")
|
|
102
|
+
for provider, scores in result.scores.items():
|
|
103
|
+
print(f" {provider}: {scores}")
|
|
104
|
+
else:
|
|
105
|
+
import requests
|
|
106
|
+
resp = requests.post(
|
|
107
|
+
"http://localhost:8787/v1/chat/completions",
|
|
108
|
+
json={
|
|
109
|
+
"model": "auto",
|
|
110
|
+
"messages": [{"role": "user", "content": "Explain quantum entanglement"}],
|
|
111
|
+
"parallel_ensemble": 3,
|
|
112
|
+
},
|
|
113
|
+
timeout=60
|
|
114
|
+
)
|
|
115
|
+
data = resp.json()
|
|
116
|
+
print(f"\nš¦ Winner: {data.get('provider', 'unknown')}")
|
|
117
|
+
print(f"š Response: {data['choices'][0]['message']['content'][:300]}...")
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def demo_code_generation():
|
|
121
|
+
"""Demo 3: Code generation routing."""
|
|
122
|
+
print_header("DEMO 3: Code Generation")
|
|
123
|
+
print("Query: 'Write a Python function to fibonacci'")
|
|
124
|
+
print("Expected: Routes to code-capable provider (DeepSeek/Groq)")
|
|
125
|
+
|
|
126
|
+
code_query = "Write a Python function to calculate fibonacci numbers recursively"
|
|
127
|
+
|
|
128
|
+
if USING_A3M_SDK:
|
|
129
|
+
router = A3MRouter(model="auto")
|
|
130
|
+
result = router.route(
|
|
131
|
+
messages=[{"role": "user", "content": code_query}]
|
|
132
|
+
)
|
|
133
|
+
print_result(result)
|
|
134
|
+
else:
|
|
135
|
+
import requests
|
|
136
|
+
resp = requests.post(
|
|
137
|
+
"http://localhost:8787/v1/chat/completions",
|
|
138
|
+
json={
|
|
139
|
+
"model": "auto",
|
|
140
|
+
"messages": [{"role": "user", "content": code_query}]
|
|
141
|
+
},
|
|
142
|
+
timeout=30
|
|
143
|
+
)
|
|
144
|
+
data = resp.json()
|
|
145
|
+
print(f"\nš¦ Provider: {data.get('provider', 'unknown')}")
|
|
146
|
+
print(f"\nš Code:\n{data['choices'][0]['message']['content']}")
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def demo_complex_reasoning():
|
|
150
|
+
"""Demo 4: Complex reasoning routes to premium."""
|
|
151
|
+
print_header("DEMO 4: Complex Reasoning (Premium Tier)")
|
|
152
|
+
print("Query: 'Design a microservices architecture for a fintech app'")
|
|
153
|
+
print("Expected: Routes to premium provider (GPT-4o/Claude)")
|
|
154
|
+
|
|
155
|
+
complex_query = "Design a microservices architecture for a fintech application with payments, KYC, and trading"
|
|
156
|
+
|
|
157
|
+
if USING_A3M_SDK:
|
|
158
|
+
router = A3MRouter(model="auto")
|
|
159
|
+
result = router.route(
|
|
160
|
+
messages=[{"role": "user", "content": complex_query}]
|
|
161
|
+
)
|
|
162
|
+
print_result(result)
|
|
163
|
+
else:
|
|
164
|
+
import requests
|
|
165
|
+
resp = requests.post(
|
|
166
|
+
"http://localhost:8787/v1/chat/completions",
|
|
167
|
+
json={
|
|
168
|
+
"model": "auto",
|
|
169
|
+
"messages": [{"role": "user", "content": complex_query}]
|
|
170
|
+
},
|
|
171
|
+
timeout=60
|
|
172
|
+
)
|
|
173
|
+
data = resp.json()
|
|
174
|
+
print(f"\nš¦ Provider: {data.get('provider', 'unknown')}")
|
|
175
|
+
print(f"š Response: {data['choices'][0]['message']['content'][:400]}...")
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def demo_health_check():
|
|
179
|
+
"""Demo 5: Check provider health."""
|
|
180
|
+
print_header("DEMO 5: Provider Health Status")
|
|
181
|
+
|
|
182
|
+
if USING_A3M_SDK:
|
|
183
|
+
router = A3MRouter(model="auto")
|
|
184
|
+
health = router.get_health()
|
|
185
|
+
print("\nš„ Provider Status:")
|
|
186
|
+
for provider, status in health.items():
|
|
187
|
+
latency = status.get('latency_ms', 'N/A')
|
|
188
|
+
available = "ā
" if status.get('available') else "ā"
|
|
189
|
+
print(f" {available} {provider}: {latency}ms")
|
|
190
|
+
else:
|
|
191
|
+
import requests
|
|
192
|
+
resp = requests.get("http://localhost:8787/health", timeout=10)
|
|
193
|
+
data = resp.json()
|
|
194
|
+
print("\nš„ Provider Status:")
|
|
195
|
+
for p in data.get('providers', []):
|
|
196
|
+
print(f" {'ā
' if p.get('available') else 'ā'} {p['name']}: {p.get('latency_ms', 'N/A')}ms")
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def main():
|
|
200
|
+
"""Run all demos."""
|
|
201
|
+
print("""
|
|
202
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
203
|
+
ā ā
|
|
204
|
+
ā A3M Router Demo - Parallel Ensemble ā
|
|
205
|
+
ā ā
|
|
206
|
+
ā Intelligent routing across 47+ LLM providers ā
|
|
207
|
+
ā Save 70-95% on AI costs ā
|
|
208
|
+
ā ā
|
|
209
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
210
|
+
|
|
211
|
+
Make sure A3M Router is running:
|
|
212
|
+
npx a3m-router serve
|
|
213
|
+
|
|
214
|
+
Then run this demo:
|
|
215
|
+
python demo.py
|
|
216
|
+
""")
|
|
217
|
+
|
|
218
|
+
# Check if server is running
|
|
219
|
+
try:
|
|
220
|
+
import requests
|
|
221
|
+
resp = requests.get("http://localhost:8787/health", timeout=5)
|
|
222
|
+
print("ā
Connected to A3M Router server\n")
|
|
223
|
+
except Exception as e:
|
|
224
|
+
print(f"ā ļø Cannot connect to A3M Router server: {e}")
|
|
225
|
+
print(" Make sure it's running: npx a3m-router serve")
|
|
226
|
+
print(" Demo will use HTTP fallback...\n")
|
|
227
|
+
|
|
228
|
+
# Run demos
|
|
229
|
+
demos = [
|
|
230
|
+
("Simple Routing", demo_simple_routing),
|
|
231
|
+
("Parallel Ensemble", demo_parallel_ensemble),
|
|
232
|
+
("Code Generation", demo_code_generation),
|
|
233
|
+
("Complex Reasoning", demo_complex_reasoning),
|
|
234
|
+
("Health Check", demo_health_check),
|
|
235
|
+
]
|
|
236
|
+
|
|
237
|
+
for name, demo_fn in demos:
|
|
238
|
+
try:
|
|
239
|
+
demo_fn()
|
|
240
|
+
except Exception as e:
|
|
241
|
+
print(f"\nā Demo failed: {e}")
|
|
242
|
+
|
|
243
|
+
print("\n" + "=" * 60)
|
|
244
|
+
print(" Demo Complete!")
|
|
245
|
+
print("=" * 60)
|
|
246
|
+
print("\nLearn more: https://github.com/Das-rebel/a3m-router")
|
|
247
|
+
print("Documentation: https://das-rebel.github.io/a3m-router/")
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
if __name__ == "__main__":
|
|
251
|
+
main()
|
|
@@ -6,7 +6,11 @@
|
|
|
6
6
|
* 2. Config file at ~/.config/a3m-router/providers.json
|
|
7
7
|
* 3. Runtime registration via registerProvider()
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* 70+ providers across free, cheap, mid-tier, premium, and enterprise tiers.
|
|
10
|
+
* Coverage: Cloudflare Workers AI, HuggingFace Inference, Modal, Lepton, NVIDIA NIM,
|
|
11
|
+
* Baseten, RunPod, Predibase, Featherless, Abacus, Hyperbolic, Stability AI,
|
|
12
|
+
* SiliconFlow, Yandex, Tencent, VolcEngine, Baidu, Kuaishou, 360 AI, Naver, Kakao,
|
|
13
|
+
* AWS Bedrock/SageMaker, Azure, and more.
|
|
10
14
|
*/
|
|
11
15
|
export type ProviderTier = 'free' | 'cheap' | 'mid' | 'premium' | 'enterprise';
|
|
12
16
|
export type ProviderFormat = 'openai' | 'anthropic' | 'google' | 'cohere' | 'aws-bedrock' | 'google-vertex';
|