fitz87 commited on
Commit
a5bd76c
·
verified ·
1 Parent(s): 4e2c7e1

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +164 -53
src/streamlit_app.py CHANGED
@@ -398,7 +398,7 @@ def generate_article(original_content, prompt_text):
398
  return "OpenAI API 키가 설정되지 않았습니다."
399
 
400
  response = st.session_state.openai_client.chat.completions.create(
401
- model="gpt-4", # 또는 사용 가능한 적절한 모델
402
  messages=[
403
  {"role": "system", "content": "당신은 전문적인 뉴스 기자입니다. 주어진 내용을 바탕으로 새로운 기사를 작성해주세요."},
404
  {"role": "user", "content": f"다음 내용을 바탕으로 {prompt_text}\n\n{original_content[:1000]}"}
@@ -409,6 +409,26 @@ def generate_article(original_content, prompt_text):
409
  except Exception as e:
410
  return f"기사 생성 오류: {str(e)}"
411
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
412
  # OpenAI API를 이용한 이미지 생성 (새로운 버전 방식)
413
  def generate_image(prompt):
414
  try:
@@ -931,19 +951,23 @@ elif menu == "새 기사 생성하기":
931
  if not articles:
932
  st.warning("저장된 기사가 없습니다. 먼저 '뉴스 기사 크롤링' 메뉴에서 기사를 수집해주세요.")
933
  else:
934
- # 기사 선택
935
- titles = [article['title'] for article in articles]
936
- selected_title = st.selectbox("원본 기사 선택", titles)
937
 
938
- selected_article = next((a for a in articles if a['title'] == selected_title), None)
939
-
940
- if selected_article:
941
- st.write(f"**원본 제목:** {selected_article['title']}")
942
 
943
- with st.expander("원본 기사 내용"):
944
- st.write(selected_article['content'])
945
 
946
- prompt_text ="""다음 기사 양식을 따라서 다시 작성해줘.
 
 
 
 
 
 
947
  역할: 당신은 신문사의 기자입니다.
948
  작업: 최근 일어난 사건에 대한 보도자료를 작성해야 합니다. 자료는 사실을 기반으로 하며, 객관적이고 정확해야 합니다.
949
  지침:
@@ -952,52 +976,139 @@ elif menu == "새 기사 생성하기":
952
  기사 내용은 정확하고 간결하며 설득력 있는 문장으로 구성합니다.
953
  관련자의 인터뷰를 인용 형태로 넣어주세요.
954
  위의 정보와 지침을 참고하여 신문 보도자료 형식의 기사를 작성해 주세요"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
955
 
956
- # 이미지 생성 여부 선택 옵션 추가
957
- generate_image_too = st.checkbox("기사 생성 이미지도 함께 생성하기", value=True)
 
958
 
959
- if st.button("새 기사 생성하기"):
960
- if st.session_state.openai_client:
961
- with st.spinner("기사를 생성 중입니다..."):
962
- new_article = generate_article(selected_article['content'], prompt_text)
963
-
964
- st.write("**생성된 기사:**")
965
- st.write(new_article)
966
-
967
- # 이미지 생성하기 (옵션이 선택된 경우)
968
- if generate_image_too:
969
- with st.spinner("기사 관련 이미지를 생성 중입니다..."):
970
- image_prompt = f"""신문기사 제목 "{selected_article['title']}" 보고 이미지를 만들어줘
971
- 이미지에는 다음 요소가 포함되어야 합니다:
972
- - 기사를 이해할 있는 도식
973
- - 기사 내용과 관련된 텍스트
974
- - 심플하게 처리
975
- """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
976
 
977
- # 이미지 생성
978
- image = generate_image(image_prompt)
979
 
980
- if isinstance(image, BytesIO):
981
- st.subheader("생성된 이미지:")
982
- st.image(image, use_column_width=True)
983
- else:
984
- st.error(image)
985
-
986
- # 생성된 기사 저장 옵션
987
- if st.button("생성된 기사 저장"):
988
- new_article_data = {
989
- 'title': f"[생성됨] {selected_article['title']}",
990
- 'source': f"AI 생성 (원본: {selected_article['source']})",
991
- 'date': datetime.now().strftime("%Y-%m-%d %H:%M"),
992
- 'description': new_article[:100] + "...",
993
- 'link': "",
994
- 'content': new_article
995
- }
996
- articles.append(new_article_data)
997
- save_articles(articles)
998
- st.success("생성된 기사가 저장되었습니다!")
999
- else:
1000
- st.warning("OpenAI API 키를 사이드바에서 설정해주세요.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1001
 
1002
  elif menu == "뉴스 기사 예약하기":
1003
  st.header("뉴스 기사 예약하기")
 
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("뉴스 기사 예약하기")