К основному содержанию
правило

mlx — правило для Cursor: что делает и как установить

Направляет Cursor при разработке ML-проектов на Apple Silicon: помогает писать модульный код на MLX, правильно компилировать шаги обучения и избегать ошибок с памятью.

Установить в Cursor · Вручную: положить файлы Все способы и платформы ↓
.cursor/rules/mlx.mdc
Открыть на GitHub

Что делает mlx

Правило настраивает ассистента на работу с фреймворком Apple MLX. Оно требует разделять проект на отдельные модули: загрузку данных, архитектуру моделей на mlx.nn и конфигурационные файлы YAML вместо монолитных скриптов с зашитыми гиперпараметрами.

В инструкциях закреплены паттерны ленивых вычислений. Ассистент применяет mx.compile() для оптимизации шагов обучения и явный mx.eval() для выполнения графа. Без mx.eval() граф вычислений бесконтрольно разрастается в памяти, что приводит к непредсказуемым просадкам скорости.

Память в Apple Silicon общая. Поэтому вызовы вроде .to("gpu") правило исключает: тензоры MLX изначально доступны графическому чипу. При необходимости изолировать операцию ассистент направляет её через stream=mx.cpu. Для экономии места при инференсе описывается квантование весов до 4 бит с размером группы 32.

Какие задачи решает

  • структурировать проект на MLX по модулям и вынести параметры в YAML
  • оптимизировать циклы обучения через mx.compile и контролировать вычисления с помощью mx.eval
  • убрать лишние переносы данных между CPU и GPU благодаря Unified Memory
  • квантовать веса модели до 4 бит для экономии памяти на устройстве

Примеры запросов агенту

  • Напиши класс свёрточной сети на mlx.nn и вынеси параметры обучения в train_config.yaml
  • Собери шаг обучения с Adam, оберни его в mx.compile и добавь явный вызов mx.eval
  • Квантуй обученную модель в 4-битный формат и сохрани веса в safetensors

Как установить mlx

Вручную: положить файлы

.cursor/rules/mlx.mdc

Во frontmatter: description, globs, alwaysApply

По шагам, с командами для каждой платформы: Cursor rules: файлы .mdc, четыре режима и замена .cursorrules

Вопросы о mlx

Как установить mlx в Cursor?

Сохраните правило в файл .cursor/rules/mlx.mdc в корне вашего проекта. Cursor сразу начнёт учитывать эти инструкции при генерации кода.

Что делает правило mlx?

Оно задаёт правила написания кода на MLX для Python и Swift. Ассистент следует принципам модульности, контролирует ленивые вычисления и применяет возможности единой памяти чипов Apple.

Почему в коде MLX нельзя вызывать методы вроде .to("gpu")?

Архитектура Apple Silicon использует единую память, где данные одновременно видны процессору и видеоядру. Массивы MLX по умолчанию выполняются на графическом ускорителе без ручного копирования.

Исходный текст

mlx.mdc · CC0-1.0
---
description: This guide provides opinionated, actionable best practices for developing high-performance machine learning applications with MLX on Apple Silicon, focusing on Python and Swift.
globs: **/*
---
# mlx Best Practices

MLX is Apple's high-performance array framework for numerical computing and AI on Apple Silicon. Adhering to these guidelines ensures your MLX code is efficient, maintainable, and integrates seamlessly with Apple's ML ecosystem.

## 1. Code Organization and Structure

Organize your MLX projects into logical, reusable modules. Mirror the structure of official Apple examples (e.g., `corenet` MLX examples) for clarity and maintainability.

### 1.1 Modularize Components
Separate concerns into dedicated files: data loading, model definition, training loops, and utility functions.

❌ **BAD: Monolithic Script**
```python
# train.py
import mlx.core as mx
import mlx.nn as nn
# ... data loading, model definition, training loop all in one file ...
```

✅ **GOOD: Modular Structure**
```
my_project/
├── data/
│   └── mnist_loader.py
├── models/
│   └── simple_cnn.py
├── config/
│   └── train_config.yaml
├── utils/
│   └── metrics.py
└── train.py
```
```python
# models/simple_cnn.py
import mlx.core as mx
import mlx.nn as nn

class SimpleCNN(nn.Module):
    def __init__(self, num_classes: int):
        super().__init__()
        self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
        self.relu1 = nn.ReLU()
        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)
        self.linear = nn.Linear(32 * 14 * 14, num_classes)

    def __call__(self, x: mx.array) -> mx.array:
        x = self.conv1(x)
        x = self.relu1(x)
        x = self.pool1(x)
        x = x.reshape(x.shape[0], -1) # Flatten
        return self.linear(x)

# train.py
from data.mnist_loader import load_mnist_data
from models.simple_cnn import SimpleCNN
# ... training logic ...
```

### 1.2 Externalize Configuration
Store training parameters, model hyperparameters, and dataset paths in version-controlled YAML or JSON files.

❌ **BAD: Hardcoded Parameters**
```python
# train.py
learning_rate = 0.001
batch_size = 32
num_epochs = 10
model = SimpleCNN(num_classes=10)
```

✅ **GOOD: Config-Driven**
```yaml
# config/train_config.yaml
training:
  learning_rate: 0.001
  batch_size: 32
  num_epochs: 10
model:
  name: SimpleCNN
  num_classes: 10
data:
  path: "./data/mnist"
```
```python
# train.py
import yaml
from models.simple_cnn import SimpleCNN

with open("config/train_config.yaml", "r") as f:
    config = yaml.safe_load(f)

model = SimpleCNN(num_classes=config["model"]["num_classes"])
# ... use config["training"]["learning_rate"] etc.
```

## 2. Common Patterns and Anti-patterns

Leverage MLX's core features like lazy evaluation and unified memory for optimal performance.

### 2.1 Embrace Lazy Evaluation
MLX computations are lazy; they build a computation graph but execute only when results are explicitly needed. Use `mlx.eval()` or `mlx.compile()` to force execution.

❌ **BAD: Relying on Implicit Evaluation for Performance Critical Sections**
```python
# This loop might build a huge graph or trigger many small evaluations
# if intermediate results are printed or accessed.
for i in range(num_steps):
    loss, grads = value_and_grad(model, loss_fn)(model, X_batch, y_batch)
    # ... optimizer update ...
    # No explicit eval, performance can be unpredictable.
```

✅ **GOOD: Explicit Evaluation for Control**
Use `mlx.eval()` on the final outputs of a computation step to trigger execution efficiently. For static graphs, `mlx.compile()` offers further optimization.

```python
import mlx.core as mx
import mlx.nn as nn
from mlx.optimizers import Adam
from mlx.utils import value_and_grad

# Define model and loss_fn (as in 1.1)

def train_step(model, X, y, optimizer):
    loss, grads = value_and_grad(model, loss_fn)(model, X, y)
    optimizer.update(model, grads)
    return loss

# Compile the training step for static graphs
compiled_train_step = mx.compile(train_step)

# In your training loop:
optimizer = Adam(learning_rate=0.001)
for i in range(num_steps):
    X_batch, y_batch = get_batch()
    # Use the compiled step
    loss = compiled_train_step(model, X_batch, y_batch, optimizer)
    # Explicitly evaluate the loss to trigger computation and get its value
    mx.eval(model, optimizer, loss) # Evaluate model state, optimizer state, and loss
    print(f"Step {i}, Loss: {loss.item()}")
```

### 2.2 Leverage Unified Memory
MLX arrays live in shared memory, eliminating explicit data transfers between CPU and GPU. Specify the device for operations when necessary, but default behavior is often sufficient.

❌ **BAD: Unnecessary Device Management (like other frameworks)**
```python
# No need to explicitly move data to 'gpu' or 'cpu'
data = mx.array([1, 2, 3]).to("gpu") # This is not how MLX works
```

✅ **GOOD: Device-Agnostic Operations (or explicit per-op)**
```python
import mlx.core as mx

a = mx.array([1, 2, 3])
b = mx.array([4, 5, 6])

# Operations run on the default device (usually GPU if available)
c = a + b
mx.eval(c)

# You can explicitly specify device per operation if needed for specific tasks
d = mx.add(a, b, stream=mx.cpu) # Force CPU execution for this specific op
mx.eval(d)
```

### 2.3 Use Type Hints and Pure Functions
Follow Python best practices: annotate functions and variables with type hints for clarity. Design functions to be pure where possible for easier testing and composability.

## 3. Performance Considerations

Optimize for Apple Silicon by understanding MLX's execution model.

### 3.1 Batching and Data Loading
Efficient data loading and proper batching are critical for GPU utilization.

❌ **BAD: Iterating over single samples or inefficient data loading**
```python
# Inefficient for GPU
for sample_x, sample_y in dataset:
    # ... process single sample ...
```

✅ **GOOD: Batch Data and Preload**
```python
# Use a DataLoader or similar utility to yield batches of MLX arrays
def data_loader(data, batch_size):
    for i in range(0, len(data), batch_size):
        yield mx.array(data[i:i+batch_size])

# In training loop:
for X_batch, y_batch in data_loader(train_data, batch_size):
    # ... process batch ...
```

### 3.2 Quantization for Deployment
For deploying models on-device, consider quantizing weights (e.g., 4-bit) to reduce memory footprint and improve inference speed.

```python
import mlx.core as mx
import mlx.nn as nn

# Assuming 'model' is a trained MLX model
# Quantize the model to 4-bit
quantized_model = model.quantize(group_size=32, bits=4)

# Save the quantized model
mx.save("quantized_model.safetensors", quantized_model.parameters())
```

## 4. Common Pitfalls and Gotchas

Avoid common mistakes that can lead to unexpected behavior or poor performance.

### 4.1 Forgetting `mlx.eval()`
The most common pitfall. If you don't explicitly evaluate, your graph might not execute, or only partially.

❌ **BAD: No `eval()` on results**
```python
# This will print the MLX array object, not its computed value
result = mx.add(mx.array([1]), mx.array([2]))
print(result) # Output: array(value=..., shape=(1,), dtype=int32)
```

✅ **GOOD: Always `eval()` when you need the value**
```python
result = mx.add(mx.array([1]), mx.array([2]))
mx.eval(result)
print(result) # Output: array(3, shape=(1,), dtype=int32)
print(result.item()) # Output: 3
```

### 4.2 Over-evaluating or Under-evaluating
Finding the right balance for `mlx.eval()` is key. Too many small `eval` calls can break graph optimization. Too few can lead to memory issues or delayed execution.

**Guideline:** Evaluate at logical synchronization points, typically at the end of a training step or inference call. Use `mx.eval(model, optimizer, loss)` to evaluate all relevant states.

## 5. Testing Approaches

Ensure the reliability and correctness of your MLX models.

### 5.1 Unit Tests for Model Components
Test individual layers, custom modules, and utility functions.

```python
# tests/test_simple_cnn.py
import mlx.core as mx
import mlx.nn as nn
from models.simple_cnn import SimpleCNN

def test_simple_cnn_output_shape():
    model = SimpleCNN(num_classes=10)
    # Initialize model parameters by running a dummy input
    _ = model(mx.zeros((1, 1, 28, 28)))
    mx.eval(model) # Ensure parameters are initialized

    input_tensor = mx.random.normal((2, 1, 28, 28))
    output = model(input_tensor)
    assert output.shape == (2, 10)
    print("SimpleCNN output shape test passed.")

if __name__ == "__main__":
    test_simple_cnn_output_shape()
```

### 5.2 Integration Tests for Inference
Verify that your trained models perform as expected on new data, especially when integrating with Core ML or other on-device frameworks.

### 5.3 Data Validation and Reproducibility
Implement sanity checks for all input data. Version control your data, models, and training configurations to ensure reproducible results.

```python
# utils/data_validation.py
import mlx.core as mx

def validate_image_data(images: mx.array, expected_shape: tuple, expected_dtype: mx.Dtype):
    assert images.ndim == len(expected_shape), f"Expected {len(expected_shape)} dims, got {images.ndim}"
    assert images.shape == expected_shape, f"Expected shape {expected_shape}, got {images.shape}"
    assert images.dtype == expected_dtype, f"Expected dtype {expected_dtype}, got {images.dtype}"
    assert images.min() >= 0 and images.max() <= 1, "Image pixel values out of range [0, 1]"
    print("Image data validation passed.")

# In your data loader or training script:
# ... load raw data ...
# raw_images = mx.array(...)
# validate_image_data(raw_images, (100, 1, 28, 28), mx.float32)
```

## 6. Swift-Specific Guidelines

When working with MLX Swift, adhere to Apple's official Swift style guides and API design guidelines.

### 6.1 Follow Swift API Style
Use idiomatic Swift patterns, consistent naming, and proper error handling. Refer to the `mlx-swift` examples (e.g., MNISTTrainer) as templates.

### 6.2 Manage Object Lifetime
Be mindful of object lifetimes, especially when bridging C++ MLX objects to Swift, as aggressive inlining and optimizations can affect behavior. The `mlx-swift` package includes recommendations for this.

© sanjeed5 · CC0-1.0 · sanjeed5/awesome-cursor-rules-mdc

Похожие правила IDE

Все правила IDE по теме «ИИ и ML» →
dflash-mlx-speculative-decoding reason-machines Ускоряет генерацию в MLX на чипах Apple Silicon в 1.7–4.1 раза без потери качества за счёт спекулятивного декодирования DFlash. CX Codex +1 443установок mac-code-local-ai-agent reason-machines Скилл поднимает локальный ИИ-агент для кодинга на Apple Silicon: модель крутится на вашем Mac, без облака и подписки. CX Codex +1 843установок speak-tts EmZod Скилл даёт агенту голос: озвучивает текст, статьи и книги прямо на Mac, без API-ключей и облака. CX Codex +1 735установок mac-mini-llm-lab devops-skills Готовит Mac mini на Apple Silicon к роли автономного сервера нейросетей: настраивает Ollama, MLX, автозапуск через launchd и удалённый доступ. CX Codex +1 309установок coreml dpearson2699 Скилл помогает подключать Core ML к iOS-приложениям на Swift: загружать модели, выполнять предсказания и настраивать вычисления на устройстве. CX Codex +1 3 700установок agent-platform-model-registry официальный google Управляет моделями и их версиями в Agent Platform Model Registry. Ставьте, если нужно просматривать, загружать, менять метаданные или удалять записи через агента. CX Codex 8 332установок

Из того же набора240

Весь набор →
mongodb Правило для Cursor с набором практик по моделированию данных, запросам и индексам в MongoDB. Помогает агенту не плодить лишние $lookup и медленные запросы. ★ 3 580звёзд репо modal Направляет ассистента Cursor при написании кода для Modal: учит настраивать образы, ресурсы GPU и постоянные диски без лишних трат и долгих холодных стартов. ★ 3 580звёзд репо mockito Правило задаёт рекомендации по тестам Java с Mockito и JUnit 5: от настройки моков до проверки аргументов. Пригодится, когда агент пишет или меняет unit-тесты. ★ 3 580звёзд репо mobx Правило для Cursor задаёт структуру MobX-приложения на React: единый RootStore, явные observables и observer только на листовых компонентах. ★ 3 580звёзд репо mkdocs Задаёт правила для Markdown-документации в проектах MkDocs с темой Material. Пригодится, если хотите упорядочить навигацию и проверять страницы перед сборкой. ★ 3 580звёзд репо microsoft-teams Правило для Cursor с набором практик разработки приложений Microsoft Teams: структура проекта, Fluent UI, Adaptive Cards и Microsoft Graph. ★ 3 580звёзд репо maven Правило настраивает Cursor для проектов на Maven: помогает выносить зависимости в родительский POM и изолировать их через строгие scope. ★ 3 580звёзд репо matplotlib Правило задаёт практики для кода на matplotlib в файлах Python: объектный API, типы, сохранение графиков и контроль памяти. ★ 3 580звёзд репо

Спонсоры проекта

Компании, которые помогают держать аналитику открытой