Assignment5-7 / api.py
Sirapatrwan's picture
Upload api.py
940ba87 verified
from fastapi import FastAPI
from pydantic import BaseModel
from utils import fetch_news, analyze_sentiment, extract_topics, generate_tts
import random
# Set up the FastAPI server with a name and description
app = FastAPI(title="News Sentiment API", description="Analyze news sentiment for companies")
class CompanyInput(BaseModel):
"""Simple model to validate incoming company name."""
company: str
@app.post("/analyze")
async def analyze_company(input: CompanyInput):
"""Take a company name and return its news sentiment analysis."""
company = input.company
articles_data = fetch_news(company)
if not articles_data:
return {"error": f"No articles found for {company}. Check logs for details."}
articles = []
sentiments = {"Positive": 0, "Negative": 0, "Neutral": 0}
positive_articles = []
negative_articles = []
neutral_articles = []
for article in articles_data:
summary = article["summary"].strip() or article["title"].split(" - ")[0].strip()
source = article["title"].split(" - ")[-1].strip() if " - " in article["title"] else ""
if source in summary:
summary = summary.replace(source, "").strip()
summary = f"{summary.rstrip(' -')} - {source}"
sentiment = analyze_sentiment(summary)
topics = extract_topics(summary)
sentiments[sentiment] += 1
title = article["title"].split(" - ")[0].strip()
if sentiment == "Positive":
positive_articles.append(title)
elif sentiment == "Negative":
negative_articles.append(title)
else:
neutral_articles.append(title)
articles.append({
"Title": article["title"],
"Summary": summary,
"Sentiment": sentiment,
"Topics": topics,
"Link": article["link"],
"PubDate": article["pub_date"]
})
detailed_comparisons = [f"- News {i + 1} {article['Sentiment'].lower()}ly discusses {', '.join(article['Topics'])}"
for i, article in enumerate(articles)]
dominant_sentiment = max(sentiments, key=sentiments.get)
trends = f"{company} News Trends: {dominant_sentiment}"
total_articles = sum(sentiments.values())
sentiment_count = f"{sentiments['Positive']} positive, {sentiments['Negative']} negative, {sentiments['Neutral']} neutral"
intro_phrases = [
f"Spanning {total_articles} recent reports, the narrative surrounding {company} tilts {dominant_sentiment.lower()}, with {sentiment_count}.",
f"Across {total_articles} articles in recent coverage, {company}’s story emerges as predominantly {dominant_sentiment.lower()}, reflecting {sentiment_count}.",
f"Drawing from {total_articles} latest publications, {company}’s news landscape leans {dominant_sentiment.lower()}, underscored by {sentiment_count}."
]
positive_phrases = [
f"With {len(positive_articles)} favorable accounts, {company} demonstrates notable progress, exemplified by '{random.choice(positive_articles) if positive_articles else 'no specific examples available'}'.",
f"Boasting {len(positive_articles)} positive developments, {company} showcases strength, as evidenced in '{random.choice(positive_articles) if positive_articles else 'no notable instances'}'.",
f"Highlighted by {len(positive_articles)} encouraging reports, {company} is forging ahead, with '{random.choice(positive_articles) if positive_articles else 'no standout reports'}' standing out."
]
negative_phrases = [
f"However, {len(negative_articles)} troubling narratives raise concerns, including '{random.choice(negative_articles) if negative_articles else 'no specific concerns noted'}'.",
f"Yet, {len(negative_articles)} adverse reports signal challenges, such as '{random.choice(negative_articles) if negative_articles else 'no highlighted issues'}'.",
f"Nevertheless, {len(negative_articles)} concerning stories cast a shadow, notably '{random.choice(negative_articles) if negative_articles else 'no notable setbacks'}'."
]
neutral_phrases = [
f"Additionally, {len(neutral_articles)} impartial updates provide context, such as '{random.choice(neutral_articles) if neutral_articles else 'no neutral updates available'}'.",
f"Meanwhile, {len(neutral_articles)} balanced accounts offer insight, including '{random.choice(neutral_articles) if neutral_articles else 'no balanced reports'}'.",
f"Furthermore, {len(neutral_articles)} objective pieces contribute details, like '{random.choice(neutral_articles) if neutral_articles else 'no objective details'}'."
]
outlook_phrases_positive = [
f"In summary, {company} appears poised for a favorable trajectory.",
f"All told, {company} stands on the cusp of a promising future.",
f"Ultimately, {company} is positioned for an optimistic course ahead."
]
outlook_phrases_negative = [
f"In conclusion, {company} confronts a challenging path forward.",
f"Overall, {company} navigates a formidable road ahead.",
f"To conclude, {company} faces a demanding horizon."
]
outlook_phrases_mixed = [
f"In the final analysis, {company} balances opportunity and uncertainty.",
f"On balance, {company} presents a complex outlook moving forward.",
f"Ultimately, {company} reflects a blend of prospects and hurdles."
]
final_text = random.choice(intro_phrases) + " "
if positive_articles:
final_text += random.choice(positive_phrases) + " "
if negative_articles:
final_text += random.choice(negative_phrases) + " "
if neutral_articles:
final_text += random.choice(neutral_phrases) + " "
if sentiments["Positive"] > sentiments["Negative"]:
final_text += random.choice(outlook_phrases_positive)
elif sentiments["Negative"] > sentiments["Positive"]:
final_text += random.choice(outlook_phrases_negative)
else:
final_text += random.choice(outlook_phrases_mixed)
print(f"Generated dynamic final sentiment for {company}: {final_text}")
return {
"Company": company,
"Articles": articles,
"Comparative Sentiment Score": {
"Sentiment Distribution": f"Positive: {sentiments['Positive']}, Negative: {sentiments['Negative']}, Neutral: {sentiments['Neutral']}",
"Trends": trends,
"Detailed Comparisons": "\n".join(detailed_comparisons)
},
"Final Sentiment Analysis": final_text.strip(),
"Audio": None
}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000) # Start the API server on port 8000