|
import streamlit as st |
|
import requests |
|
import matplotlib.pyplot as plt |
|
from transformers import pipeline |
|
from openai import OpenAI |
|
import os |
|
|
|
|
|
openai.api_key = os.getenv("OPENAI_API_KEY", "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") |
|
|
|
|
|
def fetch_naver_news(query, display=5): |
|
client_id = "I_8koTJh3R5l4wLurQbG" |
|
client_secret = "W5oWYlAgur" |
|
|
|
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 |
|
|
|
|
|
def generate_article_gpt4(prompt): |
|
try: |
|
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) |
|
|
|
response = client.completions.create( |
|
model="gpt-4", |
|
prompt=prompt, |
|
max_tokens=512, |
|
temperature=0.7 |
|
) |
|
return response.choices[0].text.strip() |
|
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) |
|
|
|
|
|
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("๋ถ์๋ ๋ด์ค ๋ฐ์ดํฐ๊ฐ ์์ต๋๋ค.") |
|
|