(انقر على الصورة أعلاه لمشاهدة فيديو هذا الدرس)
الأدوات مثيرة للاهتمام لأنها تسمح لوكلاء الذكاء الاصطناعي بامتلاك نطاق أوسع من القدرات. بدلاً من أن يكون للوكيل مجموعة محدودة من الإجراءات التي يمكنه القيام بها، بإضافة أداة، يمكن للوكيل الآن أداء مجموعة واسعة من الإجراءات. في هذا الفصل، سوف ندرس نمط تصميم استخدام الأدوات، الذي يصف كيف يمكن لوكلاء الذكاء الاصطناعي استخدام أدوات محددة لتحقيق أهدافهم.
في هذا الدرس، نسعى للإجابة على الأسئلة التالية:
بعد إكمال هذا الدرس، ستكون قادرًا على:
يركز نمط تصميم استخدام الأدوات على تمكين نماذج اللغة الكبيرة (LLMs) من التفاعل مع الأدوات الخارجية لتحقيق أهداف محددة. الأدوات هي شفرة يمكن تنفيذها بواسطة الوكيل لأداء إجراءات. يمكن أن تكون الأداة دالة بسيطة مثل آلة حاسبة، أو استدعاء لواجهة برمجة تطبيقات (API) لخدمة طرف ثالث مثل البحث عن سعر السهم أو توقع الطقس. في سياق وكلاء الذكاء الاصطناعي، تم تصميم الأدوات ليتم تنفيذها بواسطة الوكلاء استجابةً لـ مكالمات الدالة التي يولدها النموذج.
يمكن لوكلاء الذكاء الاصطناعي الاستفادة من الأدوات لإكمال مهام معقدة، استرجاع المعلومات، أو اتخاذ القرارات. يُستخدم نمط تصميم استخدام الأدوات غالبًا في السيناريوهات التي تتطلب تفاعلًا ديناميكيًا مع أنظمة خارجية مثل قواعد البيانات، الخدمات الويب، أو مفسرات الشفرات. هذه القدرة مفيدة لعدد من حالات الاستخدام المختلفة بما في ذلك:
تتيح هذه الكتل الإنشائية لوكيل الذكاء الاصطناعي أداء مجموعة واسعة من المهام. دعونا نلقي نظرة على العناصر الرئيسية اللازمة لتطبيق نمط تصميم استخدام الأدوات:
مخططات الدوال/الأدوات: تعريفات مفصلة للأدوات المتاحة، تتضمن اسم الدالة، الغرض، المعلمات المطلوبة، والمخرجات المتوقعة. تمكِّن هذه المخططات نموذج اللغة الكبير (LLM) من فهم الأدوات المتوفرة وكيفية إنشاء طلبات صحيحة.
منطق تنفيذ الدوال: تحكم في كيفية وموعد استدعاء الأدوات استنادًا إلى نية المستخدم وسياق المحادثة. قد يشمل ذلك وحدات التخطيط، آليات التوجيه، أو التدفقات الشرطية التي تحدد استخدام الأدوات بشكل ديناميكي.
نظام معالجة الرسائل: مكونات تدير تدفق المحادثة بين مدخلات المستخدم، استجابات نموذج اللغة الكبير، مكالمات الأدوات، ومخرجات الأدوات.
إطار تكامل الأدوات: البنية التحتية التي تربط الوكيل بالأدوات المختلفة، سواء كانت دوال بسيطة أو خدمات خارجية معقدة.
معالجة الأخطاء والتحقق: آليات للتعامل مع فشل تنفيذ الأدوات، التحقق من المعلمات، وإدارة الاستجابات غير المتوقعة.
إدارة الحالة: تتبع سياق المحادثة، التفاعلات السابقة مع الأدوات، والبيانات الدائمة لضمان الاتساق عبر التفاعلات متعددة الأدوار.
بعد ذلك، دعونا نلقي نظرة مفصلة على استدعاء الدوال/الأدوات.
استدعاء الدوال هو الطريقة الأساسية التي نرمّز بها تمكين نماذج اللغة الكبيرة (LLMs) من التفاعل مع الأدوات. ستلاحظ غالبًا استخدام ‘الدالة’ و’الأداة’ بالتبادل لأن ‘الدوال’ (كتل البرمجيات القابلة لإعادة الاستخدام) هي ‘الأدوات’ التي يستخدمها الوكلاء لأداء المهام. لكي يتم استدعاء شفرة دالة ما، يجب على نموذج اللغة الكبير مقارنة طلب المستخدم بوصافة الدالة. للقيام بذلك، يتم إرسال مخطط يحتوي على وصف كل الدوال المتاحة إلى نموذج اللغة الكبير. ثم يختار نموذج اللغة الكبير الدالة الأكثر ملاءمة للمهمة ويرجع اسمها ومعاملاتها. يتم استدعاء الدالة المختارة، ويتم إرسال استجابتها إلى نموذج اللغة الكبير، الذي يستخدم المعلومات للرد على طلب المستخدم.
لكي يتمكن المطورون من تنفيذ استدعاء الدوال للوكلاء، ستحتاج إلى:
لنستخدم مثال الحصول على الوقت الحالي في مدينة لتوضيح ذلك:
تهيئة نموذج LLM يدعم استدعاء الدوال:
ليست جميع النماذج تدعم استدعاء الدوال، لذا من المهم التحقق مما إذا كان النموذج الذي تستخدمه يفعل ذلك. يدعم Azure OpenAI استدعاء الدوال. يمكننا البدء بمبادرة عميل Azure OpenAI.
# تهيئة عميل Azure OpenAI
client = AzureOpenAI(
azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT"),
api_key=os.getenv("AZURE_OPENAI_API_KEY"),
api_version="2024-05-01-preview"
)
إنشاء مخطط دالة:
بعد ذلك سنقوم بتعريف مخطط JSON يحتوي على اسم الدالة، وصف ما تقوم به الدالة، وأسماء وأوصاف معلمات الدالة. ثم نأخذ هذا المخطط ونمرره إلى العميل المُنشأ سابقًا، إلى جانب طلب المستخدم للعثور على الوقت في سان فرانسيسكو. المهم أن نلاحظ أن مكالمة الأداة هي التي يتم إرجاعها، ليست الإجابة النهائية على السؤال. كما ذكرنا سابقًا، يعيد نموذج اللغة الكبير اسم الدالة التي اختارها للمهمة، والمعاملات التي ستمرير إليها.
# وصف الدالة للنموذج للقراءة
tools = [
{
"type": "function",
"function": {
"name": "get_current_time",
"description": "Get the current time in a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city name, e.g. San Francisco",
},
},
"required": ["location"],
},
}
}
]
# رسالة المستخدم الابتدائية
messages = [{"role": "user", "content": "What's the current time in San Francisco"}]
# أول استدعاء لواجهة البرمجة: طلب من النموذج استخدام الدالة
response = client.chat.completions.create(
model=deployment_name,
messages=messages,
tools=tools,
tool_choice="auto",
)
# معالجة رد النموذج
response_message = response.choices[0].message
messages.append(response_message)
print("Model's response:")
print(response_message)
Model's response:
ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_pOsKdUlqvdyttYB67MOj434b', function=Function(arguments='{"location":"San Francisco"}', name='get_current_time'), type='function')])
شفرة الدالة اللازمة لأداء المهمة:
بعد أن اختار نموذج اللغة الكبير الدالة التي يجب تشغيلها، يجب تنفيذ وتشغيل الشفرة التي تؤدي المهمة. يمكننا تنفيذ الشفرة للحصول على الوقت الحالي في بايثون. سنحتاج أيضًا إلى كتابة الشفرة لاستخراج الاسم والمعاملات من response_message للحصول على النتيجة النهائية.
def get_current_time(location):
"""Get the current time for a given location"""
print(f"get_current_time called with location: {location}")
location_lower = location.lower()
for key, timezone in TIMEZONE_DATA.items():
if key in location_lower:
print(f"Timezone found for {key}")
current_time = datetime.now(ZoneInfo(timezone)).strftime("%I:%M %p")
return json.dumps({
"location": location,
"current_time": current_time
})
print(f"No timezone data found for {location_lower}")
return json.dumps({"location": location, "current_time": "unknown"})
# معالجة استدعاءات الوظائف
if response_message.tool_calls:
for tool_call in response_message.tool_calls:
if tool_call.function.name == "get_current_time":
function_args = json.loads(tool_call.function.arguments)
time_response = get_current_time(
location=function_args.get("location")
)
messages.append({
"tool_call_id": tool_call.id,
"role": "tool",
"name": "get_current_time",
"content": time_response,
})
else:
print("No tool calls were made by the model.")
# استدعاء API الثاني: الحصول على الاستجابة النهائية من النموذج
final_response = client.chat.completions.create(
model=deployment_name,
messages=messages,
)
return final_response.choices[0].message.content
get_current_time called with location: San Francisco
Timezone found for san francisco
The current time in San Francisco is 09:24 AM.
استدعاء الدوال هو جوهر معظم، إن لم يكن كل، تصميم استخدام الأدوات للوكيل، ومع ذلك قد يكون تنفيذها من الصفر تحديًا أحيانًا. كما تعلمنا في الدرس 2 توفر أطر العمل الوكلائية لنا كتل بناء مُعدة مسبقًا لتطبيق استخدام الأدوات.
فيما يلي بعض الأمثلة على كيفية تنفيذ نمط تصميم استخدام الأدوات باستخدام أطر العمل الوكلائية المختلفة:
Semantic Kernel هو إطار عمل مفتوح المصدر للذكاء الاصطناعي لمطوري .NET و Python و Java الذين يعملون مع نماذج اللغة الكبيرة. يبسط عملية استخدام استدعاء الدوال من خلال وصف دوالك ومعاملاتها للنموذج تلقائيًا عبر عملية تسمى التسلسل (serializing). كما أنه يتعامل مع الاتصال ذهابًا وإيابًا بين النموذج والشفرة الخاصة بك. ميزة أخرى لاستخدام إطار عمل وكيل مثل Semantic Kernel هو أنه يتيح لك الوصول إلى أدوات مُعدة مسبقًا مثل البحث في الملفات ومفسر الشفرات.
يوضح الرسم البياني التالي عملية استدعاء الدوال مع Semantic Kernel:

في Semantic Kernel تُسمى الدوال/الأدوات الإضافات (Plugins). يمكننا تحويل الدالة get_current_time التي رأيناها سابقًا إلى إضافة عن طريق تحويلها إلى صنف يحتوي على الدالة. يمكننا أيضًا استيراد مزين kernel_function، الذي يأخذ وصف الدالة. عند إنشاء Kernel باستخدام GetCurrentTimePlugin، يقوم Kernel تلقائيًا بتسلسل الدالة ومعاملاتها، وينشئ المخطط لإرساله إلى نموذج اللغة الكبير في هذه العملية.
from semantic_kernel.functions import kernel_function
class GetCurrentTimePlugin:
async def __init__(self, location):
self.location = location
@kernel_function(
description="Get the current time for a given location"
)
def get_current_time(location: str = ""):
...
from semantic_kernel import Kernel
# إنشاء النواة
kernel = Kernel()
# إنشاء الملحق
get_current_time_plugin = GetCurrentTimePlugin(location)
# إضافة الملحق إلى النواة
kernel.add_plugin(get_current_time_plugin)
خدمة Azure AI Agent هي إطار عمل وكيل أحدث، مصمم لتمكين المطورين من بناء ونشر وتوسيع نطاق وكلاء ذكاء اصطناعي عالي الجودة وقابل للتوسيع بأمان دون الحاجة لإدارة الموارد الحسابية والتخزينية الأساسية. وهي مفيدة بشكل خاص لتطبيقات المؤسسات حيث أنها خدمة مدارة بالكامل مع أمان بدرجة المؤسسات.
مقارنةً بالتطوير باستخدام واجهة برمجة تطبيقات LLM مباشرة، توفر خدمة Azure AI Agent بعض المزايا، بما في ذلك:
يمكن تقسيم الأدوات المتاحة في خدمة Azure AI Agent إلى فئتين:
تتيح لنا خدمة Agent استخدام هذه الأدوات معًا كمجموعة أدوات (toolset). كما أنها تستخدم الخيوط التي تتتبع تاريخ الرسائل من محادثة معينة.
تخيل أنك وكيل مبيعات في شركة تسمى Contoso. تريد تطوير وكيل محادثة يمكنه الإجابة على أسئلة حول بيانات المبيعات الخاصة بك.
توضح الصورة التالية كيف يمكنك استخدام خدمة Azure AI Agent لتحليل بيانات المبيعات الخاصة بك:

لاستخدام أي من هذه الأدوات مع الخدمة، يمكننا إنشاء عميل وتعريف أداة أو مجموعة أدوات. لتطبيق هذا عمليًا، يمكننا استخدام كود Python التالي. سيتمكن نموذج اللغة الكبير (LLM) من النظر في مجموعة الأدوات وتقرير ما إذا كان يستخدم الدالة التي أنشأها المستخدم، fetch_sales_data_using_sqlite_query، أو مفسر الشفرة المُعد مسبقًا بناءً على طلب المستخدم.
import os
from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential
from fetch_sales_data_functions import fetch_sales_data_using_sqlite_query # دالة fetch_sales_data_using_sqlite_query والتي يمكن العثور عليها في ملف fetch_sales_data_functions.py.
from azure.ai.projects.models import ToolSet, FunctionTool, CodeInterpreterTool
project_client = AIProjectClient.from_connection_string(
credential=DefaultAzureCredential(),
conn_str=os.environ["PROJECT_CONNECTION_STRING"],
)
# تهيئة مجموعة الأدوات
toolset = ToolSet()
# تهيئة وكيل استدعاء الدالة مع دالة fetch_sales_data_using_sqlite_query وإضافتها إلى مجموعة الأدوات
fetch_data_function = FunctionTool(fetch_sales_data_using_sqlite_query)
toolset.add(fetch_data_function)
# تهيئة أداة مترجم الأكواد وإضافتها إلى مجموعة الأدوات.
code_interpreter = code_interpreter = CodeInterpreterTool()
toolset.add(code_interpreter)
agent = project_client.agents.create_agent(
model="gpt-4o-mini", name="my-agent", instructions="You are helpful agent",
toolset=toolset
)
قلق شائع يتعلق بالاستعلامات الديناميكية SQL التي يولدها نماذج اللغة الكبيرة هو الأمان، وخصوصًا خطر حقن SQL أو الإجراءات الخبيثة، مثل حذف أو العبث بقاعدة البيانات. بينما هذه المخاوف صحيحة، يمكن التخفيف منها بفعالية عن طريق تهيئة أذونات وصول قاعدة البيانات بشكل صحيح. بالنسبة لمعظم قواعد البيانات، يتضمن ذلك إعداد قاعدة البيانات كقراءة فقط. بالنسبة لخدمات قواعد البيانات مثل PostgreSQL أو Azure SQL، يجب تعيين التطبيق على دور قراءة فقط (SELECT). تشغيل التطبيق في بيئة آمنة يعزز الحماية بشكل أكبر. في سيناريوهات الشركات، يتم عادةً استخراج البيانات وتحويلها من أنظمة التشغيل إلى قاعدة بيانات أو مستودع بيانات للقراءة فقط مع مخطط سهل الاستخدام. يضمن هذا النهج أن تكون البيانات آمنة، ومحسّنة للأداء وسهولة الوصول، وأن يكون وصول التطبيق مقيدًا وقراءة فقط.
انضم إلى Azure AI Foundry Discord للقاء متعلمين آخرين، وحضور ساعات العمل، والحصول على إجابات لأسئلتك حول وكلاء الذكاء الاصطناعي.
إخلاء المسؤولية: تم ترجمة هذا المستند باستخدام خدمة الترجمة بالذكاء الاصطناعي Co-op Translator. بينما نسعى لتحقيق الدقة، يرجى العلم أن الترجمات الآلية قد تحتوي على أخطاء أو عدم دقة. يجب اعتبار المستند الأصلي بلغته الأصلية المصدر المعتمد. بالنسبة للمعلومات الحيوية، يُنصح بالاستعانة بالترجمة البشرية المهنية. نحن غير مسؤولين عن أي سوء فهم أو تفسيرات خاطئة ناتجة عن استخدام هذه الترجمة.