Spaces:
Sleeping
Sleeping
import gradio as gr | |
import openai | |
import os | |
from typing import Optional | |
from gradio_client import Client | |
############################# | |
# OpenAI API 클라이언트 설정 | |
openai.api_key = os.getenv("OPENAI_API_KEY") | |
if not openai.api_key: | |
raise ValueError("OpenAI API 토큰(OPENAI_API_KEY)이 설정되지 않았습니다.") | |
def call_openai_api( | |
content: str, | |
system_message: str, | |
max_tokens: int, | |
temperature: float, | |
top_p: float | |
) -> str: | |
""" | |
OpenAI의 GPT-4o-mini 모델을 이용해 한 번의 질문(content)에 대한 답변을 반환하는 함수. | |
""" | |
try: | |
response = openai.ChatCompletion.create( | |
model="gpt-4o-mini", | |
messages=[ | |
{"role": "system", "content": system_message}, | |
{"role": "user", "content": content}, | |
], | |
max_tokens=max_tokens, | |
temperature=temperature, | |
top_p=top_p, | |
) | |
assistant_message = response.choices[0].message['content'] | |
return assistant_message | |
except Exception as e: | |
return f"오류가 발생했습니다: {str(e)}" | |
############################# | |
# 고급 설정 (OpenAI) - 코드에서만 정의 (UI에 노출 금지) | |
############################# | |
OPENAI_SYSTEM_MESSAGE = """반드시 한글로 답변할 것. | |
너는 최고의 비서이다. | |
내가 요구하는 것들을 최대한 자세하고 정확하게 답변하라. | |
##[기본규칙] | |
1. 반드시 한국어(한글)로 작성하라. | |
2. 너는 가장 주목받는 마케터이며 블로그 마케팅 전문가이다. | |
3. 특히 너는 '정보성(Informative)' 전문 블로그 마케팅 전문가이다. | |
4. 정보 제공에 초점을 맞추어 작성한다. | |
##[텍스트 작성 규칙] | |
1. 소주제를 5개로 구분하여 2000자 이상되도록 작성하라. | |
2. 전체 맥락을 이해하고 문장의 일관성을 유지하라. | |
3. 절대로 참고글을 한문장 이상 그대로 출력하지 말 것. | |
4. 주제와 상황에 맞는 적절한 어휘를 선택하라. | |
5. 한글 어휘의 난이도는 쉽게 작성하라. | |
6. 절대 문장의 끝에 '답니다'를 사용하지 말 것. | |
###[정보성 블로그 작성 규칙] | |
1. 독자가 얻고자 하는 유용한 정보와 흥미로운 정보를 제공하도록 작성하라. | |
2. 독자의 공감을 이끌어내고 궁금증을 해결하도록 작성하라. | |
3. 독자의 관심사를 충족시키도록 작성하라. | |
4. 독자에게 이득이 되는 정보를 작성하라. | |
##[제외 규칙] | |
1. 반드시 비속어 및 욕설(expletive, abusive language, slang)은 제외하라. | |
2. 반드시 참고글의 링크(URL)는 제외하라. | |
3. 참고글에서 '링크를 확인해주세요'와 같은 링크 이동의 문구는 제외하라. | |
4. 참고글에 있는 작성자, 화자, 유튜버, 기자의 이름, 애칭, 닉네임은 반드시 제외하라. | |
5. 반드시 문장의 끝부분이 어색한 한국어 표현은 제외하라('예요', '답니다', '해요', '해주죠', '됐죠', '됐어요', '고요' 등.) | |
""" | |
OPENAI_MAX_TOKENS = 4000 | |
OPENAI_TEMPERATURE = 0.7 | |
OPENAI_TOP_P = 0.95 | |
############################# | |
# API 클라이언트 설정 (허깅페이스 스페이스) | |
############################# | |
blog_client = Client("Kims12/blog") | |
youtube_client = Client("Kims12/you") | |
############################# | |
# UI - 블로그 생성기 | |
############################# | |
with gr.Blocks() as demo: | |
gr.Markdown("# 블로그 생성기") | |
# 말투바꾸기 (라디오 버튼) | |
tone_radio = gr.Radio( | |
label="말투바꾸기", | |
choices=["친근하게", "일반적인", "전문적인"], | |
value="일반적인" # 기본 선택 | |
) | |
# 참조글 입력 (3개)과 API 실행 버튼 | |
with gr.Row(): | |
with gr.Column(): | |
ref1 = gr.Textbox(label="참조글 1 (블로그 URL)") | |
fetch_button1 = gr.Button("API 실행1") | |
with gr.Column(): | |
ref2 = gr.Textbox(label="참조글 2 (블로그 URL)") | |
fetch_button2 = gr.Button("API 실행2") | |
with gr.Column(): | |
ref3 = gr.Textbox(label="참조글 3 (블로그 URL)") | |
fetch_button3 = gr.Button("API 실행3") | |
# 유튜브 대본 입력 (3개)과 API 실행 버튼 | |
with gr.Row(): | |
with gr.Column(): | |
youtube1 = gr.Textbox(label="유튜브 URL 1") | |
fetch_youtube1 = gr.Button("유튜브 API 실행1") | |
with gr.Column(): | |
youtube2 = gr.Textbox(label="유튜브 URL 2") | |
fetch_youtube2 = gr.Button("유튜브 API 실행2") | |
with gr.Column(): | |
youtube3 = gr.Textbox(label="유튜브 URL 3") | |
fetch_youtube3 = gr.Button("유튜브 API 실행3") | |
output_box = gr.Textbox(label="결과", lines=20, interactive=False) | |
# 참조글1 블로그 API 실행 함수 | |
def fetch_ref1(url: str) -> str: | |
if not url: | |
return "블로그 URL을 입력해주세요." | |
try: | |
result = blog_client.predict( | |
url=url, | |
api_name="/predict" | |
) | |
return result | |
except Exception as e: | |
return f"오류가 발생했습니다: {str(e)}" | |
# 참조글2 블로그 API 실행 함수 | |
def fetch_ref2(url: str) -> str: | |
if not url: | |
return "블로그 URL을 입력해주세요." | |
try: | |
result = blog_client.predict( | |
url=url, | |
api_name="/predict" | |
) | |
return result | |
except Exception as e: | |
return f"오류가 발생했습니다: {str(e)}" | |
# 참조글3 블로그 API 실행 함수 | |
def fetch_ref3(url: str) -> str: | |
if not url: | |
return "블로그 URL을 입력해주세요." | |
try: | |
result = blog_client.predict( | |
url=url, | |
api_name="/predict" | |
) | |
return result | |
except Exception as e: | |
return f"오류가 발생했습니다: {str(e)}" | |
# 유튜브1 대본 API 실행 함수 | |
def fetch_youtube_ref1(url: str) -> str: | |
if not url: | |
return "유튜브 URL을 입력해주세요." | |
try: | |
result = youtube_client.predict( | |
youtube_url=url, | |
api_name="/predict" | |
) | |
return result | |
except Exception as e: | |
return f"오류가 발생했습니다: {str(e)}" | |
# 유튜브2 대본 API 실행 함수 | |
def fetch_youtube_ref2(url: str) -> str: | |
if not url: | |
return "유튜브 URL을 입력해주세요." | |
try: | |
result = youtube_client.predict( | |
youtube_url=url, | |
api_name="/predict" | |
) | |
return result | |
except Exception as e: | |
return f"오류가 발생했습니다: {str(e)}" | |
# 유튜브3 대본 API 실행 함수 | |
def fetch_youtube_ref3(url: str) -> str: | |
if not url: | |
return "유튜브 URL을 입력해주세요." | |
try: | |
result = youtube_client.predict( | |
youtube_url=url, | |
api_name="/predict" | |
) | |
return result | |
except Exception as e: | |
return f"오류가 발생했습니다: {str(e)}" | |
# 버튼 클릭 시 해당 참조글 블로그 API 실행 | |
fetch_button1.click( | |
fn=fetch_ref1, | |
inputs=ref1, | |
outputs=ref1 | |
) | |
fetch_button2.click( | |
fn=fetch_ref2, | |
inputs=ref2, | |
outputs=ref2 | |
) | |
fetch_button3.click( | |
fn=fetch_ref3, | |
inputs=ref3, | |
outputs=ref3 | |
) | |
# 버튼 클릭 시 해당 유튜브 대본 API 실행 | |
fetch_youtube1.click( | |
fn=fetch_youtube_ref1, | |
inputs=youtube1, | |
outputs=youtube1 | |
) | |
fetch_youtube2.click( | |
fn=fetch_youtube_ref2, | |
inputs=youtube2, | |
outputs=youtube2 | |
) | |
fetch_youtube3.click( | |
fn=fetch_youtube_ref3, | |
inputs=youtube3, | |
outputs=youtube3 | |
) | |
# 블로그 생성 함수 | |
def generate_blog(tone_value: str, ref1_value: str, ref2_value: str, ref3_value: str, yt1: str, yt2: str, yt3: str) -> str: | |
# 프롬프트 생성 | |
question = ( | |
f"말투: {tone_value}\n" | |
f"참조글1: {ref1_value}\n" | |
f"참조글2: {ref2_value}\n" | |
f"참조글3: {ref3_value}\n" | |
f"유튜브 대본1: {yt1}\n" | |
f"유튜브 대본2: {yt2}\n" | |
f"유튜브 대본3: {yt3}\n" | |
) | |
# OpenAI GPT-4o-mini 모델 호출 | |
response = call_openai_api( | |
content=question, | |
system_message=OPENAI_SYSTEM_MESSAGE, | |
max_tokens=OPENAI_MAX_TOKENS, | |
temperature=OPENAI_TEMPERATURE, | |
top_p=OPENAI_TOP_P | |
) | |
return response | |
generate_button = gr.Button("생성하기") | |
generate_button.click( | |
fn=generate_blog, | |
inputs=[tone_radio, ref1, ref2, ref3, youtube1, youtube2, youtube3], | |
outputs=output_box | |
) | |
if __name__ == "__main__": | |
demo.launch() | |