الأدوات والموارد والتعليمات

أنماط الأدوات المتقدمة

5 دقيقة للقراءة

الأنماط التالية تجيب كلها عن سؤال واحد بصيغ مختلفة: كم من العمل ينبغي أن يجري داخل نداء أداة واحد، وكم منه يُترك للنموذج ينظّمه بنفسه؟

تركيب الأدوات

الأداتان اللتان تُستخدمان معاً دائماً يكون دمجهما في أداة واحدة أفضل غالباً. فكل رحلة ذهاب وإياب تكلّف دوراً، وكل دور فرصة ليفقد النموذج خيط الموضوع:

أداتان دقيقتان مقابل أداة واحدة مركّبة

دقيقةمركّبة«لخّص ما نعرفه عن سياسة ا…طلب واحد من المستخدمsearch_documentsالدور الأول: النموذج يستدعي ويق…النموذج يختار خمساًالدور الثاني: يستهلك سياقاً ليق…summarizeالدور الثالث: يلخّص أخيراًsearch_and_summarizeنداء واحد. الترتيب والاقتطاع يج…الإجابة

التركيب ليس مجانياً. فالأداة المركّبة تخفي خطواتها الوسيطة، وحين يخرج الملخص خاطئاً لن تعرف أالبحث أخفق أم التلخيص. القاعدة العملية: ركّب حين لا تكون النتيجة الوسيطة مفيدة بذاتها أبداً، وافصل حين يكون من المشروع أن يتوقف النموذج في منتصف الطريق.

@server.list_tools()
async def list_tools():
    return [
        Tool(
            name="search_and_summarize",
            description="البحث في المستندات وإرجاع ملخص",
            inputSchema={
                "type": "object",
                "properties": {
                    "query": {"type": "string"},
                    "max_results": {"type": "integer", "default": 5}
                },
                "required": ["query"]
            }
        )
    ]

@server.call_tool()
async def call_tool(name: str, arguments: dict):
    if name == "search_and_summarize":
        # الخطوة 1: البحث
        results = await search_documents(arguments["query"])

        # الخطوة 2: التلخيص
        summary = await generate_summary(results[:arguments.get("max_results", 5)])

        return [TextContent(type="text", text=summary)]

النتائج المتدفقة

للعمليات طويلة المدى، اجعل النتائج تتدفق:

@server.call_tool()
async def call_tool(name: str, arguments: dict):
    if name == "analyze_large_dataset":
        results = []

        async for batch in process_in_batches(arguments["data"]):
            results.append(batch)
            # إنتاج نتائج متوسطة
            yield [TextContent(type="text", text=f"تمت معالجة الدفعة: {len(results)}")]

        # النتيجة النهائية
        yield [TextContent(type="text", text=json.dumps(results))]

الإجراءات القابلة للتأكيد

للعمليات الخطرة، اطلب التأكيد:

Tool(
    name="delete_all_files",
    description="حذف جميع الملفات في دليل. إجراء مدمر.",
    inputSchema={
        "type": "object",
        "properties": {
            "directory": {"type": "string"},
            "confirm": {
                "type": "boolean",
                "description": "يجب أن يكون true للمتابعة"
            }
        },
        "required": ["directory", "confirm"]
    }
)

@server.call_tool()
async def call_tool(name: str, arguments: dict):
    if name == "delete_all_files":
        if not arguments.get("confirm"):
            return [TextContent(
                type="text",
                text="الإجراء غير مؤكد. عيّن confirm=true للمتابعة."
            )]
        # المتابعة مع الحذف
        await delete_files(arguments["directory"])

تبعيات الأدوات

بناء أدوات تعتمد على أدوات أخرى:

class ToolRegistry:
    def __init__(self):
        self.tools = {}

    def register(self, name, handler):
        self.tools[name] = handler

    async def call(self, name, arguments):
        return await self.tools[name](arguments)

registry = ToolRegistry()

async def get_user_handler(args):
    return await db.get_user(args["id"])

async def get_user_orders_handler(args):
    # يعتمد على get_user
    user = await registry.call("get_user", {"id": args["user_id"]})
    return await db.get_orders(user["id"])

registry.register("get_user", get_user_handler)
registry.register("get_user_orders", get_user_orders_handler)

في القسم التالي، سنستكشف أنماط الموارد المتقدمة. :::

اختبار

اختبار الوحدة 3: الأدوات والموارد والتعليمات

خذ الاختبار
هل كان هذا الدرس مفيدًا؟

سجّل الدخول للتقييم