# به المپیک ایجنتهای NLP خوش آمدید!
بسیار خوشحالیم که در مسابقه بزرگ ایجنتهای NLP همراه ما هستید. این رویداد فرصتی بینظیر برای به چالش کشیدن مهارتها، یادگیری عمیق در زمینه پردازش زبان طبیعی و ساخت ایجنتهای هوشمند است. چه یک متخصص باتجربه در زمینه LLMها باشید و چه به تازگی وارد این دنیای شگفتانگیز شده باشید، این مسابقه برای شما طراحی شده تا از حل مسائل پیچیده و رقابت با بهترینها لذت ببرید.
در این رقابت، شما وظیفه ساخت یک **ایجنت هوشمند** را بر عهده دارید که باید از سد مجموعهای از چالشهایی با تمرکز روی NLP (قفلها) عبور کند. ایجنت شما باید بتواند مسائل را تحلیل کند، از ابزارهای مختلف استفاده کند و بهترین راهحل را برای باز کردن هر قفل پیدا کند.
## ساختار مسابقه
این مسابقه در دو فاز برگزار میشود:
### فاز اول: مرحله انتخابی
در این مرحله، ایجنت شما باید به صورت خطی با مجموعهای از **قفلها** روبرو شود. هر قفل، یک مسئله منحصربهفرد است که برای حل آن به ترکیبی از تحلیل متن، استدلال منطقی، و استفاده از ابزارها نیاز است.
+ **هدف:** حل کردن موفقیتآمیز تمام قفلها به ترتیب.
+ **امتیازدهی:** امتیاز نهایی شما بر اساس ترکیبی از عوامل زیر محاسبه میشود:
+ تعداد قفلهای باز شده.
+ تعداد تلاشهای ناموفق برای هر قفل (امتیاز منفی).
+ تعداد راهنماییهای (Hint) استفاده شده (امتیاز منفی).
+ **ملاک سنجش:** در این فاز، تواناییهای بنیادی ایجنت شما مانند درک مسئله، کار با ابزارها (مثل خواندن فایل از URL) و استفاده از تاریخچه مکالمات برای یادگیری از اشتباهات، ارزیابی میشود.
### فاز دوم: مرحله نهایی
<details class="red">
<summary>
\**نکتهی بسیار مهم**
</summary>
برای این بخش نیاز نیست شما به صورت کلی کدتون رو تغییر بدید، در این فاز صرفا قفلها **چالشی تر** میشود و متد **choose_path** هم استفاده میشود. که در قسمت فاز دو، توضیحات به صورت کامل آورده شده است.
</details>
\**۸ ایجنت برتر** از مرحله اول به این فاز راه پیدا میکنند. در این مرحله، ۴ ایجنت به صورت همزمان در یک **ماز (Maze)** زنده و پویا با یکدیگر به رقابت میپردازند.
+ **هدف:** قبل از شروع رقابت، یک سوال استراتژیک از ایجنتها پرسیده میشود تا مسیر خود را در ماز انتخاب کنند. پس از انتخاب مسیر، رقابت برای رسیدن به هدف نهایی در ماز آغاز میشود.
+ **ملاک سنجش:** این فاز آزمونی برای سنجش قدرت تصمیمگیری لحظهای، انتخاب استراتژی بهینه و عملکرد ایجنت در یک محیط رقابتی و پویا است.
## توضیحات فنی
برای موفقیت در این مسابقه، ایجنت شما باید نیازمندیهای فنی مشخصی را برآورده کند.
### نیازمندیهای ایجنت
فایل ارسالی شما باید با نام `solution.py` شامل کلاسی به نام `ContestantAgent` با ساختار زیر باشد:
```py
class ContestantAgent:
def __init__(self, api_key: str):
# پیادهسازی شما برای مقداردهی اولیه ایجنت
# شامل تعریف مدل، ابزارها و ...
def solve_lock(self, problem: Dict[str, Any], history: List[Tuple[str, str]]) -> str:
# پیادهسازی شما برای حل یک قفل
# این متد باید پاسخ نهایی را به صورت یک رشته برگرداند
def choose_path(self, scenario_prompt: str) -> List[str]:
# پیادهسازی شما برای انتخاب مسیر در فاز دوم
```
### محیط توسعه و داوری
+ توجه کنید که **در کل مسابقه فقط 3 دلار اعتبار در محیط داوری دارید** و این اعتبار رو باید تا پایان مسابقه مدیریت کنید.
+ پس از هر ارسال، با کلیک بر روی **نمرهی خود** در ستون «وضعیت» از بخش «**همهی ارسالها**» میتونید میزان اعتبار باقیماندهی اختصاص یافته به خود را مطابق تصویر زیر مشاهده کنید.

+ دقت کنید که در کد ارسالی حتما مقدار base_url را برابر با
"https://api.metisai.ir/openai/v1 قرار دهید و حتما از توکن داده شده در ورودی سوال استفاده کنید. استفاده از توکنهای لوکال در جوابهای ارسالی ممنوع میباشد.
#### قوانین استفاده از LLM
+ در این مسابقه حتما باید از مدل `gpt-4.1-mini` استفاده کنید.
+ میتوانید tools جدید بنویسید و از آن استفاده کنید اما استفاده از از tool های آمادهی LLM مانند web_search ،file_search و ... مجاز نیست. ( در صورت مشاهده، دیسکوالیفای میشود)
+ حالت stream پیشتیبانی نمیشود.
### نحوه ارسال پاسخ
شما باید یک فایل `zip` با ساختار زیر ارسال کنید:
```
solution.zip
├── solution.py
└── python_requirements.txt
```
### نمونه پاسخ با استفاده از `pydantic-ai`
برای استفاده از pydantic-ai باید خط زیر را در فایل `python_requirements.txt` قرار دهید:
```txt python_requirements.txt
pydantic-ai-slim[openai]
```
سپس به صورت زیر از آن استفاده کنید.
\**توجه: هنگام ایجاد `OpenAIProvider` مقدار http_client را حتما به صورت دستی در آن ست کنید وگرنه کد شما در سامانهی داوری به درستی اجرا نمیشود!**
این یک قالب کلی از ساختار `solution.py` است که از شما انتظار میرود.
```py
import os
from typing import Dict, Any, List, Tuple
from pydantic_ai import Agent, RunContext
from pydantic_ai.models.openai import OpenAIChatModel
from pydantic_ai.providers.openai import OpenAIProvider
class ContestantAgent:
def __init__(self, api_key: str):
if not api_key:
raise ValueError("OpenAI API key is required.")
provider = OpenAIProvider(api_key=api_key,
base_url="https://api.metisai.ir/openai/v1",
http_client=httpx.AsyncClient()) # Don't forget!
model = OpenAIChatModel(provider=provider,
model_name="gpt-4.1-mini")
self.agent = Agent(
model=model,
system_prompt=(
"You are an expert problem-solving assistant. Your goal is to provide "
"only the final, precise answer..."
)
)
def solve_lock(self, problem: Dict[str, Any], history: List[Tuple[str, str]]) -> str:
prompt = self._construct_prompt(problem, history)
try:
result = self.agent.run_sync(prompt)
return str(result.output)
except Exception as e:
return f"Agent execution failed with an error: {e}"
def _construct_prompt(self, problem: Dict[str, Any], history: List[Tuple[str, str]]) -> str:
description = problem.get('description', '')
files = problem.get('input_files', [])
for file in files:
name = file['filename']
file_type = file['type']
url = file['url']
return "A well-formed prompt for the agent."
def choose_path(self, scenario_prompt: str) -> List[str]:
return ["Path_A"]
```
موفق و پیروز باشید و از این چالش لذت ببرید!
# فاز ۱: مرحله انتخابی
این مرحله، آزمون اصلی تواناییهای بنیادی ایجنت شماست. در اینجا، ایجنت به صورت متوالی با مجموعهای از **قفلها (Locks)** روبرو میشود و باید آنها را به ترتیب باز کند. عبور موفقیتآمیز از تمام قفلها، جواز ورود شما به مرحله نهایی خواهد بود.
## نیازمندیهای فاز ۱
ایجنت شما باید بتواند:
+ یک **`prompt` متنی** به عنوان ورودی دریافت کرده و نیازمندیهای مسئله را از آن استخراج کند.
+ با استفاده از ابزارها، اطلاعات مورد نیاز از URLهایی که در `prompt` ذکر شده را استخراج کند.
+ تاریخچه تلاشهای ناموفق (`history`) را تحلیل کرده و از آن برای بهبود پاسخهای بعدی استفاده کند.
+ پاسخ نهایی را در قالب خواستهشده (متن، عدد و...) به صورت یک رشته برگرداند.
## ابزارهای مورد نیاز
برای موفقیت در این چالش، ایجنت شما حداقل به ابزارهای زیر نیاز خواهد داشت:
+ **ابزار خواندن/دانلود محتوای وب:** این ابزار باید بتواند محتوای یک URL را دریافت کند. این قابلیت برای خواندن فایلهای `.txt` و همچنین تعامل با APIهای ساده ضروری است.
- توانایی یک سری عملیات (مانند کلیک کردن) بر روی سایت انجام دادن. ( عملیات مورد نظر در پرامپت گفته میشود.).
- توانایی شمردن یک موجودیت در یک یا چند سایت.(اسم فیلد در داخل پرامپت ورودی ذکر میشود.)
+ **ابزار تحلیلگر CSV:** یک ابزار تخصصی برای کار با فایلهای CSV. این ابزار باید بتواند یک فایل CSV را از URL بخواند، آن را تحلیل کرده و یک خلاصه مفید (مانند هدرها، تعداد سطرها و چند نمونه داده) برای LLM آماده کند تا از محدودیت توکن جلوگیری شود. همچنین این ابزار باید بتواند کارهای زیر را انجام دهد :
- پاسخ دادن به سوالات در بارهی اطلاعات کلی یک فایل.
- پاسخ دادن به اطلاعات موجود برای یک ID خاص.(اسم فیلد در داخل پرامپت ورودی ذکر میشود.)
+ **ابزار ارسال درخواست به API:** این ابزار باید بتواند یک API call به URI داده شده داخل پرامپت به همراه پارامترهای مورد نیاز ارسال بکند.
+ **ابزار ماشین حساب:** این ابزار باید بتواند محسابات ریاضی که مدلهای زبانی به راحتی نمیتوانند انجام بدهند رو انجام بدهد. همچنین این ابزار توانایی لازم برای انجام دادن تسکی مانند زیر را داشته باشد :
تبدیل محاسبات از زبان فارسی به اعداد و عملیاتها،سپس انجام محاسبات.
- مثال: دو بهعلاوه دو -> 4
<details class="red">
<summary>
**نکتهی بسیار مهم**
</summary>
مدل شما تنها باید جواب خروجی را برگرداند یا از محافظ درخواست راهنمایی کند(برای فاز ۲).
</details>
## ورودی و خروجی نمونه
سیستم داوری، اطلاعات موجود در هر قفل را به یک `prompt` متنی تبدیل کرده و به عنوان ورودی به متد `solve_lock` شما ارسال میکند. ایجنت شما آبجکت کامل `JSON` را دریافت **نمیکند**.
\**نمونه پرامپت ورودی برای متد `solve_lock`:**
```
how many rows are there in the provided CSV file?
https://gist.githubusercontent.com/rnirmal/e01acfdaf54a6f9b24e91ba4cae63518/raw/6b589a5c5a851711e20c5eb28f9d54742d1fe2dc/datasets.csv
```
\**خروجی نمونه از متد `solve_lock`:**
```
"61"
```
# فاز ۲: مرحله نهایی
\**۸ ایجنت برتر** از مرحله اول به این فاز راه پیدا میکنند. این مرحله شامل سه رقابت زنده و استراتژیک بین چهار ایجنت است. هر شرکتکننده یک نقشه دریافت میکند که در آن هر مسیر توسط یک **ایجنت محافظ** قدرتمند محافظت میشود. اینجا دیگر فقط بهینهسازی مسیر مهم نیست، بلکه باید با تحلیل نقاط ضعف محافظان، هوشمندانهترین مسیر را برای رویارویی انتخاب کنید.
## نیازمندیهای فاز ۲
ایجنت شما باید بتواند:
+ یک `prompt` متنی که شامل نقشه، مسیرها و توضیحات فنی ایجنتهای محافظ است را به طور کامل تحلیل کند و **استراتژیکترین** مسیر را برای شروع انتخاب کند و خروجی را در قالب یک لیست از رشتهها (شامل نام مسیر انتخابی) برگرداند.
+ مانند فاز یک بر اساس مسیر انتخاب شده قفلها را حل کند و با ایجنت محافظ تعامل کند.
## نحوه برگزاری مسابقه
1. **دریافت نقشه و انتخاب مسیر:** در لحظه شروع رقابت، سیستم داوری متد `choose_path` ایجنت شما را فراخوانی کرده و یک `prompt` متنی حاوی تمام جزئیات سناریو (نقشه، مسیرها، ویژگیهای محافظان و...) را به عنوان آرگومان به آن پاس میدهد. ایجنت شما باید در همان لحظه سناریو را تحلیل کرده و نام مسیر انتخابی خود را برگرداند.
2. **اجرای رقابت:** پس از اینکه تمام ایجنتها مسیر خود را انتخاب کردند، رقابت به صورت زنده شبیهسازی میشود. ایجنت شما با ایجنت محافظ مسیر انتخابی روبرو میشود.
3. **ساختار مسابقات:** مسابقات به صورت گروهی و حذفی برگزار میشود تا در نهایت قهرمان نهایی مشخص شود.
## معرفی ایجنتهای محافظ
<details class="blue">
<summary>
\**Deceiver Guard**
</summary>
ایجنتهای جستجوگر رو با جوابهای نیمه درست گمراه میکنه.
</details>
<details class="blue">
<summary>
\**Riddler Guard**
</summary>
فقط در قالب معما(riddle) جواب میده.
</details>
<details class="blue">
<summary>
\**Silent Guard**
</summary>
فقط با بله/خیر جواب میده.
</details>
<details class="red">
<summary>
\**Evil Twins**
</summary>
دو برادر مرموز،یکیشون راست میگه و یکی دروغ.
</details>
## ورودی و خروجی نمونه
در این فاز، متد `choose_path` یک `prompt` متنی به عنوان ورودی مستقیم دریافت میکند.
\**ساختار متد در `solution.py`:**
```
def choose_path(self, scenario_prompt: str) -> List[str]:
# Agent's logic to analyze the prompt and choose a path
...
```
\**نمونه `scenario_prompt` ورودی:**
```
You are facing the Gauntlet of Guardians. Analyze the following scenario and choose the path that your agent is best equipped to handle.
Scenario: The Oracle's Test
- **Objective:** Acquire the 'Key of Truth'.
- **Paths Available:**
- **PathA (The Silent Library):** Protected by the 'Silent Guard'. To find the key, you must ask a series of precise yes/no questions to locate it among thousands of books. This path tests logical deduction and process of elimination.
- **PathB (The Twin Gates):** Protected by the 'Evil Twins'. One gate leads to the key, the other to failure. You can ask only one question to one of the twins to determine the correct gate. This path tests classic logical puzzle-solving.
- **PathC (The Whispering Gallery):** Protected by the 'Riddler Guard'. The location of the key is hidden within a complex riddle. This path tests creative interpretation and understanding of abstract language.
Based on your agent's strengths, which path offers the highest probability of success: PathA, PathB, or PathC?
```
\**خروجی نمونه از متد `choose_path`:**
خروجی باید یک لیست پایتون باشد که شامل یک رشته است. این رشته، نام مسیر انتخابی ایجنت است.
```
["PathB"]
```
## نحوه امتیازدهی و شرایط برد و باخت
+ **امتیازدهی:** امتیازدهی بر اساس موفقیت در رقابت است.
+ **شرایط برد و باخت:**
+ **برد:** در هر رقابت، ایجنتی که بتواند ایجنت محافظ مسیر خود را **شکست دهد** (یعنی پاسخهای صحیح را از او استخراج کند)، برنده آن دور از رقابت خواهد بود و به مرحله بعد صعود میکند. اگر چند ایجنت موفق شوند، ایجنتی که در زمان کمتری این کار را انجام دهد، برنده است.
+ **باخت:** ایجنتی که در مقابل محافظ خود شکست بخورد، از دور مسابقات حذف میشود.