common: runbook migration provider OpenCode Go (+ fallback OpenRouter)

Hermes x3 + family-help. Inclut le gotcha reasoning max_tokens et la
topologie stacks Portainer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Nabil Derouiche 2026-06-14 18:08:58 +01:00
parent 46515d0459
commit b29616b918
2 changed files with 107 additions and 0 deletions

View File

@ -12,6 +12,7 @@
| [Acces Bifrost (passerelle LLM, vision/OCR)](common/bifrost-access.md) | 2026-06-14 | infra, bifrost, llm, vision, x-bf-vk | | [Acces Bifrost (passerelle LLM, vision/OCR)](common/bifrost-access.md) | 2026-06-14 | infra, bifrost, llm, vision, x-bf-vk |
| [Generation / edition d'images IA (nano-banana)](common/openrouter-image-gen.md) | 2026-06-14 | infra, openrouter, image, nano-banana | | [Generation / edition d'images IA (nano-banana)](common/openrouter-image-gen.md) | 2026-06-14 | infra, openrouter, image, nano-banana |
| [Gotenberg HTML->PDF (piege police web)](common/gotenberg-pdf.md) | 2026-06-14 | infra, gotenberg, pdf, fonts | | [Gotenberg HTML->PDF (piege police web)](common/gotenberg-pdf.md) | 2026-06-14 | infra, gotenberg, pdf, fonts |
| [Migration provider OpenCode Go (+ fallback OpenRouter)](common/migration-provider-opencode-go.md) | 2026-06-14 | infra, opencode, hermes, family-help, fallback |
## hermes-perso ## hermes-perso
| Runbook | Date | Tags | | Runbook | Date | Tags |

View File

@ -0,0 +1,106 @@
# Migration provider IA → OpenCode Go (+ fallback OpenRouter)
**Instance auteur** : hermes-perso (transverse aux 3)
**Date** : 2026-06-14
**Tags** : infra, opencode, hermes, family-help, llm, fallback
**Statut** : valide
---
## Probleme
Basculer le provider IA par defaut de OpenRouter vers OpenCode Go (endpoint
`zen/go/v1`), tout en gardant DeepSeek V4 Flash et un fallback OpenRouter.
Concerne les 3 agents Hermes (gateway) + l'app family-help (module medical).
---
## Contexte et contraintes
- Image `nousresearch/hermes-agent:latest`, source montee dans `/opt/hermes`.
- Les 3 Hermes sont des **stacks Portainer** : 291=nyora, 292=perso (path-based,
compose sur le FS), 294=TT (compose **inline** dans Portainer). Le
`docker-compose.yml` top-level de `hermes-platform/` est OBSOLETE.
- 1 seul abonnement OpenCode Go, plusieurs cles tirant du meme pool (~60$/mois).
- `/Volumes/docker` (Mac) = mount SMB du NAS `/volume1/docker`.
---
## Ce qui NE fonctionne PAS
| Tentative | Erreur obtenue | Raison de l'echec |
|-----------|----------------|-------------------|
| `docker compose up` depuis `hermes-platform/` (top-level) | `Conflict. The container name is already in use` | Les containers appartiennent aux stacks per-instance, pas au compose top-level |
| `hermes model` / `hermes fallback add` en SSH | `requires an interactive terminal` | Pickers interactifs → editer le YAML directement |
| Provider custom dans `providers:` | inutile | `opencode-go` est deja BUILT-IN (models.dev) |
| family-help medical `max_tokens: 512` | `finish_reason=length`, `content` VIDE | Modele de raisonnement : reasoning_content mange le budget avant le content |
---
## Solution validee
Provider built-in `opencode-go` : base_url `https://opencode.ai/zen/go/v1`,
cle via env var **`OPENCODE_API_KEY`**, model `deepseek-v4-flash` (sans prefixe).
OpenRouter (fallback) garde `deepseek/deepseek-v4-flash`.
```yaml
# data/config.yaml (gateway) — pour chaque instance
model:
default: deepseek-v4-flash
provider: opencode-go
fallback_providers:
- provider: openrouter
model: deepseek/deepseek-v4-flash
key_env: OPENROUTER_API_KEY
```
```bash
# perso / nyora (stacks path-based) : ajouter OPENCODE_API_KEY au .env + au compose
# - OPENCODE_API_KEY=${OPENCODE_API_KEY}
cd /volume1/docker/hermes-platform/hermes-perso
docker compose up -d --force-recreate hermes-agent-perso
# TT (stack 294 inline) : via API Portainer
# GET /api/stacks/294/file → inserer "- OPENCODE_API_KEY=<cle>" → PUT /api/stacks/294?endpointId=2
```
family-help : `medical_service.py` → helper `_llm_complete()` (OpenCode primaire,
OpenRouter fallback), **`max_tokens: 2048`**, cle `BIFROST_OPENCODE_KEY`.
`docker compose build --no-cache && docker compose up -d --force-recreate`.
---
## Verification
```bash
docker exec hermes-agent-<inst> hermes fallback ls
# Attendu : Primary deepseek-v4-flash (via opencode-go)
# Test end-to-end
docker exec hermes-agent-<inst> curl -s -H "Authorization: Bearer <API_SERVER_KEY>" \
-H 'Content-Type: application/json' \
-d '{"model":"deepseek-v4-flash","messages":[{"role":"user","content":"dis OK"}],"max_tokens":40}' \
http://localhost:8642/v1/chat/completions
# Attendu : HTTP 200, content non vide
# Test fallback : pointer OPENCODE_GO_BASE_URL vers un hote injoignable → reponse via OpenRouter (200)
```
---
## Pieges specifiques DSM / NAS
- `docker` n'est PAS dans le PATH SSH → utiliser `/usr/local/bin/docker`.
- Ne jamais editer le docker-compose top-level (obsolete) ; identifier la vraie source
via `docker inspect <c> --format '{{index .Config.Labels "com.docker.compose.project.config_files"}}'`.
- TT = stack inline Portainer → API Portainer, pas le FS (sudo requis sinon).
- DeepSeek V4 Flash (OpenCode) = reasoning model → `max_tokens` >= 2048 pour les
apps maison qui parsent du JSON (Hermes gere nativement).
---
## References
- https://opencode.ai/docs/zen
- https://hermes-agent.nousresearch.com/docs/user-guide/features/fallback-providers
- NyoraNotes : note 416da848 (capitalisation), note 26c38f8c (missions)