فیلمیار؛ روایتی از یک پروژه کارشناسی: وقتی گراف دانش با هوش مصنوعی مولد ترکیب میشود
پروژه پایانی کارشناسی مهندسی کامپیوتر
این پروژه از کجا شروع شد؟
برای پروژه پایانی مقطع کارشناسی مهندسی کامپیوتر، تصمیم گرفتیم سراغ موضوعی برویم که صرفاً یک تمرین درسی نباشد، بلکه یک سیستم واقعی و قابلاجرا باشد: یک دستیار پیشنهاد فیلم به نام فیلمیار، که پاسخهایش را نه از حدس یک مدل زبانی، بلکه از دل یک گراف دانش واقعی بیرون میکشد. رویکردی که این روزها به آن GraphRAG (Retrieval-Augmented Generation مبتنی بر گراف) گفته میشود.
ماهیت پروژه در یک نگاه
فیلمیار یک چتبات تحت وب است که به فارسی و انگلیسی (هر دو، بهصورت خودکار بر اساس زبان سوال کاربر) به سوالات سینمایی پاسخ میدهد: معرفی فیلم بر اساس ژانر، بازیگر، کارگردان یا سال ساخت؛ ارائه امتیاز IMDB؛ و پیشنهاد فیلمهای مشابه. نکتهی متفاوت این پروژه نسبت به بسیاری از چتباتهای مشابه، این است که اطلاعات واقعی فیلمها (بازیگران، کارگردان، ژانر، امتیاز) از یک گراف دانش ساختهشده در Neo4j خوانده میشود، و مدل زبانی فقط وظیفه دارد این اطلاعات را بهصورت طبیعی و روان بیان کند — نه اینکه آنها را از حافظهی خودش بسازد.
معماری سیستم: پنج مرحله تا رسیدن به پاسخ
هر پیامی که کاربر میفرستد، این مسیر را طی میکند:
| مرحله | شرح |
|---|---|
| استخراج موجودیت | متن آزاد کاربر (بدون دخالت مدل زبانی، صرفاً با منطق برنامهنویسی، Regex و تطبیق فازی) تحلیل میشود تا نام ژانر، بازیگر، کارگردان یا سال از آن بیرون کشیده شود |
| پرسوجوی گراف دانش | با موجودیتهای استخراجشده، یک کوئری Cypher روی گراف Neo4j اجرا میشود |
| بازگشت به جستوجوی وب | اگر گراف محلی چیزی پیدا نکرد، بهصورت خودکار سراغ جستوجوی وب (DuckDuckGo) میرود |
| تولید پاسخ با مدل زبانی | اطلاعات پیداشده در قالب یک پرامپت جای میگیرد و به یک مدل زبانی مولد (LLaDA-8B، از خانواده مدلهای دیفیوژنی) داده میشود تا پاسخ نهایی را بنویسد |
| لایه ارتباطی | یک سرور Flask درخواستها را از یک صفحه چت اختصاصی میگیرد و از طریق تونل Cloudflare، بهصورت عمومی در دسترس قرار میدهد |
جدا نگهداشتن مرحله استخراج موجودیت از مدل زبانی یک تصمیم طراحی آگاهانه بود: مدلهای زبانی، بهخصوص مدلهای دیفیوژنی مثل LLaDA، در تولید خروجی دقیق و ساختیافته (مثل کوئری پایگاه داده) عملکرد قابلاعتمادی ندارند؛ به همین دلیل این بخش کاملاً با منطق قطعی برنامه انجام میشود، و مدل زبانی فقط در آخرین قدم، برای «حرف زدن» به کار گرفته میشود.
استفاده از یک مدل زبانی دیفیوژنی بهجای مدلهای زنجیرهای رایجتر (مثل خانواده GPT) هم یکی از جنبههای کاوشگرانهی این پروژه بود — تجربهای که رفتار و محدودیتهای متفاوتی نسبت به مدلهای متداولتر نشان داد.
پشته فناوری
| حوزه | ابزار / فناوری |
|---|---|
| گراف دانش | Neo4j (نسخه Community) |
| مدل زبانی مولد | LLaDA-8B-Instruct، با کوانتیزاسیون ۴-بیتی |
| پردازش زبان طبیعی | spaCy، Regex، تطبیق فازی با rapidfuzz |
| بکاند | Python، Flask، Flask-CORS |
| زیرساخت یادگیری عمیق | PyTorch، Transformers، Accelerate، BitsAndBytes |
| جستوجوی وب | DuckDuckGo Search، بههمراه پشتیبانی اختیاری از Tavily API |
| پردازش داده | Pandas |
| محیط اجرا | Google Colab (با GPU رایگان T4) |
| ذخیره دائمی دیتاست | Google Drive |
| دسترسی عمومی به سرویس | Cloudflare Quick Tunnel |
| رابط کاربری | HTML، CSS، JavaScript |
ویژگیهای کلیدی
- پاسخدهی دوزبانه (فارسی/انگلیسی) با تشخیص خودکار زبان سوال
- اطلاعات مبتنی بر داده واقعی، نه حدس مدل زبانی
- مکانیزم بازگشتی به جستوجوی وب در نبود داده محلی
- دیتاست فقط یکبار در Google Drive کاربر بارگذاری میشود و در اجراهای بعدی نیازی به تکرار آن نیست
- اجرای کامل روی زیرساخت رایگان Google Colab، بدون نیاز به هیچ سرور اختصاصی
- رابط کاربری وب مستقل، جدا از محیط نوتبوک
چالشهای فنی در طول توسعه
اجرای یک مدل زبانی ۸ میلیارد پارامتری روی زیرساخت رایگان، چالشهای مهندسی واقعیای به همراه داشت که برای هرکدام باید راهحل مشخصی پیدا میکردیم:
| چالش | راهحل اتخاذشده |
|---|---|
| جا نشدن مدل ۸ میلیاردی روی GPU رایگان (T4، ۱۵ گیگابایت VRAM) | کوانتیزاسیون ۴-بیتی مدل با bitsandbytes |
| ریسک خطای کمبود حافظه (OOM) به دلیل فرآیند نمونهگیری تکراری مدل دیفیوژنی (تا ۴۸ گام برای هر پاسخ) | استفاده از torch.inference_mode() و پاکسازی صریح کش CUDA بین گامها |
| نشتِ متن دستورالعمل/زمینه به داخل پاسخ نهایی مدل | افزودن نشانگر مشخص («پاسخ نهایی:») در انتهای پرامپت و پاکسازی خروجی بر اساس آن |
| کندی اولین پاسخ به دلیل بارگذاری تنبل مدل، که از مهلت زمانی تونل عمومی عبور میکرد | بارگذاری فعال مدل بلافاصله پس از بالا آمدن سرور، پیش از دریافت اولین درخواست |
| ناسازگاری نسخهای bitsandbytes با ساختار بهروزشده CUDA در Colab | ارتقا به نسخههایی از bitsandbytes/accelerate که مکانیزم تشخیص CUDA را بازنویسی کرده بودند |
| تفاوت نامگذاری ستونها در نسخههای مختلف دیتاست IMDB | نگاشت خودکار و مشروط نام ستونها |
محدودیتی که هنوز باقی است
در کمال صداقت باید گفت این پروژه با یک چالش حلنشده هم روبهروست: دیتاست محلی (TMDB 5000 و IMDB Top 1000) عمدتاً سینمای هالیوود را پوشش میدهد. برای بازیگران یا فیلمهای خارج از این دامنه، هم گراف محلی و هم جستوجوی وب رایگان ممکن است نتیجهی ضعیف یا نامرتبطی برگردانند؛ در چنین شرایطی، مدل زبانی دیفیوژنی گاهی بهجای اعلام صریح «اطلاعاتی پیدا نشد»، ترکیبی نادرست از دانش پیشآموختهی خود ارائه میدهد. این موضوع یکی از زمینههای روشن برای ادامهی کار روی پروژه است: گسترش پوشش دیتاست، و تقویت مکانیزمهای جلوگیری از پاسخ نادرست.
دیتاستهای استفادهشده
- TMDB 5000 Movie Dataset: اطلاعات پایه فیلمها شامل ژانر، بازیگران و کارگردان
- IMDB Top 1000: امتیازهای IMDB برای تکمیل اطلاعات فیلمهای مشترک
راهنمای اجرا
فیلمیار کاملاً روی Google Colab اجرا میشود؛ نیازی به نصب چیزی روی سیستم شخصی نیست.
- نوتبوک پروژه را از مخزن گیتهاب دانلود کنید: لینک مخزن گیتهاب پروژه
- فایل
.ipynbرا در Google Colab باز کنید. - از منوی Runtime، گزینه Change runtime type را انتخاب و GPU (نوع T4) را فعال کنید.
- سلولها را بهترتیب از بالا به پایین اجرا کنید.
- در سلول بارگذاری دیتاست، درخواست دسترسی به Google Drive نمایش داده میشود؛ دسترسی را تأیید کنید.
- فایلهای دیتاست را از این مسیر دانلود و در همان مرحله بارگذاری کنید: لینک دانلود دیتاستها از این پس، دیتاستها در Google Drive شما ذخیره میمانند و در اجراهای بعدی نیازی به تکرار این مرحله نیست.
- در انتهای اجرا، یک لینک عمومی (Cloudflare Tunnel) دریافت میکنید.
- صفحه چت (
ai.movie.salehaskari.ir) را در مرورگر باز کرده، لینک عمومی را در بخش «اتصال به سرور» وارد کنید و گفتوگو را شروع کنید. صفحه چت
توجه: تا زمانی که از دستیار استفاده میکنید، سلول آخر نوتبوک (سرور و تونل) نباید متوقف شود و تب Colab باید باز و فعال بماند.
جمعبندی
فیلمیار برای ما فرصتی بود تا رویکرد GraphRAG را نه بهصورت تئوری، بلکه در قالب یک سیستم واقعی و قابلاجرا تجربه کنیم؛ سیستمی که در آن پاسخ مدل زبانی، ریشه در دادهی واقعی و ساختیافته دارد. در طول این مسیر با چالشهای ملموس مهندسی نرمافزار و یادگیری ماشین — از مدیریت دقیق حافظه GPU تا رفتار گاه غیرقابلپیشبینی مدلهای زبانی مولد — دستوپنجه نرم کردیم؛ تجربهای که ارزش آن فراتر از نمرهی پایاننامه بود.
قدردانی
در پایان، از استاد راهنمای این پروژه، جناب آقای دکتر بگمحمدی، برای راهنماییها، بازخوردهای دقیق و همراهیشان در طول این مسیر صمیمانه سپاسگزاریم. نگاه دقیق و مشاورههای ایشان نقش مهمی در شکلگیری و ارتقای کیفیت این پروژه داشت.