formatted_content = re.sub(r'\*(.*?)\*', r'\1', formatted_content)
# Convert newlines to
for better formatting
formatted_content = formatted_content.replace('\n', '
')
# Convert numbered lists
formatted_content = re.sub(r'^(\d+\.\s)', r'
\1', formatted_content, flags=re.MULTILINE)
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
html_response = f"""
💬 Response
{formatted_content}
"""
return html_response
def get_example_queries(self):
"""Return categorized example queries"""
return {
"📰 Latest News": [
"What are the top 3 news stories today?",
"Latest developments in AI technology this week",
"Recent political events in the United States",
"Breaking news about climate change",
"What happened in the stock market today?"
],
"💰 Financial Data": [
"Current price of Bitcoin",
"Tesla stock price today",
"How is the S&P 500 performing today?",
"Latest cryptocurrency market trends",
"What's the current inflation rate?"
],
"🌤️ Weather Updates": [
"Current weather in New York City",
"Weather forecast for London this week",
"Is it going to rain in San Francisco today?",
"Temperature in Tokyo right now",
"Weather conditions in Sydney"
],
"🔬 Science & Technology": [
"Latest breakthroughs in fusion energy",
"Recent discoveries in space exploration",
"New developments in quantum computing",
"Latest medical research findings",
"Recent advances in renewable energy"
],
"🏆 Sports & Entertainment": [
"Latest football match results",
"Who won the recent tennis tournament?",
"Box office numbers for this weekend",
"Latest movie releases this month",
"Recent celebrity news"
],
"🔍 Fact Checking": [
"Is it true that the Earth's population reached 8 billion?",
"Verify: Did company X announce layoffs recently?",
"Check if the recent earthquake in Turkey was magnitude 7+",
"Confirm the latest unemployment rate statistics",
"Verify recent claims about electric vehicle sales"
]
}
def get_custom_prompt_examples(self):
"""Return custom system prompt examples"""
return {
"🎯 Fact-Checker": "You are a fact-checker. Always verify claims with multiple sources and clearly indicate confidence levels in your assessments. Use phrases like 'highly confident', 'moderately confident', or 'requires verification' when presenting information.",
"📊 News Analyst": "You are a news analyst. Focus on providing balanced, unbiased reporting with multiple perspectives on current events. Always present different viewpoints and avoid partisan language.",
"💼 Financial Advisor": "You are a financial advisor. Provide accurate market data with context about trends and implications for investors. Always include disclaimers about market risks and the importance of professional financial advice.",
"🔬 Research Assistant": "You are a research assistant specializing in scientific and technical information. Provide detailed, evidence-based responses with proper context about methodology and limitations of studies.",
"🌍 Global News Correspondent": "You are a global news correspondent. Focus on international events and their interconnections. Provide cultural context and explain how events in one region might affect others.",
"📈 Market Analyst": "You are a market analyst. Provide detailed financial analysis including technical indicators, market sentiment, and economic factors affecting price movements."
}
def create_interface():
fact_checker = RealTimeFactChecker()
# Modern CSS design
custom_css = """
/* Reset and base styles */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: #f8fafc;
color: #334155;
line-height: 1.6;
}
.gradio-container {
max-width: 1200px !important;
margin: 0 auto;
padding: 20px;
background: #f8fafc;
}
/* Header */
.app-header {
background: linear-gradient(135deg, #3b82f6 0%, #1e40af 100%);
color: white;
padding: 2rem;
border-radius: 16px;
margin-bottom: 2rem;
text-align: center;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
.app-header h1 {
font-size: 2.5rem;
font-weight: 700;
margin-bottom: 0.5rem;
}
.app-header p {
font-size: 1.1rem;
opacity: 0.9;
font-weight: 400;
}
/* Cards */
.card {
background: white;
border-radius: 12px;
padding: 1.5rem;
margin-bottom: 1.5rem;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
border: 1px solid #e2e8f0;
}
.card h3 {
color: #1e293b;
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 1rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
/* Status indicators */
.status-success {
background: #10b981;
color: white;
padding: 0.75rem 1rem;
border-radius: 8px;
font-weight: 500;
}
.status-warning {
background: #f59e0b;
color: white;
padding: 0.75rem 1rem;
border-radius: 8px;
font-weight: 500;
}
.status-error {
background: #ef4444;
color: white;
padding: 0.75rem 1rem;
border-radius: 8px;
font-weight: 500;
}
/* Example buttons */
.example-btn {
background: #f1f5f9;
border: 1px solid #e2e8f0;
color: #475569;
padding: 0.75rem 1rem;
border-radius: 8px;
cursor: pointer;
transition: all 0.2s ease;
margin: 0.25rem;
font-size: 0.875rem;
text-align: left;
}
.example-btn:hover {
background: #e2e8f0;
border-color: #3b82f6;
color: #1e40af;
}
/* Custom prompt examples */
.prompt-example {
background: #f8fafc;
border: 1px solid #e2e8f0;
border-radius: 8px;
padding: 1rem;
margin: 0.5rem 0;
cursor: pointer;
transition: all 0.2s ease;
}
.prompt-example:hover {
background: #e2e8f0;
border-color: #3b82f6;
}
.prompt-example-title {
font-weight: 600;
color: #1e40af;
margin-bottom: 0.5rem;
}
.prompt-example-text {
font-size: 0.875rem;
color: #64748b;
line-height: 1.4;
}
/* Response card */
.response-card {
background: white;
border-radius: 12px;
border: 1px solid #e2e8f0;
overflow: hidden;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
}
.response-header {
background: #f8fafc;
padding: 1.5rem;
border-bottom: 1px solid #e2e8f0;
}
.query-section h3 {
color: #1e293b;
font-size: 1.1rem;
font-weight: 600;
margin-bottom: 0.5rem;
}
.query-text {
background: #e2e8f0;
padding: 1rem;
border-radius: 8px;
font-style: italic;
color: #475569;
}
.meta-info {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 1rem;
font-size: 0.875rem;
color: #64748b;
}
.timestamp, .response-time {
background: #f1f5f9;
padding: 0.5rem 0.75rem;
border-radius: 6px;
font-weight: 500;
}
.response-content {
padding: 1.5rem;
}
.response-content h3 {
color: #1e293b;
font-size: 1.1rem;
font-weight: 600;
margin-bottom: 1rem;
}
.response-text {
color: #374151;
line-height: 1.7;
font-size: 0.95rem;
}
.response-text strong {
color: #1e293b;
font-weight: 600;
}
.response-text em {
color: #6366f1;
font-style: italic;
}
/* Tool info card */
.tool-info-card {
background: white;
border-radius: 12px;
border: 1px solid #e2e8f0;
overflow: hidden;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
}
.tool-info-header {
background: #f0f9ff;
padding: 1rem 1.5rem;
border-bottom: 1px solid #e2e8f0;
display: flex;
align-items: center;
gap: 0.75rem;
}
.tool-info-header .icon {
font-size: 1.5rem;
}
.tool-info-header h3 {
color: #1e40af;
font-size: 1.1rem;
font-weight: 600;
margin: 0;
}
.tool-info-content {
padding: 1.5rem;
}
.tool-item {
background: #f8fafc;
border-radius: 8px;
padding: 1rem;
margin-bottom: 0.75rem;
border: 1px solid #e2e8f0;
}
.tool-item:last-child {
margin-bottom: 0;
}
.tool-name {
font-weight: 600;
color: #1e293b;
margin-bottom: 0.5rem;
}
.tool-param {
font-size: 0.875rem;
color: #64748b;
margin-left: 1rem;
}
/* Accordion styles */
.accordion-header {
background: #f8fafc;
border: 1px solid #e2e8f0;
border-radius: 8px;
padding: 1rem;
cursor: pointer;
transition: all 0.2s ease;
margin-bottom: 0.5rem;
}
.accordion-header:hover {
background: #e2e8f0;
}
.accordion-content {
padding: 1rem;
border: 1px solid #e2e8f0;
border-top: none;
border-radius: 0 0 8px 8px;
background: white;
}
/* Performance badge */
.performance-badge {
background: #10b981;
color: white;
padding: 0.5rem 1rem;
border-radius: 20px;
font-size: 0.875rem;
font-weight: 500;
display: inline-block;
}
/* Buttons */
.btn-primary {
background: #3b82f6;
color: white;
border: none;
padding: 0.75rem 1.5rem;
border-radius: 8px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
}
.btn-primary:hover {
background: #2563eb;
}
.btn-secondary {
background: #f1f5f9;
color: #475569;
border: 1px solid #e2e8f0;
padding: 0.75rem 1.5rem;
border-radius: 8px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
}
.btn-secondary:hover {
background: #e2e8f0;
border-color: #3b82f6;
}
/* Footer */
.footer {
background: #1e293b;
color: white;
padding: 2rem;
border-radius: 12px;
margin-top: 2rem;
text-align: center;
}
.footer h3 {
color: white;
margin-bottom: 1rem;
}
.footer a {
color: #60a5fa;
text-decoration: none;
font-weight: 500;
}
.footer a:hover {
color: #93c5fd;
text-decoration: underline;
}
.footer ul {
list-style: none;
padding: 0;
margin: 1rem 0;
}
.footer ul li {
margin: 0.5rem 0;
}
/* Responsive design */
@media (max-width: 768px) {
.gradio-container {
padding: 1rem;
}
.app-header h1 {
font-size: 2rem;
}
.card {
padding: 1rem;
}
.meta-info {
flex-direction: column;
gap: 0.5rem;
}
}
"""
def validate_api_key(api_key):
if not api_key or api_key.strip() == "":
return "❌ Please enter a valid API key", False
success, message = fact_checker.initialize_client(api_key.strip())
return message, success
def process_query(query, model, temperature, api_key, system_prompt):
if not api_key or api_key.strip() == "":
return "❌ Please set your API key first", "", ""
if not query or query.strip() == "":
return "❌ Please enter a query", "", ""
# Initialize client if not already done
if not fact_checker.client:
success, message = fact_checker.initialize_client(api_key.strip())
if not success:
return message, "", ""
response, tool_info, response_time = fact_checker.query_compound_model(
query.strip(), model, temperature, system_prompt.strip() if system_prompt else None
)
# Format response with HTML
formatted_response = fact_checker.format_response(response, query, response_time)
return formatted_response, tool_info or "", f"⚡ Response time: {response_time}s"
def reset_system_prompt():
return fact_checker.get_system_prompt()
def load_example(example_text):
return example_text
def load_custom_prompt(prompt_text):
return prompt_text
# Create the Gradio interface
with gr.Blocks(title="Real-time Fact Checker & News Agent", css=custom_css) as demo:
# Header
gr.HTML("""
""")
with gr.Row():
with gr.Column(scale=2):
# API Key section
gr.HTML('')
gr.HTML('
🔑 API Configuration
')
api_key_input = gr.Textbox(
label="Groq API Key",
placeholder="Enter your Groq API key here...",
type="password",
info="Get your free API key from https://console.groq.com/"
)
api_status = gr.Textbox(
label="Status",
value="⚠️ Please enter your API key",
interactive=False
)
validate_btn = gr.Button("Validate API Key", variant="secondary")
gr.HTML('')
# Advanced options
gr.HTML('')
gr.HTML('
⚙️ Advanced Options
')
# Custom System Prompt Examples
with gr.Accordion("📝 System Prompt Examples", open=False):
gr.Markdown("**Click any example to load it as your system prompt:**")
custom_prompts = fact_checker.get_custom_prompt_examples()
for title, prompt in custom_prompts.items():
with gr.Row():
prompt_btn = gr.Button(title, variant="secondary", size="sm")
prompt_btn.click(
fn=lambda p=prompt: p,
outputs=[gr.Textbox(elem_id="system_prompt_input")]
)
with gr.Accordion("🔧 System Prompt Customization", open=False):
system_prompt_input = gr.Textbox(
label="System Prompt",
value=fact_checker.get_system_prompt(),
lines=8,
info="Customize how the AI behaves and responds",
elem_id="system_prompt_input"
)
reset_prompt_btn = gr.Button("Reset to Default", variant="secondary", size="sm")
# Add buttons for each custom prompt
gr.Markdown("**Quick Load Custom Prompts:**")
custom_prompts = fact_checker.get_custom_prompt_examples()
for title, prompt in custom_prompts.items():
prompt_btn = gr.Button(title, variant="secondary", size="sm")
prompt_btn.click(
fn=lambda p=prompt: p,
outputs=[system_prompt_input]
)
gr.HTML('')
# Query section
gr.HTML('')
gr.HTML('
💭 Your Query
')
query_input = gr.Textbox(
label="Ask anything that requires real-time information",
placeholder="e.g., What are the latest AI developments today?",
lines=4
)
with gr.Row():
model_choice = gr.Dropdown(
choices=fact_checker.model_options,
value="compound-beta",
label="Model",
info="compound-beta: More capable | compound-beta-mini: Faster"
)
temperature = gr.Slider(
minimum=0.0,
maximum=1.0,
value=0.7,
step=0.1,
label="Temperature",
info="Higher = more creative, Lower = more focused"
)
submit_btn = gr.Button("🔍 Get Real-time Information", variant="primary", size="lg")
clear_btn = gr.Button("Clear", variant="secondary")
gr.HTML('')
with gr.Column(scale=1):
# Example queries
gr.HTML('')
gr.HTML('
📝 Example Queries
')
gr.Markdown("Click any example to load it:")
examples = fact_checker.get_example_queries()
with gr.Accordion("📰 Latest News", open=True):
for query in examples["📰 Latest News"]:
example_btn = gr.Button(query, variant="secondary", size="sm")
example_btn.click(
fn=lambda q=query: q,
outputs=[query_input]
)
with gr.Accordion("💰 Financial Data", open=False):
for query in examples["💰 Financial Data"]:
example_btn = gr.Button(query, variant="secondary", size="sm")
example_btn.click(
fn=lambda q=query: q,
outputs=[query_input]
)
with gr.Accordion("🌤️ Weather Updates", open=False):
for query in examples["🌤️ Weather Updates"]:
example_btn = gr.Button(query, variant="secondary", size="sm")
example_btn.click(
fn=lambda q=query: q,
outputs=[query_input]
)
with gr.Accordion("🔬 Science & Technology", open=False):
for query in examples["🔬 Science & Technology"]:
example_btn = gr.Button(query, variant="secondary", size="sm")
example_btn.click(
fn=lambda q=query: q,
outputs=[query_input]
)
with gr.Accordion("🏆 Sports & Entertainment", open=False):
for query in examples["🏆 Sports & Entertainment"]:
example_btn = gr.Button(query, variant="secondary", size="sm")
example_btn.click(
fn=lambda q=query: q,
outputs=[query_input]
)
with gr.Accordion("🔍 Fact Checking", open=False):
for query in examples["🔍 Fact Checking"]:
example_btn = gr.Button(query, variant="secondary", size="sm")
example_btn.click(
fn=lambda q=query: q,
outputs=[query_input]
)
gr.HTML('')
# Results section
gr.HTML('📊 Results
')
with gr.Row():
with gr.Column(scale=2):
response_output = gr.HTML(
value="Your response will appear here...
"
)
with gr.Column(scale=1):
tool_info_output = gr.HTML(
value="Tool execution details will appear here...
"
)
performance_output = gr.Textbox(
label="Performance",
value="",
interactive=False
)
# Event handlers
validate_btn.click(
fn=validate_api_key,
inputs=[api_key_input],
outputs=[api_status, gr.State()]
)
reset_prompt_btn.click(
fn=reset_system_prompt,
outputs=[system_prompt_input]
)
submit_btn.click(
fn=process_query,
inputs=[query_input, model_choice, temperature, api_key_input, system_prompt_input],
outputs=[response_output, tool_info_output, performance_output]
)
clear_btn.click(
fn=lambda: ("", "Your response will appear here...
", "Tool execution details will appear here...
", ""),
outputs=[query_input, response_output, tool_info_output, performance_output]
)
# Footer
gr.HTML("""
""")
return demo
# Launch the application
if __name__ == "__main__":
demo = create_interface()
demo.launch(
share=True
)