11 min de lecture

Gemma 4 peut-il remplacer Claude Code ? Benchmark sur un vrai projet Symfony

Un modèle local de 9.6 GB peut-il générer du code Symfony fonctionnel ? Benchmark de Gemma 4 E4B : 5 scénarios, 15 runs, validation automatisée.

Un modèle local de 9.6 GB peut-il générer du code Symfony fonctionnel ? Benchmark de Gemma 4 E4B : 5 scénarios, 15 runs, validation automatisée.
Mode de lecture :

Pourquoi payer Opus 4.6 ou Codex ? Ollama + un modèle open source et c’est réglé.” On lit ça partout. Alors j’ai voulu vérifier.

Pas avec un hello world ou un script Python de 20 lignes, mais sur un vrai projet Symfony 8 : créer des entités Doctrine, des controllers avec routes, des formulaires avec validation, un CRUD complet. Le tout validé automatiquement par les outils du framework (lint:container, doctrine:mapping:info, PHPUnit…).

Le modèle testé : Gemma 4 E4B de Google (4.5B paramètres, 9.6 GB), le dernier modèle open-weights en date. L’outil : OpenCode, alternative open source à Claude Code. L’inférence : 100% locale via Ollama.

Le verdict : Gemma 4 E4B génère du code Symfony fonctionnel sur des tâches simples, mais s’effondre dès que la complexité augmente. Voici les chiffres.


La stack testée

Le modèle : Gemma 4 E4B

Gemma 4 est la dernière famille de modèles open-weights de Google (avril 2026). Elle se décline en 4 variantes :

VarianteParams totauxParams actifsArchitectureContexteTaille disque
E2B5.1B2.3B effectifsDense (PLE)128K7.2 GB
E4B8B4.5B effectifsDense (PLE)128K9.6 GB
26B25.2B3.8B actifsMoE (8/128 experts)256K17 GB
31B30.7B30.7BDense256K20 GB

Le “E” signifie “Effective parameters” : grâce à une architecture Per-Layer Embeddings (PLE), ces modèles sont optimisés pour tourner sur des appareils avec peu de mémoire. Le E4B est le modèle par défaut de ollama pull gemma4. Il supporte le texte, l’image et l’audio, et le tool calling natif.

Pour comparaison, Claude Opus 4.6 aurait environ 100B paramètres actifs (estimations communautaires, Anthropic ne communique pas ce chiffre). L’intérêt de Gemma 4 E4B est qu’il tourne en local sur un laptop, gratuitement.

Pourquoi pas le 26B ? Malgré ses 25.2B paramètres totaux, le 26B n’a que 3.8B paramètres actifs (moins que le E4B !) grâce à son architecture MoE. Mais il pèse 17 GB sur disque. J’ai essayé : OpenCode a besoin d’au moins 64K tokens de contexte pour transmettre les outils au modèle (voir la section num_ctx). Avec ce contexte, le 26B grimpe à 25 GB en RAM, ce qui dépasse les 24 GB de ma machine. En réduisant à 32K (21 GB), le modèle charge mais le swap rend l’inférence inutilisable : plus de 15 minutes sans produire le moindre résultat. Sur un MacBook 24 GB, le E4B est le seul modèle Gemma 4 réellement exploitable avec OpenCode. Le 26B nécessiterait au minimum 32 GB de RAM.

L’outil : OpenCode

OpenCode est un agent de code en terminal, open source, comparable à Claude Code. Il donne au modèle des outils (write, bash, read, edit…) pour interagir avec le filesystem. Le mode opencode run permet de l’utiliser en non-interactif, parfait pour un benchmark automatisé.

Le projet : Symfony 8

Un projet Symfony 8.0.8 frais (symfony new --webapp), avec PHP 8.5.3. Tous les composants classiques sont disponibles : Doctrine ORM, Form, Validator, Twig, PHPUnit 13.


Le protocole expérimental

La machine de test

ComposantDétail
MachineMacBook Pro M4 Pro
CPU14 cœurs (10P + 4E)
RAM24 GB
OSmacOS 15.7.3
Ollama0.20.0-rc1
OpenCode1.2.15
PHP8.5.3
Symfony8.0.8

Les 5 scénarios

Chaque scénario est un prompt unique envoyé à OpenCode. Le modèle doit utiliser les outils (write) pour créer les fichiers, pas juste afficher du code en texte.

IDDescriptionFichiers attendusComplexité
S1Entity Doctrine + Repository2Basse
S2Controller + Routes + Templates Twig3Moyenne
S3Service avec DI + Test unitaire PHPUnit2Moyenne
S4Form + Validation DTO + Controller4Haute
S5CRUD complet (Entity → Tests)9+Très haute

La validation automatisée

Pour chaque exécution, un pipeline vérifie que le code est fonctionnel (pas juste syntaxiquement correct) :

  1. php -l : syntaxe PHP valide sur chaque fichier
  2. php bin/console lint:container : le conteneur de services Symfony compile
  3. php bin/console lint:twig : les templates Twig sont valides
  4. php bin/console doctrine:mapping:info : Doctrine reconnaît les entités
  5. php bin/console debug:router : les routes sont enregistrées
  6. php bin/phpunit : les tests unitaires passent

Le barème de scoring

Un score de 0 à 100 est calculé à partir de ces vérifications :

VérificationPointsMéthode
Fichiers créés20Tous les fichiers attendus existent
Syntaxe PHP valide20php -l passe sur chaque fichier
Conteneur DI compile20php bin/console lint:container
Templates Twig valides10php bin/console lint:twig
Mapping Doctrine OK10php bin/console doctrine:mapping:info
Routes enregistrées10php bin/console debug:router (proportionnel)
Tests PHPUnit passent10php bin/phpunit (exit code 0)
Total100

Les vérifications non-applicables à un scénario (ex: pas de routes pour S1) sont automatiquement créditées.

Reproductibilité

Chaque scénario est exécuté 3 fois. Entre chaque exécution :

  • git checkout -- . + git clean -fd pour revenir à l’état initial
  • Suppression du cache Symfony
  • Nouvelle session OpenCode (pas de mémoire entre les runs)

Le piège du num_ctx : quand le modèle “oublie” ses outils

Avant de parler des résultats, un point technique crucial que j’ai découvert pendant la mise en place.

Le problème

Avec la configuration par défaut, Gemma 4 refusait d’utiliser les outils d’OpenCode. Au lieu de créer les fichiers avec write, il affichait le code en markdown dans sa réponse, exactement comme un chatbot classique.

Le diagnostic

En interceptant les requêtes entre OpenCode et Ollama, j’ai vérifié que :

  1. OpenCode envoie bien les 11 outils dans la requête (write, bash, read, edit, glob, grep…)
  2. Gemma 4 sait faire du tool calling : un test direct via l’API Ollama fonctionne parfaitement
  3. Le problème est le contexte : le prompt système d’OpenCode + les 11 définitions de tools font ~15-20K tokens

Le num_ctx par défaut d’Ollama est souvent trop petit. Le modèle ne “voit” littéralement pas les outils dans son contexte.

La solution

Créer un modèle Ollama avec un num_ctx de 64K (minimum recommandé par la doc Ollama pour OpenCode) :

# Créer un Modelfile
cat > Modelfile << 'EOF'
FROM gemma4:latest
PARAMETER num_ctx 65536
EOF

# Créer le modèle dérivé
ollama create gemma4-opencode -f Modelfile

Et dans opencode.json :

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "ollama": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Ollama (local)",
      "options": {
        "baseURL": "http://localhost:11434/v1"
      },
      "models": {
        "gemma4-opencode": {
          "name": "Gemma 4 E4B (64k ctx)"
        }
      }
    }
  }
}

⚠️ Attention : avec 64K de contexte, Gemma 4 consomme significativement plus de RAM. Sur un MacBook avec 24 GB, c’est viable mais l’inférence est plus lente (~2 min par scénario).

Après ce changement, le modèle utilise correctement les outils et crée les fichiers sur le disque. Place aux résultats.


Les résultats

Vue d’ensemble

ScénarioScore moyenÉcart-typeSuccèsTemps moyenTokens (sortie)
S1 Entity + Repo86.7/100±18.967%119s1 257
S2 Controller + Twig53.3/100±4.70%102s1 401
S3 Service + Test63.3/100±4.70%130s2 745
S4 Form + DTO50.0/100±0.00%124s1 206
S5 CRUD complet30.0/100±14.10%121s2 307

“Succès” = tous les fichiers créés + syntaxe valide + conteneur DI compile. Score ≠ succès car des points sont accordés pour les vérifications partielles (conteneur OK, Twig OK même si les fichiers ne sont pas tous créés).

Détail par scénario

S1. Entity Doctrine + Repository

Prompt : Créer une entité Article avec 5 propriétés et son ArticleRepository.

RunScoreFichiers créésContainerDoctrineTemps
160Entity seulement (repo manquant)119s
2100Entity + Repository119s
3100Entity + Repository119s

Verdict : Sur la tâche la plus simple, Gemma 4 s’en sort très bien. Le code utilise correctement les attributs PHP 8, les types sont bons, le repository étend ServiceEntityRepository. Le run 1 a simplement oublié de créer le repository, un problème de reproductibilité, pas de compétence.

S2. Controller + Routes + Twig

Prompt : Créer un ArticleController avec 2 actions, routes PHP 8, et 2 templates Twig.

RunScoreFichiers créésRoutesTwigTemps
150Template Twig seulement68s
250Controller seulement119s
360Controller seulement121s

Verdict : Le modèle ne crée jamais tous les fichiers en une passe. Soit il fait le controller, soit les templates, jamais les deux ensemble. C’est la limite du multi-fichier : avec 4.5B paramètres, le modèle perd le fil quand il doit coordonner plusieurs write consécutifs.

S3. Service + DI + Test unitaire

Prompt : Créer un SlugGenerator avec injection de SluggerInterface et un test PHPUnit avec 4 cas.

RunScoreFichiers créésTests PHPUnitTemps
170Service + Test❌ (syntax error)292s
260Aucun50s
360Aucun49s

Verdict : Résultat mitigé. Le run 1 a créé les deux fichiers mais le test PHPUnit contenait une erreur de syntaxe. Les runs 2 et 3 n’ont même pas créé de fichier : le modèle a répondu en texte au lieu d’utiliser les outils. La variance est très élevée (292s vs 50s), signe d’instabilité.

S4. Form + DTO + Validation + Controller

Prompt : Créer un formulaire de contact complet avec DTO, validations, controller et template.

RunScoreFichiers créésRoute /contactTemps
150Aucun76s
250DTO + Form (2/4)231s
350Aucun63s

Verdict : Le scénario multi-fichier (4 fichiers PHP + 1 template) est trop complexe. Un seul run a créé des fichiers, et seulement 2 sur 4. Le controller et le template n’ont jamais été générés. Score stable à 50 (conteneur + twig + yaml toujours OK car aucun fichier cassé n’est ajouté).

S5. CRUD complet

Prompt : Créer un CRUD Product complet : entity, repository, form, controller (7 routes), templates, et test fonctionnel.

RunScoreFichiers créésRoutesDoctrineTemps
140Aucun0/563s
240Aucun0/559s
310Entity + Form + Repo (3/9)0/5241s

Verdict : Le CRUD complet (9+ fichiers) est hors de portée. Le modèle est complètement dépassé : il ne crée quasiment aucun fichier, et quand il en crée (run 3), l’ensemble casse le conteneur DI. Le score de 10 au run 3 montre que la tentative partielle fait plus de mal que de bien.


Analyse

Ce qui fonctionne

  • Tâches simples (1-2 fichiers) : Gemma 4 génère du code Symfony parfaitement fonctionnel. Les entités Doctrine sont correctes, les attributs PHP 8 bien utilisés, les types cohérents.
  • Qualité du code quand il est créé : Quand le modèle réussit à écrire un fichier, le code est propre. Pas de code deprecated, pas d’annotations XML, pas de pratiques obsolètes.
  • Tool calling : Avec le num_ctx à 64K, le modèle utilise correctement les outils write et bash d’OpenCode. C’est une vraie avancée par rapport aux versions précédentes.
  • Coût : Zéro. Tout tourne en local. Sur 15 runs, pas un centime dépensé.

Ce qui ne fonctionne pas (ou mal)

  • Multi-fichier : Dès qu’il faut créer plus de 2 fichiers, le modèle décroche. Il en oublie, ou passe en mode “texte” au lieu d’utiliser les outils.
  • Reproductibilité : Le même prompt donne des résultats très différents d’un run à l’autre (S1 : 60 puis 100 puis 100). Un modèle 4.5B manque de déterminisme.
  • Complexité : Les scénarios S4 et S5 sont hors de portée. Le modèle ne peut pas maintenir la cohérence entre entity, form, controller et templates.
  • Lenteur : ~2 minutes par scénario avec 64K de contexte. C’est 4-10x plus lent qu’un modèle cloud.
  • Erreurs silencieuses : Parfois le modèle ne crée aucun fichier sans erreur visible : il répond simplement en texte au lieu d’utiliser les outils.

Comparaison avec les modèles cloud

Pour mettre en perspective, voici les données publiques sur les modèles cloud en 2026 :

CritèreGemma 4 E4B (local, 4.5B)Claude Opus 4.6 (cloud, ~100B actifs)
CoûtGratuit$5/M input, $25/M output
Latence~2 min/scénario~10-30s/scénario
Tool callingFiable après config num_ctxNatif, stable
Tâches simples (1-2 fichiers)87/100~98-100/100
Tâches complexes (multi-fichier)30-50/100~87-98/100
ReproductibilitéVariable (±19 pts)Très stable
Vie privée100% localDonnées envoyées au cloud

Reproduire ce benchmark

🔗 github.com/yoanbernabeu/gemma4-symfony-benchmark : scripts, configuration et données brutes des 15 runs.

En 3 commandes

git clone https://github.com/yoanbernabeu/gemma4-symfony-benchmark.git
cd gemma4-symfony-benchmark
./setup.sh          # Crée le projet Symfony + modèle Ollama 64k
./benchmark.sh      # Lance les 5 scénarios × 3 runs (~45 min)

Prérequis

OutilVersion min.Installation
Ollama>= 0.20.0ollama.com
OpenCode>= 1.2.0curl -fsSL https://opencode.ai/install | bash
Symfony CLI>= 5.0symfony.com/download
PHP>= 8.4Via votre gestionnaire de packages
Python 3>= 3.9Pour l’agrégation des résultats

Le dépôt contient

FichierRôle
setup.shCrée le projet Symfony, le modèle Ollama 64k, la baseline Git
benchmark.shExécute les 5 scénarios × 3 runs avec validation automatisée
opencode.jsonConfiguration OpenCode → Ollama
ModelfileModelfile Ollama avec num_ctx 65536
results/Données brutes des 15 runs (logs JSON, validations)

Test rapide sans le benchmark complet

# Créer le modèle avec 64k de contexte
echo -e "FROM gemma4:latest\nPARAMETER num_ctx 65536" | ollama create gemma4-opencode -f -

# Dans un projet Symfony existant avec opencode.json configuré :
opencode run "Create a Doctrine entity App\Entity\Article in src/Entity/Article.php with id (integer auto PK), title (string 255), content (text), createdAt (datetime_immutable), isPublished (boolean default false). Use PHP 8 attributes." \
  -m ollama/gemma4-opencode --dir .

# Vérifier
php -l src/Entity/Article.php
php bin/console lint:container
php bin/console doctrine:mapping:info

Conclusion

Gemma 4 E4B n’est pas un remplacement pour Claude Code ou Cursor avec un modèle cloud. C’est un fait, et les chiffres le montrent clairement : 87/100 sur une entité simple, 30/100 sur un CRUD complet.

Mais ce n’est pas la bonne question. La bonne question c’est : un modèle de 4.5B paramètres qui tourne sur un laptop peut-il être utile pour du développement Symfony ?

La réponse est oui, pour des tâches ciblées :

  • Générer une entité Doctrine avec ses getters/setters → ✅
  • Créer rapidement un controller simple → ✅ (avec un peu de chance)
  • Créer un CRUD complet en une passe → ❌

Le vrai apport de ce benchmark, c’est d’avoir identifié le piège du num_ctx. Sans 64K de contexte, Gemma 4 ne voit pas les outils d’OpenCode et se comporte comme un chatbot classique. C’est le genre de détail que personne ne documente et qui fait perdre des heures.

Le combo Ollama + OpenCode + un modèle local est prometteur. Aujourd’hui avec 4.5B paramètres, c’est limité. Mais les modèles locaux progressent vite. La même expérience avec un modèle 26B ou 70B donnerait probablement des résultats très différents. Ce benchmark fournit le protocole pour le vérifier.


Benchmark réalisé le 2 avril 2026 sur MacBook Pro M4 Pro (24 GB). Tous les résultats sont reproductibles avec le script fourni.

Les scripts et les données brutes des 15 runs (logs JSON, validations, code généré) sont disponibles dans le dépôt GitHub.

Back to Blog

Comments (0)

Loading comments...

Leave a Comment