GUI_MAI-DxO / utils /analyze_logs.py
DocUA's picture
Видалено застарілі файли, включаючи модулі для логування, інтерфейси Gradio та приклади використання. Оновлено документацію для відображення нових змін у структурі проекту.
143d94c
#!/usr/bin/env python3
"""
Скрипт для аналізу збережених логів MAI-DX
"""
import os
import json
import pandas as pd
from datetime import datetime
from collections import defaultdict
import argparse
def load_all_sessions(log_dir="mai_dx_logs"):
"""Завантажити всі сесії з директорії логів"""
sessions = []
if not os.path.exists(log_dir):
print(f"❌ Директорія {log_dir} не існує")
return sessions
for filename in os.listdir(log_dir):
if filename.endswith('.json') and not filename.endswith('_analytics.json'):
filepath = os.path.join(log_dir, filename)
try:
with open(filepath, 'r', encoding='utf-8') as f:
session = json.load(f)
sessions.append(session)
except Exception as e:
print(f"⚠️ Помилка читання {filename}: {e}")
return sessions
def analyze_session(session):
"""Детальний аналіз однієї сесії"""
print(f"\n{'='*60}")
print(f"📋 Аналіз сесії: {session['case_id']}")
print(f"{'='*60}")
print(f"\n📊 Основна інформація:")
print(f" - Назва випадку: {session['case_name']}")
print(f" - Час: {session['timestamp']}")
print(f" - Режим: {session['mode']}")
print(f" - Статус: {session['status']}")
print(f"\n💊 Діагноз:")
print(f" - Фінальний діагноз: {session['diagnosis']}")
print(f" - Впевненість: {session['confidence']}/5.0")
print(f" - Обґрунтування: {session['reasoning'][:100]}...")
print(f"\n💰 Економіка:")
print(f" - Витрачено: ${session['cost']}")
print(f" - Бюджет: ${session['budget']}")
print(f" - Ефективність: {((session['budget'] - session['cost']) / session['budget'] * 100):.1f}%")
print(f"\n⏱️ Продуктивність:")
print(f" - Тривалість: {session['duration']:.1f} секунд")
print(f" - Ітерацій: {session['iterations']}")
# Аналіз розмов
conversations = session.get('conversations', [])
if conversations:
print(f"\n💬 Аналіз розмов:")
print(f" - Всього раундів: {len(conversations)}")
# Підрахунок активності агентів
agent_activity = defaultdict(int)
message_types = defaultdict(int)
total_messages = 0
for conv in conversations:
for msg in conv.get('messages', []):
agent_activity[msg['agent_name']] += 1
message_types[msg['message_type']] += 1
total_messages += 1
print(f" - Всього повідомлень: {total_messages}")
print(f"\n 🤖 Активність агентів:")
for agent, count in sorted(agent_activity.items(), key=lambda x: x[1], reverse=True):
print(f" - {agent}: {count} повідомлень ({count/total_messages*100:.1f}%)")
print(f"\n 📝 Типи повідомлень:")
for msg_type, count in sorted(message_types.items(), key=lambda x: x[1], reverse=True):
print(f" - {msg_type}: {count} ({count/total_messages*100:.1f}%)")
# Деталі раундів
print(f"\n 🔄 Деталі раундів:")
for i, conv in enumerate(conversations):
msgs = len(conv.get('messages', []))
cost = conv.get('cost_incurred', 0)
decision = conv.get('decision', 'N/A')
print(f" Раунд {i+1}: {msgs} повідомлень, ${cost:.2f}, Рішення: {decision}")
def generate_summary_report(sessions, output_file="mai_dx_summary_report.html"):
"""Генерація зведеного HTML звіту по всіх сесіях"""
if not sessions:
print("❌ Немає сесій для аналізу")
return
html_content = """
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MAI-DX Summary Report</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }
.container { max-width: 1200px; margin: 0 auto; background: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
h1 { color: #333; text-align: center; }
.summary { background: #e8f4f8; padding: 20px; border-radius: 8px; margin: 20px 0; }
.metric { display: inline-block; margin: 10px 20px; }
.metric-value { font-size: 24px; font-weight: bold; color: #007bff; }
.metric-label { color: #666; }
table { width: 100%; border-collapse: collapse; margin: 20px 0; }
th { background: #007bff; color: white; padding: 12px; text-align: left; }
td { padding: 10px; border-bottom: 1px solid #ddd; }
tr:hover { background: #f5f5f5; }
.success { color: #28a745; }
.warning { color: #ffc107; }
.danger { color: #dc3545; }
</style>
</head>
<body>
<div class="container">
<h1>🏥 MAI-DX Summary Report</h1>
"""
# Загальна статистика
total_sessions = len(sessions)
avg_accuracy = sum(s['confidence'] for s in sessions) / total_sessions
avg_cost = sum(s['cost'] for s in sessions) / total_sessions
avg_duration = sum(s['duration'] for s in sessions) / total_sessions
success_rate = sum(1 for s in sessions if s['confidence'] >= 3.0) / total_sessions * 100
html_content += f"""
<div class="summary">
<h2>📊 Загальна статистика</h2>
<div class="metric">
<div class="metric-value">{total_sessions}</div>
<div class="metric-label">Всього сесій</div>
</div>
<div class="metric">
<div class="metric-value">{avg_accuracy:.2f}/5.0</div>
<div class="metric-label">Середня точність</div>
</div>
<div class="metric">
<div class="metric-value">${avg_cost:.2f}</div>
<div class="metric-label">Середня вартість</div>
</div>
<div class="metric">
<div class="metric-value">{avg_duration:.1f}с</div>
<div class="metric-label">Середній час</div>
</div>
<div class="metric">
<div class="metric-value">{success_rate:.1f}%</div>
<div class="metric-label">Успішність</div>
</div>
</div>
<h2>📋 Детальна таблиця сесій</h2>
<table>
<thead>
<tr>
<th>ID сесії</th>
<th>Час</th>
<th>Випадок</th>
<th>Діагноз</th>
<th>Точність</th>
<th>Вартість</th>
<th>Час</th>
<th>Статус</th>
</tr>
</thead>
<tbody>
"""
# Сортуємо сесії за часом
sorted_sessions = sorted(sessions, key=lambda x: x['timestamp'], reverse=True)
for session in sorted_sessions:
status_class = 'success' if session['confidence'] >= 3.0 else 'warning'
html_content += f"""
<tr>
<td>{session['case_id']}</td>
<td>{session['timestamp'][:19]}</td>
<td>{session['case_name']}</td>
<td>{session['diagnosis']}</td>
<td class="{status_class}">{session['confidence']:.1f}/5.0</td>
<td>${session['cost']:.2f}</td>
<td>{session['duration']:.1f}с</td>
<td>{session['status']}</td>
</tr>
"""
html_content += """
</tbody>
</table>
<p style="text-align: center; color: #666; margin-top: 30px;">
Згенеровано: """ + datetime.now().strftime("%Y-%m-%d %H:%M:%S") + """
</p>
</div>
</body>
</html>
"""
with open(output_file, 'w', encoding='utf-8') as f:
f.write(html_content)
print(f"\n✅ Зведений звіт збережено: {output_file}")
def export_to_csv(sessions, output_file="mai_dx_sessions.csv"):
"""Експорт сесій в CSV"""
if not sessions:
print("❌ Немає сесій для експорту")
return
# Створюємо DataFrame
data = []
for session in sessions:
# Підраховуємо агентів та повідомлення
total_messages = 0
unique_agents = set()
for conv in session.get('conversations', []):
for msg in conv.get('messages', []):
total_messages += 1
unique_agents.add(msg['agent_name'])
data.append({
'case_id': session['case_id'],
'timestamp': session['timestamp'],
'case_name': session['case_name'],
'mode': session['mode'],
'diagnosis': session['diagnosis'],
'confidence': session['confidence'],
'cost': session['cost'],
'budget': session['budget'],
'duration': session['duration'],
'iterations': session['iterations'],
'status': session['status'],
'total_messages': total_messages,
'unique_agents': len(unique_agents)
})
df = pd.DataFrame(data)
df.to_csv(output_file, index=False, encoding='utf-8')
print(f"✅ Дані експортовано в CSV: {output_file}")
print(f" Всього записів: {len(df)}")
def main():
parser = argparse.ArgumentParser(description='Аналіз логів MAI-DX')
parser.add_argument('--dir', default='mai_dx_logs', help='Директорія з логами')
parser.add_argument('--case', help='ID конкретної сесії для детального аналізу')
parser.add_argument('--export-csv', action='store_true', help='Експортувати в CSV')
parser.add_argument('--summary', action='store_true', help='Створити зведений HTML звіт')
args = parser.parse_args()
print("🔬 Аналіз логів MAI-DX")
print("=" * 60)
# Завантажуємо сесії
sessions = load_all_sessions(args.dir)
print(f"📁 Знайдено {len(sessions)} сесій в {args.dir}")
if args.case:
# Аналіз конкретної сесії
session = next((s for s in sessions if s['case_id'] == args.case), None)
if session:
analyze_session(session)
else:
print(f"❌ Сесія {args.case} не знайдена")
elif args.export_csv:
# Експорт в CSV
export_to_csv(sessions)
elif args.summary:
# Створення зведеного звіту
generate_summary_report(sessions)
else:
# Загальна статистика
if sessions:
print(f"\n📊 Загальна статистика:")
print(f" - Середня точність: {sum(s['confidence'] for s in sessions) / len(sessions):.2f}/5.0")
print(f" - Середня вартість: ${sum(s['cost'] for s in sessions) / len(sessions):.2f}")
print(f" - Середній час: {sum(s['duration'] for s in sessions) / len(sessions):.1f} секунд")
print(f"\n💡 Для детального аналізу використовуйте:")
print(f" python {__file__} --case <case_id>")
print(f" python {__file__} --export-csv")
print(f" python {__file__} --summary")
if __name__ == "__main__":
main()