Repository navigation
Expand file tree
/
Copy pathmodels.yaml
More file actions
351 lines (342 loc) · 21.7 KB
/
Copy pathmodels.yaml
File metadata and controls
351 lines (342 loc) · 21.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
providers:
groq:
base_url: https://api.groq.com/openai/v1
api_key_env: GROQ_API_KEY
# Left at 30 deliberately. The live header reports
# x-ratelimit-limit-requests: 1000, but Groq returns both per-minute and
# per-day request ceilings and the observed reset window (2m52.8s) matches
# neither cleanly, so which one that figure is remains UNVERIFIED. The
# token ceiling below is unambiguous by contrast -- its reset is ~1.1s,
# which is a per-minute window. Raising a budget on ambiguous evidence is
# how this file acquired its two retired providers.
rpm_budget: 30
# MEASURED 2026-09-14 from live response headers, all three configured
# models: x-ratelimit-limit-tokens = 8000. This was 6000, which left 25%
# of the granted budget unused and made every coder call report
# "exceeds the whole ceiling" -- rate_limiter.py:119-126 then admits an
# oversized call only when the bucket is completely full and charges it the
# entire capacity, so each one waited for a full refill.
#
# Still the binding constraint, and raising it does not remove the pacing:
# primary_coder's estimate is ~9872 tokens (MAX_CODER_TOKENS 8000 plus
# ~1900 of prompt), so it exceeds even 8000 and is throttled across
# minutes -- just less. Making it fit would mean lowering MAX_CODER_TOKENS
# to roughly 6000, which risks truncating a multi-file generation; that is
# a separate decision, not a silent change here.
#
# Omit the key entirely for a provider with no published token ceiling (a
# local Ollama, say) -- None disables token accounting rather than
# inventing a limit.
tpm_budget: 8000
# The four blocks below were DEFINED BUT UNUSED: no role referenced them, and
# router.validate_startup only walks the providers a role actually names, so
# declaring them costs nothing at startup. Pointing a role at one is then a
# one-line edit rather than a code change, which is what "any LLM is just
# configuration" is supposed to mean.
#
# `openai` is the first of the three no-longer-fully-dormant: primary_coder
# below now carries a candidate for it, gated behind `enable_env:
# VISHWAKARMA_ENABLE_OPENAI` (config.py's _parse_roles excludes a gated
# candidate from the role's list entirely unless that env var is set to a
# truthy value -- see config.py's _ENABLE_ENV_TRUTHY). OPENAI_API_KEY is not
# present in this account's .env, so the candidate has NOT been live-tested
# from here -- both the flag and the key must be set before relying on it.
# anthropic-compatible and xkiro remain fully dormant for the same reason
# (no key in this account either); wire either the same way once a key
# lands and a live chat-completion call confirms real access.
#
# None of them has been live-tested from this account. That matters, because
# this file's own history records two providers whose advertised free tiers
# turned out not to be entitled (NVIDIA NIM, Cerebras). Treat these as
# syntactically correct starting points, not as verified access.
ollama:
# Local GPU inference. The reason api_key_required exists: Ollama has no
# key at all, and LLMClient.is_available gated purely on a non-empty env
# var, so this provider was unselectable by construction no matter how it
# was configured.
# 127.0.0.1 rather than localhost, deliberately: localhost resolves to BOTH
# ::1 and 127.0.0.1, so a probe against an absent local provider pays two
# connect attempts per try. Measured with the runtime not running -- localhost
# 13.8s, 127.0.0.1 7.3s, and 2.0s once the startup probe stopped retrying
# (#57). Nothing here depends on IPv6.
base_url: http://127.0.0.1:11434/v1
api_key_required: false
# A local runtime has no published ceiling and no billing, so the request
# budget is nominal and the token budget is omitted entirely -- which
# disables token accounting for it rather than inventing a limit. A cap
# invented here would pace a local model for no reason.
rpm_budget: 600
openai:
base_url: https://api.openai.com/v1
api_key_env: OPENAI_API_KEY
# Tier-1 figures. Both ceilings are per-model on OpenAI's side while this
# config is per-provider, so these are the conservative floor across the
# models a role is likely to name, not a quoted limit.
rpm_budget: 500
tpm_budget: 30000
anthropic-compatible:
# Anthropic's own API is not OpenAI-shaped, so this block points at an
# OpenAI-compatible proxy in front of it rather than at api.anthropic.com
# directly -- calling this provider without such a proxy will fail on the
# request shape, not on the key.
base_url: http://127.0.0.1:4000/v1
api_key_env: ANTHROPIC_API_KEY
rpm_budget: 50
tpm_budget: 20000
gemini:
# Google's Gemini, through its OpenAI-COMPATIBLE endpoint rather than its
# native one. The trailing path matters: the native API lives at
# /v1beta and is not OpenAI-shaped, while /v1beta/openai/ is the
# compatibility layer this client can actually speak. Pointing at the
# former fails on the request shape, not on the key -- the same trap the
# anthropic-compatible block above documents.
base_url: https://generativelanguage.googleapis.com/v1beta/openai/
api_key_env: GEMINI_API_KEY
# Deliberately conservative. Gemini publishes its ceilings PER MODEL and
# per tier while this config is per provider, so these are a floor chosen
# to be safe across the flash/pro models a role is likely to name, not a
# quoted limit. The free tier's request ceiling is the tight one --
# single-digit RPM on some models -- so rpm_budget is set low on purpose;
# raise both once the account's real tier is known.
#
# Wired into primary_coder and reasoner (#72) as the middle fallback,
# between Groq and ollama-colab -- see those roles below. This budget is
# what a Groq-exhausted session is pinned to for the REST of that
# session: a plain rate limit does not advance the router past gemini
# (RateLimitExhaustedError is deliberately not an openai.APIError
# subclass, so calling.py re-raises it without calling
# handle_unavailable -- the same protection Groq itself relies on, see
# llm_client.py's RATE_LIMIT_WALL_CLOCK_SECONDS docstring). A gemini call
# that can't be admitted within that wall-clock window hard-fails to the
# caller; it does NOT fall through to ollama-colab's looser rpm_budget:
# 120 / no token cap. This is intentional, not a bug to "fix" into a
# fallthrough. Self-heal retries (max_heal_attempts: 3) share this same
# budget with interactive calls once pinned.
#
# GEMINI_API_KEY is the first credential in either role's chain that can
# actually incur real charges (Groq needs no card; ollama-colab is
# keyless/local) -- set a billing/quota cap on the Google Cloud project
# backing it before relying on this fallback under load.
#
# Live-tested from this account (#72): a direct chat-completion call
# against gemini-3.6-flash returned a real response ("WORKING"). Model
# choice has a history worth recording -- gemini-2.5-pro (the originally
# requested pin) is retired for new users (404, Google's own error
# message points at gemini-3.1-pro-preview); gemini-3.1-pro-preview
# resolves but its RateLimitError body is explicit and conclusive:
# "generativelanguage.googleapis.com/generate_content_free_tier_requests,
# limit: 0, model: gemini-3.1-pro" -- the free tier's quota for this
# model is not tight, it is zero, confirmed from an account with a paid
# Google Pro subscription (an AI Studio key's quota tracks whether its
# backing Cloud project has billing enabled, not a separate consumer
# subscription -- Pro does not raise this key's limit by itself);
# gemini-2.5-flash is also retired (404, points at gemini-3.6-flash);
# gemini-3.6-flash is the first candidate that actually resolved with a
# real free-tier quota. Read the warning above about NVIDIA NIM and
# Cerebras: gemini is not one of them, confirmed working.
rpm_budget: 10
tpm_budget: 250000
xkiro:
# OpenAI-compatible, 11 models, all documented as $0 in / $0 out, using
# vendor/model naming (e.g. mistralai/devstral-medium). #40 records the
# full catalog and a recommended role->model mapping; nothing below wires
# a role, matching this file's own "gemini decision" precedent -- the key
# is not in .env yet, and a role pointing at an unreachable provider fails
# at startup rather than degrading gracefully.
base_url: https://api.xkiro.com/v1
api_key_env: XKIRO_API_KEY
# UNVERIFIED, and deliberately conservative -- rpm_budget is a required
# field (config.py raises ConfigError without one), so this is a
# syntactically-necessary placeholder, not a quoted limit. #40 states
# xkiro's actual rate ceilings are unknown and explicitly must not be
# invented -- a stronger uncertainty than gemini's case above, where
# Google at least publishes per-model ceilings to floor a guess against.
# tpm_budget is deliberately OMITTED rather than given a placeholder
# number, the same way the ollama block above omits it: config.py's own
# docstring prefers disabling token accounting over inventing a ceiling
# when no real one is known. Read the warning on the gemini block just
# above: this file's history is two providers (NVIDIA NIM, Cerebras)
# whose advertised free tiers were not actually entitled to this account
# -- treat this block the same way, a starting point, not verified access.
rpm_budget: 10
#
# Recommended role -> model mapping from #40 (record only -- flip a role
# to one of these as a one-line edit once XKIRO_API_KEY lands and a live
# chat-completion smoke test confirms real access):
# router_fast -> mistralai/ministral-8b (fallback: mistralai/ministral-3b)
# reasoner -> mistralai/mistral-large-2512 (fallback: mistralai/mistral-small-2603)
# primary_coder -> mistralai/devstral-medium (fallback: mistralai/mistral-medium-3.5)
# fallback_long_context -> sensenova/sensenova-6.8-flash-lite (fallback: mistralai/mistral-medium-3.5)
# Small-output roles (router_fast) MUST use a non-reasoning model:
# calling.py's _light_reasoning_effort_for only recognizes qwen/* and
# openai/gpt-oss* prefixes, so an xkiro reasoning-capable model would
# never receive reasoning_effort and could burn its whole completion
# budget on an uncapped <think> trace -- every model picked above is
# explicitly documented as non-reasoning for exactly this reason.
ollama-colab:
# Colab-hosted Ollama, reached over an ngrok tunnel. ngrok, not
# cloudflared: a cloudflared quick tunnel (trycloudflare.com) was tried
# first (#71) and consistently returned 403 Forbidden directly from
# Cloudflare's edge on every request -- reproduced across 3 fresh
# tunnels, both QUIC and HTTP/2, from two independent networks. ngrok
# works, with one catch confirmed live in ollama.log: Ollama's own
# server-side Host-header check (a DNS-rebinding protection, unrelated to
# OLLAMA_ORIGINS, which only governs browser CORS Origin headers) 403s
# the tunnel's public hostname unless ngrok.connect() is called with
# host_header="localhost:11434" -- see colab/ollama_colab_server.ipynb.
# The real URL is session-scoped (Colab disconnects after ~12h or on
# idle -- and sometimes silently resets the backend while the notebook UI
# still shows "Connected", wiping the installed binary and pulled models,
# not just the tunnel), so it is read from OLLAMA_COLAB_BASE_URL (set in
# .env, which is already gitignored) rather than written here --
# models.yaml is git-tracked and a live unauthenticated tunnel URL has no
# business in commit history. Update the env var after every Colab
# restart. The literal below is an RFC 2606 .invalid placeholder that
# never resolves -- inert until this candidate is actually reached (this
# is the last candidate in its roles, so a healthy Groq means it may
# never be probed that session), at which point it fails gracefully as an
# ordinary candidate-skip via the existing reachability-error handling,
# rather than silently pointing calls at a stale host.
base_url: https://not-set.invalid/v1
base_url_env: OLLAMA_COLAB_BASE_URL
api_key_required: false
# No published ceiling (free Colab GPU, single session) and no billing --
# nominal budget, not a quoted limit. Lower than the local ollama block's
# 600 because requests also cross the tunnel's network hop.
rpm_budget: 120
# Omitted deliberately, same reasoning as the local ollama block: no real
# ceiling exists to floor a number against, so this disables token
# accounting rather than inventing one.
# Switched fully to Groq (2026-09-11) -- NVIDIA NIM removed entirely.
# NVIDIA's free tier was blocked by two separate, unresolved issues: a
# platform-level 403 "Authorization failed" bug on Personal-org accounts,
# and most of its catalog returning 404 "Function not found for account"
# (listed in /v1/models but never actually entitled for this account).
# Groq's free tier is an ongoing rate-limited tier (~30 RPM configured, 8K TPM measured,
# ~14.4K RPD), not a burnable dollar credit, with no card required.
#
# 2026-09-11: llama-3.1-8b-instant and llama-3.3-70b-versatile are NOT in
# this account's live catalog (checked via /v1/models) despite being
# documented on Groq's docs site -- dropped entirely rather than left as
# dead candidates. Every model ID below was live-tested with a real chat
# completion call and confirmed working (sub-2-second responses, correct
# code) before being pinned here.
#
# 2026-09-11: tried adding Cerebras as a fallback provider (cloud.cerebras.ai
# markets 1M tokens/day free, no card required) and removed it again the
# same day -- live-tested account is actually pay-as-you-go with a $0.00
# balance and no active subscription, so every model returned 402 "Payment
# required" regardless of the dashboard's Limits tab showing quota tables
# for it. Same failure pattern as NVIDIA NIM above: advertised free tier,
# not actually entitled for this account. Do not re-add without a live
# successful chat-completion call confirming real access first.
# --- Tool-calling capability + dispatch budget (multi-agent dispatch_agent tool) ---
#
# supports_tools on a role candidate below is a PUBLISHER-DOCUMENTED capability claim
# (the provider's own docs say this model accepts OpenAI-style `tools=`), not the same
# thing as this file's existing "live-tested from this account" language above, which
# is about reachability/quota. A round-trip tool-call smoke test (send a trivial
# `tools=` schema, confirm the model actually returns a `tool_calls` response instead
# of silently ignoring the field) has NOT been run against any candidate below from
# this account. Until one has, last_verified stays null and validate_startup() emits a
# one-time WARNING (never a hard failure -- omitting `tools=` for an unverified
# candidate is always safe; the call just behaves exactly like it does today) for any
# supports_tools: true entry whose last_verified is null or >90 days old. Flip
# last_verified to the ISO date of an actual confirmed round trip, per-candidate, the
# same way this file's other "live-tested" notes work.
dispatch:
# Hard per-root-task ceiling on tokens spent inside dispatch_agent's nested
# call_role() invocations, keyed by provider tier. Depth (nesting_depth <= 2) and
# dispatch_chain (visited-agent set, no repeat dispatch within one root task) bound
# *fan-out*; this bounds *cost* -- two nested calls at a provider's max context can
# otherwise multiply spend per root task with no ceiling. Deliberately conservative
# defaults, same spirit as this file's rpm_budget/tpm_budget floors above: a budget
# invented here paces the dispatch_agent tool for no measured reason, so these are
# placeholders to revisit once a real dispatch workload has run, not quoted limits.
budget_tokens_by_tier:
groq: 8000 # matches groq's own tpm_budget above -- one nested call max
gemini: 8000 # conservative floor; gemini's own tpm_budget (250000) is far
# looser, but dispatch is a bounded sub-task, not the main call
ollama-colab: 4000 # tunnel hop + shared Colab GPU -- smaller nested budget
ollama: 8000
openai: 8000
anthropic-compatible: 8000
xkiro: 8000
default_budget_tokens: 8000 # used for any provider tier not listed above
roles:
primary_coder:
# Largest available model -- confirmed ~1.2s response with clean,
# correct code on a live test call.
# supports_tools: true -- Groq documents tool use (OpenAI-compatible `tools=`) for
# its openai/gpt-oss-* models. NOT round-trip verified from this account (see
# dispatch: block comment above) -- last_verified stays null until it is.
- {provider: groq, model: openai/gpt-oss-120b, supports_tools: true, last_verified: null}
- {provider: groq, model: openai/gpt-oss-20b, supports_tools: true, last_verified: null}
# Mid-chain fallback once both Groq candidates are exhausted (#72) -- see
# the gemini provider block above for the rate-limit-pinning tradeoff.
# supports_tools: true -- Gemini's OpenAI-compat endpoint documents function
# calling. NOT round-trip verified from this account.
- {provider: gemini, model: gemini-3.6-flash, supports_tools: true, last_verified: null}
# Last-resort fallback once gemini is also exhausted -- see the
# ollama-colab provider block above for the tunnel/env-var setup.
# Live-tested from this account (#71): a direct /api/generate call
# against the Colab-hosted instance returned a real completion. Chosen
# over deepseek-v4-pro, which turned out to be Ollama's *cloud*-hosted
# tier (returns 401 Unauthorized without an ollama.com sign-in) rather
# than a locally-run model -- deepseek-coder-v2:16b is a real MoE model
# (16B total / ~2.4B active params) that fits the T4's ~15GB VRAM and
# runs entirely on the Colab GPU, no account needed.
# supports_tools: false -- deepseek-coder-v2 tool-calling support through
# Ollama's OpenAI-compat layer depends on the pulled model's chat template and
# the installed Ollama version; unconfirmed either way for this deployment, so
# this stays false (the conservative default: omit `tools=` rather than guess)
# until a round-trip test proves otherwise.
- {provider: ollama-colab, model: deepseek-coder-v2:16b, supports_tools: false, last_verified: null}
# Gap B (#40-series adaptive-routing work): an experimental, opt-in last
# resort behind ollama-colab, gated behind enable_env so it is invisible
# (excluded from this list entirely) unless VISHWAKARMA_ENABLE_OPENAI is
# set. gpt-4o-mini is OpenAI's smallest current chat-completions model --
# picked as the conservative starting point for an UNVERIFIED candidate,
# same reasoning the xkiro block above documents for its own picks.
# NOT live-tested from this account: OPENAI_API_KEY is absent from
# .env here. Do not rely on this candidate under load until both the key
# and a real chat-completion smoke test confirm access, mirroring the
# gemini/ollama-colab precedent recorded above.
# supports_tools: true -- OpenAI's own API documents tool calling for
# gpt-4o-mini; still gated by the same enable_env + no-key caveat above, and
# NOT round-trip verified from this account.
- {provider: openai, model: gpt-4o-mini, enable_env: VISHWAKARMA_ENABLE_OPENAI, supports_tools: true, last_verified: null}
router_fast:
# Smallest/fastest model -- confirmed ~0.3s response, exactly the
# "cheap and quick" role needs (classification only).
# Deliberately NOT given an ollama-colab fallback: this role's small
# max_tokens budget is exactly where calling.py's light-reasoning
# prefix gap (see _LIGHT_REASONING_EFFORT_BY_MODEL_PREFIX) bites hardest
# on an unverified reasoning-capable model -- same reasoning the xkiro
# block above documents for its own router_fast candidates.
# router_fast never carries the dispatch_agent tool (see orchestrator.py) --
# supports_tools is set for consistency/future-proofing only, unused today.
- {provider: groq, model: openai/gpt-oss-20b, supports_tools: true, last_verified: null}
- {provider: groq, model: openai/gpt-oss-120b, supports_tools: true, last_verified: null}
reasoner:
# qwen3.6-27b visibly emits a <think>...</think> reasoning trace before
# its answer -- the closest fit on this catalog for the self-heal
# "diagnose this failure" step, which benefits from an explicit
# reasoning pass.
# supports_tools: true -- Groq documents tool use for qwen/* models on its
# catalog. NOT round-trip verified from this account.
- {provider: groq, model: qwen/qwen3.6-27b, supports_tools: true, last_verified: null}
- {provider: groq, model: openai/gpt-oss-120b, supports_tools: true, last_verified: null}
# Mid-chain fallback -- see primary_coder's gemini entry above.
- {provider: gemini, model: gemini-3.6-flash, supports_tools: true, last_verified: null}
# Last-resort fallback -- see primary_coder's ollama-colab entry above
# for why deepseek-coder-v2:16b was chosen and live-verified over
# deepseek-v4-pro.
- {provider: ollama-colab, model: deepseek-coder-v2:16b, supports_tools: false, last_verified: null}
fallback_long_context:
# fallback_long_context never carries the dispatch_agent tool (see
# orchestrator.py) -- supports_tools set for consistency only, unused today.
- {provider: groq, model: openai/gpt-oss-120b, supports_tools: true, last_verified: null}
- {provider: groq, model: openai/gpt-oss-20b, supports_tools: true, last_verified: null}
max_heal_attempts: 3
heal_timeout_seconds: 300