بناء وكيل لتحليل البيانات
أنشئوا وكيلًا متكاملًا لتحليل البيانات يقبل ملف CSV وسؤالًا باللغة الطبيعية، ويكتب شيفرة pandas وmatplotlib تكراريًا، وينتج تقريرًا مصقولًا.
بناء وكيل لتحليل البيانات درس مجاني في AI Engineering Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في AI Engineering Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة AI Engineering Academy 4 دروس في المجموع.
رؤية وكيل تحليل البيانات
يقبل وكيل تحليل البيانات ملف CSV وسؤالًا باللغة الطبيعية، ثم يستكشف البيانات وينظفها ويحسب الإحصاءات وينشئ التصورات وينتج تقريرًا منسقًا، وكل ذلك من خلال إنشاء التعليمات البرمجية وتنفيذها تكراريًا. يُعد هذا أحد أكثر التطبيقات العملية لوكلاء التعليمات البرمجية، إذ يحاكي مباشرة سير عمل محلل البيانات، باستثناء الجهد البشري.
البنية العامة للوكيل
يمر وكيل تحليل البيانات بأربع مراحل مفاهيمية: الاستكشاف (فهم شكل البيانات وأنواعها وجودتها)، والتنظيف (معالجة القيم المفقودة والقيم الشاذة وتحويل الأنواع)، والتحليل (حساب المقاييس والإحصاءات التي تجيب عن السؤال)، وإعداد التقرير (إنشاء المخططات وتلخيص النتائج نثريًا). وتتوافق كل مرحلة مع 1 إلى 5 تكرارات لتنفيذ التعليمات البرمجية.
DATA_AGENT_SYSTEM_PROMPT = '''
You are a data analysis agent. Given a CSV file and a question, answer it through iterative Python code.
Phases to follow:
1. EXPLORE: Load the data, print shape, dtypes, head(), describe(), and check for nulls.
2. CLEAN: Handle missing values, fix dtypes, remove outliers.
3. ANALYZE: Compute statistics, groupbys, correlations - whatever answers the question.
4. REPORT: Generate a matplotlib chart saved to /workspace/chart.png and write a text summary.
Rules:
- Write code in ```python ... ``` blocks.
- Save intermediate results to /workspace/ for use in later steps.
- Print key findings after each computation so you can observe them.
- When all phases are done, say TASK COMPLETE and summarize the answer.
'''المرحلة 1: تعليمات استكشاف البيانات البرمجية
تحمّل مرحلة الاستكشاف البيانات وتطبع فورًا كل المعلومات اللازمة لتخطيط التحليل: الشكل، وأسماء الأعمدة وأنواعها، وصفوفًا نموذجية، والإحصاءات الموجزة، وأعداد القيم الفارغة. يقرأ LLM هذا الإخراج ويستخدمه لاتخاذ قرارات مدروسة بشأن التنظيف والتحليل في التكرارات اللاحقة.
import pandas as pd
import numpy as np
# Load dataset
df = pd.read_csv('/workspace/data.csv')
# Basic exploration
print('=== SHAPE ===' )
print(df.shape)
print('\n=== DTYPES ===')
print(df.dtypes)
print('\n=== HEAD ===')
print(df.head())
print('\n=== DESCRIBE ===')
print(df.describe(include='all'))
print('\n=== NULL COUNTS ===')
print(df.isnull().sum())
print('\n=== UNIQUE VALUES (categorical) ===')
for col in df.select_dtypes(include='object').columns:
print(f'{col}: {df[col].nunique()} unique values: {df[col].unique()[:5]}')
# Save for next iteration
df.to_parquet('/workspace/raw.parquet')
print('\nData saved to workspace.')المرحلة 2: تنظيف البيانات
بعد الاستكشاف، يكتب الوكيل تعليمات تنظيف موجهة استنادًا إلى ما لاحظه. وتكون استراتيجية التنظيف ديناميكية؛ فإذا لاحظ LLM أن 15% من قيم عمود ما فارغة، فإنه يقرر ما إذا كان سيحذفها أو يعوّضها. وإذا رأى قيمًا سالبة في عمود ينبغي ألا يحتوي إلا على قيم غير سالبة، فإنه يرشحها. وهذا التنظيف التكيفي القائم على الملاحظات هو ما يجعل الوكيل مفيدًا حقًا بدلًا من مجرد تشغيل مسار معالجة ثابت.
import pandas as pd
import numpy as np
# Load from previous iteration
df = pd.read_parquet('/workspace/raw.parquet')
# Fill numeric nulls with median (robust to outliers)
for col in df.select_dtypes(include='number').columns:
if df[col].isnull().sum() > 0:
median_val = df[col].median()
df[col] = df[col].fillna(median_val)
print(f'Filled nulls in {col} with median {median_val:.2f}')
# Drop rows where categorical key columns are null
df = df.dropna(subset=['category', 'date'])
# Fix date column type
df['date'] = pd.to_datetime(df['date'], errors='coerce')
df = df.dropna(subset=['date']) # drop unparseable dates
# Remove clear outliers: revenue > 3 std deviations from mean
if 'revenue' in df.columns:
z_scores = (df['revenue'] - df['revenue'].mean()) / df['revenue'].std()
df = df[z_scores.abs() < 3]
print(f'Removed outliers, rows remaining: {len(df)}')
df.to_parquet('/workspace/cleaned.parquet')
print('Cleaning complete:', df.shape)المرحلة 3: الإجابة عن السؤال
في مرحلة التحليل، يركّز الوكيل على حساب الإجابة المحددة عن سؤال المستخدم. فإذا كان السؤال هو "ما فئة المنتجات التي حققت أعلى إيرادات في الربع الأخير؟"، يكتب الوكيل تعليمات برمجية لترشيح البيانات حسب التاريخ، وتجميعها حسب الفئة، وجمع الإيرادات، ثم فرزها. ويُنشئ كود التحليل من جديد استنادًا إلى السؤال وما لاحظه الوكيل أثناء الاستكشاف، وليس وفق قالب عام.
import pandas as pd
import matplotlib
matplotlib.use('Agg') # non-interactive backend for server use
import matplotlib.pyplot as plt
df = pd.read_parquet('/workspace/cleaned.parquet')
# Analysis: revenue by category for last quarter
df['date'] = pd.to_datetime(df['date'])
last_quarter = df[df['date'] >= '2024-10-01']
revenue_by_category = (
last_quarter
.groupby('category')['revenue']
.sum()
.sort_values(ascending=False)
)
print('Revenue by category (last quarter):')
print(revenue_by_category)
print(f'\nTop category: {revenue_by_category.index[0]} (${revenue_by_category.iloc[0]:,.0f})')
# Save analysis result
revenue_by_category.to_json('/workspace/analysis_result.json')المرحلة 4: إنشاء المخططات
تجعل التصورات النتائج التحليلية واضحة ومقنعة. ينشئ وكيل تحليل البيانات مخططات matplotlib ويحفظها كملفات PNG في مساحة العمل. ويتخذ LLM قرارات تصميم المخطط الأساسية — نوع المخطط، ولوحة الألوان، وتسميات المحاور، والعنوان، والتعليقات التوضيحية — استنادًا إلى طبيعة البيانات. ويحفظ الوكيل المخططات دائمًا في /workspace/ حتى يمكن تضمينها في التقرير النهائي.
import pandas as pd
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import json
with open('/workspace/analysis_result.json') as f:
data = json.load(f)
categories = list(data.keys())
values = [data[k] / 1e6 for k in categories] # convert to millions
fig, ax = plt.subplots(figsize=(10, 6))
bars = ax.barh(categories, values, color='steelblue', edgecolor='white')
# Add value labels on bars
for bar, val in zip(bars, values):
ax.text(bar.get_width() + 0.05, bar.get_y() + bar.get_height()/2,
f'${val:.1f}M', va='center', fontsize=11)
ax.set_xlabel('Revenue ($ Millions)', fontsize=12)
ax.set_title('Revenue by Product Category - Q4 2024', fontsize=14, fontweight='bold')
ax.invert_yaxis() # highest on top
plt.tight_layout()
plt.savefig('/workspace/chart.png', dpi=150, bbox_inches='tight')
print('Chart saved to /workspace/chart.png')إنشاء التقرير المكتوب
ينتج التكرار النهائي تقرير الملخص المكتوب. يقرأ LLM نتائج التحليل ووصف المخطط، ثم يكتب سردًا موجزًا ودقيقًا يجيب عن السؤال الأصلي بأرقام محددة. ويشير التقرير إلى المخطط ويتضمن الرؤية الأساسية والبيانات الداعمة وتوصية أو أثرًا محتملًا على العمل.
import json
with open('/workspace/analysis_result.json') as f:
revenue_data = json.load(f)
top_category = max(revenue_data, key=revenue_data.get)
top_revenue = revenue_data[top_category]
total_revenue = sum(revenue_data.values())
share = top_revenue / total_revenue * 100
report = f'''# Q4 2024 Revenue Analysis
## Answer
The **{top_category}** category generated the highest revenue in Q4 2024:
**${top_revenue:,.0f}** ({share:.1f}% of total Q4 revenue).
## Key Findings
- Total Q4 revenue: ${total_revenue:,.0f}
- Top 3 categories: {list(revenue_data.items())[:3]}
- The top category outperformed the average by {top_revenue / (total_revenue / len(revenue_data)):.1f}x
## Chart
See chart.png for the full breakdown by category.
## Recommendation
Consider reallocating marketing budget toward {top_category} to
capitalize on its demonstrated strong performance.
'''
with open('/workspace/report.md', 'w') as f:
f.write(report)
print('TASK COMPLETE')
print(report)تجميع منسّق الوكيل
يربط المنسّق جميع المراحل معًا: إذ يهيّئ مساحة العمل، وينسخ ملف CSV المدخل، ويشغّل حلقة تنفيذ التعليمات البرمجية، ويراقب إشارة TASK COMPLETE، ثم يجمع ملفات الإخراج (report.md، chart.png). كما يتعامل المنسّق مع الأخطاء وإعادة المحاولات والتنظيف النهائي للملفات الوسيطة.
import shutil
from pathlib import Path
def run_data_analysis_agent(csv_path: str, question: str) -> dict:
workspace = setup_workspace()
shutil.copy(csv_path, workspace / 'data.csv')
messages = [
{'role': 'system', 'content': DATA_AGENT_SYSTEM_PROMPT},
{'role': 'user', 'content': f'File: /workspace/data.csv\nQuestion: {question}'}
]
state = ExecutionState(task=question)
for iteration in range(15): # max 15 iterations
response = llm.complete(messages)
code = extract_code_block(response)
if not code or 'TASK COMPLETE' in response:
break
stdout, stderr = execute_in_docker(code, workspace=workspace)
observation = format_observation(stdout, stderr)
messages += [
{'role': 'assistant', 'content': response},
{'role': 'user', 'content': observation}
]
state.after_execution(stdout, f'iteration_{iteration}')
return {
'report': (workspace / 'report.md').read_text() if (workspace / 'report.md').exists() else '',
'chart_path': str(workspace / 'chart.png'),
'iterations': state.iteration
}التعامل مع الأسئلة الغامضة
غالبًا ما يطرح المستخدمون أسئلة غامضة مثل "ما المنتجات التي تحقق أداءً جيدًا؟". ويقوم وكيل تحليل البيانات المتين بتوضيح الغموض قبل البدء: إذ يستكشف البيانات أولًا، ويحدد المقاييس المتاحة، ثم يستنتج التفسير الأكثر منطقية أو يطلب من المستخدم التوضيح. وتمنع خطوة التأمل هذه الوكيل من إنتاج إجابة صحيحة تقنيًا لكنها عديمة الفائدة عمليًا.
def handle_ambiguous_question(question: str, df_summary: dict) -> str:
clarification_prompt = f'''The user asked: '{question}'
Available data:
- Columns: {df_summary['columns']}
- Date range: {df_summary['date_range']}
- Metrics available: {df_summary['numeric_columns']}
Is the question clear enough to answer definitively?
If yes, restate the specific interpretation you will use.
If no, list the 2-3 clarifications needed to proceed.'''
response = llm.complete([{'role': 'user', 'content': clarification_prompt}])
return responseفحوصات جودة مخرجات الوكيل
بعد اكتمال عمل الوكيل، تحقّق من جودة مخرجاته. تأكّد من إنشاء ملف التقرير فعليًا، ومن أن ملف PNG الخاص بالمخطط صورة صالحة، ومن تطابق الأرقام الواردة في التقرير مع البيانات الموجودة في analysis_result.json، ومن أن التقرير يجيب فعلًا عن السؤال الأصلي. ويمكن لخطوة QA آلية تستخدم استدعاءً ثانيًا لـ LLM اكتشاف الحالات التي أكمل فيها الوكيل الحلقة لكنه قدّم إجابة ضعيفة.
def validate_analysis_output(workspace: str, question: str, report: str) -> dict:
validation_prompt = f'''Original question: {question}
Agent report:
{report[:2000]}
Rate this analysis on a scale of 1-5 for:
1. Does it directly answer the question? (1=No, 5=Yes)
2. Are specific numbers cited? (1=No, 5=Yes)
3. Is the conclusion clearly stated? (1=No, 5=Yes)
Return JSON: {{"question_answered": N, "numbers_cited": N, "clear_conclusion": N, "overall": N}}'''
result = llm.complete([{'role': 'user', 'content': validation_prompt}],
response_format={'type': 'json_object'})
scores = json.loads(result)
passed = scores['overall'] >= 4
return {'scores': scores, 'passed': passed}توسيع الوكيل باستخدام أدوات متخصصة بالمجال
يصبح وكيل البرمجة الأساسي أكثر قوة عند توسيعه بأدوات متخصصة بالمجال. بالنسبة إلى وكيل للبيانات المالية، أضيفوا دوالًا لجلب أسعار الأسهم المباشرة. وبالنسبة إلى وكيل لبيانات التسويق، أضيفوا إمكانية الوصول إلى Google Analytics API. وبالنسبة إلى وكيل للمبيعات، أضيفوا استعلامات Salesforce. تصبح هذه الأدوات متاحة لـ LLM من خلال تعريفات الدوال في system prompt أو باستخدام مُزيّن @tool في LangChain.
اختبار سريع
اختبروا مدى فهمكم لوكيل تحليل البيانات الذي تناولناه في هذا الدرس.
مراجعة الدرس
تعلّمتم في هذا الدرس أن وكيل تحليل البيانات يمر بأربع مراحل — الاستكشاف والتنظيف والتحليل وإعداد التقرير — تُنفَّذ كل منها من خلال التوليد التكراري للتعليمات البرمجية وتنفيذها، وأن توليد المخططات باستخدام matplotlib واستمرارية الحالة المعتمدة على الملفات يربطان هذه المراحل في سير عمل متماسك، وأن التحقق من المخرجات يضمن أن الإجابة النهائية للوكيل تتناول السؤال الأصلي فعلًا. سنتناول بعد ذلك قابلية رصد LLM وتتبعها.
الأسئلة الشائعة
هل درس «بناء وكيل لتحليل البيانات» مجاني؟
نعم — نص درس «بناء وكيل لتحليل البيانات» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة AI Engineering Academy، انتقل إلى CoddyKit PRO. تتضمن دورة AI Engineering Academy 4 دروس في المجموع.
ماذا ستتعلم في «بناء وكيل لتحليل البيانات»؟
أنشئوا وكيلًا متكاملًا لتحليل البيانات يقبل ملف CSV وسؤالًا باللغة الطبيعية، ويكتب شيفرة pandas وmatplotlib تكراريًا، وينتج تقريرًا مصقولًا. تتمرن على AI Engineering Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ AI Engineering Academy؟
لا تُشترط خبرة سابقة. AI Engineering Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «بناء وكيل لتحليل البيانات»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس AI Engineering Academy هذا؟
نعم. كل درس في AI Engineering Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- حلقة تنفيذ الشيفرة
- العزل باستخدام Docker وRestrictedPython
- إدارة الحالة عبر خطوات التنفيذ
- بناء وكيل لتحليل البيانات