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.mlpackage contains six fixed-shape vision functions, one for each canvas.
  • bina_language_six_bucket_mixed_fp16_fp32_cache4096.mlpackage contains five unique prefill functions plus the shared decode_cache4096 function. The seq288, seq416, and seq672 prefills use FP16; the numerically sensitive seq736, seq928, and shared decode functions use FP32. The landscape 1024x512 and portrait 512x1024 lanes intentionally share prefill_seq672 while 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:

  1. convert the source to PIL RGB;
  2. select the lane from the source aspect ratio;
  3. scale by min(canvas_width/source_width, canvas_height/source_height);
  4. round each resized dimension, resize with PIL LANCZOS, and center it on a white canvas;
  5. 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:

  1. Load the exact source checkpoint revision on CPU with BF16 parameters and eager attention.
  2. Use deterministic greedy decoding (do_sample=False), EOS token 2, and the exact prompt below.
  3. Prepare each BF16 and Core ML comparison from the same PIL six-bucket canvas.
  4. Select every Core ML multifunction function explicitly by name.
  5. Compare generated token IDs, decoded text, stop reason, and terminal EOS.
  6. Exercise all six synthetic lanes, real Persian fixtures for all six lanes, the native Swift host, and the seq-672 route collision.
  7. 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.safetensors SHA-256: 2193be4ef3d2366438121a15b7a1dea2bb85b24f83145e5a39bfa1f387891ada;
  • config.json SHA-256: e0de22be177070f206106c184d062176fcda591d9114068c42489ffc550488de.

Integrity surfaces:

  • bucket_contract.json pins all six geometries and verified M-RoPE deltas.
  • native_assets/runtime_catalog.json maps 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.json records 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.py independently 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.py binds 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
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for Reza2kn/Bina-0.1-Koochik-CoreML-Six-Bucket

Quantized
(2)
this model