Commit
b9cf696
ยท
verified ยท
1 Parent(s): e9fe77c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +40 -123
app.py CHANGED
@@ -1,151 +1,70 @@
 
1
  import subprocess
2
 
3
- # ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜ ๋ฐ ์—…๋ฐ์ดํŠธ
4
  subprocess.run(["pip", "install", "--upgrade", "pip"])
5
- subprocess.run(["pip", "install", "--upgrade", "openai", "yfinance", "gradio", "matplotlib", "Pillow"])
6
 
 
7
  import yfinance as yf
8
- import os
9
- import matplotlib.font_manager as fm
10
  import matplotlib.pyplot as plt
 
11
  import numpy as np
12
- import re # ํ•œ๊ธ€, ์ˆซ์ž, ๊ธฐํ˜ธ๋ฅผ ๋‚จ๊ธฐ๊ธฐ ์œ„ํ•œ ์ •๊ทœ ํ‘œํ˜„์‹์— ์‚ฌ์šฉ
13
- import gradio as gr
14
  import io
15
  from PIL import Image
16
  from datetime import datetime, timedelta
17
- from openai import OpenAI
18
 
19
- # 1. ๋‚˜๋ˆ”๊ณ ๋”• ํฐํŠธ ์„ค์น˜ ๋ฐ ์ ์šฉ
20
  def install_nanum_font():
21
  try:
22
  subprocess.run(["apt-get", "update"], check=True)
23
  subprocess.run(["apt-get", "install", "-y", "fonts-nanum"], check=True)
24
  subprocess.run(["fc-cache", "-fv"], check=True)
 
25
  except Exception as e:
26
  print(f"ํฐํŠธ ์„ค์น˜ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {e}")
27
 
28
  install_nanum_font()
29
 
30
- # ๋‚˜๋ˆ”๊ณ ๋”• ํฐํŠธ ๊ฒฝ๋กœ ์„ค์ • ๋ฐ ๊ฐ•์ œ ์ ์šฉ
31
- font_path = '/usr/share/fonts/truetype/nanum/NanumGothic.ttf'
32
-
33
- if os.path.exists(font_path):
34
- fm.fontManager.addfont(font_path)
35
- else:
36
- print("ํฐํŠธ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
37
-
38
- # ๋‚˜๋ˆ”๊ณ ๋”• ํฐํŠธ ๊ฐ•์ œ ์ ์šฉ
39
- font_prop = fm.FontProperties(fname=font_path)
40
- plt.rcParams['font.family'] = font_prop.get_name()
41
- plt.rcParams['axes.unicode_minus'] = False # ๋งˆ์ด๋„ˆ์Šค ๋ถ€ํ˜ธ ๊นจ์ง ๋ฐฉ์ง€
42
-
43
- # Perplexity AI API ์„ค์ •
44
- API_KEY = "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" # ์—ฌ๊ธฐ์— Perplexity AI API ํ‚ค๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”.
45
-
46
- # ๋‰ด์Šค ์š”์•ฝ์„ ๊ฐ€์ ธ์˜ค๋Š” ํ•จ์ˆ˜ (๊ธฐ์กด ์ฝ”๋“œ ์œ ์ง€)
47
  def get_real_news_summary(company, date):
48
- client = OpenAI(api_key=API_KEY, base_url="https://api.perplexity.ai")
49
-
50
- # ๋‚ ์งœ ํ˜•์‹ ์กฐ์ •
51
- target_date = datetime.strptime(date, '%Y-%m-%d')
52
- start_date = (target_date - timedelta(days=1)).strftime('%Y-%m-%d')
53
- end_date = (target_date + timedelta(days=1)).strftime('%Y-%m-%d')
54
-
55
- messages = [
56
- {"role": "system", "content": "You are a helpful assistant that summarizes stock news strictly in Korean."},
57
- {"role": "user", "content": f"Summarize the stock news for {company} between {start_date} and {end_date} in Korean. Only focus on news within this date range."}
58
- ]
59
-
60
- try:
61
- response = client.chat.completions.create(
62
- model="llama-3.1-sonar-large-128k-online",
63
- messages=messages
64
- )
65
- summary = response.choices[0].message.content
66
-
67
- # ํ•œ๊ธ€, ์ˆซ์ž, ๊ณต๋ฐฑ, ํŠน์ˆ˜ ๊ธฐํ˜ธ๋งŒ ๋‚จ๊ธฐ๋Š” ์ •๊ทœ ํ‘œํ˜„์‹
68
- korean_only_summary = re.sub(r'[^\w\s#.,!%()\-\[\]]', '', summary)
69
- formatted_summary = re.sub(r'##\s*(.+)', r'**\1**', korean_only_summary)
70
-
71
- return formatted_summary
72
- except Exception as e:
73
- return f"๋‰ด์Šค ์š”์•ฝ ์ค‘ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {str(e)}"
74
 
75
  def handle_click(company_name, date_clicked):
76
  return get_real_news_summary(company_name, date_clicked)
77
 
78
- # Gradio์—์„œ ์‚ฌ์šฉํ•  ํ•จ์ˆ˜ (๋‰ด์Šค ์š”์•ฝ ํฌํ•จ)
79
  def update_news(input_value, selected_date):
80
- if selected_date == "" or selected_date is None:
81
  return "๋‚ ์งœ๋ฅผ ์„ ํƒํ•ด์ฃผ์„ธ์š”."
82
  else:
83
- ticker = get_dynamic_ticker(input_value)
84
  company_name = ticker_to_name.get(ticker, input_value)
85
  return handle_click(company_name, selected_date)
86
 
87
- # ์ข…๋ชฉ ๋™์  ๋งค์นญ ํ•จ์ˆ˜
88
- def get_dynamic_ticker(input_value):
89
- if input_value == "๋‚˜์Šค๋‹ฅ ์‹œ์ด 1์œ„":
90
- return get_top_market_cap_stock("๋‚˜์Šค๋‹ฅ")
91
- elif input_value == "๋‚˜์Šค๋‹ฅ ๋ฐ”์ด์˜คํ… ์‹œ์ด 1์œ„":
92
- return get_top_market_cap_stock("๋‚˜์Šค๋‹ฅ", industry="Biotechnology")
93
- elif input_value == "๋‚˜์Šค๋‹ฅ ํ—ฌ์Šค์ผ€์–ด ์‹œ์ด 1์œ„":
94
- return get_top_market_cap_stock("๋‚˜์Šค๋‹ฅ", sector="Healthcare")
95
- elif input_value == "์ฝ”์Šคํ”ผ ์‹œ์ด 1์œ„":
96
- return get_top_market_cap_stock("์ฝ”์Šคํ”ผ")
97
- elif input_value == "์ฝ”์Šค๋‹ฅ ์‹œ์ด 1์œ„":
98
- return get_top_market_cap_stock("์ฝ”์Šค๋‹ฅ")
99
- else:
100
- return name_to_ticker.get(input_value, input_value)
101
-
102
- # ์‹œ๊ฐ€์ด์•ก ์ƒ์œ„ ์ข…๋ชฉ ๊ฐ€์ ธ์˜ค๊ธฐ
103
- def get_top_market_cap_stock(market, sector=None, industry=None):
104
- if market == "๋‚˜์Šค๋‹ฅ":
105
- etf_ticker = "QQQ"
106
- elif market == "์ฝ”์Šคํ”ผ":
107
- etf_ticker = "EWY"
108
- elif market == "์ฝ”์Šค๋‹ฅ":
109
- tickers = ["035420.KQ", "068270.KQ", "035720.KQ"]
110
- else:
111
- return None
112
-
113
- if market in ["๋‚˜์Šค๋‹ฅ", "์ฝ”์Šคํ”ผ"]:
114
- etf = yf.Ticker(etf_ticker)
115
- holdings = etf.info.get('holdings', [])
116
- tickers = [holding['symbol'] for holding in holdings]
117
 
118
- largest_market_cap = 0
119
- top_ticker = None
120
 
121
- for ticker in tickers:
122
- stock = yf.Ticker(ticker)
123
- stock_info = stock.info
124
- market_cap = stock_info.get('marketCap', 0)
125
- stock_sector = stock_info.get('sector', None)
126
- stock_industry = stock_info.get('industry', None)
127
-
128
- if sector and stock_sector != sector:
129
- continue
130
- if industry and stock_industry != industry:
131
- continue
132
-
133
- if market_cap > largest_market_cap:
134
- largest_market_cap = market_cap
135
- top_ticker = ticker
136
- ticker_to_name[ticker] = stock_info.get('shortName', ticker)
137
-
138
- return top_ticker
139
-
140
- # ์ฃผ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ์กฐ๊ฑด์— ๋งž๋Š” ๋‚ ์งœ์™€ ๊ทธ๋ž˜ํ”„๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜
141
  def display_stock_with_highlight(input_value, change_type, percent_change):
142
  try:
143
- ticker = get_dynamic_ticker(input_value)
144
  stock = yf.Ticker(ticker)
145
  stock_data = stock.history(period="5y")
146
 
147
  if stock_data.empty:
148
- return "์ฃผ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.", []
149
 
150
  stock_data['Change'] = stock_data['Close'].pct_change() * 100
151
  percent_change = float(percent_change)
@@ -157,23 +76,23 @@ def display_stock_with_highlight(input_value, change_type, percent_change):
157
  highlight_data = stock_data[stock_data['Change'] <= -percent_change]
158
  color = "purple"
159
  else:
160
- return "Invalid change type", []
161
 
162
- dates = stock_data.index.to_numpy()
163
- closing_prices = stock_data['Close'].to_numpy()
164
 
165
  plt.figure(figsize=(10, 6))
166
  plt.plot(dates, closing_prices, color='gray', label=input_value)
167
  plt.scatter(highlight_data.index, highlight_data['Close'], color=color, label=f'{change_type} ํฌ์ธํŠธ')
168
 
169
  for index, row in highlight_data.iterrows():
170
- plt.text(index, row['Close'], index.strftime('%Y-%m-%d'), fontsize=10, fontweight='bold', color=color, ha='right')
171
  plt.axvline(x=index, color=color, linestyle='--', linewidth=1)
172
 
173
  company_name = ticker_to_name.get(ticker, input_value)
174
- plt.title(f'{company_name} ์ฃผ๊ฐ€ ์ถ”์ด', fontproperties=font_prop)
175
- plt.xlabel('๋‚ ์งœ', fontproperties=font_prop)
176
- plt.ylabel('์ข…๊ฐ€', fontproperties=font_prop)
177
  plt.legend()
178
 
179
  buf = io.BytesIO()
@@ -184,23 +103,22 @@ def display_stock_with_highlight(input_value, change_type, percent_change):
184
 
185
  highlight_dates = highlight_data.index.strftime('%Y-%m-%d').tolist()
186
 
187
- return img, gr.update(choices=highlight_dates)
188
  except Exception as e:
189
- return f"Error processing data: {e}", gr.update(choices=[])
 
190
 
191
  # Gradio ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ (3์—ด ๋ ˆ์ด์•„์›ƒ)
192
  with gr.Blocks() as demo:
193
  gr.Markdown("## ์ฃผ๊ฐ€ ๊ทธ๋ž˜ํ”„์™€ ๋‰ด์Šค ์š”์•ฝ")
194
 
195
  with gr.Row():
196
- with gr.Column(): # ์ž…๋ ฅ๊ฐ’์„ ๋‹ด์„ ์ฒซ ๋ฒˆ์งธ ์—ด
197
  input_value = gr.Textbox(label="์ข…๋ชฉ๋ช… ๋˜๋Š” ํ‹ฐ์ปค ์ž…๋ ฅ", placeholder="์˜ˆ: SK๋ฐ”์ด์˜คํŒœ, AAPL")
198
  change_type = gr.Dropdown(choices=["์ƒ์Šน", "ํ•˜๋ฝ"], label="์ƒ์Šน ๋˜๋Š” ํ•˜๋ฝ ์„ ํƒ", value="์ƒ์Šน")
199
  percent_change = gr.Textbox(label="๋ณ€๋™ ํผ์„ผํŠธ (%)", placeholder="์˜ˆ: 10", value="10")
200
-
201
  submit_btn = gr.Button("Submit")
202
 
203
- # ์˜ˆ์ œ (๋™์ ์œผ๋กœ ๋งค์นญ)
204
  examples = [["SK๋ฐ”์ด์˜คํŒœ"],
205
  ["๋‚˜์Šค๋‹ฅ ์‹œ์ด 1์œ„"],
206
  ["๋‚˜์Šค๋‹ฅ ๋ฐ”์ด์˜คํ… ์‹œ์ด 1์œ„"],
@@ -209,11 +127,11 @@ with gr.Blocks() as demo:
209
  ["์ฝ”์Šค๋‹ฅ ์‹œ์ด 1์œ„"]]
210
  gr.Examples(examples=examples, inputs=[input_value])
211
 
212
- with gr.Column(): # ๊ทธ๋ž˜ํ”„๋ฅผ ์ถœ๋ ฅํ•  ๋‘ ๋ฒˆ์งธ ์—ด
213
  plot = gr.Image(label="์ฃผ๊ฐ€ ๊ทธ๋ž˜ํ”„")
214
  date_dropdown = gr.Dropdown(label="์กฐ๊ฑด์— ํ•ด๋‹นํ•˜๋Š” ๋‚ ์งœ ์„ ํƒ", choices=[])
215
 
216
- with gr.Column(): # ๋‰ด์Šค ์š”์•ฝ์„ ์ถœ๋ ฅํ•  ์„ธ ๋ฒˆ์งธ ์—ด
217
  news_output = gr.Markdown(label="๋‰ด์Šค ์š”์•ฝ", value="") # ๋นˆ ์นธ์œผ๋กœ ๊ธฐ๋ณธ ํ‘œ์‹œ
218
 
219
  # Submit ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ๊ทธ๋ž˜ํ”„ ๋ฐ ๋‚ ์งœ ๋“œ๋กญ๋‹ค์šด ์—…๋ฐ์ดํŠธ
@@ -230,5 +148,4 @@ with gr.Blocks() as demo:
230
  outputs=[news_output]
231
  )
232
 
233
- # Gradio ์‹คํ–‰
234
  demo.launch()
 
1
+ # ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜ ๋ฐ ์—…๋ฐ์ดํŠธ
2
  import subprocess
3
 
 
4
  subprocess.run(["pip", "install", "--upgrade", "pip"])
5
+ subprocess.run(["pip", "install", "--upgrade", "yfinance", "gradio", "matplotlib", "Pillow"])
6
 
7
+ # ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž„ํฌํŠธ
8
  import yfinance as yf
9
+ import gradio as gr
 
10
  import matplotlib.pyplot as plt
11
+ import matplotlib.font_manager as fm
12
  import numpy as np
13
+ import pandas as pd
14
+ import re
15
  import io
16
  from PIL import Image
17
  from datetime import datetime, timedelta
 
18
 
19
+ # ๋‚˜๋ˆ”๊ณ ๋”• ํฐํŠธ ์„ค์น˜ ๋ฐ ์ ์šฉ
20
  def install_nanum_font():
21
  try:
22
  subprocess.run(["apt-get", "update"], check=True)
23
  subprocess.run(["apt-get", "install", "-y", "fonts-nanum"], check=True)
24
  subprocess.run(["fc-cache", "-fv"], check=True)
25
+ plt.rcParams['font.family'] = 'NanumGothic'
26
  except Exception as e:
27
  print(f"ํฐํŠธ ์„ค์น˜ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {e}")
28
 
29
  install_nanum_font()
30
 
31
+ # ๋‰ด์Šค ์š”์•ฝ ํ•จ์ˆ˜ (์—ฌ๊ธฐ์„œ๋Š” ๊ฐ„๋‹จํžˆ ์˜ˆ์‹œ๋กœ ์ฒ˜๋ฆฌ)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  def get_real_news_summary(company, date):
33
+ # ์‹ค์ œ API๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” ํ™˜๊ฒฝ์ด๋ฏ€๋กœ, ๊ฐ„๋‹จํ•œ ๋ฌธ์ž์—ด๋กœ ๋Œ€์ฒดํ•ฉ๋‹ˆ๋‹ค.
34
+ return f"{company}์˜ {date} ์ฃผ๋ณ€ ๋‰ด์Šค ์š”์•ฝ์ž…๋‹ˆ๋‹ค."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
  def handle_click(company_name, date_clicked):
37
  return get_real_news_summary(company_name, date_clicked)
38
 
 
39
  def update_news(input_value, selected_date):
40
+ if not selected_date:
41
  return "๋‚ ์งœ๋ฅผ ์„ ํƒํ•ด์ฃผ์„ธ์š”."
42
  else:
43
+ ticker = name_to_ticker.get(input_value, input_value)
44
  company_name = ticker_to_name.get(ticker, input_value)
45
  return handle_click(company_name, selected_date)
46
 
47
+ # ์ข…๋ชฉ๋ช…๊ณผ ํ‹ฐ์ปค ๋งคํ•‘ ๋”•์…”๋„ˆ๋ฆฌ
48
+ name_to_ticker = {
49
+ "SK๋ฐ”์ด์˜คํŒœ": "326030.KS",
50
+ "๋‚˜์Šค๋‹ฅ ์‹œ์ด 1์œ„": "AAPL",
51
+ "๋‚˜์Šค๋‹ฅ ๋ฐ”์ด์˜คํ… ์‹œ์ด 1์œ„": "AMGN",
52
+ "๋‚˜์Šค๋‹ฅ ํ—ฌ์Šค์ผ€์–ด ์‹œ์ด 1์œ„": "JNJ",
53
+ "์ฝ”์Šคํ”ผ ์‹œ์ด 1์œ„": "005930.KS",
54
+ "์ฝ”์Šค๋‹ฅ ์‹œ์ด 1์œ„": "247540.KQ", # ์—์ฝ”ํ”„๋กœ๋น„์— 
55
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
 
57
+ ticker_to_name = {v: k for k, v in name_to_ticker.items()}
 
58
 
59
+ # ์ฃผ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ๊ทธ๋ž˜ํ”„๋ฅผ ๊ทธ๋ฆฌ๋Š” ํ•จ์ˆ˜
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  def display_stock_with_highlight(input_value, change_type, percent_change):
61
  try:
62
+ ticker = name_to_ticker.get(input_value, input_value)
63
  stock = yf.Ticker(ticker)
64
  stock_data = stock.history(period="5y")
65
 
66
  if stock_data.empty:
67
+ return "์ฃผ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.", gr.Dropdown.update(choices=[])
68
 
69
  stock_data['Change'] = stock_data['Close'].pct_change() * 100
70
  percent_change = float(percent_change)
 
76
  highlight_data = stock_data[stock_data['Change'] <= -percent_change]
77
  color = "purple"
78
  else:
79
+ return "Invalid change type", gr.Dropdown.update(choices=[])
80
 
81
+ dates = stock_data.index
82
+ closing_prices = stock_data['Close']
83
 
84
  plt.figure(figsize=(10, 6))
85
  plt.plot(dates, closing_prices, color='gray', label=input_value)
86
  plt.scatter(highlight_data.index, highlight_data['Close'], color=color, label=f'{change_type} ํฌ์ธํŠธ')
87
 
88
  for index, row in highlight_data.iterrows():
89
+ plt.text(index, row['Close'], index.strftime('%Y-%m-%d'), fontsize=8, color=color, ha='right')
90
  plt.axvline(x=index, color=color, linestyle='--', linewidth=1)
91
 
92
  company_name = ticker_to_name.get(ticker, input_value)
93
+ plt.title(f'{company_name} ์ฃผ๊ฐ€ ์ถ”์ด')
94
+ plt.xlabel('๋‚ ์งœ')
95
+ plt.ylabel('์ข…๊ฐ€')
96
  plt.legend()
97
 
98
  buf = io.BytesIO()
 
103
 
104
  highlight_dates = highlight_data.index.strftime('%Y-%m-%d').tolist()
105
 
106
+ return img, gr.Dropdown.update(choices=highlight_dates)
107
  except Exception as e:
108
+ print(f"Error: {e}")
109
+ return f"๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {e}", gr.Dropdown.update(choices=[])
110
 
111
  # Gradio ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ (3์—ด ๋ ˆ์ด์•„์›ƒ)
112
  with gr.Blocks() as demo:
113
  gr.Markdown("## ์ฃผ๊ฐ€ ๊ทธ๋ž˜ํ”„์™€ ๋‰ด์Šค ์š”์•ฝ")
114
 
115
  with gr.Row():
116
+ with gr.Column():
117
  input_value = gr.Textbox(label="์ข…๋ชฉ๋ช… ๋˜๋Š” ํ‹ฐ์ปค ์ž…๋ ฅ", placeholder="์˜ˆ: SK๋ฐ”์ด์˜คํŒœ, AAPL")
118
  change_type = gr.Dropdown(choices=["์ƒ์Šน", "ํ•˜๋ฝ"], label="์ƒ์Šน ๋˜๋Š” ํ•˜๋ฝ ์„ ํƒ", value="์ƒ์Šน")
119
  percent_change = gr.Textbox(label="๋ณ€๋™ ํผ์„ผํŠธ (%)", placeholder="์˜ˆ: 10", value="10")
 
120
  submit_btn = gr.Button("Submit")
121
 
 
122
  examples = [["SK๋ฐ”์ด์˜คํŒœ"],
123
  ["๋‚˜์Šค๋‹ฅ ์‹œ์ด 1์œ„"],
124
  ["๋‚˜์Šค๋‹ฅ ๋ฐ”์ด์˜คํ… ์‹œ์ด 1์œ„"],
 
127
  ["์ฝ”์Šค๋‹ฅ ์‹œ์ด 1์œ„"]]
128
  gr.Examples(examples=examples, inputs=[input_value])
129
 
130
+ with gr.Column():
131
  plot = gr.Image(label="์ฃผ๊ฐ€ ๊ทธ๋ž˜ํ”„")
132
  date_dropdown = gr.Dropdown(label="์กฐ๊ฑด์— ํ•ด๋‹นํ•˜๋Š” ๋‚ ์งœ ์„ ํƒ", choices=[])
133
 
134
+ with gr.Column():
135
  news_output = gr.Markdown(label="๋‰ด์Šค ์š”์•ฝ", value="") # ๋นˆ ์นธ์œผ๋กœ ๊ธฐ๋ณธ ํ‘œ์‹œ
136
 
137
  # Submit ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ๊ทธ๋ž˜ํ”„ ๋ฐ ๋‚ ์งœ ๋“œ๋กญ๋‹ค์šด ์—…๋ฐ์ดํŠธ
 
148
  outputs=[news_output]
149
  )
150
 
 
151
  demo.launch()