Mahi in Tech
Открыть в Telegram
698
Подписчики
Нет данных24 часа
+47 дней
+3930 дней
Архив постов
704
* با هر نسخه، آخرین ورژن مدل بهصورت خودکار از مخزن دیتاست در گیتهاب دریافت و باندل میشه. در صورت بهروزرسانی مدل، امکان ارتقای اون بدون نیاز به نصب مجدد برنامه هم وجود داره.
* مخاطبین بهصورت پیشفرض از تشخیص اسپم مصون هستن. در صورت نیاز، میتونید این مصونیت رو برای افرادی که در مخاطبینتون نیستن هم فعال کنید.
* میتونید میزان حساسیت مدل رو از تنظیمات تغییر بدید. پیشفرض روی حالت Balanced هست که فکر میکنم با مدل فعلی، همین حالت کافی باشه.
* روزانه یک بار گزارشی از پیامکهای اسپم نمایش داده میشه تا اگر پیامی بهاشتباه بهعنوان اسپم تشخیص داده شده بود، از دست نره. زمان نمایش این گزارش از تنظیمات قابل تغییره و امکان غیرفعال کردنش هم وجود داره.
704
اولین نسخهی «قیچی» منتشر شد! ✂️
راستش چند وقتی هست که پیامکهای تبلیغاتی و اسپم، شدیدا اعصابم رو خرد میکرد و دیگه با دلار ۲۷۰ تومنی، تحملِ حواسپرتی برای اساماسِ کد تخفیف ۵ هزار تومنی اسنپ و یا به خصوص وصایای امام 🍌 ممکن نبود.
برای همین تصمیم گرفتم پروژهای رو که اولین کامیتش مربوط به ۲ سال پیش بود و بعد از اون هم دیگه ادامه پیدا نکرد، بالاخره به سرانجام برسونم.
«قیچی» یک اپلیکیشن مدیریت پیامک اندرویدی هست که با MAUI + ML.NET توسعه داده شده و تنها یک هدف داره: خفه کردن پیامکهای اسپم و تبلیغاتی. قیچی به عنوان اپلیکیشن پیشفرض گوشیتون تنظیم میشه و دقیقاً همون کاری رو میکنه که هر SMS Manager دیگهای انجام میده؛ با این تفاوت که یک مدل ML خیلی سبک هم داخلش تعبیه شده که هدفش تشخیص پیامکهای تبلیغاتی در کسری از میلیثانیه و بهصورت کاملا آفلاین روی دیوایس شخص هست.
بنابراین هیچ دادهای به سمت سرور ارسال نمیشه و همهچیز کاملا آفلاین و امنه. ضمن اینکه تمام بخشهای پروژه اعم از دیتاست، سورس اپلیکیشن و مدل ML اپنسورس هستن و بیلد برنامه هم مستقیما توسط GitHub Actions گرفته میشه. یعنی اینطوری بگم که خیالتون از هر بابت راحت باشه.
دیتاست فعلی در حال حاضر خیلی جامع نیست و حدود ۶ هزار پیامِ لیبلخورده رو شامل میشه؛ اما طبق برآورد و تستهایی که داشتم، همین دیتاست کوچیک هم (که از منابع مختلفی جمعآوری شده) تا حد خوبی جوابگوی نیاز برنامه است.
همچنین داخل برنامه این امکان تعبیه شده که شما بهصورت گزینشی (و با حذف خودکار یا دستیِ اطلاعات حساس)، پیامکهای تبلیغاتی یا پیامکهای غیرتبلیغاتیای که به اشتباه تبلیغ تشخیص داده شدن رو گزارش کنید تا این دیتاست به مرور زمان کاملتر بشه و عملکرد مدل ارتقا پیدا کنه. (اگر هم نکردین چالشی نیست، خودم میکنم 😭)
نسخهی فعلی در واقع حداقل نسخهی قابل ارائه هست و احتمالا باگهای زیادی خواهد داشت. ولی خب از اونجایی که مورد استفادهی روزمرهی خودم هست، به مرور زمان بهبود پیدا میکنه.
🔗 سورس پروژه و توضیحات تکمیلی:
https://github.com/MahdiyarGHD/GheychiApp
📥 دانلود نسخهی اولیه از گیتهاب:
https://github.com/MahdiyarGHD/GheychiApp/releases
اگر دوست داشتید، با گزارش باگ، مشارکت در توسعه یا حتی یک ⭐️ روی گیتهاب میتونید کمک کنید قیچی بهتر بشه.
704
این trickـهای AI هم هرروز عجیبتر میشه ها.
یه LLM که ورودی عکس قبول نمیکنه رو گذاشته بودم یک تسک رو انجام بده، و خب بعید میدونستم که به عکس نیاز پیدا کنه. یه مدت چکاش نکردم و وقتی برگشتم دیدم یهسری اسکرینشات گرفته و یه اسکریپت نوشته که اونها رو به ASCII Art تبدیل میکنه و سعی میکنه بفهمتشون :)))
704
از این به بعد داخل کلاد کد، اگر یه وقت وسط انجام یه تسک به لیمیت ۵ ساعته برخورد کنید، دیگه اون تسک رو همونجا متوقف نمیکنه و صرفاً سعی میکنه با استفاده از لیمیت هفتگیتون، زودتر جمعوجورش کنه. (البته ظاهرا برای کاربران Pro, صرفا یک بار در هفته قابل استفادهست)
704
وقتی صحبت از پیادهسازی Rate Limiting (مخصوصا مدلهایی مثل Token Bucket یا Leaky Bucket) میشه، معمولا اولین چالش، مدیریت State هست؛ اینکه همزمان باید تعداد توکنهای باقیمونده و زمان آخرین Refresh رو نگه داریم و حواسمون به Race Condition هم باشه.
الگوریتم GCRA (Generic Cell Rate Algorithm) که توی سیستمهای توزیعشده استفاده میشه، این مسئله رو با یک ترفند ریاضی خیلی ساده حل کرده: حذف مفهوم توکن و جابجایی همهچیز به بردار زمان.
ایده اصلی اینه: به جای اینکه چک کنیم کاربر چند تا توکن داره یا شمارنده رو ریست کنیم، یک متغیر عددی به اسم TAT (Theoretical Arrival Time) نگه میداریم؛ یعنی «زمان تئوریک رسیدن درخواست بعدی».
منطق کارکرد به چه صورته؟
فرض کنید لیمیت سیستم، ۱ درخواست در ثانیه باشه و به کاربر اجازه دادید تا سقف ۳ درخواست هم ترافیک ناگهانی (Burst) داشته باشه:
هر بار که یک درخواست تایید میشه، TAT به اندازهی فاصلهی زمانی مجاز بین درخواستها، به آینده هل داده میشه.
اگر کاربر چند درخواست پشت سر هم بفرسته، TAT جلوتر و جلوتر میره. در واقع داریم میزان «جلو افتادن» جریان درخواستها از نرخ مجاز رو اندازه میگیریم، و تا وقتی فاصلهی بین زمان فعلی و TAT از محدودهی مجاز Burst بیشتر نشده باشه، درخواستها تایید میشن.
اگر این فاصله از محدودهی مجاز عبور کنه، کاربر درجا خطای 429 میگیره و مهمتر اینکه TAT هم برای درخواست ردشده تغییر نمیکنه.
به محض اینکه کاربر چند ثانیه دست نگه داره، زمان فعلی به TAT نزدیکتر میشه و عملاً ظرفیت Burst بهصورت خودکار آزاد میشه؛ بدون اینکه هیچ Job پسزمینهای نیاز باشه یا کدی برای ریست کردن شمارندهها اجرا بشه.
در سادهترین حالت، منطق چیزی شبیه به اینه:
if now < TAT - tolerance:
reject
else:
TAT = max(now, TAT) + interval
accept
و قبل از آپدیت، بررسی میکنیم که آیا TAT در محدودهی مجاز قرار داره یا نه. نکتهی مهم اینه که مقدار دقیق این محدوده به نحوهی تعریف Burst/Tolerance در پیادهسازی بستگی داره.
چرا این مدل جذابه؟
۱. استیت تکمقداری: کل وضعیت هر کاربر فقط یک عدد ساده (Timestamp) هست که توی ردیس میتونه به صورت یک String ساده ذخیره بشه.
۲. اجرای اتمیک و جلوگیری از Race Condition: خود GCRA بهتنهایی Race Condition رو حذف نمیکنه؛ چیزی که این مشکل رو حل میکنه، اجرای اتمیک کل منطق Check + Update هست. مثلا میتونیم این کار رو با یک اسکریپت چند خطی Lua داخل Redis انجام بدیم، بدون اینکه چند دستور جداگانه بین Read و Write داشته باشیم.
۳. مدیریت تمیز TTL: چون زمان موردنیاز برای نگه داشتن State قابل محاسبه است، میتونیم TTL کلید رو بر اساس زمانی تنظیم کنیم که TAT و محدودهی Burst دیگه برای تصمیمگیری لازم نیستن. در نتیجه، کلیدها بهصورت خودکار expire میشن و نیازی به Job یا فرآیند جداگانه برای پاکسازی State نداریم.
در نهایت، جذابیت اصلی GCRA این هست که به جای نگه داشتن چند متغیر مثل Token Count، Last Refill و Timestamp، کل State رو به یک مفهوم زمانی تبدیل میکنه.704
توی سیستمهای High-Load، یکی از چالشهای همیشگی اینه که خیلی سریع بفهمیم یک دیتای خاص وجود داره یا نه. اگر بخوایم برای هر چک کردن ساده بهطور مستقیم سراغ دیتابیس بریم یا حتی به صورت کامل روی Cache حساب کنیم، هم منابع زیادی درگیر میشه و هم Latency بالا میره.
یکی از رویکردهای بهینه و جذاب برای حل این مسئله، استفاده از Bloom Filter هست.
بلوم فیلتر یک Data Structure احتمالاتی 🥴 هست که با کمترین میزان مصرف مموری و سرعت خیرهکننده، بهمون میگه یک آیتم وجود داره یا نه.
سناریوی واقعی: انتخاب یوزرنیم در تلگرام
تلگرام صدها میلیون کاربر داره. وقتی شما موقع ثبتنام داری یوزرنیم تایپ میکنی، به ازای هر کاراکتری که میزنی باید چک بشه که این یوزرنیم آزاد هست یا نه. اگر تلگرام بخواد برای هر تایپ شما یک کوئری به دیتابیس اصلیش بزنه، دیتابیس در عرض چند ثانیه از حجم درخواستها نابود میشه!
راهحل چیه؟ تلگرام تمام یوزرنیمهای ثبتشده رو میده به یک Bloom Filter که توی رم قرار داره. وقتی شما یوزرنیم جدید رو تایپ میکنی، بلوم فیلتر در کسری از میلیثانیه چک میکنه. اگر بگه «این یوزرنیم بهطور قطع وجود نداره»، تلگرام همون لحظه تیک سبز رو بهت نشون میده و دیگه کاری به دیتابیس نداره (صرفهجویی عظیم در منابع). اما اگر بلوم فیلتر بگه «ممکن هست وجود داشته باشه»، تلگرام تازه اونجا میره از دیتابیس میپرسه که "مطمئنی این یوزرنیم پر شده؟" تا وضعیت دقیق رو بهت بگه. (که البته تلگرام چنین کاری نمیکنه و مثال بود=))
حالا این بلوم فیلتر چطور کار میکنه؟
پشت صحنه، Bloom Filter در واقع فقط یک آرایه طولانی از Bitهاست که اول کار همهشون صفر هستن. در کنارش، چند تا تابع Hash مستقل و سریع هم داریم.
وقتی میخوایم یک دیتای جدید رو به سیستم اضافه کنیم، این دیتا رو به توابع Hash میدیم. خروجی این توابع، ایندکسهایی از همون آرایه بیتهاست. بعد میریم اون ایندکسها رو برابر با ۱ قرار میدیم.
موقع جستجو دوباره همون دیتای ورودی رو هش میکنیم و ایندکسها رو چک میکنیم:
۱. اگر حتی یکی از اون بیتها صفر باشه، سیستم با قطعیت ۱۰۰٪ میگه این دیتا «بهطور قطع وجود نداره».
۲. اگر همه بیتها ۱ باشن، سیستم میگه این دیتا «احتمالا وجود داره».
چرا میگیم احتمالا؟ چون ممکنه اون بیتها قبلا بهخاطر هش شدنِ دیتای دیگهای ۱ شده باشن (همون پدیده Hash Collision). یعنی ما توی Bloom Filter خطای False Positive داریم، اما False Negative اصلا نداریم.
البته که این ساختار محدودیتهای خودش رو هم داره؛ بهطور مثال حذف کردن یک آیتم از بلوم فیلتر در پیادهسازیهای استانداردش یهجورایی غیرممکنه؛ چون با صفر کردن یک بیت، ممکن هست دیتای دیگهای که از همون بیت استفاده میکرده رو هم خراب کنیم.
در نهایت، در ازای پذیرش اون احتمال کمِ False Positive، سیستمی به دست میاد که میتونه وجود میلیونها رکورد رو فقط با چند مگابایت RAM در لایه Application چک کنه و زیرساخت دیتابیس شما رو از شر درخواستهای بیهوده نجات بده.
704
Repost from Persian GitHub
نسخه جدید Oblivion منتشر شد!
هسته کلاینت کاملا تغییر کرده و Aether جایگزین هسته قبلی شده؛ با پشتیبانی از MASQUE H2/H3، WARP، GOOL و قابلیت Chain با Psiphon.
برای شبکههای محدود هم روی Scan و Obfuscation کار زیادی شده تا اتصال پایدارتر و سادهتر باشه.
https://github.com/bepass-org/oblivion/releases/tag/v8
🐙 @RepoFA
704
Repost from N/a
ما میدونیم (یا نمی دونیم) که LLM ها بدون حافظه ان. یعنی توی هر پیام جدید سیستم باید کل تاریخچه گفتگو رو از اول برای مدل بخونه تا بتونه یه کلمه جدید تولید کنه ( واسه همینه که توی چتای طولانی، کندتر عمل میکنه و به مراتب هرینه اش بالاتر میره).
قبلا میومدن و برای حل این مشکل از تکنیکی به اسم Prompt Caching استفاده میکردن، یعنی محاسبات قبلی ( KV Cache) رو ذخیره میکردن تا هزینه کمتر شه. ولی خب این کش فقط روی همون مدلی کار میکرد که پیداش کرده بود! 👀
اینا رو گفتم تا برسیم به اینکه انویدیا جدیدا چه کرده-
یه متد طراحی کرده که میشه KV Cache رو مستقیما به یه مدل دیگه منتقل کرد!
مرحله Prefill (همونجایی که کل تاریخچه گفتگو رو از اول میخونه) رو کلا دور می زنه و حافظه قبلی رو با فرمت مختص به خودش ترجمه میکنه.
ولی چطوری؟( ممنون~ شما چطوری؟)
-نگاشت خطی: فهمیدن که حتی بین مدلای متفاوت لایه شباهت ساختاری وجود داره
-ترکیب لایه ها: برای هر لایه در مدل مقصد، 8 لایه برتر از مدل مبدا رو ترکیب میکنن تا شباهت به 79 درصد برسه.
-دستکاری RoPE: چرخش های موقعیتی توکن ها رو موقتا برمیدارن، تبدیل ریاضی رو انجام میدن و بعد چرخش مدل جدید رو روش پیاده میکنن.
نتایج چطور بوده؟
• ۲.۷ تا ۲۵ برابر سریعتر از پردازش مجدد متن!
• حفظ ۷۳ تا ۹۸ درصد از دقت مدل مقصد.
این مدل فعلا روی مدل های هم خانواده تست شده ولی فعلا یه بن بست بزرگ رو شکسته توی انتقال حافظه.
704
+1
کپشنی ندارم، فقط تعداد استارها رو ببینید =))
چهار تا فایل Markdown
vs
کرنل لینوکس
704
اگه این روزها از Coding Agentها استفاده میکنید (که احتمالاً همهمون دیگه داریم میکنیم :) )، احتمالا اسم Graphify به گوشتون خورده؛ ابزاری که به ایجنت وصل میشه، کدبیس شما رو به یک گراف متنی تبدیل میکنه و با دادن دید کلی به ایجنت، باعث کاهش مصرف توکن میشه.
با پیشنهاد یکی از دوستان، مدتی هست به جای Graphify رفتم سراغ Codebase Memory MCP، و خب حداقل از نظر من تجربه بهمراتب بهتری بوده.
علاوهبر اینکه پروژه رو خیلی سریعتر ایندکس میکنه، مصرف توکنش حتی از Graphify هم کمتره و به لطف MCP بودنش، خیلی تمیز و بیدردسر با ایجنت همگام میشه. تازه UI گرافش هم خوشگلتره 😅
https://github.com/DeusData/codebase-memory-mcp
704
این سرویس از پارسال تا الان پیشرفت قابل توجهای داشته، تستش کنید حتما (با پرامپت مناسب).
من که لذت بردم.
البته هنوز Claude Design رو امتحان نکردم، ولی خب این Stitch به نسبت اینکه رایگان هستش خروجیهای قابل قبولی میده.
704
+1
دو روز پیش همینطوری رندوم داشتم نرخ لپتاپهای مختلف رو چک میکردم، که تب رو روی عکس سمت راست بستم و رفتم.
امروز تصادفی این تب رو مجدد باز کردم که با عکس سمت چپ مواجه شدم 😆
704
یک نمونهی خیلی ساده با CSharp که به کمک OpenCV یک واترمارک مشخص و محدود رو توی تصویر پیدا میکنه، و با یک overlay دیگه جایگزینش میکنه.
github.com/MahdiyarGHD/WatermarkSwapper
704
داشتم ریپوهای گیتهابم رو یه نگاهی میانداختم، که چشمم به این ریپو خورد که مال حدود ۴ ۵ سال پیشه 😄 اون زمان تازه بکاند و PHP کار میکردم و AI ای هم در کار نبود :)) اوج خلافام کپی کردن از stackoverlow بود و چقدر زود گذشت. عمرا فکر میکردم ۴ ۵ سال دیگه توی چنین بدبختی و وضعیتی دست و پا بزنیم.
github.com/MahdiyarGHD/KnightTour
این هم حدودا مربوط به یک سال بعدشه:
github.com/MahdiyarGHD/ToigBot
دیتابیسش فایل جیسونه 😁 و چقدر هم خوب کار میکرد. حالا هی بیا سیستم دیزاین کن 🙂↔️
