Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -45,13 +45,19 @@ logging.basicConfig(level=logging.INFO,
|
|
| 45 |
format="%(asctime)s - %(levelname)s - %(message)s")
|
| 46 |
|
| 47 |
# ──────────────────────────────── OpenAI Client ──────────────────────────
|
|
|
|
|
|
|
| 48 |
@st.cache_resource
|
| 49 |
def get_openai_client():
|
| 50 |
-
"""Create an OpenAI client."""
|
| 51 |
if not OPENAI_API_KEY:
|
| 52 |
raise RuntimeError("⚠️ OPENAI_API_KEY 환경 변수가 설정되지 않았습니다.")
|
| 53 |
-
return OpenAI(
|
| 54 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
# ──────────────────────────────── Blog Creation System Prompt ─────────────
|
| 56 |
def get_system_prompt(template="ginigen", tone="professional", word_count=1750, include_search_results=False, include_uploaded_files=False) -> str:
|
| 57 |
"""
|
|
@@ -788,64 +794,126 @@ def process_input(prompt: str, uploaded_files):
|
|
| 788 |
# 사용자 메시지 추가
|
| 789 |
api_messages.append({"role": "user", "content": user_content})
|
| 790 |
|
| 791 |
-
# OpenAI API 호출
|
| 792 |
-
|
| 793 |
-
|
| 794 |
-
|
| 795 |
-
|
| 796 |
-
|
| 797 |
-
|
| 798 |
-
|
| 799 |
-
|
| 800 |
-
|
| 801 |
-
|
| 802 |
-
|
| 803 |
-
|
| 804 |
-
|
| 805 |
-
|
| 806 |
-
|
| 807 |
-
|
| 808 |
-
|
| 809 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 810 |
|
| 811 |
# 결과 표시
|
| 812 |
placeholder.markdown(answer)
|
| 813 |
|
| 814 |
# 이미지 생성
|
| 815 |
answer_entry_saved = False
|
| 816 |
-
if st.session_state.generate_image:
|
| 817 |
with st.spinner("Generating image..."):
|
| 818 |
-
|
| 819 |
-
|
| 820 |
-
|
| 821 |
-
|
| 822 |
-
|
| 823 |
-
|
| 824 |
-
|
| 825 |
-
|
| 826 |
-
|
| 827 |
-
|
| 828 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 829 |
|
| 830 |
# Save the answer if not saved above
|
| 831 |
-
if not answer_entry_saved:
|
| 832 |
st.session_state.messages.append({"role": "assistant", "content": answer})
|
| 833 |
|
| 834 |
# Download buttons
|
| 835 |
-
|
| 836 |
-
|
| 837 |
-
|
| 838 |
-
|
| 839 |
-
|
| 840 |
-
|
| 841 |
-
|
| 842 |
-
|
| 843 |
-
|
| 844 |
-
|
| 845 |
-
|
| 846 |
-
|
| 847 |
-
|
| 848 |
-
|
|
|
|
| 849 |
|
| 850 |
# Auto save
|
| 851 |
if st.session_state.auto_save and st.session_state.messages:
|
|
|
|
| 45 |
format="%(asctime)s - %(levelname)s - %(message)s")
|
| 46 |
|
| 47 |
# ──────────────────────────────── OpenAI Client ──────────────────────────
|
| 48 |
+
|
| 49 |
+
# OpenAI 클라이언트에 타임아웃과 재시도 로직 추가
|
| 50 |
@st.cache_resource
|
| 51 |
def get_openai_client():
|
| 52 |
+
"""Create an OpenAI client with timeout and retry settings."""
|
| 53 |
if not OPENAI_API_KEY:
|
| 54 |
raise RuntimeError("⚠️ OPENAI_API_KEY 환경 변수가 설정되지 않았습니다.")
|
| 55 |
+
return OpenAI(
|
| 56 |
+
api_key=OPENAI_API_KEY,
|
| 57 |
+
timeout=60.0, # 타임아웃 60초로 설정
|
| 58 |
+
max_retries=3 # 재시도 횟수 3회로 설정
|
| 59 |
+
)
|
| 60 |
+
|
| 61 |
# ──────────────────────────────── Blog Creation System Prompt ─────────────
|
| 62 |
def get_system_prompt(template="ginigen", tone="professional", word_count=1750, include_search_results=False, include_uploaded_files=False) -> str:
|
| 63 |
"""
|
|
|
|
| 794 |
# 사용자 메시지 추가
|
| 795 |
api_messages.append({"role": "user", "content": user_content})
|
| 796 |
|
| 797 |
+
# OpenAI API 호출 - 재시도 로직 추가
|
| 798 |
+
max_retries = 3
|
| 799 |
+
retry_delay = 2 # 초 단위
|
| 800 |
+
answer = None
|
| 801 |
+
used_model = st.session_state.ai_model
|
| 802 |
+
|
| 803 |
+
for retry in range(max_retries):
|
| 804 |
+
try:
|
| 805 |
+
status.update(label=f"Generating blog with {used_model} (attempt {retry+1}/{max_retries})...")
|
| 806 |
+
response = client.chat.completions.create(
|
| 807 |
+
model=used_model,
|
| 808 |
+
messages=api_messages,
|
| 809 |
+
temperature=1,
|
| 810 |
+
max_tokens=MAX_TOKENS,
|
| 811 |
+
top_p=1,
|
| 812 |
+
request_timeout=90 # 타임아웃 90초로 설정
|
| 813 |
+
)
|
| 814 |
+
|
| 815 |
+
# 응답 추출
|
| 816 |
+
answer = response.choices[0].message.content
|
| 817 |
+
status.update(label=f"Blog generated successfully with {used_model}!", state="complete")
|
| 818 |
+
break # 성공하면 반복문 종료
|
| 819 |
+
|
| 820 |
+
except Exception as api_error:
|
| 821 |
+
error_message = str(api_error)
|
| 822 |
+
logging.error(f"OpenAI API error (attempt {retry+1}/{max_retries}): {error_message}")
|
| 823 |
+
|
| 824 |
+
if retry < max_retries - 1:
|
| 825 |
+
wait_time = retry_delay * (retry + 1) # 점점 길어지는 대기 시간
|
| 826 |
+
status.update(label=f"API Error: {error_message}. Retrying in {wait_time}s... ({retry+1}/{max_retries})")
|
| 827 |
+
time.sleep(wait_time)
|
| 828 |
+
else:
|
| 829 |
+
# 마지막 시도에서도 실패하면 대체 모델 시도
|
| 830 |
+
fallback_models = ["gpt-3.5-turbo", "gpt-3.5-turbo-16k"]
|
| 831 |
+
if used_model in fallback_models:
|
| 832 |
+
fallback_models.remove(used_model)
|
| 833 |
+
|
| 834 |
+
# 대체 모델 시도
|
| 835 |
+
if fallback_models:
|
| 836 |
+
status.update(label="Primary model failed. Trying fallback models...")
|
| 837 |
+
for fb_model in fallback_models:
|
| 838 |
+
try:
|
| 839 |
+
status.update(label=f"Trying with fallback model: {fb_model}...")
|
| 840 |
+
response = client.chat.completions.create(
|
| 841 |
+
model=fb_model,
|
| 842 |
+
messages=api_messages,
|
| 843 |
+
temperature=1,
|
| 844 |
+
max_tokens=min(MAX_TOKENS, 4096 if "16k" not in fb_model else 16000),
|
| 845 |
+
top_p=1,
|
| 846 |
+
request_timeout=90
|
| 847 |
+
)
|
| 848 |
+
answer = response.choices[0].message.content
|
| 849 |
+
used_model = fb_model
|
| 850 |
+
status.update(label=f"Blog generated with fallback model: {used_model}", state="complete")
|
| 851 |
+
break
|
| 852 |
+
except Exception as fb_error:
|
| 853 |
+
logging.error(f"Fallback model {fb_model} also failed: {str(fb_error)}")
|
| 854 |
+
|
| 855 |
+
# 대체 모델 중 하나가 성공했는지 확인
|
| 856 |
+
if answer:
|
| 857 |
+
break
|
| 858 |
+
|
| 859 |
+
# 모든 모델이 실패한 경우
|
| 860 |
+
if not answer:
|
| 861 |
+
status.update(label="All models failed to generate content", state="error")
|
| 862 |
+
user_message = "OpenAI API 연결 문제가 발생했습니다. 인터넷 연결을 확인하거나 나중에 다시 시도해 주세요."
|
| 863 |
+
if "rate limit" in error_message.lower():
|
| 864 |
+
user_message = "OpenAI API 속도 제한에 도달했습니다. 잠시 후 다시 시도해 주세요."
|
| 865 |
+
elif "invalid api key" in error_message.lower():
|
| 866 |
+
user_message = "유효하지 않은 API 키입니다. API 키를 확인해 주세요."
|
| 867 |
+
|
| 868 |
+
raise Exception(user_message)
|
| 869 |
+
|
| 870 |
+
# 결과가 생성되지 않은 경우 오류 발생
|
| 871 |
+
if not answer:
|
| 872 |
+
raise Exception("블로그 콘텐츠를 생성하지 못했습니다.")
|
| 873 |
|
| 874 |
# 결과 표시
|
| 875 |
placeholder.markdown(answer)
|
| 876 |
|
| 877 |
# 이미지 생성
|
| 878 |
answer_entry_saved = False
|
| 879 |
+
if st.session_state.generate_image and answer:
|
| 880 |
with st.spinner("Generating image..."):
|
| 881 |
+
try:
|
| 882 |
+
ip = extract_image_prompt(answer, prompt)
|
| 883 |
+
img, cap = generate_image(ip)
|
| 884 |
+
if img:
|
| 885 |
+
st.image(img, caption=cap)
|
| 886 |
+
st.session_state.messages.append({
|
| 887 |
+
"role": "assistant",
|
| 888 |
+
"content": answer,
|
| 889 |
+
"image": img,
|
| 890 |
+
"image_caption": cap
|
| 891 |
+
})
|
| 892 |
+
answer_entry_saved = True
|
| 893 |
+
except Exception as img_error:
|
| 894 |
+
logging.error(f"Image generation error: {str(img_error)}")
|
| 895 |
+
st.warning("이미지 생성에 실패했습니다. 블로그 콘텐츠만 저장됩니다.")
|
| 896 |
|
| 897 |
# Save the answer if not saved above
|
| 898 |
+
if not answer_entry_saved and answer:
|
| 899 |
st.session_state.messages.append({"role": "assistant", "content": answer})
|
| 900 |
|
| 901 |
# Download buttons
|
| 902 |
+
if answer:
|
| 903 |
+
st.subheader("Download This Blog")
|
| 904 |
+
c1, c2 = st.columns(2)
|
| 905 |
+
c1.download_button(
|
| 906 |
+
"Markdown",
|
| 907 |
+
data=answer,
|
| 908 |
+
file_name=f"{prompt[:30]}.md",
|
| 909 |
+
mime="text/markdown"
|
| 910 |
+
)
|
| 911 |
+
c2.download_button(
|
| 912 |
+
"HTML",
|
| 913 |
+
data=md_to_html(answer, prompt[:30]),
|
| 914 |
+
file_name=f"{prompt[:30]}.html",
|
| 915 |
+
mime="text/html"
|
| 916 |
+
)
|
| 917 |
|
| 918 |
# Auto save
|
| 919 |
if st.session_state.auto_save and st.session_state.messages:
|