nas-runbooks/common/runbook-n8n-llm-bifrost.md

95 lines
3.3 KiB
Markdown

# RUNBOOK — Appels LLM depuis nœuds Code n8n : passer par Bifrost obligatoirement
**Date** : 2026-06-17
**Découvert lors** : Migration OpenCode Go veille IA — workflow VEILLE | Monitoring sources IA
---
## Problème
Les nœuds **Code** n8n (JavaScript) ne peuvent **pas** appeler `opencode.ai` directement.
Le container n8n est sur le réseau Docker `n8n` et n'a pas de connectivité sortante vers `opencode.ai`.
**Symptôme trompeur** : l'appel HTTPS semble réussir (pas de timeout, pas de `NET_ERR`), mais `choices[0].message.content` est vide ou `null`. Résultat : `JSON.parse("")``Unexpected end of JSON input`. Le workflow passe en `success` car le catch absorbe l'erreur silencieusement.
**Ce qui NE fonctionne PAS** depuis un nœud Code n8n :
- `https://opencode.ai/zen/go/v1/chat/completions` → contenu vide silencieux
- Tout endpoint LLM externe (openrouter, etc.) potentiellement concerné
---
## Solution
**Toujours passer par Bifrost** (réseau Docker interne, accessible depuis n8n) :
```javascript
const http = require('http');
const BIFROST_VK = 'bfk-e5832bfebd22e9d8252a426d0734ed5f2d923204c8033d6d'; // Nabil-Key
const body = JSON.stringify({
model: 'deepseek-v4-flash', // sans préfixe OpenRouter
max_tokens: 400,
stream: false,
temperature: 0.1,
messages: [{ role: 'user', content: '...' }]
});
const options = {
hostname: 'bifrost', // nom du container Docker
port: 8080,
path: '/v1/chat/completions',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-bf-vk': BIFROST_VK, // header Bifrost (PAS Authorization Bearer)
'Content-Length': Buffer.byteLength(body)
},
timeout: 60000
};
const req = http.request(options, (res) => { ... });
```
**Points critiques** :
- Utiliser `http` (pas `https`) car Bifrost est en HTTP interne
- Header : `x-bf-vk` (pas `Authorization: Bearer`) → 401 sinon
- Modèle : `deepseek-v4-flash` sans préfixe `deepseek/` (format OpenCode, pas OpenRouter)
- `stream: false` obligatoire
---
## Modèles disponibles via Bifrost
| Modèle | Notes |
|--------|-------|
| `deepseek-v4-flash` | ✅ Confirmé fonctionnel, rapide, JSON fiable |
| `deepseek-v4-pro` | ✅ Plus puissant |
| `glm-5.1` | ⚠️ Fait du chain-of-thought avant le JSON → tronque avec max_tokens bas |
| `kimi-k2.6` | ❌ Provider Moonshot AI down (521) au 17/06/2026 |
| `qwen3.7-plus` | ✅ Disponible |
---
## VKs Bifrost (SQLite `/volume1/docker/bifrost/data/config.db`)
| Nom | VK |
|-----|----|
| Nabil-Key | `bfk-e5832bfebd22e9d8252a426d0734ed5f2d923204c8033d6d` |
| Yesmine-Key | `bfk-1eb77f96379622db7264ae6692980e4cb81cde9e7435f66a` |
---
## Rappel : nœuds HTTP Request n8n natifs
Les nœuds **HTTP Request** (non-Code) utilisent les credentials n8n et peuvent avoir une connectivité différente. Le workflow VEILLE | Enrichissement articles utilise un nœud HTTP Request natif vers `http://bifrost:8080/v1/chat/completions` avec une credential `httpHeaderAuth` → fonctionne.
---
## Ce qui NE fonctionne PAS
- `opencode.ai` direct depuis nœud Code n8n → contenu vide silencieux
- `kimi-k2.6` via Bifrost → provider Moonshot AI en panne (code 521)
- `glm-5.1` pour JSON avec max_tokens < 800 chain-of-thought tronque avant le JSON
- Préfixe `deepseek/deepseek-v4-flash` (format OpenRouter) sur OpenCode Go 400 ou réponse sans choices