- نمنح النموذج قاعدة بيانات وثلاث أدوات تقرأ منها
- نصف تلك الأدوات ليعرف النموذج متى يلجأ إلى كل منها
- نُشغّل الحلقة التي تحوّل استدعاءات الأدوات إلى نتائج
- نراقبه وهو يطلب عدة أدوات دفعة واحدة
- نُعيد الأخطاء إلى النموذج بدلًا من رفعها كاستثناءات
- نُميّز بين ما لن يفعله النموذج وما لا يستطيع فعله
الإعداد
تحتاج إلى Python 3.9 أو أحدث، وحزمةrequests، ومفتاح Venice API. راجع إنشاء مفتاح API إن لم يكن لديك واحد. كل شيء آخر موجود في المكتبة القياسية.
agent.py مع سطور الاستيراد وكتلة الترويسة التي يُعيد كل استدعاء استخدامها:
يقوم
GET /models/traits بربط أسماء السمات الثابتة بأيّ نموذج يشغل ذلك الدور حاليًا. قراءة function_calling_default عند بدء التشغيل تعني أن وكيلك سيظل يعمل عند استبدال النموذج الأساسي. راجع النماذج للاطلاع على القائمة الكاملة للسمات.1. قاعدة بيانات تستحقّ السؤال عنها
سيفي أي ملف SQLite بالغرض. هذا الملف عبارة عن متجر صغير فيه عملاء ومنتجات وطلبات تربطهم، وهو ما يكفي لكي يتطلّب سؤال حقيقي عملية JOIN وتجميعًا:2. ثلاث أدوات يمكن للنموذج اللجوء إليها
تُحاكي الأدوات الطريقة التي يتعرّف بها شخص ما على قاعدة بيانات غير مألوفة: اكتشاف ما فيها، ثم النظر في جدول واحد عن كثب، ثم الاستعلام منه.description ليس تعليقًا، بل هو الشيء الوحيد الذي يقرأه النموذج عند تقرير أيّ أداة يستدعيها وما الذي يضعه فيها:
3. الحلقة
استدعاء الدوال محادثة، وليس طلبًا واحدًا. يردّ النموذج باستدعاءات أدوات، فتُشغّلها، ثم تُلحق النتائج، ثم تسأل مرة أخرى. تنتهي الحلقة عندما يردّ النموذج بمحتوى بدلًا من استدعاءات.messages قبل النتائج. فهي تحمل tool_calls التي تُجيب عنها النتائج، وفي نموذج تفكير (reasoning model) تحمل أيضًا حقل reasoning_content. إعادة بناء الرسالة يدويًا وإسقاط الحقول التي لم تتوقّعها هي أكثر طريقة شيوعًا لكسر الجولة الثانية.
تُطابَق كل نتيجة مع استدعائها بواسطة tool_call_id. لا شيء آخر يُميّزها.
max_rounds حدّ حقيقي، لا مجرد شكليّة. النموذج الذي يستمر بالاستعلام دون التوصّل إلى نتيجة سيدور في حلقة حتى ينفد صبرك أو رصيدك.
4. ما الذي يفعله فعلًا
اربط كتلةmain وشغّله:
stderr أثناء حدوثها، فيمكنك متابعة عمله:
الجولة الرابعة هي الجزء الذي لا يستطيع استدعاء دالة واحدة القيام به. لم يكن بمقدور النموذج كتابة ذلك الاستعلام قبل أن يرى إجابة الاستعلام الذي سبقه.
لن يُطابق تشغيلك هذا التشغيلَ استدعاءً باستدعاء. أحيانًا يصف النموذج الجداول الثلاثة دفعة واحدة، وأحيانًا واحدًا في كل مرة، وأحيانًا يتخطّى
list_tables ويُخمّن اسمًا. الأرقام ثابتة لأنها تأتي من قاعدة البيانات؛ أما الطريق إليها فليس كذلك.
أعادت الجولة الثانية ثلاثة استدعاءات أدوات في ردٍّ واحد، والحلقة أعلاه تُشغّلها واحدًا تلو الآخر. وهي مستقلّة، لذا يستحقّ استخدام
ThreadPoolExecutor هنا فور أن تُنفّذ أدواتك عمليات إدخال/إخراج فعلية. حافظ على ترتيب رسائل tool بنفس ترتيب الاستدعاءات التي أنتجتها.usage أن ذلك يؤتي ثماره:
5. دع الأخطاء تصل إلى النموذج
الغريزة هي رفع استثناء عند استعلام سيّئ. قاوم ذلك. الخطأ معلومة، والنموذج يستطيع التصرّف بناءً عليها. اطلب جدولًا غير موجود:run_query أعادت {"error": "OperationalError: no such table: purchases"} بوصفها نتيجة أداة عادية بدلًا من رفع استثناء، قرأها النموذج، واستدعى list_tables ليعرف ما هو موجود فعلًا، ثم صحّح نفسه. لو انتقل الاستثناء إلى أعلى، لكان السكربت قد توقّف بسبب خطأ إملائي.
هذا هو السبب في أن كل أداة تُعيد JSON في مسار الفشل أيضًا. القاعدة بسيطة: إذا كان مبرمج يُصحّح أداتك سيرغب في رؤية الرسالة، فإن النموذج يرغب في ذلك أيضًا.
6. ما لن يفعله، وما لا يستطيع فعله
اطلب من الوكيل تدمير شيء:SELECT عن العملاء الإسبان، ولم يجد أحدًا لأن العمود يحفظ ES وليس Spain، فأفاد بذلك بدلًا من الحذف:
run_query هي الجزء الذي لا يعتمد على اختيار:
السطر الثاني هو سبب التقاط
run_query لـ sqlite3.Warning إلى جانب sqlite3.Error. يرفض مُشغّل Python تنفيذ عبارات مكدّسة، لكنه يرفع Warning من أجلها، وWarning ليست فئة فرعية من Error. الاكتفاء بالتقاط sqlite3.Error يترك العبارة المكدّسة تُفلت من المُعالج وتُنهي الحلقة بدلًا من إعادة رسالة يستطيع النموذج قراءتها.التحكّم في متى تُستخدم الأدوات
يقرّرtool_choice قدر الصلاحية المتاحة للنموذج:
"required" أفظّ ممّا يبدو. سؤال هذا الوكيل What is 2 + 2? مع ضبط tool_choice على "required" يجعله يستدعي list_tables، وينظر في قاعدة بيانات لا حاجة له بها، ثم يجيب 4 في الجولة التالية. مع "auto" يجيب 4 فورًا ولا يستدعي شيئًا. لجأ إلى "required" عندما يجب على أداةٍ أن تعمل فعلًا، مثل تسجيل طلب، ودعها وشأنها في غير ذلك.
ضبط الوكيل
الخطوات التالية
الحلقة التي أصبحت لديك الآن هي نفسها الحلقة التي تقف خلف معظم الوكلاء. تتغيّر الأدوات فقط.- استبدل أدوات SQL باستدعاءات HTTP فيصبح وكيل API.
- أضِف البحث في الويب والاستخلاص بوصفه أداة، فيصبح قادرًا على التحقّق من الويب المباشر في منتصف الإجابة.
- اطلب نتيجة مُنمّطة (typed) بدلًا من نصّ نثري عبر الاستجابات المُهيكلة.
- اطّلع على نسخة أوسع من هذا النمط في وكيل البحث الخاص.
استدعاء الدوال
مرجع لمصفوفة الأدوات و tool_choice.
الاستجابات المُهيكلة
قيّد الإجابة النهائية بمخطط JSON.
التخزين المؤقت للموجّهات
أبقِ المحادثة المتنامية زهيدة الثمن.
وكيل البحث الخاص
الحلقة نفسها مع أدوات ويب ومخطّط.