MogulojuSai's picture
initial commit
6ee62c7 verified
import streamlit as st
import asyncio
import json
import time
from datetime import datetime
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import pandas as pd
import os
import sys
from pathlib import Path
# Add the main code directory to the path
sys.path.append(str(Path(__file__).parent))
# Import your research workflow (assuming your main code is in code.py)
try:
from code import ResearchWorkflow, ResearchContext, ResearchPhase
except ImportError:
st.error("Could not import the research workflow. Make sure code.py is in the same directory.")
st.stop()
# Page configuration
st.set_page_config(
page_title="Agno Research Assistant",
page_icon="πŸ”¬",
layout="wide",
initial_sidebar_state="expanded"
)
# Custom CSS for better styling
st.markdown("""
<style>
.main-header {
text-align: center;
background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
padding: 2rem;
border-radius: 10px;
color: white;
margin-bottom: 2rem;
}
.metric-card {
background: white;
padding: 1rem;
border-radius: 10px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
border-left: 4px solid #667eea;
}
.status-box {
padding: 1rem;
border-radius: 8px;
margin: 1rem 0;
}
.status-running {
background-color: #fff3cd;
border: 1px solid #ffeaa7;
color: #856404;
}
.status-complete {
background-color: #d4edda;
border: 1px solid #c3e6cb;
color: #155724;
}
.status-error {
background-color: #f8d7da;
border: 1px solid #f5c6cb;
color: #721c24;
}
.insight-item {
background: #f8f9fa;
padding: 1rem;
margin: 0.5rem 0;
border-radius: 8px;
border-left: 3px solid #28a745;
}
.source-item {
background: #e9ecef;
padding: 0.8rem;
margin: 0.3rem 0;
border-radius: 6px;
font-size: 0.9rem;
}
</style>
""", unsafe_allow_html=True)
# Initialize session state
if 'research_history' not in st.session_state:
st.session_state.research_history = []
if 'current_research' not in st.session_state:
st.session_state.current_research = None
if 'workflow_status' not in st.session_state:
st.session_state.workflow_status = "idle"
# Helper functions
def run_async_research(workflow, topic, config):
"""Run the async research workflow in a sync context"""
try:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
result = loop.run_until_complete(workflow.execute(topic, **config))
loop.close()
return result
except Exception as e:
st.error(f"Research failed: {str(e)}")
return None
def format_processing_time(seconds):
"""Format processing time in a human-readable way"""
if seconds < 60:
return f"{seconds:.1f} seconds"
elif seconds < 3600:
minutes = seconds // 60
remaining_seconds = seconds % 60
return f"{int(minutes)}m {remaining_seconds:.0f}s"
else:
hours = seconds // 3600
remaining_minutes = (seconds % 3600) // 60
return f"{int(hours)}h {int(remaining_minutes)}m"
def create_quality_metrics_chart(metrics):
"""Create a radar chart for quality metrics"""
categories = ['Source Quality', 'Academic Ratio', 'Insight Density', 'Verification Rate', 'Confidence']
values = [
metrics.get('average_credibility', 0),
metrics.get('academic_ratio', 0),
min(metrics.get('insight_density', 0) / 2, 1), # Normalize to 0-1
metrics.get('credibility_ratio', 0),
metrics.get('confidence_adjustment', 0)
]
fig = go.Figure()
fig.add_trace(go.Scatterpolar(
r=values,
theta=categories,
fill='toself',
name='Quality Metrics',
fillcolor='rgba(102, 126, 234, 0.2)',
line=dict(color='rgba(102, 126, 234, 1)')
))
fig.update_layout(
polar=dict(
radialaxis=dict(
visible=True,
range=[0, 1]
)),
showlegend=False,
title="Research Quality Metrics",
height=400
)
return fig
def create_source_distribution_chart(sources):
"""Create a pie chart showing source type distribution"""
source_types = {}
for source in sources:
source_type = source.get('source_type', 'unknown')
source_types[source_type] = source_types.get(source_type, 0) + 1
fig = px.pie(
values=list(source_types.values()),
names=list(source_types.keys()),
title="Source Type Distribution",
color_discrete_map={
'academic': '#28a745',
'web': '#007bff',
'unknown': '#6c757d'
}
)
return fig
def create_timeline_chart(research_history):
"""Create a timeline chart of research history"""
if not research_history:
return None
df = pd.DataFrame([
{
'Topic': item['topic'][:50] + '...' if len(item['topic']) > 50 else item['topic'],
'Date': item['timestamp'],
'Processing Time': item['processing_time'],
'Confidence': item['confidence_score'],
'Sources': item['total_sources']
}
for item in research_history
])
fig = px.scatter(
df,
x='Date',
y='Processing Time',
size='Sources',
color='Confidence',
hover_data=['Topic'],
title="Research History Timeline",
color_continuous_scale='Viridis'
)
return fig
# Main header
st.markdown("""
<div class="main-header">
<h1>πŸ”¬ Agno Research Assistant</h1>
<p>Advanced Multi-Agent Research Workflow with AI-Powered Analysis</p>
</div>
""", unsafe_allow_html=True)
# Sidebar configuration
st.sidebar.header("πŸ› οΈ Research Configuration")
# Research topic input
topic = st.sidebar.text_area(
"Research Topic",
placeholder="Enter your research topic here...",
help="Describe what you want to research. Be specific for better results."
)
# Research depth selection
depth = st.sidebar.selectbox(
"Research Depth",
["quick", "standard", "comprehensive"],
index=2,
help="Quick: 5 sources, Standard: 8 sources, Comprehensive: 10+ sources"
)
# Number of sources
sources_required = st.sidebar.slider(
"Number of Sources",
min_value=5,
max_value=20,
value=10,
help="More sources provide better coverage but take longer to process"
)
# Focus areas
st.sidebar.subheader("🎯 Focus Areas")
focus_areas = []
# Predefined focus area templates
focus_templates = {
"Technology Impact": [
"performance metrics",
"adoption rates",
"technical challenges",
"implementation strategies"
],
"Business Analysis": [
"market trends",
"cost-benefit analysis",
"competitive landscape",
"ROI assessment"
],
"Academic Research": [
"literature review",
"methodological approaches",
"empirical findings",
"theoretical frameworks"
]
}
template_choice = st.sidebar.selectbox(
"Use Focus Template",
["Custom"] + list(focus_templates.keys()),
help="Select a template or create custom focus areas"
)
if template_choice != "Custom":
focus_areas = focus_templates[template_choice]
st.sidebar.info(f"Using {template_choice} template: {', '.join(focus_areas)}")
else:
# Custom focus areas
for i in range(4):
focus_area = st.sidebar.text_input(f"Focus Area {i+1}", key=f"focus_{i}")
if focus_area:
focus_areas.append(focus_area)
# Advanced settings
with st.sidebar.expander("βš™οΈ Advanced Settings"):
enable_fact_checking = st.checkbox("Enable Fact Checking", value=True)
confidence_threshold = st.slider("Confidence Threshold", 0.0, 1.0, 0.7, 0.1)
save_report = st.checkbox("Save Report to File", value=True)
# Main content area
col1, col2 = st.columns([2, 1])
with col1:
st.header("πŸ“Š Research Dashboard")
# Research status
status_placeholder = st.empty()
# Progress tracking
progress_placeholder = st.empty()
# Start research button
if st.button("πŸš€ Start Research", type="primary", disabled=not topic):
if topic:
st.session_state.workflow_status = "running"
# Initialize workflow
workflow = ResearchWorkflow()
# Research configuration
config = {
"depth": depth,
"sources_required": sources_required,
"focus_areas": focus_areas
}
# Show running status
with status_placeholder.container():
st.markdown("""
<div class="status-box status-running">
<h4>πŸ”„ Research In Progress</h4>
<p>Your multi-agent research workflow is running...</p>
</div>
""", unsafe_allow_html=True)
# Progress bar
progress_bar = progress_placeholder.progress(0)
# Run research with progress updates
start_time = time.time()
try:
# Phase 1: Search
progress_bar.progress(0.25)
st.info("Phase 1: Information Gathering...")
# Phase 2: Analysis
progress_bar.progress(0.5)
st.info("Phase 2: Analysis and Synthesis...")
# Phase 3: Fact-checking
progress_bar.progress(0.75)
st.info("Phase 3: Fact Checking and Verification...")
# Phase 4: Report generation
progress_bar.progress(0.9)
st.info("Phase 4: Report Generation...")
# Execute research
result = run_async_research(workflow, topic, config)
if result:
progress_bar.progress(1.0)
processing_time = time.time() - start_time
# Store results
st.session_state.current_research = result
st.session_state.workflow_status = "complete"
# Add to history
research_record = {
'topic': topic,
'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
'processing_time': processing_time,
'confidence_score': result.confidence_score,
'total_sources': len(result.sources),
'insights_count': len(result.insights),
'quality_metrics': result.quality_metrics
}
st.session_state.research_history.append(research_record)
# Show success status
with status_placeholder.container():
st.markdown(f"""
<div class="status-box status-complete">
<h4>βœ… Research Completed Successfully!</h4>
<p>Processing time: {format_processing_time(processing_time)}</p>
<p>Confidence score: {result.confidence_score:.0%}</p>
</div>
""", unsafe_allow_html=True)
# Clear progress bar
progress_placeholder.empty()
# Save report if enabled
if save_report:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"research_report_{timestamp}.md"
with open(filename, "w", encoding="utf-8") as f:
f.write(result.final_report)
st.success(f"Report saved as {filename}")
else:
st.session_state.workflow_status = "error"
with status_placeholder.container():
st.markdown("""
<div class="status-box status-error">
<h4>❌ Research Failed</h4>
<p>An error occurred during the research process.</p>
</div>
""", unsafe_allow_html=True)
progress_placeholder.empty()
except Exception as e:
st.session_state.workflow_status = "error"
with status_placeholder.container():
st.markdown(f"""
<div class="status-box status-error">
<h4>❌ Research Failed</h4>
<p>Error: {str(e)}</p>
</div>
""", unsafe_allow_html=True)
progress_placeholder.empty()
# Display current research results
if st.session_state.current_research and st.session_state.workflow_status == "complete":
result = st.session_state.current_research
st.header("πŸ“ˆ Research Results")
# Key metrics
col1_1, col1_2, col1_3, col1_4 = st.columns(4)
with col1_1:
st.metric("Sources Analyzed", len(result.sources))
with col1_2:
st.metric("Key Insights", len(result.insights))
with col1_3:
st.metric("Confidence Score", f"{result.confidence_score:.0%}")
with col1_4:
academic_count = len([s for s in result.sources if s.get('source_type') == 'academic'])
st.metric("Academic Sources", f"{academic_count}/{len(result.sources)}")
# Charts
chart_col1, chart_col2 = st.columns(2)
with chart_col1:
if result.quality_metrics:
quality_chart = create_quality_metrics_chart(result.quality_metrics)
st.plotly_chart(quality_chart, use_container_width=True)
with chart_col2:
source_chart = create_source_distribution_chart(result.sources)
st.plotly_chart(source_chart, use_container_width=True)
# Tabbed content
tab1, tab2, tab3, tab4 = st.tabs(["πŸ“ Executive Summary", "πŸ’‘ Key Insights", "πŸ” Fact Checks", "πŸ“š Sources"])
with tab1:
# Extract executive summary from report
report_lines = result.final_report.split('\n')
in_exec_summary = False
exec_summary = []
for line in report_lines:
if line.strip() == "## Executive Summary":
in_exec_summary = True
continue
elif line.startswith("## ") and in_exec_summary:
break
elif in_exec_summary and line.strip():
exec_summary.append(line)
if exec_summary:
st.markdown('\n'.join(exec_summary))
else:
st.write("Executive summary not available.")
with tab2:
st.subheader("Key Research Insights")
for i, insight in enumerate(result.insights, 1):
st.markdown(f"""
<div class="insight-item">
<strong>{i}.</strong> {insight}
</div>
""", unsafe_allow_html=True)
with tab3:
st.subheader("Fact Verification Results")
if result.fact_checks:
for check in result.fact_checks:
status_icon = "βœ…" if check.get("status") == "supported" else "⚠️"
st.markdown(f"""
{status_icon} **{check.get('evidence_strength', 'unknown').title()} Evidence**
(Score: {check.get('verification_score', 0):.2f})
{check.get('claim', 'Unknown claim')[:200]}...
""")
else:
st.info("No fact checks performed.")
with tab4:
st.subheader("Source Documentation")
# Academic sources
academic_sources = [s for s in result.sources if s.get('source_type') == 'academic']
if academic_sources:
st.write("**Academic Sources:**")
for i, source in enumerate(academic_sources, 1):
authors = ', '.join(source.get('authors', ['Unknown Author']))
st.markdown(f"""
<div class="source-item">
<strong>{i}.</strong> {authors} ({source.get('year', 'n.d.')}).
{source.get('title', 'Unknown Title')}.
<em>{source.get('journal', 'Unknown Journal')}</em>
</div>
""", unsafe_allow_html=True)
# Web sources
web_sources = [s for s in result.sources if s.get('source_type') != 'academic']
if web_sources:
st.write("**Web Sources:**")
for i, source in enumerate(web_sources, 1):
st.markdown(f"""
<div class="source-item">
<strong>{i}.</strong> {source.get('title', 'Unknown Title')}
<br><small>Credibility: {source.get('credibility_score', 0):.2f}/1.0</small>
</div>
""", unsafe_allow_html=True)
# Download report button
st.download_button(
label="πŸ“„ Download Full Report",
data=result.final_report,
file_name=f"research_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.md",
mime="text/markdown"
)
with col2:
st.header("πŸ“Š Analytics")
# Research history
if st.session_state.research_history:
st.subheader("Recent Research")
for item in st.session_state.research_history[-5:]: # Show last 5
with st.expander(f"πŸ” {item['topic'][:40]}..."):
st.write(f"**Date:** {item['timestamp']}")
st.write(f"**Processing Time:** {format_processing_time(item['processing_time'])}")
st.write(f"**Confidence:** {item['confidence_score']:.0%}")
st.write(f"**Sources:** {item['total_sources']}")
st.write(f"**Insights:** {item['insights_count']}")
# Timeline chart
if len(st.session_state.research_history) > 1:
timeline_chart = create_timeline_chart(st.session_state.research_history)
if timeline_chart:
st.plotly_chart(timeline_chart, use_container_width=True)
else:
st.info("No research history yet. Start your first research to see analytics!")
# System information
st.subheader("πŸ”§ System Status")
try:
workflow = ResearchWorkflow()
status = workflow.get_workflow_status()
st.json({
"Framework": status["framework"],
"Active Agents": len(status["agents"]),
"Capabilities": len(status["capabilities"])
})
with st.expander("Agent Details"):
for role, agent_name in status["agents"].items():
st.write(f"**{role.title()}:** {agent_name}")
except Exception as e:
st.error(f"System status unavailable: {str(e)}")
# Footer
st.markdown("---")
st.markdown("""
<div style="text-align: center; color: #666;">
<p>πŸ€– Powered by Agno Framework | Built with Streamlit</p>
<p>Advanced Multi-Agent Research System with AI-Powered Quality Assurance</p>
</div>
""", unsafe_allow_html=True)