Mac って何?それって美味しいの?

マイコンと呼ばれた時代から現在まで、使用記から何から何でも。

Macで動作するメッセージアプリ風AIチャットアプリを作りました!

Macローカルで動作する恋愛AIチャットアプリ

このガイドでは、Mac上で恋愛チャットアプリをローカルで実行する手順を紹介します。キャラクターとLINE風のチャットを楽しみながら、AIによるメッセージや自撮り写真のやり取りが可能です。

美咲

1. 必要な環境

本アプリを動作させるには、以下の環境が必要です。

  • macOS
  • Python 3.9 以上
  • Ollama(ローカルでLLMを動作させる)
  • Diffusers(Stable Diffusion を使用)
  • Gradio(Web UIを構築)

2. 必要なツールのインストール

2.1 Python のインストール

Mac にはデフォルトで Python がインストールされていますが、python3 --version で確認し、3.9 以上でない場合は 公式サイト から最新バージョンをインストールしてください。

2.2 仮想環境の作成(推奨)

python3 -m venv chat_env
source chat_env/bin/activate

2.3 必要なPythonパッケージのインストール

pip install gradio diffusers torch ollama

3. Ollama のインストール

公式サイト Ollama からダウンロードし、インストールしてください。

その後、ollama run llama3:8b を実行して動作確認を行います。

4. Stable Diffusion の準備

お好みのSD1.5モデルファイルを使用できます。

sazyou-roukaku/chilled_remix at main 今回はこちらをお借りしました。

latent-consistency/lcm-lora-sdv1-5 at main LCM Loraダウンロード先

設置場所に合わせてchat_app.py中のモデルファイルパスを変更することを忘れずに。

5. アプリの構築

配置先:

/renaichat/
│── chat_app.py
│── generated_images/  # 画像ファイルを保存するフォルダ(自動作成)

5.1 バックエンド (chat_app.py)

次の内容で chat_app.py を作成します。

モデルファイルのパスは実行環境に合わせて変更してください。

import gradio as gr
import os
import time
import random
from datetime import datetime
import ollama
import torch
from diffusers import StableDiffusionPipeline, LCMScheduler

# キャラの好感度管理
character_affection = {
    "美咲": 0,
    "花音": 0,
    "涼夏": 0
}

# キャラ設定
character_settings = {
    "美咲": {"性格": "美人で優しい女性。面倒見が良く、癒し系。",
           "BIRTHDAY": "05-20",
           "PROMPT_CHAR": "a Japanese beauty woman, Light brown Long hair (wavey, glamorous style). ",
           "PROMPT_WEAR": "wearing a fitted white long sleeves ribbed top and a grey plaid suspenders overalls Dress. "},
    "花音": {"性格": "可愛くて明るいムードメーカー。元気いっぱいで好奇心旺盛。",
           "BIRTHDAY": "08-07",
           "PROMPT_CHAR": "a kawaii woman, loose curls twin tails Semi-long Hair. ",
           "PROMPT_WEAR": "wearing a white collared shirt, a red plaid pleated skirt, a plaid bow, a soft pink cardigan, knee-high white socks. "},
    "涼夏": {"性格": "クールでツンデレ。素直になれないが、時折見せる優しさが魅力。",
           "BIRTHDAY": "11-15",
           "PROMPT_CHAR": "a Japanese idol woman, Short bob Hair. ",
           "PROMPT_WEAR": "wearing a ivory long hoodie. "},
}

# メッセージ履歴
chat_history = []

# Stable Diffusionの準備
#diffusion_model = StableDiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5")
#diffusion_model.to("cuda" if torch.cuda.is_available() else "cpu")

# デバイス設定
device = "mps" if torch.backends.mps.is_available() else "cpu"

# モデルファイルのパス
PIPELINE_PATH = "/pass/to/chilled_remix_v2.safetensors"
LORA_PATH = "/pass/to/pytorch_lora_weights_SD15.safetensors"

# **Diffusers の初期化**
#pipe = StableDiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5", torch_dtype=torch.float16).to(device)
pipe = StableDiffusionPipeline.from_single_file(PIPELINE_PATH, torch_dtype=torch.float16).to(device)
pipe.load_lora_weights(LORA_PATH)
pipe.scheduler = LCMScheduler.from_config(pipe.scheduler.config)

def generate_selfie(character, scene):
    if scene == "":
        scene_prompt = character_settings[character]['PROMPT_WEAR']
    else:
        scene_prompt = scene

    """キャラの自撮り写真を生成"""
    prompt = f"{character_settings[character]['PROMPT_CHAR']} {scene_prompt}, taking a selfie, looking at camera, realistic, detailed, beautiful lighting"
    image = pipe(prompt, height=512, width=384, num_inference_steps=8, guidance_scale=1.0).images[0]  # **画像生成**

    print("自撮り写真プロンプト:", prompt)

    # 画像保存ディレクトリの作成
    save_dir = "./generated_images"
    os.makedirs(save_dir, exist_ok=True)

    # 画像を保存(Gradio で扱いやすいパスに)
    timestamp = int(time.time())  # **現在のタイムスタンプ**
    image_path = os.path.join(save_dir, f"{character}_selfie_{timestamp}.png")
    image.save(image_path)
    return image_path

def chat_response(user_message, character):
    """Ollama を使用してユーザーのメッセージに対するキャラの返信を生成"""
    global chat_history, character_affection
    now = datetime.now()
    datetime_str = now.strftime("%Y-%m-%d(%a) %H:%M")
    
    # 好感度アップの条件
    if "好き" in user_message or "かわいい" in user_message:
        character_affection[character] += 1
    
    # 自撮り写真リクエストの処理
    if "写真を送って" in user_message:
        # Ollama による応答生成
        prompt = f"あなたは{character}(性格:{character_settings[character]["性格"]})という名前のキャラクターです。チャット内容と日時から場所や場面を想像して、{character}の服装や場所を伝える英語の簡潔なメッセージを30語以内で作成してください。(現在の日時:{datetime_str})\n\nユーザー: {user_message}\n{character}: "

        try:
            response = ollama.chat(model="llama3:8b", messages=[{"role": "user", "content": prompt}])
            scene_text = response["message"]["content"].strip()
        except Exception as e:
            scene_text = f"エラーが発生しました: {str(e)}"

        image_path = generate_selfie(character, scene_text)
        chat_history.append((user_message, (image_path,)))  # 画像をタプルで追加
        return chat_history[-10:]
    
    # Ollama による応答生成
    prompt = f"あなたは{character}(性格:{character_settings[character]["性格"]})という名前のキャラクターです。日時から場所や場面を想像してユーザーとの自然なチャットを日本語で行ってください。生成したメッセージが日本語でない場合は、日本語になるまでメッセージを再生成してください。(現在の日時:{datetime_str})\n\nユーザー: {user_message}\n{character}: "
    
    try:
        response = ollama.chat(model="llama3:8b", messages=[{"role": "user", "content": prompt}])
        reply_text = response["message"]["content"].strip()
    except Exception as e:
        reply_text = f"エラーが発生しました: {str(e)}"
    
    print("プロンプト:", prompt)
    print("生成結果:", reply_text)
    
    chat_history.append((user_message, reply_text))
    return chat_history[-10:]

# Gradio UIの設定
gr_theme = gr.themes.Soft(
    primary_hue="pink",
    secondary_hue="rose",
    neutral_hue="gray",
    font=["Arial", "sans-serif"]
).set(
    body_background_fill="#ffe4e1"  # 全体の背景色(恋愛ゲーム風)
    #body_background_fill_dark="#ffccd5"  # ダークモード時の背景色
)

# Gradio UIの構築
def chat_interface():
    #with gr.Blocks(css=".gradio-container { background-color: #ffe4e1 !important; } .chatbot .user { background-color: #ffccdd !important; } .chatbot .bot { background-color: #ffffff !important; }") as demo:
    with gr.Blocks(theme=gr_theme) as demo:
        gr.Markdown("## 📱 恋愛チャットシミュレーション")
        
        with gr.Row():
            character_select = gr.Radio(["美咲", "花音", "涼夏"], label="キャラ選択", value="美咲")
        
        chatbot = gr.Chatbot(label="Chat")
        user_input = gr.Textbox(placeholder="メッセージを入力...", interactive=True)
        send_button = gr.Button("送信")
        
        def update_chat(user_message, character):
            chat_result = chat_response(user_message, character)
            return chat_result, ""
        
        user_input.submit(update_chat, [user_input, character_select], [chatbot, user_input], queue=False)
        send_button.click(update_chat, [user_input, character_select], [chatbot, user_input], queue=False)
    
    return demo

chat_interface().launch(share=True)

6. アプリの実行

準備が整ったら、次のコマンドでアプリを実行します。

python3 chat_app.py

または、仮想環境を有効にしている場合は:

source chat_env/bin/activate
python3 chat_app.py

実行後、http://127.0.0.1:7860/ にアクセスし、チャットを楽しんでください。

「写真を送って」をメッセージに含めると、彼女が自撮り写真を送ってくれます。

花音

涼夏


7. トラブルシューティング

7.1 Ollama が認識されない

ollama コマンドが見つからない場合、ターミナルを再起動し、ollama list を試してください。

7.2 画像が表示されない

  • generated_images ディレクトリが作成されているか確認してください。
  • Gradio の仕様上、ファイルパスが適切でないとエラーが出るため、アプリ実行フォルダ内に画像を保存するように修正してください。

7.3 Python のパッケージが足りない

エラーメッセージを確認し、不足しているパッケージを pip install <パッケージ名> でインストールしてください。

8. まとめ

これで、Mac ローカルで恋愛チャットアプリを実行する準備が整いました。AIキャラクターとの会話や自撮り写真のやり取りを楽しんでください!