Spaces:
Running
on
Zero
Running
on
Zero
Update app.py
Browse files
app.py
CHANGED
@@ -12,20 +12,20 @@ from nltk.sentiment import SentimentIntensityAnalyzer
|
|
12 |
from sklearn.cluster import KMeans
|
13 |
import torch
|
14 |
|
15 |
-
#
|
16 |
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
|
17 |
|
18 |
-
#
|
19 |
clf = wbgtopic.WBGDocTopic(device=device)
|
20 |
|
21 |
-
#
|
22 |
try:
|
23 |
nltk.download('punkt', quiet=True)
|
24 |
nltk.download('vader_lexicon', quiet=True)
|
25 |
except Exception as e:
|
26 |
-
print(f"NLTK
|
27 |
|
28 |
-
#
|
29 |
SAMPLE_TEXT = """
|
30 |
The three reportedly discussed the Stargate Project, a large-scale AI initiative led by OpenAI, SoftBank, and U.S. software giant Oracle. The project aims to invest $500 billion over the next four years in building new AI infrastructure in the U.S. The U.S. government has shown a strong commitment to the initiative, with President Donald Trump personally announcing it at the White House the day after his inauguration last month. If Samsung participates, the project will lead to a Korea-U.S.-Japan AI alliance.
|
31 |
The AI sector requires massive investments and extensive resources, including advanced models, high-performance AI chips to power the models, and large-scale data centers to operate them. Nvidia and TSMC currently dominate the AI sector, but a partnership between Samsung, SoftBank, and OpenAI could pave the way for a competitive alternative.
|
@@ -33,9 +33,8 @@ The AI sector requires massive investments and extensive resources, including ad
|
|
33 |
|
34 |
def safe_process(func):
|
35 |
"""
|
36 |
-
|
37 |
-
|
38 |
-
the Gradio interface does not crash from unexpected exceptions.
|
39 |
"""
|
40 |
def wrapper(*args, **kwargs):
|
41 |
try:
|
@@ -48,44 +47,89 @@ def safe_process(func):
|
|
48 |
@safe_process
|
49 |
def parse_wbg_results(raw_output):
|
50 |
"""
|
51 |
-
|
52 |
-
'label', 'score_mean',
|
53 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
"""
|
|
|
|
|
|
|
|
|
55 |
if not raw_output:
|
56 |
return []
|
57 |
|
58 |
-
# Example logic: If raw_output is something like:
|
59 |
-
# [ { "Innovation and Entrepreneurship": 0.74, "Digital Development": 0.65, ... } ]
|
60 |
-
# We'll parse it accordingly.
|
61 |
first_item = raw_output[0]
|
62 |
|
63 |
-
#
|
64 |
-
|
65 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
|
67 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
if isinstance(first_item, dict):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
parsed_list = []
|
70 |
-
for label, val in
|
71 |
parsed_list.append({
|
72 |
"label": label,
|
73 |
"score_mean": float(val),
|
74 |
-
"score_std": 0.0
|
75 |
})
|
76 |
return parsed_list
|
77 |
|
|
|
78 |
return []
|
79 |
|
80 |
@safe_process
|
81 |
def analyze_text_sections(text):
|
82 |
"""
|
83 |
-
|
84 |
-
|
85 |
-
for that section.
|
86 |
"""
|
87 |
sentences = sent_tokenize(text)
|
88 |
-
#
|
89 |
sections = [' '.join(sentences[i:i+3]) for i in range(0, len(sentences), 3)]
|
90 |
|
91 |
section_topics = []
|
@@ -99,10 +143,11 @@ def analyze_text_sections(text):
|
|
99 |
@safe_process
|
100 |
def calculate_topic_correlations(topic_dicts):
|
101 |
"""
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
|
|
106 |
"""
|
107 |
if len(topic_dicts) < 2:
|
108 |
return np.array([[1.0]]), ["Insufficient topics"]
|
@@ -119,9 +164,8 @@ def calculate_topic_correlations(topic_dicts):
|
|
119 |
@safe_process
|
120 |
def perform_sentiment_analysis(text):
|
121 |
"""
|
122 |
-
|
123 |
-
|
124 |
-
Returns a pandas DataFrame of results.
|
125 |
"""
|
126 |
sia = SentimentIntensityAnalyzer()
|
127 |
sents = sent_tokenize(text)
|
@@ -131,8 +175,8 @@ def perform_sentiment_analysis(text):
|
|
131 |
@safe_process
|
132 |
def create_topic_clusters(topic_dicts):
|
133 |
"""
|
134 |
-
|
135 |
-
|
136 |
"""
|
137 |
if len(topic_dicts) < 3:
|
138 |
return [0] * len(topic_dicts)
|
@@ -152,37 +196,37 @@ def create_topic_clusters(topic_dicts):
|
|
152 |
@safe_process
|
153 |
def create_main_charts(topic_dicts):
|
154 |
"""
|
155 |
-
|
156 |
-
|
157 |
"""
|
158 |
if not topic_dicts:
|
159 |
return go.Figure(), go.Figure()
|
160 |
|
161 |
labels = [t['label'] for t in topic_dicts]
|
162 |
-
scores = [t['score_mean'] * 100 for t in topic_dicts]
|
163 |
|
164 |
-
#
|
165 |
bar_fig = go.Figure(
|
166 |
data=[go.Bar(x=labels, y=scores, marker_color='rgb(55, 83, 109)')]
|
167 |
)
|
168 |
bar_fig.update_layout(
|
169 |
-
title='
|
170 |
-
xaxis_title='
|
171 |
-
yaxis_title='
|
172 |
template='plotly_white',
|
173 |
height=500,
|
174 |
)
|
175 |
|
176 |
-
#
|
177 |
radar_fig = go.Figure()
|
178 |
radar_fig.add_trace(go.Scatterpolar(
|
179 |
r=scores,
|
180 |
theta=labels,
|
181 |
fill='toself',
|
182 |
-
name='
|
183 |
))
|
184 |
radar_fig.update_layout(
|
185 |
-
title='
|
186 |
template='plotly_white',
|
187 |
height=500,
|
188 |
polar=dict(radialaxis=dict(visible=True)),
|
@@ -193,15 +237,15 @@ def create_main_charts(topic_dicts):
|
|
193 |
@safe_process
|
194 |
def create_correlation_heatmap(corr_matrix, labels):
|
195 |
"""
|
196 |
-
|
197 |
-
|
198 |
"""
|
199 |
if corr_matrix.ndim == 0:
|
200 |
-
#
|
201 |
corr_matrix = np.array([[corr_matrix]])
|
202 |
|
203 |
if corr_matrix.shape == (1, 1):
|
204 |
-
#
|
205 |
fig = go.Figure()
|
206 |
fig.add_annotation(text="Not enough topics for correlation", showarrow=False)
|
207 |
return fig
|
@@ -213,7 +257,7 @@ def create_correlation_heatmap(corr_matrix, labels):
|
|
213 |
colorscale='Viridis'
|
214 |
))
|
215 |
fig.update_layout(
|
216 |
-
title='
|
217 |
height=500,
|
218 |
template='plotly_white'
|
219 |
)
|
@@ -222,9 +266,8 @@ def create_correlation_heatmap(corr_matrix, labels):
|
|
222 |
@safe_process
|
223 |
def create_topic_evolution(section_topics):
|
224 |
"""
|
225 |
-
|
226 |
-
section_topics:
|
227 |
-
is a list of dicts [{'label':..., 'score_mean':...}, ...]
|
228 |
"""
|
229 |
fig = go.Figure()
|
230 |
if not section_topics or len(section_topics) == 0:
|
@@ -233,7 +276,7 @@ def create_topic_evolution(section_topics):
|
|
233 |
if not section_topics[0]:
|
234 |
return fig
|
235 |
|
236 |
-
#
|
237 |
for topic_dict in section_topics[0]:
|
238 |
label = topic_dict['label']
|
239 |
score_list = []
|
@@ -252,9 +295,9 @@ def create_topic_evolution(section_topics):
|
|
252 |
))
|
253 |
|
254 |
fig.update_layout(
|
255 |
-
title='
|
256 |
-
xaxis_title='
|
257 |
-
yaxis_title='
|
258 |
height=500,
|
259 |
template='plotly_white'
|
260 |
)
|
@@ -263,8 +306,8 @@ def create_topic_evolution(section_topics):
|
|
263 |
@safe_process
|
264 |
def create_confidence_gauge(topic_dicts):
|
265 |
"""
|
266 |
-
|
267 |
-
|
268 |
"""
|
269 |
if not topic_dicts:
|
270 |
return go.Figure()
|
@@ -273,7 +316,6 @@ def create_confidence_gauge(topic_dicts):
|
|
273 |
num_topics = len(topic_dicts)
|
274 |
|
275 |
for i, t in enumerate(topic_dicts):
|
276 |
-
# If score_std not present, default to 0 => confidence = 100%
|
277 |
conf_val = 100.0 * (1.0 - t.get("score_std", 0.0))
|
278 |
fig.add_trace(go.Indicator(
|
279 |
mode="gauge+number",
|
@@ -292,48 +334,47 @@ def create_confidence_gauge(topic_dicts):
|
|
292 |
@spaces.GPU()
|
293 |
def process_all_analysis(text):
|
294 |
"""
|
295 |
-
|
296 |
-
|
297 |
"""
|
298 |
try:
|
299 |
-
# 1)
|
300 |
raw_results = clf.suggest_topics(text)
|
301 |
all_topics = parse_wbg_results(raw_results)
|
302 |
|
303 |
-
# 2)
|
304 |
sorted_topics = sorted(all_topics, key=lambda x: x['score_mean'], reverse=True)
|
305 |
top_topics = sorted_topics[:5]
|
306 |
|
307 |
-
# 3)
|
308 |
section_topics = analyze_text_sections(text)
|
309 |
|
310 |
-
# 4)
|
311 |
corr_matrix, corr_labels = calculate_topic_correlations(all_topics)
|
312 |
sentiments_df = perform_sentiment_analysis(text)
|
313 |
clusters = create_topic_clusters(all_topics)
|
314 |
|
315 |
-
# 5)
|
316 |
bar_chart, radar_chart = create_main_charts(top_topics)
|
317 |
heatmap = create_correlation_heatmap(corr_matrix, corr_labels)
|
318 |
evolution_chart = create_topic_evolution(section_topics)
|
319 |
gauge_chart = create_confidence_gauge(top_topics)
|
320 |
|
321 |
-
# 6)
|
322 |
results = {
|
323 |
-
"top_topics": top_topics,
|
324 |
-
"clusters": clusters,
|
325 |
-
"sentiments": sentiments_df.to_dict(orient="records")
|
326 |
}
|
327 |
|
328 |
-
# Return JSON + Figures
|
329 |
return (
|
330 |
-
results,
|
331 |
-
bar_chart,
|
332 |
-
radar_chart,
|
333 |
-
heatmap,
|
334 |
-
evolution_chart
|
335 |
-
gauge_chart,
|
336 |
-
go.Figure()
|
337 |
)
|
338 |
|
339 |
except Exception as e:
|
@@ -353,38 +394,38 @@ def process_all_analysis(text):
|
|
353 |
# Gradio UI Definition #
|
354 |
######################################################
|
355 |
|
356 |
-
with gr.Blocks(title="
|
357 |
-
gr.Markdown("##
|
358 |
gr.Markdown(
|
359 |
-
"
|
360 |
-
"
|
361 |
)
|
362 |
|
363 |
with gr.Row():
|
364 |
text_input = gr.Textbox(
|
365 |
value=SAMPLE_TEXT,
|
366 |
-
label="
|
367 |
lines=8
|
368 |
)
|
369 |
with gr.Row():
|
370 |
-
submit_btn = gr.Button("
|
371 |
|
372 |
with gr.Tabs():
|
373 |
-
with gr.TabItem("
|
374 |
with gr.Row():
|
375 |
-
plot1 = gr.Plot(label="
|
376 |
-
plot2 = gr.Plot(label="
|
377 |
-
with gr.TabItem("
|
378 |
with gr.Row():
|
379 |
-
plot3 = gr.Plot(label="
|
380 |
-
plot4 = gr.Plot(label="
|
381 |
-
with gr.TabItem("
|
382 |
-
plot5 = gr.Plot(label="
|
383 |
-
with gr.TabItem("
|
384 |
-
plot6 = gr.Plot(label="
|
385 |
|
386 |
with gr.Row():
|
387 |
-
output_json = gr.JSON(label="
|
388 |
|
389 |
submit_btn.click(
|
390 |
fn=process_all_analysis,
|
@@ -397,6 +438,6 @@ if __name__ == "__main__":
|
|
397 |
demo.launch(
|
398 |
server_name="0.0.0.0",
|
399 |
server_port=7860,
|
400 |
-
share=False, #
|
401 |
debug=True
|
402 |
)
|
|
|
12 |
from sklearn.cluster import KMeans
|
13 |
import torch
|
14 |
|
15 |
+
# GPU ์ฌ์ฉ ๊ฐ๋ฅ ์ ์ค์
|
16 |
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
|
17 |
|
18 |
+
# WBGDocTopic ์ด๊ธฐํ
|
19 |
clf = wbgtopic.WBGDocTopic(device=device)
|
20 |
|
21 |
+
# NLTK ๋ฐ์ดํฐ ๋ค์ด๋ก๋ (ํ์ ์)
|
22 |
try:
|
23 |
nltk.download('punkt', quiet=True)
|
24 |
nltk.download('vader_lexicon', quiet=True)
|
25 |
except Exception as e:
|
26 |
+
print(f"NLTK ๋ฐ์ดํฐ ๋ค์ด๋ก๋ ์๋ฌ: {e}")
|
27 |
|
28 |
+
# ์ํ ํ
์คํธ
|
29 |
SAMPLE_TEXT = """
|
30 |
The three reportedly discussed the Stargate Project, a large-scale AI initiative led by OpenAI, SoftBank, and U.S. software giant Oracle. The project aims to invest $500 billion over the next four years in building new AI infrastructure in the U.S. The U.S. government has shown a strong commitment to the initiative, with President Donald Trump personally announcing it at the White House the day after his inauguration last month. If Samsung participates, the project will lead to a Korea-U.S.-Japan AI alliance.
|
31 |
The AI sector requires massive investments and extensive resources, including advanced models, high-performance AI chips to power the models, and large-scale data centers to operate them. Nvidia and TSMC currently dominate the AI sector, but a partnership between Samsung, SoftBank, and OpenAI could pave the way for a competitive alternative.
|
|
|
33 |
|
34 |
def safe_process(func):
|
35 |
"""
|
36 |
+
์์ธ ๋ฐ์ ์ ๋ก๊ทธ๋ฅผ ๋จ๊ธฐ๊ณ None์ ๋ฐํํ๋ ๋ฐ์ฝ๋ ์ดํฐ.
|
37 |
+
Gradio ์ธํฐํ์ด์ค๊ฐ ์์ธ๋ก ์ธํด ์ค๋จ๋์ง ์๋๋ก ๋์์ค๋๋ค.
|
|
|
38 |
"""
|
39 |
def wrapper(*args, **kwargs):
|
40 |
try:
|
|
|
47 |
@safe_process
|
48 |
def parse_wbg_results(raw_output):
|
49 |
"""
|
50 |
+
wbgtopic.WBGDocTopic์ suggest_topics() ๊ฒฐ๊ณผ๋ฅผ
|
51 |
+
'label', 'score_mean', 'score_std' ๊ตฌ์กฐ์ ๋ฆฌ์คํธ๋ก ํต์ผํด์ ๋ฐํํ๋ค.
|
52 |
+
|
53 |
+
๋ฐํ ๊ตฌ์กฐ ์์:
|
54 |
+
[
|
55 |
+
{
|
56 |
+
"label": "Agriculture",
|
57 |
+
"score_mean": 0.32,
|
58 |
+
"score_std": 0.05
|
59 |
+
},
|
60 |
+
...
|
61 |
+
]
|
62 |
"""
|
63 |
+
# ๋๋ฒ๊ทธ: ์ค์ ๊ฒฐ๊ณผ ๊ตฌ์กฐ๋ฅผ ํ์ธํด๋ณด์ธ์
|
64 |
+
print(">>> DEBUG: raw_output =", raw_output)
|
65 |
+
|
66 |
+
# ๊ฒฐ๊ณผ๊ฐ ๋น์์ผ๋ฉด ๋น ๋ฆฌ์คํธ ๋ฐํ
|
67 |
if not raw_output:
|
68 |
return []
|
69 |
|
|
|
|
|
|
|
70 |
first_item = raw_output[0]
|
71 |
|
72 |
+
# (1) ์ด๋ฏธ 'label' ํค๊ฐ ์๋ ๋์
๋๋ฆฌ ํํ๋ผ๋ฉด
|
73 |
+
# ์: [{"label": "...", "score": ...}, ...] ํน์ {"label": "...", "score_mean": ...}
|
74 |
+
if isinstance(first_item, dict) and ("label" in first_item):
|
75 |
+
parsed_list = []
|
76 |
+
for item in raw_output:
|
77 |
+
label = item.get("label", "")
|
78 |
+
# score_mean / score_std๊ฐ ์ด๋ฏธ ์์ผ๋ฉด ์ฌ์ฉ
|
79 |
+
# ์์ผ๋ฉด score ๋ฑ์์ ์ถ๋ก
|
80 |
+
score_mean = item.get("score_mean", None)
|
81 |
+
score_std = item.get("score_std", None)
|
82 |
+
|
83 |
+
# ์: score๋ง ์๋ ๊ฒฝ์ฐ
|
84 |
+
if score_mean is None and "score" in item:
|
85 |
+
# ์ ์๊ฐ 0~1 ๋ฒ์์ธ์ง 0~100 ๋ฒ์์ธ์ง ํ์ธ ํ์
|
86 |
+
# ์ฐ์ ๊ทธ๋๋ก float ์ฒ๋ฆฌ
|
87 |
+
score_mean = float(item["score"])
|
88 |
+
if score_mean is None:
|
89 |
+
score_mean = 0.0
|
90 |
+
|
91 |
+
if score_std is None:
|
92 |
+
score_std = 0.0
|
93 |
|
94 |
+
parsed_list.append({
|
95 |
+
"label": label,
|
96 |
+
"score_mean": float(score_mean),
|
97 |
+
"score_std": float(score_std)
|
98 |
+
})
|
99 |
+
return parsed_list
|
100 |
+
|
101 |
+
# (2) ํ ํฝ ์ด๋ฆ: ์ ์ ํํ์ ๋์
๋๋ฆฌ๊ฐ ์๋ ๊ฒฝ์ฐ
|
102 |
+
# ์: [{"Agriculture": 0.22, "Climate Change": 0.55}, ...]
|
103 |
if isinstance(first_item, dict):
|
104 |
+
# raw_output๊ฐ ์ฌ๋ฌ dict๋ฅผ ๋ด๊ณ ์์ ์ ์์ผ๋ฏ๋ก, ํ๋๋ก ํฉ์น๊ฑฐ๋
|
105 |
+
# ํน์ ์ฒซ ๋ฒ์งธ dict๋ง ํ์ฑํ ์ง ๊ฒฐ์ ํด์ผ ํจ.
|
106 |
+
# ์ผ๋จ ์ฌ๊ธฐ์๋ ํฉ์น๋ ๋ฐฉ์์ผ๋ก ์์ฐ:
|
107 |
+
merged = {}
|
108 |
+
for d in raw_output:
|
109 |
+
for k, v in d.items():
|
110 |
+
# ํค ์ค๋ณต ์ ๋ง์ง๋ง ๊ฐ์ผ๋ก overwrite
|
111 |
+
merged[k] = v
|
112 |
+
|
113 |
parsed_list = []
|
114 |
+
for label, val in merged.items():
|
115 |
parsed_list.append({
|
116 |
"label": label,
|
117 |
"score_mean": float(val),
|
118 |
+
"score_std": 0.0
|
119 |
})
|
120 |
return parsed_list
|
121 |
|
122 |
+
# ์์์น ๋ชปํ ๊ตฌ์กฐ์ธ ๊ฒฝ์ฐ
|
123 |
return []
|
124 |
|
125 |
@safe_process
|
126 |
def analyze_text_sections(text):
|
127 |
"""
|
128 |
+
ํ
์คํธ๋ฅผ ์ฌ๋ฌ ์น์
(์: 3๋ฌธ์ฅ์ฉ)์ผ๋ก ๋๋๊ณ ,
|
129 |
+
๊ฐ ์น์
๋ณ๋ก suggest_topics() ๊ฒฐ๊ณผ๋ฅผ parse_wbg_results()๋ก ํ์ฑํด ๋ฆฌ์คํธ๋ก ๋ชจ์๋ค.
|
|
|
130 |
"""
|
131 |
sentences = sent_tokenize(text)
|
132 |
+
# 3๋ฌธ์ฅ์ฉ ๋ฌถ์ด์ ํ๋์ ์น์
์ ๊ตฌ์ฑ
|
133 |
sections = [' '.join(sentences[i:i+3]) for i in range(0, len(sentences), 3)]
|
134 |
|
135 |
section_topics = []
|
|
|
143 |
@safe_process
|
144 |
def calculate_topic_correlations(topic_dicts):
|
145 |
"""
|
146 |
+
topic_dicts: [{'label': ..., 'score_mean': ..., 'score_std': ...}, ...]
|
147 |
+
|
148 |
+
์ฃผ์ ๋ณ score_mean๋ง ๋ฝ์์ ์๊ด๊ด๊ณ๋ฅผ ๊ตฌํ๋ค.
|
149 |
+
์ค์ ๋ก๋ '์๋ก ๋ค๋ฅธ ๋ฌธ์'๋ค์ ๋ํ ์๊ด์ ๊ตฌํ๋ ๊ฒ์ด ํ๋นํ๋,
|
150 |
+
์ฌ๊ธฐ์๋ ์์๋ก ๋จ์ผ ํ
์คํธ์ ์๋ก ๋ค๋ฅธ ํ ํฝ๋ค ๊ฐ ์ ์ ์๊ด๋๋ฅผ ๊ณ์ฐํ๋ค.
|
151 |
"""
|
152 |
if len(topic_dicts) < 2:
|
153 |
return np.array([[1.0]]), ["Insufficient topics"]
|
|
|
164 |
@safe_process
|
165 |
def perform_sentiment_analysis(text):
|
166 |
"""
|
167 |
+
NLTK VADER๋ฅผ ์ฌ์ฉํด ๋ฌธ์ฅ๋ณ ๊ฐ์ฑ ์ ์๋ฅผ ๊ณ์ฐํ๋ค.
|
168 |
+
๋ฐํ๊ฐ์ pandas DataFrame ํ์.
|
|
|
169 |
"""
|
170 |
sia = SentimentIntensityAnalyzer()
|
171 |
sents = sent_tokenize(text)
|
|
|
175 |
@safe_process
|
176 |
def create_topic_clusters(topic_dicts):
|
177 |
"""
|
178 |
+
score_mean, score_std 2์ฐจ์์ผ๋ก KMeans ํด๋ฌ์คํฐ๋ง.
|
179 |
+
ํ ํฝ ์๊ฐ 3๊ฐ ๋ฏธ๋ง์ด๋ฉด trivially 0๋ฒ ํด๋ฌ์คํฐ๋ก ์ฒ๋ฆฌ.
|
180 |
"""
|
181 |
if len(topic_dicts) < 3:
|
182 |
return [0] * len(topic_dicts)
|
|
|
196 |
@safe_process
|
197 |
def create_main_charts(topic_dicts):
|
198 |
"""
|
199 |
+
๋ฐ ์ฐจํธ์ ๋ ์ด๋ ์ฐจํธ๋ฅผ ์์ฑ.
|
200 |
+
'score_mean'์ 0~1๋ก ๋ณด๊ณ , 100๋ฐฐ ํ์ฌ ํผ์ผํธ๋ก ์๊ฐํ.
|
201 |
"""
|
202 |
if not topic_dicts:
|
203 |
return go.Figure(), go.Figure()
|
204 |
|
205 |
labels = [t['label'] for t in topic_dicts]
|
206 |
+
scores = [t['score_mean'] * 100 for t in topic_dicts]
|
207 |
|
208 |
+
# ๋ฐ ์ฐจํธ
|
209 |
bar_fig = go.Figure(
|
210 |
data=[go.Bar(x=labels, y=scores, marker_color='rgb(55, 83, 109)')]
|
211 |
)
|
212 |
bar_fig.update_layout(
|
213 |
+
title='์ฃผ์ ๋ถ์ ๊ฒฐ๊ณผ',
|
214 |
+
xaxis_title='์ฃผ์ ',
|
215 |
+
yaxis_title='๊ด๋ จ๋(%)',
|
216 |
template='plotly_white',
|
217 |
height=500,
|
218 |
)
|
219 |
|
220 |
+
# ๋ ์ด๋ ์ฐจํธ
|
221 |
radar_fig = go.Figure()
|
222 |
radar_fig.add_trace(go.Scatterpolar(
|
223 |
r=scores,
|
224 |
theta=labels,
|
225 |
fill='toself',
|
226 |
+
name='์ฃผ์ ๋ถํฌ'
|
227 |
))
|
228 |
radar_fig.update_layout(
|
229 |
+
title='์ฃผ์ ๋ ์ด๋ ์ฐจํธ',
|
230 |
template='plotly_white',
|
231 |
height=500,
|
232 |
polar=dict(radialaxis=dict(visible=True)),
|
|
|
237 |
@safe_process
|
238 |
def create_correlation_heatmap(corr_matrix, labels):
|
239 |
"""
|
240 |
+
์๊ด๊ด๊ณ ํ๋ ฌ์ ํํธ๋งต์ผ๋ก ์๊ฐํ.
|
241 |
+
๋ง์ฝ ๋ฐ์ดํฐ๊ฐ ๋ถ์กฑํ๋ฉด ์๋ด ๋ฌธ๊ตฌ๋ง ํ์.
|
242 |
"""
|
243 |
if corr_matrix.ndim == 0:
|
244 |
+
# ์ค์นผ๋ผ(0์ฐจ์)์ด๋ฉด 2์ฐจ์ ๋ฐฐ์ด๋ก ๋ฐ๊ฟ์ค
|
245 |
corr_matrix = np.array([[corr_matrix]])
|
246 |
|
247 |
if corr_matrix.shape == (1, 1):
|
248 |
+
# ๋ฐ์ดํฐ๊ฐ ๋ถ์กฑํ ๊ฒฝ์ฐ
|
249 |
fig = go.Figure()
|
250 |
fig.add_annotation(text="Not enough topics for correlation", showarrow=False)
|
251 |
return fig
|
|
|
257 |
colorscale='Viridis'
|
258 |
))
|
259 |
fig.update_layout(
|
260 |
+
title='์ฃผ์ ์๊ด๊ด๊ณ ํํธ๋งต',
|
261 |
height=500,
|
262 |
template='plotly_white'
|
263 |
)
|
|
|
266 |
@safe_process
|
267 |
def create_topic_evolution(section_topics):
|
268 |
"""
|
269 |
+
์น์
๋ณ ํ ํฝ ์ ์ ๋ณํ๋ฅผ ๋ผ์ธ ์ฐจํธ๋ก ๋ํ๋ธ๋ค.
|
270 |
+
section_topics: [[{'label':..., 'score_mean':...}, ...], [...], ...]
|
|
|
271 |
"""
|
272 |
fig = go.Figure()
|
273 |
if not section_topics or len(section_topics) == 0:
|
|
|
276 |
if not section_topics[0]:
|
277 |
return fig
|
278 |
|
279 |
+
# ์ฒซ ์น์
์ ํ ํฝ๋ค์ ๊ธฐ์ค์ผ๋ก, ๊ฐ ์น์
๋ง๋ค ํด๋น ํ ํฝ์ด ์กด์ฌํ๋ฉด ์ ์๋ฅผ ์ถ์ถ
|
280 |
for topic_dict in section_topics[0]:
|
281 |
label = topic_dict['label']
|
282 |
score_list = []
|
|
|
295 |
))
|
296 |
|
297 |
fig.update_layout(
|
298 |
+
title='์น์
๋ณ ์ฃผ์ ๋ณํ ์ถ์ด',
|
299 |
+
xaxis_title='์น์
',
|
300 |
+
yaxis_title='score_mean',
|
301 |
height=500,
|
302 |
template='plotly_white'
|
303 |
)
|
|
|
306 |
@safe_process
|
307 |
def create_confidence_gauge(topic_dicts):
|
308 |
"""
|
309 |
+
๊ฐ ํ ํฝ์ ์ ๋ขฐ๋๋ฅผ ๊ฒ์ด์ง ํํ๋ก ํ์.
|
310 |
+
์ฌ๊ธฐ์๋ (1 - score_std) * 100 ๋จ์ ๊ณต์ ์ฌ์ฉ.
|
311 |
"""
|
312 |
if not topic_dicts:
|
313 |
return go.Figure()
|
|
|
316 |
num_topics = len(topic_dicts)
|
317 |
|
318 |
for i, t in enumerate(topic_dicts):
|
|
|
319 |
conf_val = 100.0 * (1.0 - t.get("score_std", 0.0))
|
320 |
fig.add_trace(go.Indicator(
|
321 |
mode="gauge+number",
|
|
|
334 |
@spaces.GPU()
|
335 |
def process_all_analysis(text):
|
336 |
"""
|
337 |
+
์ ์ฒด ํ
์คํธ์ ๋ํ ํ ํฝ ๋ถ์, ์น์
๋ถ์, ์๊ด๊ด๊ณ, ๊ฐ์ฑ๋ถ์, ํด๋ฌ์คํฐ๋ง ๋ฑ์ ์ํํ ๋ค
|
338 |
+
JSON ๊ฒฐ๊ณผ์ Plotly ์ฐจํธ๋ค์ ๋ฐํํ๋ค.
|
339 |
"""
|
340 |
try:
|
341 |
+
# 1) ์ ์ฒด ํ
์คํธ ๋์ ํ ํฝ ๋ถ์
|
342 |
raw_results = clf.suggest_topics(text)
|
343 |
all_topics = parse_wbg_results(raw_results)
|
344 |
|
345 |
+
# 2) score_mean ๊ธฐ์ค ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌ ํ ์์ 5๊ฐ
|
346 |
sorted_topics = sorted(all_topics, key=lambda x: x['score_mean'], reverse=True)
|
347 |
top_topics = sorted_topics[:5]
|
348 |
|
349 |
+
# 3) ์น์
๋ณ ๋ถ์
|
350 |
section_topics = analyze_text_sections(text)
|
351 |
|
352 |
+
# 4) ์ถ๊ฐ ๋ถ์(์๊ด๊ด๊ณ, ๊ฐ์ฑ๋ถ์, ํด๋ฌ์คํฐ)
|
353 |
corr_matrix, corr_labels = calculate_topic_correlations(all_topics)
|
354 |
sentiments_df = perform_sentiment_analysis(text)
|
355 |
clusters = create_topic_clusters(all_topics)
|
356 |
|
357 |
+
# 5) ์ฐจํธ ์์ฑ
|
358 |
bar_chart, radar_chart = create_main_charts(top_topics)
|
359 |
heatmap = create_correlation_heatmap(corr_matrix, corr_labels)
|
360 |
evolution_chart = create_topic_evolution(section_topics)
|
361 |
gauge_chart = create_confidence_gauge(top_topics)
|
362 |
|
363 |
+
# 6) JSON ํํ๋ก ๋ฌถ์ด์ ๋ฐํ(๋ฌธ์์ด ํค๋ง ์ฌ์ฉ)
|
364 |
results = {
|
365 |
+
"top_topics": top_topics, # ์์ 5๊ฐ ํ ํฝ
|
366 |
+
"clusters": clusters, # ํด๋ฌ์คํฐ ๊ฒฐ๊ณผ
|
367 |
+
"sentiments": sentiments_df.to_dict(orient="records") # ๊ฐ์ฑ ๋ถ์
|
368 |
}
|
369 |
|
|
|
370 |
return (
|
371 |
+
results, # JSON output
|
372 |
+
bar_chart, # plot1
|
373 |
+
radar_chart, # plot2
|
374 |
+
heatmap, # plot3
|
375 |
+
evolution_chart, # plot4
|
376 |
+
gauge_chart, # plot5
|
377 |
+
go.Figure() # plot6 (ํ์ ์ ๊ฐ์ฑ๋ถ์ ๊ทธ๋ํ ์ฌ์ฉ)
|
378 |
)
|
379 |
|
380 |
except Exception as e:
|
|
|
394 |
# Gradio UI Definition #
|
395 |
######################################################
|
396 |
|
397 |
+
with gr.Blocks(title="๊ณ ๊ธ ๋ฌธ์ ์ฃผ์ ๋ถ์๊ธฐ") as demo:
|
398 |
+
gr.Markdown("## ๊ณ ๊ธ ๋ฌธ์ ์ฃผ์ ๋ถ์๊ธฐ")
|
399 |
gr.Markdown(
|
400 |
+
"ํ
์คํธ๋ฅผ ์
๋ ฅํ ๋ค, **๋ถ์ ์์** ๋ฒํผ์ ๋๋ฌ์ฃผ์ธ์. "
|
401 |
+
"์ฃผ์ ํ ํฝ ๋ถ์, ์๊ด๊ด๊ณ, ์ ๋ขฐ๋ ๊ฒ์ด์ง, ๊ฐ์ฑ๋ถ์ ๊ฒฐ๊ณผ ๋ฑ์ ํ์ธํ ์ ์์ต๋๋ค."
|
402 |
)
|
403 |
|
404 |
with gr.Row():
|
405 |
text_input = gr.Textbox(
|
406 |
value=SAMPLE_TEXT,
|
407 |
+
label="๋ถ์ํ ํ
์คํธ ์
๋ ฅ",
|
408 |
lines=8
|
409 |
)
|
410 |
with gr.Row():
|
411 |
+
submit_btn = gr.Button("๋ถ์ ์์", variant="primary")
|
412 |
|
413 |
with gr.Tabs():
|
414 |
+
with gr.TabItem("์ฃผ์ ๋ถ์"):
|
415 |
with gr.Row():
|
416 |
+
plot1 = gr.Plot(label="์ฃผ์ ๋ถํฌ(Bar Chart)")
|
417 |
+
plot2 = gr.Plot(label="๋ ์ด๋ ์ฐจํธ")
|
418 |
+
with gr.TabItem("์์ธ ๋ถ์"):
|
419 |
with gr.Row():
|
420 |
+
plot3 = gr.Plot(label="์๊ด๊ด๊ณ ํํธ๋งต")
|
421 |
+
plot4 = gr.Plot(label="์น์
๋ณ ํ ํฝ ๋ณํ")
|
422 |
+
with gr.TabItem("์ ๋ขฐ๋ ๋ถ์"):
|
423 |
+
plot5 = gr.Plot(label="์ ๋ขฐ๋ ๊ฒ์ด์ง")
|
424 |
+
with gr.TabItem("๊ฐ์ฑ ๋ถ์"):
|
425 |
+
plot6 = gr.Plot(label="๊ฐ์ฑ๋ถ์ ๊ฒฐ๊ณผ")
|
426 |
|
427 |
with gr.Row():
|
428 |
+
output_json = gr.JSON(label="์์ธ ๋ถ์ ๊ฒฐ๊ณผ(JSON)")
|
429 |
|
430 |
submit_btn.click(
|
431 |
fn=process_all_analysis,
|
|
|
438 |
demo.launch(
|
439 |
server_name="0.0.0.0",
|
440 |
server_port=7860,
|
441 |
+
share=False, # ๊ณต๊ฐ ๋งํฌ ํ์ ์ True
|
442 |
debug=True
|
443 |
)
|