File size: 6,635 Bytes
384f5e4 bfd4ab7 ebf358a f8297ef 0a4103c 7c4d402 febef4d 717fe8c 7916a48 7c4d402 717fe8c 37db576 c87048f f8297ef c87048f f8297ef 0a4103c bfd4ab7 0a4103c 717fe8c 0a4103c 8b3a49e 0a4103c ebf358a 0a4103c ebf358a d84d5f9 ebf358a d10e98d 7c4d402 0f0bb0d 7c4d402 c87048f 7c4d402 ebf358a 7c4d402 d10e98d 242b668 5a80960 0a4103c 5a80960 0a4103c ebf358a 8b3a49e ebf358a 0a4103c bfd4ab7 fd2d980 bfd4ab7 717fe8c 0a4103c 8b3a49e ebf358a 0a4103c ebf358a 384f5e4 ebf358a 0a4103c fd2d980 384f5e4 bfd4ab7 0a4103c bfd4ab7 58522ef ebf358a f8297ef 0a4103c f8297ef c87048f ebf358a 95eccad 0a4103c fd2d980 0a4103c 384f5e4 fd2d980 384f5e4 fd2d980 0a4103c ebf358a 0a4103c 58522ef fd2d980 ebf358a 0a4103c fd2d980 ebf358a fd2d980 ebf358a 61b8502 |
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 |
import streamlit as st
import requests
import matplotlib.pyplot as plt
import seaborn as sns
from transformers import pipeline
import openai
import os
# Streamlit ํ์ด์ง ์ค์ ์ ๊ฐ์ฅ ๋จผ์ ํธ์ถ
st.set_page_config(page_title="์ ์น์ ๊ด์ ๋ถ์", page_icon="๐ฐ", layout="wide")
# OpenAI API ํค ์ค์ (ํ๊ฒฝ๋ณ์์์ ๊ฐ์ ธ์ค๋ ๋ฐฉ๋ฒ)
openai.api_key = os.getenv("OPENAI_API_KEY")
# ํ๊ธ ํฐํธ ์ค์ (Streamlit์์ ์ ์ฉํ๊ธฐ ์ํด CSS ์ถ๊ฐ)
st.markdown(
"""
<style>
body {
font-family: 'Nanum Gothic', sans-serif;
}
</style>
""",
unsafe_allow_html=True
)
# matplotlib ํ๊ธ ํฐํธ ์ค์
import matplotlib
matplotlib.rcParams['font.family'] = 'NanumGothic' # ํ๊ธ ํฐํธ๋ฅผ ์ค์ ํฉ๋๋ค.
matplotlib.rcParams['axes.unicode_minus'] = False # ๋ง์ด๋์ค ๊ธฐํธ ๊นจ์ง ๋ฐฉ์ง
# ๋ค์ด๋ฒ ๋ด์ค 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๋ฅผ ์ด์ฉํด ๋ฐ๋ ๊ด์ ๊ธฐ์ฌ ์์ฑ
def generate_article_gpt4(prompt):
try:
# GPT-4 ๋ชจ๋ธ์ ์ด์ฉํด ๋ฐ๋ ๊ด์ ๊ธฐ์ฌ๋ฅผ ์์ฑ
response = openai.ChatCompletion.create(
model="gpt-4", # GPT-4 ๋ชจ๋ธ์ ์ฌ์ฉ
messages=[
{"role": "system", "content": "You are a helpful assistant that generates articles."},
{"role": "user", "content": prompt} # ์ฌ์ฉ์๊ฐ ์ ๊ณตํ ํ๋กฌํํธ
],
max_tokens=1024, # ๊ธ์ ์ ์ ํ ํด์ (์ต๋ 1024 ํ ํฐ)
temperature=0.7 # ์ฐฝ์์ฑ ์ ๋
)
return response['choices'][0]['message']['content'] # 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"]
link = item["link"] # ๋ด์ค ๋งํฌ ๊ฐ์ ธ์ค๊ธฐ
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,
"๋ด์ค ๋งํฌ": link # ๋งํฌ ์ถ๊ฐ
})
return results, sentiment_counts
# ์ฑํฅ ๋ถํฌ ์๊ฐํ (๋ง๋ ๊ทธ๋ํ)
def visualize_sentiment_distribution(sentiment_counts):
fig, ax = plt.subplots(figsize=(8, 5))
labels = list(sentiment_counts.keys())
sizes = list(sentiment_counts.values())
# ์์ ์ค์ (๋ถ๋๋ฌ์ด ํ๋ ํธ)
color_palette = sns.color_palette("pastel")[0:len(sizes)]
ax.bar(labels, sizes, color=color_palette)
ax.set_xlabel('์ฑํฅ', fontsize=14)
ax.set_ylabel('๊ฑด์', fontsize=14)
ax.set_title('๋ด์ค ์ฑํฅ ๋ถํฌ', fontsize=16)
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(f"- **๋ด์ค ๋งํฌ**: [๋งํฌ]({result['๋ด์ค ๋งํฌ']})") # ๋งํฌ ์ถ๋ ฅ
st.write("---")
else:
st.error("๋ถ์๋ ๋ด์ค ๋ฐ์ดํฐ๊ฐ ์์ต๋๋ค.")
|