Update app.py
Browse files
app.py
CHANGED
@@ -1,111 +1,131 @@
|
|
1 |
import streamlit as st
|
2 |
import requests
|
3 |
-
import openai
|
4 |
-
from transformers import pipeline
|
5 |
import matplotlib.pyplot as plt
|
|
|
|
|
6 |
import pandas as pd
|
7 |
|
8 |
# OpenAI API ํค ์ค์
|
9 |
openai.api_key = "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"
|
10 |
|
11 |
-
#
|
12 |
-
def
|
13 |
-
client_id = "I_8koTJh3R5l4wLurQbG"
|
14 |
-
client_secret = "W5oWYlAgur"
|
|
|
15 |
url = "https://openapi.naver.com/v1/search/news.json"
|
16 |
-
headers = {
|
17 |
-
|
18 |
-
|
19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
|
21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
def load_sentiment_model():
|
23 |
-
|
|
|
24 |
|
25 |
-
#
|
26 |
def generate_article_gpt4(prompt):
|
27 |
try:
|
28 |
-
response = openai.
|
29 |
-
|
30 |
-
|
31 |
-
max_tokens=
|
32 |
-
temperature=0.7
|
33 |
)
|
34 |
-
return response
|
35 |
except Exception as e:
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
results = []
|
45 |
-
sentiment_counts = {"์ง๋ณด": 0, "๋ณด์": 0}
|
46 |
|
47 |
-
for item in
|
48 |
title = item["title"]
|
49 |
description = item["description"]
|
50 |
combined_text = f"{title}. {description}"
|
51 |
|
52 |
-
# ์ฑํฅ ๋ถ์
|
53 |
-
sentiment =
|
54 |
-
|
55 |
-
sentiment_score = sentiment["score"]
|
56 |
-
|
57 |
-
# ์ง๋ณด์ /๋ณด์์ ๊ด์ ๋ฐ๋๋ก ๊ธฐ์ฌ ์์ฑ
|
58 |
-
if sentiment_label == "์ง๋ณด":
|
59 |
-
prompt = f"๋ค์ ๊ธฐ์ฌ๋ฅผ ๋ณด์์ ๊ด์ ์์ ์์ฑํด์ฃผ์ธ์:\n{combined_text}"
|
60 |
-
elif sentiment_label == "๋ณด์":
|
61 |
-
prompt = f"๋ค์ ๊ธฐ์ฌ๋ฅผ ์ง๋ณด์ ๊ด์ ์์ ์์ฑํด์ฃผ์ธ์:\n{combined_text}"
|
62 |
-
else:
|
63 |
-
continue # ์ค๋ฆฝ ๊ธฐ์ฌ๋ ์ ์ธ
|
64 |
|
65 |
-
|
66 |
-
|
|
|
|
|
67 |
|
68 |
-
# ๊ฒฐ๊ณผ ์ ์ฅ
|
69 |
results.append({
|
70 |
"์ ๋ชฉ": title,
|
71 |
"์๋ณธ ๊ธฐ์ฌ": description,
|
72 |
-
"์ฑํฅ":
|
73 |
-
"์ฑํฅ ์ ์":
|
74 |
-
"๋์กฐ ๊ด์ ๊ธฐ์ฌ":
|
75 |
})
|
76 |
|
77 |
-
return
|
78 |
|
79 |
-
#
|
80 |
def visualize_sentiment_distribution(sentiment_counts):
|
81 |
-
labels = list(sentiment_counts.keys())
|
82 |
-
values = list(sentiment_counts.values())
|
83 |
fig, ax = plt.subplots()
|
84 |
-
|
85 |
-
|
86 |
-
ax.
|
|
|
87 |
st.pyplot(fig)
|
88 |
|
89 |
-
#
|
90 |
st.title("์ ์น์ ๊ด์ ๋น๊ต ๋ถ์ ๋๊ตฌ")
|
91 |
-
st.markdown("
|
92 |
|
93 |
query = st.text_input("๊ฒ์ ํค์๋๋ฅผ ์
๋ ฅํ์ธ์", value="์ ์น")
|
94 |
if st.button("๋ถ์ ์์"):
|
95 |
-
with st.spinner("๋ถ์
|
96 |
-
|
97 |
-
status_message, analysis_results, sentiment_counts = analyze_news_political_viewpoint(query, sentiment_model)
|
98 |
|
99 |
-
# ๊ฒฐ๊ณผ ์ถ๋ ฅ
|
100 |
-
st.subheader(status_message)
|
101 |
if analysis_results:
|
102 |
-
st.
|
|
|
|
|
|
|
103 |
visualize_sentiment_distribution(sentiment_counts)
|
104 |
-
|
105 |
-
|
|
|
106 |
for result in analysis_results:
|
107 |
st.write(f"#### ์ ๋ชฉ: {result['์ ๋ชฉ']}")
|
108 |
st.write(f"- **์๋ณธ ๊ธฐ์ฌ**: {result['์๋ณธ ๊ธฐ์ฌ']}")
|
109 |
st.write(f"- **์ฑํฅ**: {result['์ฑํฅ']} (์ ์: {result['์ฑํฅ ์ ์']:.2f})")
|
110 |
st.write(f"- **๋์กฐ ๊ด์ ๊ธฐ์ฌ**: {result['๋์กฐ ๊ด์ ๊ธฐ์ฌ']}")
|
111 |
st.write("---")
|
|
|
|
|
|
1 |
import streamlit as st
|
2 |
import requests
|
|
|
|
|
3 |
import matplotlib.pyplot as plt
|
4 |
+
from transformers import pipeline
|
5 |
+
import openai
|
6 |
import pandas as pd
|
7 |
|
8 |
# OpenAI API ํค ์ค์
|
9 |
openai.api_key = "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"
|
10 |
|
11 |
+
# ๋ค์ด๋ฒ ๋ด์ค API๋ฅผ ํตํด ์ค์ ๋ด์ค ๊ธฐ์ฌ ๊ฐ์ ธ์ค๊ธฐ
|
12 |
+
def fetch_naver_news(query, display=5):
|
13 |
+
client_id = "I_8koTJh3R5l4wLurQbG" # ๋ค์ด๋ฒ ๊ฐ๋ฐ์ ์ผํฐ์์ ๋ฐ๊ธ๋ฐ์ Client ID
|
14 |
+
client_secret = "W5oWYlAgur" # ๋ค์ด๋ฒ ๊ฐ๋ฐ์ ์ผํฐ์์ ๋ฐ๊ธ๋ฐ์ Client Secret
|
15 |
+
|
16 |
url = "https://openapi.naver.com/v1/search/news.json"
|
17 |
+
headers = {
|
18 |
+
"X-Naver-Client-Id": client_id,
|
19 |
+
"X-Naver-Client-Secret": client_secret,
|
20 |
+
}
|
21 |
+
params = {
|
22 |
+
"query": query,
|
23 |
+
"display": display,
|
24 |
+
"start": 1,
|
25 |
+
"sort": "date", # ์ต์ ์์ผ๋ก ์ ๋ ฌ
|
26 |
+
}
|
27 |
|
28 |
+
response = requests.get(url, headers=headers, params=params)
|
29 |
+
if response.status_code == 200:
|
30 |
+
news_data = response.json()
|
31 |
+
return news_data['items'] # ๋ด์ค ๊ธฐ์ฌ ๋ฆฌ์คํธ ๋ฐํ
|
32 |
+
else:
|
33 |
+
st.error("๋ด์ค ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ค๋ ๋ฐ ์คํจํ์ต๋๋ค.")
|
34 |
+
return []
|
35 |
+
|
36 |
+
# ์ ์น ์ฑํฅ ๋ถ์ ๋ชจ๋ธ ๋ก๋
|
37 |
def load_sentiment_model():
|
38 |
+
classifier = pipeline("text-classification", model="bucketresearch/politicalBiasBERT")
|
39 |
+
return classifier
|
40 |
|
41 |
+
# GPT-4๋ฅผ ์ด์ฉํด ๋ฐ๋ ๊ด์ ๊ธฐ์ฌ ์์ฑ
|
42 |
def generate_article_gpt4(prompt):
|
43 |
try:
|
44 |
+
response = openai.Completion.create(
|
45 |
+
engine="text-davinci-004", # GPT-4 ์์ง
|
46 |
+
prompt=prompt,
|
47 |
+
max_tokens=300,
|
48 |
+
temperature=0.7
|
49 |
)
|
50 |
+
return response.choices[0].text.strip()
|
51 |
except Exception as e:
|
52 |
+
st.error(f"Error generating text: {e}")
|
53 |
+
return "GPT-4 ํ
์คํธ ์์ฑ ์คํจ"
|
54 |
+
|
55 |
+
# ๊ธฐ์ฌ ์ฑํฅ ๋ถ์
|
56 |
+
def analyze_article_sentiment(text, classifier):
|
57 |
+
result = classifier(text[:512]) # ๋๋ฌด ๊ธด ํ
์คํธ๋ ์๋ผ์ ๋ถ์
|
58 |
+
label = result[0]["label"]
|
59 |
+
score = result[0]["score"]
|
60 |
+
return label, score
|
61 |
+
|
62 |
+
# ์ ์น์ ๊ด์ ๋น๊ต ๋ฐ ๋ฐ๋ ๊ด์ ์์ฑ
|
63 |
+
def analyze_news_political_viewpoint(query):
|
64 |
+
# ๋ด์ค ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ
|
65 |
+
news_items = fetch_naver_news(query)
|
66 |
+
if not news_items:
|
67 |
+
return [], {}
|
68 |
+
|
69 |
+
classifier = load_sentiment_model()
|
70 |
results = []
|
71 |
+
sentiment_counts = {"์ง๋ณด": 0, "๋ณด์": 0, "์ค๋ฆฝ": 0}
|
72 |
|
73 |
+
for item in news_items:
|
74 |
title = item["title"]
|
75 |
description = item["description"]
|
76 |
combined_text = f"{title}. {description}"
|
77 |
|
78 |
+
# ๊ธฐ์ฌ ์ฑํฅ ๋ถ์
|
79 |
+
sentiment, score = analyze_article_sentiment(combined_text, classifier)
|
80 |
+
sentiment_counts[sentiment] += 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
|
82 |
+
# ๋ฐ๋ ๊ด์ ๊ธฐ์ฌ ์์ฑ
|
83 |
+
opposite_perspective = "๋ณด์์ " if sentiment == "์ง๋ณด" else "์ง๋ณด์ "
|
84 |
+
prompt = f"{combined_text}๋ฅผ ๊ธฐ๋ฐ์ผ๋ก {opposite_perspective} ๊ด์ ์ ๊ธฐ์ฌ๋ฅผ ์์ฑํด์ฃผ์ธ์."
|
85 |
+
opposite_article = generate_article_gpt4(prompt)
|
86 |
|
|
|
87 |
results.append({
|
88 |
"์ ๋ชฉ": title,
|
89 |
"์๋ณธ ๊ธฐ์ฌ": description,
|
90 |
+
"์ฑํฅ": sentiment,
|
91 |
+
"์ฑํฅ ์ ์": score,
|
92 |
+
"๋์กฐ ๊ด์ ๊ธฐ์ฌ": opposite_article
|
93 |
})
|
94 |
|
95 |
+
return results, sentiment_counts
|
96 |
|
97 |
+
# ์ฑํฅ ๋ถํฌ ์๊ฐํ
|
98 |
def visualize_sentiment_distribution(sentiment_counts):
|
|
|
|
|
99 |
fig, ax = plt.subplots()
|
100 |
+
labels = list(sentiment_counts.keys())
|
101 |
+
sizes = list(sentiment_counts.values())
|
102 |
+
ax.pie(sizes, labels=labels, autopct='%1.1f%%', startangle=90, colors=["blue", "red", "gray"])
|
103 |
+
ax.axis("equal")
|
104 |
st.pyplot(fig)
|
105 |
|
106 |
+
# Streamlit ์ ํ๋ฆฌ์ผ์ด์
|
107 |
st.title("์ ์น์ ๊ด์ ๋น๊ต ๋ถ์ ๋๊ตฌ")
|
108 |
+
st.markdown("๋ด์ค ๊ธฐ์ฌ์ ์ ์น ์ฑํฅ ๋ถ์๊ณผ ๋ฐ๋ ๊ด์ ๊ธฐ์ฌ๋ฅผ ์์ฑํ์ฌ ๋น๊ตํฉ๋๋ค.")
|
109 |
|
110 |
query = st.text_input("๊ฒ์ ํค์๋๋ฅผ ์
๋ ฅํ์ธ์", value="์ ์น")
|
111 |
if st.button("๋ถ์ ์์"):
|
112 |
+
with st.spinner("๋ถ์ ์ค..."):
|
113 |
+
analysis_results, sentiment_counts = analyze_news_political_viewpoint(query)
|
|
|
114 |
|
|
|
|
|
115 |
if analysis_results:
|
116 |
+
st.success("๋ด์ค ๋ถ์์ด ์๋ฃ๋์์ต๋๋ค.")
|
117 |
+
|
118 |
+
# ์ฑํฅ ๋ถํฌ ์๊ฐํ
|
119 |
+
st.subheader("์ฑํฅ ๋ถํฌ ์๊ฐํ")
|
120 |
visualize_sentiment_distribution(sentiment_counts)
|
121 |
+
|
122 |
+
# ์์ธ ๋ถ์ ๊ฒฐ๊ณผ ์ถ๋ ฅ
|
123 |
+
st.subheader("์์ธ ๋ถ์ ๊ฒฐ๊ณผ")
|
124 |
for result in analysis_results:
|
125 |
st.write(f"#### ์ ๋ชฉ: {result['์ ๋ชฉ']}")
|
126 |
st.write(f"- **์๋ณธ ๊ธฐ์ฌ**: {result['์๋ณธ ๊ธฐ์ฌ']}")
|
127 |
st.write(f"- **์ฑํฅ**: {result['์ฑํฅ']} (์ ์: {result['์ฑํฅ ์ ์']:.2f})")
|
128 |
st.write(f"- **๋์กฐ ๊ด์ ๊ธฐ์ฌ**: {result['๋์กฐ ๊ด์ ๊ธฐ์ฌ']}")
|
129 |
st.write("---")
|
130 |
+
else:
|
131 |
+
st.error("๋ถ์๋ ๋ด์ค ๋ฐ์ดํฐ๊ฐ ์์ต๋๋ค.")
|