File size: 10,721 Bytes
f01d87d 7287745 aa0b994 f75caf0 fce7c2b f75caf0 fce7c2b aa0b994 f01d87d f75caf0 f01d87d aa0b994 f01d87d f75caf0 fce7c2b f01d87d aa0b994 f75caf0 aa0b994 f01d87d fce7c2b c67e9f8 fce7c2b aa0b994 c67e9f8 aa0b994 c67e9f8 aa0b994 fce7c2b f75caf0 fce7c2b f75caf0 fce7c2b f01d87d fce7c2b 7287745 fce7c2b c67e9f8 fce7c2b c67e9f8 fce7c2b c67e9f8 fce7c2b c67e9f8 fce7c2b f75caf0 fce7c2b c67e9f8 fce7c2b f75caf0 c67e9f8 fce7c2b f75caf0 fce7c2b f75caf0 c67e9f8 7287745 fce7c2b f01d87d f75caf0 e13fa72 f75caf0 f01d87d 7287745 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
import gradio as gr
from duckduckgo_search import DDGS
from datetime import datetime
import os
import asyncio
import nest_asyncio
from openai import OpenAI
import traceback
import re
try:
from agents import Agent, Runner, function_tool, OpenAIChatCompletionsModel
AGENTS_AVAILABLE = True
except Exception:
print("WARNING: openai-agents package not fully functional, using fallback mode")
AGENTS_AVAILABLE = False
# Apply nest_asyncio to allow nested event loops
nest_asyncio.apply()
# Set up environment variables
OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
# Get current date for default value
default_date = datetime.now().strftime("%Y-%m-%d")
# Configure OpenAI client
client = OpenAI(api_key=OPENAI_API_KEY)
# Function to make URLs clickable in Markdown
def make_urls_clickable(text):
# Find URLs in the text
url_pattern = r'(https?://[^\s]+)'
# Replace URLs with markdown links
text_with_links = re.sub(url_pattern, r'[\1](\1)', text)
return text_with_links
# Function to format article output with better readability
def format_articles(text):
# Make URLs clickable
text = make_urls_clickable(text)
# Add better formatting for article titles (lines starting with #)
text = re.sub(r'# (.+)', r'## \1', text)
# Add horizontal rule between articles if not already present
if "---" not in text:
text = re.sub(r'\n\n(?=# )', r'\n\n---\n\n', text)
# Enhance description and URL formatting
text = re.sub(r'\*\*URL\*\*: (.+)', r'**Source**: \1', text)
text = re.sub(r'\*\*Description\*\*:', r'**Summary**:', text)
return text
# Direct search function that doesn't depend on the agents package
def direct_news_search(topic, language="English", search_date=None):
"""Search for news articles using DuckDuckGo directly"""
if not search_date:
search_date = datetime.now().strftime("%Y-%m")
else:
search_date = search_date[:7] # Just get YYYY-MM portion
print(f"Running DuckDuckGo news search for {topic} in {language} for date {search_date}...")
# Map common languages to their search keywords
language_keywords = {
"English": "", # Default, no special keyword needed
"Hindi": "हिंदी",
"Spanish": "español",
"French": "français",
"German": "deutsch",
"Japanese": "日本語",
"Chinese": "中文",
"Russian": "русский",
"Arabic": "العربية",
"Portuguese": "português",
"Italian": "italiano",
"Dutch": "nederlands",
"Korean": "한국어",
"Turkish": "türkçe",
"Kannada": "ಕನ್ನಡ",
"Tamil": "தமிழ்",
"Telugu": "తెలుగు",
"Bengali": "বাংলা",
"Marathi": "मराठी"
}
# Get language keyword if available
lang_keyword = language_keywords.get(language, language)
# Add language to search query if it's not English
search_query = f"{topic} {lang_keyword} {search_date}" if language != "English" else f"{topic} {search_date}"
try:
# DuckDuckGo search
ddg_api = DDGS()
results = ddg_api.text(search_query, max_results=5)
if results:
news_results = "\n\n".join([f"# {result['title']}\n**URL**: {result['href']}\n**Description**: {result['body']}" for result in results])
return news_results
else:
return f"Could not find news results for {topic} in {language} for {search_date}."
except Exception as e:
return f"Error searching for news: {str(e)}"
# Direct OpenAI API call
def generate_with_openai(prompt):
"""Use OpenAI API directly to generate content"""
try:
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
temperature=0.7,
max_tokens=2000
)
return response.choices[0].message.content
except Exception as e:
return f"Error with OpenAI API: {str(e)}"
# Try to set up agents if available
if AGENTS_AVAILABLE:
try:
# Define the model
model = OpenAIChatCompletionsModel(
model="gpt-4o-mini",
openai_client=client
)
# News search tool
@function_tool
def get_news_articles(topic, language="English", search_date=None):
return direct_news_search(topic, language, search_date)
# Create agents
news_agent = Agent(
name="News Agent",
instructions="You provide the latest news articles for a given topic using DuckDuckGo search. You can search for news in different languages when specified. Format each article with a # heading.",
tools=[get_news_articles],
model=model
)
editor_agent = Agent(
name="Editor Assistant",
instructions="Rewrite and give me a news article ready for publishing. Each news story should be in a separate section with a clear headline (use # for headlines). Maintain the original language of the news stories. If the content is in a language other than English, edit and format in that same language. Keep the original URLs and mark them as **URL**: [url]. Use --- to separate articles.",
model=model
)
print("Successfully initialized agent-based workflow")
except Exception as e:
print(f"Failed to initialize agents: {e}")
AGENTS_AVAILABLE = False
# Workflow function for Gradio
def fetch_and_edit_news(topic, language, search_date):
"""Process news request using agents if available, otherwise fall back to direct API calls"""
try:
# Try agent-based approach if available
if AGENTS_AVAILABLE:
try:
print("Attempting to use agent-based workflow...")
# Initialize event loop
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
# Run the news agent
news_prompt = f"Get me the news about {topic} in {language} for date {search_date}"
news_result = Runner.run_sync(news_agent, news_prompt)
raw_news = news_result.final_output
# Run the editor agent
editor_prompt = f"Please edit the following news in {language} language. Maintain the original language and URLs. Format with markdown, using # for headlines and --- to separate articles: \n\n{raw_news}"
editor_result = Runner.run_sync(editor_agent, editor_prompt)
edited_news = editor_result.final_output
print("Agent-based workflow completed successfully")
# Format the output with better readability
return format_articles(edited_news)
except Exception as agent_error:
print(f"Agent-based workflow failed: {agent_error}")
print(traceback.format_exc())
print("Falling back to direct API approach...")
# Fall through to the direct approach
else:
print("Using direct API approach (agents not available)...")
# Direct approach (used when agents fail or aren't available)
# Step 1: Get news directly
raw_news = direct_news_search(topic, language, search_date)
if raw_news.startswith("Error") or raw_news.startswith("Could not find"):
return raw_news
# Step 2: Edit the news with OpenAI
editor_prompt = f"""
Please edit and reformat the following news into a cohesive, publication-ready format.
Maintain the original language ({language}).
Format with markdown, using # for headlines and --- to separate articles.
Keep the original URLs and mark them as **URL**: [url].
{raw_news}
"""
edited_news = generate_with_openai(editor_prompt)
# Format the output with better readability
return format_articles(edited_news)
except Exception as e:
error_details = traceback.format_exc()
print(f"Error in workflow: {e}")
print(error_details)
return f"Error processing your request: {str(e)}\n\nPlease check that your OpenAI API key is correctly set in the repository secrets."
# Read custom CSS from file
try:
with open('style.css', 'r') as f:
custom_css = f.read()
except Exception as e:
print(f"Warning: Could not read CSS file: {e}")
# Fallback minimal CSS if file can't be read
custom_css = """
.container { max-width: 900px; margin: auto; }
.article-output { border: 1px solid #ddd; padding: 20px; }
"""
# Create Gradio interface with a custom theme
with gr.Blocks(title="Multilingual AI News Generator", theme=gr.themes.Soft(primary_hue="blue"), css=custom_css) as demo:
with gr.Column(elem_classes="container"):
with gr.Column(elem_classes="header"):
gr.Markdown("# Multilingual AI News Generator")
gr.Markdown("Enter a topic, select a language, and choose a date to receive curated and edited news articles")
with gr.Row(elem_classes="search-options"):
topic_input = gr.Textbox(
label="News Topic",
placeholder="Enter a topic (e.g., AI, Climate Change, Sports)"
)
language_dropdown = gr.Dropdown(
choices=[
"English", "Hindi", "Spanish", "French", "German",
"Japanese", "Chinese", "Russian", "Arabic", "Portuguese",
"Italian", "Dutch", "Korean", "Turkish", "Kannada",
"Tamil", "Telugu", "Bengali", "Marathi"
],
label="Language",
value="English"
)
date_picker = gr.Textbox(
label="Search Date",
placeholder="YYYY-MM-DD",
value=default_date
)
submit_btn = gr.Button("Generate News Article", elem_classes="generate-btn")
# Use Markdown for output to enable clickable links and better formatting
output_box = gr.Markdown(elem_classes="article-output")
submit_btn.click(
fn=fetch_and_edit_news,
inputs=[topic_input, language_dropdown, date_picker],
outputs=output_box
)
# Launch the app
if __name__ == "__main__":
demo.launch() |