[chore] Bump local LLM glm-5→glm-5.2 + swap Ollama fleet defaults off minimax

- llm_catalog: OLLAMA_DEFAULT_MODEL minimax-m3:cloud → kimi-k2.7-code:cloud;
  role defaults kimi-k2.6→kimi-k2.7-code, developer minimax→kimi, product_owner/
  ceo kimi→glm-5.2, documenter glm→kimi; GLM 5.1→5.2 comment fix.
- config + .env.example + docker-compose{.yml,.yaml,.registry.yml} + docs +
  memory_distiller + optimal_brain: glm-5:cloud → glm-5.2:cloud.
- panel ai-routing-card: typed SelfHostedModel/boolean annotations; drop the
  stale "Minimax M3 default" string (default is now catalog-driven).
- tests: glm-5:cloud → glm-5.2:cloud in pricing + rate-limit-retry fixtures.
This commit is contained in:
Renn F
2026-06-28 02:02:33 +02:00
parent a978efb3f9
commit 676a87985f
16 changed files with 43 additions and 42 deletions
+1 -1
View File
@@ -80,7 +80,7 @@ ROBOCO_REDIS_DB=0
# For docker compose use the container name (roboco-ollama); locally, localhost.
ROBOCO_OLLAMA_BASE_URL=http://localhost:11434
ROBOCO_LOCAL_LLM_BASE_URL=http://localhost:11434/v1
ROBOCO_LOCAL_LLM_MODEL=glm-5:cloud
ROBOCO_LOCAL_LLM_MODEL=glm-5.2:cloud
ROBOCO_DEFAULT_EMBEDDING_MODEL=qwen3-embedding:0.6b
# =============================================================================
+3 -3
View File
@@ -80,7 +80,7 @@ pnpm test
| Cache/Queue | Redis |
| Container Runtime | Docker + Docker Compose |
| Cloud LLM | Claude API (claude-opus-4-6) + xAI Grok (official `grok` CLI, SuperGrok subscription) |
| Local LLM | Ollama (glm-5:cloud for RAG/hybrid retrieval) |
| Local LLM | Ollama (glm-5.2:cloud for RAG/hybrid retrieval) |
| Embeddings | qwen3-embedding:0.6b (1024 dim) |
| Frontend | Next.js 16 + TypeScript + Tailwind + Radix UI (in `panel/`) |
| Edge / Proxy | nginx (single entry point on port 3000) |
@@ -464,7 +464,7 @@ ROBOCO_RAG_USE_HYBRID_SEARCH=true
# AI/LLM
ROBOCO_DEFAULT_EMBEDDING_MODEL=qwen3-embedding:0.6b
ROBOCO_LOCAL_LLM_MODEL=glm-5:cloud
ROBOCO_LOCAL_LLM_MODEL=glm-5.2:cloud
ROBOCO_LOCAL_LLM_BASE_URL=http://roboco-ollama:11434/v1
ROBOCO_OLLAMA_BASE_URL=http://roboco-ollama:11434
```
@@ -524,7 +524,7 @@ The startup order is critical due to dependencies:
postgres ──┐
redis ─────┼──> ollama ──> ollama-init ──> orchestrator ──> panel ──> nginx
│ │ │
│ │ └── Pulls qwen3-embedding:0.6b, glm-5:cloud
│ │ └── Pulls qwen3-embedding:0.6b, glm-5.2:cloud
│ └── Healthcheck: ollama list
└── Healthcheck: pg_isready, redis-cli ping
```
+2 -2
View File
@@ -178,7 +178,7 @@ ROBOCO_WORKSPACE_AUTO_CLONE=true
# RAG/LLM
ROBOCO_LOCAL_LLM_BASE_URL=http://roboco-ollama:11434/v1
ROBOCO_LOCAL_LLM_MODEL=glm-5:cloud
ROBOCO_LOCAL_LLM_MODEL=glm-5.2:cloud
# Feature flags (default-off unless noted; toggle from Settings → Feature Flags)
ROBOCO_CONVENTIONS_ENABLED=false # per-project architectural conventions standard
@@ -283,7 +283,7 @@ uv run mypy roboco/
| Cache/Queue | Redis |
| RAG Engine | in-house (asyncpg + pgvector, hybrid retrieval) |
| Embeddings | qwen3-embedding:0.6b (Ollama) |
| Local LLM | Ollama (glm-5:cloud) |
| Local LLM | Ollama (glm-5.2:cloud) |
| Cloud LLM | Claude API (Anthropic) + xAI Grok (official `grok` CLI, SuperGrok subscription) |
| Package Manager | uv |
+4 -4
View File
@@ -96,14 +96,14 @@ services:
status=$$(echo "$$line" | grep -o '"status":"[^"]*"' | cut -d'"' -f4)
[ -n "$$status" ] && echo " $$status"
done || echo " (pull failed — relying on the cached model)"
echo "=== Pulling LLM model (glm-5:cloud) — best-effort ==="
curl -sN http://ollama:11434/api/pull -d '{"name":"glm-5:cloud"}' | while read -r line; do
echo "=== Pulling LLM model (glm-5.2:cloud) — best-effort ==="
curl -sN http://ollama:11434/api/pull -d '{"name":"glm-5.2:cloud"}' | while read -r line; do
status=$$(echo "$$line" | grep -o '"status":"[^"]*"' | cut -d'"' -f4)
[ -n "$$status" ] && echo " $$status"
done || echo " (pull failed — relying on the cached model)"
echo "=== Verifying models are present (the real success gate) ==="
curl -sf http://ollama:11434/api/tags | grep -q "qwen3-embedding" || { echo "FATAL: qwen3-embedding missing and could not be pulled"; exit 1; }
curl -sf http://ollama:11434/api/tags | grep -q "glm-5" || { echo "FATAL: glm-5 missing and could not be pulled"; exit 1; }
curl -sf http://ollama:11434/api/tags | grep -q "glm-5.2" || { echo "FATAL: glm-5.2 missing and could not be pulled"; exit 1; }
echo "=== All models ready! ==="
# --------------------------------------------------------------------------
@@ -204,7 +204,7 @@ services:
ROBOCO_AGENT_AUTH_SECRET: ${ROBOCO_AGENT_AUTH_SECRET:?ROBOCO_AGENT_AUTH_SECRET is required}
ROBOCO_AGENT_AUTH_REQUIRED: ${ROBOCO_AGENT_AUTH_REQUIRED:-false}
ROBOCO_LOCAL_LLM_BASE_URL: http://roboco-ollama:11434/v1
ROBOCO_LOCAL_LLM_MODEL: glm-5:cloud
ROBOCO_LOCAL_LLM_MODEL: glm-5.2:cloud
ROBOCO_DEFAULT_EMBEDDING_MODEL: qwen3-embedding:0.6b
ROBOCO_OLLAMA_BASE_URL: http://roboco-ollama:11434
# Spawn the PRE-BUILT agent images from the same registry instead of
+4 -4
View File
@@ -83,14 +83,14 @@ services:
status=$$(echo "$$line" | grep -o '"status":"[^"]*"' | cut -d'"' -f4)
[ -n "$$status" ] && echo " $$status"
done || echo " (pull failed — relying on the cached model)"
echo "=== Pulling LLM model (glm-5:cloud) — best-effort ==="
curl -sN http://ollama:11434/api/pull -d '{"name":"glm-5:cloud"}' | while read -r line; do
echo "=== Pulling LLM model (glm-5.2:cloud) — best-effort ==="
curl -sN http://ollama:11434/api/pull -d '{"name":"glm-5.2:cloud"}' | while read -r line; do
status=$$(echo "$$line" | grep -o '"status":"[^"]*"' | cut -d'"' -f4)
[ -n "$$status" ] && echo " $$status"
done || echo " (pull failed — relying on the cached model)"
echo "=== Verifying models are present (the real success gate) ==="
curl -sf http://ollama:11434/api/tags | grep -q "qwen3-embedding" || { echo "FATAL: qwen3-embedding missing and could not be pulled"; exit 1; }
curl -sf http://ollama:11434/api/tags | grep -q "glm-5" || { echo "FATAL: glm-5 missing and could not be pulled"; exit 1; }
curl -sf http://ollama:11434/api/tags | grep -q "glm-5.2" || { echo "FATAL: glm-5.2 missing and could not be pulled"; exit 1; }
echo "=== All models ready! ==="
# ==========================================================================
@@ -303,7 +303,7 @@ services:
ROBOCO_AGENT_AUTH_REQUIRED: ${ROBOCO_AGENT_AUTH_REQUIRED:-false}
# Ollama (use container name)
ROBOCO_LOCAL_LLM_BASE_URL: http://roboco-ollama:11434/v1
ROBOCO_LOCAL_LLM_MODEL: glm-5:cloud
ROBOCO_LOCAL_LLM_MODEL: glm-5.2:cloud
ROBOCO_DEFAULT_EMBEDDING_MODEL: qwen3-embedding:0.6b
ROBOCO_OLLAMA_BASE_URL: http://roboco-ollama:11434
# Host paths for spawning agent containers (required for Docker-in-Docker)
+4 -4
View File
@@ -83,14 +83,14 @@ services:
status=$$(echo "$$line" | grep -o '"status":"[^"]*"' | cut -d'"' -f4)
[ -n "$$status" ] && echo " $$status"
done || echo " (pull failed — relying on the cached model)"
echo "=== Pulling LLM model (glm-5:cloud) — best-effort ==="
curl -sN http://ollama:11434/api/pull -d '{"name":"glm-5:cloud"}' | while read -r line; do
echo "=== Pulling LLM model (glm-5.2:cloud) — best-effort ==="
curl -sN http://ollama:11434/api/pull -d '{"name":"glm-5.2:cloud"}' | while read -r line; do
status=$$(echo "$$line" | grep -o '"status":"[^"]*"' | cut -d'"' -f4)
[ -n "$$status" ] && echo " $$status"
done || echo " (pull failed — relying on the cached model)"
echo "=== Verifying models are present (the real success gate) ==="
curl -sf http://ollama:11434/api/tags | grep -q "qwen3-embedding" || { echo "FATAL: qwen3-embedding missing and could not be pulled"; exit 1; }
curl -sf http://ollama:11434/api/tags | grep -q "glm-5" || { echo "FATAL: glm-5 missing and could not be pulled"; exit 1; }
curl -sf http://ollama:11434/api/tags | grep -q "glm-5.2" || { echo "FATAL: glm-5.2 missing and could not be pulled"; exit 1; }
echo "=== All models ready! ==="
# ==========================================================================
@@ -303,7 +303,7 @@ services:
ROBOCO_AGENT_AUTH_REQUIRED: ${ROBOCO_AGENT_AUTH_REQUIRED:-false}
# Ollama (use container name)
ROBOCO_LOCAL_LLM_BASE_URL: http://roboco-ollama:11434/v1
ROBOCO_LOCAL_LLM_MODEL: glm-5:cloud
ROBOCO_LOCAL_LLM_MODEL: glm-5.2:cloud
ROBOCO_DEFAULT_EMBEDDING_MODEL: qwen3-embedding:0.6b
ROBOCO_OLLAMA_BASE_URL: http://roboco-ollama:11434
# Host paths for spawning agent containers (required for Docker-in-Docker)
+1 -1
View File
@@ -74,7 +74,7 @@ A feature flag set in `.env` takes effect on the next backend restart. The env-g
| `ROBOCO_ANTHROPIC_API_KEY` | *(unset)* | Optional Anthropic key. Agents use the mounted Claude Code auth, not a metered key. |
| `ROBOCO_DEFAULT_EMBEDDING_MODEL` | `qwen3-embedding:0.6b` | Embedding model (1024-dim). |
| `ROBOCO_EMBEDDING_DIMENSIONS` | `1024` | Embedding dimensions — must match the model. |
| `ROBOCO_LOCAL_LLM_MODEL` | `glm-5:cloud` | Local LLM for RAG answer synthesis. |
| `ROBOCO_LOCAL_LLM_MODEL` | `glm-5.2:cloud` | Local LLM for RAG answer synthesis. |
| `ROBOCO_LOCAL_LLM_BASE_URL` | `http://roboco-ollama:11434/v1` | Ollama OpenAI-compatible endpoint. |
| `ROBOCO_OLLAMA_BASE_URL` | `http://roboco-ollama:11434` | Ollama native endpoint (embeddings, model management). |
+1 -1
View File
@@ -57,7 +57,7 @@ Environment variables for RoboCo (prefix: `ROBOCO_`).
| Variable | Default | Description |
|----------|---------|-------------|
| `ROBOCO_LOCAL_LLM_MODEL` | `glm-5:cloud` | Local LLM for RAG |
| `ROBOCO_LOCAL_LLM_MODEL` | `glm-5.2:cloud` | Local LLM for RAG |
| `ROBOCO_LOCAL_LLM_BASE_URL` | `http://roboco-ollama:11434/v1` | OpenAI-compat API |
| `ROBOCO_OLLAMA_BASE_URL` | `http://roboco-ollama:11434` | Native Ollama API |
@@ -43,6 +43,7 @@ import {
} from "lucide-react";
import { toast } from "sonner";
import { AssignmentScope, ModelProvider } from "@/types";
import type { SelfHostedModel } from "@/lib/api/providers";
import type { RoutingMode, SelfHostedTestResult } from "@/lib/api/providers";
import { SelfHostedSection } from "@/components/settings/self-hosted-section";
import { Badge } from "@/components/ui/badge";
@@ -288,7 +289,7 @@ export function AIRoutingCard() {
return;
}
const needsSelfHosted = Object.values(per_agent).some((m) =>
selfHostedModels.find((sh) => sh.model_name === m),
selfHostedModels.find((sh: SelfHostedModel) => sh.model_name === m),
);
if (needsSelfHosted && !isSelfHostedConnected) {
toast.error(
@@ -350,7 +351,7 @@ export function AIRoutingCard() {
<label className="flex items-center gap-2 text-xs text-muted-foreground cursor-pointer">
<Checkbox
checked={clearGrokKey}
onCheckedChange={(checked) => {
onCheckedChange={(checked: boolean) => {
const next = checked === true;
setClearGrokKey(next);
if (next) setGrokKey("");
@@ -402,7 +403,7 @@ export function AIRoutingCard() {
<label className="flex items-center gap-2 text-xs text-muted-foreground cursor-pointer">
<Checkbox
checked={clearKey}
onCheckedChange={(checked) => {
onCheckedChange={(checked: boolean) => {
const next = checked === true;
setClearKey(next);
if (next) setApiKey("");
@@ -457,7 +458,7 @@ export function AIRoutingCard() {
label="Ollama"
description={
hasOllamaKey
? "Every agent uses Ollama Cloud (Minimax M3 default)."
? "Every agent uses Ollama Cloud." // TODO: Add dynamic default model name based on llm_catalog.py
: "Save the Ollama key first."
}
active={currentMode === "ollama"}
@@ -529,7 +530,7 @@ export function AIRoutingCard() {
<SelectItem value="__clear__">
(use server default)
</SelectItem>
{selfHostedModels.map((m) => (
{selfHostedModels.map((m: SelfHostedModel) => (
<SelectItem key={m.model_name} value={m.model_name}>
{m.display_name}
{m.display_name !== m.model_name
@@ -641,7 +642,7 @@ export function AIRoutingCard() {
<ProviderBadge variant="self-hosted" />
Self-Hosted
</SelectLabel>
{selfHostedModels.map((m) => (
{selfHostedModels.map((m: SelfHostedModel) => (
<SelectItem key={m.model_name} value={m.model_name}>
{m.display_name}
</SelectItem>
+1 -1
View File
@@ -162,7 +162,7 @@ class Settings(BaseSettings):
# Local LLM for RAG answer synthesis
local_llm_model: str = Field(
default="glm-5:cloud",
default="glm-5.2:cloud",
description="Local LLM for RAG answer synthesis "
"(non-thinking models are faster)",
)
+9 -9
View File
@@ -102,31 +102,31 @@ def provider_type_for_model(model_name: str) -> ModelProvider | None:
# 200-300 sequential tool calls. Best at reasoning, orchestration, tool use.
# MiniMax M3 — SWE-Bench 73.8%, SWE-Pro 56.2%, 10B active params (fastest,
# cheapest). Explicitly "built for Max coding & agentic workflows".
# GLM 5.1 — SWE-Bench 77.8% (highest of the three, 94.6% of Claude Opus 4.6),
# GLM 5.2 — SWE-Bench 77.8% (highest of the three, 94.6% of Claude Opus 4.6),
# self-correcting across hundreds of iterations, strong creative writing.
OLLAMA_ROLE_DEFAULTS: dict[str, str] = {
# High-volume agentic coding — M3 is purpose-built for this.
"developer": "minimax-m3:cloud",
"developer": "kimi-k2.7-code:cloud",
# Deep code review — GLM 5.2 has the highest SWE-Bench and iterates thoroughly.
"qa": "glm-5.2:cloud",
# Orchestration + tool coordination — Kimi K2.6's Agent Swarm is the exact fit.
"cell_pm": "kimi-k2.6:cloud",
"main_pm": "kimi-k2.6:cloud",
"cell_pm": "kimi-k2.7-code:cloud",
"main_pm": "kimi-k2.7-code:cloud",
# Quality reasoning — Kimi K2.6 leads HLE by a wide margin.
"auditor": "kimi-k2.6:cloud",
"auditor": "kimi-k2.7-code:cloud",
# Product reasoning — same profile as PM work.
"product_owner": "kimi-k2.6:cloud",
"product_owner": "glm-5.2:cloud",
# Writing with code-context — GLM 5.2's creative writing + SWE-Bench combo.
"documenter": "glm-5.2:cloud",
"documenter": "kimi-k2.7-code:cloud",
# Stylistic writing — GLM 5.2's creative-writing strength.
"head_marketing": "glm-5.2:cloud",
# CEO is human-in-the-loop; keep an entry in case someone forces
# a route to it, but the Settings UI intentionally excludes it.
"ceo": "kimi-k2.6:cloud",
"ceo": "glm-5.2:cloud",
}
# The Ollama model picked for "pure Ollama" mode's GLOBAL row when the
# caller doesn't override. Minimax M3 wins as the generalist because it has
# the strongest reasoning/tool-use profile and can fall back to coding/writing
# adequately if a role ends up mapped to the global default.
OLLAMA_DEFAULT_MODEL: str = "minimax-m3:cloud"
OLLAMA_DEFAULT_MODEL: str = "kimi-k2.7-code:cloud"
+1 -1
View File
@@ -2,7 +2,7 @@
Replaces the noisy raw-notes / duration / commit-count capture with one curated
lesson in a fixed Problem -> Approach -> Gotcha shape (<=120 words). Runs on the
LOCAL model only (glm-5:cloud via the OpenAI-compatible endpoint) never a cloud
LOCAL model only (glm-5.2:cloud via the OpenAI-compatible endpoint) never a cloud
LLM in the hot path. Best-effort: any failure (LLM down, empty output) returns
None and the caller records nothing rather than storing junk.
"""
@@ -68,7 +68,7 @@ class IndexConfig:
chunk_size: int = 512
chunk_overlap: int = 50
embedding_model: str = "qwen3-embedding:0.6b"
llm_model: str = "glm-5:cloud"
llm_model: str = "glm-5.2:cloud"
llm_base_url: str = "http://roboco-ollama:11434/v1"
@classmethod
@@ -42,7 +42,7 @@ DEFAULT_BATCH_SIZE = 32 # default batch size for Ollama embedding requests
# Keep the embedding model resident in Ollama. It runs on CPU and Ollama's
# default 5-min idle unload means a `say` after an idle window pays a cold 2.4 GB
# reload before embedding; under contention with glm-5:cloud that overran the
# reload before embedding; under contention with glm-5.2:cloud that overran the
# embed retry window and dropped the background conversation ingest. -1 = never
# unload (sent as `keep_alive` on every /api/embed request).
EMBED_KEEP_ALIVE = -1
+2 -2
View File
@@ -360,7 +360,7 @@ class TestProviderAwareness:
def test_ollama_cloud_model_returns_zero(self) -> None:
"""Ollama Cloud (``:cloud`` tag) is subscription-billed, not per token."""
cost = calculate_cost("glm-5:cloud", tokens_input=_M, tokens_output=_M)
cost = calculate_cost("glm-5.2:cloud", tokens_input=_M, tokens_output=_M)
assert cost == _ZERO_COST
def test_bare_local_model_returns_zero(self) -> None:
@@ -373,5 +373,5 @@ class TestProviderAwareness:
assert _is_anthropic_model(name) is True, name
def test_is_anthropic_model_false_for_non_claude_names(self) -> None:
for name in ("ollama/llama3", "glm-5:cloud", "qwen3-embedding", "gpt-4o"):
for name in ("ollama/llama3", "glm-5.2:cloud", "qwen3-embedding", "gpt-4o"):
assert _is_anthropic_model(name) is False, name
+1 -1
View File
@@ -130,7 +130,7 @@ def _make_journal_plugin() -> JournalsIndexPlugin:
plugin = JournalsIndexPlugin.__new__(JournalsIndexPlugin)
plugin._config = MagicMock()
plugin._config.llm_base_url = "http://ollama-test:11434/v1"
plugin._config.llm_model = "glm-5:cloud"
plugin._config.llm_model = "glm-5.2:cloud"
plugin._store = MagicMock()
plugin._chunker = MagicMock()
plugin._embedder = MagicMock()