AIBLOG / app.py
LEEDONGGEUN's picture
Create app.py
647040c verified
import gradio as gr
import google.generativeai as genai
from transformers import pipeline
import os
from typing import IO # ํŒŒ์ผ ํƒ€์ž… ํžŒํŠธ๋ฅผ ์œ„ํ•ด ์ถ”๊ฐ€
# Hugging Face Spaces์˜ ๋ฉ”๋ชจ๋ฆฌ ์ œํ•œ์„ ๊ณ ๋ คํ•˜์—ฌ ๊ฒฝ๋Ÿ‰ ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
# ํ•œ๊ตญ์–ด ์š”์•ฝ์— ํŠนํ™”๋œ ๋ชจ๋ธ์„ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.
try:
summarizer = pipeline("summarization", model="gogamza/kobart-summarization")
except Exception as e:
print(f"๋ชจ๋ธ ๋กœ๋”ฉ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {e}")
summarizer = None
# Gradio 4.x์— ๋งž์ถฐ ํ•จ์ˆ˜ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.
# progress ์ธ์ž๋ฅผ ํƒ€์ž… ํžŒํŠธ๋กœ ๋ฐ›์Šต๋‹ˆ๋‹ค.
def generate_blog_post(api_key: str, file1: IO, file2: IO, file3: IO, progress: gr.Progress):
"""
3๊ฐœ์˜ ํ…์ŠคํŠธ ํŒŒ์ผ์„ ์ž…๋ ฅ๋ฐ›์•„ ์š”์•ฝํ•˜๊ณ , Gemini API๋ฅผ ํ†ตํ•ด ๋ธ”๋กœ๊ทธ ๊ธ€์„ ์ƒ์„ฑํ•˜๋Š” ํ•จ์ˆ˜
"""
# 1. ์ž…๋ ฅ ๊ฐ’ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ
if not api_key:
raise gr.Error("Google API ํ‚ค๋ฅผ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.")
if not (file1 and file2 and file3):
raise gr.Error("3๊ฐœ์˜ ํ…์ŠคํŠธ ํŒŒ์ผ์„ ๋ชจ๋‘ ์—…๋กœ๋“œํ•ด ์ฃผ์„ธ์š”.")
if not summarizer:
raise gr.Error("์š”์•ฝ ๋ชจ๋ธ์„ ๋กœ๋“œํ•˜๋Š” ๋ฐ ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค. ์•ฑ ๋กœ๊ทธ๋ฅผ ํ™•์ธํ•ด ์ฃผ์„ธ์š”.")
try:
# 2. Google Gemini API ์„ค์ •
progress(0.1, desc="Google API ํ‚ค ์„ค์ • ์ค‘...")
genai.configure(api_key=api_key)
# 3. ํ…์ŠคํŠธ ํŒŒ์ผ ์ฝ๊ธฐ
progress(0.2, desc="ํ…์ŠคํŠธ ํŒŒ์ผ ์ฝ๋Š” ์ค‘...")
texts = []
# Gradio 4.x์—์„œ File ๊ฐ์ฒด๋Š” ์ž„์‹œ ํŒŒ์ผ ๊ฒฝ๋กœ๋ฅผ name ์†์„ฑ์œผ๋กœ ๊ฐ€์ง‘๋‹ˆ๋‹ค.
files = [file1, file2, file3]
for f in files:
with open(f.name, 'r', encoding='utf-8') as file:
texts.append(file.read())
# 4. ํ—ˆ๊น…ํŽ˜์ด์Šค ๋ชจ๋ธ๋กœ ๊ฐ ํ…์ŠคํŠธ ์š”์•ฝ
summaries = []
for i, text in enumerate(texts):
progress(0.3 + i * 0.1, desc=f"๋ฌธ์„œ {i+1} ์š”์•ฝ ์ค‘...")
summary = summarizer(text, max_length=200, min_length=50, do_sample=False)
summaries.append(summary[0]['summary_text'])
# 5. Gemini API๋กœ ์ƒˆ๋กœ์šด ๊ธ€ ์ƒ์„ฑ
progress(0.6, desc="Gemini API๋กœ ๋ธ”๋กœ๊ทธ ์•„์›ƒ๋ผ์ธ ์ƒ์„ฑ ์ค‘...")
model = genai.GenerativeModel('gemini-1.5-flash-latest')
summaries_str = "\n".join([f"- ์š”์•ฝ {i+1}: {s}" for i, s in enumerate(summaries)])
prompt = f"""
๋‹น์‹ ์€ IT ์ „๋ฌธ ๋„ค์ด๋ฒ„ ๋ธ”๋กœ๊ฑฐ์ž…๋‹ˆ๋‹ค. ์•„๋ž˜ 3๊ฐœ์˜ ์š”์•ฝ๋ฌธ์„ ์ฐธ๊ณ ํ•˜์—ฌ, ๋…์ž๋“ค์˜ ํฅ๋ฏธ๋ฅผ ๋Œ ์ˆ˜ ์žˆ๋Š” ๋ธ”๋กœ๊ทธ ๊ธ€์„ ์ž‘์„ฑํ•ด ์ฃผ์„ธ์š”.
**์ž‘์„ฑ ์กฐ๊ฑด:**
1. ๋จผ์ € ๊ธ€์˜ ์ „์ฒด์ ์ธ '์•„์›ƒ๋ผ์ธ'์„ ์„œ๋ก , ๋ณธ๋ก , ๊ฒฐ๋ก  ํ˜•์‹์œผ๋กœ ๋ช…ํ™•ํ•˜๊ฒŒ ์ œ์‹œํ•ด ์ฃผ์„ธ์š”.
2. ๊ทธ ๋‹ค์Œ, ์œ„์—์„œ ์ œ์‹œํ•œ ์•„์›ƒ๋ผ์ธ์— ๋งž์ถฐ์„œ ์ „์ฒด ๊ธ€์„ ์ž‘์„ฑํ•ด ์ฃผ์„ธ์š”.
3. ๋„ค์ด๋ฒ„ ๋ธ”๋กœ๊ทธ ์Šคํƒ€์ผ์— ๋งž๊ฒŒ ์นœ๊ทผํ•˜๊ณ  ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์šด ์–ดํˆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ์ ์ ˆํžˆ ์ด๋ชจ์ง€๋ฅผ ์‚ฌ์šฉํ•ด ์ฃผ์„ธ์š”.
4. SEO๋ฅผ ๊ณ ๋ คํ•˜์—ฌ '์ธ๊ณต์ง€๋Šฅ', 'AI ๊ธฐ์ˆ ', '๋ฏธ๋ž˜ ์‚ฌํšŒ', 'ํ—ˆ๊น…ํŽ˜์ด์Šค', 'Gemini API'์™€ ๊ฐ™์€ ํ‚ค์›Œ๋“œ๋ฅผ ๋ณธ๋ฌธ์— ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํฌํ•จ์‹œ์ผœ ์ฃผ์„ธ์š”.
5. ์ „์ฒด ๊ธ€์ž ์ˆ˜๋Š” ๊ณต๋ฐฑ ํฌํ•จ 3,000์ž ๋‚ด์™ธ๋กœ ๋งž์ถฐ์ฃผ์„ธ์š”.
6. ๊ฒฐ๊ณผ๋Š” ๋งˆํฌ๋‹ค์šด ํ˜•์‹์œผ๋กœ ๊น”๋”ํ•˜๊ฒŒ ์ •๋ฆฌํ•ด์„œ ๋ณด์—ฌ์ฃผ์„ธ์š”.
**[์ฐธ๊ณ ํ•  ์š”์•ฝ๋ฌธ]**
{summaries_str}
**[๊ฒฐ๊ณผ ์ถœ๋ ฅ ํ˜•์‹]**
# [๋ธ”๋กœ๊ทธ ์ œ๋ชฉ]
## ๐Ÿ“ ์•„์›ƒ๋ผ์ธ
- **์„œ๋ก **: ...
- **๋ณธ๋ก **: ...
- **๊ฒฐ๋ก **: ...
---
## โœ๏ธ ์™„์„ฑ๋œ ๋ธ”๋กœ๊ทธ ๊ธ€
(์—ฌ๊ธฐ์— ์™„์„ฑ๋œ ๊ธ€์„ ์ถœ๋ ฅ)
"""
progress(0.8, desc="Gemini API๋กœ ์ตœ์ข… ๋ธ”๋กœ๊ทธ ๊ธ€ ์ƒ์„ฑ ์ค‘...")
response = model.generate_content(prompt)
progress(1.0, desc="์™„๋ฃŒ!")
return response.text
except Exception as e:
raise gr.Error(f"์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {e}")
# Gradio ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌ์„ฑ
with gr.Blocks(theme=gr.themes.Soft()) as demo:
gr.Markdown(
"""
# ๐Ÿค– AI ๊ธฐ๋ฐ˜ ๋„ค์ด๋ฒ„ ๋ธ”๋กœ๊ทธ ํฌ์ŠคํŒ… ์ž๋™ ์ƒ์„ฑ
3๊ฐœ์˜ ํ…์ŠคํŠธ ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•˜๊ณ  Google API ํ‚ค๋ฅผ ์ž…๋ ฅํ•˜๋ฉด, AI๊ฐ€ ํŒŒ์ผ ๋‚ด์šฉ์„ ๋ถ„์„ํ•˜๊ณ  ์š”์•ฝํ•˜์—ฌ ๋„ค์ด๋ฒ„ ๋ธ”๋กœ๊ทธ ํ˜•์‹์˜ ์ƒˆ๋กœ์šด ๊ธ€์„ ๋งŒ๋“ค์–ด ๋“œ๋ฆฝ๋‹ˆ๋‹ค.
"""
)
with gr.Row():
with gr.Column(scale=1):
api_key = gr.Textbox(
label="Google API ํ‚ค",
placeholder="์—ฌ๊ธฐ์— Google API ํ‚ค๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”.",
type="password",
lines=1
)
file1 = gr.File(label="ํ…์ŠคํŠธ ํŒŒ์ผ 1")
file2 = gr.File(label="ํ…์ŠคํŠธ ํŒŒ์ผ 2")
file3 = gr.File(label="ํ…์ŠคํŠธ ํŒŒ์ผ 3")
generate_btn = gr.Button("๐Ÿš€ ๋ธ”๋กœ๊ทธ ๊ธ€ ์ƒ์„ฑํ•˜๊ธฐ", variant="primary")
with gr.Column(scale=2):
output_text = gr.Markdown(label="โœจ ์ƒ์„ฑ๋œ ๋ธ”๋กœ๊ทธ ๊ธ€")
generate_btn.click(
fn=generate_blog_post,
inputs=[api_key, file1, file2, file3],
outputs=output_text
)
gr.Markdown(
"""
---
**์‚ฌ์šฉ ๋ฐฉ๋ฒ•:**
1. [Google AI Studio](https://aistudio.google.com/app/apikey)์—์„œ API ํ‚ค๋ฅผ ๋ฐœ๊ธ‰๋ฐ›์•„ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.
2. ์ฃผ์ œ๊ฐ€ ์œ ์‚ฌํ•œ 3๊ฐœ์˜ ํ…์ŠคํŠธ ํŒŒ์ผ(.txt)์„ ๊ฐ๊ฐ ์—…๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.
3. '๋ธ”๋กœ๊ทธ ๊ธ€ ์ƒ์„ฑํ•˜๊ธฐ' ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๊ณ  ์ž ์‹œ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.
4. ์˜ค๋ฅธ์ชฝ ์ฐฝ์— ์ƒ์„ฑ๋œ ๊ธ€์˜ ์•„์›ƒ๋ผ์ธ๊ณผ ์ตœ์ข… ๊ฒฐ๊ณผ๋ฌผ์ด ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.
"""
)
if __name__ == "__main__":
demo.launch()