jju71 님의 블로그

AI 광고 문구 생성 앱 본문

Python/FastAPI

AI 광고 문구 생성 앱

jju71 2026. 7. 29. 09:08

실행

server : uvicorn 19_server:app --reload
client : python 19_client.py

 

.env

OPENAI_API_KEY=sk-proj-P9tdGUne25JLu65aXfzwXoz9FDfrL1-4vjZGuQVALMZLmqu_mc8ikce7H5RIBEEWhYR1WpWw
ECT3BlbkFJBgKSD8KfZaQWp2ZuM-PfIg-GwcKONR-olXrD90OwnYZM3CHiH9EDNRDQU-NETYfwWXIlVhZFQA
DB_URL=mongodb+srv://JJU:Chojyung1219!@cluster0.qnwmj2q.mongodb.net/?appName=Cluster0
AD_API_URL=http://127.0.0.1:8000/create_ad

 

server.py

import os
from dotenv import load_dotenv
from pymongo import MongoClient, DESCENDING
from openai import OpenAI
from pydantic import BaseModel, Field 
# BaseModel은 JSON의 틀(스키마)를 생성
from typing import List  # 타입지정
from fastapi import FastAPI, HTTPException
from pymongo.errors import PyMongoError

load_dotenv()

OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
DB_URL = os.getenv("DB_URL")

client = OpenAI(api_key=OPENAI_API_KEY)

mongo_client = MongoClient(DB_URL, serverSelectionTimeoutMS=5000)
# 5초 동안 연결되지 않으면 에러 (5000=5초)

database = mongo_client['ai']
collection = database['ad']

class ProductRequest(BaseModel):
    product_name: str = Field(min_length=1, max_length=100, description="광고할 제품 이름")
    details: str = Field(min_length=1, max_length=1000, description="제품의 주요 특징과 설명")
    tone_and_manner: str = Field(min_length=1, max_length=200, description="광고 문구의 분위기와 스타일")

class AdData(BaseModel):
    product_name: str
    details : str
    tone_and_manner: str
    ad: str

class AdResponse(BaseModel):
    ad: str
    datas: List[AdData]

# 광고 문구
class AdGenerator: 
    def __init__(self, model: str = "gpt-5-nano"):
        self.model = model

    def using_llm(self, prompt: str) -> str:
        developer_instruction = """
        당신은 전문 광고 카피라이터입니다.

        사용자가 제공한 제품 이름, 주요 내용, 광고 문구 스타일을 분석하여 자연스럽고 기억하기 쉬운 한국어 광고 문구를 작성하세요.

        다음 규칙을 반드시 지키세요.
        1. 광고 문구는 한 문장으로 작성합니다.
        2. 제품의 특징이 문구에 반영되어야 합니다.
        3. 사용자가 지정한 분위기와 스타일을 반영합니다.
        4. 지나치게 허위이거나 검증되지 않은 효과는 단정하지 않습니다.
        5. 설명, 제목, 따옴표 없이 광고 문구만 출력합니다.
""".strip()

        try:
            response = client.responses.create(
                model=self.model,
                input=[
                    {
                        "role" : "developer",
                        "content": developer_instruction
                    },
                    {
                        "role" : "user",
                        "content" : prompt
                    }
                ],
                reasoning={"effort":"low"},
                max_output_tokens=1000
            )
            result = response.output_text.strip()
            if not result:
                raise ValueError("모델이 빈 응답을 반환했습니다.")
            return result

        except Exception as e:
            print(f"API 오류: {e}")
            raise HTTPException(
                status_code=502,
                detail='광고 문구 생성 중 AI 서버 오류가 발생했습니다.'
            ) from e

    def generate(self, product_name: str, details: str, tone_and_manner: str) -> str:
        prompt = f"""
        제품 이름: {product_name}
        제품 주요 내용: {details}
        광고 문구 스타일: {tone_and_manner}

        위 정보를 바탕으로 광고 문구를 한 문장으로 작성하세요
        """.strip()
        return self.using_llm(prompt)

ad_generator = AdGenerator()
app = FastAPI(title="AI 광고 문구 생성 API", description="GPT 모델과 MongoDB를 이용한 광고 문구 생성 API", version="1.0.0")

@app.get("/")
def root():
    return { "message": "AI 광고 문구 생성 API가 실행 중입니다." }

@app.post("/create-ad", response_model=AdResponse)
def create_ad(product: ProductRequest):
    generated_ad = ad_generator.generate(
        product_name=product.product_name, 
        details=product.details, 
        tone_and_manner=product.tone_and_manner
    )
    document = {
        "product_name" : product.product_name,
        "details" : product.details,
        "tone_and_manner": product.tone_and_manner,
        "ad": generated_ad
    }
    try:
        collection.insert_one(document)
        cursor = (
            collection.find({}, {"_id": 0})
            .sort("_id", DESCENDING)
            .limit(20)
        )
        datas = list(cursor)

    except PyMongoError as e:
        raise HTTPException(
            status_code=503,
            detail="광고 문구 저장 중 데이터베이스 오류가 발생했습니다."
        ) from e

    # 보내주기
    return {
        "ad" : generated_ad,
        "datas" : datas
    }

 

Client

import os
import gradio as gr
# 서버 연결
import requests
from dotenv import load_dotenv

load_dotenv()

API_URL = os.getenv("AD_API_URL")

def generate_ad(product_name, details, tone_and_manner):
    product_name = (product_name or "").strip()   # 객체로 받아옴
    details = (details or "").strip()
    tone_and_manner = tone_and_manner or []

    if not product_name:
        return "제품 이름을 입력하세요", []
    if not details:
        return "제품의 주요 내용을 입력하세요", []
    if not tone_and_manner:
        return "광고 문구의 느낌을 한개 이상 선택하세요", []

    request_data = {
        "product_name": product_name,
        "details": details,
        "tone_and_manner": ",".join(tone_and_manner) # 값 사이에 ,를 넣어줌
    }

    # 통신 태우기
    try:
        response = requests.post(API_URL, json=request_data, timeout=60)
        response.raise_for_status()
        result = response.json()

        ad = result.get("ad", "")
        datas = result.get("datas", []) # 없다면 빈 리스트를 넣어줌

        if not ad:
            return "서버에서 광고 문구를 받지 못했습니다"

        processed_datas = [
            [
                data.get("product_name", ""), 
                data.get("details", ""),
                data.get("tone_and_manner", ""),
                data.get("ad", "")
            ] for data in datas
        ]
        return ad, processed_datas

    except requests.exceptions.ConnectionError:
        return "FastAPI 서버에 연결할 수 없습니다"
    except requests.exceptions.Timeout:
        return "서버의 응답 시간이 초과되었습니다"
    except requests.exceptions.HTTPError as e:
        try:
            error_data = e.response.json()
            detail = e.get("detail", "서버 요청 처리 중 오류가 발생했습니다")
        except ValueError:
            detail = "서버 요청 처리 중 오류가 발생했습니다"
        return f'서버 오류: {detail}'
    except Exception as e:
        print(f'알 수 없는 오류: {e}')


# 화면 구성
with gr.Blocks(title="AI 광고 문구 생성기") as demo:
    gr.Markdown(
    """
    # AI 광고 문구 생성기
    제품의 이름과 주요 특징을 입력하고 원하는 광고 분위기를 선택하세요.
    AI가 입력 내용을 분석하여 한 문장의 광고 문구를 생성합니다.
    """
    )
    with gr.Row():
        product_input = gr.Textbox(label="제품 이름", placeholder="제품 이름을 입력하세요")
        details_input = gr.Textbox(label="주요 내용", placeholder="제품의 특징과 장점을 입력하세요")

    tone_options = gr.CheckboxGroup(label="광고 문구의 느낌",
                                    choices = ["재밌게", '과장스럽게', '참신하게', '고급스럽게', '센스있게', '신선하게', '전문성있게'], value = ["참신하게"])
    generate_button = gr.Button("광고 문구 생성하기", variant="primary")
    output_ad = gr.Textbox(label="생성된 광고 문구", lines=3, interactive=False)
    output_table = gr.DataFrame(label="최근 생성 데이터", headers=["제품 이름", "주요 내용", '광고 문구의 느낌', '생성된 광고 문구'], datatype=["str", 'str', 'str', 'str'], wrap=True, interactive=False) # 표처럼 보이게 해줌

    generate_button.click(fn=generate_ad, inputs=[product_input, details_input, tone_options], outputs=[output_ad, output_table])

    demo.launch()

'Python > FastAPI' 카테고리의 다른 글

번역 앱 예제  (0) 2026.07.28
Gradio  (0) 2026.07.27
GPT API  (0) 2026.07.27
Fast API  (0) 2026.07.27