Update src/streamlit_app.py

#1
by fitz87 - opened
Files changed (1) hide show
  1. src/streamlit_app.py +189 -69
src/streamlit_app.py CHANGED
@@ -318,44 +318,53 @@ def generate_wordcloud(keywords_dict):
318
  st.warning("์›Œ๋“œํด๋ผ์šฐ๋“œ ์„ค์น˜์•ˆ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.")
319
  return None
320
  try:
321
- wc= WordCloud(
 
322
  width=800,
323
  height=400,
324
- background_color = 'white',
325
- colormap = 'viridis',
326
  max_font_size=150,
327
  random_state=42
328
- ).generate_from_frequencies(keywords_dict)
329
 
330
  try:
331
  import os
332
- script_dir = os.path.dirname(os.path.abspath(__file__))
333
- possible_font_paths = ["NanumGothic.ttf", "์ด๋ฆ„"]
 
 
334
 
335
  font_path = None
336
- for path in possible_font_paths:
337
- candidate = os.path.join(script_dir, fname)
338
  if os.path.exists(candidate):
339
  font_path = candidate
340
  break
341
-
 
342
  if font_path:
343
- wc= WordCloud(
344
  font_path=font_path,
345
  width=800,
346
  height=400,
347
- background_color = 'white',
348
- colormap = 'viridis',
349
  max_font_size=150,
350
  random_state=42
351
  ).generate_from_frequencies(keywords_dict)
352
- except Exception as e:
353
- print(f"์˜ค๋ฅ˜๋ฐœ์ƒ {str(e)}")
354
 
355
- return wc
 
 
 
 
 
356
 
357
  except Exception as e:
358
- st.error(f"์˜ค๋ฅ˜๋ฐœ์ƒ {str(e)}")
359
  return None
360
 
361
  # ๋‰ด์Šค ๋ถ„์„ ํ•จ์ˆ˜
@@ -389,7 +398,7 @@ def generate_article(original_content, prompt_text):
389
  return "OpenAI API ํ‚ค๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค."
390
 
391
  response = st.session_state.openai_client.chat.completions.create(
392
- model="gpt-4", # ๋˜๋Š” ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ ์ ˆํ•œ ๋ชจ๋ธ
393
  messages=[
394
  {"role": "system", "content": "๋‹น์‹ ์€ ์ „๋ฌธ์ ์ธ ๋‰ด์Šค ๊ธฐ์ž์ž…๋‹ˆ๋‹ค. ์ฃผ์–ด์ง„ ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ ์ƒˆ๋กœ์šด ๊ธฐ์‚ฌ๋ฅผ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”."},
395
  {"role": "user", "content": f"๋‹ค์Œ ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ {prompt_text}\n\n{original_content[:1000]}"}
@@ -400,6 +409,26 @@ def generate_article(original_content, prompt_text):
400
  except Exception as e:
401
  return f"๊ธฐ์‚ฌ ์ƒ์„ฑ ์˜ค๋ฅ˜: {str(e)}"
402
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
403
  # OpenAI API๋ฅผ ์ด์šฉํ•œ ์ด๋ฏธ์ง€ ์ƒ์„ฑ (์ƒˆ๋กœ์šด ๋ฒ„์ „ ๋ฐฉ์‹)
404
  def generate_image(prompt):
405
  try:
@@ -922,19 +951,23 @@ elif menu == "์ƒˆ ๊ธฐ์‚ฌ ์ƒ์„ฑํ•˜๊ธฐ":
922
  if not articles:
923
  st.warning("์ €์žฅ๋œ ๊ธฐ์‚ฌ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋จผ์ € '๋‰ด์Šค ๊ธฐ์‚ฌ ํฌ๋กค๋ง' ๋ฉ”๋‰ด์—์„œ ๊ธฐ์‚ฌ๋ฅผ ์ˆ˜์ง‘ํ•ด์ฃผ์„ธ์š”.")
924
  else:
925
- # ๊ธฐ์‚ฌ ์„ ํƒ
926
- titles = [article['title'] for article in articles]
927
- selected_title = st.selectbox("์›๋ณธ ๊ธฐ์‚ฌ ์„ ํƒ", titles)
928
 
929
- selected_article = next((a for a in articles if a['title'] == selected_title), None)
930
-
931
- if selected_article:
932
- st.write(f"**์›๋ณธ ์ œ๋ชฉ:** {selected_article['title']}")
933
 
934
- with st.expander("์›๋ณธ ๊ธฐ์‚ฌ ๋‚ด์šฉ"):
935
- st.write(selected_article['content'])
936
 
937
- prompt_text ="""๋‹ค์Œ ๊ธฐ์‚ฌ ์–‘์‹์„ ๋”ฐ๋ผ์„œ ๋‹ค์‹œ ์ž‘์„ฑํ•ด์ค˜.
 
 
 
 
 
 
938
  ์—ญํ• : ๋‹น์‹ ์€ ์‹ ๋ฌธ์‚ฌ์˜ ๊ธฐ์ž์ž…๋‹ˆ๋‹ค.
939
  ์ž‘์—…: ์ตœ๊ทผ ์ผ์–ด๋‚œ ์‚ฌ๊ฑด์— ๋Œ€ํ•œ ๋ณด๋„์ž๋ฃŒ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ž๋ฃŒ๋Š” ์‚ฌ์‹ค์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฉฐ, ๊ฐ๊ด€์ ์ด๊ณ  ์ •ํ™•ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
940
  ์ง€์นจ:
@@ -943,52 +976,139 @@ elif menu == "์ƒˆ ๊ธฐ์‚ฌ ์ƒ์„ฑํ•˜๊ธฐ":
943
  ๊ธฐ์‚ฌ ๋‚ด์šฉ์€ ์ •ํ™•ํ•˜๊ณ  ๊ฐ„๊ฒฐํ•˜๋ฉฐ ์„ค๋“๋ ฅ ์žˆ๋Š” ๋ฌธ์žฅ์œผ๋กœ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.
944
  ๊ด€๋ จ์ž์˜ ์ธํ„ฐ๋ทฐ๋ฅผ ์ธ์šฉ ํ˜•ํƒœ๋กœ ๋„ฃ์–ด์ฃผ์„ธ์š”.
945
  ์œ„์˜ ์ •๋ณด์™€ ์ง€์นจ์„ ์ฐธ๊ณ ํ•˜์—ฌ ์‹ ๋ฌธ ๋ณด๋„์ž๋ฃŒ ํ˜•์‹์˜ ๊ธฐ์‚ฌ๋ฅผ ์ž‘์„ฑํ•ด ์ฃผ์„ธ์š”"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
946
 
947
- # ์ด๋ฏธ์ง€ ์ƒ์„ฑ ์—ฌ๋ถ€ ์„ ํƒ ์˜ต์…˜ ์ถ”๊ฐ€
948
- generate_image_too = st.checkbox("๊ธฐ์‚ฌ ์ƒ์„ฑ ํ›„ ์ด๋ฏธ์ง€๋„ ํ•จ๊ป˜ ์ƒ์„ฑํ•˜๊ธฐ", value=True)
 
949
 
950
- if st.button("์ƒˆ ๊ธฐ์‚ฌ ์ƒ์„ฑํ•˜๊ธฐ"):
951
- if st.session_state.openai_client:
952
- with st.spinner("๊ธฐ์‚ฌ๋ฅผ ์ƒ์„ฑ ์ค‘์ž…๋‹ˆ๋‹ค..."):
953
- new_article = generate_article(selected_article['content'], prompt_text)
954
-
955
- st.write("**์ƒ์„ฑ๋œ ๊ธฐ์‚ฌ:**")
956
- st.write(new_article)
957
-
958
- # ์ด๋ฏธ์ง€ ์ƒ์„ฑํ•˜๊ธฐ (์˜ต์…˜์ด ์„ ํƒ๋œ ๊ฒฝ์šฐ)
959
- if generate_image_too:
960
- with st.spinner("๊ธฐ์‚ฌ ๊ด€๋ จ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑ ์ค‘์ž…๋‹ˆ๋‹ค..."):
961
- image_prompt = f"""์‹ ๋ฌธ๊ธฐ์‚ฌ ์ œ๋ชฉ "{selected_article['title']}" ์„ ๋ณด๊ณ  ์ด๋ฏธ์ง€๋ฅผ ๋งŒ๋“ค์–ด์ค˜
962
- ์ด๋ฏธ์ง€์—๋Š” ๋‹ค์Œ ์š”์†Œ๊ฐ€ ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค:
963
- - ๊ธฐ์‚ฌ๋ฅผ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ๋„์‹
964
- - ๊ธฐ์‚ฌ ๋‚ด์šฉ๊ณผ ๊ด€๋ จ๋œ ํ…์ŠคํŠธ
965
- - ์‹ฌํ”Œํ•˜๊ฒŒ ์ฒ˜๋ฆฌ
966
- """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
967
 
968
- # ์ด๋ฏธ์ง€ ์ƒ์„ฑ
969
- image = generate_image(image_prompt)
970
 
971
- if isinstance(image, BytesIO):
972
- st.subheader("์ƒ์„ฑ๋œ ์ด๋ฏธ์ง€:")
973
- st.image(image, use_column_width=True)
974
- else:
975
- st.error(image)
976
-
977
- # ์ƒ์„ฑ๋œ ๊ธฐ์‚ฌ ์ €์žฅ ์˜ต์…˜
978
- if st.button("์ƒ์„ฑ๋œ ๊ธฐ์‚ฌ ๏ฟฝ๏ฟฝ๏ฟฝ์žฅ"):
979
- new_article_data = {
980
- 'title': f"[์ƒ์„ฑ๋จ] {selected_article['title']}",
981
- 'source': f"AI ์ƒ์„ฑ (์›๋ณธ: {selected_article['source']})",
982
- 'date': datetime.now().strftime("%Y-%m-%d %H:%M"),
983
- 'description': new_article[:100] + "...",
984
- 'link': "",
985
- 'content': new_article
986
- }
987
- articles.append(new_article_data)
988
- save_articles(articles)
989
- st.success("์ƒ์„ฑ๋œ ๊ธฐ์‚ฌ๊ฐ€ ์ €์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!")
990
- else:
991
- st.warning("OpenAI API ํ‚ค๋ฅผ ์‚ฌ์ด๋“œ๋ฐ”์—์„œ ์„ค์ •ํ•ด์ฃผ์„ธ์š”.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
992
 
993
  elif menu == "๋‰ด์Šค ๊ธฐ์‚ฌ ์˜ˆ์•ฝํ•˜๊ธฐ":
994
  st.header("๋‰ด์Šค ๊ธฐ์‚ฌ ์˜ˆ์•ฝํ•˜๊ธฐ")
 
318
  st.warning("์›Œ๋“œํด๋ผ์šฐ๋“œ ์„ค์น˜์•ˆ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.")
319
  return None
320
  try:
321
+ # ๊ธฐ๋ณธ WordCloud ๊ฐ์ฒด (ํฐํŠธ ๊ฒฝ๋กœ ์—†์ด)
322
+ wc = WordCloud(
323
  width=800,
324
  height=400,
325
+ background_color='white',
326
+ colormap='viridis',
327
  max_font_size=150,
328
  random_state=42
329
+ )
330
 
331
  try:
332
  import os
333
+ script_dir = os.path.dirname(os.path.abspath(__file__))
334
+ # ์‚ฌ์šฉ์ž๊ฐ€ ๋ฃจํŠธ์— ๋„ฃ์€ ํฐํŠธ ํŒŒ์ผ ์ด๋ฆ„์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
335
+ # ๋งŒ์•ฝ ๋‹ค๋ฅธ ์ด๋ฆ„์˜ ํฐํŠธ๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค๋ฉด ์ด ๋ถ€๋ถ„์„ ์ˆ˜์ •ํ•ด์ฃผ์„ธ์š”. (์˜ˆ: "YourFontName.ttf")
336
+ possible_font_paths = ["NanumGothic.ttf"]
337
 
338
  font_path = None
339
+ for path_segment in possible_font_paths:
340
+ candidate = os.path.join(script_dir, path_segment)
341
  if os.path.exists(candidate):
342
  font_path = candidate
343
  break
344
+
345
+ # font_path๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์ฐพ์•„์ง„ ๊ฒฝ์šฐ์—๋งŒ ํฐํŠธ ๊ฒฝ๋กœ๋ฅผ ํฌํ•จํ•˜์—ฌ WordCloud ์žฌ์ƒ์„ฑ
346
  if font_path:
347
+ wc = WordCloud(
348
  font_path=font_path,
349
  width=800,
350
  height=400,
351
+ background_color='white',
352
+ colormap='viridis',
353
  max_font_size=150,
354
  random_state=42
355
  ).generate_from_frequencies(keywords_dict)
356
+ else:
357
+ st.warning(f"์ง€์ •๋œ ํ•œ๊ตญ์–ด ๊ธ€๊ผด ํŒŒ์ผ({', '.join(possible_font_paths)})์„ ์Šคํฌ๋ฆฝํŠธ ๋””๋ ‰ํ„ฐ๋ฆฌ์—์„œ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์›Œ๋“œํด๋ผ์šฐ๋“œ๊ฐ€ ๊นจ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.")
358
 
359
+ except Exception as e:
360
+ print(f"๊ธ€๊ผด ๋กœ๋”ฉ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}")
361
+ st.warning(f"๊ธ€๊ผด ๋กœ๋”ฉ ์ค‘ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {str(e)}") # ์‚ฌ์šฉ์ž์—๊ฒŒ๋„ ๊ฒฝ๊ณ  ํ‘œ์‹œ
362
+
363
+ # ์ตœ์ข…์ ์œผ๋กœ wc ๊ฐ์ฒด ๋ฐ˜ํ™˜ (ํฐํŠธ๊ฐ€ ์ ์šฉ๋˜์—ˆ๊ฑฐ๋‚˜, ๊ธฐ๋ณธ ๊ฐ์ฒด์ด๊ฑฐ๋‚˜)
364
+ return wc.generate_from_frequencies(keywords_dict) if isinstance(wc, WordCloud) else None
365
 
366
  except Exception as e:
367
+ st.error(f"์›Œ๋“œํด๋ผ์šฐ๋“œ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜๋ฐœ์ƒ: {str(e)}")
368
  return None
369
 
370
  # ๋‰ด์Šค ๋ถ„์„ ํ•จ์ˆ˜
 
398
  return "OpenAI API ํ‚ค๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค."
399
 
400
  response = st.session_state.openai_client.chat.completions.create(
401
+ model="gpt-4.1-nano", # ๋˜๋Š” ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ ์ ˆํ•œ ๋ชจ๋ธ
402
  messages=[
403
  {"role": "system", "content": "๋‹น์‹ ์€ ์ „๋ฌธ์ ์ธ ๋‰ด์Šค ๊ธฐ์ž์ž…๋‹ˆ๋‹ค. ์ฃผ์–ด์ง„ ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ ์ƒˆ๋กœ์šด ๊ธฐ์‚ฌ๋ฅผ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”."},
404
  {"role": "user", "content": f"๋‹ค์Œ ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ {prompt_text}\n\n{original_content[:1000]}"}
 
409
  except Exception as e:
410
  return f"๊ธฐ์‚ฌ ์ƒ์„ฑ ์˜ค๋ฅ˜: {str(e)}"
411
 
412
+ # ์—ฌ๋Ÿฌ ์ œ๋ชฉ์œผ๋กœ๋ถ€ํ„ฐ ๊ธฐ์‚ฌ ์ƒ์„ฑํ•˜๋Š” ํ•จ์ˆ˜ ์ถ”๊ฐ€
413
+ def generate_article_from_titles(titles, prompt_text):
414
+ try:
415
+ if not st.session_state.openai_client:
416
+ return "OpenAI API ํ‚ค๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค."
417
+
418
+ titles_text = "\n".join([f"- {title}" for title in titles])
419
+
420
+ response = st.session_state.openai_client.chat.completions.create(
421
+ model="gpt-4.1-nano", # ๋˜๋Š” ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ ์ ˆํ•œ ๋ชจ๋ธ
422
+ messages=[
423
+ {"role": "system", "content": "๋‹น์‹ ์€ ์ „๋ฌธ์ ์ธ ๋‰ด์Šค ๊ธฐ์ž์ž…๋‹ˆ๋‹ค. ์ฃผ์–ด์ง„ ์—ฌ๋Ÿฌ ๋‰ด์Šค ์ œ๋ชฉ์„ ๋ฐ”ํƒ•์œผ๋กœ ์ƒˆ๋กœ์šด ํ†ตํ•ฉ ๊ธฐ์‚ฌ๋ฅผ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”."},
424
+ {"role": "user", "content": f"๋‹ค์Œ ๋‰ด์Šค ์ œ๋ชฉ๋“ค์„ ๋ฐ”ํƒ•์œผ๋กœ {prompt_text}\n\n{titles_text}"}
425
+ ],
426
+ max_tokens=2000
427
+ )
428
+ return response.choices[0].message.content
429
+ except Exception as e:
430
+ return f"๊ธฐ์‚ฌ ์ƒ์„ฑ ์˜ค๋ฅ˜: {str(e)}"
431
+
432
  # OpenAI API๋ฅผ ์ด์šฉํ•œ ์ด๋ฏธ์ง€ ์ƒ์„ฑ (์ƒˆ๋กœ์šด ๋ฒ„์ „ ๋ฐฉ์‹)
433
  def generate_image(prompt):
434
  try:
 
951
  if not articles:
952
  st.warning("์ €์žฅ๋œ ๊ธฐ์‚ฌ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋จผ์ € '๋‰ด์Šค ๊ธฐ์‚ฌ ํฌ๋กค๋ง' ๋ฉ”๋‰ด์—์„œ ๊ธฐ์‚ฌ๋ฅผ ์ˆ˜์ง‘ํ•ด์ฃผ์„ธ์š”.")
953
  else:
954
+ # ํƒญ ์ถ”๊ฐ€: ๋‹จ์ผ ๊ธฐ์‚ฌ๋กœ ์ƒ์„ฑ vs ๋‹ค์ค‘ ์ œ๋ชฉ์œผ๋กœ ์ƒ์„ฑ
955
+ tab1, tab2 = st.tabs(["๋‹จ์ผ ๊ธฐ์‚ฌ๋กœ ์ƒ์„ฑ", "์—ฌ๋Ÿฌ ์ œ๋ชฉ์œผ๋กœ ์ƒ์„ฑ"])
 
956
 
957
+ with tab1:
958
+ # ๊ธฐ์กด ์ฝ”๋“œ: ๋‹จ์ผ ๊ธฐ์‚ฌ ์„ ํƒ
959
+ titles = [article['title'] for article in articles]
960
+ selected_title = st.selectbox("์›๋ณธ ๊ธฐ์‚ฌ ์„ ํƒ", titles, key="single_article")
961
 
962
+ selected_article = next((a for a in articles if a['title'] == selected_title), None)
 
963
 
964
+ if selected_article:
965
+ st.write(f"**์›๋ณธ ์ œ๋ชฉ:** {selected_article['title']}")
966
+
967
+ with st.expander("์›๋ณธ ๊ธฐ์‚ฌ ๋‚ด์šฉ"):
968
+ st.write(selected_article['content'])
969
+
970
+ prompt_text ="""๋‹ค์Œ ๊ธฐ์‚ฌ ์–‘์‹์„ ๋”ฐ๋ผ์„œ ๋‹ค์‹œ ์ž‘์„ฑํ•ด์ค˜.
971
  ์—ญํ• : ๋‹น์‹ ์€ ์‹ ๋ฌธ์‚ฌ์˜ ๊ธฐ์ž์ž…๋‹ˆ๋‹ค.
972
  ์ž‘์—…: ์ตœ๊ทผ ์ผ์–ด๋‚œ ์‚ฌ๊ฑด์— ๋Œ€ํ•œ ๋ณด๋„์ž๋ฃŒ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ž๋ฃŒ๋Š” ์‚ฌ์‹ค์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฉฐ, ๊ฐ๊ด€์ ์ด๊ณ  ์ •ํ™•ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
973
  ์ง€์นจ:
 
976
  ๊ธฐ์‚ฌ ๋‚ด์šฉ์€ ์ •ํ™•ํ•˜๊ณ  ๊ฐ„๊ฒฐํ•˜๋ฉฐ ์„ค๋“๋ ฅ ์žˆ๋Š” ๋ฌธ์žฅ์œผ๋กœ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.
977
  ๊ด€๋ จ์ž์˜ ์ธํ„ฐ๋ทฐ๋ฅผ ์ธ์šฉ ํ˜•ํƒœ๋กœ ๋„ฃ์–ด์ฃผ์„ธ์š”.
978
  ์œ„์˜ ์ •๋ณด์™€ ์ง€์นจ์„ ์ฐธ๊ณ ํ•˜์—ฌ ์‹ ๋ฌธ ๋ณด๋„์ž๋ฃŒ ํ˜•์‹์˜ ๊ธฐ์‚ฌ๋ฅผ ์ž‘์„ฑํ•ด ์ฃผ์„ธ์š”"""
979
+
980
+ # ์ด๋ฏธ์ง€ ์ƒ์„ฑ ์—ฌ๋ถ€ ์„ ํƒ ์˜ต์…˜ ์ถ”๊ฐ€
981
+ generate_image_too = st.checkbox("๊ธฐ์‚ฌ ์ƒ์„ฑ ํ›„ ์ด๋ฏธ์ง€๋„ ํ•จ๊ป˜ ์ƒ์„ฑํ•˜๊ธฐ", value=True, key="single_image")
982
+
983
+ if st.button("์ƒˆ ๊ธฐ์‚ฌ ์ƒ์„ฑํ•˜๊ธฐ", key="generate_single"):
984
+ if st.session_state.openai_client:
985
+ with st.spinner("๊ธฐ์‚ฌ๋ฅผ ์ƒ์„ฑ ์ค‘์ž…๋‹ˆ๋‹ค..."):
986
+ new_article = generate_article(selected_article['content'], prompt_text)
987
+
988
+ st.write("**์ƒ์„ฑ๋œ ๊ธฐ์‚ฌ:**")
989
+ st.write(new_article)
990
+
991
+ # ์ด๋ฏธ์ง€ ์ƒ์„ฑํ•˜๊ธฐ (์˜ต์…˜์ด ์„ ํƒ๋œ ๊ฒฝ์šฐ)
992
+ if generate_image_too:
993
+ with st.spinner("๊ธฐ์‚ฌ ๊ด€๋ จ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑ ์ค‘์ž…๋‹ˆ๋‹ค..."):
994
+ image_prompt = f"""์‹ ๋ฌธ๊ธฐ์‚ฌ ์ œ๋ชฉ "{selected_article['title']}" ์„ ๋ณด๊ณ  ์ด๋ฏธ์ง€๋ฅผ ๋งŒ๋“ค์–ด์ค˜
995
+ ์ด๋ฏธ์ง€์—๋Š” ๋‹ค์Œ ์š”์†Œ๊ฐ€ ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค:
996
+ - ๊ธฐ์‚ฌ๋ฅผ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ๋„์‹
997
+ - ๊ธฐ์‚ฌ ๋‚ด์šฉ๊ณผ ๊ด€๋ จ๋œ ํ…์ŠคํŠธ
998
+ - ์‹ฌํ”Œํ•˜๊ฒŒ ์ฒ˜๋ฆฌ
999
+ """
1000
+
1001
+ # ์ด๋ฏธ์ง€ ์ƒ์„ฑ
1002
+ image = generate_image(image_prompt)
1003
+
1004
+ if isinstance(image, BytesIO):
1005
+ st.subheader("์ƒ์„ฑ๋œ ์ด๋ฏธ์ง€:")
1006
+ st.image(image, use_column_width=True)
1007
+ else:
1008
+ st.error(image)
1009
+
1010
+ # ์ƒ์„ฑ๋œ ๊ธฐ์‚ฌ ์ €์žฅ ์˜ต์…˜
1011
+ if st.button("์ƒ์„ฑ๋œ ๊ธฐ์‚ฌ ์ €์žฅ", key="save_single"):
1012
+ new_article_data = {
1013
+ 'title': f"[์ƒ์„ฑ๋จ] {selected_article['title']}",
1014
+ 'source': f"AI ์ƒ์„ฑ (์›๋ณธ: {selected_article['source']})",
1015
+ 'date': datetime.now().strftime("%Y-%m-%d %H:%M"),
1016
+ 'description': new_article[:100] + "...",
1017
+ 'link': "",
1018
+ 'content': new_article
1019
+ }
1020
+ articles.append(new_article_data)
1021
+ save_articles(articles)
1022
+ st.success("์ƒ์„ฑ๋œ ๊ธฐ์‚ฌ๊ฐ€ ์ €์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!")
1023
+ else:
1024
+ st.warning("OpenAI API ํ‚ค๋ฅผ ์‚ฌ์ด๋“œ๋ฐ”์—์„œ ์„ค์ •ํ•ด์ฃผ์„ธ์š”.")
1025
+
1026
+ with tab2:
1027
+ # ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ: ์—ฌ๋Ÿฌ ์ œ๋ชฉ์œผ๋กœ ๊ธฐ์‚ฌ ์ƒ์„ฑ
1028
+ st.subheader("์—ฌ๋Ÿฌ ์ œ๋ชฉ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋‚˜์˜ ๊ธฐ์‚ฌ ์ƒ์„ฑํ•˜๊ธฐ")
1029
 
1030
+ # ๋‹ค์ค‘ ์„ ํƒ ์œ„์ ฏ์œผ๋กœ ์—ฌ๋Ÿฌ ์ œ๋ชฉ ์„ ํƒ ๊ฐ€๋Šฅ
1031
+ titles = [article['title'] for article in articles]
1032
+ selected_titles = st.multiselect("์—ฌ๋Ÿฌ ๊ธฐ์‚ฌ ์ œ๋ชฉ ์„ ํƒ (2๊ฐœ ์ด์ƒ ๊ถŒ์žฅ)", titles)
1033
 
1034
+ if selected_titles:
1035
+ st.write(f"**์„ ํƒ๋œ ์ œ๋ชฉ ์ˆ˜:** {len(selected_titles)}๊ฐœ")
1036
+
1037
+ with st.expander("์„ ํƒ๋œ ์ œ๋ชฉ ๋ชฉ๋ก"):
1038
+ for i, title in enumerate(selected_titles):
1039
+ st.write(f"{i+1}. {title}")
1040
+
1041
+ multi_prompt_text = """๋‹ค์Œ ๋‰ด์Šค ์ œ๋ชฉ๋“ค์„ ์ข…ํ•ฉํ•˜์—ฌ ํ•˜๋‚˜์˜ ํ†ตํ•ฉ๋œ ๊ธฐ์‚ฌ๋กœ ์ž‘์„ฑํ•ด์ค˜.
1042
+ ์—ญํ• : ๋‹น์‹ ์€ ์‹ ๋ฌธ์‚ฌ์˜ ๊ธฐ์ž์ž…๋‹ˆ๋‹ค.
1043
+ ์ž‘์—…: ์—ฌ๋Ÿฌ ๋‰ด์Šค ์ œ๋ชฉ์—์„œ ๊ณตํ†ต ์ฃผ์ œ๋ฅผ ํŒŒ์•…ํ•˜๊ณ , ์ด๋ฅผ ์ข…ํ•ฉํ•œ ๋ณด๋„์ž๋ฃŒ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
1044
+ ์ง€์นจ:
1045
+ - ์ œ๊ณต๋œ ์—ฌ๋Ÿฌ ์ œ๋ชฉ์„ ์ข…ํ•ฉ์ ์œผ๋กœ ๋ถ„์„ํ•˜์—ฌ ํ•˜๋‚˜์˜ ์ผ๊ด€๋œ ๊ธฐ์‚ฌ๋ฅผ ์ž‘์„ฑํ•˜์„ธ์š”.
1046
+ - ๊ธฐ์‚ฌ ์ œ๋ชฉ์€ ์ œ๊ณต๋œ ๋ชจ๋“  ์ œ๋ชฉ์˜ ํ•ต์‹ฌ ์ฃผ์ œ๋ฅผ ๋‹ด์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.
1047
+ - ๊ธฐ์‚ฌ ๋‚ด์šฉ์€ ์ œ๋ชฉ๋“ค์ด ๋‹ค๋ฃจ๋Š” ๋ชจ๋“  ์ฃผ์š” ์ฃผ์ œ๋ฅผ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
1048
+ - ๊ด€๋ จ์ž์˜ ๊ฐ€์ƒ ์ธํ„ฐ๋ทฐ๋ฅผ ์ธ์šฉ ํ˜•ํƒœ๋กœ ๋„ฃ์–ด์ฃผ์„ธ์š”.
1049
+ - ์ œ๊ณต๋œ ์ œ๋ชฉ๋“ค์˜ ๋งฅ๋ฝ์„ ์œ ์ง€ํ•˜๋ฉด์„œ ์ผ๊ด€์„ฑ ์žˆ๋Š” ๋‚ด๋Ÿฌํ‹ฐ๋ธŒ๋ฅผ ๊ตฌ์„ฑํ•˜์„ธ์š”."""
1050
+
1051
+ # ํ”„๋กฌํ”„ํŠธ ํŽธ์ง‘ ์˜ต์…˜
1052
+ custom_prompt = st.checkbox("์ง์ ‘ ํ”„๋กฌํ”„ํŠธ ์ž‘์„ฑํ•˜๊ธฐ")
1053
+ if custom_prompt:
1054
+ multi_prompt_text = st.text_area("ํ”„๋กฌํ”„ํŠธ ์ง์ ‘ ์ž…๋ ฅ", multi_prompt_text, height=250)
1055
+
1056
+ # ์ด๋ฏธ์ง€ ์ƒ์„ฑ ์˜ต์…˜
1057
+ generate_multi_image = st.checkbox("๊ธฐ์‚ฌ ์ƒ์„ฑ ํ›„ ์ด๋ฏธ์ง€๋„ ํ•จ๊ป˜ ์ƒ์„ฑํ•˜๊ธฐ", value=True, key="multi_image")
1058
+
1059
+ if st.button("์ƒˆ ๊ธฐ์‚ฌ ์ƒ์„ฑํ•˜๊ธฐ", key="generate_multi"):
1060
+ if st.session_state.openai_client:
1061
+ if len(selected_titles) < 1:
1062
+ st.error("์ตœ์†Œ 1๊ฐœ ์ด์ƒ์˜ ์ œ๋ชฉ์„ ์„ ํƒํ•ด์ฃผ์„ธ์š”.")
1063
+ else:
1064
+ with st.spinner("์—ฌ๋Ÿฌ ์ œ๋ชฉ์œผ๋กœ๋ถ€ํ„ฐ ๊ธฐ์‚ฌ๋ฅผ ์ƒ์„ฑ ์ค‘์ž…๋‹ˆ๋‹ค..."):
1065
+ # ์„ ํƒ๋œ ์ œ๋ชฉ๋“ค์„ ์ด์šฉํ•˜์—ฌ ์ƒˆ ๊ธฐ์‚ฌ ์ƒ์„ฑ
1066
+ new_article = generate_article_from_titles(selected_titles, multi_prompt_text)
1067
 
1068
+ st.write("**์ƒ์„ฑ๋œ ๊ธฐ์‚ฌ:**")
1069
+ st.write(new_article)
1070
 
1071
+ # ์ด๋ฏธ์ง€ ์ƒ์„ฑ (์˜ต์…˜์ด ์„ ํƒ๋œ ๊ฒฝ์šฐ)
1072
+ if generate_multi_image:
1073
+ with st.spinner("๊ธฐ์‚ฌ ๊ด€๋ จ ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑ ์ค‘์ž…๋‹ˆ๋‹ค..."):
1074
+ combined_titles = " / ".join(selected_titles[:3]) # ์ฒ˜์Œ 3๊ฐœ ์ œ๋ชฉ๋งŒ ์‚ฌ์šฉ
1075
+ image_prompt = f"""์—ฌ๋Ÿฌ ๋‰ด์Šค๋ฅผ ์ข…ํ•ฉํ•œ ๊ธฐ์‚ฌ "{combined_titles}" ๊ด€๋ จ ์ด๋ฏธ์ง€๋ฅผ ๋งŒ๋“ค์–ด์ค˜.
1076
+ ์ด๋ฏธ์ง€์—๋Š” ๋‹ค์Œ ์š”์†Œ๊ฐ€ ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค:
1077
+ - ์—ฌ๋Ÿฌ ๋‰ด์Šค์˜ ๊ณตํ†ต ์ฃผ์ œ๋ฅผ ์‹œ๊ฐํ™”ํ•œ ๋„์‹
1078
+ - ํ•ต์‹ฌ ํ‚ค์›Œ๋“œ๋‚˜ ๊ฐœ๋…
1079
+ - ์‹ฌํ”Œํ•˜๊ณ  ํ†ตํ•ฉ๋œ ๋””์ž์ธ
1080
+ """
1081
+
1082
+ # ์ด๋ฏธ์ง€ ์ƒ์„ฑ
1083
+ image = generate_image(image_prompt)
1084
+
1085
+ if isinstance(image, BytesIO):
1086
+ st.subheader("์ƒ์„ฑ๋œ ์ด๋ฏธ์ง€:")
1087
+ st.image(image, use_column_width=True)
1088
+ else:
1089
+ st.error(image)
1090
+
1091
+ # ์ƒ์„ฑ๋œ ๊ธฐ์‚ฌ ์ €์žฅ ์˜ต์…˜
1092
+ if st.button("์ƒ์„ฑ๋œ ๊ธฐ์‚ฌ ์ €์žฅ", key="save_multi"):
1093
+ # ํ†ตํ•ฉ ์ œ๋ชฉ ์ƒ์„ฑ (์ฒซ ๋ฒˆ์งธ ์ œ๋ชฉ + ์ถ”๊ฐ€ ์ œ๋ชฉ ์ˆ˜)
1094
+ if len(selected_titles) > 1:
1095
+ combined_title = f"{selected_titles[0]} ์™ธ {len(selected_titles)-1}๊ฑด ๊ด€๋ จ ์†Œ์‹"
1096
+ else:
1097
+ combined_title = selected_titles[0]
1098
+
1099
+ new_article_data = {
1100
+ 'title': f"[์—ฌ๋Ÿฌ ์ œ๋ชฉ ํ†ตํ•ฉ] {combined_title}",
1101
+ 'source': "AI ์ƒ์„ฑ (์—ฌ๋Ÿฌ ์ œ๋ชฉ ํ†ตํ•ฉ)",
1102
+ 'date': datetime.now().strftime("%Y-%m-%d %H:%M"),
1103
+ 'description': new_article[:100] + "...",
1104
+ 'link': "",
1105
+ 'content': new_article
1106
+ }
1107
+ articles.append(new_article_data)
1108
+ save_articles(articles)
1109
+ st.success("์ƒ์„ฑ๋œ ๊ธฐ์‚ฌ๊ฐ€ ์ €์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!")
1110
+ else:
1111
+ st.warning("OpenAI API ํ‚ค๋ฅผ ์‚ฌ์ด๋“œ๋ฐ”์—์„œ ์„ค์ •ํ•ด์ฃผ์„ธ์š”.")
1112
 
1113
  elif menu == "๋‰ด์Šค ๊ธฐ์‚ฌ ์˜ˆ์•ฝํ•˜๊ธฐ":
1114
  st.header("๋‰ด์Šค ๊ธฐ์‚ฌ ์˜ˆ์•ฝํ•˜๊ธฐ")