"""
AI Papers Intelligence Classifier - Main Gradio Application
Analyzes AI papers from AI-Papers-of-the-Week across the intelligence spectrum
"""
import gradio as gr
import pandas as pd
import plotly.graph_objects as go
import plotly.express as px
from datetime import datetime
from data_fetcher import AIPapersFetcher
from classifier import AIPapersIntelligenceClassifier
from ranker import PaperRanker
from model_manager import ModelManager
from advanced_analyzer import AdvancedAnalyzer
from reasoning_classifier import ReasoningClassifier
# Initialize components
fetcher = AIPapersFetcher()
model_manager = ModelManager()
classifier = AIPapersIntelligenceClassifier()
reasoning_classifier = ReasoningClassifier()
ranker = PaperRanker()
advanced_analyzer = AdvancedAnalyzer()
def analyze_week(year: str, week: str, model_id: str = "keyword",
classification_mode: str = "keyword", use_semantic: bool = False) -> tuple:
"""
Analyze papers from a specific week across the intelligence spectrum
Args:
year: Year to analyze
week: Week to analyze
model_id: Model to use for analysis
classification_mode: Classification mode ('keyword', 'reasoning', 'hybrid')
use_semantic: Whether to use semantic analysis
Returns:
Tuple of (summary_text, statistics_text, top_papers_text, dataframe, chart)
"""
print(f"DEBUG: analyze_week called with year={year}, week={week}, model_id={model_id}, classification_mode={classification_mode}, use_semantic={use_semantic}")
try:
# Update classifier with selected model
if use_semantic:
classifier.use_semantic = True
classifier.model_id = model_id
classifier.model_manager.set_model(model_id)
else:
classifier.use_semantic = False
# Fetch data
year_data = fetcher.fetch_year_data(year)
if not year_data or week not in year_data:
available_weeks = list(year_data.keys()) if year_data else []
error_msg = f"No data found for {year}, week: {week}. Available weeks: {available_weeks[:5]}..."
return error_msg, "", "", None, None, None, None, ""
week_info = year_data[week]
papers = week_info['papers']
total_papers = len(papers)
# Debug: Check if papers have required fields
if total_papers > 0:
first_paper = papers[0]
if 'title' not in first_paper or 'summary' not in first_paper:
error_msg = f"Paper data structure error. Paper fields: {list(first_paper.keys())}"
return error_msg, "", "", None, None, None, None, ""
if total_papers == 0:
return f"No papers found for {week}", "", "", None, None, None, None, None, ""
# Handle classification mode
if classification_mode == "reasoning":
# Use reasoning-based classification for all papers
classified_papers = []
for paper in papers:
reasoning_result = reasoning_classifier.classify_paper(paper)
# Convert reasoning result to classification format
classification_level = reasoning_result.get('category', 'Not Related')
paper['classification_result'] = {
'classification': classification_level,
'classification_reason': reasoning_result.get('analysis', ''),
'agi_score': 0,
'asi_score': 0,
'aci_score': 0,
'ani_score': 0, # Added missing key
'related_score': 0,
'other_ai_score': 0, # Added missing key
'ml_score': 0, # Added missing key
'ds_score': 0, # Added missing key
'combined_score': reasoning_result.get('confidence_score', 0),
'matched_agi_keywords': [],
'matched_asi_keywords': [],
'matched_aci_keywords': [],
'matched_ani_keywords': [], # Added missing key
'matched_other_ai_keywords': [], # Added missing key
'matched_ml_keywords': [], # Added missing key
'matched_ds_keywords': [], # Added missing key
'matched_related_keywords': [],
'semantic_analysis': reasoning_result
}
classified_papers.append(paper)
elif classification_mode == "hybrid":
# Use keyword classification first, then reasoning for top candidates
keyword_classified = classifier.batch_classify(papers)
# Get top 10 papers by keyword score
top_keyword = sorted(keyword_classified,
key=lambda x: x['classification_result']['combined_score'],
reverse=True)[:10]
# Apply reasoning to top papers
for paper in keyword_classified:
if paper in top_keyword:
reasoning_result = reasoning_classifier.classify_paper(paper)
# Override with reasoning result if confidence is high
if reasoning_result.get('confidence_score', 0) > 70:
paper['classification_result']['classification'] = reasoning_result.get('category', paper['classification_result']['classification'])
paper['classification_result']['classification_reason'] = reasoning_result.get('analysis', paper['classification_result']['classification_reason'])
paper['classification_result']['combined_score'] = reasoning_result.get('confidence_score', paper['classification_result']['combined_score'])
paper['classification_result']['semantic_analysis'] = reasoning_result
classified_papers = keyword_classified
else:
# Use keyword classification (default)
classified_papers = classifier.batch_classify(papers)
# Debug: Check first paper classification
if classified_papers:
first_paper = classified_papers[0]
print(f"DEBUG: First paper title: {first_paper.get('title', 'Unknown')}")
print(f"DEBUG: First paper has classification_result: {'classification_result' in first_paper}")
if 'classification_result' in first_paper:
print(f"DEBUG: First paper classification: {first_paper.get('classification_result', {})}")
else:
print(f"DEBUG: First paper keys: {list(first_paper.keys())}")
else:
print("DEBUG: No classified papers found!")
# Get statistics
stats = classifier.get_statistics(classified_papers)
# Rank papers
ranked_papers = ranker.rank_papers(classified_papers, criteria='composite')
# Debug: Check first paper after ranking
if ranked_papers:
first_ranked = ranked_papers[0]
print(f"DEBUG: After ranking - First paper title: {first_ranked.get('title', 'Unknown')}")
print(f"DEBUG: After ranking - First paper has classification_result: {'classification_result' in first_ranked}")
if 'classification_result' in first_ranked:
print(f"DEBUG: After ranking - First paper classification: {first_ranked.get('classification_result', {})}")
else:
print(f"DEBUG: After ranking - First paper keys: {list(first_ranked.keys())}")
else:
print("DEBUG: No ranked papers found!")
# Filter for AGI/ASI related papers
relevant_papers = ranker.filter_by_classification(ranked_papers, min_level='Narrow AI')
# Generate summary
summary = generate_weekly_summary(year, week, total_papers, stats, relevant_papers, model_id, use_semantic)
# Generate statistics
stats_text = generate_statistics_text(stats)
# Generate top papers
top_papers_text = generate_top_papers_text(ranked_papers[:10])
# Create dataframe for display
df_data = []
for paper in ranked_papers:
# Debug: Check if classification_result exists
if 'classification_result' not in paper:
print(f"DEBUG: Paper missing classification_result: {paper.get('title', 'Unknown')}")
continue
classification_result = paper['classification_result']
if 'classification' not in classification_result:
print(f"DEBUG: Paper missing classification in result: {paper.get('title', 'Unknown')}")
print(f"DEBUG: classification_result keys: {list(classification_result.keys())}")
continue
semantic_info = ""
if paper.get('semantic_analysis'):
semantic_info = f" ({paper['semantic_analysis'].get('model_used', 'N/A')})"
# Get links
paper_link = paper.get('links', {}).get('paper', '')
tweet_link = paper.get('links', {}).get('tweet', '')
# Create clickable links
paper_link_html = f'๐ Paper' if paper_link else ''
tweet_link_html = f'๐ฆ Tweet' if tweet_link else ''
links_html = ' | '.join(filter(None, [paper_link_html, tweet_link_html]))
# Add color-coded classification badge
classification = classification_result['classification']
classification_colors = {
'ASI': '#7C3AED',
'AGI': '#00D4AA',
'ACI': '#F59E0B',
'ANI': '#64748B',
'Other AI': '#3B82F6',
'ML': '#10B981',
'DS': '#F97316',
'Not Related': '#EF4444'
}
color = classification_colors.get(classification, '#64748B')
classification_html = f'{classification}'
df_data.append({
'Rank': paper.get('rank_position', 0),
'Title': paper.get('title', 'Unknown'), # Full title
'Classification': classification_html,
'ASI Score': classification_result.get('asi_score', 0),
'AGI Score': classification_result.get('agi_score', 0),
'ACI Score': classification_result.get('aci_score', 0),
'ANI Score': classification_result.get('ani_score', 0),
'Other AI Score': classification_result.get('other_ai_score', 0),
'ML Score': classification_result.get('ml_score', 0),
'DS Score': classification_result.get('ds_score', 0),
'Combined Score': classification_result.get('combined_score', 0),
'Final Rank': paper.get('final_rank', 0),
'Model': semantic_info,
'Links': links_html
})
df = pd.DataFrame(df_data)
# Create visualization charts
classification_chart = create_classification_chart(stats)
ranking_chart = create_ranking_chart(ranked_papers)
scatter_chart = create_scatter_chart(ranked_papers)
# Generate advanced analysis report
advanced_report = advanced_analyzer.generate_analysis_report(ranked_papers)
return summary, stats_text, top_papers_text, df, classification_chart, ranking_chart, scatter_chart, advanced_report
except Exception as e:
error_msg = f"Error analyzing week: {str(e)}"
return error_msg, "", "", None, None, None, None, ""
def generate_weekly_summary(year: str, week: str, total_papers: int,
stats: dict, relevant_papers: list, model_id: str,
use_semantic: bool) -> str:
"""Generate summary text for weekly analysis"""
summary = f"# ๐ง AI Papers Intelligence Classifier: {week}, {year}\n\n"
summary += f"## ๐ Overview\n\n"
summary += f"- **Analysis Method**: {'Semantic AI (' + model_id + ')' if use_semantic else 'Keyword-Based'}\n"
summary += f"- **Total Papers Analyzed**: {total_papers}\n"
summary += f"- **AGI/ASI Related Papers**: {stats['agi'] + stats['asi'] + stats['aci']}\n"
summary += f"- **AGI Papers**: {stats['agi']}\n"
summary += f"- **ASI Papers**: {stats['asi']}\n"
summary += f"- **ACI Papers**: {stats['aci']}\n"
summary += f"- **ANI Papers**: {stats['ani']}\n"
summary += f"- **Other AI Papers**: {stats['other_ai']}\n"
summary += f"- **ML Papers**: {stats['ml']}\n"
summary += f"- **DS Papers**: {stats['ds']}\n"
summary += f"- **Not Related**: {stats['not_related']}\n"
summary += f"- **Relevance Rate**: {stats['relevance_rate']}%\n\n"
if relevant_papers:
summary += f"## ๐ฏ Top Intelligence Papers\n\n"
for i, paper in enumerate(relevant_papers[:5], 1):
title = paper.get('title', 'Unknown')
classification = paper['classification_result']['classification']
combined_score = paper['classification_result']['combined_score']
summary += f"{i}. **{title}**\n"
summary += f" - Classification: {classification}\n"
summary += f" - Relevance Score: {combined_score}/100\n\n"
else:
summary += "## ๐ฏ Top AGI/ASI Papers\n\n"
summary += "No AGI/ASI related papers found in this week.\n\n"
return summary
def generate_statistics_text(stats: dict) -> str:
"""Generate statistics text"""
text = "## ๐ Classification Statistics\n\n"
text += f"- **Total Papers**: {stats['total']}\n"
text += f"- **ASI**: {stats['asi']} ({stats['asi']/stats['total']*100:.1f}%)\n"
text += f"- **AGI**: {stats['agi']} ({stats['agi']/stats['total']*100:.1f}%)\n"
text += f"- **ACI**: {stats['aci']} ({stats['aci']/stats['total']*100:.1f}%)\n"
text += f"- **ANI**: {stats['ani']} ({stats['ani']/stats['total']*100:.1f}%)\n"
text += f"- **Other AI**: {stats['other_ai']} ({stats['other_ai']/stats['total']*100:.1f}%)\n"
text += f"- **ML**: {stats['ml']} ({stats['ml']/stats['total']*100:.1f}%)\n"
text += f"- **DS**: {stats['ds']} ({stats['ds']/stats['total']*100:.1f}%)\n"
text += f"- **Not Related**: {stats['not_related']} ({stats['not_related']/stats['total']*100:.1f}%)\n"
text += f"- **Overall Relevance Rate**: {stats['relevance_rate']}%\n\n"
return text
def generate_top_papers_text(papers: list) -> str:
"""Generate top papers text"""
text = "## ๐ Top 10 Ranked Papers\n\n"
for i, paper in enumerate(papers, 1):
title = paper.get('title', 'Unknown')
# Defensive: Check if classification_result exists
if 'classification_result' not in paper:
text += f"### {i}. {title}\n"
text += "- **Classification**: Error - Missing classification result\n\n"
continue
classification_result = paper['classification_result']
classification = classification_result.get('classification', 'Error')
agi_score = classification_result.get('agi_score', 0)
asi_score = classification_result.get('asi_score', 0)
combined_score = classification_result.get('combined_score', 0)
final_rank = paper.get('final_rank', 0)
# Get links
paper_link = paper.get('links', {}).get('paper', '')
tweet_link = paper.get('links', {}).get('tweet', '')
text += f"### {i}. {title}\n"
text += f"- **Classification**: {classification}\n"
text += f"- **AGI Keywords**: {agi_score}\n"
text += f"- **ASI Keywords**: {asi_score}\n"
text += f"- **Combined Score**: {combined_score}/100\n"
text += f"- **Final Rank**: {final_rank}/100\n"
if paper_link:
text += f"- **๐ Paper**: [{paper_link}]({paper_link})\n"
if tweet_link:
text += f"- **๐ฆ Tweet**: [{tweet_link}]({tweet_link})\n"
text += "\n"
return text
def create_classification_chart(stats: dict) -> go.Figure:
"""Create a pie chart showing classification distribution"""
labels = ['ASI', 'AGI', 'ACI', 'ANI', 'Other AI', 'ML', 'DS', 'Not Related']
values = [stats['asi'], stats['agi'], stats['aci'],
stats['ani'], stats['other_ai'], stats['ml'], stats['ds'],
stats['not_related']]
# Modern color palette
colors = ['#7C3AED', '#00D4AA', '#F59E0B', '#64748B', '#3B82F6', '#10B981', '#F97316', '#EF4444']
fig = go.Figure(data=[go.Pie(
labels=labels,
values=values,
marker=dict(
colors=colors,
line=dict(color='white', width=2)
),
textinfo='label+percent',
textposition='inside',
textfont=dict(size=14, family='Arial'),
hole=0.4,
hovertemplate='%{label}
Count: %{value}
Percentage: %{percent}
Final Rank: %{y:.1f}
Combined Score: %{y:.1f}
' +
'Relevance: %{x:.1f}
' +
'Novelty: %{y:.1f}
' +
'Classification: %{customdata}
Relevance Rate: %{y:.1f}%
Intelligence Papers: %{y}
Analyze AI papers from AI-Papers-of-the-Week across the intelligence spectrum: ANI, AGI, ASI, ACI, ML, and DS.