JUNGU commited on
Commit
a204a9d
ยท
verified ยท
1 Parent(s): 8c7fccd

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +53 -52
src/streamlit_app.py CHANGED
@@ -11,7 +11,7 @@ from collections import Counter
11
  import json
12
  import os
13
  from datetime import datetime, timedelta
14
- import openai
15
  from dotenv import load_dotenv
16
  import traceback
17
  import plotly.graph_objects as go
@@ -39,27 +39,29 @@ class SchedulerState:
39
  # ์ „์—ญ ์Šค์ผ€์ค„๋Ÿฌ ์ƒํƒœ ๊ฐ์ฒด ์ƒ์„ฑ (์Šค๋ ˆ๋“œ ์•ˆ์—์„œ ์‚ฌ์šฉ)
40
  global_scheduler_state = SchedulerState()
41
 
42
- # API ํ‚ค ์„ค์ •
43
  if 'openai_api_key' not in st.session_state:
44
- # Hugging Face Spaces์˜ Streamlit secrets์—์„œ API ํ‚ค ๊ฐ€์ ธ์˜ค๊ธฐ
45
- if 'OPENAI_API_KEY' in st.secrets:
46
- st.session_state.openai_api_key = st.secrets['OPENAI_API_KEY']
47
- # OpenAI ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™”
48
- from openai import OpenAI
49
- st.session_state.openai_client = OpenAI(api_key=st.session_state.openai_api_key)
50
- else:
51
- st.session_state.openai_api_key = None
52
- st.session_state.openai_client = None
53
- # # API ํ‚ค ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ ์„ธ์…˜ ์ƒํƒœ ์ดˆ๊ธฐํ™”
54
- # if 'openai_api_key' not in st.session_state:
55
- # st.session_state.openai_api_key = None
56
 
57
- # # ํ™˜๊ฒฝ ๋ณ€์ˆ˜์—์„œ API ํ‚ค ๋กœ๋“œ ์‹œ๋„
58
- # load_dotenv()
59
- # if os.getenv('OPENAI_API_KEY'):
60
- # st.session_state.openai_api_key = os.getenv('OPENAI_API_KEY')
61
- # elif 'OPENAI_API_KEY' in st.secrets:
62
- # st.session_state.openai_api_key = st.secrets['OPENAI_API_KEY']
 
 
 
 
 
63
 
64
  # ์ž„์‹œ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก NLTK ๋ฐ์ดํ„ฐ ๊ฒฝ๋กœ ์„ค์ •
65
  nltk_data_dir = '/tmp/nltk_data'
@@ -77,23 +79,23 @@ try:
77
  except LookupError:
78
  nltk.download('stopwords', download_dir=nltk_data_dir)
79
 
80
- # OpenAI API ํ‚ค ์„ค์ • (์‹ค์ œ ์‚ฌ์šฉ ์‹œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋‚˜ Streamlit secrets์—์„œ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค)
81
- if 'OPENAI_API_KEY' in os.environ:
82
- openai.api_key = os.environ['OPENAI_API_KEY']
83
- elif 'OPENAI_API_KEY' in st.secrets:
84
- openai.api_key = st.secrets['OPENAI_API_KEY']
85
- elif os.getenv('OPENAI_API_KEY'):
86
- openai.api_key = os.getenv('OPENAI_API_KEY')
87
-
88
  # ํŽ˜์ด์ง€ ์„ค์ •
89
  st.set_page_config(page_title="๋‰ด์Šค ๊ธฐ์‚ฌ ๋„๊ตฌ", page_icon="๐Ÿ“ฐ", layout="wide")
90
 
91
- # ์‚ฌ์ด๋“œ๋ฐ” ๋ฉ”๋‰ด ์„ค์ •
92
- st.sidebar.title("๋‰ด์Šค ๊ธฐ์‚ฌ ๋„๊ตฌ")
93
- menu = st.sidebar.radio(
94
- "๋ฉ”๋‰ด ์„ ํƒ",
95
- ["๋‰ด์Šค ๊ธฐ์‚ฌ ํฌ๋กค๋ง", "๊ธฐ์‚ฌ ๋ถ„์„ํ•˜๊ธฐ", "์ƒˆ ๊ธฐ์‚ฌ ์ƒ์„ฑํ•˜๊ธฐ", "๋‰ด์Šค ๊ธฐ์‚ฌ ์˜ˆ์•ฝํ•˜๊ธฐ"]
96
- )
 
 
 
 
 
 
 
 
97
 
98
  # ์ €์žฅ๋œ ๊ธฐ์‚ฌ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ํ•จ์ˆ˜
99
  def load_saved_articles():
@@ -260,7 +262,6 @@ def extract_keywords_for_wordcloud(text, top_n=50):
260
 
261
 
262
  # ์›Œ๋“œ ํด๋ผ์šฐ๋“œ ์ƒ์„ฑ ํ•จ์ˆ˜
263
-
264
  def generate_wordcloud(keywords_dict):
265
  if not WordCloud:
266
  st.warning("์›Œ๋“œํด๋ผ์šฐ๋“œ ์„ค์น˜์•ˆ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.")
@@ -330,6 +331,9 @@ def analyze_news_content(news_df):
330
  # OpenAI API๋ฅผ ์ด์šฉํ•œ ์ƒˆ ๊ธฐ์‚ฌ ์ƒ์„ฑ
331
  def generate_article(original_content, prompt_text):
332
  try:
 
 
 
333
  response = st.session_state.openai_client.chat.completions.create(
334
  model="gpt-4.1-mini",
335
  messages=[
@@ -345,12 +349,19 @@ def generate_article(original_content, prompt_text):
345
  # OpenAI API๋ฅผ ์ด์šฉํ•œ ์ด๋ฏธ์ง€ ์ƒ์„ฑ
346
  def generate_image(prompt):
347
  try:
348
- response = openai.images.generate(
 
 
 
349
  model="gpt-image-1",
350
  prompt=prompt
351
  )
352
- image_base64=response.data[0].b64_json
353
- return f"data:image/png;base64,{image_base64}"
 
 
 
 
354
  except Exception as e:
355
  return f"์ด๋ฏธ์ง€ ์ƒ์„ฑ ์˜ค๋ฅ˜: {str(e)}"
356
 
@@ -522,7 +533,7 @@ if menu == "๋‰ด์Šค ๊ธฐ์‚ฌ ํฌ๋กค๋ง":
522
  st.write(f"**์š”์•ฝ:** {article['description']}")
523
  st.write(f"**๋งํฌ:** {article['link']}")
524
  st.write("**๋ณธ๋ฌธ ๋ฏธ๋ฆฌ๋ณด๊ธฐ:**")
525
- st.write(article['content'][:300] + "...")
526
 
527
  elif menu == "๊ธฐ์‚ฌ ๋ถ„์„ํ•˜๊ธฐ":
528
  st.header("๊ธฐ์‚ฌ ๋ถ„์„ํ•˜๊ธฐ")
@@ -557,7 +568,6 @@ elif menu == "๊ธฐ์‚ฌ ๋ถ„์„ํ•˜๊ธฐ":
557
  keyword_tab1, keyword_tab2 = st.tabs(["ํ‚ค์›Œ๋“œ ๋นˆ๋„", "์›Œ๋“œํด๋ผ์šฐ๋“œ"])
558
 
559
  with keyword_tab1:
560
-
561
  keywords = analyze_keywords(selected_article['content'])
562
 
563
  # ์‹œ๊ฐํ™”
@@ -633,13 +643,7 @@ elif menu == "๊ธฐ์‚ฌ ๋ถ„์„ํ•˜๊ธฐ":
633
  try:
634
  nltk.data.find('taggers/averaged_perceptron_tagger')
635
  except LookupError:
636
- nltk.download('averaged_perceptron_tagger')
637
-
638
- # Try using the correct resource name as shown in the error message
639
- try:
640
- nltk.data.find('averaged_perceptron_tagger_eng')
641
- except LookupError:
642
- nltk.download('averaged_perceptron_tagger_eng')
643
 
644
  # ์–ธ์–ด ๊ฐ์ง€ (๊ฐ„๋‹จํ•œ ๋ฐฉ์‹)
645
  is_korean = bool(re.search(r'[๊ฐ€-ํžฃ]', content))
@@ -710,11 +714,9 @@ elif menu == "๊ธฐ์‚ฌ ๋ถ„์„ํ•˜๊ธฐ":
710
 
711
  elif analysis_type == "๊ฐ์ • ๋ถ„์„":
712
  if st.button("๊ฐ์ • ๋ถ„์„ํ•˜๊ธฐ"):
713
- if st.session_state.openai_api_key:
714
  with st.spinner("๊ธฐ์‚ฌ์˜ ๊ฐ์ •์„ ๋ถ„์„ ์ค‘์ž…๋‹ˆ๋‹ค..."):
715
  try:
716
- openai.api_key = st.session_state.openai_api_key
717
-
718
  # ๊ฐ์ • ๋ถ„์„ ํ”„๋กฌํ”„ํŠธ ์„ค์ •
719
  response = st.session_state.openai_client.chat.completions.create(
720
  model="gpt-4.1-mini",
@@ -913,8 +915,7 @@ elif menu == "์ƒˆ ๊ธฐ์‚ฌ ์ƒ์„ฑํ•˜๊ธฐ":
913
  generate_image_too = st.checkbox("๊ธฐ์‚ฌ ์ƒ์„ฑ ํ›„ ์ด๋ฏธ์ง€๋„ ํ•จ๊ป˜ ์ƒ์„ฑํ•˜๊ธฐ", value=True)
914
 
915
  if st.button("์ƒˆ ๊ธฐ์‚ฌ ์ƒ์„ฑํ•˜๊ธฐ"):
916
- if st.session_state.openai_api_key:
917
- openai.api_key = st.session_state.openai_api_key
918
  with st.spinner("๊ธฐ์‚ฌ๋ฅผ ์ƒ์„ฑ ์ค‘์ž…๋‹ˆ๋‹ค..."):
919
  new_article = generate_article(selected_article['content'], prompt_text)
920
 
 
11
  import json
12
  import os
13
  from datetime import datetime, timedelta
14
+ from openai import OpenAI
15
  from dotenv import load_dotenv
16
  import traceback
17
  import plotly.graph_objects as go
 
39
  # ์ „์—ญ ์Šค์ผ€์ค„๋Ÿฌ ์ƒํƒœ ๊ฐ์ฒด ์ƒ์„ฑ (์Šค๋ ˆ๋“œ ์•ˆ์—์„œ ์‚ฌ์šฉ)
40
  global_scheduler_state = SchedulerState()
41
 
42
+ # API ํ‚ค ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ ์„ธ์…˜ ์ƒํƒœ ์ดˆ๊ธฐํ™”
43
  if 'openai_api_key' not in st.session_state:
44
+ st.session_state.openai_api_key = None
45
+ st.session_state.openai_client = None
46
+
47
+ # ์—ฌ๋Ÿฌ ๋ฐฉ๋ฒ•์œผ๋กœ API ํ‚ค ๋กœ๋“œ ์‹œ๋„
48
+ load_dotenv() # .env ํŒŒ์ผ์—์„œ ๋กœ๋“œ ์‹œ๋„
49
+
50
+ # 1. ํ™˜๊ฒฝ ๋ณ€์ˆ˜์—์„œ API ํ‚ค ํ™•์ธ
51
+ if os.environ.get('OPENAI_API_KEY'):
52
+ st.session_state.openai_api_key = os.environ.get('OPENAI_API_KEY')
 
 
 
53
 
54
+ # 2. Streamlit secrets์—์„œ API ํ‚ค ํ™•์ธ (try-except๋กœ ์˜ค๋ฅ˜ ๋ฐฉ์ง€)
55
+ if not st.session_state.openai_api_key:
56
+ try:
57
+ if 'OPENAI_API_KEY' in st.secrets:
58
+ st.session_state.openai_api_key = st.secrets['OPENAI_API_KEY']
59
+ except Exception as e:
60
+ pass # secrets ํŒŒ์ผ์ด ์—†์–ด๋„ ์˜ค๋ฅ˜ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Œ
61
+
62
+ # 3. API ํ‚ค๊ฐ€ ์žˆ์œผ๋ฉด ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™”
63
+ if st.session_state.openai_api_key:
64
+ st.session_state.openai_client = OpenAI(api_key=st.session_state.openai_api_key)
65
 
66
  # ์ž„์‹œ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก NLTK ๋ฐ์ดํ„ฐ ๊ฒฝ๋กœ ์„ค์ •
67
  nltk_data_dir = '/tmp/nltk_data'
 
79
  except LookupError:
80
  nltk.download('stopwords', download_dir=nltk_data_dir)
81
 
 
 
 
 
 
 
 
 
82
  # ํŽ˜์ด์ง€ ์„ค์ •
83
  st.set_page_config(page_title="๋‰ด์Šค ๊ธฐ์‚ฌ ๋„๊ตฌ", page_icon="๐Ÿ“ฐ", layout="wide")
84
 
85
+ # ์‚ฌ์ด๋“œ๋ฐ”์— API ํ‚ค ์ž…๋ ฅ ํ•„๋“œ ์ถ”๊ฐ€
86
+ with st.sidebar:
87
+ st.title("๋‰ด์Šค ๊ธฐ์‚ฌ ๋„๊ตฌ")
88
+ menu = st.radio(
89
+ "๋ฉ”๋‰ด ์„ ํƒ",
90
+ ["๋‰ด์Šค ๊ธฐ์‚ฌ ํฌ๋กค๋ง", "๊ธฐ์‚ฌ ๋ถ„์„ํ•˜๊ธฐ", "์ƒˆ ๊ธฐ์‚ฌ ์ƒ์„ฑํ•˜๊ธฐ", "๋‰ด์Šค ๊ธฐ์‚ฌ ์˜ˆ์•ฝํ•˜๊ธฐ"]
91
+ )
92
+
93
+ st.divider()
94
+ api_key = st.text_input("OpenAI API ํ‚ค ์ž…๋ ฅ", type="password")
95
+ if api_key:
96
+ st.session_state.openai_api_key = api_key
97
+ st.session_state.openai_client = OpenAI(api_key=api_key)
98
+ st.success("API ํ‚ค๊ฐ€ ์„ค์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค!")
99
 
100
  # ์ €์žฅ๋œ ๊ธฐ์‚ฌ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ํ•จ์ˆ˜
101
  def load_saved_articles():
 
262
 
263
 
264
  # ์›Œ๋“œ ํด๋ผ์šฐ๋“œ ์ƒ์„ฑ ํ•จ์ˆ˜
 
265
  def generate_wordcloud(keywords_dict):
266
  if not WordCloud:
267
  st.warning("์›Œ๋“œํด๋ผ์šฐ๋“œ ์„ค์น˜์•ˆ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.")
 
331
  # OpenAI API๋ฅผ ์ด์šฉํ•œ ์ƒˆ ๊ธฐ์‚ฌ ์ƒ์„ฑ
332
  def generate_article(original_content, prompt_text):
333
  try:
334
+ if not st.session_state.openai_client:
335
+ return "OpenAI API ํ‚ค๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค."
336
+
337
  response = st.session_state.openai_client.chat.completions.create(
338
  model="gpt-4.1-mini",
339
  messages=[
 
349
  # OpenAI API๋ฅผ ์ด์šฉํ•œ ์ด๋ฏธ์ง€ ์ƒ์„ฑ
350
  def generate_image(prompt):
351
  try:
352
+ if not st.session_state.openai_client:
353
+ return "OpenAI API ํ‚ค๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค."
354
+
355
+ response = st.session_state.openai_client.images.generate(
356
  model="gpt-image-1",
357
  prompt=prompt
358
  )
359
+ try:
360
+ image_base64 = response.data[0].b64_json
361
+ return f"data:image/png;base64,{image_base64}"
362
+ except AttributeError:
363
+ # b64_json๊ฐ€ ์—†์„ ๊ฒฝ์šฐ URL ์‚ฌ์šฉ
364
+ return response.data[0].url
365
  except Exception as e:
366
  return f"์ด๋ฏธ์ง€ ์ƒ์„ฑ ์˜ค๋ฅ˜: {str(e)}"
367
 
 
533
  st.write(f"**์š”์•ฝ:** {article['description']}")
534
  st.write(f"**๋งํฌ:** {article['link']}")
535
  st.write("**๋ณธ๋ฌธ ๋ฏธ๋ฆฌ๋ณด๊ธฐ:**")
536
+ st.write(article['content'][:300] + "..." if len(article['content']) > 300 else article['content'])
537
 
538
  elif menu == "๊ธฐ์‚ฌ ๋ถ„์„ํ•˜๊ธฐ":
539
  st.header("๊ธฐ์‚ฌ ๋ถ„์„ํ•˜๊ธฐ")
 
568
  keyword_tab1, keyword_tab2 = st.tabs(["ํ‚ค์›Œ๋“œ ๋นˆ๋„", "์›Œ๋“œํด๋ผ์šฐ๋“œ"])
569
 
570
  with keyword_tab1:
 
571
  keywords = analyze_keywords(selected_article['content'])
572
 
573
  # ์‹œ๊ฐํ™”
 
643
  try:
644
  nltk.data.find('taggers/averaged_perceptron_tagger')
645
  except LookupError:
646
+ nltk.download('averaged_perceptron_tagger', download_dir=nltk_data_dir)
 
 
 
 
 
 
647
 
648
  # ์–ธ์–ด ๊ฐ์ง€ (๊ฐ„๋‹จํ•œ ๋ฐฉ์‹)
649
  is_korean = bool(re.search(r'[๊ฐ€-ํžฃ]', content))
 
714
 
715
  elif analysis_type == "๊ฐ์ • ๋ถ„์„":
716
  if st.button("๊ฐ์ • ๋ถ„์„ํ•˜๊ธฐ"):
717
+ if st.session_state.openai_client:
718
  with st.spinner("๊ธฐ์‚ฌ์˜ ๊ฐ์ •์„ ๋ถ„์„ ์ค‘์ž…๋‹ˆ๋‹ค..."):
719
  try:
 
 
720
  # ๊ฐ์ • ๋ถ„์„ ํ”„๋กฌํ”„ํŠธ ์„ค์ •
721
  response = st.session_state.openai_client.chat.completions.create(
722
  model="gpt-4.1-mini",
 
915
  generate_image_too = st.checkbox("๊ธฐ์‚ฌ ์ƒ์„ฑ ํ›„ ์ด๋ฏธ์ง€๋„ ํ•จ๊ป˜ ์ƒ์„ฑํ•˜๊ธฐ", value=True)
916
 
917
  if st.button("์ƒˆ ๊ธฐ์‚ฌ ์ƒ์„ฑํ•˜๊ธฐ"):
918
+ if st.session_state.openai_client:
 
919
  with st.spinner("๊ธฐ์‚ฌ๋ฅผ ์ƒ์„ฑ ์ค‘์ž…๋‹ˆ๋‹ค..."):
920
  new_article = generate_article(selected_article['content'], prompt_text)
921