Pratik333's picture
Update app.py
1a0aefb verified
import streamlit as st
import urllib.request
import json
import requests
import os
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_openai import ChatOpenAI
# Set OpenAI API key
os.environ["OPENAI_API_KEY"] = "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"
def fetch_ai_news(num_articles=10):
"""
Fetches top AI news using the GNews API and returns a list of articles with their details.
"""
api_key = "4e21d7361fdd189f4243c9df6725fb60"
url = f"https://gnews.io/api/v4/search?q=artificial+intelligence&lang=en&country=us&max={num_articles}&sortby=publishedAt&apikey={api_key}"
try:
with urllib.request.urlopen(url) as response:
data = json.loads(response.read().decode("utf-8"))
return data.get("articles", [])
except Exception as e:
st.error(f"An error occurred while fetching AI news: {e}")
return []
def scrape_content(url: str) -> str:
"""
Scrapes the content of a given link using Jina AI.
"""
try:
response = requests.get("https://r.jina.ai/" + url)
if response.status_code == 200:
return response.text
else:
st.error(f"Failed to fetch the content from {url}. Status code: {response.status_code}")
return ""
except Exception as e:
st.error(f"An error occurred while scraping {url}: {e}")
return ""
def generate_blog(content: str, title: str, instructions: str = "") -> str:
"""
Generates a professional-quality blog based on the scraped content and user instructions.
"""
system_prompt = """You are a professional blog writer specializing in creating detailed, insightful, and engaging blogs about AI and technology.
Follow these guidelines to create high-quality content:
1. Structure:
- Create an engaging title that captures attention
- Write a compelling introduction that sets the context
- Develop a well-organized main body with detailed analysis
- Include practical implications and real-world applications
- Conclude with key points and future outlook
2. Style:
- Maintain a professional yet conversational tone
- Use clear paragraphs and transitions
- Include relevant examples and case studies
- Balance technical detail with accessibility
- Incorporate industry insights and expert perspectives
3. Technical Accuracy:
- Verify technical concepts and terminology
- Explain complex ideas clearly
- Provide context for technical innovations
- Include relevant statistics and data points
- Reference key developments and trends
4. Engagement:
- Use engaging subheadings
- Include relevant quotes when appropriate
- Ask thought-provoking questions
- Provide actionable insights
- Create a narrative flow
5. SEO Optimization:
- Use relevant keywords naturally
- Create scannable content with proper formatting
- Include meta description suggestions
- Structure headings hierarchically
- Optimize for readability
Ensure the content is:
- Well-researched and accurate
- Engaging and valuable to readers
- Properly structured and formatted
- Technical yet accessible
- Original and insightful"""
if instructions:
system_prompt += f"\n\nAdditional instructions: {instructions}"
chat = ChatOpenAI(model="gpt-4o-mini")
messages = [
SystemMessage(content=system_prompt),
HumanMessage(content=f"Content: {content}\n\nGenerate a blog with title: {title}")
]
response = chat(messages)
return response.content
def modify_blog(blog_content: str, modification_instructions: str) -> str:
"""
Modifies an existing blog based on user instructions while maintaining quality and coherence.
"""
system_prompt = """ Modifies an existing blog based on user instructions while maintaining quality and coherence.
Makes changes visibly apparent to the user.
"""
system_prompt = """You are an expert blog editor specializing in AI and technology content. Your task is to modify the provided blog according to the user's instructions while maintaining its professional quality.
Follow these two key guidelines:
1. Content Modification:
- Apply requested changes precisely while preserving core message
- Maintain professional quality, technical accuracy, and readability
- Ensure smooth transitions and logical flow throughout the modified content
- Make the requested changes regardless of the type (shortening, expanding, changing tone, etc.)
2. Visibility of Changes:
- Add a "## MODIFICATIONS SUMMARY" section at the very end of the blog
- List 2-4 bullet points that clearly explain what major changes were made
- Be specific about what was modified (e.g., "Shortened introduction by 40%", "Added new section on ethics")
Return the complete modified blog with the summary section at the end."""
chat = ChatOpenAI(model="gpt-4o-mini")
messages = [
SystemMessage(content=system_prompt),
HumanMessage(content=f"Original blog:\n\n{blog_content}\n\nPlease modify the blog according to these instructions:\n{modification_instructions}")
]
response = chat(messages)
return response.content
def generate_newspaper(articles: list) -> str:
"""
Generates a comprehensive multi-page newspaper format with in-depth analysis of AI news.
"""
system_prompt = """You are an experienced newspaper editor-in-chief specializing in AI and technology. Create a comprehensive, multi-page newspaper that deeply analyzes the provided articles.
NEWSPAPER STRUCTURE:
FRONT PAGE:
1. Main Headline & Lead Story
- Compelling primary headline
- Engaging subheadline
- In-depth analysis of key story
- Related infographic descriptions
- Expert quotes and insights
TECHNOLOGY SECTION:
2. Technical Deep Dives
- Detailed technical analysis
- Architecture and implementation details
- Expert technical perspectives
- Innovation challenges and solutions
- Future technical implications
BUSINESS & INDUSTRY:
3. Market Impact Analysis
- Industry trends and patterns
- Market predictions
- Investment implications
- Startup ecosystem insights
- Corporate strategy analysis
SOCIETY & ETHICS:
4. Societal Implications
- Workforce impact analysis
- Ethical considerations
- Policy and regulation updates
- Privacy and security concerns
- Social responsibility discussion
INNOVATION SPOTLIGHT:
5. Research & Development
- Latest breakthroughs
- Academic perspectives
- Emerging technologies
- Innovation roadmaps
- Future predictions
EDITORIAL & OPINION:
6. Expert Commentary
- Industry leader perspectives
- Academic viewpoints
- Policy maker opinions
- Public discourse analysis
- Strategic recommendations
FORMAT GUIDELINES:
- Use newspaper-style formatting
- Include clear section breaks
- Add relevant subheadings
- Maintain consistent style
- Use proper citations
WRITING STYLE:
- Professional and authoritative
- Technically accurate
- Balanced and objective
- Engaging and insightful
- Forward-thinking
Create a cohesive narrative that connects related stories and provides comprehensive coverage of the AI landscape."""
chat = ChatOpenAI(model="gpt-4o-mini")
messages = [
SystemMessage(content=system_prompt),
HumanMessage(content=f"Articles to include:\n\n{json.dumps(articles, indent=2)}\n\nGenerate a comprehensive newspaper analyzing these articles.")
]
response = chat(messages)
return response.content
# Streamlit UI with enhanced styling
st.set_page_config(page_title="AI News Hub", page_icon="πŸ“°", layout="wide")
# Custom CSS
st.markdown("""
<style>
.main {
padding: 2rem;
}
.stButton>button {
width: 100%;
border-radius: 5px;
height: 3em;
background-color: #4CAF50;
color: white;
}
.stTextInput>div>div>input {
border-radius: 5px;
}
.stSelectbox>div>div>input {
border-radius: 5px;
}
.news-card {
padding: 1rem;
border-radius: 10px;
border: 1px solid #e0e0e0;
margin: 1rem 0;
}
.tab-content {
padding: 1rem;
}
.card {
padding: 1.5rem;
border-radius: 10px;
border: 1px solid #e0e0e0;
margin-bottom: 1.5rem;
background-color: #f9f9f9;
}
</style>
""", unsafe_allow_html=True)
# Main title with custom styling
st.title("πŸ€– AI News Hub")
st.markdown("---")
# Initialize session state
if "articles" not in st.session_state:
st.session_state.articles = []
if "custom_links" not in st.session_state:
st.session_state.custom_links = []
if "generated_blogs" not in st.session_state:
st.session_state.generated_blogs = {}
if "newspaper" not in st.session_state:
st.session_state.newspaper = ""
# Sidebar configuration
with st.sidebar:
st.header("βš™οΈ Configuration")
st.markdown("---")
# News fetch configuration
st.subheader("πŸ“Š News Settings")
num_articles = st.slider(
"Number of articles to fetch:",
min_value=0,
max_value=10,
value=5,
step=5,
help="Select how many AI news articles to fetch"
)
# Custom link input
st.subheader("πŸ”— Add Custom Link")
with st.form("custom_link_form"):
custom_url = st.text_input("URL:", placeholder="https://example.com")
custom_title = st.text_input("Title:", placeholder="Article title")
custom_source = st.text_input("Source:", placeholder="Website name")
submitted = st.form_submit_button("Add Link")
if submitted and custom_url and custom_title:
st.session_state.custom_links.append({
'url': custom_url,
'title': custom_title,
'source': {'name': custom_source or 'Custom Source'},
'publishedAt': 'Custom',
'description': 'User-added article'
})
st.success("βœ… Link added successfully!")
# Create main tabs for the application
news_tab, blog_tab, newspaper_tab = st.tabs([
"πŸ“° AI Fetch News",
"✍️ Blog Generation",
"πŸ“„ Newspaper"
])
# TAB 1: AI Fetch News
with news_tab:
st.header("πŸ” Latest AI News")
if st.button("πŸ”„ Fetch Latest AI News", help="Get fresh AI news articles"):
with st.spinner("Fetching latest news..."):
st.session_state.articles = fetch_ai_news(num_articles)
st.success(f"πŸ“š {len(st.session_state.articles)} articles fetched!")
# Display all sources
all_sources = st.session_state.articles + st.session_state.custom_links
if all_sources:
st.subheader("πŸ“° Available Sources")
# Create tabs for different source types
fetched_news_tab, custom_links_tab = st.tabs(["πŸ“„ Fetched News", "πŸ”— Custom Links"])
with fetched_news_tab:
if st.session_state.articles:
for i, article in enumerate(st.session_state.articles):
with st.container():
st.markdown(f"""
<div class="news-card">
<h3>{article['title']}</h3>
<p><strong>Source:</strong> {article['source']['name']}</p>
<p><strong>Published:</strong> {article['publishedAt']}</p>
<p>{article['description']}</p>
</div>
""", unsafe_allow_html=True)
else:
st.info("No fetched news yet. Click 'Fetch Latest AI News' to get started.")
with custom_links_tab:
if st.session_state.custom_links:
for i, link in enumerate(st.session_state.custom_links):
with st.container():
st.markdown(f"""
<div class="news-card">
<h3>{link['title']}</h3>
<p><strong>Source:</strong> {link['source']['name']}</p>
<p><strong>URL:</strong> {link['url']}</p>
</div>
""", unsafe_allow_html=True)
else:
st.info("No custom links added yet. Use the sidebar to add custom links.")
else:
st.info("No news sources available. Fetch news or add custom links to get started.")
# TAB 2: Blog Generation
with blog_tab:
st.header("✍️ Blog Generation")
# Get all sources for blog generation
all_sources = st.session_state.articles + st.session_state.custom_links
if all_sources:
col1, col2 = st.columns([2, 1])
with col1:
st.subheader("πŸ“ Select Sources")
# Select sources for blog generation
selected_sources = st.multiselect(
"Select sources for blog generation:",
range(len(all_sources)),
format_func=lambda x: all_sources[x]['title']
)
if selected_sources:
with st.container():
st.markdown('<div class="card">', unsafe_allow_html=True)
st.subheader("🎯 Generation Options")
blog_instructions = st.text_area(
"Additional instructions (optional):",
placeholder="E.g., 'Focus on technical aspects' or 'Make it business-oriented'",
help="Provide specific instructions for blog generation"
)
if st.button("πŸš€ Generate Blog Content"):
for idx in selected_sources:
source = all_sources[idx]
with st.spinner(f"Processing: {source['title']}"):
content = scrape_content(source['url'])
if content:
blog = generate_blog(content, source['title'], blog_instructions)
st.session_state.generated_blogs[idx] = {
'title': source['title'],
'content': blog,
'version': 1
}
st.success(f"βœ… Generated: {source['title']}")
st.markdown('</div>', unsafe_allow_html=True)
else:
st.info("Select sources from the list to generate blog content.")
with col2:
st.subheader("ℹ️ Selected Sources")
if selected_sources:
for idx in selected_sources:
source = all_sources[idx]
st.markdown(f"""
<div class="news-card">
<h4>{source['title']}</h4>
<p><strong>Source:</strong> {source['source']['name']}</p>
</div>
""", unsafe_allow_html=True)
else:
st.info("No sources selected yet.")
# Display generated blogs
if st.session_state.generated_blogs:
st.markdown("---")
st.subheader("πŸ“ Generated Blog Content")
for idx, blog in st.session_state.generated_blogs.items():
with st.expander(f"πŸ“„ {blog['title']}"):
st.markdown(blog['content'])
# Modification controls
st.markdown("### ✏️ Modify Content")
mod_instructions = st.text_area(
"Modification instructions:",
key=f"blog_mod_{idx}",
help="Describe how you want to modify this blog content"
)
if st.button("πŸ”„ Apply Changes", key=f"blog_mod_btn_{idx}"):
with st.spinner("Applying modifications..."):
modified = modify_blog(blog['content'], mod_instructions)
st.session_state.generated_blogs[idx]['content'] = modified
st.session_state.generated_blogs[idx]['version'] += 1
st.success(f"βœ… Changes applied! (Version {st.session_state.generated_blogs[idx]['version']})")
else:
st.warning("⚠️ No sources available. Fetch news or add custom links first.")
# TAB 3: Newspaper Generation
with newspaper_tab:
st.header("πŸ“° AI Newspaper Generation")
# Get all sources for newspaper generation
all_sources = st.session_state.articles + st.session_state.custom_links
if all_sources:
col1, col2 = st.columns([2, 1])
with col1:
st.subheader("πŸ“ Select Sources")
# Select sources for newspaper generation
newspaper_sources = st.multiselect(
"Select sources for newspaper generation:",
range(len(all_sources)),
format_func=lambda x: all_sources[x]['title'],
key="newspaper_sources"
)
if newspaper_sources:
with st.container():
st.markdown('<div class="card">', unsafe_allow_html=True)
st.subheader("🎯 Newspaper Options")
newspaper_instructions = st.text_area(
"Additional instructions (optional):",
placeholder="E.g., 'Focus on business impact' or 'Highlight ethical considerations'",
help="Provide specific instructions for newspaper generation",
key="newspaper_instructions"
)
if st.button("πŸš€ Generate Newspaper"):
with st.spinner("Generating comprehensive newspaper..."):
# Prepare selected articles for newspaper generation
selected_articles = []
for idx in newspaper_sources:
source = all_sources[idx]
content = scrape_content(source['url'])
if content:
selected_articles.append({
'title': source['title'],
'content': content,
'source': source['source']['name'],
'url': source['url']
})
if selected_articles:
newspaper_content = generate_newspaper(selected_articles)
st.session_state.newspaper = {
'content': newspaper_content,
'version': 1
}
st.success("βœ… Newspaper generated!")
else:
st.error("⚠️ Could not retrieve content from any of the selected sources.")
st.markdown('</div>', unsafe_allow_html=True)
else:
st.info("Select sources from the list to generate a newspaper.")
with col2:
st.subheader("ℹ️ Selected Sources")
if newspaper_sources:
for idx in newspaper_sources:
source = all_sources[idx]
st.markdown(f"""
<div class="news-card">
<h4>{source['title']}</h4>
<p><strong>Source:</strong> {source['source']['name']}</p>
</div>
""", unsafe_allow_html=True)
else:
st.info("No sources selected yet.")
# Display generated newspaper
if st.session_state.newspaper:
st.markdown("---")
st.subheader("πŸ“° Generated Newspaper")
with st.expander("πŸ“„ AI Newspaper", expanded=True):
st.markdown(st.session_state.newspaper['content'])
# Modification controls
st.markdown("### ✏️ Modify Newspaper")
newspaper_mod_instructions = st.text_area(
"Modification instructions:",
key="newspaper_mod",
help="Describe how you want to modify this newspaper content"
)
col1, col2, col3 = st.columns(3)
with col1:
if st.button("πŸ”„ Apply Changes", key="newspaper_mod_btn"):
with st.spinner("Applying modifications..."):
modified = modify_blog(st.session_state.newspaper['content'], newspaper_mod_instructions)
st.session_state.newspaper['content'] = modified
st.session_state.newspaper['version'] += 1
st.success(f"βœ… Changes applied! (Version {st.session_state.newspaper['version']})")
with col2:
if st.button("πŸ’Ύ Save as TXT", key="save_newspaper"):
with open("ai_newspaper.txt", "w", encoding="utf-8") as f:
f.write(st.session_state.newspaper['content'])
st.success("βœ… Saved as 'ai_newspaper.txt'")
with col3:
if st.button("πŸ—‘οΈ Clear Newspaper", key="clear_newspaper"):
st.session_state.newspaper = ""
st.success("βœ… Newspaper cleared!")
st.rerun()
else:
st.warning("⚠️ No sources available. Fetch news or add custom links first.")