Spaces:
Sleeping
Sleeping
File size: 7,659 Bytes
b34f0d5 bcec348 16edf41 bf61b83 c4c9f37 2d9e222 2bc2ba7 c4c9f37 84e39e9 2d9e222 10c6fc3 bcec348 c231a45 673dbba 10c6fc3 092cc1c bcec348 c231a45 092cc1c 673dbba 092cc1c 10c6fc3 c753d25 2bc2ba7 77f2f20 2bc2ba7 2d9e222 10c6fc3 2bc2ba7 c4c9f37 2d9e222 77f2f20 2d9e222 c4c9f37 2d9e222 77f2f20 2d9e222 77f2f20 e00748b 77f2f20 e00748b 77f2f20 e00748b 77f2f20 958e155 b34f0d5 5d429a8 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
import gradio as gr
import openai
import os
from typing import Optional
from gradio_client import Client
import requests
from bs4 import BeautifulSoup
#############################
# [기본코드]
#############################
# 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)}"
#############################
# 고급 설정 (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
def generate_blog(tone_value: str, ref1_value: str, ref2_value: str, ref3_value: str) -> str:
# 프롬프트 생성
question = (
f"말투: {tone_value}\n"
f"참조글1: {ref1_value}\n"
f"참조글2: {ref2_value}\n"
f"참조글3: {ref3_value}\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
#############################
# [추가코드] - 네이버 블로그 스크래핑
#############################
def convert_to_mobile_url(url):
"""
PC URL을 모바일 URL로 변환.
"""
if "m.blog.naver.com" not in url:
if "blog.naver.com" in url:
url_parts = url.split("/")
if len(url_parts) >= 5:
user_id = url_parts[3]
post_id = url_parts[4]
return f"https://m.blog.naver.com/{user_id}/{post_id}"
return url
def scrape_naver_blog(url):
"""
네이버 블로그의 제목과 내용(텍스트만) 스크래핑.
"""
try:
# 모바일 URL 변환
mobile_url = convert_to_mobile_url(url)
print(f"Converted Mobile URL: {mobile_url}")
response = requests.get(mobile_url)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
# 제목 스크래핑
title_element = soup.find("div", class_="se-module se-module-text se-title-text")
title = title_element.get_text(strip=True) if title_element else "제목을 찾을 수 없음"
# 본문 내용 스크래핑
content_elements = soup.find_all("div", class_="se-module se-module-text")
content = "\n".join(
elem.get_text(strip=True) for elem in content_elements
) if content_elements else "내용을 찾을 수 없음"
# 디버깅 메시지 출력
print(f"Scraped Title: {title}")
print(f"Scraped Content: {content}")
# 결과 반환
result = f"제목: {title}\n\n내용: {content}"
return result
except Exception as e:
print(f"Error: {e}")
return f"Error: {e}"
def run_scraper(url):
return scrape_naver_blog(url)
#############################
# 전체 UI - 한 화면에 통합 (블로그 생성기 + 네이버 블로그 스크래핑)
#############################
with gr.Blocks() as demo:
gr.Markdown("# 블로그 생성 및 네이버 블로그 스크래핑")
# 네이버 블로그 스크래핑 영역
with gr.Column():
gr.Markdown("## 네이버 블로그 스크래핑")
scraper_input = gr.Textbox(label="네이버 블로그 URL")
scraper_output = gr.Textbox(label="스크래핑 결과", lines=10, interactive=False)
scraper_button = gr.Button("스크래핑 실행")
scraper_button.click(fn=run_scraper, inputs=scraper_input, outputs=scraper_output)
gr.Markdown("---")
# 블로그 생성기 영역
with gr.Column():
gr.Markdown("## 블로그 생성기")
tone_radio = gr.Radio(
label="말투바꾸기",
choices=["친근하게", "일반적인", "전문적인"],
value="일반적인"
)
ref1 = gr.Textbox(label="참조글 1")
ref2 = gr.Textbox(label="참조글 2")
ref3 = gr.Textbox(label="참조글 3")
output_box = gr.Textbox(label="생성된 블로그", lines=10, interactive=False)
generate_button = gr.Button("생성하기")
generate_button.click(fn=generate_blog,
inputs=[tone_radio, ref1, ref2, ref3],
outputs=output_box)
# 두 영역의 결과를 함께 확인할 수 있도록 최종 결과 영역 추가 (선택 사항)
gr.Markdown("### 최종 결과")
combined_output = gr.Textbox(label="최종 결과", lines=10, interactive=False)
def combine_results(blog: str, scrape: str) -> str:
return f"블로그 생성 결과:\n{blog}\n\n네이버 블로그 스크래핑 결과:\n{scrape}"
combine_button = gr.Button("최종 결과 보기")
combine_button.click(fn=combine_results,
inputs=[output_box, scraper_output],
outputs=combined_output)
if __name__ == "__main__":
demo.launch()
|