Views
No views yet
TouchGrass/
├── configs/ # Model configurations
│ ├── touchgrass_3b_config.py # 3B variant config
│ ├── touchgrass_7b_config.py # 7B variant config
│ └── training_config.py # Training hyperparameters
├── tokenizer/
│ └── music_token_extension.py # Extends Qwen tokenizer with music tokens
├── models/ # Specialized music modules
│ ├── tab_chord_module.py # Guitar tabs and chords
│ ├── music_theory_module.py # Theory knowledge
│ ├── ear_training_module.py # Ear training exercises
│ ├── eq_adapter.py # Emotional intelligence
│ └── songwriting_module.py # Song creation assistance
├── data/
│ ├── music_qa_generator.py # Synthetic dataset generator
│ ├── chat_formatter.py # Qwen chat format converter
│ └── dataset_loader.py # PyTorch dataset
├── training/
│ ├── losses.py # Multi-task loss functions
│ ├── trainer.py # LoRA-aware trainer
│ └── train.py # Main training entry point
├── inference/
│ └── inference.py # Unified inference with context
├── benchmarks/
│ ├── evaluate_music_modules.py # Module-level benchmarks
│ └── evaluate_inference.py # End-to-end inference benchmarks
├── tests/ # Comprehensive test suite
│ ├── test_*.py # Unit tests for each module
│ ├── conftest.py # Pytest fixtures
│ └── run_tests.py # Test runner
├── configuration_touchgrass.py # HuggingFace config class
├── tokenization_touchgrass.py # HuggingFace tokenizer wrapper
├── ollama_3b_modelfile # Ollama config for 3B
├── ollama_7b_modelfile # Ollama config for 7B
└── train.py # Main training script1# Clone the repository
2cd TouchGrass
3
4# Install dependencies
5pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
6pip install transformers peft datasets accelerate tqdm pytest
7
8# Optional: For GPU support
9pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu1181python -c "
2from TouchGrass.data.music_qa_generator import MusicQAGenerator
3from TouchGrass.data.chat_formatter import ChatFormatter
4
5# Generate synthetic dataset
6generator = MusicQAGenerator(seed=42)
7dataset = generator.generate_dataset(num_samples=1000, output_path='data/music_qa.jsonl')
8
9# Format for Qwen
10formatter = ChatFormatter()
11formatted = formatter.format_dataset(dataset)
12train_data, val_data = formatter.create_splits(formatted, val_size=0.1)
13
14formatter.save_dataset(train_data, 'data/train.jsonl')
15formatter.save_dataset(val_data, 'data/val.jsonl')
16"1# Train 3B variant
2python train.py \
3 --base_model Qwen/Qwen3.5-3B-Instruct \
4 --train_data data/train.jsonl \
5 --val_data data/val.jsonl \
6 --output_dir checkpoints/touchgrass-3b \
7 --lora_r 16 \
8 --lora_alpha 32 \
9 --batch_size 4 \
10 --gradient_accumulation_steps 4 \
11 --learning_rate 2e-4 \
12 --num_epochs 3 \
13 --mixed_precision fp16
14
15# Train 7B variant (requires GPU with 16GB+ VRAM)
16python train.py \
17 --base_model Qwen/Qwen3.5-7B-Instruct \
18 --train_data data/train.jsonl \
19 --val_data data/val.jsonl \
20 --output_dir checkpoints/touchgrass-7b \
21 --lora_r 16 \
22 --lora_alpha 32 \
23 --batch_size 2 \
24 --gradient_accumulation_steps 8 \
25 --learning_rate 1e-4 \
26 --num_epochs 3 \
27 --mixed_precision bf161from TouchGrass.inference.inference import TouchGrassInference
2
3# Load model
4model = TouchGrassInference(
5 model_path="checkpoints/touchgrass-3b",
6 device="cpu" # or "cuda"
7)
8
9# Single query with instrument context
10response = model.generate(
11 prompt="How do I play a G major chord?",
12 instrument="guitar",
13 skill_level="beginner",
14 max_new_tokens=200
15)
16print(response)
17
18# Interactive mode
19model.chat(instrument="piano")1# Create modelfile from provided template
2cat ollama_3b_modelfile > Modelfile
3
4# Build and run
5ollama create touchgrass-3b -f Modelfile
6ollama run touchgrass-3b "How do I play a G major chord on guitar?"1from transformers import AutoModelForCausalLM, AutoTokenizer
2
3# Load with custom config and tokenizer
4config = TouchGrassConfig.from_pretrained("checkpoints/touchgrass-3b")
5tokenizer = TouchGrassTokenizer.from_pretrained("checkpoints/touchgrass-3b")
6model = AutoModelForCausalLM.from_pretrained(
7 "checkpoints/touchgrass-3b",
8 config=config,
9 device_map="auto"
10)
11
12# Generate
13inputs = tokenizer("system\nYou are a music assistant.\nuser\nHow do I play a G major chord?\nassistant\n", return_tensors="pt")
14outputs = model.generate(**inputs, max_new_tokens=200)
15print(tokenizer.decode(outputs[0], skip_special_tokens=True))1# Run all tests
2python tests/run_tests.py
3
4# Run with coverage
5python tests/run_tests.py --coverage
6
7# Run specific test categories
8pytest tests/test_music_theory_module.py -v
9pytest tests/test_tokenizer.py -v
10pytest tests/test_eq_adapter.py -v
11
12# Skip slow tests
13pytest -m "not slow"1# Evaluate music modules
2python benchmarks/evaluate_music_modules.py --device cpu --d_model 768
3
4# Run inference benchmarks
5python benchmarks/evaluate_inference.py --model_path checkpoints/touchgrass-3b --device cpuconfigs/training_config.py to customize:lm_loss_weight=1.0 (primary language modeling)eq_loss_weight=0.1 (emotional intelligence)music_module_loss_weight=0.05 (specialized modules)[GUITAR], [PIANO], [DRUMS], [VOCALS], [THEORY], [PRODUCTION][FRUSTRATED], [CONFUSED], [EXCITED], [CONFIDENT][EASY], [MEDIUM], [HARD][TAB], [CHORD], [SCALE], [INTERVAL], [PROGRESSION][SIMPLIFY], [ENCOURAGE]1from TouchGrass.data.music_qa_generator import MusicQAGenerator
2
3# Create custom templates
4custom_templates = {
5 "guitar": [
6 {
7 "system": "You are a {instrument} specialist.",
8 "user": "How do I play {chord}?",
9 "assistant": "Place your fingers: {fingering}"
10 }
11 ]
12}
13
14generator = MusicQAGenerator(templates=custom_templates, seed=123)
15dataset = generator.generate_dataset(num_samples=500)1from TouchGrass.inference.inference import TouchGrassInference
2
3model = TouchGrassInference(model_path="checkpoints/touchgrass-3b")
4
5# Switch between instruments seamlessly
6guitar_response = model.generate("How do I palm mute?", instrument="guitar")
7piano_response = model.generate("What are the scales in C major?", instrument="piano")
8theory_response = model.generate("Explain the circle of fifths", instrument="theory")1from transformers import LoraConfig
2
3lora_config = LoraConfig(
4 task_type=TaskType.CAUSAL_LM,
5 r=32, # Rank (higher = more parameters)
6 lora_alpha=64, # Alpha (typically 2×r)
7 target_modules=["q_proj", "k_proj", "v_proj", "o_proj"], # Qwen attention modules
8 lora_dropout=0.1,
9 bias="none"
10)tab_validator: Confidence score [0, 1] for tab validitydifficulty: 3-class classification (easy/medium/hard)get_scale_from_key(key, mode): Returns scale notesdetect_chord_function(root, chord_type, key): Returns Roman numeralget_circle_of_fifths(): Returns 12-key circleconstruct_chord(root, chord_type): Returns chord notesanalyze_progression(progression, key): Returns functional analysisfp16 for NVIDIA, bf16 for newer GPUspython tests/run_tests.py)