narcolepticchicken commited on
Commit
f0139c7
Β·
verified Β·
1 Parent(s): 1856652

Upload DEPLOYMENT.md

Browse files
Files changed (1) hide show
  1. DEPLOYMENT.md +330 -0
DEPLOYMENT.md ADDED
@@ -0,0 +1,330 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ACO Deployment Guide
2
+
3
+ ## What ACO Is
4
+
5
+ ACO (Agent Cost Optimizer) is a middleware proxy that sits between your agent and LLM providers. It reduces cost by:
6
+
7
+ 1. **Model routing** β€” cheapest adequate model per request
8
+ 2. **Tool gating** β€” suppresses unnecessary tool calls (DistilBERT F1=0.92)
9
+ 3. **Context compression** β€” trims verbose traces/error logs
10
+ 4. **Cache-aware layout** β€” reorders prompts for provider prefix-cache discounts
11
+ 5. **Telemetry** β€” live dashboard + JSON API for cost tracking
12
+
13
+ ## Quick Start
14
+
15
+ ### Option 1: Run as a proxy (zero agent code changes)
16
+
17
+ ```bash
18
+ pip install aco-proxy
19
+ # Or: pip install fastapi uvicorn httpx openai
20
+
21
+ # Set provider API keys
22
+ export OPENAI_API_KEY=sk-...
23
+ export ANTHROPIC_API_KEY=sk-ant-...
24
+ export DEEPSEEK_API_KEY=sk-...
25
+ export GOOGLE_API_KEY=AI...
26
+
27
+ # Start the proxy
28
+ aco-proxy --port 8080
29
+ ```
30
+
31
+ Then point your agent at the proxy:
32
+ ```python
33
+ import openai
34
+ client = openai.OpenAI(base_url="http://localhost:8080/v1", api_key="your-key")
35
+ ```
36
+
37
+ That's it. All LLM calls now go through ACO optimizations.
38
+
39
+ ### Option 2: Run via Docker
40
+
41
+ ```bash
42
+ docker run -p 8080:8080 \
43
+ -e OPENAI_API_KEY=sk-... \
44
+ -e ANTHROPIC_API_KEY=sk-ant-... \
45
+ ghcr.io/narcolepticchicken/aco-proxy:latest
46
+ ```
47
+
48
+ ### Option 3: Run as HF Space
49
+
50
+ Deploy the proxy as a Hugging Face Space for a hosted dashboard:
51
+
52
+ ```bash
53
+ # Create a Space with Docker SDK
54
+ huggingface-cli repo create aco-proxy --type space --sdk docker
55
+ ```
56
+
57
+ ## Configuration
58
+
59
+ ### Model Registry
60
+
61
+ ACO's model registry maps models to cost tiers. Edit `aco/proxy.py` to add/remove models:
62
+
63
+ ```python
64
+ MODEL_REGISTRY = {
65
+ "deepseek-v4-flash": {"tier": 1, "cost_in": 0.14, "cost_out": 0.28, "ctx": 128000},
66
+ "gpt-5-mini": {"tier": 2, "cost_in": 0.15, "cost_out": 0.60, "ctx": 128000},
67
+ "gemini-2.5-pro": {"tier": 3, "cost_in": 1.25, "cost_out": 10.00, "ctx": 1048576},
68
+ # Add your models here
69
+ }
70
+ ```
71
+
72
+ ### Provider Endpoints
73
+
74
+ ```python
75
+ PROVIDER_ENDPOINTS = {
76
+ "openai": "https://api.openai.com/v1",
77
+ "anthropic": "https://api.anthropic.com/v1",
78
+ "google": "https://generativelanguage.googleapis.com/v1beta",
79
+ "deepseek": "https://api.deepseek.com/v1",
80
+ }
81
+ ```
82
+
83
+ ### Environment Variables
84
+
85
+ | Variable | Purpose | Default |
86
+ |---|---|---|
87
+ | `OPENAI_API_KEY` | OpenAI provider key | Required |
88
+ | `ANTHROPIC_API_KEY` | Anthropic provider key | Optional |
89
+ | `DEEPSEEK_API_KEY` | DeepSeek provider key | Optional |
90
+ | `GOOGLE_API_KEY` | Google provider key | Optional |
91
+ | `OPENAI_BASE_URL` | Custom OpenAI endpoint | `https://api.openai.com/v1` |
92
+ | `ACO_PORT` | Proxy port | `8080` |
93
+ | `ACO_HOST` | Proxy host | `0.0.0.0` |
94
+
95
+ ## API Endpoints
96
+
97
+ ### `POST /v1/chat/completions`
98
+ OpenAI-compatible. Pass any model from the registry; ACO routes to the cheapest adequate model.
99
+
100
+ ### `GET /dashboard`
101
+ Live HTML dashboard showing:
102
+ - Total calls, cost, success rate
103
+ - Per-model call distribution
104
+ - Cache hit rate, tool gates, model reroutes
105
+ - Recent request log (last 30 calls)
106
+
107
+ ### `GET /telemetry`
108
+ JSON telemetry for programmatic consumption:
109
+ ```json
110
+ {
111
+ "total_calls": 42,
112
+ "total_cost": 0.0234,
113
+ "calls": [{"model": "gpt-5-mini", "tier": 2, "cost": 0.0005, ...}]
114
+ }
115
+ ```
116
+
117
+ ### `GET /telemetry/reset`
118
+ Clear all telemetry data.
119
+
120
+ ### `GET /health`
121
+ Health check endpoint.
122
+
123
+ ### `GET /v1/models`
124
+ List available models in OpenAI format.
125
+
126
+ ## How Routing Works
127
+
128
+ ```
129
+ Request comes in with model="gemini-2.5-pro" (tier 3)
130
+ β”‚
131
+ β–Ό
132
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
133
+ β”‚ Extract user text β”‚
134
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
135
+ β”‚
136
+ β–Ό
137
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
138
+ β”‚ Is text < 300 chars │─── Yes ──→ Route to tier 1 (deepseek-v4-flash)
139
+ β”‚ AND tier >= 3? β”‚
140
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
141
+ β”‚ No
142
+ β–Ό
143
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
144
+ β”‚ Coding keywords? │─── Yes ──→ Keep tier 2 minimum
145
+ β”‚ (def, class, fix) β”‚
146
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
147
+ β”‚ No
148
+ β–Ό
149
+ Pass through (no routing change)
150
+ ```
151
+
152
+ ## How Tool Gating Works
153
+
154
+ The tool-gater is a DistilBERT classifier (F1=0.92) trained on ToolACE + RouterArena data.
155
+
156
+ ```
157
+ Request has tools=[search, calculator, ...]
158
+ β”‚
159
+ β–Ό
160
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
161
+ β”‚ Check conversation β”‚
162
+ β”‚ history for prior │─── Has tool history ──→ Don't gate
163
+ β”‚ tool calls β”‚
164
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€οΏ½οΏ½οΏ½β”€β”€β”€β”€β”€β”€β”€β”˜
165
+ β”‚ No prior tools
166
+ β–Ό
167
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
168
+ β”‚ Run DistilBERT β”‚
169
+ β”‚ classifier on β”‚
170
+ β”‚ user query β”‚
171
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
172
+ β”‚
173
+ β–Ό
174
+ P(skip_tool) > P(call_tool)?
175
+ β”‚
176
+ Yes ─┴─ No
177
+ β”‚ β”‚
178
+ β–Ό β–Ό
179
+ Gate tools Keep tools
180
+ (remove (pass to
181
+ tools param) upstream)
182
+ ```
183
+
184
+ ## Integration Examples
185
+
186
+ ### With LangChain
187
+
188
+ ```python
189
+ from langchain_openai import ChatOpenAI
190
+
191
+ llm = ChatOpenAI(
192
+ model="gpt-5-mini",
193
+ openai_api_base="http://localhost:8080/v1",
194
+ openai_api_key="your-key"
195
+ )
196
+ ```
197
+
198
+ ### With CrewAI
199
+
200
+ ```python
201
+ from crewai import Agent
202
+
203
+ agent = Agent(
204
+ llm=ChatOpenAI(
205
+ model="gpt-5-mini",
206
+ base_url="http://localhost:8080/v1",
207
+ api_key="your-key"
208
+ )
209
+ )
210
+ ```
211
+
212
+ ### With AutoGen
213
+
214
+ ```python
215
+ from autogen import ConversableAgent
216
+
217
+ agent = ConversableAgent(
218
+ "assistant",
219
+ llm_config={
220
+ "model": "gpt-5-mini",
221
+ "api_base": "http://localhost:8080/v1",
222
+ "api_key": "your-key"
223
+ }
224
+ )
225
+ ```
226
+
227
+ ### With raw HTTP
228
+
229
+ ```bash
230
+ curl http://localhost:8080/v1/chat/completions \
231
+ -H "Content-Type: application/json" \
232
+ -d '{
233
+ "model": "gpt-5-mini",
234
+ "messages": [{"role": "user", "content": "What is 2+2?"}]
235
+ }'
236
+ ```
237
+
238
+ ## Supported Providers
239
+
240
+ | Provider | Models | Key Env Var |
241
+ |---|---|---|
242
+ | OpenAI | gpt-5-mini, gpt-5.2, gpt-5-nano | `OPENAI_API_KEY` |
243
+ | Anthropic | claude-opus-4.7 | `ANTHROPIC_API_KEY` |
244
+ | Google | gemini-2.5-flash, gemini-2.5-pro, gemini-3-pro | `GOOGLE_API_KEY` |
245
+ | DeepSeek | deepseek-v4-flash, deepseek-v3.2 | `DEEPSEEK_API_KEY` |
246
+
247
+ ## Supported Agent Types
248
+
249
+ - **Coding agents** (SWE-bench style) β€” routing floor at tier 2
250
+ - **Research agents** β€” routing to tier 2-3 with retrieval
251
+ - **RAG agents** β€” context compression + cache layout
252
+ - **Tool-use agents** β€” ML tool gating
253
+ - **Legal/security agents** β€” verifier always on for high-risk
254
+ - **Personal assistants** β€” aggressive cost reduction
255
+
256
+ ## Performance
257
+
258
+ Benchmarked on 100 simulated tasks across 5 domains:
259
+
260
+ | Config | Success | Cost | Savings |
261
+ |---|---|---|---|
262
+ | Always frontier | 89% | $10.79 | baseline |
263
+ | Always cheap | 61% | $0.11 | 99% (but -28pp quality) |
264
+ | **Full ACO** | **91%** | **$1.56** | **85.5%** |
265
+
266
+ Full ACO achieves **iso-quality** (actually +2pp better) at 85.5% cost reduction.
267
+
268
+ ## Modules That Matter (Ablation Results)
269
+
270
+ | Module | Impact if Removed | Verdict |
271
+ |---|---|---|
272
+ | Model router | -13pp quality | CRITICAL |
273
+ | Verifier budgeter | -8pp quality | CRITICAL |
274
+ | Retry optimizer | -8pp quality | CRITICAL |
275
+ | Cache layout | +1.8% cost | SAVES MONEY |
276
+ | Tool gate | +2.5% cost | SAVES MONEY |
277
+ | Context budgeter | +0.9% cost, +2pp quality | MARGINAL |
278
+ | Meta-tools | -1pp quality | MARGINAL |
279
+
280
+ ## Limitations
281
+
282
+ 1. **Tool-gater is the only production-ready specialist** (F1=0.92). Tier-router (F1=0.67) and verifier-gater (F1=0.65) are too weak to deploy.
283
+ 2. **Proxy is untested against live LLM APIs** β€” all validation is simulated.
284
+ 3. **Model prices are hardcoded** β€” update `MODEL_REGISTRY` when providers change pricing.
285
+ 4. **No streaming tool-gate** β€” tool gating is skipped for streaming requests.
286
+ 5. **No multi-turn cascade** β€” retry cascade only escalates once.
287
+
288
+ ## Troubleshooting
289
+
290
+ ### "No module named 'transformers'"
291
+ The tool-gater needs transformers + torch. Install:
292
+ ```bash
293
+ pip install transformers torch
294
+ ```
295
+ Or run without ML gating (heuristic fallback works).
296
+
297
+ ### "Upstream 401: Unauthorized"
298
+ Check that your API keys are set:
299
+ ```bash
300
+ echo $OPENAI_API_KEY
301
+ ```
302
+
303
+ ### "Upstream 404: Model not found"
304
+ The model name in your request must match the provider's API. Check `MODEL_REGISTRY` in `aco/proxy.py`.
305
+
306
+ ### Dashboard shows no data
307
+ Send at least one request to `/v1/chat/completions` first. The dashboard auto-refreshes every 3 seconds.
308
+
309
+ ## Files
310
+
311
+ | File | Purpose |
312
+ |---|---|
313
+ | `aco/proxy.py` | Main proxy server (FastAPI) |
314
+ | `aco/router.py` | Model cascade router |
315
+ | `aco/cascade.py` | Cascade router with fallback |
316
+ | `aco/compression.py` | Context compression |
317
+ | `aco/telemetry.py` | Telemetry collector |
318
+ | `aco/tool_gater.py` | ML tool-gating classifier |
319
+ | `benchmark_suite.py` | Simulated benchmark (9 configs Γ— 100 tasks) |
320
+ | `ablation_study.py` | Ablation + frontier report |
321
+ | `smoke_test_proxy.py` | End-to-end proxy smoke test |
322
+ | `train_aco.py` | Reproducible training pipeline |
323
+ | `config.yaml` | Policy configuration |
324
+
325
+ ## Links
326
+
327
+ - **Hub repo**: https://huggingface.co/narcolepticchicken/agent-cost-optimizer
328
+ - **Tool-gater model**: https://huggingface.co/narcolepticchicken/aco-specialists-tool-gater
329
+ - **Training data**: https://huggingface.co/datasets/narcolepticchicken/aco-traces
330
+ - **Truth document**: https://huggingface.co/narcolepticchicken/agent-cost-optimizer/blob/main/TRUTH.md