From a47f233f191b73b8a21b0ec25c6c3656b8e24a3c Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 3 Oct 2026 11:47:40 +0000 Subject: [PATCH] docs: translate the repository to English Translate the README, Documentation.md, installer and publishing script messages, and the FlyBrain, bench and router-eval console output. Kept in French on purpose: the router's bilingual keyword rules and the French prompts that test them, the recorded bench answers, and the former FlyBrain voice (fly-language), whose prompt contract must match its trained adapter. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01X9mEcAVjGKUr7yaqnrkc9h --- Documentation.md | 475 +++++++++++++++++++++--------------------- bench/bench.mjs | 4 +- brain/eval-router.mjs | 14 +- brain/flybrain.mjs | 4 +- install.sh | 34 +-- readme.md | 168 +++++++-------- scripts/publish.sh | 16 +- 7 files changed, 358 insertions(+), 357 deletions(-) diff --git a/Documentation.md b/Documentation.md index 4daf5f6..57175b1 100644 --- a/Documentation.md +++ b/Documentation.md @@ -1,43 +1,43 @@ -# Documentation de FlyCoder 0.3 beta +# FlyCoder 0.3 beta documentation -FlyCoder est un modèle de code local qui tourne dans [Ollama](https://ollama.com), réglé pour les MacBook et Mac mini Apple Silicon. Cette documentation couvre l'installation, l'utilisation, les réglages, le banc d'essai, la publication et le dépannage. Pour une vue d'ensemble rapide, voir le [README](readme.md). +FlyCoder is a local coding model that runs in [Ollama](https://ollama.com), tuned for Apple Silicon MacBooks and Mac minis. This documentation covers installation, usage, settings, the benchmark, publishing and troubleshooting. For a quick overview, see the [README](readme.md). -## Sommaire +## Contents -1. [Ce qu'est FlyCoder](#1-ce-quest-flycoder) -2. [Prérequis](#2-prérequis) +1. [What FlyCoder is](#1-what-flycoder-is) +2. [Requirements](#2-requirements) 3. [Installation](#3-installation) -4. [Choisir une variante](#4-choisir-une-variante) -5. [Utilisation](#5-utilisation) -6. [Réglages](#6-réglages) -7. [Banc d'essai](#7-banc-dessai) -8. [Publier une version sur ollama.com](#8-publier-une-version-sur-ollamacom) -9. [Dépannage](#9-dépannage) -10. [Développement](#10-développement) -11. [Limites connues](#11-limites-connues) -12. [Historique des versions](#12-historique-des-versions) -13. [Licences](#13-licences) +4. [Choosing a variant](#4-choosing-a-variant) +5. [Usage](#5-usage) +6. [Settings](#6-settings) +7. [Benchmark](#7-benchmark) +8. [Publishing a version on ollama.com](#8-publishing-a-version-on-ollamacom) +9. [Troubleshooting](#9-troubleshooting) +10. [Development](#10-development) +11. [Known limitations](#11-known-limitations) +12. [Version history](#12-version-history) +13. [Licenses](#13-licenses) -## 1. Ce qu'est FlyCoder +## 1. What FlyCoder is -FlyCoder 0.2 beta est un **profil Ollama** : un modèle de base ouvert, une quantification adaptée aux Mac, des réglages d'échantillonnage officiels, une fenêtre de contexte explicite et une consigne système dédiée au code. Il s'utilise comme n'importe quel modèle Ollama : dans le terminal, par l'API, ou derrière un agent de code. +FlyCoder 0.2 beta is an **Ollama profile**: an open base model, a quantization suited to Macs, the official sampling settings, an explicit context window and a system prompt dedicated to code. You use it like any Ollama model: in the terminal, through the API, or behind a coding agent. -FlyCoder ne réentraîne pas les poids. Les gains par rapport à la 0.1 viennent du choix de la base et des réglages, et sont mesurés par le banc d'essai du dépôt (section 7). +FlyCoder does not retrain the weights. The gains over 0.1 come from the choice of base and settings, and are measured by the repository's benchmark (section 7). -Depuis la 0.2, FlyCoder n'inclut plus d'atelier (CLI, interface web, application Electron, contrôleur FlyBrain) : seul le modèle est livré. +Since 0.2, FlyCoder no longer includes a workshop (CLI, web interface, Electron app, FlyBrain controller): only the model ships. -## 2. Prérequis +## 2. Requirements -| Élément | Minimum | Remarque | +| Item | Minimum | Note | |---|---|---| -| Mac | Apple Silicon (M1 ou plus récent) | Mac Intel, Linux et Windows : variantes GGUF | -| Mémoire | 8 Go pour `fast`, 16 Go pour la variante principale | L'installateur choisit seul | -| Ollama | 0.31 ou plus récent | Variante principale MLX ; `fast` MLX demande 0.19 | -| Disque | 4,0 Go (`fast`) ou 7,7 Go (principale) | Partagés avec les modèles de base, pas de double copie | -| Node.js | 22 | Seulement pour le banc d'essai et les tests | -| Python 3 | Celui de macOS | Seulement pour le banc d'essai | +| Mac | Apple Silicon (M1 or later) | Intel Macs, Linux and Windows: GGUF variants | +| Memory | 8 GB for `fast`, 16 GB for the main variant | The installer picks for you | +| Ollama | 0.31 or later | Main variant on MLX; `fast` on MLX needs 0.19 | +| Disk | 4.0 GB (`fast`) or 7.7 GB (main) | Shared with the base models, no duplicate copy | +| Node.js | 22 | Only for the benchmark and the tests | +| Python 3 | The one shipped with macOS | Only for the benchmark | -Vérifier la version d'Ollama : +Check the Ollama version: ```sh ollama --version @@ -45,48 +45,49 @@ ollama --version ## 3. Installation -### 3.1 Depuis ollama.com +### 3.1 From ollama.com -FlyCoder est publié sur [ollama.com/delairvictor9/flycoder](https://ollama.com/delairvictor9/flycoder). Une seule commande suffit : +FlyCoder is published at [ollama.com/delairvictor9/flycoder](https://ollama.com/delairvictor9/flycoder). One command is enough: ```sh -ollama run delairvictor9/flycoder # variante principale (Gemma 4 12B, MLX) -ollama run delairvictor9/flycoder:fast # variante rapide (Qwen3.5 4B, MLX) -ollama run delairvictor9/flycoder:0.2-beta-gguf # principale, Mac Intel, Linux, Windows -ollama run delairvictor9/flycoder:0.2-beta-fast-gguf # rapide, Mac Intel, Linux, Windows +ollama run delairvictor9/flycoder # main variant (Gemma 4 12B, MLX) +ollama run delairvictor9/flycoder:fast # fast variant (Qwen3.5 4B, MLX) +ollama run delairvictor9/flycoder:0.2-beta-gguf # main, Intel Mac, Linux, Windows +ollama run delairvictor9/flycoder:0.2-beta-fast-gguf # fast, Intel Mac, Linux, Windows ``` -Tags disponibles : `latest` et `0.2-beta` (principale), `fast` et `0.2-beta-fast` (rapide), `0.2-beta-gguf` et `0.2-beta-fast-gguf` (portables). Pour l'appeler simplement `flycoder` : `ollama cp delairvictor9/flycoder flycoder`. +Available tags: `latest` and `0.2-beta` (main), `fast` and `0.2-beta-fast` (fast), `0.2-beta-gguf` and `0.2-beta-fast-gguf` (portable). To call it simply `flycoder`: `ollama cp delairvictor9/flycoder flycoder`. -### 3.2 Installateur en une commande +### 3.2 One-command installer ```sh curl -fsSL https://raw.githubusercontent.com/Tromset/flycoder/main/install.sh | sh ollama run flycoder ``` -L'installateur : +The installer: -1. vérifie qu'Ollama est installé, démarré et en version 0.31 ou plus ; -2. détecte le système et la mémoire ; -3. choisit `flycoder:0.2-beta` à partir de 15 Go de mémoire, sinon `flycoder:0.2-beta-fast` ; -4. télécharge le modèle de base, crée la variante et la copie sous `flycoder:latest`. +1. checks that Ollama is installed, running and at version 0.31 or later; +2. detects the system and the memory; +3. picks `flycoder:0.2-beta` from 15 GB of memory up, otherwise `flycoder:0.2-beta-fast`; +4. downloads the base model, creates the variant and copies it to `flycoder:latest`. -Options, à placer après `sh -s --` quand le script est lu depuis `curl` : +Options, placed after `sh -s --` when the script is read from `curl`: -| Option | Effet | +| Option | Effect | |---|---| -| `--fast` | installe seulement la variante rapide | -| `--all` | installe les deux variantes ; `latest` pointe vers la principale | -| `--gguf` | utilise les poids GGUF portables (Mac Intel, Linux, Windows) au lieu de MLX | +| `--fast` | installs only the fast variant | +| `--all` | installs both variants; `latest` points to the main one | +| `--gguf` | uses the portable GGUF weights (Intel Mac, Linux, Windows) instead of MLX | +| `--no-brain` | skips the FlyBrain experts (`flycoder:router`, `flycoder:0.2-beta-lite`) | ```sh curl -fsSL https://raw.githubusercontent.com/Tromset/flycoder/main/install.sh | sh -s -- --all ``` -Depuis une copie du dépôt, `sh install.sh` utilise les Modelfiles locaux. La variable `FLYCODER_REF` choisit une autre branche ou étiquette GitHub pour les télécharger. +From a copy of the repository, `sh install.sh` uses the local Modelfiles. The `FLYCODER_REF` variable picks another GitHub branch or tag to download them from. -### 3.3 À la main +### 3.3 By hand ```sh git clone https://github.com/Tromset/flycoder.git && cd flycoder @@ -95,93 +96,93 @@ ollama create flycoder:0.2-beta-fast -f Modelfile.fast ollama cp flycoder:0.2-beta flycoder:latest ``` -Sur une machine sans Apple Silicon, remplacez d'abord la ligne `FROM` : `gemma4:12b-mlx` par `gemma4:12b`, et `qwen3.5:4b-mlx` par `qwen3.5:4b`. +On a machine without Apple Silicon, first replace the `FROM` line: `gemma4:12b-mlx` with `gemma4:12b`, and `qwen3.5:4b-mlx` with `qwen3.5:4b`. -### 3.4 Vérifier l'installation +### 3.4 Checking the installation ```sh ollama list # flycoder:latest, flycoder:0.2-beta... -ollama show flycoder # base, quantification, capacités -ollama show flycoder --parameters # réglages appliqués -ollama run flycoder "Écris une fonction Python qui inverse une chaîne." -ollama ps # mémoire utilisée, part GPU, contexte alloué +ollama show flycoder # base, quantization, capabilities +ollama show flycoder --parameters # applied settings +ollama run flycoder "Write a Python function that reverses a string." +ollama ps # memory used, GPU share, allocated context ``` -Dans `ollama ps`, la colonne PROCESSOR doit afficher `100% GPU`. Une répartition CPU/GPU signale un manque de mémoire (section 9). +In `ollama ps`, the PROCESSOR column should show `100% GPU`. A CPU/GPU split means memory is short (section 9). -### 3.5 Désinstaller +### 3.5 Uninstalling ```sh ollama rm flycoder:latest flycoder:0.2-beta flycoder:0.2-beta-fast -ollama rm gemma4:12b-mlx qwen3.5:4b-mlx # bases, si aucun autre modèle ne les utilise +ollama rm gemma4:12b-mlx qwen3.5:4b-mlx # bases, if no other model uses them ``` -## 4. Choisir une variante +## 4. Choosing a variant -| Tag | Base | Poids | Contexte | Pour | +| Tag | Base | Weights | Context | For | |---|---|---|---|---| -| `flycoder:0.2-beta`, `latest` | Gemma 4 12B (Google DeepMind), NVFP4 sur MLX | 7,7 Go | 32 768 | Mac 16 Go et plus, qualité maximale | -| `flycoder:0.2-beta-fast`, `fast` | Qwen3.5 4B (Alibaba Qwen), NVFP4 sur MLX | 4,0 Go | 16 384 | Mac 8 Go, vitesse de la 0.1 | -| `flycoder:0.2-beta-gguf` | Gemma 4 12B, GGUF Q4_K_M | 8,0 Go | 32 768 | Mac Intel, Linux, Windows | -| `flycoder:0.2-beta-fast-gguf` | Qwen3.5 4B, GGUF Q4_K_M | 3,4 Go | 16 384 | Mac Intel, Linux, Windows | +| `flycoder:0.2-beta`, `latest` | Gemma 4 12B (Google DeepMind), NVFP4 on MLX | 7.7 GB | 32,768 | Macs with 16 GB or more, maximum quality | +| `flycoder:0.2-beta-fast`, `fast` | Qwen3.5 4B (Alibaba Qwen), NVFP4 on MLX | 4.0 GB | 16,384 | 8 GB Macs, 0.1's speed | +| `flycoder:0.2-beta-gguf` | Gemma 4 12B, GGUF Q4_K_M | 8.0 GB | 32,768 | Intel Mac, Linux, Windows | +| `flycoder:0.2-beta-fast-gguf` | Qwen3.5 4B, GGUF Q4_K_M | 3.4 GB | 16,384 | Intel Mac, Linux, Windows | -Les deux bases gèrent l'appel d'outils, la réflexion (thinking) et les images. +Both bases support tool calling, thinking and images. -Règle simple : prenez la variante principale si votre Mac a 16 Go ou plus et que la qualité du code compte plus que la latence ; prenez `fast` sur 8 Go ou si vous voulez exactement la réactivité de la 0.1. Pour changer le modèle par défaut : +Rule of thumb: take the main variant if your Mac has 16 GB or more and code quality matters more than latency; take `fast` on 8 GB or if you want exactly 0.1's responsiveness. To change the default model: ```sh -ollama cp flycoder:0.2-beta-fast flycoder:latest # la variante rapide devient « flycoder » -ollama cp flycoder:0.2-beta flycoder:latest # retour à la variante principale +ollama cp flycoder:0.2-beta-fast flycoder:latest # the fast variant becomes "flycoder" +ollama cp flycoder:0.2-beta flycoder:latest # back to the main variant ``` -## 5. Utilisation +## 5. Usage -### 5.1 Dans le terminal +### 5.1 In the terminal ```sh ollama run flycoder ``` -Tapez votre demande puis Entrée. Pour un texte sur plusieurs lignes, encadrez-le de `"""`. Commandes utiles dans la conversation : +Type your request, then press Enter. For multi-line text, wrap it in `"""`. Useful commands in a conversation: -| Commande | Effet | +| Command | Effect | |---|---| -| `/set nothink` / `/set think` | désactive ou réactive la réflexion | -| `/set parameter num_ctx 65536` | agrandit le contexte pour la session | -| `/set system "…"` | remplace la consigne système pour la session | -| `/show parameters` | affiche les réglages en cours | -| `/clear` | efface la conversation | -| `/bye` | quitte | +| `/set nothink` / `/set think` | turns thinking off or back on | +| `/set parameter num_ctx 65536` | enlarges the context for the session | +| `/set system "…"` | replaces the system prompt for the session | +| `/show parameters` | shows the current settings | +| `/clear` | clears the conversation | +| `/bye` | quits | -Options de lancement : `--think=false` (réponse immédiate), `--hidethinking` (masque la réflexion mais la garde), `--verbose` (affiche le débit en tokens par seconde après chaque réponse). +Launch options: `--think=false` (immediate answer), `--hidethinking` (hides the thinking but keeps it), `--verbose` (shows the tokens-per-second rate after each answer). -Donner un fichier au modèle : +Giving the model a file: ```sh -ollama run flycoder "Trouve les bugs de ce fichier et propose un correctif : $(cat src/parser.py)" +ollama run flycoder "Find the bugs in this file and suggest a fix: $(cat src/parser.py)" ``` -Donner une image (capture d'écran, schéma) : écrivez son chemin dans la demande, par exemple `ollama run flycoder "Écris le HTML de cette maquette : ./maquette.png"`. +Giving it an image (screenshot, diagram): write its path in the request, for example `ollama run flycoder "Write the HTML for this mockup: ./mockup.png"`. -### 5.2 API REST d'Ollama +### 5.2 Ollama REST API ```sh curl http://localhost:11434/api/chat -d '{ "model": "flycoder", - "messages": [{"role": "user", "content": "Écris une fonction JavaScript debounce(fn, ms)."}], + "messages": [{"role": "user", "content": "Write a JavaScript function debounce(fn, ms)."}], "think": false, "stream": false }' ``` -- `"think": true` ou `false` active ou coupe la réflexion ; la réflexion est renvoyée à part dans `message.thinking`. -- `"stream": true` (par défaut) envoie la réponse au fil de l'eau en lignes JSON. -- `"options": {"num_ctx": 65536}` change un réglage pour une requête. -- Un message `{"role": "system", ...}` remplace la consigne système de FlyCoder pour cette conversation. +- `"think": true` or `false` turns thinking on or off; the thinking comes back separately in `message.thinking`. +- `"stream": true` (the default) sends the answer as it is generated, as JSON lines. +- `"options": {"num_ctx": 65536}` changes a setting for one request. +- A `{"role": "system", ...}` message replaces FlyCoder's system prompt for that conversation. -### 5.3 API compatible OpenAI +### 5.3 OpenAI-compatible API -Ollama expose aussi `http://localhost:11434/v1`. Exemple en Python avec le paquet `openai` : +Ollama also exposes `http://localhost:11434/v1`. Example in Python with the `openai` package: ```python from openai import OpenAI @@ -189,14 +190,14 @@ from openai import OpenAI client = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama") reply = client.chat.completions.create( model="flycoder", - messages=[{"role": "user", "content": "Écris un test pytest pour une fonction slugify."}], + messages=[{"role": "user", "content": "Write a pytest test for a slugify function."}], ) print(reply.choices[0].message.content) ``` -### 5.4 Agents de code et éditeurs +### 5.4 Coding agents and editors -`ollama launch` configure et ouvre un agent avec FlyCoder : +`ollama launch` sets up and opens an agent with FlyCoder: ```sh ollama launch claude --model flycoder # Claude Code @@ -204,57 +205,57 @@ ollama launch codex --model flycoder # Codex ollama launch opencode --model flycoder # OpenCode ``` -Si vous avez pris FlyCoder sur ollama.com sans `install.sh`, utilisez le nom publié : `ollama launch claude --model delairvictor9/flycoder`. +If you got FlyCoder from ollama.com without `install.sh`, use the published name: `ollama launch claude --model delairvictor9/flycoder`. -`ollama launch --help` liste les autres intégrations, dont VS Code, Copilot CLI, Cline, Qwen Code, Pi et Droid. Les agents envoient de longues consignes et beaucoup de fichiers : Ollama recommande au moins 64 000 tokens de contexte pour eux (section 6.2). +`ollama launch --help` lists the other integrations, including VS Code, Copilot CLI, Cline, Qwen Code, Pi and Droid. Agents send long instructions and many files: Ollama recommends at least 64,000 tokens of context for them (section 6.2). -### 5.5 FlyBrain : le routeur qui baisse la RAM +### 5.5 FlyBrain: the router that lowers RAM use -FlyBrain est un petit serveur Node 22, sans dépendance, qui se place devant Ollama sur le port 11435. Il répond aux noms `flycoder` et `flycoder:fast`, choisit un expert pour chaque demande et ne garde qu'un expert en mémoire. Les autres modèles et les autres routes passent tels quels. +FlyBrain is a small, dependency-free Node 22 server that sits in front of Ollama on port 11435. It answers to the names `flycoder` and `flycoder:fast`, picks an expert for each request and keeps only one expert in memory. Other models and other routes pass through unchanged. ```sh -node ~/.flycoder/brain/flybrain.mjs # copié par install.sh ; ou npm run brain dans ce dépôt -node brain/flybrain.mjs --prefix delairvictor9/ # avec les modèles publiés sur ollama.com +node ~/.flycoder/brain/flybrain.mjs # copied by install.sh; or npm run brain in this repository +node brain/flybrain.mjs --prefix delairvictor9/ # with the models published on ollama.com ``` -Options : `--port` (11435), `--ollama` (http://127.0.0.1:11434), `--prefix`, `--max-expert auto|full|fast`. Avec `auto`, la valeur par défaut, un Mac de moins de 16 Go plafonne `flycoder` au 4B. +Options: `--port` (11435), `--ollama` (http://127.0.0.1:11434), `--prefix`, `--max-expert auto|full|fast`. With `auto`, the default, a Mac with less than 16 GB caps `flycoder` at the 4B. -Comment une demande est aiguillée : +How a request is routed: -1. **Règles** (gratuites) : la demande est difficile si elle contient des outils (agents), plus de 6 000 caractères, plusieurs blocs de code, une spécification en liste, ou un mot comme débogue, algorithme, optimise, sécurité, erreur. Elle est simple si c'est une question courte sans code (« qu'est-ce que », « comment on », « explique »…). -2. **Micro-modèle** `flycoder:router` (Qwen3.5 0.8B, 1 Go) pour le reste. Il répond `{"level":"simple"}` ou `{"level":"hard"}` au format JSON imposé. S'il échoue, dépasse 8 s ou répond autre chose, la demande part vers le gros modèle. Il n'est pas appelé si le gros modèle est déjà chargé. `flycoder:fast` n'a pas de micro-modèle : une demande ambiguë garde le 4B. -3. **Mémoire de conversation** : une conversation garde son expert et ne peut que monter vers le plus fort. -4. **Un seul expert** : avant de charger un autre expert, FlyBrain attend la fin des réponses en cours, puis décharge l'ancien. Il décharge aussi le micro-modèle avant le gros modèle. +1. **Rules** (free): a request is hard if it carries tools (agents), more than 6,000 characters, several code blocks, a bulleted specification, or a word such as debug, algorithm, optimize, security, error. It is simple if it is a short question without code ("what is", "how do I", "explain"…). The rules recognize these cues in both English and French. +2. **The `flycoder:router` micro-model** (Qwen3.5 0.8B, 1 GB) for the rest. It answers `{"level":"simple"}` or `{"level":"hard"}` in an enforced JSON format. If it fails, takes longer than 8 s or answers anything else, the request goes to the large model. It is not called when the large model is already loaded. `flycoder:fast` has no micro-model: an unclear request keeps the 4B. +3. **Conversation memory**: a conversation keeps its expert and can only move up to the stronger one. +4. **A single expert**: before loading another expert, FlyBrain waits for the running answers to finish, then unloads the old one. It also unloads the micro-model before the large model. -La variante normale force la réflexion (`think: true`) sauf si le client la coupe. Chaque réponse porte les en-têtes `x-flybrain-expert` et `x-flybrain-reason`, et le terminal de FlyBrain affiche une ligne par décision. +The normal variant forces thinking (`think: true`) unless the client turns it off. Each response carries the `x-flybrain-expert` and `x-flybrain-reason` headers, and FlyBrain's terminal prints one line per decision. -Brancher les outils : +Connecting tools: ```sh OLLAMA_HOST=127.0.0.1:11435 ollama run flycoder ANTHROPIC_BASE_URL=http://127.0.0.1:11435 ANTHROPIC_AUTH_TOKEN=ollama ANTHROPIC_API_KEY="" claude --model flycoder -curl http://127.0.0.1:11435/v1/chat/completions -d '{"model":"flycoder","messages":[{"role":"user","content":"Bonjour"}]}' +curl http://127.0.0.1:11435/v1/chat/completions -d '{"model":"flycoder","messages":[{"role":"user","content":"Hello"}]}' ``` -Mesurer la justesse du routeur sur vos propres demandes : ajoutez-les à `tests/fixtures/route-prompts.json`, puis lancez `node brain/eval-router.mjs`. Les mesures de mémoire et de justesse sont dans le [README](readme.md#flybrain--moins-de-ram-même-qualité-sur-les-demandes-difficiles). +To measure the router's accuracy on your own requests: add them to `tests/fixtures/route-prompts.json`, then run `node brain/eval-router.mjs`. The memory and accuracy measurements are in the [README](readme.md#flybrain-less-ram-same-quality-on-hard-requests). -## 6. Réglages +## 6. Settings -### 6.1 Ce que fixent les Modelfiles +### 6.1 What the Modelfiles set -| Paramètre | Principale | `fast` | Pourquoi | +| Parameter | Main | `fast` | Why | |---|---|---|---| -| `num_ctx` | 32 768 | 16 384 | Ollama limite sinon à 4 096 tokens sous 24 Go de mémoire | -| `temperature` | 1 | 0,6 | Valeurs officielles de Google et de Qwen pour le code | -| `top_k` | 64 | 20 | Idem | -| `top_p` | 0,95 | 0,95 | Idem | -| `min_p`, `presence_penalty`, `repeat_penalty` | hérités | 0, 0, 1 | Réglages Qwen « code en mode réflexion » | +| `num_ctx` | 32,768 | 16,384 | Otherwise Ollama limits machines under 24 GB of memory to 4,096 tokens | +| `temperature` | 1 | 0.6 | Official values from Google and Qwen for coding | +| `top_k` | 64 | 20 | Same | +| `top_p` | 0.95 | 0.95 | Same | +| `min_p`, `presence_penalty`, `repeat_penalty` | inherited | 0, 0, 1 | Qwen's "coding in thinking mode" settings | -La variante principale hérite aussi de Gemma 4 son modèle brouillon de prédiction multi-tokens, activé par Ollama. Évitez de baisser la température : Qwen et Google la recommandent telle quelle, et la 0.1 (température 0,2) produisait des réponses en boucle. +The main variant also inherits Gemma 4's multi-token prediction draft model, enabled by Ollama. Avoid lowering the temperature: Qwen and Google recommend it as is, and 0.1 (temperature 0.2) produced looping answers. -### 6.2 Agrandir le contexte +### 6.2 Enlarging the context -Pour une session : `/set parameter num_ctx 65536`. Pour un modèle permanent, créez une variante : +For one session: `/set parameter num_ctx 65536`. For a permanent model, create a variant: ```sh printf 'FROM flycoder:0.2-beta\nPARAMETER num_ctx 65536\n' > Modelfile.64k @@ -262,125 +263,125 @@ ollama create flycoder:64k -f Modelfile.64k ollama launch claude --model flycoder:64k ``` -Coût mémoire du cache, en plus des poids : environ 0,5 Go par tranche de 32 768 tokens pour la variante principale, et environ 0,5 Go par tranche de 16 384 tokens pour `fast`. Sur un Mac 16 Go, 65 536 tokens devraient tenir avec la variante principale si peu d'autres applications tournent (non mesuré) : vérifiez avec `ollama ps` que le modèle reste à `100% GPU`. +Memory cost of the cache, on top of the weights: about 0.5 GB per 32,768 tokens for the main variant, and about 0.5 GB per 16,384 tokens for `fast`. On a 16 GB Mac, 65,536 tokens should fit with the main variant if few other applications are running (not measured): check with `ollama ps` that the model stays at `100% GPU`. -### 6.3 Réflexion +### 6.3 Thinking -La réflexion est activée par défaut : le modèle raisonne avant de répondre, ce qui améliore nettement le code sur les problèmes difficiles mais allonge l'attente. Coupez-la pour les questions simples (`--think=false`, `/set nothink`, ou `"think": false` dans l'API). Sans réflexion, le banc a montré que les modèles laissent parfois une première tentative abandonnée dans le code rendu ; gardez-la pour du code à livrer. +Thinking is on by default: the model reasons before answering, which clearly improves code on hard problems but lengthens the wait. Turn it off for simple questions (`--think=false`, `/set nothink`, or `"think": false` in the API). Without thinking, the benchmark showed that models sometimes leave an abandoned first attempt in the returned code; keep it on for code you ship. -### 6.4 Consigne système +### 6.4 System prompt -La consigne de FlyCoder (`ollama show flycoder --system`) demande de : +FlyCoder's system prompt (`ollama show flycoder --system`) asks the model to: -- respecter exactement les noms, signatures et fichiers demandés ; -- livrer du code complet et exécutable, sans « TODO » ; -- traiter les cas limites ; -- privilégier la bibliothèque standard et ne jamais inventer d'API ; -- choisir un algorithme adapté ; -- ne montrer que les parties modifiées d'un fichier existant ; -- ne jamais prétendre avoir exécuté des tests ; -- éviter les failles classiques ; -- répondre dans la langue de l'utilisateur. +- keep the requested names, signatures and files exactly; +- deliver complete, runnable code, without "TODO"; +- handle edge cases; +- prefer the standard library and never invent APIs; +- choose a suitable algorithm; +- show only the changed parts of an existing file; +- never claim to have run tests; +- avoid common vulnerabilities; +- answer in the user's language. -Remplacez-la pour une session avec `/set system`, ou par un message `system` dans l'API. +Replace it for a session with `/set system`, or with a `system` message in the API. -### 6.5 Réglages du serveur Ollama +### 6.5 Ollama server settings -Ces variables s'appliquent à tous les modèles. Sur Mac, avec l'application Ollama, définissez-les avec `launchctl setenv` puis redémarrez Ollama : +These variables apply to every model. On a Mac running the Ollama app, set them with `launchctl setenv`, then restart Ollama: ```sh -launchctl setenv OLLAMA_KV_CACHE_TYPE q8_0 # cache de contexte deux fois plus petit, perte de précision faible -launchctl setenv OLLAMA_KEEP_ALIVE 30m # garde le modèle chargé 30 minutes +launchctl setenv OLLAMA_KV_CACHE_TYPE q8_0 # context cache half the size, small loss of precision +launchctl setenv OLLAMA_KEEP_ALIVE 30m # keeps the model loaded for 30 minutes ``` -`OLLAMA_KV_CACHE_TYPE=q8_0` divise par deux la mémoire du cache de contexte des modèles GGUF (tags `-gguf`) ; la documentation d'Ollama ne précise pas son effet sur le moteur MLX. `OLLAMA_KEEP_ALIVE` évite de recharger le modèle entre deux questions espacées. +`OLLAMA_KV_CACHE_TYPE=q8_0` halves the context cache memory of GGUF models (`-gguf` tags); Ollama's documentation does not say how it affects the MLX engine. `OLLAMA_KEEP_ALIVE` avoids reloading the model between two widely spaced questions. -## 7. Banc d'essai +## 7. Benchmark -Le dossier `bench/` mesure le taux de réussite et la vitesse de n'importe quel modèle Ollama sur 20 exercices de code : +The `bench/` folder measures the pass rate and speed of any Ollama model on 20 coding problems: -- 13 en Python et 7 en JavaScript ; -- chacun avec des tests cachés, que le modèle ne voit jamais ; -- chaque test est prouvé par une solution de référence et rejette une solution vide (`npm test`). +- 13 in Python and 7 in JavaScript; +- each with hidden tests that the model never sees; +- each test is proven by a reference solution and rejects an empty solution (`npm test`). ```sh -ollama create flycoder0.1beta -f bench/baselines/flycoder-0.1-beta.Modelfile # pour comparer à la 0.1 +ollama create flycoder0.1beta -f bench/baselines/flycoder-0.1-beta.Modelfile # to compare with 0.1 npm run bench -- --models flycoder0.1beta,flycoder:0.2-beta,flycoder:0.2-beta-fast ``` -| Option | Effet | +| Option | Effect | |---|---| -| `--models a,b` | modèles à comparer, l'un après l'autre (la mémoire est libérée entre deux) | -| `--think on\|off\|default` | force ou coupe la réflexion ; `default` suit le modèle | -| `--samples 3` | plusieurs essais par exercice, pour lisser le hasard | -| `--only py-lcs,js-evaluate` | sous-ensemble d'exercices | -| `--max-tokens 8192` | plafond de tokens par réponse ; une réponse coupée compte comme un échec | -| `--num-ctx 8192` | contexte réduit pour les machines à court de mémoire, sans effet sur ces réponses courtes | -| `--out fichier.json` | emplacement du rapport ; par défaut `bench/results/` | -| `--no-sandbox` | désactive la sandbox macOS | +| `--models a,b` | models to compare, one after the other (memory is freed in between) | +| `--think on\|off\|default` | forces or disables thinking; `default` follows the model | +| `--samples 3` | several attempts per problem, to smooth out randomness | +| `--only py-lcs,js-evaluate` | subset of problems | +| `--max-tokens 8192` | token cap per answer; a truncated answer counts as a failure | +| `--num-ctx 8192` | smaller context for machines short on memory, with no effect on these short answers | +| `--out file.json` | report location; `bench/results/` by default | +| `--no-sandbox` | disables the macOS sandbox | -Le banc affiche un tableau (réussites, débit de génération, vitesse de lecture du prompt, tokens par réponse, secondes par exercice) et enregistre chaque réponse, chaque erreur de test et chaque compteur dans le JSON, mis à jour après chaque exercice. +The bench prints a table (passes, generation rate, prompt processing speed, tokens per answer, seconds per problem) and records every answer, every test error and every counter in the JSON, updated after each problem. -Il exécute le code écrit par les modèles sur votre machine, dans un dossier temporaire, avec un délai limite. Sur macOS, `sandbox-exec` lui interdit le réseau et l'écriture hors de ce dossier. +It runs the code written by the models on your machine, in a temporary folder, with a time limit. On macOS, `sandbox-exec` blocks network access and writes outside that folder. -Résultats de référence, enregistrés dans [docs/bench/cpu-nothink.json](docs/bench/cpu-nothink.json) sur un serveur Linux sans GPU, avec les poids GGUF, sans réflexion et un essai par exercice : +Reference results, recorded in [docs/bench/cpu-nothink.json](docs/bench/cpu-nothink.json) on a Linux server without a GPU, with GGUF weights, without thinking and one attempt per problem: -| Profil | Réussis | Génération | Tokens par réponse | Temps par exercice | +| Profile | Passed | Generation | Tokens per answer | Time per problem | |---|---|---|---|---| -| `flycoder0.1beta` (0.1) | 5/20 | 6,6 tok/s | 581 | 94 s | -| `flycoder:0.2-beta-fast` | 5/20 | 6,5 tok/s | 537 | 89 s | -| `flycoder:0.2-beta` | 14/20 | 3,4 tok/s | 739 | 235 s | +| `flycoder0.1beta` (0.1) | 5/20 | 6.6 tok/s | 581 | 94 s | +| `flycoder:0.2-beta-fast` | 5/20 | 6.5 tok/s | 537 | 89 s | +| `flycoder:0.2-beta` | 14/20 | 3.4 tok/s | 739 | 235 s | -Sur ce serveur, la variante principale réussit presque trois fois plus d'exercices, mais met environ 2,5 fois plus de temps par exercice. La variante rapide garde la vitesse et le taux de réussite de la 0.1. Aucune mesure n'a encore été faite sur Mac, où le moteur MLX et la prédiction multi-tokens devraient réduire l'écart de vitesse. +On this server, the main variant solves almost three times as many problems, but takes about 2.5 times as long per problem. The fast variant keeps 0.1's speed and pass rate. No measurement has been made on a Mac yet, where the MLX engine and multi-token prediction should narrow the speed gap. -## 8. Publier une version sur ollama.com +## 8. Publishing a version on ollama.com -La 0.2 beta est publiée sous le compte `delairvictor9`. Pour publier une nouvelle version, suivez ces étapes. Le script refuse de pousser des versions non MLX sous les tags principaux : construisez-les sur un Mac Apple Silicon. +0.2 beta is published under the `delairvictor9` account. To publish a new version, follow these steps. The script refuses to push non-MLX builds under the main tags: build them on an Apple Silicon Mac. -1. Créez un compte sur [ollama.com](https://ollama.com/signup). Le nom d'utilisateur devient le préfixe du modèle (`/flycoder`). -2. Reliez la machine au compte : `ollama signin`, puis validez dans le navigateur. Les machines autorisées se gèrent dans les réglages du compte, rubrique des clés Ollama ; retirez celles dont vous ne vous servez plus. -3. Construisez les deux variantes : `sh install.sh --all`. -4. Publiez : `sh scripts/publish.sh `. Ajoutez `--gguf` pour publier aussi `0.2-beta-gguf` et `0.2-beta-fast-gguf`. -5. Sur la page `https://ollama.com//flycoder`, collez le texte de [docs/ollama-model-page.md](docs/ollama-model-page.md). +1. Create an account on [ollama.com](https://ollama.com/signup). The username becomes the model's prefix (`/flycoder`). +2. Link the machine to the account: `ollama signin`, then confirm in the browser. Authorized machines are managed in the account settings, under Ollama keys; remove the ones you no longer use. +3. Build both variants: `sh install.sh --all`. +4. Publish: `sh scripts/publish.sh `. Add `--gguf` to also publish the GGUF tags (`0.2-beta-gguf`, `0.2-beta-fast-gguf`, `0.2-beta-lite-gguf`, `router-gguf`). +5. On the `https://ollama.com//flycoder` page, paste the text of [docs/ollama-model-page.md](docs/ollama-model-page.md). -Tags publiés : `0.2-beta` et `latest` (principale), `0.2-beta-fast` et `fast` (rapide), plus les deux tags GGUF avec `--gguf`. Les poids déjà présents sur le registre d'Ollama ne sont pas renvoyés : pour la 0.2, dont les bases viennent de la bibliothèque officielle, la publication des six tags n'a pris que quelques minutes. +Published tags: `0.2-beta` and `latest` (main), `0.2-beta-fast` and `fast` (fast), `0.2-beta-lite` and `router` (FlyBrain experts), plus the GGUF tags with `--gguf`. Weights already on Ollama's registry are not uploaded again: for 0.2, whose bases come from the official library, publishing the six tags took only a few minutes. -Pour une nouvelle version, mettez à jour la version dans `package.json`, `install.sh`, `scripts/publish.sh` et la consigne système des deux Modelfiles. `npm test` vérifie qu'ils concordent. +For a new version, update the version in `package.json`, `install.sh`, `scripts/publish.sh` and the system prompt of the Modelfiles. `npm test` checks that they agree. -## 9. Dépannage +## 9. Troubleshooting -| Symptôme | Cause probable | Solution | +| Symptom | Likely cause | Fix | |---|---|---| -| `this model requires MLX support` | machine sans Apple Silicon, ou Ollama trop ancien | mettre Ollama à jour ; sinon `sh install.sh --gguf` ou les tags `-gguf` | -| `requires a newer version of Ollama` | Ollama antérieur à 0.31 | mettre à jour depuis https://ollama.com/download | -| L'installateur dit « Ollama ne répond pas » | application fermée | ouvrir Ollama, ou lancer `ollama serve` | -| Réponses très lentes, `ollama ps` montre une part CPU | mémoire insuffisante, le modèle déborde du GPU | fermer des applications, réduire `num_ctx`, ou passer à `flycoder:fast` | -| Le modèle s'arrête ou plante au chargement | mémoire saturée | idem ; un seul gros modèle chargé à la fois | -| Le modèle oublie le début d'un long fichier | contexte trop petit | agrandir `num_ctx` (section 6.2) | -| Réflexion trop longue | question simple traitée en mode réflexion | `--think=false` ou `/set nothink` | -| Répétitions sans fin | température modifiée trop basse | revenir aux réglages du Modelfile | -| `npm run bench` : « Reference solution failed » | `python3` ou `node` absent, ou sandbox refusée | `xcode-select --install`, Node 22, ou `--no-sandbox` | -| `publish.sh` : « n'est pas la version MLX » | variantes construites en GGUF | relancer `sh install.sh --all` sur un Mac Apple Silicon | - -## 10. Développement - -### 10.1 Structure du dépôt - -| Chemin | Rôle | +| `this model requires MLX support` | machine without Apple Silicon, or Ollama too old | update Ollama; otherwise `sh install.sh --gguf` or the `-gguf` tags | +| `requires a newer version of Ollama` | Ollama older than 0.31 | update from https://ollama.com/download | +| The installer says "Ollama is not responding" | the app is closed | open Ollama, or run `ollama serve` | +| Very slow answers, `ollama ps` shows a CPU share | not enough memory, the model spills out of the GPU | close applications, lower `num_ctx`, or switch to `flycoder:fast` | +| The model stops or crashes while loading | memory full | same; only one large model loaded at a time | +| The model forgets the start of a long file | context too small | enlarge `num_ctx` (section 6.2) | +| Thinking takes too long | simple question handled in thinking mode | `--think=false` or `/set nothink` | +| Endless repetition | temperature changed to a value that is too low | go back to the Modelfile's settings | +| `npm run bench`: "Reference solution failed" | `python3` or `node` missing, or sandbox refused | `xcode-select --install`, Node 22, or `--no-sandbox` | +| `publish.sh`: "is not the MLX build" | variants built as GGUF | rerun `sh install.sh --all` on an Apple Silicon Mac | + +## 10. Development + +### 10.1 Repository layout + +| Path | Role | |---|---| -| `Modelfile`, `Modelfile.fast` | définitions des deux variantes | -| `Modelfile.lite`, `Modelfile.router` | expert 2B et micro-modèle de FlyBrain | -| `brain/flybrain.mjs`, `brain/router.mjs` | serveur FlyBrain et règles de routage | -| `brain/eval-router.mjs`, `tests/fixtures/route-prompts.json` | mesure de la justesse du routeur | -| `install.sh` | installateur en une commande | -| `scripts/publish.sh` | publication sur ollama.com | -| `bench/bench.mjs`, `bench/problems.mjs` | banc d'essai et exercices | -| `bench/baselines/` | profil de la 0.1, pour comparer | -| `docs/bench/` | résultats de référence | -| `docs/ollama-model-page.md` | texte de la page ollama.com | -| `tests/` | tests du banc, des Modelfiles et des scripts | -| `.github/workflows/test.yml` | CI sur Linux et macOS | -| `training/`, `scripts/build_language_dataset.js`, `server/fly-language.js` | ancien pipeline de voix FlyBrain, indépendant de FlyCoder | +| `Modelfile`, `Modelfile.fast` | definitions of the two variants | +| `Modelfile.lite`, `Modelfile.router` | FlyBrain's 2B expert and micro-model | +| `brain/flybrain.mjs`, `brain/router.mjs` | FlyBrain server and routing rules | +| `brain/eval-router.mjs`, `tests/fixtures/route-prompts.json` | router accuracy measurement | +| `install.sh` | one-command installer | +| `scripts/publish.sh` | publishing on ollama.com | +| `bench/bench.mjs`, `bench/problems.mjs` | benchmark and problems | +| `bench/baselines/` | 0.1 profile, for comparison | +| `docs/bench/` | reference results | +| `docs/ollama-model-page.md` | text of the ollama.com page | +| `tests/` | tests for the bench, the Modelfiles and the scripts | +| `.github/workflows/test.yml` | CI on Linux and macOS | +| `training/`, `scripts/build_language_dataset.js`, `server/fly-language.js` | former FlyBrain voice pipeline, independent of FlyCoder; the voice speaks French by design | ### 10.2 Tests @@ -388,54 +389,54 @@ Pour une nouvelle version, mettez à jour la version dans `package.json`, `insta npm test ``` -Les tests vérifient : +The tests check: -- que chaque solution de référence passe ses tests cachés, et qu'une solution vide échoue ; -- l'extraction du code des réponses et le calcul des statistiques ; -- la lecture des réponses en flux continu et le délai limite d'exécution ; -- que les deux Modelfiles partent des bonnes bases, avec les réglages attendus et une consigne identique hormis le nom de la base ; -- que l'installateur et le script de publication concordent avec les Modelfiles et la version ; -- les règles de FlyBrain (les 20 exercices du banc vont au gros modèle), le repli vers le gros modèle quand le micro-modèle échoue, la mémoire de conversation et l'ordonnanceur ; -- le serveur FlyBrain contre un faux Ollama : réécriture du modèle sur les API native, OpenAI et Anthropic, flux transmis, un seul expert chargé à la fois. +- that each reference solution passes its hidden tests, and that an empty solution fails; +- code extraction from answers and the statistics; +- reading streamed answers and the execution time limit; +- that the Modelfiles start from the right bases, with the expected settings and an identical system prompt apart from the base name; +- that the installer and the publishing script agree with the Modelfiles and the version; +- FlyBrain's rules (the 20 bench problems go to the large model), the fallback to the large model when the micro-model fails, conversation memory and the scheduler; +- the FlyBrain server against a fake Ollama: model rewriting on the native, OpenAI and Anthropic APIs, streaming passed through, a single expert loaded at a time. -La CI les lance sur Linux et sur macOS, où les solutions de référence tournent dans la sandbox. +CI runs them on Linux and on macOS, where the reference solutions run inside the sandbox. -### 10.3 Modifier la consigne système +### 10.3 Changing the system prompt -Modifiez le bloc `SYSTEM` des deux Modelfiles à l'identique (seule la phrase qui nomme la base diffère), lancez `npm test`, reconstruisez avec `ollama create`, puis comparez avant et après avec `npm run bench`. +Edit the `SYSTEM` block of the Modelfiles identically (only the sentence naming the base differs), run `npm test`, rebuild with `ollama create`, then compare before and after with `npm run bench`. -### 10.4 Ajouter un exercice au banc +### 10.4 Adding a problem to the bench -Ajoutez un objet à `bench/problems.mjs` avec : +Add an object to `bench/problems.mjs` with: -- `id` (préfixe `py-` ou `js-`) ; -- `language` (`python` ou `javascript`) ; -- `entry` (fonction ou classe attendue) ; -- `prompt` (seul texte envoyé au modèle) ; -- `reference` (solution correcte) ; +- `id` (`py-` or `js-` prefix); +- `language` (`python` or `javascript`); +- `entry` (expected function or class); +- `prompt` (the only text sent to the model); +- `reference` (correct solution); - `test` (assertions). -`npm test` refuse l'exercice si la référence échoue ou si une solution vide passe. +`npm test` rejects the problem if the reference fails or if an empty solution passes. -## 11. Limites connues +## 11. Known limitations -- Les poids ne sont pas réentraînés : FlyCoder est un profil de modèles existants. -- Les chiffres LiveCodeBench (72,0 % pour Gemma 4 12B, 55,8 % pour Qwen3.5 4B) sont ceux publiés par Google et Qwen, pas des mesures FlyCoder. -- Le banc compte 20 exercices et un essai par exercice : il départage des profils, sans remplacer un benchmark public. -- La vitesse sur Mac n'a pas été mesurée pour cette version. Les gains MLX (environ +20 %) et multi-tokens (environ +90 % sur Apple Silicon) sont ceux annoncés par Ollama ; sur processeur, le gain multi-tokens mesuré est de 49 %. -- Le mode réflexion n'a pas été mesuré par le banc. -- Les tags MLX ne fonctionnent que sur Apple Silicon. -- FlyBrain ne baisse pas le pic de mémoire des demandes difficiles, et changer d'expert coûte quelques secondes. Ses mesures (mémoire, justesse sur 60 demandes) viennent d'un serveur Linux en GGUF, pas d'un Mac en MLX. Les règles ont été retouchées une fois après une première mesure sur ces mêmes demandes : le score sur des demandes nouvelles peut être un peu plus bas. +- The weights are not retrained: FlyCoder is a profile of existing models. +- The LiveCodeBench figures (72.0% for Gemma 4 12B, 55.8% for Qwen3.5 4B) are the ones published by Google and Qwen, not FlyCoder measurements. +- The bench has 20 problems and one attempt per problem: it separates profiles without replacing a public benchmark. +- Speed on a Mac has not been measured for this version. The MLX (about +20%) and multi-token (about +90% on Apple Silicon) gains are those reported by Ollama; on CPU, the measured multi-token gain is 49%. +- Thinking mode has not been measured by the bench. +- The MLX tags only work on Apple Silicon. +- FlyBrain does not lower the memory peak of hard requests, and switching experts costs a few seconds. Its measurements (memory, accuracy on 60 requests) come from a Linux server running GGUF, not from a Mac running MLX. The rules were adjusted once after a first measurement on these same requests: the score on new requests may be a little lower. -## 12. Historique des versions +## 12. Version history -| Version | Contenu | +| Version | Contents | |---|---| -| 0.1 beta | Atelier complet : Qwen3.5 4B, contrôleur FlyBrain entraînable, CLI, interface web et Electron, agents architecte, codeur et relecteur. | -| 0.2 beta | FlyCoder devient uniquement un modèle Ollama : variante Gemma 4 12B (MLX, multi-tokens) et variante Qwen3.5 4B corrigée, installation en une commande, publication ollama.com, banc d'essai à tests cachés, atelier retiré. | -| 0.3 beta | Routeur FlyBrain facultatif : règles et micro-modèle Qwen3.5 0.8B, expert 2B pour `flycoder:fast`, un seul expert en mémoire. Moins de RAM pour les demandes simples. Les modèles 0.2 sont inchangés. | +| 0.1 beta | Full workshop: Qwen3.5 4B, trainable FlyBrain controller, CLI, web and Electron interfaces, architect, coder and reviewer agents. | +| 0.2 beta | FlyCoder becomes an Ollama model only: Gemma 4 12B variant (MLX, multi-token) and a fixed Qwen3.5 4B variant, one-command install, ollama.com publishing, hidden-test benchmark, workshop removed. | +| 0.3 beta | Optional FlyBrain router: rules and a Qwen3.5 0.8B micro-model, a 2B expert for `flycoder:fast`, a single expert in memory. Less RAM for simple requests. The 0.2 models are unchanged. | -## 13. Licences +## 13. Licenses -- Code du dépôt : MIT, voir [license.md](license.md). -- Poids : Apache 2.0 pour Gemma 4 et pour Qwen3.5. Les conditions de chaque base s'affichent avec `ollama show flycoder --license`. +- Repository code: MIT, see [license.md](license.md). +- Weights: Apache 2.0 for Gemma 4 and for Qwen3.5. Each base's terms are shown by `ollama show flycoder --license`. diff --git a/bench/bench.mjs b/bench/bench.mjs index 5e400b8..4eb70a8 100644 --- a/bench/bench.mjs +++ b/bench/bench.mjs @@ -127,7 +127,7 @@ export function summarize(model, results) { export function table(summaries) { const rows = summaries.map(s => `| ${s.model} | ${s.passed}/${s.total} (${(s.passRate * 100).toFixed(0)} %) | ${s.decodeTokensPerSecond?.toFixed(1) ?? '-'} | ${s.prefillTokensPerSecond?.toFixed(0) ?? '-'} | ${s.meanOutputTokens.toFixed(0)} | ${s.meanSecondsPerProblem.toFixed(1)} |`); - return ['| Modèle | Tests réussis | Génération (tok/s) | Lecture du prompt (tok/s) | Tokens produits / problème | Secondes / problème |', '|---|---|---|---|---|---|', ...rows].join('\n'); + return ['| Model | Tests passed | Generation (tok/s) | Prompt processing (tok/s) | Tokens generated / problem | Seconds / problem |', '|---|---|---|---|---|---|', ...rows].join('\n'); } async function main() { @@ -175,7 +175,7 @@ async function main() { } save(); console.log(table(report.models.map(m => m.summary))); - console.log(`\nDétails : ${out}`); + console.log(`\nDetails: ${out}`); } if (process.argv[1] && import.meta.url === pathToFileURL(fs.realpathSync(process.argv[1])).href) { diff --git a/brain/eval-router.mjs b/brain/eval-router.mjs index 84a75f2..4c33daa 100644 --- a/brain/eval-router.mjs +++ b/brain/eval-router.mjs @@ -29,11 +29,11 @@ for (const c of cases) { } const count = f => rows.filter(f).length; const decided = rows.filter(r => r.rule !== 'unsure'); -console.log(`Cas : ${rows.length} (${count(r => r.want === 'simple')} simples, ${count(r => r.want === 'hard')} difficiles)`); -console.log(`Règles seules : ${decided.length} décidés, ${count(r => r.rule !== 'unsure' && r.rule === r.want)} justes, ${count(r => r.rule === 'unsure')} confiés au micro-modèle`); -console.log(`Règles + micro-modèle : ${count(r => r.final === r.want)}/${rows.length} justes`); -console.log(` difficile envoyé au petit expert (perte de qualité) : ${count(r => r.want === 'hard' && r.final === 'simple')}`); -console.log(` simple envoyé au gros expert (temps et RAM en plus) : ${count(r => r.want === 'simple' && r.final === 'hard')}`); +console.log(`Cases: ${rows.length} (${count(r => r.want === 'simple')} simple, ${count(r => r.want === 'hard')} hard)`); +console.log(`Rules alone: ${decided.length} decided, ${count(r => r.rule !== 'unsure' && r.rule === r.want)} correct, ${count(r => r.rule === 'unsure')} handed to the micro-model`); +console.log(`Rules + micro-model: ${count(r => r.final === r.want)}/${rows.length} correct`); +console.log(` hard sent to the small expert (quality loss): ${count(r => r.want === 'hard' && r.final === 'simple')}`); +console.log(` simple sent to the large expert (extra time and RAM): ${count(r => r.want === 'simple' && r.final === 'hard')}`); const times = rows.filter(r => r.modelMs).map(r => r.modelMs).sort((a, b) => a - b); -if (times.length) console.log(`Micro-modèle : médiane ${times[Math.floor(times.length / 2)]} ms sur ${times.length} appels`); -for (const r of rows.filter(r => r.final !== r.want)) console.log(` ✗ voulu ${r.want}, obtenu ${r.final} (${r.rule}) : ${r.text.slice(0, 90).replace(/\n/g, ' ')}`); +if (times.length) console.log(`Micro-model: median ${times[Math.floor(times.length / 2)]} ms over ${times.length} calls`); +for (const r of rows.filter(r => r.final !== r.want)) console.log(` ✗ wanted ${r.want}, got ${r.final} (${r.rule}): ${r.text.slice(0, 90).replace(/\n/g, ' ')}`); diff --git a/brain/flybrain.mjs b/brain/flybrain.mjs index e71fced..9e88ce7 100644 --- a/brain/flybrain.mjs +++ b/brain/flybrain.mjs @@ -98,9 +98,9 @@ function main() { const maxExpert = values['max-expert'] === 'auto' ? defaultMaxExpert() : values['max-expert']; if (!['full', 'fast'].includes(maxExpert)) throw new Error('--max-expert must be auto, full or fast'); const server = createFlyBrain({ ollama: values.ollama, prefix: values.prefix, maxExpert }); - server.listen(Number(values.port), values.host, () => console.error(`FlyBrain écoute sur http://${values.host}:${values.port} (Ollama : ${values.ollama}, expert max : ${maxExpert}). Modèles : flycoder, flycoder:fast`)); + server.listen(Number(values.port), values.host, () => console.error(`FlyBrain listening on http://${values.host}:${values.port} (Ollama: ${values.ollama}, max expert: ${maxExpert}). Models: flycoder, flycoder:fast`)); } if (process.argv[1] && import.meta.url === pathToFileURL(fs.realpathSync(process.argv[1])).href) { - try { main(); } catch (error) { console.error(`FlyBrain : ${error.message}`); process.exitCode = 1; } + try { main(); } catch (error) { console.error(`FlyBrain: ${error.message}`); process.exitCode = 1; } } diff --git a/install.sh b/install.sh index 5c4dc4f..24a73bb 100755 --- a/install.sh +++ b/install.sh @@ -14,7 +14,7 @@ REF=${FLYCODER_REF:-main} RAW=https://raw.githubusercontent.com/Tromset/flycoder/$REF say() { printf '%s\n' "$@"; } -die() { printf 'FlyCoder : %s\n' "$*" >&2; exit 1; } +die() { printf 'FlyCoder: %s\n' "$*" >&2; exit 1; } choice=auto engine=auto @@ -26,20 +26,20 @@ for arg in "$@"; do --gguf) engine=gguf ;; --no-brain) brain=no ;; -h|--help) sed -n '2,9p' "$0" 2>/dev/null || true; exit 0 ;; - *) die "option inconnue : $arg" ;; + *) die "unknown option: $arg" ;; esac done -command -v ollama >/dev/null 2>&1 || die "Ollama n'est pas installé. Téléchargez-le sur https://ollama.com/download puis relancez cette commande." -ollama list >/dev/null 2>&1 || die "Ollama ne répond pas. Ouvrez l'application Ollama (ou lancez 'ollama serve') puis relancez." +command -v ollama >/dev/null 2>&1 || die "Ollama is not installed. Download it from https://ollama.com/download, then run this command again." +ollama list >/dev/null 2>&1 || die "Ollama is not responding. Open the Ollama app (or run 'ollama serve'), then try again." # Version check: returns success when $1 >= $2 (x.y.z). version_ge() { [ "$(printf '%s\n%s\n' "$2" "$1" | sort -t. -k1,1n -k2,2n -k3,3n | head -n 1)" = "$2" ] } current=$(ollama --version 2>/dev/null | sed -n 's/.*version is \([0-9][0-9.]*\).*/\1/p' | head -n 1) -[ -n "$current" ] || die "impossible de lire la version d'Ollama." -version_ge "$current" "$MIN_OLLAMA" || die "Ollama $current est trop ancien. FlyCoder $VERSION demande Ollama $MIN_OLLAMA ou plus récent : https://ollama.com/download" +[ -n "$current" ] || die "could not read the Ollama version." +version_ge "$current" "$MIN_OLLAMA" || die "Ollama $current is too old. FlyCoder $VERSION needs Ollama $MIN_OLLAMA or later: https://ollama.com/download" os=$(uname -s) arch=$(uname -m) @@ -65,7 +65,7 @@ trap 'rm -rf "$workdir"' EXIT trap 'exit 130' INT TERM fetch() { if [ -f "$here/$1" ] && grep -q "FlyCoder" "$here/$1"; then cp "$here/$1" "$workdir/$1" - else curl -fsSL "$RAW/$1" -o "$workdir/$1" || die "téléchargement impossible : $RAW/$1"; fi + else curl -fsSL "$RAW/$1" -o "$workdir/$1" || die "download failed: $RAW/$1"; fi } build() { # build @@ -75,14 +75,14 @@ build() { # build base=$4 sed "s|^FROM $3\$|FROM $4|" "$workdir/$1" > "$workdir/$1.gguf" && mv "$workdir/$1.gguf" "$workdir/$1" fi - grep -q "^FROM $base\$" "$workdir/$1" || die "$1 ne part pas de $base." - say "" "==> Téléchargement de la base $base" + grep -q "^FROM $base\$" "$workdir/$1" || die "$1 does not start from $base." + say "" "==> Downloading base model $base" ollama pull "$base" - say "==> Création de flycoder:$2" + say "==> Creating flycoder:$2" ollama create "flycoder:$2" -f "$workdir/$1" } -say "FlyCoder $VERSION · Ollama $current · $os $arch · ${memory_gb} Go · moteur $engine" +say "FlyCoder $VERSION · Ollama $current · $os $arch · ${memory_gb} GB · $engine engine" case $choice in default) build Modelfile "$VERSION" gemma4:12b-mlx gemma4:12b; ollama cp "flycoder:$VERSION" flycoder:latest ;; fast) build Modelfile.fast "$VERSION-fast" qwen3.5:4b-mlx qwen3.5:4b; ollama cp "flycoder:$VERSION-fast" flycoder:latest ;; @@ -102,15 +102,15 @@ if [ "$brain" = yes ]; then mkdir -p "$brain_dir" for file in brain/router.mjs brain/flybrain.mjs; do if [ -f "$here/$file" ]; then cp "$here/$file" "$brain_dir/" - else curl -fsSL "$RAW/$file" -o "$brain_dir/${file#brain/}" || die "téléchargement impossible : $RAW/$file"; fi + else curl -fsSL "$RAW/$file" -o "$brain_dir/${file#brain/}" || die "download failed: $RAW/$file"; fi done fi -say "" "FlyCoder est installé. Lancez : ollama run flycoder" +say "" "FlyCoder is installed. Run: ollama run flycoder" if [ "$brain" = yes ]; then - say "Avec le routeur FlyBrain (moins de RAM, Node 22) : node $brain_dir/flybrain.mjs" \ - "puis, dans un autre terminal : OLLAMA_HOST=127.0.0.1:11435 ollama run flycoder" - if [ "$choice" = fast ]; then say "(sans le modèle 12B, lancez FlyBrain avec --max-expert fast)"; fi + say "With the FlyBrain router (less RAM, Node 22): node $brain_dir/flybrain.mjs" \ + "then, in another terminal: OLLAMA_HOST=127.0.0.1:11435 ollama run flycoder" + if [ "$choice" = fast ]; then say "(without the 12B model, start FlyBrain with --max-expert fast)"; fi fi -[ "$choice" = default ] && say "Version la plus rapide (8 Go) : sh install.sh --fast" +[ "$choice" = default ] && say "Fastest version (8 GB): sh install.sh --fast" exit 0 diff --git a/readme.md b/readme.md index ddd6079..9d92823 100644 --- a/readme.md +++ b/readme.md @@ -1,161 +1,161 @@ # FlyCoder 0.3 beta -FlyCoder est un modèle de code local pour Ollama, réglé pour les MacBook et Mac mini Apple Silicon. Vous l'utilisez directement avec `ollama run`, ou dans n'importe quel outil compatible Ollama. Depuis la 0.3, le routeur facultatif **FlyBrain** n'active que la partie de FlyCoder dont une demande a besoin, ce qui baisse la mémoire utilisée (voir plus bas). +FlyCoder is a local coding model for Ollama, tuned for Apple Silicon MacBooks and Mac minis. Use it directly with `ollama run`, or from any Ollama-compatible tool. Since 0.3, the optional **FlyBrain** router only activates the part of FlyCoder a request needs, which lowers memory use (see below). -Documentation complète (installation, utilisation, API, réglages, banc d'essai, publication, dépannage) : [Documentation.md](Documentation.md). +Full documentation (installation, usage, API, settings, benchmark, publishing, troubleshooting): [Documentation.md](Documentation.md). -## Installer en une commande +## One-command install -Il faut [Ollama](https://ollama.com/download) 0.31 ou plus récent, ouvert. FlyCoder est publié sur [ollama.com/delairvictor9/flycoder](https://ollama.com/delairvictor9/flycoder) : +You need [Ollama](https://ollama.com/download) 0.31 or later, running. FlyCoder is published at [ollama.com/delairvictor9/flycoder](https://ollama.com/delairvictor9/flycoder): ```sh -ollama run delairvictor9/flycoder # Gemma 4 12B, Mac 16 Go et plus -ollama run delairvictor9/flycoder:fast # Qwen3.5 4B, Mac 8 Go +ollama run delairvictor9/flycoder # Gemma 4 12B, Macs with 16 GB or more +ollama run delairvictor9/flycoder:fast # Qwen3.5 4B, 8 GB Macs ``` -Ou, pour l'installer sous le nom court `flycoder` avec la variante choisie selon la mémoire du Mac : +Or, to install it under the short name `flycoder`, with the variant picked from your Mac's memory: ```sh curl -fsSL https://raw.githubusercontent.com/Tromset/flycoder/main/install.sh | sh ollama run flycoder ``` -L'installateur détecte la mémoire du Mac et construit la bonne variante dans votre Ollama local : `flycoder:0.2-beta` à partir de 16 Go, `flycoder:0.2-beta-fast` en dessous. Dans les deux cas, `ollama run flycoder` fonctionne. Options : `sh -s -- --fast` (variante rapide), `sh -s -- --all` (les deux), `sh -s -- --gguf` (poids GGUF pour Mac Intel, Linux ou Windows). +The installer detects your Mac's memory and builds the right variant in your local Ollama: `flycoder:0.2-beta` from 16 GB up, `flycoder:0.2-beta-fast` below that. Either way, `ollama run flycoder` works. Options: `sh -s -- --fast` (fast variant), `sh -s -- --all` (both), `sh -s -- --gguf` (GGUF weights for Intel Macs, Linux or Windows). -## Les deux variantes +## The two variants -| Tag | Base | Poids | Mac conseillé | Contexte | +| Tag | Base | Weights | Recommended Mac | Context | |---|---|---|---|---| -| `flycoder:0.2-beta` (`latest`) | Gemma 4 12B, Google DeepMind | 7,7 Go, NVFP4 sur MLX | 16 Go et plus | 32 768 tokens | -| `flycoder:0.2-beta-fast` (`fast`) | Qwen3.5 4B, Alibaba Qwen | 4,0 Go, NVFP4 sur MLX | 8 Go et plus | 16 384 tokens | +| `flycoder:0.2-beta` (`latest`) | Gemma 4 12B, Google DeepMind | 7.7 GB, NVFP4 on MLX | 16 GB or more | 32,768 tokens | +| `flycoder:0.2-beta-fast` (`fast`) | Qwen3.5 4B, Alibaba Qwen | 4.0 GB, NVFP4 on MLX | 8 GB or more | 16,384 tokens | -Les deux bases sont sous licence Apache 2.0 et gèrent les outils (tool calling), la réflexion (thinking) et les images. +Both bases are licensed under Apache 2.0 and support tool calling, thinking and images. -## FlyBrain : moins de RAM, même qualité sur les demandes difficiles +## FlyBrain: less RAM, same quality on hard requests -FlyBrain s'inspire du cerveau de la mouche : de petits indices tirés de la demande (comme les cellules de Kenyon du corps pédonculé) suffisent à trancher les cas nets. Quand rien n'est net, un micro-modèle de 0,8 milliard de paramètres décide. Un seul « lobe » expert est ensuite chargé en mémoire. +FlyBrain takes its cue from the fly's brain: small hints drawn from the request (like the Kenyon cells of the mushroom body) are enough to settle the clear cases. When nothing is clear, a 0.8-billion-parameter micro-model decides. Only one expert "lobe" is then loaded into memory. -| Vous appelez | Demande simple | Demande difficile, outils (agents) ou long contexte | Demande ambiguë | +| You call | Simple request | Hard request, tools (agents) or long context | Unclear request | |---|---|---|---| -| `flycoder` | Qwen3.5 4B, avec réflexion | Gemma 4 12B, avec réflexion | le micro-modèle `flycoder:router` (Qwen3.5 0.8B) choisit | -| `flycoder:fast` | `flycoder:0.2-beta-lite` (Qwen3.5 2B) | Qwen3.5 4B | Qwen3.5 4B (pas de micro-modèle) | +| `flycoder` | Qwen3.5 4B, with thinking | Gemma 4 12B, with thinking | the `flycoder:router` micro-model (Qwen3.5 0.8B) decides | +| `flycoder:fast` | `flycoder:0.2-beta-lite` (Qwen3.5 2B) | Qwen3.5 4B | Qwen3.5 4B (no micro-model) | -Mémoire mesurée (mémoire résidente des processus du modèle après une réponse, serveur Linux 16 Go sans GPU, poids GGUF ; sur Mac avec MLX, les valeurs absolues diffèrent) : +Measured memory (resident memory of the model processes after one answer, 16 GB Linux server without a GPU, GGUF weights; on a Mac with MLX the absolute values differ): -| Cas | Sans FlyBrain | Avec FlyBrain | +| Case | Without FlyBrain | With FlyBrain | |---|---|---| -| `flycoder`, demande simple | 10,5 Gio | **6,1 Gio** (4B + micro-modèle) | -| `flycoder`, demande difficile | 10,5 Gio | 10,5 Gio (identique : la qualité est gardée) | -| `flycoder:fast`, demande simple | 4,6 Gio | **3,7 Gio** | -| `flycoder:fast`, demande difficile | 4,6 Gio | 4,6 Gio | +| `flycoder`, simple request | 10.5 GiB | **6.1 GiB** (4B + micro-model) | +| `flycoder`, hard request | 10.5 GiB | 10.5 GiB (unchanged: quality is kept) | +| `flycoder:fast`, simple request | 4.6 GiB | **3.7 GiB** | +| `flycoder:fast`, hard request | 4.6 GiB | 4.6 GiB | -Le routeur se trompe rarement : sur 60 demandes étiquetées (les 20 exercices du banc et 40 demandes écrites pour l'occasion dans [tests/fixtures/route-prompts.json](tests/fixtures/route-prompts.json)), il en aiguille 59 correctement. Aucune demande difficile n'est partie vers le petit modèle ; une question git simple est partie vers le gros. Les règles décident seules 39 fois ; le micro-modèle répond en 0,6 s environ (médiane, sur processeur). Si le micro-modèle échoue ou hésite, la demande part vers le gros modèle. Une conversation garde son expert, et ne peut que monter vers le plus fort. Sous 16 Go de mémoire, FlyBrain plafonne `flycoder` au 4B. +The router is rarely wrong: out of 60 labelled requests (the 20 bench problems plus 40 requests written for the purpose in [tests/fixtures/route-prompts.json](tests/fixtures/route-prompts.json)), it routes 59 correctly. No hard request went to the small model; one simple git question went to the large one. The rules decide on their own 39 times; the micro-model answers in about 0.6 s (median, on CPU). If the micro-model fails or hesitates, the request goes to the large model. A conversation keeps its expert and can only move up to the stronger one. Below 16 GB of memory, FlyBrain caps `flycoder` at the 4B. ```sh -node ~/.flycoder/brain/flybrain.mjs # installé par install.sh ; ou : npm run brain depuis ce dépôt +node ~/.flycoder/brain/flybrain.mjs # installed by install.sh; or: npm run brain from this repository OLLAMA_HOST=127.0.0.1:11435 ollama run flycoder ``` -FlyBrain parle l'API d'Ollama sur le port 11435 et laisse passer tous les autres modèles. Pour un agent de code, pointez-le sur FlyBrain plutôt que sur Ollama : +FlyBrain speaks the Ollama API on port 11435 and passes every other model through. For a coding agent, point it at FlyBrain instead of Ollama: ```sh ANTHROPIC_BASE_URL=http://127.0.0.1:11435 ANTHROPIC_AUTH_TOKEN=ollama ANTHROPIC_API_KEY="" claude --model flycoder # Claude Code -# Codex, OpenCode, Cline… : URL compatible OpenAI http://127.0.0.1:11435/v1, modèle flycoder +# Codex, OpenCode, Cline…: OpenAI-compatible URL http://127.0.0.1:11435/v1, model flycoder ``` -Avec les modèles publiés sur ollama.com plutôt qu'installés par `install.sh` : `ollama pull delairvictor9/flycoder:router` (et `:0.2-beta-lite`, `:0.2-beta-fast`, `:0.2-beta`), puis `node brain/flybrain.mjs --prefix delairvictor9/`. +With the models published on ollama.com rather than installed by `install.sh`: `ollama pull delairvictor9/flycoder:router` (and `:0.2-beta-lite`, `:0.2-beta-fast`, `:0.2-beta`), then `node brain/flybrain.mjs --prefix delairvictor9/`. -## Ce qui change par rapport à la 0.1 +## What changed since 0.1 -**Un modèle de base nettement plus fort.** La 0.1 reposait sur Qwen3.5 4B. Sur LiveCodeBench v6, chiffres publiés par les auteurs en mode réflexion, Gemma 4 12B obtient 72,0 % contre 55,8 % pour Qwen3.5 4B (et 65,6 % pour Qwen3.5 9B, qui serait deux fois plus lent). Son Elo Codeforces publié est de 1659. +**A much stronger base model.** 0.1 was built on Qwen3.5 4B. On LiveCodeBench v6, using the figures published by the authors in thinking mode, Gemma 4 12B scores 72.0% against 55.8% for Qwen3.5 4B (and 65.6% for Qwen3.5 9B, which would be twice as slow). Its published Codeforces Elo is 1659. -**La prédiction multi-tokens limite le coût des 12 milliards de paramètres.** Gemma 4 embarque un petit modèle brouillon qui propose plusieurs tokens d'avance ; le modèle principal les vérifie en une seule passe. Mesuré ici sur 14 réponses de code : 77 % des 6 594 tokens proposés acceptés, 3,35 tokens validés par passe, et une génération 49 % plus rapide qu'avec le brouillon désactivé (2,7 → 4,1 tokens/s sur le même exemple). Ollama annonce environ +90 % sur Apple Silicon. +**Multi-token prediction keeps the cost of 12 billion parameters in check.** Gemma 4 ships a small draft model that proposes several tokens ahead; the main model verifies them in a single pass. Measured here over 14 coding answers: 77% of the 6,594 proposed tokens accepted, 3.35 tokens validated per pass, and generation 49% faster than with the draft disabled (2.7 → 4.1 tokens/s on the same example). Ollama reports about +90% on Apple Silicon. -**Le moteur MLX d'Apple Silicon.** Les deux variantes utilisent les poids NVFP4 du moteur MLX d'Ollama. Selon Ollama, ce format génère environ 20 % plus vite que le Q4_K_M de la 0.1 et divise à peu près par deux la perte de qualité due à la quantification. +**Apple Silicon's MLX engine.** Both variants use NVFP4 weights on Ollama's MLX engine. According to Ollama, this format generates about 20% faster than 0.1's Q4_K_M and roughly halves the quality loss from quantization. -**Des réglages corrigés.** La 0.1 tournait à une température de 0,2, ce que Qwen déconseille (risque de répétitions sans fin et baisse de qualité). La 0.2 applique les réglages officiels : ceux de Google pour Gemma 4, ceux de Qwen pour le code en mode réflexion. +**Fixed settings.** 0.1 ran at a temperature of 0.2, which Qwen advises against (risk of endless repetition and lower quality). 0.2 applies the official settings: Google's for Gemma 4, Qwen's for coding in thinking mode. -**Assez de contexte pour du vrai code.** Sans réglage, Ollama limite à 4 096 tokens les machines de moins de 24 Go. FlyCoder fixe 32 768 tokens (variante principale) et 16 384 (variante rapide). +**Enough context for real code.** Out of the box, Ollama limits machines with less than 24 GB to 4,096 tokens. FlyCoder sets 32,768 tokens (main variant) and 16,384 (fast variant). -**Une consigne système dédiée au code**, courte : respecter exactement les noms et signatures demandés, livrer du code complet sans « TODO », traiter les cas limites, ne pas inventer d'API, ne jamais prétendre avoir exécuté des tests, éviter les failles classiques, répondre dans la langue de l'utilisateur. +**A short system prompt dedicated to code**: keep the requested names and signatures exactly, deliver complete code without "TODO", handle edge cases, never invent APIs, never claim to have run tests, avoid common vulnerabilities, answer in the user's language. -## Vitesse et qualité mesurées +## Measured speed and quality -Le banc d'essai `bench/` contient 20 exercices de code (13 en Python, 7 en JavaScript) avec tests cachés : intervalles, chiffres romains stricts, tri topologique, cache LRU, SemVer, CSV, Dijkstra sur 100 000 arêtes, évaluateur d'expressions, joker `*`/`?` résistant aux cas pathologiques, etc. Chaque test est validé par une solution de référence et rejette une solution vide (`npm test`). +The `bench/` benchmark holds 20 coding problems (13 in Python, 7 in JavaScript) with hidden tests: intervals, strict Roman numerals, topological sort, LRU cache, SemVer, CSV, Dijkstra on 100,000 edges, expression evaluator, `*`/`?` wildcard matching that withstands pathological cases, and more. Each test is validated against a reference solution and rejects an empty solution (`npm test`). -Passage enregistré dans [docs/bench/cpu-nothink.json](docs/bench/cpu-nothink.json), sur un serveur Linux à 4 cœurs **sans GPU** (Ollama 0.35, poids GGUF Q4_K_M, réflexion désactivée comme dans l'ancien atelier, un essai par exercice, 2 048 tokens maximum). Les vitesses absolues sont bien plus basses que sur un Mac ; seules les comparaisons entre profils comptent : +Run recorded in [docs/bench/cpu-nothink.json](docs/bench/cpu-nothink.json), on a 4-core Linux server **without a GPU** (Ollama 0.35, GGUF Q4_K_M weights, thinking disabled as in the former workshop, one attempt per problem, 2,048 tokens maximum). Absolute speeds are much lower than on a Mac; only the comparisons between profiles matter: -| Profil | Base | Exercices réussis | Génération | Tokens par réponse | Temps par exercice | +| Profile | Base | Problems solved | Generation | Tokens per answer | Time per problem | |---|---|---|---|---|---| -| `flycoder0.1beta` (0.1) | Qwen3.5 4B, température 0,2 | 5/20 (25 %) | 6,6 tok/s | 581 | 94 s | -| `flycoder:0.2-beta-fast` | Qwen3.5 4B, réglages Qwen | 5/20 (25 %) | 6,5 tok/s | 537 | 89 s | -| `flycoder:0.2-beta` | Gemma 4 12B, multi-tokens | **14/20 (70 %)** | 3,4 tok/s | 739 | 235 s | +| `flycoder0.1beta` (0.1) | Qwen3.5 4B, temperature 0.2 | 5/20 (25%) | 6.6 tok/s | 581 | 94 s | +| `flycoder:0.2-beta-fast` | Qwen3.5 4B, Qwen settings | 5/20 (25%) | 6.5 tok/s | 537 | 89 s | +| `flycoder:0.2-beta` | Gemma 4 12B, multi-token | **14/20 (70%)** | 3.4 tok/s | 739 | 235 s | -Ce que ces chiffres disent : +What these numbers say: -- **La variante principale résout presque trois fois plus d'exercices** que la 0.1 : 14 contre 5, dont l'évaluateur d'expressions, le parseur CSV, le cache LRU, les chiffres romains stricts et l'écriture des nombres en toutes lettres, tous ratés par la 0.1. -- **Elle est plus lente par exercice sur ce serveur** : environ 2,5 fois le temps de la 0.1, car elle écrit un code plus complet (validations, docstrings) et chaque token coûte plus cher sur processeur. Sur Mac, le moteur MLX et le gain multi-tokens, plus fort sur GPU, devraient réduire cet écart ; ce n'est pas encore mesuré. -- **La variante rapide garde exactement la vitesse de la 0.1** (6,5 contre 6,6 tokens/s, 89 contre 94 s par exercice) avec le même taux de réussite sans réflexion, et 8 % de tokens en moins. Sur Mac, elle gagne en plus le moteur MLX. +- **The main variant solves almost three times as many problems** as 0.1: 14 against 5, including the expression evaluator, the CSV parser, the LRU cache, strict Roman numerals and spelling numbers out in words, all failed by 0.1. +- **It is slower per problem on this server**: about 2.5 times 0.1's time, because it writes more complete code (validation, docstrings) and each token costs more on CPU. On a Mac, the MLX engine and the multi-token gain, which is larger on GPU, should narrow that gap; this is not measured yet. +- **The fast variant keeps exactly 0.1's speed** (6.5 against 6.6 tokens/s, 89 against 94 s per problem) with the same pass rate without thinking, and 8% fewer tokens. On a Mac, it also gains the MLX engine. -Sept exercices de la variante principale et un de la variante rapide ont été relancés : au premier passage, le serveur avait manqué de mémoire ou le banc avait coupé la requête après 5 minutes. Ce sont des pannes d'infrastructure, pas des réponses ; le banc envoie désormais les réponses en flux continu et relance une fois un modèle qui plante. +Seven problems for the main variant and one for the fast variant were rerun: on the first pass, the server had run out of memory or the bench had cut the request after 5 minutes. These were infrastructure failures, not answers; the bench now streams answers and retries a crashed model once. -Pour mesurer sur votre Mac : +To measure on your Mac: ```sh -ollama create flycoder0.1beta -f bench/baselines/flycoder-0.1-beta.Modelfile # pour comparer à la 0.1 +ollama create flycoder0.1beta -f bench/baselines/flycoder-0.1-beta.Modelfile # to compare with 0.1 npm run bench -- --models flycoder0.1beta,flycoder:0.2-beta,flycoder:0.2-beta-fast ``` -Le banc exécute le code produit par les modèles sur votre machine, dans un dossier temporaire, avec un délai limite ; sur macOS, `sandbox-exec` lui interdit le réseau et l'écriture hors de ce dossier. Options utiles : `--think on|off`, `--samples 3`, `--only py-lcs,js-evaluate`. +The bench runs the code the models produce on your machine, in a temporary folder, with a time limit; on macOS, `sandbox-exec` blocks network access and writes outside that folder. Useful options: `--think on|off`, `--samples 3`, `--only py-lcs,js-evaluate`. -## Utilisation +## Usage ```sh -ollama run flycoder # réflexion activée par défaut : meilleure qualité -ollama run flycoder --think=false # réponse immédiate, pour les questions simples -ollama run flycoder:fast # variante 4B si vous l'avez installée +ollama run flycoder # thinking on by default: best quality +ollama run flycoder --think=false # immediate answer, for simple questions +ollama run flycoder:fast # 4B variant if you installed it ``` -Dans une conversation, `/set nothink` coupe la réflexion et `/set parameter num_ctx 65536` agrandit le contexte (environ 0,5 Go de mémoire en plus pour la variante principale). Ollama recommande au moins 64 000 tokens pour les agents de code ; FlyCoder fonctionne aussi avec `ollama launch` (Claude Code, Codex, OpenCode) : `ollama launch claude --model flycoder` si vous l'avez installé avec `install.sh`, ou `ollama launch claude --model delairvictor9/flycoder` depuis ollama.com. `ollama launch` parle directement à Ollama ; pour passer par FlyBrain, voir la section FlyBrain. +In a conversation, `/set nothink` turns thinking off and `/set parameter num_ctx 65536` enlarges the context (about 0.5 GB of extra memory for the main variant). Ollama recommends at least 64,000 tokens for coding agents; FlyCoder also works with `ollama launch` (Claude Code, Codex, OpenCode): `ollama launch claude --model flycoder` if you installed it with `install.sh`, or `ollama launch claude --model delairvictor9/flycoder` from ollama.com. `ollama launch` talks to Ollama directly; to go through FlyBrain, see the FlyBrain section. -Depuis une application, l'API d'Ollama suffit : +From an application, the Ollama API is all you need: ```sh -curl http://localhost:11434/api/chat -d '{"model":"flycoder","messages":[{"role":"user","content":"Écris une fonction Python qui fusionne des intervalles."}]}' +curl http://localhost:11434/api/chat -d '{"model":"flycoder","messages":[{"role":"user","content":"Write a Python function that merges intervals."}]}' ``` -## Publier FlyCoder sur ollama.com +## Publishing FlyCoder on ollama.com -À faire une seule fois, depuis un Mac Apple Silicon : +Done once, from an Apple Silicon Mac: -1. Créez un compte sur [ollama.com](https://ollama.com/signup). Le nom d'utilisateur fera partie du nom du modèle. -2. Reliez ce Mac au compte : `ollama signin`. -3. Construisez les deux variantes : `sh install.sh --all`. -4. Publiez : `sh scripts/publish.sh ` (ajoutez `--gguf` pour publier aussi les versions Mac Intel, Linux et Windows). -5. Collez le texte de [docs/ollama-model-page.md](docs/ollama-model-page.md) dans la description de la page du modèle. +1. Create an account on [ollama.com](https://ollama.com/signup). The username becomes part of the model name. +2. Link this Mac to the account: `ollama signin`. +3. Build both variants: `sh install.sh --all`. +4. Publish: `sh scripts/publish.sh ` (add `--gguf` to also publish the Intel Mac, Linux and Windows builds). +5. Paste the text of [docs/ollama-model-page.md](docs/ollama-model-page.md) into the model page description. -Ensuite, n'importe qui peut lancer `ollama run /flycoder` ou `ollama run /flycoder:fast`. La 0.2 beta est publiée sous `delairvictor9`. +After that, anyone can run `ollama run /flycoder` or `ollama run /flycoder:fast`. 0.2 beta is published under `delairvictor9`. -## Contenu du dépôt +## Repository contents -- `Modelfile`, `Modelfile.fast` : définitions des deux variantes (`ollama create flycoder -f Modelfile`). -- `Modelfile.lite`, `Modelfile.router` : expert 2B et micro-modèle de FlyBrain. -- `brain/` : le serveur FlyBrain (`flybrain.mjs`), ses règles (`router.mjs`) et la mesure de justesse du routeur (`eval-router.mjs`). -- `install.sh` : installation en une commande. `scripts/publish.sh` : publication sur ollama.com. -- `bench/` : banc d'essai qualité et vitesse ; `bench/baselines/` garde le profil 0.1 pour comparer. -- `tests/` : `npm test` vérifie les tests du banc, la cohérence des Modelfiles et des scripts. -- `training/`, `scripts/build_language_dataset.js`, `server/fly-language.js` : pipeline QLoRA de l'ancienne voix FlyBrain (Qwen 2.5 1.5B, MLX), indépendant de FlyCoder. +- `Modelfile`, `Modelfile.fast`: definitions of the two variants (`ollama create flycoder -f Modelfile`). +- `Modelfile.lite`, `Modelfile.router`: FlyBrain's 2B expert and micro-model. +- `brain/`: the FlyBrain server (`flybrain.mjs`), its rules (`router.mjs`) and the router accuracy measurement (`eval-router.mjs`). +- `install.sh`: one-command install. `scripts/publish.sh`: publishing on ollama.com. +- `bench/`: quality and speed benchmark; `bench/baselines/` keeps the 0.1 profile for comparison. +- `tests/`: `npm test` checks the bench tests and the consistency of the Modelfiles and scripts. +- `training/`, `scripts/build_language_dataset.js`, `server/fly-language.js`: QLoRA pipeline for the former FlyBrain voice (Qwen 2.5 1.5B, MLX), independent of FlyCoder. That voice speaks French by design, so its prompts and dataset stay in French. -## Limites de cette beta +## Limitations of this beta -- Les poids ne sont pas réentraînés : FlyCoder 0.2 est un profil Ollama (base, quantification, réglages, contexte, consigne système). Les gains de qualité viennent du changement de base et des réglages, pas d'un fine-tuning. -- Les chiffres LiveCodeBench et Codeforces sont ceux publiés par Google et Qwen, pas des mesures FlyCoder. Le banc fourni est petit (20 exercices) : il départage des profils, il ne remplace pas un benchmark public. -- La vitesse sur Mac n'a pas été mesurée pour cette version : les gains MLX et multi-tokens cités sont ceux annoncés par Ollama. Sur processeur, la variante principale est environ 2,5 fois plus lente par exercice que la 0.1 ; si l'écart reste trop grand sur votre Mac, `ollama cp flycoder:0.2-beta-fast flycoder:latest` fait de la variante rapide le modèle par défaut. -- Sans réflexion, les trois profils laissent parfois une première tentative abandonnée dans le code rendu (3 réponses sur 20 chacun) : gardez la réflexion activée pour du code à livrer. -- Le banc a tourné sans réflexion. Avec la réflexion activée (le défaut de `ollama run`), la qualité monte pour les deux bases mais les réponses sont plus longues ; mesurez-le avec `npm run bench -- --think on`. -- Les variantes MLX demandent un Mac Apple Silicon ; ailleurs, utilisez `--gguf`. -- FlyBrain baisse la mémoire des demandes simples, pas celle des demandes difficiles : le pic reste celui du gros modèle. Changer d'expert prend quelques secondes de rechargement. Les agents (qui envoient des outils) vont toujours au gros modèle. Les mesures de mémoire et du routeur viennent d'un serveur Linux en GGUF, pas encore d'un Mac en MLX. +- The weights are not retrained: FlyCoder 0.2 is an Ollama profile (base, quantization, settings, context, system prompt). The quality gains come from the change of base and settings, not from fine-tuning. +- The LiveCodeBench and Codeforces figures are the ones published by Google and Qwen, not FlyCoder measurements. The bundled bench is small (20 problems): it separates profiles, it does not replace a public benchmark. +- Speed on a Mac has not been measured for this version: the MLX and multi-token gains quoted are those reported by Ollama. On CPU, the main variant is about 2.5 times slower per problem than 0.1; if the gap stays too large on your Mac, `ollama cp flycoder:0.2-beta-fast flycoder:latest` makes the fast variant the default model. +- Without thinking, all three profiles sometimes leave an abandoned first attempt in the returned code (3 answers out of 20 each): keep thinking on for code you ship. +- The bench ran without thinking. With thinking on (the `ollama run` default), quality goes up for both bases but answers are longer; measure it with `npm run bench -- --think on`. +- The MLX variants need an Apple Silicon Mac; elsewhere, use `--gguf`. +- FlyBrain lowers memory for simple requests, not for hard ones: the peak stays that of the large model. Switching experts takes a few seconds of reloading. Agents (which send tools) always go to the large model. The memory and router measurements come from a Linux server running GGUF, not yet from a Mac running MLX. -## Licence +## License -Code du dépôt : MIT, voir [license.md](license.md). Les poids restent sous la licence de leur base : Apache 2.0 pour Gemma 4 et pour Qwen3.5, affichée par `ollama show flycoder --license`. +Repository code: MIT, see [license.md](license.md). The weights keep the license of their base: Apache 2.0 for Gemma 4 and for Qwen3.5, shown by `ollama show flycoder --license`. diff --git a/scripts/publish.sh b/scripts/publish.sh index b7f54d8..a7c47e2 100755 --- a/scripts/publish.sh +++ b/scripts/publish.sh @@ -7,15 +7,15 @@ set -eu VERSION=0.2-beta -die() { printf 'FlyCoder : %s\n' "$*" >&2; exit 1; } +die() { printf 'FlyCoder: %s\n' "$*" >&2; exit 1; } user=${1:-} -[ -n "$user" ] && [ "${user#-}" = "$user" ] || die "usage : sh scripts/publish.sh [--gguf]" +[ -n "$user" ] && [ "${user#-}" = "$user" ] || die "usage: sh scripts/publish.sh [--gguf]" gguf=${2:-} -[ -z "$gguf" ] || [ "$gguf" = --gguf ] || die "option inconnue : $gguf" -command -v ollama >/dev/null 2>&1 || die "Ollama n'est pas installé." +[ -z "$gguf" ] || [ "$gguf" = --gguf ] || die "unknown option: $gguf" +command -v ollama >/dev/null 2>&1 || die "Ollama is not installed." -require() { ollama show "$1" >/dev/null 2>&1 || die "$1 est absent. Lancez d'abord : sh install.sh --all"; } +require() { ollama show "$1" >/dev/null 2>&1 || die "$1 is missing. First run: sh install.sh --all"; } format() { ollama show "$1" 2>/dev/null | awk '/quantization/ {print $2}' | head -n 1; } push() { # push ollama cp "$1" "$user/flycoder:$2" @@ -29,7 +29,7 @@ require "flycoder:$VERSION-lite" require flycoder:router # The main tags must hold the Apple Silicon (MLX) builds, never a GGUF fallback. for model in "flycoder:$VERSION" "flycoder:$VERSION-fast" "flycoder:$VERSION-lite" flycoder:router; do - [ "$(format "$model")" = nvfp4 ] || die "$model n'est pas la version MLX. Publiez depuis un Mac Apple Silicon après : sh install.sh --all" + [ "$(format "$model")" = nvfp4 ] || die "$model is not the MLX build. Publish from an Apple Silicon Mac after: sh install.sh --all" done push "flycoder:$VERSION" "$VERSION" @@ -56,5 +56,5 @@ if [ "$gguf" = --gguf ]; then push flycoder:router-gguf router-gguf fi -printf '\nPublié. Tout le monde peut maintenant lancer :\n ollama run %s/flycoder (Gemma 4 12B, Mac 16 Go et plus)\n ollama run %s/flycoder:fast (Qwen3.5 4B, Mac 8 Go)\n' "$user" "$user" -printf 'Page du modèle : https://ollama.com/%s/flycoder (collez-y docs/ollama-model-page.md)\n' "$user" +printf '\nPublished. Anyone can now run:\n ollama run %s/flycoder (Gemma 4 12B, Macs with 16 GB or more)\n ollama run %s/flycoder:fast (Qwen3.5 4B, 8 GB Macs)\n' "$user" "$user" +printf 'Model page: https://ollama.com/%s/flycoder (paste docs/ollama-model-page.md there)\n' "$user"