惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

爱范儿
爱范儿
博客园 - 叶小钗
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
腾讯CDC
S
SegmentFault 最新的问题
D
DataBreaches.Net
Hugging Face - Blog
Hugging Face - Blog
L
LangChain Blog
Recent Announcements
Recent Announcements
阮一峰的网络日志
阮一峰的网络日志
N
Netflix TechBlog - Medium
大猫的无限游戏
大猫的无限游戏
M
MIT News - Artificial intelligence
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 三生石上(FineUI控件)
F
Fortinet All Blogs
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Martin Fowler
Martin Fowler
雷峰网
雷峰网
J
Java Code Geeks
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
小众软件
小众软件
云风的 BLOG
云风的 BLOG
T
Tailwind CSS Blog

GoPenAI - Medium

Group Relative Policy Optimization (GRPO) Your agent fleet can build trustworthy state with their own keys Epistemic Backbone #1: Why AI Systems Need Shared Memory, Not Just Models Transformers Beyond NLP: Fun and Trendy Use Cases Your First Transformer: The Road to Attention Part 4. From Seats to Agents: Early Evidence on the Future of Work in the Agentic AI Era The AI Trust Gap: Why Faster Code Is Creating Less Confidence From Bytes to BPE: A From-Scratch Tour of LLM Tokenization ️ Grok Voice Think Fast 1.0: The First Voice AI That Actually Thinks While Talking .NET 10.0.7 OOB Security Update: The Kind of Bug You Can’t Afford to Ignore Writing Custom Pallas Kernels for vLLM on TPU — A Step-by-Step Guide Contrastive Learning Day 39: Advanced Ensemble Learning Techniques — Stacking, Random Forest, AdaBoost, and Gradient… Localization: Beyond Translation, Into the Territory of Growth Hacking Can We Translate Our Sentiments? What Is Data, and Why Does It Matter for AI? A Complete Guide to Prompt Engineering: Best Practices & Tips DeepSeek TileKernels: The Hidden Tech Making AI Models Insanely Fast Can AI Growth Really Become Economic Growth? Evaluating API Test Generation Across Leading AI Tools Pin Clustering in .NET MAUI Maps: Finally Making Maps Usable (With Example) Unsupervised Learning What is an LLM? Tokens, Context Window, and Why They Matter Build a reactive AI agent harness — Part 1. Conversation. From Hallucination to Citation… RAG Made Simple: How AI Finds the Right Answers CLI Coding Agents Tierlist Google Deep Research Max: Build Autonomous AI Research Agents Hermes Agent vs Every AI Assistant: Why Memory Changes Everything I Watched a Startup Burn $1,200 in a Week. The Culprit Was 800 Tokens.
Training the first modern architecture encoder for South ...
Mitar Perovi · 2026-05-02 · via GoPenAI - Medium
After the release of BalkanBench two days ago, I am more than proud to finally release the ModernBERTic model. Model achieving the highest average score on the SuperGLUE benchmark and being the first modern architecture encoder for Serbian, Montenegrin, Bosnian, and Croatian languages! ModernBERTic the first modern encoder for Serbian, Montenegrin, Croatian and Bosnian The model was trained on up to 64 A100 GPUs on the Leonardo HPC provided to us by the EU grant at Recrewty . I have had a short weekly series on ModernBERTic ( ModernBERTić actually, as ić is a common way of naming a diminutive in our language ) training on LinkedIn since February, where you can get a bit more information on the timeline of progression and the hardware used. Why a new encoder pretrained from scratch There were several encoder models released for BCMS languages. However, all of them were either from old architecture (or before the transformer++ :) date) or just continuously pretrained multilingual models such as XLM-RoBERTa. We had a need for a context length way higher than 512 tokens and a native tokenizer to minimize waste. ModernBERTic model, being based on the ModernBERT architecture, with a tokenizer trained from scratch, was our best bet. Most people do not realize this, given the hype around decoders, but when you account for production-ready use cases and just check which model is the most downloaded one in the last 30 days, guess what you will find? An encoder model with 220M downloads . Data Building a pretraining dataset for a language family with ~20M speakers is a different game than English. There is no single massive crawl you can just download and filter. You assemble it. In total, I have ingested 22 BCMS sources and ended up with around 60B tokens across 227M documents, the largest curated pretraining corpus for BCMS to date (as far as I know). The list spans the full quality spectrum: FineWiki and curated news on the high end, CLASSLA’s web text and bertic-macocu in the middle, then the big web crawls (FineWeb-2, HPLT 3.0, FinePDFs) at the bottom of the priority hierarchy. Each source comes with its own failure modes. The fun part of this stage was discovering what those failure modes actually look like for BCMS. A few examples worth sharing: Casino spam. The highest-quality bins of HPLT (bins 9 and 10, on a 1–10 quality scale) still contained large clusters of online gambling content targeted at the Balkans. Clean grammar, proper morphology, ranked high by the upstream classifier. The kind of text that passes English-trained quality filters with flying colors. Found ~166K documents with keyword patterns in both Latin and Cyrillic. Content farms. Foreign domains squatting on .sr and .bs subdomains, or /sr/ URL paths, serving auto-translated articles designed to rank in Google. Read 20 of them in a row, and the patterns become obvious - broken named entities, especially in Cyrillic transliterations of foreign names. ~25.5% of HPLT3 Serbian documents fell into this bucket. ~811K documents removed. OCR garbage in Cyrillic PDFs. FinePDFs has a Serbian Cyrillic split with systematic character substitutions (о ↔ п, и ↔ н, that kind of thing). I excluded the entire srp_Cyrl split and kept Latin-only PDFs, since transliteration on broken OCR just compounds the noise. The pipeline took shape in stages: multi-source ingestion tiered prioritization script normalization (Cyrillic → Latin via transliteration library) BCMS-specific quality filters (Gopher-derived heuristics plus our own stop-word ratio over 65 curated function words) cross-source MinHash LSH dedup (128 permutations, 0.8 Jaccard threshold, word 5-grams) tokenize with ModernBERTic tokenizer pack offline for faster training MDS shards on S3 The dedup step is where priority ordering matters. Higher-quality sources get indexed into the MinHash LSH structure first. When a duplicate pair is found across tiers, the higher-quality copy wins. Result: HPLT 3.0 (lowest priority) lost 38–67% of its documents as duplicates of content already in FineWeb-2, CLASSLA, or xlm_bertic. Meanwhile, xlm_bertic, after filtering, had only 0.04% removal- it was already unique. The priority pipeline did exactly what it should. After dedup, selective upsampling: FineWiki 2× (encyclopedic quality is scarce), Montenegrin 4× (smallest BCMS variant, boosted from 0.8% to 3% of the final mix). The whole pipeline writes MDS shards to S3 in around 7.5 hours on a 1.5TB RAM bare metal instance (some things, like the MinHash index, really did need that kind of RAM :D). Tokenizer The choice to train a dedicated BPE from scratch was driven by one number: fertility (tokens per word). On held-out Serbian text: ModernBERTić (BPE, 50,304, Latin, cased): 1.59 tokens/word BERTić (WordPiece, 32K): 1.66 XLM-R-BERTić (SentencePiece, 250K): 1.91 ModernBERT multilingual (BPE, 50K, but a different vocab): 2.57 A multilingual vocabulary spreads its budget across 100+ languages. For BCMS, most of those tokens are dead weight. In an 8192-token context window at 2.57 fertility, you fit ~3,190 words. At 1.59, you fit ~5,150. 62% more text per sequence, same architecture. Four decisions, in order of impact: Algorithm: BPE. Literature on morphologically rich languages suggests Unigram (SentencePiece) should win, it optimizes globally over the vocabulary rather than greedy pair merging. I tested both on subsets of 10–100M tokens. BPE: 1.59. Unigram: 1.63. Within 3% of each other. BPE trains on the full corpus without the memory issues that Unigram’s EM loop runs into at scale, so the engineering tradeoff favored BPE. On a corpus this size, the algorithmic advantage of Unigram seems to collapse. Vocab size: 50,304. Nearest multiple of 64 above 50K. GPU tensor cores operate on tiles of 8/16/64, so aligning the embedding matrix avoids wasted compute on every forward pass. Karpathy has a tweet on nanoGPT showing a 25% speedup from this exact tweak (referenced below). Across 4500 Leonardo node-hours, those things compound. Script: Latin only. Serbian uses both Cyrillic and Latin in active use. Training the tokenizer on both splits the vocabulary — half your BPE merges go to Cyrillic subwords, half to Latin, and you end up mediocre at both. We transliterate everything to Latin upfront, before tokenization, on every source. Our production use cases see <1% Cyrillic input, so the loss is minimal. Casing: cased. This one surprised me. Cased: 1.59. Uncased: 1.85. A 14% gap, because lowercasing destroys merge patterns where proper nouns and sentence-initial capitals carry a real subword signal. Architecture and the training setup The recipe is a BCMS adaptation of the ModernBERT-large configuration: 28 layers, 1024 hidden dim, 16 attention heads, 395M parameters Alternating attention: 256-token sliding window with full (global) attention every second layer RoPE position embeddings with base 160K, native 8192-token context FlashAttention 2, unpadding, GLU MLPs, prenorm 30% MLM masking (vs the standard 15%, gives ~2× signal per batch) Peak LR 5e-4 with warmup-stable-decay schedule, decay phase at ~9% of total tokens Global batch size 4096 sequences, kept constant across GPU counts (strong scaling) Mixed precision bf16 The training stack is built around MosaicML Composer + the FlexBERT codebase that ModernBERT ships with. Composer handles process spawning via torchrun, gradient sync via NCCL, learning rate scheduling in tokens (not steps), checkpointing keyed on ${SLURM_JOB_ID}, and mixed precision. MDS streaming handles deterministic shuffling and instant auto-resume across the 24-hour job limit on Leonardo. Charts for loss and eval metrics and throughput on weights and biases That MFU number is the one I am happiest with. It is computed as (6 × 395M × 59,584 tokens/s/device) / 312 TFLOPs/s using the standard FLOPs-per-token approximation. Well-tuned encoder runs on A100s usually land in the 35-50% range; 45% on a 28-layer ModernBERTic with alternating sliding-window attention is exactly where a competent setup should sit. The two changes that moved this number the most: Offline sequence prepacking. The first runs were doing variable-length-to-fixed-length packing online during training. CPU bottleneck, GPUs starving for data, throughput stuck at ~144K tokens/sec aggregate. Moving the packing offline (a 6-hour preprocessing job consuming 200GB of RAM) and streaming pre-packed batches via MosaicML’s MDS format pushed throughput up by ~13×. Cross-document attention masking via cu_seqlens. Sequence packing is throughput-positive but correctness-negative if you do not threadthe sequence_id boundaries through to FlashAttention's cu_seqlens. Without it, every packed sequence is treated as one continuous document, and tokens from doc A attend to tokens from doc B. Silent corruption, no error, all previous runs affected. Fixing this bumped effective packing utilization from ~10% to 95%+. Worth its own post. Standard caveats apply to the MFU number. The 6 × N × D approximation slightly overstates FLOPs for the alternating sliding-window pattern (you do not pay full quadratic cost on the windowed layers), so the true compute utilization is a couple of points higher. Reporting the conservative number. A few notes on the 64-GPU run. SLURM allocates 16 nodes, 4 GPUs each. The thing to watch for is NCCL falling back to TCP instead of using InfiniBand; it does not error, it just runs an order of magnitude slower. The kind of bug that shows up as “mysteriously low throughput” on the WandB dashboard, not as a stack trace. Set NCCL_IB_DISABLE=0 and NCCL_DEBUG=INFOThen, verify the IB transport is selected in the first few log lines of the run. The full ~60B token training run on the large model took roughly 7 hours on 64 A100s for the large version. Evaluation and results BalkanBench v1.0 evaluates BCMS encoders on the SuperGLUE -SR suite: BoolQ, CB, COPA, RTE, MultiRC, and WSC. Every cell on the leaderboard is a mean across 5 random seeds with reported standard deviation. ModernBERTić-large versus the strongest publicly available encoders for BCMS languages: Serbian SuperGLUE results from balkanbench.com ModernBERTić-large takes the top spot at 73.44 average, +1.98 over BERTić (71.46), winning 4 of 6 tasks outright. The full leaderboard with all 9 evaluated models is live at balkanbench.com . The single most interesting result in this table is COPA. ModernBERTić-large hits 76.84 vs BERTić’s 68.87- a +7.97 point gain . COPA is causal reasoning over premise-alternative pairs. The pairs frequently span 150+ tokens, which is exactly the regime where 8K-context modeling and global attention every second layer should dominate over 512-token full-attention BERT. They do. This is the architecture bet paying off in the cleanest possible way. A few honest observations the leaderboard makes you confront: The base model loses to BERTić. ModernBERTić-base at 149M lands 1.73 points below BERTić-110M. This is the ELECTRA signal-density gap I have been writing about. BERTić’s discriminator gives a training signal on 100% of tokens; MLM at 30% masking gives a signal on 30%. At a smaller capacity, that supervision deficit is not absorbed by the architecture. By 395M it is. The cleaner statement of the result: ModernBERTić wins decisively at scale, but matching BERTić at the base scale required techniques (denser supervision, longer training) that are not in the standard ModernBERT recipe. Workshop paper material, maybe :) Variance is a story, too. ModernBERTić-large’s worst standard deviation on any task is ±3.82 on CB. The lower variance is partly due to more parameters absorbing seed noise, but it is also cleaner training and fewer corrupted gradients. This was the case after the cooldown phase and switching to 15% masking ratio and later context extension. Inference throughput. On identical hardware, 1454 samples/sec vs BERTić’s 408 . 3.5× faster , thanks to FlashAttention 2 and unpadding . For our production use case at Recrewty , processing thousands of CVs daily, this compounds fast. What is coming next You can freely try out and interact with the base model through the links in the bottom section. As of now, we are wrapping up search models built for Serbian, Montenegrin, Croatian, and Bosnian, as well as specific domain adaptations. ModernBERTic model will power new features in our Recrewty platform: Assessment recommender - based on the job description by the hiring manager, the model will recommend the necessary assessments for evaluation. Roster management - a system that will, based on the criteria and description of a new hiring selection, predict the highest fit candidates for a new position from all of the previous hiring selections. Proprietary embedding and reranker models will be offered to our partners and clients. If you have use cases that this could be a great fit, let’s chat about it. Can’t wait to share all of this with you during May, as we will organize live events in Serbia and Montenegro. Stay tuned! :) Contact us at: benchmark@recrewty.com; hello@recrewty.com; mitar@recrewty.com For more details. References Model card of the model on HuggingFace: https://huggingface.co/permitt/galton-modernbertic-large Demo space to try out filling a mask: https://huggingface.co/spaces/permitt/modernbertic-demo LinkedIn build-in-public series: https://www.linkedin.com/in/perovicmitar/ All links are in one place: https://permitt.io Training the first modern architecture encoder for South Slavic languages was originally published in GoPenAI on Medium, where people are continuing the conversation by highlighting and responding to this story.