تخطَّ إلى المحتوى

استكشاف البيانات في نواة دائمة

يبيّن هذا الدليل كيف تجعل الوكيل يحمّل ما يكلّف مرة واحدة، ثم تطرح عدة أسئلة عنه، بدل أن تُحتسب كلفة التحميل مع كل سؤال.

أداة eval تشغّل مفسّر دائم. تبقى المتغيرات والوحدات المستورَدة والبيانات المحمّلة بين الاستدعاءات.

استدعاء python -c لمرة واحدة يتحمّل كلفة التجهيز مع كل سؤال. تحميل إطار بيانات يكلّف ثوانٍ ومئة ميجابايت؛ ورسمه يكلّف مللي ثوانٍ. حين يكلّف كل سؤال التحميل، يسأل الوكيل أقل مما ينبغي — ويعود كل جواب نصًا يحلّله من جديد.

حمّل data/runs.csv وأخبرني بمدة p95 حسب الوكيل.

import pandas as pd
runs = pd.read_csv("data/runs.csv")
len(runs)

يُعاد آخر تعبير كما يفعل دفتر الملاحظات، فيُبلّغ len(runs) عن عدد الصفوف من غير print.

ثم، في استدعاء منفصل:

runs.groupby("agent")["duration_ms"].quantile(0.95).sort_values()

runs ما زال محمّلًا. يُعرَض إطار pandas جدولًا، لا تمثيل repr.

import matplotlib.pyplot as plt
runs.groupby("agent")["duration_ms"].mean().plot.bar()

تُلتقَط الأشكال بعد انتهاء الخلية وتُعاد صورًا يعرضها نص المحادثة. ترى المخطط، ويراه الوكيل.

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

هذه تُحوَّل إلى شفرة عادية بدل أن ترفع خطأ:

ما تكتبه ما يحدث
%pip install x يشغّل pip، ثم يمسح الذاكرة المؤقتة للوحدات حتى يرى import التالي ما ثُبّت للتو
%cd path os.chdir
!command عملية فرعية يُلتقَط خرجها
%%bash بقية الخلية سكربت صدفة
%%timeit 1000 تشغيل موقوت

ما يهم هو إخلاء %pip للذاكرة المؤقتة: التثبيت في مفسّر يعمل لا يغيّر وحدة سبق استيرادها، فمن دونه لا تكون النسخة التي ثبّتها للتو هي التي تعمل.

paths = tool("find", {"pattern": "**/*.dart", "path": "lib"})
for path in paths.splitlines()[:100]:
contents = tool("read", {"path": path})
...

يعيد tool(name, args) الدخول إلى سجل أدوات الوكيل نفسه. فتستطيع الخلية أن تتفرّع على مئة ملف، أو أن تفوّض عبر task، من غير أن ينفق النموذج جولة لكل عنصر.

الاستدعاء المُجسَّر يعلّق مهلة الخلية ما دام لم يرجع. الميزانية تقيس الخمول لا الزمن الفعلي — خلية تتفرّع إلى وكلاء فرعيين وتنتظر أربع دقائق ليست عالقة، وقتلها في منتصف التفريع يفقد حالة النواة كلها.

eval(code: "…", reset: true, description: "Start a clean interpreter")

يتخلّص من المفسّر ويبدأ مفسّرًا نظيفًا. يزول كل ما حُمّل، وهذا المقصود.

في الحاوية المعزولة للمحادثة إن كانت لها واحدة، وعلى المضيف فيما عدا ذلك.

وجود مفسّر دائم يقوده نموذج يقرأ مستودعًا غير موثوق هو بالضبط الغرض من قصر التنفيذ على الحاوية المعزولة: استدعاء bash لمرة واحدة ينتهي على الأقل، أما النواة فصدفة تتذكّر.

النواة لا تقلع حاوية معزولة كي تعمل داخلها — القاعدة نفسها التي تمنع تبويب المنصة من الإقلاع تلقائيًا. إن أردت النواة داخل الحاوية المعزولة، افتح صدفة المحادثة أولًا. انظر امنح وكيلًا آلة للاختبار عليها.

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