Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -3,16 +3,13 @@ import os, json, re, logging, requests, markdown, time, io
|
|
3 |
from datetime import datetime
|
4 |
|
5 |
import streamlit as st
|
6 |
-
|
7 |
-
# import anthropic
|
8 |
-
from openai import OpenAI # 컀μ€ν
λνΌ(λλ λ³λ λΌμ΄λΈλ¬λ¦¬)λΌκ³ κ°μ
|
9 |
|
10 |
from gradio_client import Client
|
11 |
import pandas as pd
|
12 |
import PyPDF2 # For handling PDF files
|
13 |
|
14 |
# ββββββββββββββββββββββββββββββββ Environment Variables / Constants βββββββββββββββββββββββββ
|
15 |
-
# κΈ°μ‘΄ ANTHROPIC_KEY -> OPENAI_API_KEY λ‘ λ³κ²½
|
16 |
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY", "")
|
17 |
BRAVE_KEY = os.getenv("SERPHOUSE_API_KEY", "") # Keep this name
|
18 |
BRAVE_ENDPOINT = "https://api.search.brave.com/res/v1/web/search"
|
@@ -50,15 +47,10 @@ logging.basicConfig(level=logging.INFO,
|
|
50 |
# ββββββββββββββββββββββββββββββββ OpenAI Client ββββββββββββββββββββββββββ
|
51 |
@st.cache_resource
|
52 |
def get_openai_client():
|
53 |
-
"""
|
54 |
-
컀μ€ν
OpenAI κ°μ²΄λ₯Ό μμ±νλ€κ³ κ°μ ν©λλ€.
|
55 |
-
μ€μ λ‘λ openai.api_key = OPENAI_API_KEY λ‘λ§ μ€μ νλ κ²½μ°κ° λ§μ΅λλ€.
|
56 |
-
"""
|
57 |
if not OPENAI_API_KEY:
|
58 |
raise RuntimeError("β οΈ OPENAI_API_KEY νκ²½ λ³μκ° μ€μ λμ§ μμμ΅λλ€.")
|
59 |
-
|
60 |
-
client = OpenAI(api_key=OPENAI_API_KEY)
|
61 |
-
return client
|
62 |
|
63 |
# ββββββββββββββββββββββββββββββββ Blog Creation System Prompt βββββββββββββ
|
64 |
def get_system_prompt(template="ginigen", tone="professional", word_count=1750, include_search_results=False, include_uploaded_files=False) -> str:
|
@@ -521,56 +513,23 @@ def generate_image(prompt, w=768, h=768, g=3.5, steps=30, seed=3):
|
|
521 |
|
522 |
def extract_image_prompt(blog_text: str, topic: str):
|
523 |
"""
|
524 |
-
|
525 |
-
related to the topic.
|
526 |
"""
|
527 |
-
# κΈ°μ‘΄ anthropic ν΄λΌμ΄μΈνΈ μ¬μ© -> OpenAI νΈμΆλ‘ λ체
|
528 |
client = get_openai_client()
|
529 |
-
|
530 |
-
system_msg = (
|
531 |
-
f"Generate a single-line English image prompt from the following text:\n"
|
532 |
-
f"Topic: {topic}\n\n"
|
533 |
-
f"---\n"
|
534 |
-
f"{blog_text}\n\n"
|
535 |
-
f"---\n"
|
536 |
-
f"Return only the prompt text, nothing else."
|
537 |
-
)
|
538 |
-
|
539 |
-
# μ€μ λ‘λ openai APIλ₯Ό μ΄λ»κ² νΈμΆνλλμ λ°λΌ λ¬λΌμ§λλ€.
|
540 |
-
# μ¬κΈ°μλ μμλ‘ client.responses.create()λ₯Ό μ¬μ©νλ€κ³ κ°μ
|
541 |
try:
|
542 |
-
response = client.
|
543 |
-
model="gpt-
|
544 |
-
|
545 |
-
{
|
546 |
-
|
547 |
-
"content": [
|
548 |
-
{
|
549 |
-
"type": "input_text",
|
550 |
-
"text": system_msg
|
551 |
-
}
|
552 |
-
]
|
553 |
-
}
|
554 |
],
|
555 |
-
text={"format": {"type": "text"}},
|
556 |
temperature=1,
|
557 |
-
|
558 |
top_p=1
|
559 |
)
|
560 |
-
|
561 |
-
|
562 |
-
content = ""
|
563 |
-
if "responses" in dir(response):
|
564 |
-
# κ°μ μμ: response.responses[0].content[0].text
|
565 |
-
# λλ response["choices"][0]["text"] ννμΌ μλ μμ
|
566 |
-
first_resp = response.responses[0] # κ°μ
|
567 |
-
# λ³Έ μμλ "content" νλκ° listλ‘ μκ³ , κ·Έ μ€ [0]["text"]μ κ°μ΄ μλ€κ³ κ°μ
|
568 |
-
content = first_resp.content[0]["text"].strip()
|
569 |
-
else:
|
570 |
-
content = "A professional photo related to the topic, high quality"
|
571 |
-
|
572 |
-
return content
|
573 |
-
|
574 |
except Exception as e:
|
575 |
logging.error(f"OpenAI image prompt generation error: {e}")
|
576 |
return f"A professional photo related to {topic}, high quality"
|
@@ -590,8 +549,7 @@ def ginigen_app():
|
|
590 |
|
591 |
# Set default session state
|
592 |
if "ai_model" not in st.session_state:
|
593 |
-
|
594 |
-
st.session_state.ai_model = "gpt-4.1-mini"
|
595 |
if "messages" not in st.session_state:
|
596 |
st.session_state.messages = []
|
597 |
if "auto_save" not in st.session_state:
|
@@ -611,6 +569,10 @@ def ginigen_app():
|
|
611 |
sb = st.sidebar
|
612 |
sb.title("Blog Settings")
|
613 |
|
|
|
|
|
|
|
|
|
614 |
sb.subheader("Blog Style Settings")
|
615 |
sb.selectbox(
|
616 |
"Blog Template",
|
@@ -772,25 +734,31 @@ def process_input(prompt: str, uploaded_files):
|
|
772 |
has_uploaded_files = bool(uploaded_files) and len(uploaded_files) > 0
|
773 |
|
774 |
try:
|
|
|
|
|
|
|
|
|
775 |
client = get_openai_client()
|
776 |
|
777 |
# Prepare conversation messages
|
778 |
-
messages = [
|
779 |
|
780 |
# Web search
|
|
|
781 |
if use_web_search:
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
messages.append({"role": "user", "content": sr})
|
786 |
|
787 |
# Process uploaded files β content
|
788 |
file_content = None
|
789 |
if has_uploaded_files:
|
790 |
-
|
|
|
791 |
file_content = process_uploaded_files(uploaded_files)
|
792 |
|
793 |
# Build system prompt
|
|
|
794 |
sys_prompt = get_system_prompt(
|
795 |
template=st.session_state.blog_template,
|
796 |
tone=st.session_state.blog_tone,
|
@@ -799,68 +767,48 @@ def process_input(prompt: str, uploaded_files):
|
|
799 |
include_uploaded_files=has_uploaded_files
|
800 |
)
|
801 |
|
802 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
803 |
if file_content:
|
804 |
-
|
805 |
-
"\n\n"
|
806 |
-
"Below is the content of the uploaded file(s). Please make sure to integrate it thoroughly in the blog:\n\n"
|
807 |
-
f"{file_content}\n\n"
|
808 |
-
"Ensure the file content is accurately reflected in the blog.\n"
|
809 |
-
)
|
810 |
|
811 |
-
#
|
812 |
-
|
813 |
-
extra_user_msg = (
|
814 |
-
f"{prompt}\n\n"
|
815 |
-
"Additional note: Please make sure to reference the uploaded file content in the blog. "
|
816 |
-
"Use and analyze any data, statistics, or text included in the file(s)."
|
817 |
-
)
|
818 |
-
messages.append({"role": "user", "content": extra_user_msg})
|
819 |
|
820 |
-
#
|
821 |
-
|
822 |
-
response = client.
|
823 |
model=st.session_state.ai_model,
|
824 |
-
|
825 |
-
input=[
|
826 |
-
{
|
827 |
-
"role": "system",
|
828 |
-
"content": [
|
829 |
-
{
|
830 |
-
"type": "input_text",
|
831 |
-
"text": sys_prompt
|
832 |
-
}
|
833 |
-
]
|
834 |
-
},
|
835 |
-
{
|
836 |
-
"role": "user",
|
837 |
-
"content": [
|
838 |
-
{
|
839 |
-
"type": "input_text",
|
840 |
-
"text": prompt
|
841 |
-
}
|
842 |
-
]
|
843 |
-
}
|
844 |
-
# νμνλ©΄ messages μ 체λ₯Ό λ£μ μλ μμ§λ§,
|
845 |
-
# μ¬κΈ°μλ promptμ system promptλ§ λ£λ μμ
|
846 |
-
],
|
847 |
-
text={"format": {"type": "text"}},
|
848 |
temperature=1,
|
849 |
-
|
850 |
-
top_p=1
|
851 |
-
store=True
|
852 |
)
|
853 |
-
|
854 |
-
#
|
855 |
-
|
856 |
-
|
857 |
-
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
|
|
862 |
|
863 |
-
#
|
864 |
placeholder.markdown(answer)
|
865 |
|
866 |
# μ΄λ―Έμ§ μμ±
|
@@ -911,6 +859,7 @@ def process_input(prompt: str, uploaded_files):
|
|
911 |
except Exception as e:
|
912 |
error_message = str(e)
|
913 |
placeholder.error(f"An error occurred: {error_message}")
|
|
|
914 |
ans = f"An error occurred while processing your request: {error_message}"
|
915 |
st.session_state.messages.append({"role": "assistant", "content": ans})
|
916 |
|
@@ -919,4 +868,4 @@ def main():
|
|
919 |
ginigen_app()
|
920 |
|
921 |
if __name__ == "__main__":
|
922 |
-
main()
|
|
|
3 |
from datetime import datetime
|
4 |
|
5 |
import streamlit as st
|
6 |
+
from openai import OpenAI # OpenAI λΌμ΄λΈλ¬λ¦¬
|
|
|
|
|
7 |
|
8 |
from gradio_client import Client
|
9 |
import pandas as pd
|
10 |
import PyPDF2 # For handling PDF files
|
11 |
|
12 |
# ββββββββββββββββββββββββββββββββ Environment Variables / Constants βββββββββββββββββββββββββ
|
|
|
13 |
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY", "")
|
14 |
BRAVE_KEY = os.getenv("SERPHOUSE_API_KEY", "") # Keep this name
|
15 |
BRAVE_ENDPOINT = "https://api.search.brave.com/res/v1/web/search"
|
|
|
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(api_key=OPENAI_API_KEY)
|
|
|
|
|
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:
|
|
|
513 |
|
514 |
def extract_image_prompt(blog_text: str, topic: str):
|
515 |
"""
|
516 |
+
Generate a single-line English image prompt from the blog content.
|
|
|
517 |
"""
|
|
|
518 |
client = get_openai_client()
|
519 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
520 |
try:
|
521 |
+
response = client.chat.completions.create(
|
522 |
+
model="gpt-3.5-turbo", # μΌλ°μ μΌλ‘ μ¬μ© κ°λ₯ν λͺ¨λΈλ‘ μ€μ
|
523 |
+
messages=[
|
524 |
+
{"role": "system", "content": "Generate a single-line English image prompt from the following text. Return only the prompt text, nothing else."},
|
525 |
+
{"role": "user", "content": f"Topic: {topic}\n\n---\n{blog_text}\n\n---"}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
526 |
],
|
|
|
527 |
temperature=1,
|
528 |
+
max_tokens=80,
|
529 |
top_p=1
|
530 |
)
|
531 |
+
|
532 |
+
return response.choices[0].message.content.strip()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
533 |
except Exception as e:
|
534 |
logging.error(f"OpenAI image prompt generation error: {e}")
|
535 |
return f"A professional photo related to {topic}, high quality"
|
|
|
549 |
|
550 |
# Set default session state
|
551 |
if "ai_model" not in st.session_state:
|
552 |
+
st.session_state.ai_model = "gpt-3.5-turbo" # κΈ°λ³Έ λͺ¨λΈλ‘ μ€μ
|
|
|
553 |
if "messages" not in st.session_state:
|
554 |
st.session_state.messages = []
|
555 |
if "auto_save" not in st.session_state:
|
|
|
569 |
sb = st.sidebar
|
570 |
sb.title("Blog Settings")
|
571 |
|
572 |
+
# λͺ¨λΈ μ ν μΆκ°
|
573 |
+
available_models = ["gpt-3.5-turbo", "gpt-4o", "gpt-4-turbo"]
|
574 |
+
sb.selectbox("AI Model", available_models, key="ai_model")
|
575 |
+
|
576 |
sb.subheader("Blog Style Settings")
|
577 |
sb.selectbox(
|
578 |
"Blog Template",
|
|
|
734 |
has_uploaded_files = bool(uploaded_files) and len(uploaded_files) > 0
|
735 |
|
736 |
try:
|
737 |
+
# μν νμλ₯Ό μν μν μ»΄ν¬λνΈ
|
738 |
+
status = st.status("Preparing to generate blog...")
|
739 |
+
status.update(label="Initializing OpenAI client...")
|
740 |
+
|
741 |
client = get_openai_client()
|
742 |
|
743 |
# Prepare conversation messages
|
744 |
+
messages = []
|
745 |
|
746 |
# Web search
|
747 |
+
search_content = None
|
748 |
if use_web_search:
|
749 |
+
status.update(label="Performing web search...")
|
750 |
+
with st.spinner("Searching the web..."):
|
751 |
+
search_content = do_web_search(keywords(prompt, top=5))
|
|
|
752 |
|
753 |
# Process uploaded files β content
|
754 |
file_content = None
|
755 |
if has_uploaded_files:
|
756 |
+
status.update(label="Processing uploaded files...")
|
757 |
+
with st.spinner("Analyzing files..."):
|
758 |
file_content = process_uploaded_files(uploaded_files)
|
759 |
|
760 |
# Build system prompt
|
761 |
+
status.update(label="Preparing system prompt...")
|
762 |
sys_prompt = get_system_prompt(
|
763 |
template=st.session_state.blog_template,
|
764 |
tone=st.session_state.blog_tone,
|
|
|
767 |
include_uploaded_files=has_uploaded_files
|
768 |
)
|
769 |
|
770 |
+
# OpenAI API νΈμΆ μ€λΉ
|
771 |
+
status.update(label="Generating blog content...")
|
772 |
+
|
773 |
+
# λ©μμ§ κ΅¬μ±
|
774 |
+
api_messages = [
|
775 |
+
{"role": "system", "content": sys_prompt}
|
776 |
+
]
|
777 |
+
|
778 |
+
user_content = prompt
|
779 |
+
|
780 |
+
# κ²μ κ²°κ³Όκ° μμΌλ©΄ μ¬μ©μ ν둬ννΈμ μΆκ°
|
781 |
+
if search_content:
|
782 |
+
user_content += "\n\n" + search_content
|
783 |
+
|
784 |
+
# νμΌ λ΄μ©μ΄ μμΌλ©΄ μ¬μ©μ ν둬ννΈμ μΆκ°
|
785 |
if file_content:
|
786 |
+
user_content += "\n\n" + file_content
|
|
|
|
|
|
|
|
|
|
|
787 |
|
788 |
+
# μ¬μ©μ λ©μμ§ μΆκ°
|
789 |
+
api_messages.append({"role": "user", "content": user_content})
|
|
|
|
|
|
|
|
|
|
|
|
|
790 |
|
791 |
+
# OpenAI API νΈμΆ
|
792 |
+
try:
|
793 |
+
response = client.chat.completions.create(
|
794 |
model=st.session_state.ai_model,
|
795 |
+
messages=api_messages,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
796 |
temperature=1,
|
797 |
+
max_tokens=MAX_TOKENS,
|
798 |
+
top_p=1
|
|
|
799 |
)
|
800 |
+
|
801 |
+
# μλ΅ μΆμΆ
|
802 |
+
answer = response.choices[0].message.content
|
803 |
+
status.update(label="Blog generated successfully!", state="complete")
|
804 |
+
|
805 |
+
except Exception as api_error:
|
806 |
+
error_message = str(api_error)
|
807 |
+
logging.error(f"OpenAI API error: {error_message}")
|
808 |
+
status.update(label=f"API Error: {error_message}", state="error")
|
809 |
+
raise Exception(f"OpenAI API error: {error_message}")
|
810 |
|
811 |
+
# κ²°κ³Ό νμ
|
812 |
placeholder.markdown(answer)
|
813 |
|
814 |
# μ΄λ―Έμ§ μμ±
|
|
|
859 |
except Exception as e:
|
860 |
error_message = str(e)
|
861 |
placeholder.error(f"An error occurred: {error_message}")
|
862 |
+
logging.error(f"Process input error: {error_message}")
|
863 |
ans = f"An error occurred while processing your request: {error_message}"
|
864 |
st.session_state.messages.append({"role": "assistant", "content": ans})
|
865 |
|
|
|
868 |
ginigen_app()
|
869 |
|
870 |
if __name__ == "__main__":
|
871 |
+
main()
|