Modèles auto-hébergés
Takuto Core peut piloter un serveur de modèle auto-hébergé et compatible OpenAI — LM Studio, Ollama, vLLM, et similaires — via le fournisseur OpenCode. Cela garde le code source et les prompts entièrement sur une infrastructure que vous contrôlez. Cette page couvre la configuration et les modes de défaillance que nous avons rencontrés en branchant LM Studio avec Docker Desktop, pour que vous n’ayez pas à les redécouvrir.
Chaque réglage ci-dessous est éditable depuis Configuration → AI Settings → OpenCode dans le dashboard. Inutile d’éditer
config.tomlà la main.
Configuration de base
-
Réglez le fournisseur sur OpenCode dans Configuration → AI Settings.
-
Renseignez le champ Model. Le flag
-md’OpenCode attend<providerId>/<modelId>, et la config générée par Takuto Core nomme toujours le fournisseurself_hosted; la valeur doit donc ressembler à :self_hosted/<model-id-as-reported-by-the-server>Id de modèle rapporté par le serveur À régler dans Takuto qwen/qwen2.5-vl-7bself_hosted/qwen/qwen2.5-vl-7blmstudio-community/Llama-3.1-8B-Instruct-GGUFself_hosted/lmstudio-community/Llama-3.1-8B-Instruct-GGUF -
Réglez la Base URL sur l’endpoint compatible OpenAI, en incluant le
/v1final :http://host.docker.internal:1234/v1 -
Si votre serveur n’a pas besoin d’une vraie clé API (LM Studio, Ollama n’en ont en général pas besoin), cochez Allow shared default token pour que Takuto Core injecte un bearer factice.
-
Réglez Context limit / Output limit pour correspondre à votre modèle — les endpoints locaux ne peuvent pas les rapporter, donc OpenCode s’appuie sur les valeurs que vous fournissez.
Côté serveur de modèle
Rendez le serveur joignable depuis les containers :
- LM Studio : activez Developer → Local Server → « Serve on Local Network ». Sans cela,
LM Studio ne se lie qu’à
127.0.0.1et aucun container ne peut l’atteindre. - Firewall macOS : soit désactivé, soit avec le serveur de modèle explicitement autorisé.
Vérifiez qu’il est bien lié à toutes les interfaces, pas seulement à la loopback :
lsof -nP -iTCP -sTCP:LISTEN | grep 1234
# Attendu : *:1234 (LISTEN) — lié à toutes les interfaces
# S’il affiche 127.0.0.1:1234, « Serve on Local Network » est désactivé.
Le sidecar de pont (contournement gVisor)
Vous n’en avez besoin que lorsque le serveur de modèle tourne sur le Mac hôte et que Docker Desktop utilise la pile réseau gVisor (le défaut depuis la 4.34+). Vous n’en avez pas besoin pour les fournisseurs cloud, ni quand le serveur de modèle tourne comme un container dans le réseau compose de Takuto Core — dans ce cas, pointez la Base URL sur le nom du service (par ex.
http://lm-studio:1234/v1) et sautez le pont.
Avec gVisor, le trafic des containers vers des IP privées sur le LAN du Mac — y compris
host.docker.internal (qui se résout en 192.168.65.254 dans le container) — peut expirer
silencieusement, alors que les IP publiques fonctionnent très bien. Vérifiez votre type de
réseau :
ps ax | grep com.docker.virtualization | grep -o 'networkType [a-z]*'
# networkType gvisor ← concerné
Confirmer que c’est bien le problème gVisor
Si le serveur se lie à *:1234, que le firewall est désactivé, que l’internet public fonctionne
depuis un container, mais que host.docker.internal:1234 et l’IP LAN du Mac expirent tous deux
depuis l’intérieur du container — c’est la pile gVisor.
# L’internet public fonctionne depuis un container :
docker exec <takuto-container> sh -c 'wget -q -O - -T 3 https://1.1.1.1 | head -3'
# host.docker.internal se résout mais les connexions expirent :
docker exec <takuto-container> sh -c 'curl -v -m 3 http://host.docker.internal:1234/v1/models 2>&1 | tail -5'
# * Connection timed out after 3001 milliseconds
Correctif : le sidecar socat lm-bridge
Takuto Core fournit un minuscule container socat qui s’attache à la fois au réseau bridge
par défaut (qui atteint l’hôte correctement sous gVisor) et au réseau compose (pour que les
workers imbriqués DinD puissent y router). Activez-le avec un seul flag — les cibles make
ci-dessous sont l’enrobage de confort du dépôt du moteur Takuto Core (la
voie construisez-votre-propre-container) ; sous le capot, LM_BRIDGE=1
se contente de fusionner docker-compose.lm-bridge.yml dans la stack Compose :
make start BACKEND=postgres LM_BRIDGE=1
Cela démarre maestro-lm-bridge à l’IP fixe 172.20.0.250, redirigeant
TCP/1234 → host.docker.internal:${LM_HOST_PORT:-1234}. Réglez ensuite la Base URL dans
AI Settings sur :
http://172.20.0.250:1234/v1
Pour un port non standard (le 11434 d’Ollama, par exemple) :
LM_HOST_PORT=11434 make start BACKEND=postgres LM_BRIDGE=1
Test rapide une fois le pont en place
docker exec maestro-core-dind-1 docker run --rm --entrypoint /bin/bash \
maestro:latest -c \
'exec 3<>/dev/tcp/172.20.0.250/1234;
printf "GET /v1/models HTTP/1.0\r\nHost: x\r\n\r\n" >&3;
timeout 5 cat <&3 | head -5'
Un 200 OK suivi de JSON signifie que la voie du worker est saine.
Checklist pour OpenCode error: unknown error
Quand le dashboard affiche le cryptique OpenCode error: unknown error, parcourez ceci dans
l’ordre — chaque point est un mode de défaillance réel :
- Le champ Model commence par
self_hosted/. - Allow shared default token est coché (sauf si vous avez enregistré un bearer par
utilisateur). Quand il est désactivé et qu’aucun bearer n’est enregistré, aucun
opencode.jsonn’est monté dans le worker et OpenCode quitte juste après sa migration de base de données du premier lancement. - La Base URL se termine par
/v1. - Le serveur de modèle a « Serve on Local Network » activé (
*:<port>, pas127.0.0.1:<port>). - Le réseau Docker Desktop est sain — lancez le test rapide ; s’il expire, utilisez le sidecar
LM_BRIDGEci-dessus.
Si les cinq sont au vert et que l’exécution échoue toujours, lancez opencode run manuellement
dans le container avec --print-logs --log-level WARN pour voir la sortie stderr propre
d’OpenCode au lieu du « unknown error » masqué.