Add GGUF support for Cohere2 (Command R7B / Command A)
Author: Madhav-000-s
Pull request: yes

<!-- ci-dashboard-badge:start -->
[![CI](https://transformers-ci.lor-e.huggingface.cool/badge/pr?pr=47052)](https://transformers-ci.lor-e.huggingface.cool/d/pytest-observability-by-pr/pytest-observability-branch?var-pr=47052)
<!-- ci-dashboard-badge:end -->

# What does this PR do?

Adds GGUF loading support for the **Cohere2** architecture (Command R7B / Command A), as suggested in #33260.

- `c4ai-command-r7b-12-2024` and `c4ai-command-a-03-2025` both use the llama.cpp `cohere2` architecture, so this enables both.

## Changes

- **`GGUF_CONFIG_MAPPING`**: new `cohere2` entry. Cohere2 uses LayerNorm (not RMSNorm), so `attention.layer_norm_epsilon → layer_norm_eps`; also maps `logit_scale` and `attention.sliding_window`. `rope.dimension_count` is ignored since `Cohere2Config` derives `head_dim = hidden_size // num_attention_heads`.
- **`GGUFCohere2Converter`**: builds on `GPT2Converter` (Cohere GGUFs use byte-level BPE, `tokenizer.ggml.model = "gpt2"`), and additionally:
  - registers control tokens (`token_type == 3`, e.g. `
`) as special tokens so they are never split by BPE,
  - prepends BOS via a `TemplateProcessing` post-processor (`tokenizer.ggml.add_bos_token = true` in Cohere GGUFs — Cohere2 generation degenerates without BOS).
- Tensor mapping needs no custom `TensorProcessor` — the model is dense and gguf-py's `MODEL_ARCH.COHERE2` name map covers all tensors.
- Tests: generation test + tokenizer round-trip test in `tests/quantization/ggml/test_ggml.py`.

## Testing done

Verified locally with `bartowski/c4ai-command-r7b-12-2024-GGUF` (Q2_K):

- **Config**: all fields match the original `Cohere2Config` (hidden 4096, 32 layers, 32/8 heads, logit_scale 0.25, sliding_window 4096, rope_theta 50000, layer_types pattern).
- **Weights**: all 258 GGUF tensors map to HF parameters, zero unmapped in either direction (lm_head correctly tied).
- **Tokenizer parity**: token-by-token identical with the original tokenizer on a 19-case battery (unicode, digits, contractions, whitespace, control tokens, chat template, with/without special tokens).
- **Generation** (greedy, Q2_K, fp16): coherent output; chat-template prompt "What is the capital of France?" → "Paris."
- `RUN_SLOW=1 pytest tests/quantization/ggml/test_ggml.py -k cohere2` passes locally (CPU).

Note: `EXPECTED_TEXT` in `test_cohere2_q2_k` was produced on CPU (fp16) — happy to update if the CI GPU runners produce a different completion.

Fixes item "c4ai-command-a" in #33260.

## Who can review?

@SunMarc @Isotr0py

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Comments:
**[For maintainers]** Suggested jobs to run (before merge)

run-slow: ggml

<!-- ci-dashboard-recap:start -->

---

### CI recap

**Dashboard:** [View test results in Grafana](https://transformers-ci.lor-e.huggingface.cool/d/pytest-observability-by-pr/pytest-observability-branch?var-pr=47052)
**Latest run:** [28699687355:2](https://github.com/huggingface/transformers/actions/runs/28699687355)
**Result:** `failure` | **Jobs:** 15 | **Tests:** 171,360 | **Failures:** 6 | **Duration:** 24h 31m

<!-- ci-dashboard-recap:end -->

The failing tests_non_model [shard 0/8] is unrelated to this PR: 6 failures in tests/cli/* with AttributeError: 'HFCliTyperGroup' object has no attribute '_add_completion'. This started with huggingface_hub 1.22.0 (released yesterday), where typer_factory() now returns a click Group instead of a typer.Typer, breaking typer.testing.CliRunner in tests/cli/conftest.py. Reproducible on main with pip install huggingface_hub==1.22.0 + pytest tests/cli/test_system.py. All other checks pass.
should I File as a separate issue?