تصور کنید هزاران مخزن گیتهاب را ستاره زدهاید اما برای یافتن یک ابزار خاص، باید دقیقاً نام آن را به یاد بیاورید. حالا میتوانید بدون نیاز به اینترنت و با تایپ مفاهیم، دقیقترین نتایج را در کسری از ثانیه پیدا کنید.
جستوجو در میان هزاران ستاره گیتهاب معمولاً به تطبیق دقیق کلمات کلیدی یا تکیه بر نمایهسازیهای ابری وابسته است. EmbeddingGemma — مدل ۳۰۸ میلیون پارامتری گوگل — اکنون جایگزینی کاملاً آفلاین ارائه میدهد که بهجای کلمات، معنای پشت پرسوجو را میفهمد. این مدل یک بردار معنایی (Embedding) تولید میکند؛ چیزی شبیه به کارت معرفی عددی برای هر واژه که میگوید این کلمه «همسایهی» چه کلمات دیگری است. این رویکرد یادآور راهکارهای بهینهسازی هزینههای زیرساختی است که در بررسی بردارهای سرورلس در برابر LLM به آنها پرداختیم تا هزینههای عملیاتی به صفر برسد.
این رویکرد در زمانی ارائه میشود که توسعهدهندگان بهشدت به دنبال ابزارهای هوش مصنوعی «اول-محلی» (Local-first) برای حفظ حریم خصوصی و کاهش تأخیر هستند. همانطور که در تحلیلهای قبلی ما دربارهی امنیت مدلهای بازمتن اشاره کردیم، کاهش وابستگی به APIهای ابری یک روند صعودی است. در حالی که اکثر سامانههای جستوجوی معنایی به پایگاهدادههای برداری عظیم در ابر متکی هستند، این پیادهسازی ثابت میکند که یک مدل کوچک و کوانتیده روی CPU لپتاپ میتواند مجموعهدادههای شخصی را با دقت بالا مدیریت کند. این توازن میان کارایی و حریم خصوصی، مشابه همان منطقی است که در معماری x-algorithm برای تعادل میان سرعت و محرمانگی مورد بحث قرار گرفت.
معماری مدل
در هسته این سیستم، EmbeddingGemma قرار دارد که بر پایه معماری Gemma 3 ساخته شده و بهطور خاص برای دستگاههای لبه (Edge devices) مثل گوشیها و لپتاپها طراحی شده است. طبق مستندات گوگل، این مدل بردارهایی با ۷۶۸ بُعد تولید میکند، هرچند از یادگیری نمایش ماتروشکا (Matryoshka representation learning) پشتیبانی میکند تا در صورت محدودیت شدید حافظه، بتوان این ابعاد را به ۵۱۲، ۲۵۶ یا ۱۲۸ کاهش داد.
گوگل این مدل را بسیار سبک طراحی کرده است. به نقل از گزارشهای فنی، این مدل پس از کوانتیده کردن (Quantization) — که شبیه فشردهسازی یک عکس برای اشغال فضای کمتر بدون از دست دادن زیاد کیفیت است — به کمتر از ۲۰۰ مگابایت رم نیاز دارد. همچنین پنجرهٔ زمینه (Context Window) آن ۲۰۰۰ توکن است؛ یعنی مثل میز کاری که جا برای چند ورق دارد، نه کل کتابخانه. این ظرفیت برای تبدیل متادیتای یک مخزن و ابتدای فایل README کافی است. علاوه بر این، چون مدل از بیش از ۱۰۰ زبان پشتیبانی میکند، میتواند مستندات و پرسوجوهای غیرانگلیسی را نیز بهطور مؤثر مدیریت کند.
خط لوله اجرای محلی
برای اجرای آفلاین، سیستم از ONNX Runtime از طریق بسته onnxruntime-node استفاده میکند. این پیادهسازی برای جلوگیری از حجیم شدن فایل نهایی (Binary)، افزونههای بومی مخصوص هر سیستمعامل و وزنهای مدل را در یک فرآیند بوتاسترپ (Bootstrap) در اولین اجرا دانلود میکند.
کاربران بسته به سختافزار خود میتوانند سطوح مختلف کوانتیزاسیون و دقت را انتخاب کنند:
- q4: حدود ۱۹۷ مگابایت (پیشفرض و کوچکترین حجم).
- q8: حدود ۳۰۹ مگابایت (حالت متعادل).
- fp16: حدود ۶۱۸ مگابایت (کیفیت بالاتر).
- fp32: حدود ۱.۲ گیگابایت (دقت کامل).
تمام این نسخهها مستقیماً روی CPU اجرا میشوند. سیستم برای جلوگیری از مصرف تکراری حافظه در زمانهای همزمانِ نمایهسازی و جستوجو، تنها از یک نمونه مدل (Shared Instance) در هر فرآیند استفاده میکند.
منطق بردارسازی نامتقارن
یک جزئیات فنی حیاتی این است که EmbeddingGemma نامتقارن (Asymmetric) است. این یعنی بسته به اینکه مدل در حال پردازش یک سند برای ذخیرهسازی است یا یک پرسوجو برای جستوجو، به پرامپتهای متفاوتی نیاز دارد.
برای اسناد، سیستم از پیشوند title: none | text: [content] استفاده میکند. اما برای پرسوجوهای کاربر، پیشوند task: search result | query: [text] اعمال میشود. ترکیب یا جابجایی این دو حالت باعث کاهش محسوس دقت جستوجو میشود، به همین دلیل در این پیادهسازی، این دو عملیات بهصورت دو تابع مجزا یعنی embedDocument() و embedQuery() صادر شدهاند.
ذخیرهسازی برداری محلی با PGlite
بهجای استفاده از یک پایگاهداده برداری مستقل و سنگین، سیستم از PGlite استفاده میکند؛ یک دیتابیس Postgres جاسازیشده که مجهز به افزونه pgvector است. بردارهای ۷۶۸ بُعدی در یک ستون از نوع vector با بُعد ثابت ذخیره میشوند.
جستوجو با استفاده از فاصله کسینوسی (Cosine Distance) و اپراتور <=> در pgvector انجام میشود. برای لیستی از چند هزار ستاره شخصی، سیستم یک اسکن دقیق (Exact Scan) انجام میدهد و فاصله را برای تکتک ردیفها محاسبه میکند. این روش تضمین میکند که نزدیکترین همسایهها بدون خطاهای تخمینی (که در شاخصهای بزرگتر رایج است) بازگردانده شوند.
توسعهدهنده اشاره کرده است که اگر مجموعهداده بهطور قابلتوجهی رشد کند، میتوان از طریق یک مهاجرت (Migration) سفارشی، شاخص HNSW (Hierarchical Navigable Small World) را برای حفظ سرعت جستوجو اضافه کرد.
تجربه کاربری
در بخش رابط کاربری، جستوجو در TanStack Start ادغام شده است. برای جلوگیری از لگ زدن UI هنگام استنتاج (Inference) — که لحظهای است مدل واقعاً جواب تولید میکند — یک تأخیر ۶۰۰ میلیثانیهای (Debounce) روی جعبه جستوجو اعمال شده است.
وقتی کاربر عبارت «graph databases in Rust» را تایپ میکند، مراحل زیر در کمتر از یک ثانیه رخ میدهد:
۱. پرسوجو به یک مسیر (Route) در Elysia ارسال میشود.
۲. متن توسط مدل ONNX محلی به یک آرایه Float32Array(768) تبدیل میشود.
۳. PGlite بردارهای ذخیره شده را بر اساس فاصله کسینوسی رتبهبندی میکند.
۴. ۵۰ لینک برتر مخازن منطبق به رابط کاربری بازگردانده میشوند.
برای اینکه تجربه کاربری کاملاً «محلی» به نظر برسد، رابط کاربری بهجای نمایش یک اسپینر معمولی، عبارت «Embedding query...» را نمایش میدهد. همچنین از placeholderData استفاده شده تا نتایج قبلی تا زمان پردازش پرسوجوی جدید روی صفحه باقی بمانند و از پرش یا چشمکزدن صفحه جلوگیری شود.
تحلیل: تغییر رویکرد به سمت RAG محلی
این پیادهسازی نشاندهنده تغییری در نگاه توسعهدهندگان به تولید تقویتشده با بازیابی (RAG) است. با انتقال کل خط لوله — شامل بردارسازی، ذخیرهسازی و بازیابی — به ماشین کاربر، سیستم هزینههای API و نگرانیهای حریم خصوصی را بهطور کامل حذف میکند. این رویکرد در واقع تکاملی از روشهای دسترسی به داده است؛ همانطور که رویکرد Scry در دسترسی برنامهریزیشده به وب سعی داشت جایگزینی برای اسکرپینگهای کند باشد، این سیستم نیز بازیابی محلی را جایگزین جستوجوهای ابری میکند.
برای کاربر نهایی، این بدان معناست که دادههای گیتهاب او هرگز دستگاهش را ترک نمیکند. همچنین معیار عملکرد از «تأخیر شبکه» به «سرعت استنتاج CPU» تغییر میکند. از آنجایی که مدل تنها ۳۰۰ میلیون پارامتر دارد، توازن بهشدت به نفع اجرای محلی برای مجموعهدادههای شخصی سنگینی میکند.
تصمیم برای نگه داشتن سیستم در حالت «فقط بازیابی» (بازگرداندن لیست لینکها بهجای تولید خلاصه متنی) یک انتخاب استراتژیک است. این کار نیاز به یک LLM دوم و بسیار بزرگتر را از بین میبرد، ردپای حافظه (Memory Footprint) را پایین نگه میدارد و تضمین میکند که نتایج همیشه بر اساس واقعیتهای موجود در ستارههای کاربر باشند.
بهینهسازیهای آینده
مسیرهای روشنی برای گسترش این قابلیت وجود دارد. افزودن رتبهبندی ترکیبی (Hybrid Ranking) — یعنی ترکیب جستوجوی برداری با جستوجوی متنی کامل (Full-text search) استاندارد Postgres — تضمین میکند که تطبیقهای دقیق نام (مثل «tokio») همیشه در رتبه اول قرار گیرند.
بهروزرسانیهای احتمالی دیگر شامل تکهتکه کردن (Chunking) کامل فایلهای README برای تطبیق محتوای عمیقتر و افزودن فیلترهایی برای زبانهای برنامهنویسی یا مالکان مخازن است. تکامل نهایی این سیستم میتواند ارسال نتایج برتر به یک LLM محلی کوچک برای تولید خلاصهای یکپاراگرافی از نتایج باشد.
با وجود کارایی رویکرد مبتنی بر Deno، توسعهدهنده پیشنهاد میکند که استفاده از یک پوسته مبتنی بر Go با استفاده از Wails میتواند حجم فایل نهایی را باز هم کاهش دهد، زیرا محیط اجرای Deno در حال حاضر حدود ۷۰ مگابایت به حجم پایه برنامه اضافه میکند.
گام بعدی شما
- اگر توسعهدهنده هستید، مدل EmbeddingGemma را برای جستوجوی محلی در مستندات شخصی خود امتحان کنید.
- برای کاهش مصرف رم، از نسخه کوانتیده q4 استفاده کنید.
- برای افزایش دقت، منطق نامتقارن پرامپتها را در پیادهسازی خود رعایت کنید.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای NPU در لپتاپهای جدید مراجعه کنید.




گفتگو