پرش به محتوای اصلی
پرش به محتوای مقاله

۳ گام فنی برای بازسازی معماری نانوبات در حلقه‌های مستقل

·۵ تیر ۱۴۰۵۱۸ دقیقه مطالعه
راهنما
ساخت عامل هوش مصنوعی نانوبات در گوگل کولب با ابزارها، حافظه، مهارت‌ها و سرورهای MCP
ساخت عامل هوش مصنوعی نانوبات در گوگل کولب با ابزارها، حافظه، مهارت‌ها و سرورهای MCP
اشتراک‌گذاری
واقعاً چه چیز جدید است؟

بازسازی کامل معماری nanobot در محیط Colab با تمرکز بر پیاده‌سازی دستی پروتکل MCP و سیستم قلاب (Hook) برای نظارت بر چرخه حیات عامل، بدون استفاده از فریم‌ورک‌های آماده.

تصور کنید می‌خواهید یک دستیار هوشمند بسازید که بدون نیاز به کتابخانه‌های حجیم، بتواند کد بزند، محاسبات پیچیده انجام دهد و حقایق را به خاطر بسپارد. شما می‌توانید یک عامل (Agent) کامل و تقویت‌شده با ابزار را تنها در یک دفترچه گوگل کولب (Google Colab) پیاده کنید، بدون اینکه به چارچوب‌های پیچیده شخص ثالث وابسته باشید. با بازسازی معماری هسته nanobot، توسعه‌دهندگان می‌توانند یک حلقه مستقل از ارائه‌دهنده (provider-agnostic loop) پیاده کنند که ثبت ابزارها، حافظه نشست و سرورهای خارجی را در یک بسته سبک مدیریت می‌کند. تمرکز این آموزش بر بازسازی بلوک‌های سازنده اصلی — پیام‌ها، ابزارها، حافظه و پاسخ‌های مدل — است تا سازوکارهای داخلی حلقه عامل کاملاً شفاف شوند.

این رویکرد در زمانی ارائه می‌شود که عامل‌های هوش مصنوعی از ساختارهای یکپارچه (monolithic) به سمت طراحی‌های ماژولار و ابزار-محور حرکت می‌کنند. همان‌طور که در تحلیل قبلی ما درباره‌ی ابزارهای تحلیل پرتفوی در گوگل فایننس اشاره کردیم، تمرکز اکنون از استفاده از اپلیکیشن‌های آماده به مهندسی منطق زیربنایی «عامل‌بودن» تغییر کرده است. در واقع، مدل زبانی بزرگ (LLM) در اینجا صرفاً به عنوان یک موتور استدلالی عمل می‌کند که تصمیم می‌گیرد کدام تابع خارجی اجرا شود و چه پاسخی برگرداند. این رویکرد با استراتژی‌های پیشرفته‌تر در چارچوب‌های صنعتی متفاوت است؛ برای مثال، می‌توان ساخت عامل‌های درآمدزا در LangChain با ادغام ابزارهای خارجی را به عنوان نمونه‌ای از پیاده‌سازی‌های متمرکز بر کسب‌وکار در مقیاس بزرگ‌تر بررسی کرد.

لایه انتزاعی ارائه‌دهنده

معماری با یک کلاس پایه به نام Provider آغاز می‌شود. این انتزاع تضمین می‌کند که حلقهٔ عامل مستقل از مدل زبانی خاص مورد استفاده باقی بماند. به نقل از آموزشگاه Marktechpost که در سال ۲۰۲۴ منتشر شد، این ساختار اجازه می‌دهد عامل به راحتی بین یک ارائه‌دهنده واقعی سازگار با OpenAI (مانند DeepSeek، OpenRouter، Together، vLLM، LM Studio یا مسیر /v1 در Ollama) و یک ارائه‌دهنده شبیه‌ساز (MockProvider) جابه‌جا شود.

برای حفظ سازگاری و ثبات در تمامی بک‌اندهای مختلف، سیستم از ساختارهای داده‌ای نرمال‌شده (normalized) استفاده می‌کند:

  • ToolCall: یک دیتاکلاس که شناسه منحصربه‌فرد (ID)، نام و آرگومان‌های درخواست ابزار توسط مدل را ثبت می‌کند.
  • Usage: ردیابی توکن‌های پرامپت (prompt) و تکمیل (completion)، که در آن کل مصرف به صورت prompt_tokens + completion_tokens محاسبه می‌شود.
  • LLMResponse: قالبی واحد که هر ارائه‌دهنده‌ای باید آن را بازگرداند؛ شامل محتوا، فراخوانی‌های ابزار، دلیل پایان عملیات (مانند "stop" یا "tool_calls") و آمار مصرف توکن.

ارائه‌دهنده سازگار با OpenAI به‌طور خاص از کلاینت AsyncOpenAI بهره می‌برد. این لایه مدیریت انتخاب ابزار را با استفاده از تنظیم tool_choice="auto" انجام می‌دهد و آرگومان‌های فراخوانی ابزار مدل را از رشته‌های JSON تجزیه می‌کند. اگر در این مرحله خطای JSONDecodeError رخ دهد، سیستم آرگومان‌های خام را تحت یک کلید _raw ذخیره می‌کند تا از متوقف شدن یا کرش کردن حلقه جلوگیری شود.

MockProvider برای توسعه و تست حیاتی است. این بخش با استفاده از منطق مبتنی بر قوانین (rule-based)، فراخوانی ابزارها و پاسخ‌ها را شبیه‌سازی می‌کند تا بتوان حلقه عامل را بدون نیاز به کلیدهای API یا مواجهه با تأخیرهای شبکه تست کرد. این شبیه‌ساز دقیقاً یک رفتار ضروری مدل‌های واقعی را تقلید می‌کند: تصمیم به صدور یک فراخوانی ابزار در یک قالب نرمال و سپس تولید پاسخ نهایی به زبان طبیعی پس از بازگشت نتایج. هدف مرکزی قرارداد ارائه‌دهنده (provider contract) این است که حلقه عامل نتواند تفاوتی بین MockProvider و یک ارائه‌دهنده زنده OpenAI حس کند.

مکانیزم‌های ارائه‌دهنده شبیه‌ساز

این ارائه‌دهنده از چندین دستیار داخلی برای شبیه‌سازی «هوش» از طریق عبارات منظم (regex) و تطبیق قوانین استفاده می‌کند:

  • _last_user_text: پیام‌ها را به‌صورت معکوس اسکن می‌کند تا آخرین ورودی کاربر را بیابد و محتواهای غیررشته‌ای را به رشته‌های JSON تبدیل کند.
  • _already_called: با بررسی اینکه آیا یک ابزار خاص در تاریخچه گفتگو استفاده شده است یا خیر، از ورود مدل شبیه‌ساز به حلقه‌های بی‌نهایت جلوگیری می‌کند.
  • _scan_memory: نوبت‌های کاربر را با Regex برای یافتن عباراتی مثل «نام من ... است» یا «من ... را دوست دارم» تحلیل می‌کند تا ثابت کند حافظه نشست دوباره به مدلe تغذیه می‌شود. این متد نام (به عنوان عنوان) و مورد علاقه کاربر را استخراج می‌کند.
  • _extract_math: از عبارات منظم برای تبدیل جملاتی مانند «جذر ۱۶» به فرمت sqrt(16) و تبدیل علامت «^» به «**» قبل از ارسال آن‌ها به ابزار ماشین‌حساب استفاده می‌کند.

در متد complete است، MockProvider قصد کاربر را ارزیابی می‌کند. برای مثال، اگر یک رقم و یک عملگر ریاضی (مانند + ، - ، * ، / ، ^) شناسایی شوند، ابزار calculator را فعال می‌کند. اگر کلمات کلیدی مانند «زمان»، «تاریخ» یا «امروز» ظاهر شوند، سعی می‌کند یک منطقه زمانی (مانند توکیو، دهلی، نیویورک یا لندن) را شناسایی کرده و ابزار get_current_time را فراخوانی کند.

پیاده‌سازی ثبت ابزار و حافظه

سیستم از یک ToolRegistry استفاده می‌کند که توابع استاندارد پایتون را به طرح‌های JSON سبک (JSON Schemas) مشابه OpenAI تبدیل می‌کند. این کار با استفاده از راهنمای تایپ (Type Hints) و مستندات تابع (Docstrings) برای تولید خودکار توضیحات پارامترها انجام می‌شود. دکوراتور @tool امضای تابع و اولین خط از داک‌استرینگ را تحلیل می‌کند تا مشخصاتی (spec) ایجاد کند که مدل بتواند آن را درک کند. این قابلیت تبدیل توابع به ابزارها، پایه و اساس بسیاری از سیستم‌های اتوماسیون است؛ برای نمونه می‌توان دید که چگونه با عامل‌های Langchain، زنجیره تولید محتوا تا درآمد AdSense را خودکار می‌کنند تا منجر به کسب درآمد شود.

برای نگاشت تایپ‌های پایتون به طرح‌های JSON، سیستم از یک دیکشنری به نام _PYTYPE_TO_JSON استفاده می‌کند که در آن str به "string"، int به "integer"، float به "number"، bool به "boolean"، list به "array" و dict به "object" تبدیل می‌شوند.

جزئیات ابزارهای داخلی

  • calculator: محاسبات ریاضی و جذرها را از طریق ماژول math مدیریت می‌کند. این ابزار از یک محیط eval محدود شده استفاده می‌کند که فقط شامل توابع math و توابع abs ، round ، min ، max و sqrt است. این ابزار از عباراتی مانند 2 ** 10 + sqrt(144) پشتیبانی کرده و علامت ^ را با ** جایگزین می‌کند.
  • get_current_time: برچسب‌های زمانی حساس به منطقه زمانی IANA را ارائه می‌دهد. این ابزار از ماژول zoneinfo برای شهرهای خاص مانند توکیو (Asia/Tokyo)، دهلی (Asia/Kolkata)، نیویورک (America/New_York) یا لندن (Europe/London) استفاده می‌کند و در صورت نامعتبر بودن منطقه زمانی، به UTC باز می‌گردد.
  • run_python: کدها را در یک فضای نام (namespace) محدود با استفاده از دیکشنری safe_builtins اجرا می‌کند. این دیکشنری شامل توابع print ، range ، len ، sum ، min ، max ، abs ، sorted ، enumerate ، list ، dict ، set ، str ، int ، float ، bool ، map ، filter ، zip ، all ، any و round است. کاربردهای آن شامل کارهایی مثل لیست کردن ۱۲ عدد اول فیبوناتچی یا محاسبه اعداد اول زیر ۵۰ است.
  • web_search: یک تابع جست‌وجوی ساده (stubbed) است که تکه‌هایی شبیه‌سازی شده را برمی‌گرداند: «(۱) مقاله کلی. (۲) مستندات رسمی. (۳) بحث‌های اخیر».
  • remember_fact & recall_fact: ابزارهای حافظه کلید-مقدار بلندمدت هستند که حقایق را در یک دیکشنری سراسری به نام _FACTS ذخیره و بازیابی می‌کنند. این به عامل اجازه می‌دهد کلیدی (مثلاً favorite_language) و مقداری (مثلاً Python) را ذخیره کند.

حافظه نشست و بودجه توکن

برای جلوگیری از سرریز شدن پنجره متنی (Context Window)، عامل از یک کلاس Memory با بودجه پیش‌فرض ۳۰۰۰ توکن استفاده می‌کند. تخمین توکن‌ها به‌صورت تقریبی و با نرخ ۴ کاراکتر برای هر توکن (chars // 4) انجام می‌شود.

این سیستم از یک مکانیزم compact استفاده می‌کند که قدیمی‌ترین پیام‌ها را در قالب «نوبت‌های کامل» (whole turns) حذف می‌کند. این کار تضمین می‌کند که تاریخچه با یک نتیجه ابزار یتیم (orphan tool result) شروع نشود؛ اگر اولین پیام در لیست دارای نقش "tool" باشد، تا زمانی که یک نوبت منسجم (شامل درخواست و نتیجه) برسد، پیام‌ها حذف می‌شوند. این روند باعث می‌شود جفت‌های-فراخوانی/نتیجه-ابزار حتی هنگام کوتاه شدن تاریخچه از ابتدای لیست، سازگار باقی بمانند.

قلاب‌های چرخه حیات و حلقه عامل

هسته عامل یک حلقه است که تا ۶ بار برای هر درخواست تکرار می‌شود (max_iterations). برای اجازه مشاهده عملیات بدون تغییر در زمان اجرا، سیستم AgentHooks را پیاده‌سازی کرده است. این قلاب‌ها (hooks) به‌صورت Async هستند و ایزوله شده‌اند؛ یعنی اگر یک قلاب شکست بخورد، یک بلوک try-except در دستیار _fan_out تضمین می‌کند که عامل به کار خود ادامه دهد.

این قلاب‌ها در مراحل خاصی از طریق یک AgentHookContext اجرا می‌شوند که شماره تکرار، پیام‌های فعلی، نتایج ابزار و مجموع توکن‌های مصرف شده را ردیابی می‌کند:

  • before_iteration: در شروع هر گام از حلقه فعال می‌شود.
  • before_execute_tools: پس از اینکه مدل ابزاری را درخواست کرد اما قبل از اجرای تابع پایتون اجرا می‌شود.
  • after_iteration: پس از پردازش نتایج ابزار یا رسیدن به پاسخ نهایی فعال می‌گردد.
  • finalize_content: یک متد خط لوله (pipeline) سنکرون است که می‌تواند خروجی متنی نهایی را با تغییر رشته محتوا، متحول کند.

مثال‌های کاربردی قلاب‌ها

  • AuditHook: هر ابزاری را که مدل تصمیم به فراخوانی‌اش می‌گیرد ثبت کرده و نام ابزار و آرگومان‌ها را از طریق before_execute_tools در کنسول چاپ می‌کند.
  • TimingHook: تأخیر هر انتقال مدل (LLM transition) را بر حسب میلی‌ثانیه با استفاده از time.perf_counter() اندازه‌گیری کرده و زمان سپری شده برای هر تکرار را گزارش می‌دهد.
  • CensorHook: از طریق finalize_content به عنوان یک فیلتر محتوا عمل کرده و کلمات حساس (مانند "secret") را قبل از نمایش به کاربر، با ستاره (***) جایگزین می‌کند.

مهارت‌ها و سرورهای سبک MCP

علاوه بر ابزارهای ساده، سیستم Skills را معرفی می‌کند. یک مهارت، یک دیتاکلاس است که نام، توضیحات، دستورالعمل‌های خاص و لیستی از ابزارها را دسته‌بندی می‌کند. بارگذاری یک مهارت از طریق load_skill باعث می‌شود دستورالعمل‌های تخصصی آن به پرامپت سیستمی اضافه شده و ابزارهای آن در ثبت‌کننده (registry) قرار گیرند. برای مثال، یک مهارت «پژوهش» به عامل دستور می‌دهد: «هنگام پژوهش، ابتدا وب را جست‌وجو کن، سپس تکه‌های یافته شده را در یک خلاصه کوتاه و دارای منبع ترکیب کن».

این معماری همچنین یک MCPServer (پروتکل زمینه مدل) حداقلی را پیاده می‌کند که به عنوان جایگزینی برای سرورهای ابزار خارجی عمل می‌کند. این سرورها ابزارهای نام‌گذاری شده را از طریق یک متد register که شرح ابزار، پارامترها و هندلر (handler) را تعریف می‌کند، ارائه می‌دهند.

آداپتور mcp_tools این‌ها را به اشیاء بومی Tool تبدیل می‌کند و برای جلوگیری از تداخل نام‌ها، نام سرور را به عنوان پیشوند اضافه می‌کند. برای مثال، سروری به نام "weather" با ابزار "forecast" به weather__forecast تبدیل می‌شود. این به عامل اجازه می‌دهد پیش‌بینی‌های هوایی را برای شهرهایی مثل دهلی بر اساس داده‌های شبیه‌سازی شده MCP (مانند "27°C, partly cloudy") ارائه دهد.

اجرای نهایی و رابط SDK

در نهایت، تمام این اجزا در یک رابط Nanobot SDK بسته‌بندی می‌شوند. این رابط ارکستراسیون ارائه‌دهنده، ثبت‌کننده و حافظه را مدیریت می‌کند. این SDK از یک پرامپت سیستمی پیش‌فرض استفاده می‌کند: «شما نانوبات هستید، یک عامل شخصی موجز و مفید... برای ریاضیات، زمان جاری، اجرای کد، جست‌وجوی وب یا بازیابی حقایق ذخیره شده، ترجیحاً از ابزار استفاده کنید تا حدس نزنید».

در یک دموی نهایی، عامل گفتگوهای چندمرحله‌ای را در کلیدهای مختلف نشست (مانند "user-ada" و "user-alan") مدیریت می‌کند. این امر ثابت می‌کند که حافظه نشست‌ها مستقل است؛ در حالی که آدا پایتون را دوست دارد، آلان عاشق هسکل است. عامل با اجرای یک توالی عملیاتی، توانایی خود را نشان می‌دهد: بازیابی زبان مورد علاقه از حافظه و هم‌زمان اجرای کد پایتون برای لیست کردن اعداد اول زیر ۵۰ با استفاده از یک قطعه کد سفارشی.

این بازسازی دستی شفاف می‌کند که بسته HKUDS/nanobot در لایه‌های زیرین چگونه عمل می‌کند و نقشه‌ای برای ساخت گردش‌کارهای مقیاس‌پذیر شخصی بدون نیاز به کتابخانه‌های سنگین ارکستراسیون ارائه می‌دهد.

این طراحی ماژولار به این معناست که توسعه‌دهندگان اکنون می‌توانند پیش از استقرار در محیط عملیاتی، روی پایداری وضعیت (state persistence) و ادغام ابزارهای خارجی به‌صورت محلی آزمایش کنند. چرخش به سمت سرورهای مدل MCP نشان می‌دهد که آینده عامل‌های هوش مصنوعی در استانداردسازی ارتباط بین مدل‌ها و منابع داده خارجی نهفته است.

برای شروع ساخت، می‌توانید کد کامل را در گیت‌هاب بررسی کنید یا بسته رسمی nanobot-ai را برای نسخه عملیاتی این معماری نصب کنید. برای کسانی که به محیط تولید (production) منتقل می‌شوند، متد Nanobot.auto() می‌تواند به‌طور خودکار NANOBOT_API_KEY یا OPENAI_API_KEY را شناسایی کند تا از MockProvider به یک مدل زنده مانند gpt-4o-mini با استفاده از آدرس پایه api.openai.com (در صورت عدم تعیین جایگزین) تغییر وضعیت دهد.

گام بعدی شما

  • کد کامل این پیاده‌سازی را در گیت‌هاب بررسی کنید یا بسته رسمی nanobot-ai را نصب کنید.
  • برای انتقال به محیط عملیاتی، از متد Nanobot.auto() برای شناسایی خودکار کلیدهای API استفاده کنید.
  • سعی کنید یک مهارت (Skill) جدید برای تحلیل داده‌های محلی خود تعریف کرده و آن را به حلقه عامل اضافه کنید.

اما داستان سخت‌افزاری این تحول حتی شگفت‌انگیزتر است — به تحلیل ما درباره‌ی تراشه‌های Blackwell مراجعه کنید.

چرا این موضوع مهم است؟

این معماری با کاهش وابستگی به کتابخانه‌های Third-party، هزینه توسعه و استقرار عامل‌های تخصصی را به شدت کاهش می‌دهد. تخصص در طراحی لایه‌های انتزاعی ارائه‌دهنده، امکان جابه‌جایی سریع بین مدل‌های مختلف را بدون بازنویسی کد فراهم می‌کند.

تأثیر برای ایران

برنامه‌نویسان ایرانی می‌توانند با استفاده از این ساختار سبک و MockProvider، بدون نیاز به پرداخت‌های ارزی یا دسترسی مستقیم به APIهای گران‌قیمت، منطق عامل‌های خود را توسعه و تست کنند.

·نگاه ما
تحریریه دات‌هوش

جایگزینی فریم‌ورک‌های سنگین با حلقه‌های سبک و انتزاعی، نشان می‌دهد که پیچیدگی عامل‌های هوش مصنوعی لزوماً در لایه‌های مدیریت نیست، بلکه در تعریف دقیق قراردادهای ارتباطی (Contract) بین مدل و ابزار است. این رویکرد، «شفافیت عملیاتی» را جایگزین «جعبه‌های سیاه» کتابخانه‌های آماده می‌کند و به توسعه‌دهنده اجازه می‌دهد کنترل دقیقی روی بودجه توکن و مدیریت حافظه داشته باشد.

منابع

این گزارش با خط‌لولهٔ خودکار دات‌هوش از منابع معتبر جهانی تدوین و زیر نظر تحریریه منتشر شده است. روش کار ما

گفتگو

پنج‌شنبه‌های هوش‌محور

بسته‌ی هفتگی دات‌هوش

۵ خبر، ۲ ابزار، ۱ پرامپت در هر شماره. به‌زودی راه‌اندازی می‌شود — هر پنج‌شنبه صبح.

خبر کلیدی
ابزار کاربردی
پرامپت حرفه‌ای
تحلیل پژوهش
به‌زودی
زاویه‌ی ایرانی
به‌زودی
تمرین این هفته
به‌زودی

راهنماهای دات‌هوش

راهنماهای کاربردیِ دات‌هوش برای کار با هوش مصنوعی — از همین‌جا شروع کنید:

دات‌هوش

راهنمای فارسی هوش مصنوعی — با نگاه به ایران

اخبار روزانه، معرفی ابزارها و مدل‌ها، و آموزشِ کار با هوش مصنوعی؛ همیشه با این پرسش که از ایران چه چیزی کار می‌کند و چه چیزی نه.