بازگشت به بلاگ

زبان‌های برنامه‌نویسی عامل‌محور

تاریخچه هوش مصنوعی عامل‌ها LLM زبان‌های برنامه‌نویسی مهندسی پرامپت
زبان‌های برنامه‌نویسی عامل‌محور — تصویر اصلی مقاله

تاریخچه

دانش در هستهٔ پیشرفت بشر قرار دارد. گاه در طول تاریخ، دیدگاه محدود به دانش مانع از پیشرفت شده است. به نوعی، این امر می‌تواند همان تنش ابدی میان دانشمندان و مهندسان باشد. از یک سو، دانشمندی را داریم که ارزش نهایی را برای «دانش واقع‌بنیاد» (factual knowledge) قایل است که معمولاً گزاره‌ای (Declarative) هستند. به عنوان مثال، ریاضی‌دانان از یک چارچوب رسمی متشکل از زبانی استاندارد برای استخراج دانش گزاره‌ایِ پیچیده‌تر استفاده می‌کنند. به همین شکل علوم نظری نیز سیستم‌هایی از دانش واقع‌بنیاد ایجاد می‌کنند.

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

در مصر باستان و بین‌النهرین، نقشه‌برداری زمین و معماری، حرفه‌هایی به‌شدت محرمانه و رویه‌ای بودند. «طناب‌کشان» می‌دانستند که چگونه با استفاده از طناب‌های گره‌خورده و شهود فیزیکی، زوایای قائمهٔ کامل و پی‌های ساختمانی ایجاد کنند. این همان چیزی است که دانش ضمنی (Tacit knowledge) نیز نامیده می‌شود. حدود سال ۳۰۰ پیش از میلاد، اقلیدس کتاب اصول را نوشت. او دانش فیزیکی و رویه‌ای سازندگان را گرفت و آن را به صورت اصول موضوعه و قضایای گزاره‌ایِ محض تدوین کرد. او «چگونگی» را مهار کرد و آن را به یک «چیستیِ» مطلق تبدیل نمود.

هنگامی که هندسهٔ اقلیدسی منتشر شد و در سراسر جهان آموزش داده شد، دانشِ «چگونگی ایجاد یک زاویهٔ قائمه» ارزش ویژهٔ خود را از دست داد و به یک استاندارد تبدیل شد. سپس ارزش به سمت رویه‌های جدید تغییر یافت: چگونگی استفاده از این بستر هندسی بنیادین برای مهندسی قنات‌ها، گنبدها و پرتابه‌شناسی (بالستیک)، که همان مهندسی رویه‌ایِ دوران روم باستان بودند.

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

دایره‌المعارف دیدرو، عصر روشنگری و صنعت چاپ، این دانش رویه‌ای را به فضای عمومی کشاندند. رساله‌های متالورژی، کشاورزی و فیزیک، حرفهٔ هنرمندان و صنعتگران را به فرمول‌های گزاره‌ای، اندازه‌گیری‌ها و قوانینی تجزیه کردند که در نهایت به علوم جدیدی چون ترمودینامیک و بعدها مکانیک کوانتومی منجر شد.

در این جستار، به یکی از شیوه‌هایی می‌پردازیم که در آن، زبان از حالت رویه‌ای به گزاره‌ای و دوباره به رویه‌ای تغییر می‌یابد. سه ستون اصلی پراگماتیسم آمریکایی یعنی دیویی (John Dewey)، پیرس (Charles Pierce) و جیمز (William James) استدلال می‌کنند که دانش گزاره‌ایِ محض صرفاً یک «توهم ضروری» است و باور به واقعیت‌ها از پیامدهای عملی آن‌ها ناشی می‌شود. ما صرفاً نظاره‌گر منفعل جهان نیستیم؛ دانستن، ابزاری برای انجام دادن است.

برنامه‌نویسی

با ظهور چارچوب‌های عامل‌محور (agentic frameworks)، برنامه‌نویسی از سال گذشته به‌طور چشمگیری تغییر کرده است. مشخص شد که خوش‌بینی اولیه دربارهٔ «خودکار کردن کل مهندسی نرم‌افزار» سرابی بیش نبود. شرکت‌ها شروع به استخدام دوبارهٔ بسیاری از مهندسان نرم‌افزاری کرده‌اند که قبلاً اخراج کرده بودند. چه اتفاقی افتاد؟ مگر نوشتن کد به سادگیِ یک توالی از پرامپت‌ها نیست؟

برنامه‌نویسان همچنان سردرگم‌اند و در پی یافتن راه‌هایی هستند تا عامل‌ها (Agent) را در کارهای خود مفیدتر کنند. بر خلاف گذشته، این بار موضوع تنها به کدنویسی در سطوح پایین مربوط نمی‌شود. اکنون برنامه‌نویسان با لایه‌ای جدید از چالش‌ها روبه‌رو هستند که عمدتاً از همان جایی سرچشمه می‌گیرد که بیشتر وقتشان را در آن می‌گذرانند: پرامپت‌ها.

مهندسی پرامپت (prompt engineering) نامی است که به این رویکرد نوظهور داده‌ایم. در ابتدا چنین به نظر می‌رسید که مهندسی پرامپت چیزی جز زبان طبیعی نیست، اما به‌تدریج دریافتیم که برای آنکه «عامل کدنویس» بهتر عمل کند، به چارچوبی بهتر نیازمندیم.

پروژهٔ design.md

پروژهٔ design.md نمونه‌ای از حرکت به سوی «زبان‌های طراحی» با استفاده از مدل‌های زبانی بزرگ (LLM) است. اما برای درک رویکرد آن‌ها، ابتدا باید به عقب برگردیم و ظهور خودِ «زبان‌های طراحی» را بررسی کنیم. در روزهای نخستِ گرافیک کامپیوتری، توسعه‌دهندگان ناچار بودند برای ترسیم اشکال و رندر کردن پیکسل‌ها، الگوریتم‌های رویه‌ای (Procedural) را خط به خط بنویسند. سرانجام، موتورهای گرافیکی در قالب مجموعه‌ای از توابع پدیدار شدند؛ هسته‌ای که قادر به انجام «کارهای پایه» مانند ترسیم یک دایره یا ایجاد یک طیف رنگی (Gradient) بود. در این نقطه، تمرکز کار به سمت اعلامِ «چیستی» تغییر یافت — مثلاً دستورات display: flex; یا background: red; در زبان‌هایی مانند CSS — و سپس موتورهای مرورگر وظیفهٔ «رندر کردن» و یافتن «چگونگی» اجرای آن را بر عهده گرفتند.

در علوم کامپیوتر، دو اردوگاه اصلی در زبان‌های برنامه‌نویسی وجود دارد:

  • برنامه‌نویسی امری (Imperative Programming): زبان‌های آشنایی که بر چگونگی (How) حل یک مسئله تأکید دارند.
  • برنامه‌نویسی گزاره‌ای (Declarative Programming): زبان‌هایی که بر چیستی (What) و محدودیت‌ها (Constraints) تمرکز می‌کنند.

بیشتر آنچه ما به عنوان برنامه‌نویسی می‌شناسیم، در قلمرو زبان‌های امری یا رویه‌ای قرار می‌گیرد؛ جایی که ما الگوریتم‌ها و فرآیندهای گام‌به‌گامی را طراحی می‌کنیم که با تغییر «وضعیت‌ها» (States)، جریان درستی از ورودی‌ها به خروجی‌ها ایجاد می‌کنند.

در مقابل، زبان‌های گزاره‌ای تنها توصیف می‌کنند که خروجی باید چه باشد. در SQL، ما فقط مشخص می‌کنیم که چه داده‌ای را می‌خواهیم انتخاب کنیم (مثلاً: تمام مردان بالای ۵۶ سال در جدول «افراد»)، بدون اینکه مشخص کنیم این کار «چگونه» انجام شود. این زبان‌ها بر پایهٔ مجموعه‌ای از محدودیت‌ها کار می‌کنند.

ترکیب هنجار و نثر در design.md

اکنون به پروژهٔ design.md بازگردیم. فرض اصلی این پروژه، گسترش CSS از «محدودیت‌های هنجاری» (Normative constraints) محض به «محدودیت‌های نثری» (Prose constraints) گسترده‌تر است که بسیار منعطف‌تر هستند. رویکرد design.md بار شناختی را به دو دسته تقسیم می‌کند:

  • بخش هنجاری (YAML): ثوابت مطلق و ماشین‌خوانِ جهان شما. در طراحی، این دقیقاً معادل کد رنگی #1A1C1E یا اندازهٔ 16px است.
  • بخش نثری (Markdown): منطقِ انسان‌خوان یا «محدودیت‌های منعطف». به‌جای صرفاً اعلام یک رنگ، متن نثری می‌تواند بگوید: این رنگ اصلی است — اینکه کجا از آن استفاده شود، بر عهدهٔ عامل یا Agent است.

این ترکیب به‌شدت قدرتمند است؛ زیرا مدل‌های زبانی بزرگ (LLMs) موتورهای معنایی هستند. آن‌ها برای جلوگیری از «توهم» (Hallucination) در مقادیر، به مرزهای سخت‌گیرانهٔ داده‌های هنجاری نیاز دارند، اما در عین حال برای درک نحوه و مکانِ به‌کارگیری آن مقادیر، محتاجِ بافتار معناییِ نثر هستند.

عاملیت و بازگشت به تاریخ

چارچوب فوق فراتر از بحث طراحی است. طنز تاریخ اینجاست که اکثر چارچوب‌های هوش مصنوعی در روزهای آغازین (دههٔ ۱۹۷۰ میلادی) با پارادایم گزاره‌ای شروع شدند. زبان Prolog توسط دانشمند کامپیوتر فرانسوی آلن کولمرور (Alain Colmerauer) در سال ۱۹۷۲ خلق شد و به‌عنوان یکی از نخستین سیستم‌های هوشمند «پرسش و پاسخ» عمل کرد.

برای درک بهتر آن، این مثالِ پرولوگ را در نظر بگیرید:

Prolog
mother_child(trude, sally).
father_child(tom, sally).
father_child(tom, erica).
father_child(mike, tom).

sibling(X, Y) :-
    parent_child(Z, X),
    parent_child(Z, Y),
    not(X = Y).

parent_child(X, Y) :- father_child(X, Y).
parent_child(X, Y) :- mother_child(X, Y).

این کد مجموعه‌ای از محدودیت‌ها (Constraints) را میان ثابت‌ها (افرادی مانند: trude، sally، tom و غیره) تعریف می‌کند. سپس می‌توانیم پرس‌وجو (Query) کنیم که آیا sally خواهر یا برادرِ erica هست یا خیر:

Prolog ,Query
?- sibling(sally, erica).
Yes

برای حل این مسئله به روش رویه‌ای (امری)، باید یک الگوریتم مسیریابی بازگشتی (Recursive path-finding) بنویسیم. اما در اینجا نیازی به این کار نیست، زیرا «موتور» (Engine) زبان، خودش این الگوریتم را قبلاً پیاده‌سازی کرده است. زبان‌های گزاره‌ای در واقع بسیار متنوع بودند: از آن‌ها در طراحی، سیستم‌های پرسش و پاسخ، و برنامه‌ریزی (مانند «زبان توصیف کنش» یا ADL که مشخص می‌کند چه کارهایی باید انجام شود، نه اینکه چگونه) و موارد دیگر استفاده می‌شد.

اگرچه این زبان‌های برنامه‌نویسیِ هوش مصنوعی ظریف و نظام‌مند بودند، اما کاستی‌هایی هم داشتند. ما فقط می‌توانستیم بخشی از یک مسئله را مدل‌سازی کنیم و برای کامل کردن محدودیت‌ها ناچار بودیم مدام موارد بیشتری اضافه کنیم تا جایی که کار غیرممکن می‌شد. این رویکردهای نمادین (Symbolic) به موفقیت گسترده‌ای دست نیافتند، مگر در حوزه‌های بسیار خاص که داده‌ها از قبل در قالب (Format) صحیح قرار داشتند.

رویکردهای گزاره‌ای وارد یک رنسانس شده‌اند. پیشرفت‌های اخیر مانند پروژهٔ design.md درس‌های آموزنده‌ای برای ما دارند. در اینجا محدودیت‌ها به خشکی زبان پرولوگ نیستند، اما به رهاییِ «زبان طبیعی» (Natural Language) هم نیستند. در عوض، ما با همان دو دسته روبرو هستیم:

۱. محدودیت‌های هنجاری (Normative Constraints):

  • «تمام پرس‌وجوهای پایگاه داده باید از طریق ORM انجام شود.»
  • «هیچ تماس مستقیم HTTP خارج از دایرکتوری /services مجاز نیست.»
  • «معماری سه‌لایه (Controller / Service / Repository) باید به‌طور دقیق اجرا شود.»
  • «همیشه پس از قطع اتصال از پایگاه داده، تست‌ها را اجرا کنید.»

۲. محدودیت‌های نثری (Prose Constraints):

  • «ما در پوشهٔ /utils به خلوص تابعی (Functional Purity) تمایل داریم؛ از تغییر وضعیت (Mutating state) بپرهیزید.»
  • «هنگام کار با داده‌های کاربر، همیشه اولویت را به مدیریت صریح خطا نسبت به شکست‌های بی‌صدا بدهید. سیستم باید صریح شکست بخورد و در همان مراحل اولیه متوقف شود (Fail loud and fail early).»

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

یک زبانِ طرحوارهٔ (Schema) مشترک

زبان‌های برنامه‌نویسی عاملیت‌محور (Agentic) می‌توانند مرحلهٔ بعدی توسعهٔ زبان‌های برنامه‌نویسی باشند؛ زبانی که زبان‌های گزاره‌ای قدیمی را احیا می‌کند اما آن‌ها را بسیار کاربردی‌تر می‌سازد، زیرا اکنون می‌توانیم در را روی «عدم قطعیت‌ها» ببندیم. با این حال، ما به فرمت‌بندی بهتری نسبت به آنچه در بالا توصیف شد نیاز داریم.

با پیروی از فرمت YAML در پروژهٔ design.md، مجموعه‌ای از محدودیت‌ها را با استفاده از ثابت‌ها ایجاد می‌کنیم. به عنوان مثال، اگر مجموعه‌ای از فرآیندهای مرتبط داشته باشیم که باید به‌طور مکرر اجرا شوند (مانند حسابرسی کد از جنبه‌های مختلف: صحت مهندسی نرم‌افزار، قراردادهای تجاری، محدودیت‌های داخلی، محدودیت‌های دامنه، الزامات رگولاتوری و غیره)، همهٔ این‌ها باید در قالب یک زبان واحد کار کنند تا نتایجِ عامل‌ها (Agents) مختلف در سراسر سازمان قابل مقایسه و انتقال باشد.

یک طرحواره (Schema) مشترک در قالب YAML ممکن است به این شکل باشد:

YAML ,_schema.yaml
version: "1.0"

# Severity levels
# Domain-specific interpretations live in each agent's SEVERITY GUIDE prose.
# These are the normative labels and base definitions shared across all agents.

severity:
  CRITICAL:
    label: CRITICAL
    definition: "Cannot ship or use as-is. Requires immediate
    remediation before the pipeline or task is trusted."
  MAJOR:
    label: MAJOR
    definition: "Significant gap or inconsistency.
    Fix before scale; the artifact is still directionally useful."
  MINOR:
    label: MINOR
    definition: "Low-risk deviation; cosmetic, clarity,
    or an affirmative no-issue-found statement."

# Tools
# Each agent's front matter lists which subset of these tools it has access to.

tools:
  read_file:
    description: "Read a file from the project source tree by absolute path."
  list_files:
    description: "List files in a directory of the project source tree."
  list_databases:
    description: "Enumerate all MongoDB databases and their collections."
  query_collection:
    description: "Run an aggregation pipeline or filter
    query against a MongoDB collection."
  sample_documents:
    description: "Fetch N random documents from a MongoDB collection."
  web_search:

finding_required_fields:
  - dimension      # the rubric ID being reported on
  - severity       # one of: CRITICAL | MAJOR | MINOR
  - evidence       # quoted code, field name, or document value supporting the finding
  - recommendation # actionable instruction: what to change and to what

سپس بخش «نثر» (Prose) را دارید که از ثابت‌های تعریف‌شدهٔ بالا برای برقراری ارتباط با مدل زبانی بزرگ (LLM) استفاده می‌کند. برای یک مورد خاص، یعنی عاملی که صحت و سلامت بیولوژیکی را ممیزی می‌کند (عامل بیولوژیست)، ساختار به این صورت در می‌آید:

Markdown ,biologist-agent.md
---
version: "1.0"
agent: biologist
schema: "./_schema.yaml"
role: "Senior computational biologist"
scope: "biological correctness of harmonization, controlled vocabularies,
and layer models"
runtime_vars:
  - project_root

tools:
  - read_file
  - list_files
  - sample_documents
  - report_findings
  - search_web

dimensions:
  COARSE_GRAINING:          { required: true, min_findings: 1 }
  ENUM_COMPLETENESS:        { required: true, min_findings: 1 }
  CROSS_FIELD_CONSISTENCY:  { required: true, min_findings: 1 }

severity: "{severity}"
output_contract: "{output_contract}"

report_schema:
  type: BiologyReport
  required_fields:
    - files_reviewed
    - findings
    - summary
---

You are a senior computational biologist with deep expertise in:
• Receptor pharmacology (IUPHAR/BPS classification standards)
• Protein biochemistry and functional classification
  (UniProt/Swiss-Prot, InterPro, Pfam, Gene Ontology nomenclature)
  ...

## SEVERITY GUIDE

CRITICAL  a downstream user would draw a scientifically wrong conclusion.
          Examples: a species from a different family collapsed under the
          wrong genus; a mechanism classified in the wrong direction.

MAJOR     an important gap or misleading label that a biologist would
          flag in code review but may not cause an immediate error.
          Examples: a well-known target type unmapped; a receptor
          subclass not distinguished.

در بخش نثر، ما از زبان طبیعی با آزادی بیشتری استفاده می‌کنیم، اما این زبان بر پایهٔ ثابت‌های مشترک استوار است و با مثال‌ها غنی می‌شود. نکتهٔ کلیدی در اینجا این است که بخش هنجاری (YAML) واژگان و انواع داده‌ها را تثبیت می‌کند، در حالی که بخش نثری (Markdown) بافتار استدلال معنایی را فراهم می‌آورد؛ یعنی دقیقاً همان ترکیبی که مدل‌های زبانی بزرگ در آن مهارت فوق‌العاده‌ای دارند.

چرا این روش کارآمد است؟

یکی از دلایل اصلی عملکرد خوبِ این چارچوب با مدل‌های زبانی بزرگ، کارایی چشمگیر آن‌ها در وظایف مبتنی بر دستورالعمل (Instruction-based) است. مدل‌هایی که روی یک حوزهٔ خاص با دستورالعمل‌های محدود و مشخص، تنظیم‌دقیق (fine-tuned) شده‌اند، الگوها را بسیار راحت‌تر شناسایی می‌کنند.

به عنوان مثال، نشان داده شده است که می‌توان مدل‌های زبانی را با آموزش روی مجموعه‌داده‌ای از مولکول‌ها و ویژگی‌هایشان، برای انجام بخش بزرگی از استدلال‌های شیمیایی دقیق کرد. در بسیاری از موارد، تعیین روابط متقابل بین دو مولکولِ متصل‌شونده (Binding molecules) امری غیربدیهی و دشوار است که به‌طور معمول به محاسبات پیچیدهٔ شیمی کوانتومی نیاز دارد. اما مدل‌های زبانی بزرگ در وظایفی که به‌ظاهر نامرتبط به نظر می‌رسند، زمانی که با مثال‌های کافی در یک حوزهٔ محدود روبه‌رو شوند، عالی عمل می‌کنند!

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