Spaces:
Build error
Build error
docs: add design spec for MiniCPM5-1B text engine replacement
Browse files
docs/superpowers/specs/2026-06-10-minicpm5-text-engine-design.md
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Replace Nemotron with MiniCPM5-1B β Design Spec
|
| 2 |
+
|
| 3 |
+
## Overview
|
| 4 |
+
|
| 5 |
+
Replace the Phase 1 English text generation pipeline: swap `TextEngine` (which spawns `llama-cli` subprocesses with Nemotron 30B-A3B, ~16 GB) for a new `MiniCPMTextEngine` that loads MiniCPM5-1B Q8_0 via llama-cpp-python (~1.1 GB). Phase 2 translation via tiny-aya-water remains unchanged.
|
| 6 |
+
|
| 7 |
+
## Why This Change
|
| 8 |
+
|
| 9 |
+
| Aspect | Nemotron (current) | MiniCPM5-1B (new) |
|
| 10 |
+
|---|---|---|
|
| 11 |
+
| Model size | ~16 GB (IQ4_XS) | ~1.1 GB (Q8_0) |
|
| 12 |
+
| Runtime | llama-cli subprocess | llama-cpp-python in-process |
|
| 13 |
+
| Architecture | MoE (needs `--n-cpu-moe`) | Standard LlamaForCausalLM |
|
| 14 |
+
| VRAM / RAM usage | High (~16 GB) | Low (~1.1 GB) |
|
| 15 |
+
| Subprocess overhead | Yes (spawn + wait per call) | No (lazy-load once, unload after) |
|
| 16 |
+
| Context window | 32k | 131k |
|
| 17 |
+
|
| 18 |
+
## Architecture
|
| 19 |
+
|
| 20 |
+
```
|
| 21 |
+
User input β app.py click handler β EnginePool.get(config) β MiniCPMTextEngine (Phase 1) β cards rendered with English on front
|
| 22 |
+
```
|
| 23 |
+
|
| 24 |
+
### Component Changes
|
| 25 |
+
|
| 26 |
+
**New:** `MiniCPMTextEngine` in `core/engine.py`
|
| 27 |
+
- Uses llama-cpp-python directly (same runtime as existing `LlamaCppTextEngine`)
|
| 28 |
+
- Lazy-loads the Q8_0 model (~1.1 GB) on first `.generate()` call
|
| 29 |
+
- Unloads after completion to free memory (via EnginePool mutual exclusion)
|
| 30 |
+
- Uses MiniCPM5-1B's built-in chat template (`apply_chat_template`) β no manual prompt formatting
|
| 31 |
+
|
| 32 |
+
**Removed:** `TextEngine` in `core/engine.py`
|
| 33 |
+
- Deletes the entire class and all llama-cli subprocess logic
|
| 34 |
+
- Removes `_build_command`, `_build_generation_prompt`, `_build_translation_prompt`, `_build_translation_prompt` methods that were only used by TextEngine
|
| 35 |
+
- Keeps translation-specific prompts inside `LlamaCppTextEngine` (those are still needed)
|
| 36 |
+
|
| 37 |
+
**Updated:** `EnginePool.get_english_engine()` returns `MiniCPMTextEngine` instead of `TextEngine`
|
| 38 |
+
|
| 39 |
+
**Updated:** `EngineConfig.from_settings_yaml()` loads `minicpm_model_path` and simplified generation params (no MoE, no n_ubatch)
|
| 40 |
+
|
| 41 |
+
**Unchanged:** Phase 2 pipeline β `LlamaCppTextEngine`, `TTSEngine`, `ImageGenEngine`, `EnginePool._ensure_exclusive("translation")`, all media engines
|
| 42 |
+
|
| 43 |
+
## Component Details
|
| 44 |
+
|
| 45 |
+
### MiniCPMTextEngine
|
| 46 |
+
|
| 47 |
+
```python
|
| 48 |
+
class MiniCPMTextEngine:
|
| 49 |
+
def __init__(self, model_path: str, device: str = "cuda"): ...
|
| 50 |
+
def _load_model(self) -> None: ... # Lazy-load via llama_cpp.Llama
|
| 51 |
+
def generate(self, texts: list[str], scenario: str, cefr_level: CEFRLevel, batch_size: int | None = None) -> TextResult: ...
|
| 52 |
+
def unload(self) -> None: ... # del model + torch.cuda.empty_cache()
|
| 53 |
+
```
|
| 54 |
+
|
| 55 |
+
**Prompt format:** Chat template via `apply_chat_template(messages=[{"role": "system", "content": "..."}, {"role": "user", "content": "..."}])`
|
| 56 |
+
|
| 57 |
+
System prompt instructs the model to act as a language teacher generating simple sentences at the specified CEFR level about the given scenario. User message is identical to the current Nemotron prompt (batch size, CEFR level, scenario).
|
| 58 |
+
|
| 59 |
+
**Generation parameters:**
|
| 60 |
+
- `max_tokens`: 512
|
| 61 |
+
- `temperature`: 0.7
|
| 62 |
+
- `echo`: False
|
| 63 |
+
- `n_ctx`: 4096 (sufficient for batch_size=3 sentences)
|
| 64 |
+
|
| 65 |
+
### EngineConfig Changes
|
| 66 |
+
|
| 67 |
+
| Removed | Added |
|
| 68 |
+
|---|---|
|
| 69 |
+
| `nemotron_model_path: str` | `minicpm_model_path: str` |
|
| 70 |
+
| `n_cpu_moe: int = 36` | *(not needed β standard Llama arch)* |
|
| 71 |
+
| `n_ubatch: int = 1024` | *(llama-cpp-python handles this internally)* |
|
| 72 |
+
|
| 73 |
+
All other fields (`n_ctx`, `n_threads`, `n_batch`, `top_k`, `repeat_penalty`, `top_p`, `min_p`, `temperature`, `max_tokens`) are retained.
|
| 74 |
+
|
| 75 |
+
### settings.yaml Changes
|
| 76 |
+
|
| 77 |
+
- Rename `nemotron` section to `minicpm` with repo `Abiray/MiniCPM5-1B-GGUF`, file `minicpm5-1b-Q8_0.gguf`, runtime `llama-cpp-python`
|
| 78 |
+
- Remove `n_cpu_moe` from `generation` section
|
| 79 |
+
|
| 80 |
+
### download_models.py Changes
|
| 81 |
+
|
| 82 |
+
- Rename `nemotron` entry to `minicpm` with repo `Abiray/MiniCPM5-1B-GGUF`, file `minicpm5-1b-Q8_0.gguf`
|
| 83 |
+
- Update description text
|
| 84 |
+
|
| 85 |
+
## Data Flow
|
| 86 |
+
|
| 87 |
+
```
|
| 88 |
+
Phase 1:
|
| 89 |
+
User enters scenario + CEFR level β app.py clicks "Generate Text"
|
| 90 |
+
β generate_text_async() calls EnginePool.get(config).get_english_engine()
|
| 91 |
+
β returns MiniCPMTextEngine (lazy-load on first call)
|
| 92 |
+
β .generate(texts=[], scenario, cefr_level, batch_size)
|
| 93 |
+
β MiniCPM builds chat prompt, generates sentences
|
| 94 |
+
β TextResult.translations β list of English sentences
|
| 95 |
+
β Cards rendered with placeholder_back=True
|
| 96 |
+
|
| 97 |
+
Phase 2 (unchanged):
|
| 98 |
+
User clicks "Generate Cards" β EnginePool.get_translation_engine()
|
| 99 |
+
β LlamaCppTextEngine (tiny-aya-water) translates sentences
|
| 100 |
+
```
|
| 101 |
+
|
| 102 |
+
## Error Handling
|
| 103 |
+
|
| 104 |
+
- Model file missing: `FileNotFoundError` raised in `__init__`, caught by `generate_text_async()` with same user-facing message pattern as current Nemotron error handling
|
| 105 |
+
- llama-cpp-python not installed: `ImportError` β but package is already installed via `LlamaCppTextEngine`, so this path is unlikely
|
| 106 |
+
- Generation failure: RuntimeError with stderr capture, shown to user in styled error box (same as current)
|
| 107 |
+
|
| 108 |
+
## Testing
|
| 109 |
+
|
| 110 |
+
- `scripts/smoke_test.py`: Must pass (imports all modules, constructs Gradio app)
|
| 111 |
+
- Manual test: Generate text for a scenario β verify MiniCPM produces readable English sentences at appropriate CEFR level
|
| 112 |
+
- Phase 2 still works unchanged: generate media after text generation
|
| 113 |
+
|
| 114 |
+
## Files Modified
|
| 115 |
+
|
| 116 |
+
| File | Action |
|
| 117 |
+
|---|---|
|
| 118 |
+
| `core/engine.py` | Remove `TextEngine`, add `MiniCPMTextEngine` |
|
| 119 |
+
| `core/types.py` | Rename `nemotron_model_path` β `minicpm_model_path`, remove MoE/ubatch params |
|
| 120 |
+
| `configs/settings.yaml` | Rename nemotron β minicpm, remove n_cpu_moe |
|
| 121 |
+
| `models/download_models.py` | Rename nemotron entry to minicpm |
|
| 122 |
+
| `docs/superpowers/specs/2026-06-10-minicpm5-text-engine-design.md` | This spec (new) |
|