تصویر از طریق Unsplash.
تصویر از طریق Unsplash.

مقدمه‌ای بر SDK و API پاسخ‌های OpenAI Agents

همزمان با معرفی SDK Agents توسط OpenAI, این شرکت اذعان کرد که استفاده از قابلیت‌های موجود به صورت یکپارچه «می‌تواند چالش‌برانگیز باشد و اغلب به تکرار گسترده پرامپت (prompt) و منطق ارکستراسیون سفارشی بدون دید کافی یا پشتیبانی داخلی نیاز دارد.» به طور خلاصه، استفاده از عامل‌ها (agents) به کمی برنامه‌نویسی نیاز داشت و این چیزی نیست که هیچ ارائه‌دهنده هوش مصنوعی بخواهد بفروشد.

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

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

برای شروع سفر ارکستراسیون، OpenAI APIهای جدیدی را به پلتفرم اصلی خود اضافه کرده است. به طور خاص، یک API پاسخ‌ها (Responses API) اساسی معرفی کرده است که برخی از فرضیات مطرح‌شده توسط عامل‌های گفتگو (chat agents) را برطرف می‌کند.

به ساده‌ترین شکل، این API می‌تواند خروجی را ثبت کند:

from openai import OpenAI
client = OpenAI()

response = client.responses.create(
 model="gpt-4o",
 input="Write a one-sentence bedtime story about a unicorn."
)

print(response.output_text)

شما می‌توانید تصاویر را در این سطح تجزیه و تحلیل کنید و یکی از ابزارهای زیر را اضافه کنید. هشدار: مدل‌های جدید احتمالاً از پشتیبانی از Chat Completions API موجود دست خواهند کشید - بسیاری از ویژگی‌های جدید فقط از Responses API جدید پشتیبانی می‌کنند.

بیایید نگاهی به این ابزارهای جدید بیندازیم. جستجوی وب (Web search) به یک عامل اجازه می‌دهد تا وب را برای انجام وظایف ساده جستجو کند. اسکریپت کوتاه پایتون زیر نشان می‌دهد که چگونه به یک مدل این امکان داده می‌شود که از این ابزار استفاده کند:

from openai import OpenAI
client = OpenAI()

response = client.responses.create(
 model="gpt-4o",
 tools=[{"type": "web_search_preview"}],
 input="What Kubernetes news story appeared today?"
)

print(response.output_text)

response همچنین حاوی ارجاعاتی به مقالات ذکر شده خواهد بود. این پرس و جوها را می‌توان بر اساس زمان یا مکان تعریف کرد. شما همچنین می‌توانید هزینه، کیفیت و تأخیر را وزن‌دهی کنید.

جستجوی فایل (File Search) در واقع یک مخزن برداری (vector store) میزبانی‌شده است. شما نشان می‌دهید که جستجوی فایل یک ابزار در دسترس است و مخزن برداری خود را مشخص می‌کنید:

from openai import OpenAI
client = OpenAI()

response = client.responses.create(
 model="gpt-4o-mini",
 input="What is deep research by OpenAI?",
 tools=[{
 "type": "file_search",
 "vector_store_ids": ["<vector_store_id>"]
 }]
)
print(response)

در صورت نیاز، یک عامل از آن استفاده خواهد کرد. پاسخ، اسناد استفاده‌شده در پاسخ را ذکر می‌کند. شما می‌توانید پاسخ‌ها را برای کنترل استفاده از توکن و تأخیر محدود کنید. محدودیت‌هایی برای کل اندازه فایل، فایل‌های جستجو شده و اندازه مخزن برداری وجود دارد. انواع اسنادی که قابل جستجو هستند (بر اساس نوع فایل) به نظر گسترده می‌رسند.

ابزار استفاده از کامپیوتر (Computer Use) جالب است:

«ابزار استفاده از کامپیوتر در یک حلقه پیوسته عمل می‌کند. این ابزار، اقدامات کامپیوتری مانند click(x,y) یا type(text) را ارسال می‌کند که کد شما آن را در یک محیط کامپیوتر یا مرورگر اجرا می‌کند و سپس اسکرین‌شات‌هایی از نتایج را به مدل بازمی‌گرداند.»

امتحان کردن عامل‌ها

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

نتیجه این بود که [email protected] 3.13.2 از قبل نصب شده و به روز است.

pip من نیز در آنجا وجود دارد (به عنوان pip3).

بنابراین اکنون می‌توانم بسته‌های OpenAI را نصب کنم:

آه، این را به یاد دارم. ما به یک virtual نیاز داریم:

سپس virtual را فعال می‌کنم:

و ما آماده ادامه هستیم.

اکنون، البته، شما باید از OPENAI_API_KEY استفاده کرده و آن را تنظیم کنید. من یک کلید جدید برای خودم در صفحه حساب خود ایجاد کردم و OPANAI_API_KEY را تنظیم کردم (نگران نباشید، بسیار طولانی‌تر از این است):

و شما باید مطمئن شوید که مقداری طلای سیاه دارید - منظورم توکن‌ها است. من برخی از راه‌های جلوگیری از پرداخت هزینه به OpenAI را با استفاده از مدل‌های محلی ارائه کرده‌ام، اما برای این پست فرض می‌کنم که شما برای توکن‌ها هزینه می‌پردازید.

طبق سنت، بیایید فقط با یک بررسی شروع کنیم که موارد اساسی فوق از طریق یک درخواست ساده با haiku.py زیر در جای خود قرار دارند:

from agents import Agent, Runner

agent = Agent(name="Assistant", instructions="You are a helpful assistant")

result = Runner.run_sync(agent, "Write a haiku about recursion in programming.")
print(result.final_output)

و ما یک پاسخ خوب دریافت می‌کنیم:

(یک هایکو سنتی خوب باید اشاره‌ای به فصل‌های گذرا داشته باشد، اما به همین دلیل اینجا نیستیم.) معمولاً، من موجودی خود را نیز بررسی می‌کنم - اما مختل نشده است.

لانه‌ای از عامل‌ها

همانطور که می‌بینید، ما قبلاً از یک عامل استفاده کرده‌ایم. نه اینکه به هیچ وجه مداخله کرده باشد، اما به آن خواهیم پرداخت.

OpenAI فرآیند ارکستراسیون را با برخی اصطلاحات ساده، ساده کرده است. یک تحویل (handoff) مقدمه‌ای برای دنیای ناهمزمان است، جایی که چیزی باید منتظر چیز دیگری بماند. بیایید مثال آن‌ها را تجزیه کنیم که من آن را به عنوان hola.py اجرا خواهم کرد:

from agents import Agent, Runner
import asyncio

spanish_agent = Agent(
 name="Spanish agent",
 instructions="You only speak Spanish.",
)

english_agent = Agent(
 name="English agent",
 instructions="You only speak English",
)

triage_agent = Agent(
 name="Triage agent",
 instructions="Handoff to the appropriate agent based on the language of the request.",
 handoffs=[spanish_agent, english_agent],
)

async def main():
 result = await Runner.run(triage_agent, input="Hola, ¿cómo estás?")
 print(result.final_output)

if __name__ == "__main__":
 asyncio.run(main())

این دو چیز اساسی را نشان می‌دهد. اول از همه تنظیم نقش برای عامل‌ها به زبان ساده انگلیسی که به آن عادت کرده‌ایم، اما همچنین تنظیم تعامل بین عامل‌ها. عامل تحویل لیستی از عامل‌های موجود را برای پاسخگویی به پاسخ‌ها نگه می‌دارد.

اکنون، این نشان می‌دهد که درخواست آلمانی من پاسخ درستی دریافت نخواهد کرد. بنابراین اگر پرس و جو را در hola.py تغییر دهیم:

...

async def main():
 result = await Runner.run(triage_agent,
 input="Wie geht es ihnen?")

...

و لانه‌ی عامل‌های خود را اجرا کنیم:

بنابراین، در حالی که OpenAI هیچ مشکلی در ترجمه آلمانی نداشت، عامل تریاژ هیچ عامل زبانی مرتبطی برای تحویل دادن نداشت، بنابراین کار را انجام داد و به انگلیسی پاسخ داد. بعید است که مشتریان آلمانی ما خیلی ناراحت شوند، اما می‌توانیم آن را بهبود بخشیم.

بنابراین اگر در نهایت عامل آلمانی را اضافه کنیم و آن را در لیست تحویل به hola.py قرار دهیم:

...
german_agent = Agent(
 name="German agent",
 instructions="You only speak German",
)

triage_agent = Agent(
 name="Triage agent",
 instructions="Handoff to the appropriate agent based on the language of the request.",
 handoffs=[spanish_agent, english_agent, german_agent],
)
...

می‌توانیم دوباره آن درخواست آلمانی را امتحان کنیم:

این بار عامل صحیح فراخوانی می‌شود و پاسخ می‌دهد. مشتریان آلمانی ما اکنون خوشحال‌تر هستند - ausgezeichnet! فراموش نکنید که ترمینال Warp من زمان این پاسخ‌ها را نیز به شما می‌دهد.

<a href="https://medium.com/@sahin.samia/building-ai-agents-with-openai-agents-sdk-a-step-by-step-guide-5f1a4f1133b3" rel="external">از طریق Sahin Ahmed</a>

نتیجه‌گیری

ما ابتدا به حلقه پاسخ نگاه کردیم که ممکن است شامل فراخوانی‌های ابزار بیشتری باشد. اگر پاسخ دارای تحویل باشد، عامل را روی عامل جدید تنظیم می‌کنیم و به ابتدا برمی‌گردیم.

گزینه‌های ورود به سیستم (logging) در زیر این وجود دارد، اما طبق معمول OpenAI در این مرحله یک API سطح بالا ارائه می‌دهد - که باید آزمایش را بدون نیاز به درگیر شدن بیش از حد در ارکستراسیون تشویق کند.

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