Создание агента для анализа данных
Создайте полноценного агента для анализа данных, который принимает 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}Расширение агента предметными инструментами
Базовый агент для работы с кодом становится ещё мощнее после расширения предметными инструментами. Для агента, работающего с финансовыми данными, добавьте функции получения актуальных котировок акций. Для агента, работающего с маркетинговыми данными, добавьте доступ к API Google Analytics. Для агента отдела продаж добавьте запросы к Salesforce. Эти инструменты становятся доступными LLM через определения функций в системном запросе или декоратор LangChain @tool.
Быстрая проверка
Проверьте, насколько хорошо Вы поняли материал об агенте анализа данных из этого урока.
Итоги урока
В этом уроке Вы узнали, что агент анализа данных проходит четыре этапа — исследование, очистку, анализ и подготовку отчёта, каждый из которых реализуется посредством итеративной генерации и выполнения кода; создание диаграмм с помощью 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 включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Цикл выполнения кода
- Изоляция с Docker и RestrictedPython
- Управление состоянием между этапами выполнения
- Создание агента для анализа данных