Перейти до основного вмісту

Внесок у проєкт LLiMa

LLiMa містить компілятор GenAI для сторони хоста та C++ середовище виконання для Modalix. Середовище виконання працює через упаковані точки входу CLI/HTTP/ZMQ; Python використовується для оркестрації CLI, а не як окремий загальнодоступний API середовища виконання. Зберігайте компілятор і середовище виконання, а також їхні залежності, окремо. Під час отримання коду з репозиторію, CONTRIBUTING.md надає інструкції для швидкого старту, а AGENTS.md визначає специфічні для агентів правила; цей посібник є детальним описом правил для розробників.

Навички програміста-агента.​

Встановіть обидва набори навичок для учасників, LLiMa, як частину стандартного налаштування для учасників. Вони навмисно не встановлюються за допомогою стандартного індексу сценаріїв Neat SDK:

sima-cli playbooks install \
gh:sima-neat/llima/skills/sima-contribute-to-llima
sima-cli playbooks install \
gh:sima-neat/llima/skills/sima-add-llima-model-support

Загальні навички учасника охоплюють компілятор, середовище виконання, пакування, тестування, документацію та зміни, що стосуються всього репозиторію. Навички підтримки моделі додають сумісність і робочий процес реалізації для архітектур LLM і VLM, контрольних точок, розміщення тензорів, токенізаторів і шаблонів підказок. Переконайтеся, що обидва встановлено, щоб відповідні інструкції були доступні, коли внесок виходить за межі цих параметрів.

Схема репозиторію.​

ПлощаШляхи, стежкиВідповідальність.
Конфігураціяsima_lmm/config/Конфігураційні файли для LLM, VLM та ASR.
Вживання.sima_lmm/hf/, sima_lmm/gguf/Завантаження та перетворення форматів Hugging Face і GGUF.
Компіляціяsima_lmm/model/, sima_lmm/preproc/Компоненти моделі, квантування, графіки та попередня обробка.
Інструменти для хостингу.sima_lmm/host/Зберіть, розгорніть, LoRA, і проведіть тестування продуктивності основних точок входу.
Оцінювання.sima_lmm/mole/MoLE робочі процеси
Інтерфейс командного рядка для середовища виконання.sima_lmm/devkit/Python Оркестрація за допомогою інтерфейсу командного рядка та керування моделлю.
C++ середовище виконанняsima_lmm/devkit/cpp/Моделі, токенізатор, MLA, реалізації CLI/HTTP/ZMQ та внутрішнє зв’язування CLI.
Тестиtests/Тести компілятора та середовища виконання Modalix.
УпаковкаCMakeLists.txt, cmake/, build*.sh, tools/install_*.shDebian, формат wheel та збірка артефактів.
Кеші CI.github/workflows/, tools/ci/, tools/hf-safetensors/Здійснює збірку, тестування та зберігає кеш моделі.
Документація/навичкиREADME.md, docs/, skills/Користувач, автор, інструкції щодо використання Playbooks.

Залежності, які потрібні лише для компіляції, не повинні включатися до sima_lmm/devkit/ або до пакетів Modalix, що використовуються в середовищі виконання.

Середовища розробки​

Середовище виконання та пакування.​

Використовуйте Neat SDK як підтримуване середовище для збірки. Зберіть усі пакети для середовища виконання та упаковані тести за допомогою:

./build.sh --all --clean

Під час звичайної збірки виконуються всі необхідні налаштування, зокрема, ініціалізація підмодулів; не потрібно виконувати окремий етап встановлення залежностей для стандартного процесу.

Корисні альтернативні варіанти збірки:

./build.sh --clean --core
./build.sh --clean --core --dev
./build.sh --clean --cli
./build.sh --no-dist

Результати генеруються в рамках build-deb/ і розміщуються в dist/. Modalix необхідний для виконання MLA і для реальної перевірки llima run.

Розробка компіляторів.​

Використовуйте середовище Python 3.12, встановлене за допомогою Model Compiler. Здійснюйте пошук у наступному порядку:

  1. /sdk-extensions/model-compiler
  2. /sdk-add-on/model-compiler
  3. $HOME/sdk-extensions/model-compiler
source <model-compiler-venv>/bin/activate
python -m pip install -e '.[sdk_ext,tests]'
llima-compile --help

Не створюйте додаткове середовище, яке затінюватиме встановлені пакети компілятора. Створюйте профілі для публікації за допомогою:

./build_compiler_wheel.sh
./build_mole_package.sh

Вони використовують інструменти для роботи з колісними приводами під час build/ і розміщують проміжні результати під час dist/compiler/ та dist/mole/.

Розробка Whisper та ASR.​

Загальнодоступний процес llima-compile охоплює LLM та VLM. Для наявної Whisper замість попередньої використовується утиліта для розробників: scripts/gen_models--openai--whisper.py.

python scripts/gen_models--openai--whisper.py \
--model_path /path/to/openai/whisper-small \
--output /path/to/whisper-output \
--part all

Запустіть його в середовищі Model Compiler із зазначенням явного шляху до моделі. --part приймає all, encoder, language_detect, init, single_pre, single_post та single_cache. Додайте --enable_log_probe, щоб скомпілювати вихідні дані декодера з увімкненим журналюванням; використовуйте --part all --enable_log_probe для повної збірки з увімкненим журналюванням.

Репозиторії моделей Whisper містять один ELF на кожен шар кодувальника. Середовище виконання не підтримує застарілі репозиторії з монолітним ELF кодувальника; завантажте пошарову модель або перекомпілюйте контрольну точку поточною версією LLiMa.

Зазвичай зміни в компіляторі стосуються файлів sima_lmm/config/whisper_config.py, sima_lmm/model/whisper_*.py та скрипту; зміни в середовищі виконання стосуються sima_lmm/devkit/cpp/whisper_*. Перевірте за допомогою упакованого тесту середовища виконання C++ ASR, описаного в tests/README.md, та репрезентативних аудіофайлів на Modalix. Це специфічний шлях для Whisper, а не загальна архітектурна структура ASR.

Компоненти нативного графа​

Використовуйте ModelGraph з sima_lmm/model/model_graph.py. Він одноразово прив’язує вихідні ваги, точність і шлях виведення компонента. Побудова вузлів графа міститься в класі, а незалежні засоби перетворення масивів і найменування залишаються функціями модуля. Компоненти моделі використовують методи графа, тому їхня реалізація може зосередитися на топології:

from sima_lmm.model.model_graph import ModelGraph

def generate_graph(self, layer_cfg, quantizable):
graph = ModelGraph(self, {"hidden": (1, 1, self.num_tokens, self.cfg.d_model)}, quantizable)
hidden = graph.layer_norm("model.norm", graph.inputs["hidden"])
output = graph.mlp("model.mlp", hidden, "gelu", residual=graph.inputs["hidden"])
graph.save([output])

Визначайте входи окремого компонента, топологію верхнього рівня та graph.save() у generate_graph(). Залишайте _build_nodes(graph, inputs) для спільної побудови графів, зокрема частин pre/cache/post Whisper, що використовуються в об’єднаних графах декодера.

Область журналювання визначає BaseModel.gen_files(); побудова графа не потребує окремого аргументу журналювання.

За формами визначаються входи FP32 для quantizable=True (граф із рухомою комою для подальшого квантування) або BF16 для False (прямий граф із точністю вихідних ваг). Для цілочисельних входів, зокрема кешів, використовуйте input_dtypes={"cache": np.int8}; імена мають відповідати специфікаціям входів. Для низькорівневих викликів і надалі підтримуються явні специфікації тензорів AFE. Порядок входів і виходів відповідає наданим специфікаціям, а форми й типи виходів визначає AFE. constant() перетворює дані з рухомою комою на точність активацій; якщо цілочисельні константи потребують певної розрядності, використовуйте, наприклад, dtype=np.int32. Імена вузлів формуються за детермінованим лічильником створення AFE.

Для анотацій вузлів графа імпортуйте Node з model_graph.py. Допоміжні функції отримують граф замість окремого прапорця quantizable. graph.constant() автоматично вибирає точність рухомої коми; коли обчислення масивів на хості потребують цієї точності, використовуйте тип NumPy graph.dtype. Прапорець етапу залишається лише в generate_graph() та під час створення графа.

save() завершує підмережу MLA та створює кортежі виходів зовнішнього графа, зберігає цілочисельні виходи, перетворює виходи BF16 на FP32 на EV і записує артефакт зі стандартним ім’ям (.fp32 для графа з рухомою комою). Щоб отримати завершену мережу, використовуйте finish(). Обидва методи приймають transform_subnet для специфічних для моделі перетворень перед вилученням зовнішніх виходів. Передавайте допоміжним функціям компонента сам граф; входи, точність і вихідні ваги залишаються прив’язаними до одного об’єкта.

Виконуйте завершений граф з іменованими входами NumPy:

graph.finish([output])
outputs = graph.run(hidden=x)
outputs_jax = graph.run(hidden=x, use_jax=True)
graph.save()

Імена, форми та типи даних входів мають відповідати оголошеним входам; неявні перетворення типів не виконуються. Виходи зберігають порядок, переданий у finish(). Виконання NumPy використовує fast mode AFE, результати якого можуть відрізнятися від еталонних обчислень MLA. use_jax=True вибирає еталонне виконання JAX, де fast mode не має впливу. Операції JAX використовують налаштований бекенд і можуть виконуватися на GPU за сумісної інсталяції JAX. Цей API не виконує квантування, компіляцію чи запуск на Modalix. Завершіть граф один раз, а потім повторно використовуйте run() та save(); save(outputs) і далі дозволяє завершити та зберегти граф за один крок.

Поширені операції включають add, sub, mul, matmul, concat, slice, transpose, reshape, softmax, topk, sum_channels, argmax, linear, conv, layer_norm, rms_norm, activation, softcap, mlp, rope, rope2d, split_heads, merge_heads, split_concat, clip, avgpool2d, space_to_depth, quant, dequant. Для MLP із вентилем використовується projections=("gate_proj", "up_proj", "down_proj"); типове значення — ("fc1", "fc2"). rms_norm("model.norm", input) використовує epsilon і зміщення ваг із конфігурації мовної моделі. Для нормалізацій vision та GDN явний epsilon залишає нульове зміщення ваг, якщо також не задано weight_offset. rms_norm(None, input, epsilon=...) визначає канали без ваг. RoPE підтримує повне, часткове та пропорційне обертання split-half. rope2d(input, cos_x, sin_x, cos_y, sin_y) обертає чверті каналів у порядку [x-real, x-imag, y-real, y-imag]. split_heads(input, heads, repeat=...) повторює кожну голову для схем grouped-query. split_concat() надає операцію перегрупування AFE для просторових і токенних схем, які не можна виразити лише через reshape. space_to_depth(input, blocksize) об’єднує повні просторові блоки в канали. quant(input) повертає (int8_values, scale); dequant(int8_values, scale) відновлює точність активацій графа. argmax(input) повертає індекси каналів INT32. slice(input, begin, end, stride, axis) автоматично використовує селекторні згортки для невирівняних неперервних зрізів каналів уздовж однієї осі чотиривимірних тензорів FP32/BF16; інші зрізи зберігають нативну поведінку AFE.

linear("model.proj", input) знаходить model.proj.weight та необов’язкове зміщення, перетворює вихідні ваги OI на схему SiMa та зберігає упаковані значення ваг, масштаби, невирівняні розміри груп і метадані переміщення. conv() визначає вихідні схеми OIW або OIHW; явне перетворення може обробляти інші схеми, зокрема п’ятивимірні ваги патчів Qwen. WeightOptions описує перевизначення вихідного імені, схеми, перетворення ваг/масштабів/зміщень і переміщення. Під час зрізання групованих ваг надавайте відповідну scale_process_func; групи мають зберігати фактичний розмір із контрольної точки. Ранг LoRA та поведінка об’єднаного адаптера є явними аргументами linear() і mlp().

Будуйте attention із проєкцій і операцій над схемою голів. Включайте масштабування запитів у linear(), щоб зберегти наявне округлення проєкції:

queries = graph.split_heads(graph.linear("attn.q_proj", hidden, scale=head_dim ** -0.5), heads)
keys = graph.split_heads(graph.linear("attn.k_proj", hidden), heads)
values = graph.split_heads(graph.linear("attn.v_proj", hidden), heads)
context = graph.attention(queries, keys, values)
output = graph.linear("attn.out_proj", graph.merge_heads(context))

split_heads() обробляє невирівняні канали голів через селекторні згортки. Стандартний vision attention доповнює ваги проєкцій невирівняних голів, щоб уникнути цих згорток; груповані вихідні ваги зберігають початкову схему. attention() використовує довжини запитів і ключів для вибору окремих гілок голів великих тензорів attention, зокрема cross-attention. Він приймає адитивну mask та припускає, що запити вже масштабовано, якщо не задано score_scale. Цей масштаб застосовується після Q×K і перед маскою, зберігаючи порядок обчислень BF16 таких моделей, як Qwen vision. Маски мають бути чотиривимірними тензорами, векторами або скалярами й підтримувати трансляцію до [N,H,T_query,T_key]; непідтримувані форми спричиняють ValueError.

graph.matmul(lhs, rhs) створює пакетне множення матриць MLA. Обидва прапорці транспонування типово мають значення False; для Kᵀ×V використовуйте transpose_a=True, а для Q×Kᵀ — transpose_b=True. Входи мають бути чотиривимірними тензорами FP32/BF16 з однаковими пакетами та узгодженими розмірами згортання. Якщо кількості голів діляться одна на одну, grouped-query attention використовує неявне повторення; неправильні форми або типи спричиняють ValueError.

graph.softmax(x) типово використовує останню вісь; також підтримується явний axis. Для неперервного зрізу вздовж однієї осі використовуйте graph.slice(x, start=0, stop=128, axis=-1), а для кількох осей — наявні списки begin/end/stride/axis. Одноосьова форма типово починається з нуля, потребує явної осі та непорожніх меж у допустимому діапазоні й зберігає обробку невирівняних каналів. Не поєднуйте ці дві форми.

ModelGraph розширює SimaBuilder з AFE, тому нативні операції та спільні допоміжні функції доступні в одному об’єкті:

projected = graph.linear("model.proj", graph.inputs["hidden"])
output = graph.add(projected, graph.inputs["hidden"])
graph.save([output])

Стислі примітивні операції є прямими псевдонімами методів AFE та зберігають їхні сигнатури, визначення типів і детерміноване найменування. Для рідкісних операцій у тому самому графі залишаються доступними успадковані методи create_*. Графи з власним життєвим циклом кількох підмереж можуть і далі використовувати SimaBuilder з AFE безпосередньо разом із низькорівневими допоміжними операціями.

Теселяція централізовано визначається в sima_analysis.get_tessellate_parameters(): схема HWC16, автоматичні розміри плиток і детерміновані імена постійних буферів. Звичайні компоненти успадковують порожні перевизначення від BaseModel. Особливі схеми, наприклад кеші KV із кроком, перевизначають наявні методи get_mla_input_tessellate_params() / get_mla_output_tessellate_params(); ключами є індекси тензорів, а від’ємні індекси рахуються з кінця.

Компоненти Whisper, усі нативні частини мовних графів і стандартна vision tower демонструють використання цього API; допоміжні функції attention, MLP та обертання мають спільні реалізації. Компоненти DFlash для злиття контексту, проєкції K/V та відновлення стану також використовують generate_graph() і ModelGraph. Фінальний граф чернеткової моделі зберігає упаковані ваги та масштаби вихідної голови відповідної цільової моделі; граф перевірки зберігає виходи S1 та обчислених проміжних результатів, потрібні засобу відновлення стану в середовищі виконання.

Тестування​

Обирайте тести за типом помилки. Збірка не замінює перевірку поведінки, і пропущений обов’язковий тест не вважається успішно пройденим.

Герметичні випробування.​

Забезпечте, щоб чиста конфігурація, відображення, серіалізація, перевірка та числова логіка були незалежними від завантаження моделей:

pytest -q <targeted-test-path>

Тести компілятора, що використовують модель.​

Тести компілятора розміщено за адресою tests/compilation/. Оберіть відповідну групу та маркер, описані в tests/README.md. Наприклад:

export LLIMA_HF_MODELS_PATH=/path/to/llima-model-inputs
python -P -m pytest \
-c pytest.ini \
tests/compilation/configuration \
-m compiler_config \
--strict-markers \
-vv -ra

--model-inputs-path та LLIMA_HF_MODELS_PATH визначають підготовлену кореневу директорію Hugging Face/GGUF. Система безперервної інтеграції (CI) використовує маніфести, що знаходяться в tools/hf-safetensors/.

Налаштуйте необхідні вхідні дані замість того, щоб дозволяти пропуск тестів.

Матриця тестів, очікувані кількості та політика базових результатів містяться в tests/README.md; виклик CI — у .github/workflows/model-compiler-tests.yml. Генеруйте нативні графи SDK та артефакти числового порівняння під час виконання, замість додавання двійкових базових результатів до репозиторію.

Перевірка під час виконання (у середовищі виконання).​

Створіть пакети для кандидатів і додаткові компоненти для тестування в середовищі виконання:

./build.sh --all --clean

Це дозволяє зібрати проєкт, але не запускає тести. Встановіть відповідні пакети кандидата LLiMa на Modalix, розпакуйте додатковий архів і запустіть упаковані тести CTest і pytest, дотримуючись інструкцій щодо тестування в середовищі виконання DevKit, наведених у файлі tests/README.md.

Запускайте відповідні апаратні тести, коли зміни стосуються завантаження моделі, виконання висновків, токенізації, багатомодальної попередньої обробки, спекулятивного декодування, CLI/HTTP/ZMQ або життєвого циклу ресурсів. За потреби додайте репрезентативний базовий тест.

llima run <model_dir> --mode cli

Для змін, пов’язаних з VLM, додайте запит, що містить зображення. Ручне тестування на наявність помилок доповнює, але не замінює, охоплення відповідних пакетів.

Neat Core використовує встановлені LLiMa API та пакети середовища виконання C++. Коли будь-яка з цих компонентів або поведінка, що реалізується через API GenAI Core, змінюється, створіть Core, використовуючи кандидатські пакети sima-lmm-core та sima-lmm-dev, а не опубліковану або кешовану збірку LLiMa. Запустіть відповідні тести Core GenAI C++ на Modalix. Ця перевірка на наступному етапі не потрібна для ізольованих змін, що стосуються компілятора, документації або лише тестів.

Перевірка відповідності пакування встановленим вимогам.​

Зберіть кожен змінений профіль:

./build.sh --all --clean
./build_compiler_wheel.sh
./build_mole_package.sh

Перевірте назви пакетів, права власності на файли, файли маніфестів встановлення, залежності, контрольні суми та метадані.

Стандарти кодування​

Сумісність і межі.​

Розглядайте встановлені заголовні файли C++, команди інтерфейсу командного рядка, серіалізовану конфігурацію, метадані пакету та згенеровані макети артефактів як сумісні інтерфейси. Віддавайте перевагу інкрементним змінам. У разі внесення несумісних змін, документуйте задіяні компоненти, процес міграції та заплановані зміни; оновлюйте виклики, тести, приклади та документацію для користувачів.

Тримайте компілятор, середовище виконання та залежності MoLE окремо. Стан середовища виконання не повинен бути вхідними даними для компіляції. Зміни меж пакету середовища виконання повинні зберігати ролі sima-lmm-core, sima-lmm-dev та sima-lmm-cli і включати відповідну валідацію API/ABI.

Якість реалізації.​

  • Цільові версії C++20 і Python, зазначені у файлі pyproject.toml.
  • Дотримуйтеся загального форматування, використовуйте відповідні назви та забезпечте групування; уникайте надмірної узагальненості. механічне переформатування.
  • Зберігайте кількість встановлених інтерфейсів на мінімальному рівні та не розголошуйте деталі реалізації.
  • Додайте анотації типів Python, де це доцільно.
  • Поясніть неявні умови договорів, числові припущення та технічні характеристики обладнання. обмеження; не потрібно описувати код.
  • Перш ніж додавати абстракції, повторно використовуйте наявні допоміжні функції.
  • Забезпечте збереження детермінованого вибору моделі, структури графа та можливості серіалізації. імена артефактів. Зберігайте початкові значення та уникайте впорядкування файлової системи/процесів.
  • Відхиляйте неприйнятні або недійсні вхідні дані, надаючи контекст; зберігайте першопричини. між різними рівнями, і при цьому ніколи не обирає інший шлях виконання мовчки.
  • Організуйте взаємодію між працівниками та процес демонтажу. Створіть буфер, обробіть, налаштуйте та... Явно вказуйте власника тимчасових файлів; безпечно видаляйте частково виконану роботу.
  • Уникайте зайвого виділення пам’яті, створення копій і синхронізації в критичних ділянках коду.

Моделі, артефакти, залежності та секрети.​

Дозволено використовувати наступні матеріали для тестування:

  • переглянуто контракти щодо налаштувань JSON;
  • джерела, контрольовані версії, початкові дані, допустимі відхилення та політика порівняння; і
  • створює файли маніфесту для затверджених незмінних версій Hugging Face/GGUF.

Не додавайте до репозиторію завантажені ваги, дані користувачів або згенеровані файли ONNX, NumPy, квантовані дані, MPK, ELF або дерева моделей для середовища виконання. Зберігайте згенеровані результати в папках, які не відстежуються системою контролю версій, або в тимчасових папках.

Використовуйте deps/manifest.json для версій пакетів/платформ. Розглядайте third_party/ як сторонній код; ізолюйте та документуйте навмисні оновлення підмодулів. Не додавайте залежності компілятора до пакетів Debian, які використовуються під час виконання.

Ніколи не додавайте до репозиторію або не зберігайте в логах токени, облікові дані SSH, приватні репозиторії, підписані URL-адреси або особисті шляхи. Зберігайте авторизацію для моделей, що потребують контролю доступу, поза системою контролю версій і використовуйте загальнодоступні ідентифікатори моделей, незмінні версії та відредаговані журнали у звітах.

Документація, навички та запити на внесення змін.​

Оновіть найближчий посібник для користувача:

Залиште файл CONTRIBUTING.md як інструкцію для швидкого старту, цей файл – як детальну політику, а AGENTS.md – як набір правил для агентів, що підлягають виконанню. У наборі навичок обов’язково повинні бути вказані дійсні SKILL.md, playbook.yml та метадані агентів; зробіть їх основний робочий процес коротким і перенесіть умовні деталі в прямі посилання.

Перевіряйте всі корисні дані навичок з кореневої директорії репозиторію в Neat SDK, не змінюючи встановлений стан агентів:

playbooks_validation_dir="$(mktemp -d)"
CODEX_HOME="${playbooks_validation_dir}/codex" \
CLAUDE_HOME="${playbooks_validation_dir}/claude" \
SIMA_CLI_HOME="${playbooks_validation_dir}/sima-cli" \
sima-cli playbooks install ./skills

Звіт про встановлення має містити інформацію про те, що було detected: 3, що було valid: 3 і що було discarded: 0. Версія sima-cli має відповідати вимогам min_cli_version у кожному файлі playbook.yml.

Для повідомлень про дефекти використовуйте шаблон звіту про помилку, а для пропозицій покращень — шаблон запиту функції. Заповніть відповідні розділи та видаліть секретні дані з журналів і кроків відтворення.

Для запитів на внесення змін:

  • створіть гілку на основі та націльте її на поточну гілку develop;
  • зосереджуйте зміни в коді, використовуючи наказові форми дієслів у повідомленнях до комітів;
  • використовуйте .github/PULL_REQUEST_TEMPLATE.md;
  • пов’яжіть вирішені проблеми з Fixes #<issue>;
  • повідомити про ризики, сумісність/перехід, вплив на документацію, відтворювані команди. версії моделі/пакета, дані про апаратне забезпечення, пропущені перевірки та залишковий ризик; і
  • виключіть облікові дані та конфіденційні активи.

Внесок вважається готовим, коли всі відповідні тести успішно проходять без непередбачених пропусків, необхідні пакети та перевірки Modalix завершено або чітко вказано, що вони недоступні, питання сумісності та документації вирішено, і в запиті на внесення змін (PR) містяться відтворювані докази.

Обробка блокувань пакетів SDK​

Операції CI з пакетами хоста SDK використовують спільний допоміжний скрипт із sima-neat/.github@main. Він повторює спроби лише за розпізнаних конфліктів блокування dpkg/APT, до 120 секунд на операцію, надаючи діагностичні дані про власника блокування та процеси під час конфлікту. Інші помилки одразу завершують операцію невдачею; файли блокувань і процеси, що утримують блокування, залишаються недоторканими. Скрипт не керує цільовим sysroot або базою даних пакетів DevKit. Для локальних скриптів налаштування CI встановіть SDK_PACKAGE_HELPER на абсолютний шлях до scripts/sdk-package.sh у перевіреній локальній копії спільного репозиторію. Див. контракт спільного допоміжного скрипту.