- Bina 0.1 Koochik Core ML — Six Aspect Buckets
- What is in this release
- Exact six-bucket contract
- Precision and cache contract
- Important compatibility boundary: six canvases vs current Flax production
- Qualified and unqualified image paths
- Swift usage
- Validation methodology
- Integrity and provenance
- Repository layout
- محدودیتها و خلاصهٔ فارسی
- License
- What is in this release
Bina 0.1 Koochik Core ML — Six Aspect Buckets
This repository is the bounded-shape Core ML release of
Reza2kn/Bina-0.1-Koochik,
the merged BF16 Persian OCR baseline. It provides six fixed image geometries,
five language-prefill lengths, one shared 4,096-token decode step, and a native
Swift runtime for macOS 15+ and iOS 18+.
This is a mixed-precision Core ML derivative of a BF16 source checkpoint. It is not a claim that Core ML executes the model in BF16.
What is in this release
The runtime is distributed as two Core ML multifunction packages:
bina_vision_six_bucket_fp32.mlpackagecontains six fixed-shape vision functions, one for each canvas.bina_language_six_bucket_mixed_fp16_fp32_cache4096.mlpackagecontains five unique prefill functions plus the shareddecode_cache4096function. Theseq288,seq416, andseq672prefills use FP16; the numerically sensitiveseq736,seq928, and shared decode functions use FP32. The landscape1024x512and portrait512x1024lanes intentionally shareprefill_seq672while retaining different vision functions and bucket-local host constants.
The packages are assembled with Core ML Tools' multifunction descriptor. Common weights are deduplicated inside each package rather than shipping a complete copy of the model for every fixed shape. The runtime always selects a function by name; it does not rely on the package defaults.
Exact six-bucket contract
Let r = source_width / source_height. Threshold comparisons are inclusive on
the wider lane. Selection happens from the original positive image dimensions,
before resize and padding.
| Public bucket | Aspect-ratio lane | RGB canvas | grid_thw |
pixel_values FP32 |
Image tokens | Prompt tokens | M-RoPE delta | First decode position | Core ML route |
|---|---|---|---|---|---|---|---|---|---|
1024x128 |
r >= 5.0 |
1024 × 128 |
[1, 8, 64] |
[512, 1536] |
128 | 288 | -96 | 192 | vision_1024x128 + prefill_seq288 |
1024x256 |
2.5 <= r < 5.0 |
1024 × 256 |
[1, 16, 64] |
[1024, 1536] |
256 | 416 | -224 | 192 | vision_1024x256 + prefill_seq416 |
1024x512 |
1.3 <= r < 2.5 |
1024 × 512 |
[1, 32, 64] |
[2048, 1536] |
512 | 672 | -480 | 192 | vision_1024x512 + prefill_seq672 |
768x768 |
0.77 <= r < 1.3 |
768 × 768 |
[1, 48, 48] |
[2304, 1536] |
576 | 736 | -552 | 184 | vision_768x768 + prefill_seq736 |
768x1024 |
0.5 <= r < 0.77 |
768 × 1024 |
[1, 64, 48] |
[3072, 1536] |
768 | 928 | -736 | 192 | vision_768x1024 + prefill_seq928 |
512x1024 |
0 < r < 0.5 |
512 × 1024 |
[1, 64, 32] |
[2048, 1536] |
512 | 672 | -480 | 192 | vision_512x1024 + prefill_seq672 |
The exact canvas operation is:
- convert the source to PIL RGB;
- select the lane from the source aspect ratio;
- scale by
min(canvas_width/source_width, canvas_height/source_height); - round each resized dimension, resize with PIL LANCZOS, and center it on a white canvas;
- run the checked-in Qwen processor and the fixed OCR prompt.
The authoritative machine-readable copy is bucket_contract.json.
Precision and cache contract
| Component | Runtime precision |
|---|---|
| Source checkpoint and BF16 reference execution | BF16 |
| Vision functions | Core ML FP32 |
| Language prefill functions | Core ML FP16 for seq288/seq416/seq672; FP32 for seq736/seq928 |
| Autoregressive decode function | Core ML FP32 |
| Host storage | FP32; BF16 RNE only for 768x768/768x1024, otherwise preserved FP32 |
Core ML does not expose BF16 tensors for this deployment target. The runtime
therefore declares an explicit policy per bucket. 1024x128, 1024x256,
1024x512, and 512x1024 preserve FP32 language-boundary values. Only the two
FP32-prefill routes, 768x768 and 768x1024, apply bit-exact BF16
round-to-nearest-even and expand back to FP32. On those two routes this covers
prompt embeddings and M-RoPE inputs, prefill cache/state outputs, decode
embedding and M-RoPE inputs, and every recurrent/cache update before reuse.
Logits and the FP32 attention-mask sentinel are never rounded. The runtime
catalog and Swift implementation enforce this per-bucket contract.
The decode package uses fixed full-attention KV tensors with a length of 4,096.
The shared decode RoPE tables are absolute-position tables with shape
[1, 4096, 64]. For every generated step, the host selects:
absolute_rope_row = cache_length + bucket_mrope_position_delta
The native runtime checks that both the cache index and absolute RoPE row remain
inside 0..<4096. Full-attention KV insertion, Gated DeltaNet convolution
state, and recurrent state updates happen on the host between calls to the
stateless decode function.
Core ML multifunction models require specification version 9 here, so the declared deployment floor is:
- macOS 15.0 or newer;
- iOS 18.0 or newer;
- Swift tools 6.0 for the included package.
Important compatibility boundary: six canvases vs current Flax production
This repository preserves the historical six-canvas compatibility contract
from the public Flax work at revision
1782084d4bc468464faaefa0ad27f0e99bb17f6c. It provides a bounded set of shapes
that can be compiled and selected predictably on Apple devices.
The current
Reza2kn/Bina-0.1-Flax-BF16
production path instead preserves each crop's natural processor geometry for
source parity and groups batches by exact prepared shape. A previously unseen
natural shape can therefore trigger a new XLA compilation in that runtime.
These contracts are related but not interchangeable:
- This Core ML release resizes and pads a raw image to one of six canvases.
- Current Flax production keeps the natural prepared geometry.
- The resulting pixels, patch grid, prompt length, M-RoPE delta, and transcript can differ for the same raw image.
- Core ML parity must therefore be evaluated against the pinned BF16 source on the same six-bucket PIL canvas. It must not be reported as arbitrary-image parity with the current natural-geometry Flax service.
The included compare_bucketed_bf16_to_natural.py keeps this geometry comparison
separate from the Core ML conversion-parity gate.
Qualified and unqualified image paths
Parity-qualified path
SuryaCoreMLRuntime.generate(pixelValues:bucketID:maxNewTokens:) is the strict
entry point. It requires:
- an externally selected canonical bucket ID;
- a Float32 tensor with that bucket's exact shape;
- pixels prepared by the PIL RGB + LANCZOS + checked-in processor contract.
The runtime rejects a mismatched bucket, shape, or dtype before model execution. For an exact local tensor, run this from the repository root:
PYTHONPATH=scripts python - input.png prepared.pixel_values_fp32.bin <<'PY'
import sys
from pathlib import Path
import numpy as np
from PIL import Image
from transformers import AutoProcessor
from bina_bucket_contract import bucket_canvas, processor_sample, validate_sample
source_path = Path(sys.argv[1])
output_path = Path(sys.argv[2])
processor = AutoProcessor.from_pretrained("processor", trust_remote_code=True)
with Image.open(source_path) as opened:
canvas, bucket = bucket_canvas(opened)
sample = processor_sample(processor, canvas)
validate_sample(bucket, sample)
pixels = sample["pixel_values"].detach().cpu().numpy().astype(np.dtype("<f4"), copy=False)
output_path.write_bytes(pixels.tobytes(order="C"))
print(bucket.id)
PY
Use the printed bucket ID with the Swift command below. The bucket is mandatory; the raw tensor shape alone is not accepted as routing authority.
Explicitly unqualified convenience path
prepareImageUnqualified(_:bucketID:) and the smoke executable's --image
option use CoreGraphics resizing and patchification. CoreGraphics interpolation
is not byte-identical to PIL LANCZOS. These methods are useful integration
helpers, but no BF16 transcription-parity claim is attached to their output.
Swift usage
Clone with Git LFS, then build the included package:
git lfs install
git lfs pull
swift build -c release --package-path native/SuryaCoreMLRuntime
One strict bucket run
For single-input mode, --bucket is mandatory. This example uses the catalog's
qualified synthetic tensor for 1024x128:
cd native/SuryaCoreMLRuntime
swift run -c release surya-coreml-smoke \
--model-dir ../.. \
--bucket 1024x128 \
--pixel-values-fp32 ../../native_assets/buckets/1024x128/canary_pixel_values_fp32.bin \
--max-tokens 128
To exercise the unqualified CoreGraphics convenience path explicitly:
cd native/SuryaCoreMLRuntime
swift run -c release surya-coreml-smoke \
--model-dir ../.. \
--bucket 768x1024 \
--image /absolute/path/to/image.png \
--max-tokens 128
All canonical canaries and the route-collision check
cd native/SuryaCoreMLRuntime
swift run -c release surya-coreml-smoke \
--model-dir ../.. \
--all-canaries \
--max-tokens 128
--all-canaries runs the six canonical buckets in threshold order and then the
intentional 1024x512 -> 512x1024 -> 1024x512 route-collision sequence. That
sequence checks that the shared prefill_seq672 function cannot accidentally
reuse the previous bucket's vision function or host constants.
Validation methodology
The release qualification is designed to fail closed:
- Load the exact source checkpoint revision on CPU with BF16 parameters and eager attention.
- Use deterministic greedy decoding (
do_sample=False), EOS token2, and the exact prompt below. - Prepare each BF16 and Core ML comparison from the same PIL six-bucket canvas.
- Select every Core ML multifunction function explicitly by name.
- Compare generated token IDs, decoded text, stop reason, and terminal EOS.
- Exercise all six synthetic lanes, real Persian fixtures for all six lanes, the native Swift host, and the seq-672 route collision.
- Run the independent static gate over every native asset and both final packages: relative paths, byte sizes, SHA-256 values, shapes, dtypes, source provenance, cache formulas, Core ML spec version, defaults, and complete function I/O signatures.
The exact transcription prompt is:
OCR this image. Return only the exact text visible in the image, preserving Persian, numbers, line breaks, and punctuation. Do not explain.
Parity results
| Release gate | Result |
|---|---|
| BF16 source vs Python-hosted Core ML | PASS — 12/12 token-exact, 12/12 transcript-exact, all EOS |
| Native Swift six-bucket runtime | PASS — 9/9 exact, all EOS, including 1024x512 -> 512x1024 -> 1024x512 |
| Static package, asset, signature, and provenance integrity | PASS |
Machine-readable evidence is stored under validation/. Token-capped long-page
checks, if present, are prefix evidence and are labeled separately; they are not
silently presented as EOS-complete transcript parity.
Integrity and provenance
Source identity:
- model:
Reza2kn/Bina-0.1-Koochik; - revision:
9b5812be94e3e015142da22a4b61b34aad5d2c02; - architecture:
Qwen3_5ForConditionalGeneration; - source parameter dtype: BF16;
model.safetensorsSHA-256:2193be4ef3d2366438121a15b7a1dea2bb85b24f83145e5a39bfa1f387891ada;config.jsonSHA-256:e0de22be177070f206106c184d062176fcda591d9114068c42489ffc550488de.
Integrity surfaces:
bucket_contract.jsonpins all six geometries and verified M-RoPE deltas.native_assets/runtime_catalog.jsonmaps every public bucket to its exact vision/prefill functions and records shared-file and bucket-constants descriptors. Each bucket's constants file records its remaining assets. Every referenced file has a byte size and SHA-256; raw tensor descriptors additionally carry an exact shape and dtype.multifunction_packages.jsonrecords each package's deterministic tree hash, per-file hashes, Core ML specification version, default function, and complete per-function I/O inventory.scripts/validate_bina_native_assets.pyindependently requires the canonical six buckets and validates the catalog, constants, native-asset tree, both multifunction packages, and assembly report.scripts/validate_bina_swift_six_bucket_runtime.pybinds its parity receipt to the executable, expected BF16/Core ML receipt, runtime catalog, complete native-assets tree, and both final Core ML package trees.
Run the static integrity gate from the repository root:
python scripts/validate_bina_native_assets.py \
--artifact-dir . \
--output validation/static-artifact-validation.json
Repository layout
bina_vision_six_bucket_fp32.mlpackage— six FP32 vision functions.bina_language_six_bucket_mixed_fp16_fp32_cache4096.mlpackage— five prefills (three FP16 and two FP32) plus one FP32 decode function.native_assets/— shared FP32 embedding and absolute RoPE tables plus per-bucket prompt assets, constants, and qualified canary tensors.native/SuryaCoreMLRuntime/— Swift library, tests, and smoke executable.processor/— pinned tokenizer, chat template, and image-processor settings.requirements-conversion.txt— exact Python conversion and validation environment.scripts/— export, materialization, preprocessing, comparison, and fail-closed validators.validation/— machine-readable parity and integrity receipts.
Internal Surya names reflect the upstream architecture. The graph weights are
the Bina 0.1 Koochik fine-tuned weights pinned above.
محدودیتها و خلاصهٔ فارسی
این مخزن نسخهٔ Core ML مدل «بینا ۰.۱ کوچک» برای OCR فارسی است. مدل مبدأ با
پارامترهای BF16 منتشر شده، اما خود Core ML در این خروجی محاسبات BF16 انجام
نمیدهد. برج بینایی با FP32 اجرا میشود. توابع prefill با طولهای ۲۸۸، ۴۱۶ و
۶۷۲ از FP16 و توابع ۷۳۶ و ۹۲۸ بههمراه decode مشترک از FP32 استفاده میکنند.
دادهها در میزبان بهصورت FP32 نگهداری میشوند. مسیرهای 1024x128،
1024x256، 1024x512 و 512x1024 مقادیر مرز زبانی FP32 را بدون گردکردن حفظ
میکنند. فقط دو مسیر 768x768 و 768x1024 گردکردن دقیق BF16 با روش
round-to-nearest-even را انجام میدهند و نتیجه را دوباره در FP32 نگه میدارند؛
در این دو مسیر، این قرارداد ورودیهای prompt و M-RoPE و همچنین state و cache
بازخورانیشده را شامل میشود. بنابراین این خروجی یک مشتق Core ML با مبدأ BF16،
دقت ترکیبی و سیاست مرزی وابسته به باکت است، نه یک مدل Core ML کاملاً BF16.
قرارداد شش باکت
نسبت عرض به ارتفاع تصویر خام، پیش از تغییر اندازه، یکی از شش مسیر جدول بالا
را انتخاب میکند. مرزهای 5.0، 2.5، 1.3، 0.77 و 0.5 شامل باکت عریضتر
هستند. تصویر ابتدا RGB میشود، با PIL LANCZOS و بدون برش داخل بوم انتخابشده جا
میگیرد و در مرکز زمینهٔ سفید قرار میگیرد. شناسهٔ باکت بخشی از قرارداد ورودی
است؛ صرفاً برابر بودن شکل تنسور برای انتخاب مسیر کافی نیست.
دو باکت 1024x512 و 512x1024 هر دو طول prompt برابر ۶۷۲ دارند و تابع
prefill_seq672 را مشترک استفاده میکنند، ولی تابع vision و ثابتهای محلی آنها
متفاوت است. به همین دلیل runtime هنگام جابهجایی بین این دو مسیر، کل route را
فعال میکند و تنها نام prefill را ملاک قرار نمیدهد.
تفاوت مهم با runtime فعلی Flax
این نسخه قرارداد تاریخی شش بوم ثابت را از revision
1782084d4bc468464faaefa0ad27f0e99bb17f6c حفظ میکند. در مقابل، runtime تولیدی
فعلی Flax هندسهٔ طبیعی خروجی processor را نگه میدارد و نمونهها را بر اساس شکل
دقیق آمادهشده گروهبندی میکند. پس برای یک تصویر خام یکسان، پیکسلها، شبکهٔ
patch، طول prompt، delta مربوط به M-RoPE و حتی متن نهایی میتوانند میان مسیر
ششباکتی و مسیر طبیعی متفاوت باشند.
ادعای برابری این مخزن فقط زمانی معتبر است که مدل BF16 مبدأ و Core ML هر دو دقیقاً همان بوم ششباکتی ساختهشده با PIL را دریافت کنند. این مخزن نباید بهعنوان جایگزین کاملاً همسان برای سرویس Flax با هندسهٔ طبیعی و تصاویر خام دلخواه معرفی شود. مقایسهٔ «هندسهٔ طبیعی در برابر بوم ثابت» یک آزمون سازگاری جداگانه است و جای آزمون parity تبدیل Core ML را نمیگیرد.
مسیر ورودی تأییدشده و مسیر کمکی
مسیر تأییدشده، متد generate(pixelValues:bucketID:maxNewTokens:) با تنسور FP32
ساختهشده توسط PIL و processor همین مخزن است. runtime پیش از اجرای مدل، شناسهٔ
باکت، شکل و dtype را بررسی میکند. گزینهٔ --bucket در اجرای تکنمونهای Swift
اجباری است.
متد prepareImageUnqualified و گزینهٔ --image از CoreGraphics استفاده میکنند.
درونیابی CoreGraphics از نظر بایت با PIL LANCZOS یکسان نیست؛ بنابراین این مسیر
برای راحتی یکپارچهسازی ارائه شده و ادعای برابری transcript با BF16 ندارد.
حافظهٔ decode طول ثابت ۴۰۹۶ دارد. جدول M-RoPE مشترک، موقعیت مطلق را نگه میدارد
و سطر هر گام از جمع cache_length و delta باکت انتخاب میشود. runtime مرز cache
و جدول را بررسی میکند و در صورت خروج از محدوده متوقف میشود.
روش اعتبارسنجی
آزمون انتشار از decoding حریصانه و قطعی، توکن پایان 2، prompt ثابت، مدل BF16
با revision و hash مشخص، و انتخاب صریح نام توابع Core ML استفاده میکند. توکنها،
متن decodeشده، علت توقف و رسیدن به EOS مقایسه میشوند. علاوه بر شش canary،
نمونههای واقعی فارسی برای هر شش باکت، runtime بومی Swift و جابهجایی حساس بین
دو مسیر ۶۷۲ توکنی بررسی شدهاند. آزمون ایستای مستقل نیز hash، اندازه، شکل، dtype،
نسخهٔ spec و امضای ورودی/خروجی همهٔ توابع را کنترل میکند. نتیجهٔ نهایی ۱۲ از
۱۲ نمونهٔ Python و ۹ از ۹ مسیر Swift را با برابری دقیق توکن و متن و پایان EOS
تأیید میکند؛ آزمونهایی که به سقف توکن میرسند صرفاً مدرک prefix هستند، نه
parity کامل تا EOS.
License
This derivative follows the source Bina/Surya OCR 2 OpenRAIL license. Review the source and upstream license terms before use, redistribution, or deployment.
این مشتق از مجوز OpenRAIL مدل مبدأ بینا و Surya OCR 2 پیروی میکند. پیش از استفاده، بازتوزیع یا استقرار، متن مجوز مدل مبدأ و پروژهٔ بالادستی را بررسی کنید.
- Downloads last month
- 4