ginipick commited on
Commit
eb59db6
Β·
verified Β·
1 Parent(s): a21561f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +95 -113
app.py CHANGED
@@ -775,48 +775,47 @@ def process_example(topic):
775
 
776
  def process_input(prompt: str, uploaded_files):
777
  # Add user's message
778
- if not any(m["role"] == "user" and m["content"] == prompt for m in st.session_state.messages):
 
779
  st.session_state.messages.append({"role": "user", "content": prompt})
780
 
781
  with st.chat_message("user"):
782
  st.markdown(prompt)
783
-
784
  with st.chat_message("assistant"):
785
  placeholder = st.empty()
786
  message_placeholder = st.empty()
787
  full_response = ""
788
 
789
- use_web_search = st.session_state.web_search_enabled
790
- has_uploaded_files = bool(uploaded_files) and len(uploaded_files) > 0
791
-
792
  try:
793
- status = st.status("Preparing to generate ideas...")
794
- status.update(label="Initializing client...")
795
 
796
  client = get_openai_client()
797
-
798
- # Prepare system prompt
799
 
 
800
  selected_cat = st.session_state.get("category_focus", "(None)")
801
  if selected_cat == "(None)":
802
  selected_cat = None
803
-
804
  sys_prompt = get_idea_system_prompt(selected_category=selected_cat)
805
- # Optional: gather search results
 
806
  search_content = None
807
  if use_web_search:
808
- status.update(label="Performing web search...")
809
- with st.spinner("Searching the web..."):
810
  search_content = do_web_search(keywords(prompt, top=5))
811
 
812
- # File contents
813
  file_content = None
814
- if has_uploaded_files:
815
- status.update(label="Processing uploaded files...")
816
- with st.spinner("Analyzing files..."):
817
  file_content = process_uploaded_files(uploaded_files)
818
 
819
- # Build messages
820
  user_content = prompt
821
  if search_content:
822
  user_content += "\n\n" + search_content
@@ -825,108 +824,91 @@ def process_input(prompt: str, uploaded_files):
825
 
826
  api_messages = [
827
  {"role": "system", "content": sys_prompt},
828
- {"role": "user", "content": user_content}
829
  ]
830
 
831
- # OpenAI API streaming
832
- status.update(label="Generating creative ideas...")
833
- try:
834
- stream = client.chat.completions.create(
835
- model="gpt-4.1-mini",
836
- messages=api_messages,
837
- temperature=1,
838
- max_tokens=MAX_TOKENS,
839
- top_p=1,
840
- stream=True
841
- )
842
- for chunk in stream:
843
- if (chunk.choices
844
- and len(chunk.choices) > 0
845
  and chunk.choices[0].delta.content is not None):
846
- content_delta = chunk.choices[0].delta.content
847
- full_response += content_delta
848
- message_placeholder.markdown(full_response + "β–Œ")
849
- message_placeholder.markdown(full_response)
850
- status.update(label="Ideas created!", state="complete")
851
-
852
- except Exception as api_error:
853
- error_message = str(api_error)
854
- logging.error(f"API error: {error_message}")
855
- status.update(label=f"Error: {error_message}", state="error")
856
- raise Exception(f"Idea generation error: {error_message}")
857
-
858
- # Store final text
859
- answer_entry_saved = False
860
-
861
- # μžλ™ 이미지 생성이 ν™œμ„±ν™”λ˜μ–΄ μžˆλ‹€λ©΄
862
  if st.session_state.generate_image and full_response:
863
- # 아이디어λ₯Ό 3개둜 κ΅¬λΆ„ν•˜κ³ , 각 μ•„μ΄λ””μ–΄λ§ˆλ‹€ 이미지 ν”„λ‘¬ν”„νŠΈλ₯Ό μΆ”μΆœ
864
- # κ°„λ‹¨ν•œ 방식: μ •κ·œμ‹μœΌλ‘œ `Image Prompt:` ν˜•νƒœλ₯Ό μ°ΎλŠ”λ‹€κ³  κ°€μ • (μ‹œμŠ€ν…œν”„λ‘¬ν”„νŠΈμ— μ§€μ‹œ)
865
- # ν˜Ήμ€ λ‹¨μˆœνžˆ ν•œ 번만 μΆ”μΆœ -> μ—¬κΈ°μ„œλŠ” 3개 아이디어 각각을 μ°ΎκΈ° μœ„ν•΄ λ‚˜λˆ λ³Έλ‹€.
866
- # 일단은 전체 λ‹΅λ³€μ—μ„œ "English prompt for generating an image" 뢀뢄을 μ°ΎλŠ”λ‹€.
867
-
868
- # 맀우 λ‹¨μˆœν•œ νŒŒμ‹± μ˜ˆμ‹œ (κ°œμ„  κ°€λŠ₯)
869
  idea_sections = re.split(r"(## Idea \d+:)", full_response)
870
- # idea_sectionsλŠ” ['', '## Idea 1:', ' ...', '## Idea 2:', ' ...', '## Idea 3:', ' ...'] ν˜•νƒœ
871
-
872
- # λ‹€μ‹œ λ¬Άμ–΄μ„œ [('## Idea 1:', idea_text), ('## Idea 2:', idea_text), ...] ν˜•νƒœλ‘œ
873
- pairs = []
874
- for i in range(1, len(idea_sections), 2):
875
- idea_title = idea_sections[i].strip()
876
- idea_body = idea_sections[i+1].strip() if i+1 < len(idea_sections) else ""
877
- pairs.append((idea_title, idea_body))
878
-
879
- # 각 μ•„μ΄λ””μ–΄λ§ˆλ‹€ 이미지 생성
880
- # 각 μ•„μ΄λ””μ–΄λ§ˆλ‹€ 이미지 생성 (!!! 전체 블둝 ꡐ체 !!!)
881
- for idx, (title, text_block) in enumerate(pairs, start=1):
882
- # β‘  ν‘œ(λ§ˆν¬λ‹€μš΄ ν…Œμ΄λΈ”) μ•ˆμ— λ“€μ–΄μžˆλŠ” ν˜•νƒœ ──> | **Image Prompt** | prompt |
883
  table_match = re.search(
884
- r"\|\s*\*\*Image\s+Prompt\*\*\s*\|\s*([^\n|]+)",
885
- text_block,
886
- flags=re.IGNORECASE,
887
- )
888
-
889
- # β‘‘ λ°±μ—… νŒ¨ν„΄: "Image Prompt: ..." λ˜λŠ” "Image Prompt - ..."
890
- if not table_match:
891
- table_match = re.search(
892
- r"(?i)Image\s+Prompt\s*[:|-]\s*([^\n]+)", text_block
893
- )
894
-
895
- if table_match:
896
- raw_prompt = table_match.group(1).strip()
897
- raw_prompt = re.sub(r"[\r\n\|`'\"\\]", " ", raw_prompt) # κ°œν–‰Β·κ΅¬λ‘μ  정리
898
-
899
- # 이미지 생성
900
- with st.spinner(f"Generating image for {title}..."):
901
- img, cap = generate_image(raw_prompt)
902
- if img:
903
- st.image(img, caption=f"{title} – {cap}")
904
- st.session_state.messages.append(
905
- {
906
- "role": "assistant",
907
- "content": "",
908
- "image": img,
909
- "image_caption": f"{title} – {cap}",
910
- }
911
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
912
 
913
-
914
- # λ§Œμ•½ λ¬Έμž₯ 끝에 λΆˆν•„μš”ν•œ κ΅¬λ‘μ μ΄λ‚˜ μ€„λ°”κΏˆμ΄ μžˆμ„ μ‹œ 제거
915
- raw_prompt = re.sub(r"[\r\n]+", " ", raw_prompt)
916
- raw_prompt = re.sub(r"[\"'`]", "", raw_prompt)
917
- # 이미지 생성
918
- with st.spinner(f"Generating image for {title}..."):
919
- img, cap = generate_image(raw_prompt)
920
- if img:
921
- st.image(img, caption=f"{title} - {cap}")
922
- # λŒ€ν™”μ— μ €μž₯
923
- st.session_state.messages.append({
924
- "role": "assistant",
925
- "content": "",
926
- "image": img,
927
- "image_caption": f"{title} - {cap}"
928
- })
929
-
930
  # 3개 이미지 생성 ν”„λ‘œμ„ΈμŠ€λ₯Ό 마친 ν›„ μ΅œμ’… ν…μŠ€νŠΈλ₯Ό μ €μž₯
931
  st.session_state.messages.append({"role": "assistant", "content": full_response})
932
  answer_entry_saved = True
 
775
 
776
  def process_input(prompt: str, uploaded_files):
777
  # Add user's message
778
+ if not any(m["role"] == "user" and m["content"] == prompt
779
+ for m in st.session_state.messages):
780
  st.session_state.messages.append({"role": "user", "content": prompt})
781
 
782
  with st.chat_message("user"):
783
  st.markdown(prompt)
784
+
785
  with st.chat_message("assistant"):
786
  placeholder = st.empty()
787
  message_placeholder = st.empty()
788
  full_response = ""
789
 
790
+ use_web_search = st.session_state.web_search_enabled
791
+ has_uploaded = bool(uploaded_files)
792
+
793
  try:
794
+ status = st.status("Preparing to generate ideas…")
795
+ status.update(label="Initializing model…")
796
 
797
  client = get_openai_client()
 
 
798
 
799
+ # ── β‘  μ‹œμŠ€ν…œ ν”„λ‘¬ν”„νŠΈ ──────────────────────────────
800
  selected_cat = st.session_state.get("category_focus", "(None)")
801
  if selected_cat == "(None)":
802
  selected_cat = None
 
803
  sys_prompt = get_idea_system_prompt(selected_category=selected_cat)
804
+
805
+ # ── β‘‘ (선택) μ›Ή 검색 & νŒŒμΌλ‚΄μš© ───────────────────
806
  search_content = None
807
  if use_web_search:
808
+ status.update(label="Searching the web…")
809
+ with st.spinner("Searching…"):
810
  search_content = do_web_search(keywords(prompt, top=5))
811
 
 
812
  file_content = None
813
+ if has_uploaded:
814
+ status.update(label="Reading uploaded files…")
815
+ with st.spinner("Processing files…"):
816
  file_content = process_uploaded_files(uploaded_files)
817
 
818
+ # ── β‘’ λŒ€ν™” λ©”μ‹œμ§€ ꡬ성 ─────────────────────────────
819
  user_content = prompt
820
  if search_content:
821
  user_content += "\n\n" + search_content
 
824
 
825
  api_messages = [
826
  {"role": "system", "content": sys_prompt},
827
+ {"role": "user", "content": user_content},
828
  ]
829
 
830
+ # ── β‘£ OpenAI 슀트리밍 호좜 ────────────────────────
831
+ status.update(label="Generating ideas…")
832
+ stream = client.chat.completions.create(
833
+ model = "gpt-4.1-mini",
834
+ messages = api_messages,
835
+ temperature = 1,
836
+ max_tokens = MAX_TOKENS,
837
+ top_p = 1,
838
+ stream = True
839
+ )
840
+ for chunk in stream:
841
+ if (chunk.choices
 
 
842
  and chunk.choices[0].delta.content is not None):
843
+ full_response += chunk.choices[0].delta.content
844
+ message_placeholder.markdown(full_response + "β–Œ")
845
+ message_placeholder.markdown(full_response)
846
+ status.update(label="Ideas created!", state="complete")
847
+
848
+ # ── β‘€ 이미지 생성 ────────────────────────────────
 
 
 
 
 
 
 
 
 
 
849
  if st.session_state.generate_image and full_response:
 
 
 
 
 
 
850
  idea_sections = re.split(r"(## Idea \d+:)", full_response)
851
+ pairs = [(idea_sections[i].strip(),
852
+ idea_sections[i+1].strip() if i+1 < len(idea_sections) else "")
853
+ for i in range(1, len(idea_sections), 2)]
854
+
855
+ for idx, (title, text_block) in enumerate(pairs, start=1):
856
+ # ν‘œ ν˜•νƒœ: | **Image Prompt** | prompt |
857
+ table_match = re.search(
858
+ r"\|\s*\*\*Image\s+Prompt\*\*\s*\|\s*([^\n\|]+)",
859
+ text_block, flags=re.IGNORECASE)
860
+ # λ°±μ—… ν˜•νƒœ: Image Prompt: …
861
+ if not table_match:
 
 
862
  table_match = re.search(
863
+ r"(?i)Image\s+Prompt\s*[:|-]\s*([^\n]+)", text_block)
864
+
865
+ if not table_match:
866
+ continue
867
+
868
+ raw_prompt = re.sub(r"[\r\n\|`'\"\\]", " ",
869
+ table_match.group(1).strip())
870
+
871
+ with st.spinner(f"Generating image for {title}…"):
872
+ img, cap = generate_image(raw_prompt)
873
+
874
+ if img:
875
+ st.image(img, caption=f"{title} – {cap}")
876
+ st.session_state.messages.append({
877
+ "role": "assistant",
878
+ "content": "",
879
+ "image": img,
880
+ "image_caption": f"{title} – {cap}"
881
+ })
882
+
883
+ # ── β‘₯ κ²°κ³Ό μ €μž₯ & λ‹€μš΄λ‘œλ“œ ──────���──────────────────
884
+ st.session_state.messages.append(
885
+ {"role": "assistant", "content": full_response})
886
+
887
+ st.subheader("Download This Output")
888
+ c1, c2 = st.columns(2)
889
+ c1.download_button("Markdown", full_response,
890
+ file_name=f"{prompt[:30]}.md",
891
+ mime="text/markdown")
892
+ c2.download_button("HTML",
893
+ md_to_html(full_response, prompt[:30]),
894
+ file_name=f"{prompt[:30]}.html",
895
+ mime="text/html")
896
+
897
+ # ── ⑦ μžλ™ μ €μž₯ ─────────────────────────────────
898
+ if st.session_state.auto_save:
899
+ fn = f"chat_history_auto_{datetime.now():%Y%m%d_%H%M%S}.json"
900
+ with open(fn, "w", encoding="utf-8") as fp:
901
+ json.dump(st.session_state.messages, fp,
902
+ ensure_ascii=False, indent=2)
903
+
904
+ except Exception as e:
905
+ err = str(e)
906
+ placeholder.error(f"Error: {err}")
907
+ logging.error(err)
908
+ st.session_state.messages.append(
909
+ {"role": "assistant",
910
+ "content": f"⚠️ μž‘μ—… 쀑 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€: {err}"})
911
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
912
  # 3개 이미지 생성 ν”„λ‘œμ„ΈμŠ€λ₯Ό 마친 ν›„ μ΅œμ’… ν…μŠ€νŠΈλ₯Ό μ €μž₯
913
  st.session_state.messages.append({"role": "assistant", "content": full_response})
914
  answer_entry_saved = True