生成AIによるパーソナル広告の可能性を探ってみる

## はじめに

　どっかの偉い人「今のウェブ広告はな、クラスター分析でえらいこっちゃにグループ分けされてんねん。ほんでそのグループにぴったりの広告がドンピシャで出るようになってるわけや。それがな、生成AIがめっちゃ発達することで、あんたのちょっとした特徴をつかんで、その場でサクッとあんたに合う広告をぶち込むようになるんやで。」
 (文章はCHatGPTで胡散臭い関西弁風にしてもらいました。)

　多分、どこかの飲み会で聞いた話なので、誰が言ったのかは覚えてません。もしかしたら、この事を言った人なんてこの世に存在しないかもしれません。そして私は広告とは全く関係のない業界にいます。


## ChatGPT-4oで作ってみる

　現状の生成AIでどこまでパーソナル広告を実現できるのかChatGPT-4oでちょっと探ってみたいと思います。Chat-GPTのサイトでプロンプトを打ってもいいのですが、[前回の記事](https://qiita.com/miso_taku/items/559f771b5b259a2f7bd7)でChatGPT APIを叩くアプリをGradio作ったので、それをちょっと改良して使います。軽く試したいだけなので、ターゲットの選択は性別と年齢のみにしています。

 
## 準備

　前回の記事同様、openai, gradioあたりをpipでインストールしておいてください。あと、前回の記事で記載するの忘れてましたが、OpenAI APIが利用できるようにアカウントを作成してください。


## ソースコード

　ソースコードは以下になります。secret.jsonに取得したAPIキーを入れてください。OSの環境変数から読み込みたい人は適宜ソースコードを修正してください。

```secret.json
{
    "OPENAI_API_KEY": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
```

　pythonコードはこちらです。

```gr_gpt4o_image_and_text.py
# gradioでChatGPTを使って商品の広告画像とコピーを生成するプログラム
import json
import requests
from io import BytesIO
from PIL import Image

import gradio as gr
from openai import OpenAI


SYSTEM_ROLE_CONTENT = "このシステムは商品とその特徴から、特定のターゲット（年齢、性別）を対象とした商品の広告コピーを作成します。"


def get_gpt_openai_apikey():
    with open("secret.json") as f:
        secret = json.load(f)
    return secret["OPENAI_API_KEY"]


def create_message(system_role, prompt):
    """ChatGPTのメッセージ形式に変換する。"""
    message = [
        {
            'role': 'system',
            'content': system_role
        },
        {
            'role': 'user',
            'content': [
                {
                    'type': 'text',
                    'text': prompt
                }
            ]
        }
    ]
    return message


def generate_product_ad_image_prompt(product_name, feature, age, gender):
    """入力された商品名、特徴、年齢から商品広告画像生成のプロンプトを返す。"""
    return (
        f"商品名: {product_name}\n"
        f"特徴: {feature}\n"
        f"ターゲット年齢: {age}\n"
        f"性別: {gender}\n"
        "この情報を元に広告画像を生成してください。画像内には文字を載せず写真のような画像のみにしてください。"
    )


def generate_product_ad_copy_prompt(product_name, feature, age, gender):
    """入力された商品名、特徴、年齢、性別から商品コピーを生成させるプロンプトを返す。"""
    return (
        f"商品名: {product_name}\n"
        f"特徴: {feature}\n"
        f"ターゲット年齢: {age}\n"
        f"性別: {gender}\n"
        "この情報を元に商品広告コピーを生成してください。応答は生成したコピーのみとしてください。"
    )


def download_image(url, save_path):
    """画像をダウンロードして保存する。"""
    try:
        response = requests.get(url)
        response.raise_for_status()  # エラーが発生した場合は例外を投げる
        image = Image.open(BytesIO(response.content))
        image.save(save_path)
    except requests.exceptions.RequestException as e:
        print(f"リクエストエラー: {e}")
    except IOError as e:
        print(f"画像の保存エラー: {e}")


def generate_content(product_name, feature, age, gender):
    """" 商品名、特徴、年齢、性別から商品広告のコピーと画像を生成する"""
    openai_client = OpenAI(api_key=get_gpt_openai_apikey())


    text_prompt = generate_product_ad_copy_prompt(product_name, feature, age, gender)
    messages = create_message(SYSTEM_ROLE_CONTENT, text_prompt)
    # テキスト生成
    text_response = openai_client.chat.completions.create(
        model='gpt-4o-2024-05-13',
        messages = messages,
        temperature = 0.1,
    )
    generated_text = text_response.choices[0].message.content


    image_prompt = generate_product_ad_image_prompt(product_name, feature, age, gender)

    # 画像生成
    image_response = openai_client.images.generate(
        model="dall-e-3",
        prompt=image_prompt,
        quality="standard",
        size="1024x1024",
        n=1
    )
    image_url = image_response.data[0].url
    download_image(image_url, "image.jpg")
    image = Image.open("image.jpg")

    return image, generated_text


def main():
    iface = gr.Interface(
        title="CHatGPTによる商品広告生成",
        fn=generate_content,
        inputs=[
                gr.Textbox(label="商品名"),
                gr.Textbox(label="特徴"),
                gr.Radio(label="年齢", choices=["10代", "20代", "30代", "40代", "50代", "60代以上"]),
                gr.Radio(label="性別", choices=["男性", "女性"])
                ],
        outputs=[
                  gr.Image(label="広告画像", type="pil"),
                  gr.Textbox(label="コピー")
                ]
        )
    iface.launch()


if __name__ == "__main__":
    main()  
```

## アプリの起動
　ターミナルより以下を実行
```
python gr_gpt4o_image_and_test.py
```

　出力されたURLにブラウザでアクセスすると以下の画面が出ます。

![スクリーンショット 2024-05-18 164638.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350321/2b98a1f5-a95e-92ae-5501-19d23f4d51cf.png)


　ここで商品名と特徴を入力し、年齢と性別を選択してSubmitボタンを押します。

## 実行結果

　商品は「コーヒー」、特徴は「柔らかな酸味と滑らかな口当たり」で40代男性、10代女性で広告を生成してみたいと思います。


 ### 40代男性

![スクリーンショット 2024-05-19 155407.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350321/04ca1b79-7782-0a9e-cac3-4647541623a2.png)

 ### 10代女性

![スクリーンショット 2024-05-19 155506.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350321/535f8fa0-0ba9-b72a-8c33-42e8fcbbe2df.png)


## おわりに

　ChatGPTとgradioでパーソナル広告をちょっと試してみました。私の印象としては生成された広告のクオリティはそこまで高くないし、現状実行時間も20秒くらいかかっているので、リアルタイムでパーソナル広告を生成するのはもう少し先になるかなとは思います。今後の生成AIの発展に期待ですね。