الخطوة 3 في الوكلاء: بناء وكيل بحث
ابنِ وكيلًا يستطيع البحث عن المعلومات في الويب.
ما ستتعلمه
- استخدام أدوات متعددة داخل وكيل واحد
- واجهة Wikipedia البرمجية (API)
- توجيه الأدوات (إسناد الطلب إلى الدالة المناسبة)
- التعامل مع استدعاءات أدوات متعددة في استجابة واحدة
الخطوة 1: إضافة أداة بحث في Wikipedia
أضف إلى agent.py:
import requests
def search_wikipedia(query: str) -> str:
"""Search Wikipedia and return a summary."""
try:
url = "https://en.wikipedia.org/api/rest_v1/page/summary/" + requests.utils.quote(query)
response = requests.get(url, timeout=10)
if response.status_code == 200:
data = response.json()
return f"Title: {data['title']}\nSummary: {data['extract'][:500]}"
elif response.status_code == 404:
return f"No Wikipedia page found for '{query}'"
else:
return f"Wikipedia error: {response.status_code}"
except Exception as e:
return f"Error searching Wikipedia: {str(e)}"
الخطوة 2: إضافة مخطط الأداة
tools = [
{
"type": "function",
"function": {
"name": "calculate",
"description": "Evaluate a mathematical expression",
"parameters": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "Math expression like '2 + 2' or '3 * (4 + 5)'"
}
},
"required": ["expression"]
}
}
},
{
"type": "function",
"function": {
"name": "search_wikipedia",
"description": "Search Wikipedia for a topic and get a summary",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "The topic to search for"
}
},
"required": ["query"]
}
}
}
]
الخطوة 3: تحديث حلقة الوكيل مع توجيه الأدوات
def run_tool(tool_call):
"""Execute the right function based on tool name."""
args = json.loads(tool_call.function.arguments)
if tool_call.function.name == "calculate":
return calculate(args["expression"])
elif tool_call.function.name == "search_wikipedia":
return search_wikipedia(args["query"])
else:
return f"Unknown tool: {tool_call.function.name}"
def run_agent(user_message: str) -> str:
messages = [
{"role": "system", "content": "You are a research assistant with access to a calculator and Wikipedia."},
{"role": "user", "content": user_message},
]
max_turns = 5 # منع الحلقات اللانهائية
for _ in range(max_turns):
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
tools=tools,
tool_choice="auto",
)
message = response.choices[0].message
if not message.tool_calls:
return message.content
messages.append(message)
for tool_call in message.tool_calls:
print(f" → Calling: {tool_call.function.name}({tool_call.function.arguments})")
result = run_tool(tool_call)
print(f" → Result: {result[:100]}...")
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": result,
})
return "Agent stopped after maximum turns."
أبرز التغييرات:
- توجيه الأدوات — تتولى run_tool() إسناد الطلب إلى الدالة الصحيحة
- الحد الأقصى للجولات — يمنع الحلقات اللانهائية إذا استمر الذكاء الاصطناعي في استدعاء الأدوات
- طباعة معلومات التصحيح — تُظهر ما يفعله الذكاء الاصطناعي
الخطوة 4: اختبار الأدوات وآلية التوجيه
اختبار أداة Wikipedia
أضف إلى advanced/agentic/tests/test_tools.py:
from agent import search_wikipedia
def test_search_wikipedia_returns_summary():
result = search_wikipedia("Python (programming language)")
assert "Python" in result
assert len(result) > 50
def test_search_wikipedia_handles_not_found():
result = search_wikipedia("XyzzyNotARealTopic12345")
assert "No Wikipedia page found" in result
اختبار توجيه الأدوات
أنشئ advanced/agentic/tests/test_agent.py:
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
from agent import run_tool
class FakeToolCall:
def __init__(self, name, args):
self.function = FakeFunction(name, args)
self.id = "test_123"
class FakeFunction:
def __init__(self, name, args):
self.name = name
self.arguments = args
def test_run_tool_dispatches_calculate():
tool = FakeToolCall("calculate", '{"expression": "10 * 5"}')
result = run_tool(tool)
assert result == "50"
def test_run_tool_unknown():
tool = FakeToolCall("nonexistent", "{}")
result = run_tool(tool)
assert "Unknown tool" in result
شغّل جميع الاختبارات:
cd aiproject
python -m pytest advanced/agentic/tests/ -v
الخطوة 5: اختبار وكيل البحث
if __name__ == "__main__":
queries = [
"What is the capital of France and what is its population?",
"Search Wikipedia for Python programming language and tell me about it",
"What is 2 + 2?",
"Who is Marie Curie and what year was she born?",
]
for query in queries:
print(f"\n{'='*50}")
print(f"User: {query}")
print("-" * 50)
result = run_agent(query)
print(f"AI: {result}")
كيف يعمل وكيل البحث
اسأل: «من هي Marie Curie وفي أي عام وُلدت؟»
- الذكاء الاصطناعي: «ينبغي أن أبحث في Wikipedia عن Marie Curie»
- → يستدعي
search_wikipedia("Marie Curie") - → يعيد ملخصًا يتضمن سنة الميلاد
- الذكاء الاصطناعي: «وُلدت Marie Curie عام 1867...»
اسأل: «كم يبلغ عدد سكان فرنسا مقسومًا على 1000؟»
- الذكاء الاصطناعي: «أولًا، سأبحث عن عدد سكان فرنسا»
- → يستدعي
search_wikipedia("France")→ ويحصل على نحو 68 مليون نسمة - الذكاء الاصطناعي: «الآن سأقسم على 1000»
- → يستدعي
calculate("68000000 / 1000")→ فيُعيد "68000" - الذكاء الاصطناعي: «عدد سكان فرنسا مقسومًا على 1000 هو 68,000»
يربط الوكيل الأدوات بعضها ببعض بشكل طبيعي — وهذا جوهر الذكاء الاصطناعي الوكيلي.