diff --git a/.github/ci/benchmark_config.json b/.github/ci/benchmark_config.json index 43f8895d..0700669b 100644 --- a/.github/ci/benchmark_config.json +++ b/.github/ci/benchmark_config.json @@ -315,6 +315,9 @@ }, "smolvlm_500m": { "config": "ported_models/llama_cpp_et/benchmarks/smolvlm_500m.json" + }, + "modernbert_sentiment": { + "config": "ported_models/llama_cpp_et/benchmarks/modernbert_sentiment.json" } } } diff --git a/ported_models/llama_cpp_et/artifacts.json b/ported_models/llama_cpp_et/artifacts.json index 9c419ae1..614e6a55 100644 --- a/ported_models/llama_cpp_et/artifacts.json +++ b/ported_models/llama_cpp_et/artifacts.json @@ -485,6 +485,25 @@ "sha256": "d1eb8b6b23979205fdf63703ed10f788131a3f812c7b1f72e0119d5d81295150", "size_bytes": 108783360, "note": "SmolVLM 500M vision projector (SigLIP ~93M + MLP). Q8_0 quantized. Must be loaded alongside smolvlm_500m_q8_gguf." + }, + "modernbert_sentiment_f32_gguf": { + "kind": "model", + "framework": "llama.cpp-et", + "variant": "modernBERT-base-multilingual-sentiment-F32", + "filename": "modernbert_sentiment_f32.gguf", + "env": "MODERNBERT_SENTIMENT_MODEL_PATH", + "source": { + "type": "github_release", + "repo": "DarthCeltic/hf-hackathon", + "tag": "model-port-modernbert-sentiment-v1", + "filename": "modernbert_sentiment_f32.gguf", + "url": "https://github.com/DarthCeltic/hf-hackathon/releases/download/model-port-modernbert-sentiment-v1/modernbert_sentiment_f32.gguf", + "note": "GGUF conversion of upstream clapAI/modernBERT-base-multilingual-sentiment (huggingface.co, revision baa7f26fee4eca5aec35538caa5fdda7b86d83c6, license apache-2.0), produced with this repo's own convert_hf_to_gguf.py (ggml LLM_ARCH_MODERN_BERT). Hosted as a GitHub Release asset because we do not have a Hugging Face upload token; reproducible from the committed recipe (ported_models/modernbert_sentiment/docs/RECIPE.md)." + }, + "sha256": "7896d82f2548762409157ae4e68732cd2c78796b5c8cea5e0145b964e916ab4c", + "size": 600207808, + "local_cache": "local-artifacts/models/modernbert_sentiment_f32.gguf", + "board_path": "/data/models/modernbert_sentiment_f32.gguf" } } } diff --git a/ported_models/llama_cpp_et/benchmarks/modernbert_sentiment.json b/ported_models/llama_cpp_et/benchmarks/modernbert_sentiment.json new file mode 100644 index 00000000..1d341432 --- /dev/null +++ b/ported_models/llama_cpp_et/benchmarks/modernbert_sentiment.json @@ -0,0 +1,34 @@ +{ + "runner": "llama_server", + "board": true, + "framework": { + "name": "llama.cpp-et", + "runner": "llama_server", + "source_artifact": "llama_cpp_source" + }, + "artifacts_file": "../artifacts.json", + "canonical_variant": "modernbert_sentiment_f32", + "score": { + "metric": "tokens_per_second", + "label": "Decode tokens/s", + "higher_is_better": true + }, + "llama_server": { + "source_artifact": "llama_cpp_source", + "model_artifact": "modernbert_sentiment_f32_gguf", + "server_artifact": "llama_server", + "workdir_artifact": "llama_cpp_build", + "host": "127.0.0.1", + "port": 18152, + "device": "ET", + "gpu_layers": 99, + "ctx_size": 512, + "batch_size": 128, + "ubatch_size": 128, + "parallel": 1, + "cache_ram_mib": 0, + "ready_timeout_s": 300, + "request_timeout_s": 420, + "api": "rerank" + } +} diff --git a/ported_models/modernbert_sentiment/docs/RECIPE.md b/ported_models/modernbert_sentiment/docs/RECIPE.md new file mode 100644 index 00000000..8892d8d4 --- /dev/null +++ b/ported_models/modernbert_sentiment/docs/RECIPE.md @@ -0,0 +1,78 @@ +# ModernBERT-base Multilingual Sentiment Porting Recipe + +## Overview + +Adds `clapAI/modernBERT-base-multilingual-sentiment` (149M-parameter +encoder-only sequence-classification model, 3-way sentiment) to the +`llama.cpp-et` framework. Confirmed via local GGUF metadata inspection and +a real server load test: `general.architecture = modern-bert` -- distinct +from `bert` (already ported earlier in this campaign as `distilbert_sst2`) +and from `nomic-bert`/`jina-bert-v2`/`jina-bert-v3`/`neo-bert`/`eurobert` +(all separate, unclaimed arches) -- ModernBERT is architecturally its own +family: alternating global/local sliding-window attention (`n_swa=128`, +pattern every 3 layers), RoPE instead of learned position embeddings, +GeGLU FFN. + +This artifact was self-converted earlier this session (before this +specific porting campaign) and hosted as a GitHub Release +(`model-port-modernbert-sentiment-v1`), matching the same precedent as +`distilbert_sst2`/`roberta_sst2` -- it had not yet had a model-ports claim +filed until now. + +## Model Reference + +- **Source**: `clapAI/modernBERT-base-multilingual-sentiment` (Hugging + Face), revision `baa7f26fee4eca5aec35538caa5fdda7b86d83c6` +- **License**: Apache-2.0 +- **Artifact**: self-converted F32 GGUF (no quantization -- encoder + classification heads are small; F32 avoids any quantization-accuracy + question for a 3-way classifier), produced via this repo's own + `convert_hf_to_gguf.py`, hosted at + `https://github.com/DarthCeltic/hf-hackathon/releases/download/model-port-modernbert-sentiment-v1/modernbert_sentiment_f32.gguf`, + `sha256=7896d82f2548762409157ae4e68732cd2c78796b5c8cea5e0145b964e916ab4c` + (verified locally against the downloaded file), 600,207,808 bytes +- **Architecture**: `arch = modern-bert` per GGUF metadata, 138 tensors, + 22 layers, 768 embedding, 12 heads, sliding-window attention (window + 128, every 3rd layer is global), `n_cls_out=3` + (`cls_label = [negative, neutral, positive]`) + +## Verification performed this round + +Built `llama-server` from a plain CPU-only (`GGML_ET=OFF`) configuration +of the vendored `llama.cpp-et` source, loaded the GGUF, and issued a real +`POST /rerank` request. The server loaded all metadata correctly (3-way +classifier head, sliding-window pattern) and returned real relevance +scores for both documents -- confirmed live, not just GGUF-metadata +inspection: + +``` +{"model":"modernbert_sentiment_f32.gguf","results":[ + {"index":1,"relevance_score":2.3337833881378174}, + {"index":0,"relevance_score":0.5375099182128906}]} +``` + +This is the same verification tier as `distilbert_sst2`/`roberta_sst2` +earlier in this campaign (real server load + real endpoint response), not +just a metadata read. + +## Why this port likely needs no new ET-SoC1 kernel work + +Sliding-window attention is already proven on this backend by Gemma2/ +Cohere2/Starcoder2/PLaMo-3 earlier in this campaign (an ordinary masked +`GGML_OP_SOFT_MAX`, not a new op). RoPE, LayerNorm-family norm, and GeGLU +FFN (an existing gated-unary op) are all already proven elsewhere on this +board. Not confirmed live against ET sysemu specifically this round -- +only the CPU backend was exercised. + +## Open items for maintainer review + +- Registered in `artifacts.json`, `ported_models/llama_cpp_et/benchmarks/modernbert_sentiment.json`, + and `.github/ci/benchmark_config.json` -- but see the same caveat as + `distilbert_sst2`: the shared runner (`run_llama_server_benchmark.py`) + only speaks `/completion`/`/v1/chat/completions`, not `/rerank`, so this + entry documents the port but cannot be scored by automated per-PR CI + without a maintainer adding `/rerank` support to that script (a protected + file we cannot edit ourselves). +- `ported_models/submissions/model_ports/modernbert_sentiment.json` is the + model-ports track claim, pending identity approval. +- No changes to any protected file or the vendored submodule. diff --git a/ported_models/modernbert_sentiment/oracle/sentiment_oracle.json b/ported_models/modernbert_sentiment/oracle/sentiment_oracle.json new file mode 100644 index 00000000..debbae37 --- /dev/null +++ b/ported_models/modernbert_sentiment/oracle/sentiment_oracle.json @@ -0,0 +1,27 @@ +{ + "oracle_type": "sentiment_rerank_reference", + "model_artifact": { + "repo": "DarthCeltic/hf-hackathon", + "release_tag": "model-port-modernbert-sentiment-v1", + "filename": "modernbert_sentiment_f32.gguf", + "sha256": "7896d82f2548762409157ae4e68732cd2c78796b5c8cea5e0145b964e916ab4c" + }, + "reference_run": { + "endpoint": "POST /rerank", + "results": [ + { + "index": 1, + "relevance_score": 2.3337833881378174 + }, + { + "index": 0, + "relevance_score": 0.5375099182128906 + } + ], + "measured_on": "CPU (ggml-cpu backend, GGML_ET=OFF build)" + }, + "comparison_threshold": { + "metric": "relevance_score_rank_order", + "note": "A reproduction run should preserve the same relative rank order (index 1 scoring higher than index 0) for the same two fixed input documents; exact score reproduction is not expected across backends but rank order should be stable. No ET-SoC1 hardware was available to this session to perform a full-offload re-run directly." + } +} diff --git a/ported_models/submissions/model_ports/modernbert_sentiment.json b/ported_models/submissions/model_ports/modernbert_sentiment.json new file mode 100644 index 00000000..ad1b7948 --- /dev/null +++ b/ported_models/submissions/model_ports/modernbert_sentiment.json @@ -0,0 +1,14 @@ +{ + "schema_version": 1, + "track": "most_models_ported", + "benchmark_model": "modernbert_sentiment", + "identity_id": "modern-bert", + "source": { + "repo": "clapAI/modernBERT-base-multilingual-sentiment", + "revision": "baa7f26fee4eca5aec35538caa5fdda7b86d83c6", + "license": "apache-2.0" + }, + "implementation_paths": ["ported_models/modernbert_sentiment"], + "benchmark_config": ".github/ci/benchmark_config.json", + "recipe": "ported_models/modernbert_sentiment/docs/RECIPE.md" +}