Test / app.py
820nam's picture
Update app.py
47c9735 verified
raw
history blame
5.41 kB
import streamlit as st
import requests
import matplotlib.pyplot as plt
from transformers import pipeline
from openai import OpenAI
import os
# OpenAI API ํ‚ค ์„ค์ •
openai.api_key = os.getenv("OPENAI_API_KEY", "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") # ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ๋˜๋Š” ์ง์ ‘ ํ‚ค ์ž…๋ ฅ
# ๋„ค์ด๋ฒ„ ๋‰ด์Šค API๋ฅผ ํ†ตํ•ด ์‹ค์ œ ๋‰ด์Šค ๊ธฐ์‚ฌ ๊ฐ€์ ธ์˜ค๊ธฐ
def fetch_naver_news(query, display=5):
client_id = "I_8koTJh3R5l4wLurQbG" # ๋„ค์ด๋ฒ„ ๊ฐœ๋ฐœ์ž ์„ผํ„ฐ์—์„œ ๋ฐœ๊ธ‰๋ฐ›์€ Client ID
client_secret = "W5oWYlAgur" # ๋„ค์ด๋ฒ„ ๊ฐœ๋ฐœ์ž ์„ผํ„ฐ์—์„œ ๋ฐœ๊ธ‰๋ฐ›์€ Client Secret
url = "https://openapi.naver.com/v1/search/news.json"
headers = {
"X-Naver-Client-Id": client_id,
"X-Naver-Client-Secret": client_secret,
}
params = {
"query": query,
"display": display,
"start": 1,
"sort": "date", # ์ตœ์‹ ์ˆœ์œผ๋กœ ์ •๋ ฌ
}
response = requests.get(url, headers=headers, params=params)
if response.status_code == 200:
news_data = response.json()
return news_data['items'] # ๋‰ด์Šค ๊ธฐ์‚ฌ ๋ฆฌ์ŠคํŠธ ๋ฐ˜ํ™˜
else:
st.error("๋‰ด์Šค ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฐ ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.")
return []
# ์ •์น˜ ์„ฑํ–ฅ ๋ถ„์„ ๋ชจ๋ธ ๋กœ๋“œ
def load_sentiment_model():
classifier = pipeline("text-classification", model="bucketresearch/politicalBiasBERT")
return classifier
# GPT-4๋ฅผ ์ด์šฉํ•ด ๋ฐ˜๋Œ€ ๊ด€์  ๊ธฐ์‚ฌ ์ƒ์„ฑ (์ตœ์‹  OpenAI API ๋ฐฉ์‹)
def generate_article_gpt4(prompt):
try:
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
response = client.completions.create(
model="gpt-4", # GPT-4 ๋ชจ๋ธ ์‚ฌ์šฉ
prompt=prompt,
max_tokens=512,
temperature=0.7
)
return response.choices[0].text.strip() # GPT์˜ ์‘๋‹ต ํ…์ŠคํŠธ
except Exception as e:
return f"Error generating text: {e}"
# ์ •์น˜ ์„ฑํ–ฅ ๋ถ„์„
def analyze_article_sentiment(text, classifier):
result = classifier(text[:512]) # ๋„ˆ๋ฌด ๊ธด ํ…์ŠคํŠธ๋Š” ์ž˜๋ผ์„œ ๋ถ„์„
label = result[0]["label"]
score = result[0]["score"]
# ๋ชจ๋ธ์—์„œ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ผ๋ฒจ์„ "์ง„๋ณด", "๋ณด์ˆ˜", "์ค‘๋ฆฝ"์œผ๋กœ ๋งคํ•‘
if label == "LEFT":
return "์ง„๋ณด", score
elif label == "RIGHT":
return "๋ณด์ˆ˜", score
else:
return "์ค‘๋ฆฝ", score
# ์ •์น˜์  ๊ด€์  ๋น„๊ต ๋ฐ ๋ฐ˜๋Œ€ ๊ด€์  ์ƒ์„ฑ
def analyze_news_political_viewpoint(query):
# ๋‰ด์Šค ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ
news_items = fetch_naver_news(query)
if not news_items:
return [], {}
classifier = load_sentiment_model()
results = []
sentiment_counts = {"์ง„๋ณด": 0, "๋ณด์ˆ˜": 0, "์ค‘๋ฆฝ": 0} # ๋งคํ•‘๋œ ๋ผ๋ฒจ์— ๋งž๊ฒŒ ์ดˆ๊ธฐํ™”
for item in news_items:
title = item["title"]
description = item["description"]
combined_text = f"{title}. {description}"
# ๊ธฐ์‚ฌ ์„ฑํ–ฅ ๋ถ„์„
sentiment, score = analyze_article_sentiment(combined_text, classifier)
sentiment_counts[sentiment] += 1 # ๋งคํ•‘๋œ ํ‚ค๋กœ ์นด์šดํŠธ ์ฆ๊ฐ€
# ๋ฐ˜๋Œ€ ๊ด€์  ๊ธฐ์‚ฌ ์ƒ์„ฑ
opposite_perspective = "๋ณด์ˆ˜์ " if sentiment == "์ง„๋ณด" else "์ง„๋ณด์ "
prompt = f"{combined_text}๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ {opposite_perspective} ๊ด€์ ์˜ ๊ธฐ์‚ฌ๋ฅผ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”."
opposite_article = generate_article_gpt4(prompt)
results.append({
"์ œ๋ชฉ": title,
"์›๋ณธ ๊ธฐ์‚ฌ": description,
"์„ฑํ–ฅ": sentiment,
"์„ฑํ–ฅ ์ ์ˆ˜": score,
"๋Œ€์กฐ ๊ด€์  ๊ธฐ์‚ฌ": opposite_article
})
return results, sentiment_counts
# ์„ฑํ–ฅ ๋ถ„ํฌ ์‹œ๊ฐํ™”
def visualize_sentiment_distribution(sentiment_counts):
fig, ax = plt.subplots()
labels = list(sentiment_counts.keys())
sizes = list(sentiment_counts.values())
ax.pie(sizes, labels=labels, autopct='%1.1f%%', startangle=90, colors=["blue", "red", "gray"])
ax.axis("equal")
st.pyplot(fig)
# Streamlit ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜
st.title("์ •์น˜์  ๊ด€์  ๋น„๊ต ๋ถ„์„ ๋„๊ตฌ")
st.markdown("๋‰ด์Šค ๊ธฐ์‚ฌ์˜ ์ •์น˜ ์„ฑํ–ฅ ๋ถ„์„๊ณผ ๋ฐ˜๋Œ€ ๊ด€์  ๊ธฐ์‚ฌ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋น„๊ตํ•ฉ๋‹ˆ๋‹ค.")
query = st.text_input("๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”", value="์ •์น˜")
if st.button("๋ถ„์„ ์‹œ์ž‘"):
with st.spinner("๋ถ„์„ ์ค‘..."):
analysis_results, sentiment_counts = analyze_news_political_viewpoint(query)
if analysis_results:
st.success("๋‰ด์Šค ๋ถ„์„์ด ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.")
# ์„ฑํ–ฅ ๋ถ„ํฌ ์‹œ๊ฐํ™”
st.subheader("์„ฑํ–ฅ ๋ถ„ํฌ ์‹œ๊ฐํ™”")
visualize_sentiment_distribution(sentiment_counts)
# ์ƒ์„ธ ๋ถ„์„ ๊ฒฐ๊ณผ ์ถœ๋ ฅ
st.subheader("์ƒ์„ธ ๋ถ„์„ ๊ฒฐ๊ณผ")
for result in analysis_results:
st.write(f"#### ์ œ๋ชฉ: {result['์ œ๋ชฉ']}")
st.write(f"- **์›๋ณธ ๊ธฐ์‚ฌ**: {result['์›๋ณธ ๊ธฐ์‚ฌ']}")
st.write(f"- **์„ฑํ–ฅ**: {result['์„ฑํ–ฅ']} (์ ์ˆ˜: {result['์„ฑํ–ฅ ์ ์ˆ˜']:.2f})")
st.write(f"- **๋Œ€์กฐ ๊ด€์  ๊ธฐ์‚ฌ**: {result['๋Œ€์กฐ ๊ด€์  ๊ธฐ์‚ฌ']}")
st.write("---")
else:
st.error("๋ถ„์„๋œ ๋‰ด์Šค ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.")