ایک ڈائریکٹری لُک اَپ۔
ایک متصل اسکین۔
فلٹرڈ ویکٹر سرچ عموماً ایسے انڈیکس پر scatter-gather ہوتی ہے جو آپ کے فلٹر سے بے خبر ہو۔ Telys اس کے بجائے طبعی ترتیب کا مالک ہے: پارٹیشن کی پر، nearest-neighbours-where-key-equals-x ایک O(1) ڈائریکٹری لُک اَپ اور ایک متصل بلاک کا ترتیب وار اسکین ہے۔ یہ صفحہ آج فراہم رن ٹائم کی سیر کراتا ہے، پھر اس آرکیٹیکچر کی جس کی طرف یہ بڑھ رہا ہے — spec کے طور پر لیبل شدہ۔
انجن ہر ویکٹر کے مقام کا مالک ہے۔
ایک collection تخلیق کے وقت partition_by اعلان کرتا ہے، اور ترتیب کی کو فالو کرتی ہے۔ بیس سیگمنٹ پارٹیشن کے مطابق clustered ہے — ہر کی ایک متصل سلائس سے ملتی ہے — اور حالیہ writes اس کے ساتھ ایک قابلِ تبدیل، Arrow-shaped ڈیلٹا میں موجود ہیں۔
پارٹیشن-clustered
ویکٹرز پارٹیشن کی کے مطابق ترتیب سے ذخیرہ ہیں، تاکہ ہر پارٹیشن ایک متصل بلاک ہو۔ ایک scoped query میموری کا ایک ترتیب وار رن پڑھتی ہے، نہ کہ انڈیکس میں بکھری قطاریں۔
O(1) key → slice
ایک ڈائریکٹری ہر پارٹیشن ویلیو کو بیس سیگمنٹ میں اس کے (offset, length) سے ملاتی ہے۔ فلٹر حل کرنا ایک dictionary lookup ہے، انڈیکس traversal نہیں۔
Arrow نما تحریریں
add اور upsert یہاں append کرتے ہیں، ہر قطار ایک monotonic write LSN سے مہر زد۔ ڈیلٹا فوری طور پر قابلِ query ہے اور ایک اسکین راستے سے بیس سلائس کے ساتھ یکجا ہوتا ہے۔
ایک scoped query کیا عمل کرتی ہے۔
col.search(qvec, where={"tenant_id": "acme"}, top_k=10)
فلٹر اس پارٹیشن کی کا نام لیتا ہے جس کے ساتھ collection بنائی گئی تھی۔
O(1) لُک اَپ: پارٹیشن ویلیو بیس سیگمنٹ میں (offset, length) سے حل ہوتی ہے۔ کوئی candidate generation نہیں، کوئی graph entry point نہیں۔
ایک ترتیب وار بلاک پر SIMD exact scoring۔ اس راستے پر Recall 1.0 ہے — یہ اسکین ہے، تخمینہ نہیں۔ اس مرحلے کے ماپے گئے p50/p95 benchmarks صفحے پر شائع ہیں، ہر عدد اپنے recall gate اور rig کے ساتھ۔
ایک ہی کلید کی rows کو Arrow-shaped delta میں اسی path سے score کیا جاتا ہے۔ ایک write اگلی query کو فوری طور پر نظر آتی ہے۔
snapshot LSN پر hits فلٹر ہوتے ہیں: tombstoned اور superseded versions کبھی سامنے نہیں آتے۔ Top-k نتائج explain payload کے ساتھ واپس آتے ہیں۔
بڑے partitions ایک واضح fork اختیار کرتے ہیں: build_ivf ہر اس partition پر per-partition IVF لگاتا ہے جو row threshold سے اوپر ہو، اور queries اس سے exact rerank کے ساتھ گزرتی ہیں — recall floor کے مطابق کیلیبریٹ شدہ، اور plan میں نامزد۔
ہر نتیجہ اپنا plan بتاتا ہے۔
explain=True وہ physical plan واپس کرتا ہے جو query نے اصل میں اختیار کیا۔ partition key پر آپ کو contiguous-slice scan ملتا ہے۔ بڑے partitions IVF fork ظاہر کرتے ہیں۔ off-key filters scatter-gather پر fall back کرتے ہیں — اور payload بتاتا ہے کیوں۔
hits = col.search(qvec, where={"tenant_id": "acme"}, top_k=10, explain=True)
hits["explain"]["plan"]
# on the partition key → "PartitionSliceExactF32" # one contiguous slice, exact, recall 1.0
# oversized partition → "PartitionIVFRerankF32" # per-partition IVF + exact rerank
# off-key filter → "ScatterGatherExact" # fallback — and it says why:
hits["explain"]["fallback_reason"]
# "path is not the physical partition key"کچھ overwrite نہیں ہوتا۔ Versions superseded ہوتے ہیں۔
write model append-only MVCC ہے۔ upsert ایک logical id کا نیا version لکھتا ہے اور پچھلے کو superseded قرار دیتا ہے؛ delete ایک delete LSN پر tombstone رکھتا ہے؛ snapshot() ایک consistent read view pin کرتا ہے؛ compact() delta کو base میں ضم کرتا ہے اور جو کوئی snapshot نہیں دیکھ سکتا اسے حذف کر دیتا ہے۔
col.upsert(vectors, ids=ids, metadata=metadata) # a new version; the prior one is superseded col.delete(["doc-41"]) # tombstone at a delete LSN — no in-place erase lsn = col.snapshot() # pin a consistent read view at an LSN col.compact() # fold delta into base; drop superseded rows col.build_ivf(min_rows=20000, target_recall=0.98)
| Call | کیا کرتا ہے |
|---|---|
| add / add_texts | نئی rows داخل کریں۔ Duplicate ids مسترد ہوتے ہیں — ایک logical id کے لیے دوسری physical row کے لیے جان بوجھ کر upsert درکار ہے۔ |
| upsert / upsert_texts | ایک logical id کا نیا version لکھیں؛ پچھلا version superseded ہو جاتا ہے، کبھی in place overwrite نہیں ہوتا۔ |
| search / search_text | Filtered top-k۔ explain=True physical plan کو نتیجے کے ساتھ منسلک کرتا ہے۔ |
| delete | ایک delete LSN پر logical rows کو tombstone کریں۔ |
| compact | delta کو base segment میں ضم کریں؛ tombstoned اور superseded versions حذف کریں۔ |
| build_ivf | row threshold سے اوپر کے partitions پر per-partition IVF بنائیں، recall floor کے مطابق کیلیبریٹ شدہ۔ |
| snapshot | ایک LSN واپس کریں جو consistent read view pin کرے۔ |
| save / stats | collection کو disk پر محفوظ کریں؛ row counts، partitions، اور layout کی تفصیلات رپورٹ کریں۔ |
نیچے سب کچھ specification ہے، shipped API reference نہیں۔ یہ وہ substrate ہے جس پر runtime converge کر رہا ہے۔ SDK-facing seam منجمد ہے، اس لیے نیچے کی تبدیلی callers کو نظر نہیں آتی۔
ایک planner۔ ایک flat IR۔ ایک executor۔
تین front ends ایک planner میں lower ہوتے ہیں، جو ایک flat physical intermediate representation emit کرتا ہے، جسے ایک Mojo vectorized executor براہ راست Arrow buffers پر execute کرتا ہے۔
memory model (remember · recall · as_of)، query API (point_get · scan · search · hybrid_search)، اور fabric۔ ایک entry contract؛ کوئی per-API engine نہیں۔
logical اور physical planning ایک جگہ۔ Selectivity کا تخمینہ segment statistics سے لگایا جاتا ہے؛ plan واضح ہے اور نتیجے کے ساتھ واپس آتا ہے۔
integer slots سے bound operators کی ایک flat array۔ inter-operator register ایک row set ہے — bitmap، sorted row-ids، یا selection vector۔
Arrow buffers اور FAISS candidate arrays پر vectorized execution۔ SIMD hot path Python سے باہر رہتا ہے؛ compressed Parquet pages پہلے scratch buffers میں decode ہوتے ہیں۔
mutation layer
durability اور ordering کے لیے write-ahead log، اور فوری visibility کے لیے mutable Arrow-shaped delta — وہ table layer جو Parquet اکیلے فراہم نہیں کرتا۔
Sealed، immutable
پائیدار compressed columnar segments۔ Footer statistics سے segment اور row-group pruning ہوتی ہے؛ sealed files کبھی mutate نہیں ہوتیں۔
FAISS ANN
Per-segment FAISS indexes، segment کے checksum اور version سے bound، read-only mapped، lifetime read snapshot سے منسلک۔
Pruning اور lexical
pruning کے لیے zone maps، bloom filters، اور bitmaps؛ sparse retrieval اور score fusion کے لیے BM25 sidecar۔
SCAN FILTER PROJECT POINT_GET RANGE_GET AGGREGATE TOP_K HASH_JOIN HASH_GROUP_BY SORT ANN_SEARCH SPARSE_SEARCH FUSE RERANK MATERIALIZE
پہلے WAL۔ فوری visibility۔ پس منظر میں seal۔
checksums اور monotonic LSNs کے ساتھ append-only frames۔ Recovery آخری sealed LSN کے بعد records replay کرتی ہے اور پہلے bad checksum پر truncate کرتی ہے۔
write mutable delta میں آتی ہے اور فوری قابل query ہو جاتی ہے — sealed segments اور delta ایک scan path سے union ہوتے ہیں۔
سائز، قطار، یا عمر کی حد پار ہوتے ہی، delta کو ترتیب دے کر اپنے .vidx اور sidecars کے ساتھ ایک Parquet segment کے طور پر لکھا جاتا ہے، پھر ایک atomic manifest swap کے ذریعے شائع کیا جاتا ہے۔
پس منظر میں merges چھوٹے segments کو یکجا کرتے، tombstoned قطاریں حذف کرتے، اور sidecars دوبارہ تعمیر کرتے ہیں — budget-controlled، تاکہ on-device تعیناتیاں خاموش رہیں۔
Sealed segments کبھی تبدیل نہیں ہوتے۔ ایک read، manifest snapshot اور LSN کو pin کرتی ہے؛ writers نئے segments seal کر کے manifest swap کرتے ہیں — زیرِ عمل readers متاثر نہیں ہوتے۔ Garbage collection سب سے پرانے live snapshot کا انتظار کرتا ہے۔
فلٹر منصوبہ چنتا ہے، نہ کہ اس کے برعکس۔
Filtered ANN دراصل selectivity پر مبنی adaptive planning ہے: planner، segment statistics سے اندازہ لگاتا ہے کہ فلٹر کتنی قطاریں گزرنے دیتا ہے، پھر سب سے سستی حکمتِ عملی چنتا ہے جو recall contract برقرار رکھے۔
پریفلٹر → عین مطابق
پہلے scalar یا bitmap prefilter، پھر بچ جانے والوں پر exact SIMD scoring۔ قطاروں کی حد سے نیچے ANN بالکل چھوڑ دیا جاتا ہے — exact scan، recall 1.0۔
Allow-bitmap ٹراورسل
ANN traversal ایک allow-bitmap ساتھ لے کر چلتی ہے، اس لیے index صرف وہی قطاریں سامنے لاتا ہے جنہیں فلٹر قبول کرتا ہے۔
ANN → پوسٹفلٹر
پہلے adaptive over-fetch کے ساتھ ANN، پھر post-filter۔ فلٹر بہت کم ہٹاتا ہے، اس لیے candidate generation آگے رہتی ہے۔
درستگی کے معیار رفتار کے کسی بھی عدد سے پہلے آتے ہیں۔
بھیجا گیا runtime دونوں engine implementations کے خلاف چلائے گئے parity suites سے تصدیق شدہ ہے، اور ہر query اپنا physical plan بتا سکتی ہے۔ یہاں ترتیبِ کار یہی ہے: پہلے درستگی کے معیار، پھر پیمائش۔
Benchmarks ایک fairness contract کے تحت شائع ہوتے ہیں — matched recall، matched hardware، transport-separated نتائج، win / tie / lose رپورٹ کیے جاتے ہیں۔ پہلے ماپے گئے نتائج اب benchmarks صفحے پر موجود ہیں، ہر عدد اپنی مکمل شرائط کے ساتھ: ہارڈویئر، ڈیٹاسیٹ، dimension، selectivity، recall، اور ٹرانسپورٹ۔ ہر multiplier اپنی مذکور شرائط سے باہر ایک hypothesis ہے۔