merlina 2.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- merlina-2.2.0/.env.example +165 -0
- merlina-2.2.0/.github/workflows/README.md +144 -0
- merlina-2.2.0/.gitignore +234 -0
- merlina-2.2.0/API.md +1819 -0
- merlina-2.2.0/CHANGELOG.md +495 -0
- merlina-2.2.0/LICENSE +21 -0
- merlina-2.2.0/PKG-INFO +462 -0
- merlina-2.2.0/README.md +394 -0
- merlina-2.2.0/bump_version.py +310 -0
- merlina-2.2.0/config.py +273 -0
- merlina-2.2.0/dataset_handlers/__init__.py +62 -0
- merlina-2.2.0/dataset_handlers/base.py +465 -0
- merlina-2.2.0/dataset_handlers/deduplication.py +168 -0
- merlina-2.2.0/dataset_handlers/factory.py +229 -0
- merlina-2.2.0/dataset_handlers/formatters.py +637 -0
- merlina-2.2.0/dataset_handlers/loaders.py +449 -0
- merlina-2.2.0/dataset_handlers/messages_converter.py +162 -0
- merlina-2.2.0/dataset_handlers/validators.py +124 -0
- merlina-2.2.0/docs/README.md +43 -0
- merlina-2.2.0/docs/dev/dataset-implementation.md +183 -0
- merlina-2.2.0/docs/dev/implementation-notes.md +246 -0
- merlina-2.2.0/docs/dev/preview-feature.md +213 -0
- merlina-2.2.0/docs/dev/tokenizer-implementation.md +132 -0
- merlina-2.2.0/docs/user/CONFIG_MANAGEMENT.md +268 -0
- merlina-2.2.0/docs/user/dataset-guide.md +343 -0
- merlina-2.2.0/docs/user/mcp.md +149 -0
- merlina-2.2.0/docs/user/new-features.md +429 -0
- merlina-2.2.0/docs/user/quick-start.md +171 -0
- merlina-2.2.0/docs/user/runpod.md +70 -0
- merlina-2.2.0/docs/user/tokenizer-format.md +223 -0
- merlina-2.2.0/examples/README.md +93 -0
- merlina-2.2.0/examples/basic-training.json +24 -0
- merlina-2.2.0/examples/custom-format.json +28 -0
- merlina-2.2.0/examples/datasets/sample-dpo-dataset.json +25 -0
- merlina-2.2.0/examples/example_messages_format.py +99 -0
- merlina-2.2.0/examples/example_messages_format_with_toggle.py +140 -0
- merlina-2.2.0/examples/huggingface-dataset.json +29 -0
- merlina-2.2.0/examples/job_history.py +252 -0
- merlina-2.2.0/examples/local-dataset.json +22 -0
- merlina-2.2.0/examples/manage_configs.py +283 -0
- merlina-2.2.0/examples/tokenizer-format.json +31 -0
- merlina-2.2.0/examples/validate_and_train.py +158 -0
- merlina-2.2.0/examples/websocket_monitor.py +189 -0
- merlina-2.2.0/frontend/css/animations.css +245 -0
- merlina-2.2.0/frontend/css/base.css +145 -0
- merlina-2.2.0/frontend/css/components.css +1294 -0
- merlina-2.2.0/frontend/css/layout.css +330 -0
- merlina-2.2.0/frontend/css/utilities.css +446 -0
- merlina-2.2.0/frontend/css/variables.css +147 -0
- merlina-2.2.0/frontend/favicon.ico +0 -0
- merlina-2.2.0/frontend/index.html +2048 -0
- merlina-2.2.0/frontend/js/api.js +723 -0
- merlina-2.2.0/frontend/js/app.js +1195 -0
- merlina-2.2.0/frontend/js/config.js +800 -0
- merlina-2.2.0/frontend/js/dataset.js +904 -0
- merlina-2.2.0/frontend/js/diffusion.js +676 -0
- merlina-2.2.0/frontend/js/disk.js +577 -0
- merlina-2.2.0/frontend/js/export.js +514 -0
- merlina-2.2.0/frontend/js/form_config.js +364 -0
- merlina-2.2.0/frontend/js/gpu.js +143 -0
- merlina-2.2.0/frontend/js/hf_namespaces.js +136 -0
- merlina-2.2.0/frontend/js/inference.js +444 -0
- merlina-2.2.0/frontend/js/jobs.js +793 -0
- merlina-2.2.0/frontend/js/model.js +198 -0
- merlina-2.2.0/frontend/js/package.json +3 -0
- merlina-2.2.0/frontend/js/theme.js +151 -0
- merlina-2.2.0/frontend/js/ui.js +956 -0
- merlina-2.2.0/frontend/js/validation.js +342 -0
- merlina-2.2.0/frontend/madewithmerlina_smol.png +0 -0
- merlina-2.2.0/frontend/merlina.png +0 -0
- merlina-2.2.0/frontend/styles.css +20 -0
- merlina-2.2.0/mcp_server.py +605 -0
- merlina-2.2.0/merlina.py +5150 -0
- merlina-2.2.0/merlina_cli.py +82 -0
- merlina-2.2.0/pyproject.toml +155 -0
- merlina-2.2.0/pytest.ini +47 -0
- merlina-2.2.0/requirements.txt +66 -0
- merlina-2.2.0/scripts/cleanup_checkpoints.py +101 -0
- merlina-2.2.0/scripts/generate_diffusion_samples.py +146 -0
- merlina-2.2.0/scripts/runpod_setup.sh +50 -0
- merlina-2.2.0/src/__init__.py +105 -0
- merlina-2.2.0/src/checkpoint_policy.py +72 -0
- merlina-2.2.0/src/checkpoint_rescue.py +181 -0
- merlina-2.2.0/src/config_image.py +263 -0
- merlina-2.2.0/src/config_manager.py +364 -0
- merlina-2.2.0/src/constants.py +223 -0
- merlina-2.2.0/src/disk_manager.py +596 -0
- merlina-2.2.0/src/exceptions.py +276 -0
- merlina-2.2.0/src/gguf_exporter.py +650 -0
- merlina-2.2.0/src/gpu_utils.py +244 -0
- merlina-2.2.0/src/hf_namespaces.py +180 -0
- merlina-2.2.0/src/job_manager.py +580 -0
- merlina-2.2.0/src/job_queue.py +505 -0
- merlina-2.2.0/src/llama_cpp_resolver.py +310 -0
- merlina-2.2.0/src/llama_server.py +335 -0
- merlina-2.2.0/src/local_models.py +141 -0
- merlina-2.2.0/src/memory_guard.py +694 -0
- merlina-2.2.0/src/merge_artifact.py +60 -0
- merlina-2.2.0/src/model_artifacts.py +239 -0
- merlina-2.2.0/src/model_card.py +684 -0
- merlina-2.2.0/src/preflight_checks.py +961 -0
- merlina-2.2.0/src/presets.py +181 -0
- merlina-2.2.0/src/train_worker.py +909 -0
- merlina-2.2.0/src/training_runner.py +2095 -0
- merlina-2.2.0/src/training_runner_diffusion.py +602 -0
- merlina-2.2.0/src/training_runner_vlm.py +604 -0
- merlina-2.2.0/src/upload_state.py +195 -0
- merlina-2.2.0/src/utils.py +399 -0
- merlina-2.2.0/src/vram_estimator.py +619 -0
- merlina-2.2.0/src/websocket_manager.py +367 -0
- merlina-2.2.0/src/worker_reattach.py +316 -0
- merlina-2.2.0/tests/README.md +308 -0
- merlina-2.2.0/tests/TEST_SUMMARY.md +322 -0
- merlina-2.2.0/tests/conftest.py +223 -0
- merlina-2.2.0/tests/fixtures/test_dataset.json +25 -0
- merlina-2.2.0/tests/fixtures/test_messages_dataset.json +74 -0
- merlina-2.2.0/tests/frontend/playwright.config.mjs +57 -0
- merlina-2.2.0/tests/frontend/serve_for_tests.py +61 -0
- merlina-2.2.0/tests/frontend/test_api.mjs +348 -0
- merlina-2.2.0/tests/frontend/test_form_config.mjs +601 -0
- merlina-2.2.0/tests/frontend/test_integration.spec.mjs +770 -0
- merlina-2.2.0/tests/frontend/test_theme.mjs +269 -0
- merlina-2.2.0/tests/frontend/test_ui.mjs +447 -0
- merlina-2.2.0/tests/frontend/test_validation.mjs +602 -0
- merlina-2.2.0/tests/requirements-test.txt +26 -0
- merlina-2.2.0/tests/test_api_comprehensive.py +1354 -0
- merlina-2.2.0/tests/test_api_endpoints.py +105 -0
- merlina-2.2.0/tests/test_artemis_runner.py +189 -0
- merlina-2.2.0/tests/test_attention_settings.py +153 -0
- merlina-2.2.0/tests/test_build_grimoire_config.py +190 -0
- merlina-2.2.0/tests/test_centralized_config_save.py +469 -0
- merlina-2.2.0/tests/test_chat_template_embedding.py +194 -0
- merlina-2.2.0/tests/test_checkpoint_policy.py +68 -0
- merlina-2.2.0/tests/test_cleanup.py +288 -0
- merlina-2.2.0/tests/test_config_field_names.py +303 -0
- merlina-2.2.0/tests/test_config_image.py +241 -0
- merlina-2.2.0/tests/test_config_manager.py +190 -0
- merlina-2.2.0/tests/test_config_only.py +91 -0
- merlina-2.2.0/tests/test_dataset_config_bugs.py +393 -0
- merlina-2.2.0/tests/test_dataset_config_name.py +127 -0
- merlina-2.2.0/tests/test_dataset_loaders.py +70 -0
- merlina-2.2.0/tests/test_deduplication.py +258 -0
- merlina-2.2.0/tests/test_diffusion_dispatch.py +461 -0
- merlina-2.2.0/tests/test_disk_manager.py +441 -0
- merlina-2.2.0/tests/test_event_loop_blocking.py +224 -0
- merlina-2.2.0/tests/test_frontend_wb_changes.py +118 -0
- merlina-2.2.0/tests/test_gguf_exporter.py +411 -0
- merlina-2.2.0/tests/test_hf_hub_private.py +144 -0
- merlina-2.2.0/tests/test_hf_hub_private_simple.py +122 -0
- merlina-2.2.0/tests/test_hf_namespace_api.py +188 -0
- merlina-2.2.0/tests/test_hf_namespaces.py +191 -0
- merlina-2.2.0/tests/test_job_deletion.py +168 -0
- merlina-2.2.0/tests/test_linear_attention_kernels.py +117 -0
- merlina-2.2.0/tests/test_llama_cpp_resolver.py +183 -0
- merlina-2.2.0/tests/test_local_models.py +202 -0
- merlina-2.2.0/tests/test_mcp_server.py +370 -0
- merlina-2.2.0/tests/test_memory_guard.py +491 -0
- merlina-2.2.0/tests/test_merge_artifact.py +107 -0
- merlina-2.2.0/tests/test_messages_format.py +225 -0
- merlina-2.2.0/tests/test_messages_format_toggle.py +89 -0
- merlina-2.2.0/tests/test_model_artifacts.py +166 -0
- merlina-2.2.0/tests/test_model_loading_integration.py +200 -0
- merlina-2.2.0/tests/test_model_path_detection.py +65 -0
- merlina-2.2.0/tests/test_model_readme.py +600 -0
- merlina-2.2.0/tests/test_multi_dataset.py +218 -0
- merlina-2.2.0/tests/test_new_settings.py +150 -0
- merlina-2.2.0/tests/test_optimizer_settings.py +151 -0
- merlina-2.2.0/tests/test_pipeline.py +93 -0
- merlina-2.2.0/tests/test_presets.py +231 -0
- merlina-2.2.0/tests/test_queue.py +461 -0
- merlina-2.2.0/tests/test_raw_formatter.py +95 -0
- merlina-2.2.0/tests/test_share_config_readme.py +378 -0
- merlina-2.2.0/tests/test_streaming_loader.py +329 -0
- merlina-2.2.0/tests/test_tokenizer_formatter.py +105 -0
- merlina-2.2.0/tests/test_upload_state.py +193 -0
- merlina-2.2.0/tests/test_v1_1_features.py +345 -0
- merlina-2.2.0/tests/test_vlm_model_type.py +312 -0
- merlina-2.2.0/tests/test_vlm_processor_saving.py +427 -0
- merlina-2.2.0/tests/test_vram_estimator.py +306 -0
- merlina-2.2.0/tests/test_wandb_missing_key.py +45 -0
- merlina-2.2.0/tests/test_wandb_settings.py +224 -0
- merlina-2.2.0/tests/test_wandb_standalone.py +226 -0
- merlina-2.2.0/version.py +39 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# Merlina Configuration Template
|
|
2
|
+
# Copy this file to .env and customize for your environment
|
|
3
|
+
|
|
4
|
+
# ==========================================
|
|
5
|
+
# Server Configuration
|
|
6
|
+
# ==========================================
|
|
7
|
+
|
|
8
|
+
# Server host (0.0.0.0 allows external connections, 127.0.0.1 is localhost only)
|
|
9
|
+
HOST=0.0.0.0
|
|
10
|
+
|
|
11
|
+
# Server port
|
|
12
|
+
PORT=8000
|
|
13
|
+
|
|
14
|
+
# Production domain (leave empty for development)
|
|
15
|
+
# Examples:
|
|
16
|
+
# http://localhost:8000
|
|
17
|
+
# https://merlina.example.com
|
|
18
|
+
# http://192.168.1.100:8000
|
|
19
|
+
# DOMAIN=
|
|
20
|
+
|
|
21
|
+
# ==========================================
|
|
22
|
+
# Directory Paths (Optional)
|
|
23
|
+
# ==========================================
|
|
24
|
+
|
|
25
|
+
# Uncomment to customize data directories
|
|
26
|
+
# DATA_DIR=./data
|
|
27
|
+
# MODELS_DIR=./models
|
|
28
|
+
# RESULTS_DIR=./results
|
|
29
|
+
# UPLOADS_DIR=./data/uploads
|
|
30
|
+
# FRONTEND_DIR=./frontend
|
|
31
|
+
|
|
32
|
+
# Database location
|
|
33
|
+
# DATABASE_PATH=./data/jobs.db
|
|
34
|
+
|
|
35
|
+
# ==========================================
|
|
36
|
+
# External Services — API Secrets
|
|
37
|
+
# ==========================================
|
|
38
|
+
# Setting these here means clients don't need to send the tokens in HTTP
|
|
39
|
+
# requests. The server will automatically fall back to these values for
|
|
40
|
+
# any training/upload/preload/inference request that omits them. A token
|
|
41
|
+
# sent in a request still overrides the env value.
|
|
42
|
+
#
|
|
43
|
+
# The GET /env/secrets endpoint reports which of these are configured
|
|
44
|
+
# (booleans only — never the values themselves) so the frontend can hide
|
|
45
|
+
# token fields when the server already has them.
|
|
46
|
+
|
|
47
|
+
# Weights & Biases API Key
|
|
48
|
+
# Get your key from: https://wandb.ai/authorize
|
|
49
|
+
# WANDB_API_KEY=
|
|
50
|
+
|
|
51
|
+
# HuggingFace Token (required for gated models like Llama, and for Hub uploads)
|
|
52
|
+
# Get your token from: https://huggingface.co/settings/tokens
|
|
53
|
+
# HF_TOKEN=
|
|
54
|
+
|
|
55
|
+
# ==========================================
|
|
56
|
+
# Training Defaults (Optional)
|
|
57
|
+
# ==========================================
|
|
58
|
+
|
|
59
|
+
# Default LoRA settings
|
|
60
|
+
# DEFAULT_LORA_R=64
|
|
61
|
+
# DEFAULT_LORA_ALPHA=32
|
|
62
|
+
|
|
63
|
+
# Default training hyperparameters
|
|
64
|
+
# DEFAULT_LEARNING_RATE=0.000005
|
|
65
|
+
# DEFAULT_BATCH_SIZE=1
|
|
66
|
+
# DEFAULT_GRADIENT_ACCUMULATION_STEPS=16
|
|
67
|
+
# DEFAULT_NUM_EPOCHS=2
|
|
68
|
+
|
|
69
|
+
# ==========================================
|
|
70
|
+
# Job Queue Configuration
|
|
71
|
+
# ==========================================
|
|
72
|
+
|
|
73
|
+
# Maximum number of training jobs to run simultaneously
|
|
74
|
+
# Set to 1 for safety (prevents OOM on single GPU)
|
|
75
|
+
# Increase if you have multiple GPUs with sufficient VRAM
|
|
76
|
+
# MAX_CONCURRENT_JOBS=1
|
|
77
|
+
|
|
78
|
+
# ==========================================
|
|
79
|
+
# System Configuration
|
|
80
|
+
# ==========================================
|
|
81
|
+
|
|
82
|
+
# GPU selection (comma-separated GPU IDs)
|
|
83
|
+
# Examples:
|
|
84
|
+
# CUDA_VISIBLE_DEVICES=0 # Use only GPU 0
|
|
85
|
+
# CUDA_VISIBLE_DEVICES=0,1 # Use GPUs 0 and 1
|
|
86
|
+
# CUDA_VISIBLE_DEVICES=1,2,3 # Use GPUs 1, 2, and 3
|
|
87
|
+
# CUDA_VISIBLE_DEVICES=
|
|
88
|
+
|
|
89
|
+
# Logging level (DEBUG, INFO, WARNING, ERROR)
|
|
90
|
+
LOG_LEVEL=INFO
|
|
91
|
+
|
|
92
|
+
# Offline mode: never contact the HuggingFace Hub. Models and datasets are
|
|
93
|
+
# loaded from the local HF cache or local paths only (sets HF_HUB_OFFLINE
|
|
94
|
+
# and TRANSFORMERS_OFFLINE). Use GET /models/local or the "Local Models"
|
|
95
|
+
# picker in the UI to see what's available offline.
|
|
96
|
+
OFFLINE_MODE=false
|
|
97
|
+
|
|
98
|
+
# ==========================================
|
|
99
|
+
# Unified-Memory Protection (DGX Spark / Grace-Blackwell)
|
|
100
|
+
# ==========================================
|
|
101
|
+
# On unified-memory machines (NVIDIA GB10 "DGX Spark", GH200/GB200, Jetson)
|
|
102
|
+
# the GPU and system RAM share one physical pool. A training memory spike
|
|
103
|
+
# there doesn't raise a clean CUDA OOM — it can starve the OS and take the
|
|
104
|
+
# whole machine down. Merlina's memory guard detects these systems, caps
|
|
105
|
+
# the CUDA allocator so spikes fail as ordinary OOMs, and runs a watchdog
|
|
106
|
+
# that gracefully stops (or, as a last resort, aborts) training before the
|
|
107
|
+
# OS runs out of RAM. It also writes an fsync'd forensic log to
|
|
108
|
+
# data/memory_guard.log so post-crash investigation has a memory timeline.
|
|
109
|
+
#
|
|
110
|
+
# The guard is a no-op on discrete-GPU systems. Defaults are tuned for a
|
|
111
|
+
# 128GB GB10; you rarely need to change anything.
|
|
112
|
+
|
|
113
|
+
# Master switch for the guard
|
|
114
|
+
# MEMORY_GUARD_ENABLED=true
|
|
115
|
+
|
|
116
|
+
# Detection override: auto (default) | true (force on) | false (force off)
|
|
117
|
+
# UNIFIED_MEMORY=auto
|
|
118
|
+
|
|
119
|
+
# RAM kept off-limits to the CUDA allocator (GB). Capped at 25% of the pool
|
|
120
|
+
# on small boards.
|
|
121
|
+
# MEMORY_GUARD_RESERVE_GB=12
|
|
122
|
+
|
|
123
|
+
# Free-RAM floors for the watchdog (GB): below the soft floor training is
|
|
124
|
+
# gracefully stopped (checkpoint saved); below the hard floor the job is
|
|
125
|
+
# aborted to keep the machine alive. Scaled down automatically on systems
|
|
126
|
+
# with less total RAM.
|
|
127
|
+
# MEMORY_GUARD_SOFT_FREE_GB=8
|
|
128
|
+
# MEMORY_GUARD_HARD_FREE_GB=3
|
|
129
|
+
|
|
130
|
+
# Watchdog sampling interval (seconds) and forensic log switch
|
|
131
|
+
# MEMORY_GUARD_POLL_SECONDS=5
|
|
132
|
+
# MEMORY_GUARD_LOG_ENABLED=true
|
|
133
|
+
|
|
134
|
+
# At the soft floor the watchdog first releases the CUDA allocator's idle
|
|
135
|
+
# cache (e.g. eval leftovers) and only stops training if free RAM is still
|
|
136
|
+
# below the floor — or if pressure returns within this cooldown (seconds).
|
|
137
|
+
# MEMORY_GUARD_RECLAIM_COOLDOWN_SECONDS=60
|
|
138
|
+
|
|
139
|
+
# ==========================================
|
|
140
|
+
# Security & Limits
|
|
141
|
+
# ==========================================
|
|
142
|
+
|
|
143
|
+
# CORS origins (comma-separated list or "*" for all)
|
|
144
|
+
# CORS_ORIGINS=*
|
|
145
|
+
|
|
146
|
+
# Maximum upload file size in MB
|
|
147
|
+
# MAX_UPLOAD_SIZE_MB=500
|
|
148
|
+
|
|
149
|
+
# ==========================================
|
|
150
|
+
# llama.cpp Integration (Optional)
|
|
151
|
+
# ==========================================
|
|
152
|
+
# Merlina uses llama.cpp for GGUF export/quantization and (optionally)
|
|
153
|
+
# spinning up llama-server for synthetic rejected-response generation.
|
|
154
|
+
#
|
|
155
|
+
# Resolution precedence (first hit wins):
|
|
156
|
+
# 1. LLAMA_CPP_DIR — path to a llama.cpp checkout (contains
|
|
157
|
+
# convert_hf_to_gguf.py and build/bin/)
|
|
158
|
+
# 2. LLAMA_CPP_BIN_DIR — path to a directory of built binaries only
|
|
159
|
+
# 3. System PATH — llama-quantize, llama-server, etc. on PATH
|
|
160
|
+
# 4. ./vendor/llama.cpp — conventional local clone
|
|
161
|
+
#
|
|
162
|
+
# If none of the above are present, llama.cpp-backed features stay disabled
|
|
163
|
+
# in the UI and pre-flight surfaces a warning (never an error).
|
|
164
|
+
# LLAMA_CPP_DIR=/opt/llama.cpp
|
|
165
|
+
# LLAMA_CPP_BIN_DIR=/opt/llama.cpp/build/bin
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# GitHub Actions Workflows
|
|
2
|
+
|
|
3
|
+
This directory contains CI/CD workflows for automated testing and quality checks.
|
|
4
|
+
|
|
5
|
+
## Workflows
|
|
6
|
+
|
|
7
|
+
### 1. Tests (`tests.yml`)
|
|
8
|
+
|
|
9
|
+
**Triggers**: Push to main/master/develop, Pull Requests
|
|
10
|
+
|
|
11
|
+
**What it does**:
|
|
12
|
+
- Runs on Python 3.10 and 3.11 (matrix testing)
|
|
13
|
+
- Installs all dependencies
|
|
14
|
+
- Runs comprehensive API test suite
|
|
15
|
+
- Generates coverage reports
|
|
16
|
+
- Uploads coverage to Codecov
|
|
17
|
+
- Runs code quality checks (ruff, black, mypy)
|
|
18
|
+
|
|
19
|
+
**Jobs**:
|
|
20
|
+
- `test`: Runs all tests with coverage
|
|
21
|
+
- `lint`: Code quality checks
|
|
22
|
+
- `test-summary`: Posts summary to GitHub
|
|
23
|
+
|
|
24
|
+
**Duration**: ~3-5 minutes
|
|
25
|
+
|
|
26
|
+
### 2. Quick Tests (`quick-test.yml`)
|
|
27
|
+
|
|
28
|
+
**Triggers**: Push to any branch
|
|
29
|
+
|
|
30
|
+
**What it does**:
|
|
31
|
+
- Fast feedback on every commit
|
|
32
|
+
- Runs only comprehensive API tests
|
|
33
|
+
- Times out after 5 minutes
|
|
34
|
+
- Comments on PR if tests fail
|
|
35
|
+
|
|
36
|
+
**Duration**: ~2-3 minutes
|
|
37
|
+
|
|
38
|
+
## Status Badges
|
|
39
|
+
|
|
40
|
+
Add these badges to your README:
|
|
41
|
+
|
|
42
|
+
```markdown
|
|
43
|
+
[](https://github.com/Schneewolf-Labs/Merlina/actions/workflows/tests.yml)
|
|
44
|
+
[](https://github.com/Schneewolf-Labs/Merlina/actions/workflows/quick-test.yml)
|
|
45
|
+
[](https://codecov.io/gh/Schneewolf-Labs/Merlina)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Configuration
|
|
49
|
+
|
|
50
|
+
### Required Secrets
|
|
51
|
+
|
|
52
|
+
None required for basic testing. Optional:
|
|
53
|
+
|
|
54
|
+
- `CODECOV_TOKEN`: For private repo coverage reports
|
|
55
|
+
- `HF_TOKEN`: For testing with gated models
|
|
56
|
+
|
|
57
|
+
### Permissions
|
|
58
|
+
|
|
59
|
+
Default permissions are sufficient. The workflows need:
|
|
60
|
+
- Read access to repository
|
|
61
|
+
- Write access to checks (automatic)
|
|
62
|
+
|
|
63
|
+
## Running Locally
|
|
64
|
+
|
|
65
|
+
To run the same tests locally:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# Run all tests
|
|
69
|
+
pytest tests/test_api_comprehensive.py -v
|
|
70
|
+
|
|
71
|
+
# Run with coverage
|
|
72
|
+
pytest --cov=src --cov=merlina --cov-report=html
|
|
73
|
+
|
|
74
|
+
# Quick test (matches quick-test.yml)
|
|
75
|
+
pytest tests/test_api_comprehensive.py -v --tb=short -x
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Customization
|
|
79
|
+
|
|
80
|
+
### Change Python Versions
|
|
81
|
+
|
|
82
|
+
Edit `tests.yml`:
|
|
83
|
+
|
|
84
|
+
```yaml
|
|
85
|
+
strategy:
|
|
86
|
+
matrix:
|
|
87
|
+
python-version: ['3.10', '3.11', '3.12']
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Add More Tests
|
|
91
|
+
|
|
92
|
+
Edit the test step:
|
|
93
|
+
|
|
94
|
+
```yaml
|
|
95
|
+
- name: Run all tests
|
|
96
|
+
run: |
|
|
97
|
+
pytest tests/ -v
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Disable Lint Checks
|
|
101
|
+
|
|
102
|
+
Remove or comment out the `lint` job in `tests.yml`.
|
|
103
|
+
|
|
104
|
+
## Troubleshooting
|
|
105
|
+
|
|
106
|
+
### Tests Fail Locally but Pass in CI
|
|
107
|
+
|
|
108
|
+
- Check Python version: `python --version`
|
|
109
|
+
- Clear pytest cache: `pytest --cache-clear`
|
|
110
|
+
- Install exact dependencies: `pip install -r requirements.txt -r tests/requirements-test.txt`
|
|
111
|
+
|
|
112
|
+
### Slow Tests
|
|
113
|
+
|
|
114
|
+
- Use `quick-test.yml` for fast feedback
|
|
115
|
+
- Run specific tests: `pytest tests/test_api_comprehensive.py::TestTrainingEndpoints`
|
|
116
|
+
- Enable parallel testing: `pytest -n auto`
|
|
117
|
+
|
|
118
|
+
### Coverage Not Uploading
|
|
119
|
+
|
|
120
|
+
- Check Codecov token (for private repos)
|
|
121
|
+
- Verify coverage.xml is generated
|
|
122
|
+
- Check Codecov action logs
|
|
123
|
+
|
|
124
|
+
## Best Practices
|
|
125
|
+
|
|
126
|
+
1. **Keep tests fast**: Use mocking to avoid slow operations
|
|
127
|
+
2. **Fail fast**: Use `-x` flag to stop on first failure
|
|
128
|
+
3. **Matrix testing**: Test multiple Python versions
|
|
129
|
+
4. **Branch protection**: Require tests to pass before merge
|
|
130
|
+
5. **Coverage goals**: Maintain >80% coverage
|
|
131
|
+
|
|
132
|
+
## Maintenance
|
|
133
|
+
|
|
134
|
+
These workflows are automatically maintained and updated with the test suite. No manual updates needed unless:
|
|
135
|
+
|
|
136
|
+
- Adding new Python versions
|
|
137
|
+
- Changing test structure
|
|
138
|
+
- Adding new dependencies
|
|
139
|
+
- Modifying coverage requirements
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
**Last Updated**: 2025-11-16
|
|
144
|
+
**Maintained by**: Merlina Development Team
|
merlina-2.2.0/.gitignore
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
.env
|
|
2
|
+
|
|
3
|
+
# Node.js (installed by CI for Playwright tests). Anchored to repo root
|
|
4
|
+
# so legitimate sub-package.json files (e.g. frontend/js/package.json,
|
|
5
|
+
# which marks that directory as ESM for older Node versions) stay tracked.
|
|
6
|
+
node_modules/
|
|
7
|
+
/package.json
|
|
8
|
+
/package-lock.json
|
|
9
|
+
|
|
10
|
+
# Playwright test artifacts
|
|
11
|
+
test-results/
|
|
12
|
+
playwright-report/
|
|
13
|
+
|
|
14
|
+
# ML stuff
|
|
15
|
+
wandb/
|
|
16
|
+
|
|
17
|
+
# Merlina app outputs
|
|
18
|
+
models/
|
|
19
|
+
results/
|
|
20
|
+
data/
|
|
21
|
+
uploads/
|
|
22
|
+
*.safetensors
|
|
23
|
+
*.bin
|
|
24
|
+
|
|
25
|
+
# Byte-compiled / optimized / DLL files
|
|
26
|
+
__pycache__/
|
|
27
|
+
*.py[codz]
|
|
28
|
+
*$py.class
|
|
29
|
+
|
|
30
|
+
# C extensions
|
|
31
|
+
*.so
|
|
32
|
+
|
|
33
|
+
# Distribution / packaging
|
|
34
|
+
.Python
|
|
35
|
+
build/
|
|
36
|
+
develop-eggs/
|
|
37
|
+
dist/
|
|
38
|
+
downloads/
|
|
39
|
+
eggs/
|
|
40
|
+
.eggs/
|
|
41
|
+
lib/
|
|
42
|
+
lib64/
|
|
43
|
+
parts/
|
|
44
|
+
sdist/
|
|
45
|
+
var/
|
|
46
|
+
wheels/
|
|
47
|
+
share/python-wheels/
|
|
48
|
+
*.egg-info/
|
|
49
|
+
.installed.cfg
|
|
50
|
+
*.egg
|
|
51
|
+
MANIFEST
|
|
52
|
+
|
|
53
|
+
# PyInstaller
|
|
54
|
+
# Usually these files are written by a python script from a template
|
|
55
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
56
|
+
*.manifest
|
|
57
|
+
*.spec
|
|
58
|
+
|
|
59
|
+
# Installer logs
|
|
60
|
+
pip-log.txt
|
|
61
|
+
pip-delete-this-directory.txt
|
|
62
|
+
|
|
63
|
+
# Unit test / coverage reports
|
|
64
|
+
htmlcov/
|
|
65
|
+
.tox/
|
|
66
|
+
.nox/
|
|
67
|
+
.coverage
|
|
68
|
+
.coverage.*
|
|
69
|
+
.cache
|
|
70
|
+
nosetests.xml
|
|
71
|
+
coverage.xml
|
|
72
|
+
*.cover
|
|
73
|
+
*.py.cover
|
|
74
|
+
.hypothesis/
|
|
75
|
+
.pytest_cache/
|
|
76
|
+
cover/
|
|
77
|
+
|
|
78
|
+
# Translations
|
|
79
|
+
*.mo
|
|
80
|
+
*.pot
|
|
81
|
+
|
|
82
|
+
# Django stuff:
|
|
83
|
+
*.log
|
|
84
|
+
local_settings.py
|
|
85
|
+
db.sqlite3
|
|
86
|
+
db.sqlite3-journal
|
|
87
|
+
|
|
88
|
+
# Flask stuff:
|
|
89
|
+
instance/
|
|
90
|
+
.webassets-cache
|
|
91
|
+
|
|
92
|
+
# Scrapy stuff:
|
|
93
|
+
.scrapy
|
|
94
|
+
|
|
95
|
+
# Sphinx documentation
|
|
96
|
+
docs/_build/
|
|
97
|
+
|
|
98
|
+
# PyBuilder
|
|
99
|
+
.pybuilder/
|
|
100
|
+
target/
|
|
101
|
+
|
|
102
|
+
# Jupyter Notebook
|
|
103
|
+
.ipynb_checkpoints
|
|
104
|
+
|
|
105
|
+
# IPython
|
|
106
|
+
profile_default/
|
|
107
|
+
ipython_config.py
|
|
108
|
+
|
|
109
|
+
# pyenv
|
|
110
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
111
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
112
|
+
# .python-version
|
|
113
|
+
|
|
114
|
+
# pipenv
|
|
115
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
116
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
117
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
118
|
+
# install all needed dependencies.
|
|
119
|
+
#Pipfile.lock
|
|
120
|
+
|
|
121
|
+
# UV
|
|
122
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
123
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
124
|
+
# commonly ignored for libraries.
|
|
125
|
+
#uv.lock
|
|
126
|
+
|
|
127
|
+
# poetry
|
|
128
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
129
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
130
|
+
# commonly ignored for libraries.
|
|
131
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
132
|
+
#poetry.lock
|
|
133
|
+
#poetry.toml
|
|
134
|
+
|
|
135
|
+
# pdm
|
|
136
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
137
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
138
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
139
|
+
#pdm.lock
|
|
140
|
+
#pdm.toml
|
|
141
|
+
.pdm-python
|
|
142
|
+
.pdm-build/
|
|
143
|
+
|
|
144
|
+
# pixi
|
|
145
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
146
|
+
#pixi.lock
|
|
147
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
148
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
149
|
+
.pixi
|
|
150
|
+
|
|
151
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
152
|
+
__pypackages__/
|
|
153
|
+
|
|
154
|
+
# Celery stuff
|
|
155
|
+
celerybeat-schedule
|
|
156
|
+
celerybeat.pid
|
|
157
|
+
|
|
158
|
+
# SageMath parsed files
|
|
159
|
+
*.sage.py
|
|
160
|
+
|
|
161
|
+
# Environments
|
|
162
|
+
.env # Merlina configuration (API keys, secrets)
|
|
163
|
+
.env.* # Environment-specific configs (.env.production, etc.)
|
|
164
|
+
!.env.example # Keep example config template
|
|
165
|
+
.envrc
|
|
166
|
+
.venv
|
|
167
|
+
env/
|
|
168
|
+
venv/
|
|
169
|
+
ENV/
|
|
170
|
+
env.bak/
|
|
171
|
+
venv.bak/
|
|
172
|
+
|
|
173
|
+
# Spyder project settings
|
|
174
|
+
.spyderproject
|
|
175
|
+
.spyproject
|
|
176
|
+
|
|
177
|
+
# Rope project settings
|
|
178
|
+
.ropeproject
|
|
179
|
+
|
|
180
|
+
# mkdocs documentation
|
|
181
|
+
/site
|
|
182
|
+
|
|
183
|
+
# mypy
|
|
184
|
+
.mypy_cache/
|
|
185
|
+
.dmypy.json
|
|
186
|
+
dmypy.json
|
|
187
|
+
|
|
188
|
+
# Pyre type checker
|
|
189
|
+
.pyre/
|
|
190
|
+
|
|
191
|
+
# pytype static type analyzer
|
|
192
|
+
.pytype/
|
|
193
|
+
|
|
194
|
+
# Cython debug symbols
|
|
195
|
+
cython_debug/
|
|
196
|
+
|
|
197
|
+
# PyCharm
|
|
198
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
199
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
200
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
201
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
202
|
+
#.idea/
|
|
203
|
+
|
|
204
|
+
# Abstra
|
|
205
|
+
# Abstra is an AI-powered process automation framework.
|
|
206
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
207
|
+
# Learn more at https://abstra.io/docs
|
|
208
|
+
.abstra/
|
|
209
|
+
|
|
210
|
+
# Visual Studio Code
|
|
211
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
212
|
+
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
213
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
214
|
+
# you could uncomment the following to ignore the entire vscode folder
|
|
215
|
+
# .vscode/
|
|
216
|
+
|
|
217
|
+
# Ruff stuff:
|
|
218
|
+
.ruff_cache/
|
|
219
|
+
|
|
220
|
+
# PyPI configuration file
|
|
221
|
+
.pypirc
|
|
222
|
+
|
|
223
|
+
# Cursor
|
|
224
|
+
# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
|
|
225
|
+
# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
|
|
226
|
+
# refer to https://docs.cursor.com/context/ignore-files
|
|
227
|
+
.cursorignore
|
|
228
|
+
.cursorindexingignore
|
|
229
|
+
|
|
230
|
+
# Marimo
|
|
231
|
+
marimo/_static/
|
|
232
|
+
marimo/_lsp/
|
|
233
|
+
__marimo__/
|
|
234
|
+
.test-venv/
|