VLM migration: qwen3.5-9b-vlm → gemma-4-12b across entire harness
- router/router.py: model ID, context window (131K→262K), VRAM comment - litellm_config.yaml: model name updated - gpu-router.conf, gpu-router-docker.conf: pool names, comments - dashboard/dashboard.py: MODELS array refactor for single-point config - README.md: architecture diagram, model table
This commit is contained in:
+18
-18
@@ -10,31 +10,31 @@ GPU_LIGHT_URL = os.environ.get("GPU_LIGHT_URL", "http://192.168.68.110:8080/v1")
|
||||
GPU_SIDECARS = {
|
||||
"qwen3.6-35B-A3B": "http://192.168.68.15:8090",
|
||||
"qwen3.6-27B-code": "http://192.168.68.8:8090",
|
||||
"qwen3.5-9b-vlm": "http://192.168.68.110:8090",
|
||||
"gemma-4-12b": "http://192.168.68.110:8090",
|
||||
}
|
||||
GPU_URLS = {
|
||||
"qwen3.6-35B-A3B": GPU_MOE_URL,
|
||||
"qwen3.6-27B-code": GPU_DENSE_URL,
|
||||
"qwen3.5-9b-vlm": GPU_LIGHT_URL,
|
||||
"gemma-4-12b": GPU_LIGHT_URL,
|
||||
}
|
||||
# Max concurrent requests per GPU (based on llama.cpp --parallel)
|
||||
GPU_MAX_CONCURRENT = {
|
||||
"qwen3.6-35B-A3B": 2, # 2 slots
|
||||
"qwen3.6-27B-code": 2, # 2 slots
|
||||
"qwen3.5-9b-vlm": 2, # 2 slots (12GB VRAM, 4GB headroom)
|
||||
"gemma-4-12b": 2, # 2 slots (7.1GB VRAM)
|
||||
}
|
||||
|
||||
# Context window sizes (tokens) — used for compaction signals
|
||||
GPU_CONTEXT = {
|
||||
"qwen3.6-35B-A3B": 131072,
|
||||
"qwen3.6-27B-code": 98304,
|
||||
"qwen3.5-9b-vlm": 131072,
|
||||
"gemma-4-12b": 262144, # 262K context (gemma-4-12b)
|
||||
}
|
||||
|
||||
TIER_MODELS = {
|
||||
"starter": ["qwen3.5-9b-vlm"],
|
||||
"professional": ["qwen3.6-35B-A3B", "qwen3.6-27B-code", "qwen3.5-9b-vlm"],
|
||||
"enterprise": ["qwen3.6-35B-A3B", "qwen3.6-27B-code", "qwen3.5-9b-vlm"],
|
||||
"starter": ["gemma-4-12b"],
|
||||
"professional": ["qwen3.6-35B-A3B", "qwen3.6-27B-code", "gemma-4-12b"],
|
||||
"enterprise": ["qwen3.6-35B-A3B", "qwen3.6-27B-code", "gemma-4-12b"],
|
||||
}
|
||||
API_KEYS = {
|
||||
"sk-syslog-local-master-key": {"tier": "enterprise", "agent": "admin"},
|
||||
@@ -149,7 +149,7 @@ def route(rd, tier):
|
||||
sys = any(m.get("role")=="system" for m in msgs)
|
||||
turns = len([m for m in msgs if m.get("role") in ("user","assistant")])
|
||||
hints = rd.get("routing_hints",{})
|
||||
allowed = TIER_MODELS.get(tier, ["qwen3.5-9b-vlm"])
|
||||
allowed = TIER_MODELS.get(tier, ["gemma-4-12b"])
|
||||
avail = [m for m in available_models() if m in allowed]
|
||||
if not avail: return {"model": allowed[0], "reason": "all_saturated", "saturated": True}
|
||||
# Check if all available GPUs are at max capacity
|
||||
@@ -168,8 +168,8 @@ def route(rd, tier):
|
||||
return {"model": target, "reason": "explicit"}
|
||||
|
||||
if hints:
|
||||
if hints.get("priority")=="speed" and "qwen3.5-9b-vlm" in avail:
|
||||
return select_best_gpu(["qwen3.5-9b-vlm"], "hint_speed") or {"model":"qwen3.5-9b-vlm","reason":"hint_speed"}
|
||||
if hints.get("priority")=="speed" and "gemma-4-12b" in avail:
|
||||
return select_best_gpu(["gemma-4-12b"], "hint_speed") or {"model":"gemma-4-12b","reason":"hint_speed"}
|
||||
if hints.get("priority")=="quality" and "qwen3.6-27B-code" in avail:
|
||||
return select_best_gpu(["qwen3.6-27B-code"], "hint_quality") or {"model":"qwen3.6-27B-code","reason":"hint_quality"}
|
||||
|
||||
@@ -177,18 +177,18 @@ def route(rd, tier):
|
||||
words = len(first_msg.split()) if isinstance(first_msg, str) else 99
|
||||
|
||||
# TIER 1: Lightweight — single-turn short queries → VLM first
|
||||
if not sys and turns <= 1 and words <= 100 and "qwen3.5-9b-vlm" in avail:
|
||||
if not is_gpu_busy("qwen3.5-9b-vlm"):
|
||||
return {"model":"qwen3.5-9b-vlm","reason":"lightweight"}
|
||||
if not sys and turns <= 1 and words <= 100 and "gemma-4-12b" in avail:
|
||||
if not is_gpu_busy("gemma-4-12b"):
|
||||
return {"model":"gemma-4-12b","reason":"lightweight"}
|
||||
# VLM busy — fall back to Dense, then MoE
|
||||
fallback = [m for m in ["qwen3.6-35B-A3B","qwen3.6-27B-code"] if m in avail]
|
||||
result = select_best_gpu(fallback, "lightweight_fallback")
|
||||
if result: return result
|
||||
|
||||
# TIER 2: Simple conversations — short context, any prompt → VLM preferred
|
||||
if t <= 1000 and turns <= 4 and "qwen3.5-9b-vlm" in avail:
|
||||
if not is_gpu_busy("qwen3.5-9b-vlm"):
|
||||
return {"model":"qwen3.5-9b-vlm","reason":"simple_conv"}
|
||||
if t <= 1000 and turns <= 4 and "gemma-4-12b" in avail:
|
||||
if not is_gpu_busy("gemma-4-12b"):
|
||||
return {"model":"gemma-4-12b","reason":"simple_conv"}
|
||||
# VLM busy — try Dense
|
||||
if "qwen3.6-27B-code" in avail and not is_gpu_busy("qwen3.6-27B-code"):
|
||||
return {"model":"qwen3.6-27B-code","reason":"simple_conv_fallback"}
|
||||
@@ -196,13 +196,13 @@ def route(rd, tier):
|
||||
# TIER 3: Heavy reasoning — extremely large context or very long conversations
|
||||
if t > 50000 or turns > 25:
|
||||
# MoE first (131K context handles heavy sessions), then Dense (98K reasoning), then Light (131K fallback)
|
||||
candidates = [m for m in ["qwen3.6-35B-A3B","qwen3.6-27B-code","qwen3.5-9b-vlm"] if m in avail]
|
||||
candidates = [m for m in ["qwen3.6-35B-A3B","qwen3.6-27B-code","gemma-4-12b"] if m in avail]
|
||||
result = select_best_gpu(candidates, "heavy_reasoning")
|
||||
if result: return result
|
||||
|
||||
# TIER 4: Default — MoE first, VLM helps, Dense last (slow)
|
||||
if t <= 50000:
|
||||
candidates = [m for m in ["qwen3.6-35B-A3B","qwen3.5-9b-vlm","qwen3.6-27B-code"] if m in avail]
|
||||
candidates = [m for m in ["qwen3.6-35B-A3B","gemma-4-12b","qwen3.6-27B-code"] if m in avail]
|
||||
result = select_best_gpu(candidates, "default")
|
||||
if result: return result
|
||||
|
||||
|
||||
Reference in New Issue
Block a user