Chess Gemma Commentary 🎯♟️

By NAKST Studio


Fine-tuned Gemma 3 270M model for generating chess move commentary, ELO predictions, and move classifications in 14 languages. Includes an optional .task file for lightweight mobile inference with flutter_gemma

💙 Support & Shape NAKST Studio

Donate Vote Next App

Help us keep building free, privacy-focused chess tools! Support teen developers creating amazing apps without ads or data collection. Vote for what we build next!


Model Details

  • Base Model: Google Gemma 3 270M (270 Million Parameters)
  • Fine-tuning Method: LoRA (Low-Rank Adaptation) - Rank 8, Alpha 16
  • Training Data: 25,000+ chess positions with expert commentary
  • Training Epochs: 3
  • Training Framework: Unsloth + Hugging Face Transformers
  • Hardware: Google Colab T4 GPU
  • Model Size: 500MB (full) / 270 mb .task (int 8 dynamic quantized)
  • Languages Supported: 14 (English, Hindi, Spanish, Mandarin Chinese, French, German, Portuguese, Russian, Japanese, Arabic, Korean, Turkish, Indonesian, Bengali)

Capabilities

Chess Move Commentary - Detailed analysis of chess positions and moves
ELO Prediction - Estimates player skill rating (1000-2800)
Move Classification - Labels moves as Best Move, Good Move, Blunder, etc.
Multilingual Support - Generate commentary in 14 different languages
Mobile Ready - Works on Android with flutter_gemma or Ollama
Offline - No internet required for inference

Supported Languages

Language Code Language Name Native Name
en English English
hi Hindi हिन्दी
es Spanish Español
zh Mandarin Chinese 中文
fr French Français
de German Deutsch
pt Portuguese Português
ru Russian Русский
ja Japanese 日本語
ar Arabic العربية
ko Korean 한국어
tr Turkish Türkçe
id Indonesian Bahasa Indonesia
bn Bengali বাংলা

Input Format

The model uses a conversational format with system and user messages. The input expects a JSON-like structure with role-based messages.

System Message (Required)

{
    'role': 'system',
    'content': 'Generate professional chess commentary in the specified language. For Type=standard use 30–40 words. For Type=explanation, explain the best move briefly (≤50 words). Return exactly: Commentary, Predicted ELO, Verified Classification.'
}

User Message Format

{
    'role': 'user',
    'content': '''LanguageL: English
LangCode: en
Type: standard
FEN: rnbqkbnr/pppppppp/8/8/3P4/8/PPP1PPPP/RNBQKBNR b KQkq - 0 1
MoveSAN: Nf6
Side: Black
Actor: human
Name: John
Gender: male
Tag: Book
BestAlt: g8f6
CP: 27->21 (Δ=6)'''
}

Field Descriptions

Field Type Required Example Explanation
LanguageL string ✅ REQUIRED English, Hindi, Spanish Full language name for commentary generation
LangCode string ✅ REQUIRED en, hi, es ISO 639-1 language code (see table above)
Type string ✅ REQUIRED standard, explanation Commentary type: standard (30-40 words) or explanation (explain best move, ≤50 words)
FEN string ✅ REQUIRED rnbqkbnr/pppppppp/8/8/3P4/8/PPP1PPPP/RNBQKBNR b KQkq - 0 1 Forsyth-Edwards Notation - exact chess position before the move
MoveSAN string ✅ REQUIRED Nf6, e4, O-O Standard Algebraic Notation - the move that was played
Side string ✅ REQUIRED White, Black Which side played the move
Actor string ✅ REQUIRED human, bot Whether move was made by human or engine
NAME string OPTIONAL Name of human or bot Human or bot gender who played the move for personalized commentary
Gender string OPTIONAL male, female, neutral Player or bot gender for personalized commentary
Tag string ✅ REQUIRED Book, Best, Good, Inaccuracy, Mistake, Blunder, Brilliant Move classification tag
BestAlt string ✅ REQUIRED g8f6, e2e4 Best alternative move in coordinate notation
CP string ✅ REQUIRED 27->21 (Δ=6) Centipawn evaluation: before->after (Delta=change). Format: CPBefore->CPAfter (Δ=change)

Sample Input & Output

Example 1: English Commentary (Standard)

Input:

[
    {
        'role': 'system',
        'content': 'Generate professional chess commentary in the specified language. For Type=standard use 30–40 words. For Type=explanation, explain the best move briefly (≤50 words). Return exactly: Commentary, Predicted ELO, Verified Classification.'
    },
    {
        'role': 'user',
        'content': '''LanguageL: English
LangCode: en
Type: standard
FEN: rnbqkbnr/pppppppp/8/8/3P4/8/PPP1PPPP/RNBQKBNR b KQkq - 0 1
MoveSAN: Nf6
Side: Black
Actor: human
Gender: male
Tag: Book
BestAlt: g8f6
CP: 27->21 (Δ=6)'''
    }
]

Output:

Commentary: Excellent opening response! Nf6 is the classical development move against d4. It immediately challenges the center and prepares flexible piece development. This maintains the tension and gives Black excellent counterplay.
Predicted ELO: 1850
Verified Classification: Book Move

Example 2: Hindi Commentary (Standard)

Input:

[
    {
        'role': 'system',
        'content': 'Generate professional chess commentary in the specified language. For Type=standard use 30–40 words. For Type=explanation, explain the best move briefly (≤50 words). Return exactly: Commentary, Predicted ELO, Verified Classification.'
    },
    {
        'role': 'user',
        'content': '''LanguageL: Hindi
LangCode: hi
Type: standard
FEN: r1bqkb1r/pppp1ppp/2n2n2/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq e6 0 4
MoveSAN: Nc3
Side: White
Actor: human
Gender: female
Tag: Best
BestAlt: b1c3
CP: 42->38 (Δ=4)'''
    }
]

Output:

Commentary: शानदार केंद्रीकरण! Nc3 e4 पर दबाव के साथ विकसित होता है और प्रमुख केंद्रीय वर्गों को नियंत्रित करता है। यह चाल विकास को पूरा करने की तैयारी करती है जबकि केंद्र तनाव बनाए रखती है।
Predicted ELO: 2400
Verified Classification: Best Move

Example 3: Explanation Type (Spanish)

Input:

[
    {
        'role': 'system',
        'content': 'Generate professional chess commentary in the specified language. For Type=standard use 30–40 words. For Type=explanation, explain the best move briefly (≤50 words). Return exactly: Commentary, Predicted ELO, Verified Classification.'
    },
    {
        'role': 'user',
        'content': '''LanguageL: Spanish
LangCode: es
Type: explanation
FEN: 2rq1rk1/pb1nb1pp/1p6/3p1p2/3Pn3/P1N5/1PQNBPPP/R1B1R1K1 w - - 0 16
MoveSAN: f3
Side: White
Actor: human
Gender: male
Tag: Mistake
BestAlt: d2e4
CP: 23->59 (Δ=36)'''
    }
]

Output:

Commentary: El movimiento f3 debilita el rey y permite contraataques tácticos. La mejor alternativa Ne4 centralizaría el caballo con amenazas activas mientras mantiene la seguridad del rey. Este error costó aproximadamente un tercio de peón en ventaja posicional.
Predicted ELO: 1650
Verified Classification: Mistake

Usage Examples

Python (Transformers)

from transformers import AutoModelForCausalLM, AutoTokenizer

model = AutoModelForCausalLM.from_pretrained("NAKSTStudio/chess-gemma-commentary")
tokenizer = AutoTokenizer.from_pretrained("NAKSTStudio/chess-gemma-commentary")

# Prepare messages
messages = [
    {
        'role': 'system',
        'content': 'Generate professional chess commentary in the specified language. For Type=standard use 30–40 words. For Type=explanation, explain the best move briefly (≤50 words). Return exactly: Commentary, Predicted ELO, Verified Classification.'
    },
    {
        'role': 'user',
        'content': '''LanguageL: English
LangCode: en
Type: standard
FEN: rnbqkbnr/pppppppp/8/8/3P4/8/PPP1PPPP/RNBQKBNR b KQkq - 0 1
MoveSAN: Nf6
Side: Black
Actor: human
Gender: male
Tag: Book
BestAlt: g8f6
CP: 27->21 (Δ=6)'''
    }
]

# Generate response
inputs = tokenizer.apply_chat_template(messages, return_tensors="pt", add_generation_prompt=True)
outputs = model.generate(inputs, max_new_tokens=256, temperature=0.7)
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
print(response)

Flutter (flutter_gemma)

import 'package:flutter_gemma/flutter_gemma.dart';

class ChessAnalyzer {
  late InferenceModel model;
  
  Future<void> initModel() async {
    // Install model from Hugging Face (one-time operation)
    await FlutterGemma.installModel(
      modelType: ModelType.gemmaIt,
    ).fromNetwork(
      'https://huggingface.co/NAKSTStudio/chess-gemma-commentary/resolve/main/model.safetensors',
    ).withProgress((progress) {
      print('Downloading model: ${progress.percentage}%');
    }).install();
    
    // Create model instance for inference
    model = await FlutterGemma.getActiveModel(
      maxTokens: 256,
      preferredBackend: PreferredBackend.gpu,
    );
  }

  Future<String> analyzeMove({
    required String language,
    required String langCode,
    required String type,
    required String fen,
    required String moveSAN,
    required String side,
    required String actor,
    required String gender,
    required String tag,
    required String bestAlt,
    required String cp,
  }) async {
    final chat = await model.createChat(temperature: 0.7);
    
    // Add system message
    await chat.addQueryChunk(Message.text(
      text: 'Generate professional chess commentary in the specified language. For Type=standard use 30–40 words. For Type=explanation, explain the best move briefly (≤50 words). Return exactly: Commentary, Predicted ELO, Verified Classification.',
      isUser: false,
    ));
    
    // Add user message with chess position data
    await chat.addQueryChunk(Message.text(
      text: '''LanguageL: $language
LangCode: $langCode
Type: $type
FEN: $fen
MoveSAN: $moveSAN
Side: $side
Actor: $actor
Gender: $gender
Tag: $tag
BestAlt: $bestAlt
CP: $cp''',
      isUser: true,
    ));
    
    // Generate response
    final response = await chat.generateChatResponse();
    
    await chat.close();
    
    if (response is TextResponse) {
      return response.token;
    }
    
    return 'Error generating response';
  }
  
  Future<void> dispose() async {
    await model.close();
  }
}

// Usage
final analyzer = ChessAnalyzer();

// Initialize once (downloads model if not present)
await analyzer.initModel();

// Use multiple times
final result = await analyzer.analyzeMove(
  language: 'English',
  langCode: 'en',
  type: 'standard',
  fen: 'rnbqkbnr/pppppppp/8/8/3P4/8/PPP1PPPP/RNBQKBNR b KQkq - 0 1',
  moveSAN: 'Nf6',
  side: 'Black',
  actor: 'human',
  gender: 'male',
  tag: 'Book',
  bestAlt: 'g8f6',
  cp: '27->21 (Δ=6)',
);

print(result);

// Clean up when done
await analyzer.dispose();

Output Format

The model generates three key components:

  1. Commentary: Multi-sentence chess analysis in the specified language (30-50 words typically)
  2. Predicted ELO: Integer rating (1000-2800 typically)
  3. Verified Classification: Single label describing the move (Book Move, Best Move, Good Move, Inaccuracy, Mistake, Blunder, Brilliant)

Performance Metrics

  • Inference Speed: 15-30 tokens/second on mid-range Android phones
  • 💾 Memory Required: 4GB minimum RAM for on-device inference
  • 📱 Model Sizes:
    • TASK File(int 8 dynamic): ~250 mb
    • TASK File: ~500 mb
  • 🌍 Language Coverage: 14 languages spanning 5+ billion speakers

Training Configuration

  • LoRA Rank (r): 8
  • LoRA Alpha: 16
  • LoRA Dropout: 0.1
  • Target Modules: q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj
  • Learning Rate: 2e-4
  • Batch Size: 8 (effective; per device: 1, gradient accumulation: 8)
  • Optimizer: AdamW 8-bit
  • Warmup Steps: 5
  • Training Time: ~100 minutes (4 epochs on Colab T4)

Model Files

chess-gemma-commentary/
├── model.safetensors          # Fine-tuned weights (500MB)
├── tokenizer.model            # SentencePiece tokenizer
├── tokenizer.json             # Tokenizer config
├── tokenizer_config.json      # Tokenizer settings
├── config.json                # Model architecture config
├── chat_template.jinja        # Chat formatting template
├── added_tokens.json          # Special tokens
└── README.md                  # Documentation

Important Notes

⚠️ Format Sensitivity: This model is trained on the EXACT format shown above. Follow field order, spacing, and field names precisely for best results.

⚠️ Language Codes: Use the correct ISO 639-1 language code from the supported languages table. Incorrect codes may produce unexpected results.

⚠️ Commentary Types:

  • Type=standard: Generates 30-40 word general commentary
  • Type=explanation: Generates ≤50 word explanation focusing on why the best alternative move is superior

Conversational Format: The model uses a message-based format with system and user roles for better context understanding.

Gender-Aware: Optionally customize commentary style based on player gender (male/female/neutral).

Delta Information: The CP field format CPBefore->CPAfter (Δ=change) helps the model understand move impact.

Known Limitations

  • ❌ Very unusual or impossible positions may generate generic responses
  • ❌ Requires 4GB+ RAM for mobile inference (quantization helps)
  • ❌ Temperature affects output randomness (0.7 recommended for chess)
  • ❌ Cannot analyze positions with invalid FEN notation
  • ❌ Language quality may vary - English has most training data coverage
  • ❌ Some languages may require native speaker validation for natural phrasing

License

This model is distributed under the Gemma Community License. See: https://ai.google.dev/gemma/terms

Citation

@model{chess_gemma_commentary_2025,
  title={Chess Gemma Commentary: Multilingual Chess Analysis},
  author={NAKST Studio},
  year={2025},
  howpublished={Hugging Face Hub}
}

Credits

Support & Feedback

  • 🐛 Found a bug? Open an issue on the model page
  • 💡 Feature request? Leave a discussion comment
  • Enjoying it? Star the model!
  • 💙 Our Site https://nakststudio.com/

Made with ❤️ by NAKST Studio

Last Updated: November 7, 2025

Downloads last month
797
Safetensors
Model size
0.3B params
Tensor type
F32
·
F16
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support