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

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

Windows 10 で Wi-Fi と有線 LAN の両方を接続しつつ、デフォルトゲートウェイを有線 LAN に設定する簡単な方法

Windows 10 で Wi-Fi と有線 LAN の両方を接続しつつ、デフォルトゲートウェイを有線 LAN に設定する簡単な方法は、ネットワークインターフェースのメトリック値を調整すること です。

手順:

  1. [ネットワーク接続] を開く
    Win + R を押して ncpa.cpl と入力し、Enter を押す。

  2. 有線 LAN(イーサネット)のプロパティを開く

  3. IPv4 の設定を変更

    • 「インターネット プロトコル バージョン 4(TCP/IPv4)」を選択し、「プロパティ」をクリック。

    • 「詳細設定」を開く。

  4. 自動メトリックをオフにして手動設定

    • 「自動メトリック」のチェックを外し、「インターフェイス メトリック」に 10 などの小さい値を入力。

  5. Wi-Fi のメトリックを変更

    • 同様に「Wi-Fi」のプロパティを開き、IPv4 の「詳細設定」で「インターフェイス メトリック」を 20 などの大きな値に変更。

  6. 設定を適用して再接続

    • すべてのウィンドウで「OK」を押して設定を保存し、ネットワークを再接続する。

効果:

この方法なら、簡単な設定変更で デフォルトゲートウェイを有線に固定 できます。

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キャラクターとの会話や自撮り写真のやり取りを楽しんでください!

Let's Encryptを利用したWindows IISでの無料HTTPS証明書取得手順

Windows IISLet's Encrypt を利用して HTTPS を有効にする手順を説明します。
Let's Encrypt は 無料のSSL証明書 を発行でき、自動更新も可能です。

 

 


1. 必要なツールの準備

Windows IIS で Let's Encrypt を利用するには、win-acme というツールを使います。

🔹 win-acme のダウンロード

  1. win-acme 公式サイト にアクセス
  2. 「Download」から win-acme.v2.x.x.zip をダウンロード
  3. ダウンロードした ZIP を C:\win-acme などに展開

2. IISHTTPS 設定

  1. IIS マネージャー(inetmgr)を開く
  2. 左ペインで 対象のWebサイト を選択
  3. 右側の「バインドの編集」から HTTPS のバインドがない場合は追加
  4. 「閉じる」をクリック

3. Let's Encrypt 証明書の取得

  1. 管理者権限で PowerShell または コマンドプロンプト を開く

  2. cd C:\win-acme で win-acme のフォルダに移動

  3. 以下のコマンドを実行

    wacs.exe
    
  4. インタラクティブなセットアップが始まるので、順番に選択

    • N: Create new certificate (simple) を選択
    • 対象のWebサイト(IISのサイト名)を選択
    • 「yes」を選択して証明書を取得
  5. 証明書が正常に発行されると、IIS に自動で適用される


4. HTTPSリダイレクトの設定(オプション)

HTTP から HTTPS へ自動リダイレクトするには URLリライト を設定します。

方法1: IISの「HTTPリダイレクト」を使う

  1. IIS マネージャーで Webサイトを選択
  2. 「HTTP リダイレクト」 を開く
  3. 「要求をリダイレクトする」にチェックを入れ https://yourdomain.com を指定
  4. 「適用」をクリック

方法2: Web.config にリダイレクトルールを追加

C:\inetpub\wwwroot\web.config に以下を追加

<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <rule name="Redirect to HTTPS" stopProcessing="true">
                    <match url="(.*)" />
                    <conditions>
                        <add input="{HTTPS}" pattern="^OFF$" />
                    </conditions>
                    <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>

5. 自動更新の設定

Let's Encrypt の証明書は 90日ごとに更新が必要 ですが、win-acme で自動更新できます。

タスクスケジューラを使う

  1. タスクスケジューラ(taskschd.msc)を開く
  2. 「基本タスクの作成」で以下を設定
    • 名前: Let's Encrypt 更新
    • トリガー: 毎日
    • 開始時刻: 午前3時(任意)
    • 操作: プログラムの開始
    • プログラム/スクリプト: C:\win-acme\wacs.exe
    • 引数の追加: --renew --quiet
  3. 完了をクリックして保存

6. ファイアウォールとポートの確認


7. 動作確認

ブラウザで https://yourdomain.com にアクセスし、SSL が適用されていることを確認。
証明書の詳細を開き、「Let's Encrypt」と表示されていれば成功! 🎉


まとめ

ステップ 手順
1. win-acme をダウンロード win-acme をダウンロードして展開
2. IISHTTPS設定 IISHTTPSバインドを追加
3. 証明書取得 wacs.exe を実行して Let's Encrypt 証明書を取得
4. HTTPSリダイレクト IISの「HTTPリダイレクト」または Web.config を設定
5. 自動更新設定 タスクスケジューラで wacs.exe --renew を実行
6. ファイアウォール設定 ポート 443 を開放
7. 動作確認 https://yourdomain.com にアクセス

これで、Windows IIS で Let's Encrypt を利用した 無料のHTTPS環境 が構築できます! 🚀

MacOSローカルで動くシナリオ自動生成の恋愛ゲームを作成しました!

無人島サバイバル恋愛アドベンチャーゲームMacOSで動作させる手順

美咲

はじめに

本記事では、AIを活用してシナリオとシーン画像を自動生成する無人島サバイバル恋愛アドベンチャーゲーム「恋AIらんど -RenAIsland-」を、MacOS上に構築し動作させる手順を紹介します。

このゲームは、ストーリーおよびシーン画像を生成AIを活用して実行時に作成しています。3人の女性キャラクターとの、毎回異なる恋愛ストーリーを楽しめます。

1. 必要な環境の準備

今回使用したマシン

iMac Retina 4K 2017
CPU: Core i5
RAM: 8GB
GPU: Radeon Pro 560 4GB
OS: Ventura 13.6.7

1.1 Pythonのインストール

まずはPythonがインストールされていることを確認します。MacOSにはデフォルトでPythonが含まれていますが、最新バージョンを利用するためにHomebrewを使用してインストールします。

brew install python3

1.2 仮想環境の作成

作業フォルダを作成し、仮想環境を構築します。

mkdir renaisland
cd renaisland
mkdir static
mkdir templates
python3 -m venv venv
source venv/bin/activate

1.3 必要なライブラリのインストール

以下のパッケージをインストールします。

pip install flask torch diffusers pillow

1.4 Ollama のセットアップ

シナリオの分岐をAIで作るためにローカルのLLMを使用します。今回は一番手軽なOllamaで動かします。

公式サイト からダウンロード & インストール

日本語でシナリオ作成指示するので、日本語対応のモデルをダウンロードします。

ollama pull gemma:7b

または

ollama pull llama3:8b

使用するLLMに応じてapp.py中の1箇所を変更してください。

        # llama3:8b または gemma:7b
        print("シナリオ生成開始")
        result = subprocess.run(
            ["ollama", "run", "llama3:8b", prompt],
            capture_output=True,
            text=True
        )

1.5 StableDiffusionモデルファイル&LCM Loraダウンロード

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

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

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

花音

2. ゲームの構築

配置先:

/renaisland/
│── app.py
│── static/  # 画像ファイルを保存するフォルダ
│── templates/
│   └── index.html  # フロントエンド

2.1 バックエンド (app.py)

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

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

import re
import os
import time
import subprocess
import json
import random
import torch
from flask import Flask, render_template, request, jsonify, send_from_directory
from diffusers import StableDiffusionPipeline, LCMScheduler
from PIL import Image

app = Flask(__name__)

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

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

# **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)

# **シーンカウントの設定**
MAX_SCENES = 8  # **クライマックスに移行する指定回数**
scene_count = 0  # **現在のシーン数**
MAX_RETRIES = 5  # **シナリオ生成最大リトライ回数**

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

def generate_image(scene_text, scene_name, image_prompt):
    """Diffusers を使って画像を生成し、保存する"""
    image_path = f"static/{scene_name}.png"

    # **既存の画像があれば削除**
    if os.path.exists(image_path):
        os.remove(image_path)

    person_prompt = ""

    if "女性" in scene_text or "彼女" in scene_text:
        person_prompt = "(solo shot), Silhouette of a woman, "

    if "美咲" in scene_text:
        person_prompt = "(solo shot), " + person["美咲"]["PROMPT"]

    if "花音" in scene_text:
        person_prompt = "(solo shot), " + person["花音"]["PROMPT"]

    if "涼子" in scene_text:
        person_prompt = "(solo shot), " + person["涼子"]["PROMPT"]

    prompt = f"(SFW), realistic, {person_prompt}{image_prompt}, highly detailed."
    image = pipe(prompt, height=512, width=512, num_inference_steps=8, guidance_scale=1.0).images[0]  # **画像生成**
    image.save(image_path)  # **画像を保存**

    timestamp = int(time.time())  # **現在のタイムスタンプ**
    
    return f"{image_path}?t={timestamp}"  # **キャッシュを防ぐURLを返す**

# **最初のシナリオ**
story = {}
def static_story():
    global story

    start_text = f"""飛行機は突如エンジントラブルに見舞われ、見知らぬ海へと墜落した。奇跡的に生き残ったあなたは、無人島に漂着し、砂浜にもう一人の生存した女性を見つけた。
    その女性はー"""
    start_image_prompt = "A deserted tropical island beach with a crashed airplane. The wreckage is partially buried in the sand, surrounded by palm trees and ocean waves."
    start_image = generate_image(start_text, "start", start_image_prompt)  # **最初の画像を生成**

    story = {
        "start": {
            "text": start_text,
            "choices": {
                "美咲": "美咲",
                "花音": "花音",
                "涼子": "涼子"
            },
            "image_prompt": start_image_prompt,
            "image": start_image  # **生成した画像のパスを設定**
        }
    }
    return

static_story()

# **JSON の中から `text` の値を抽出し、改行のみをエスケープ**
def fix_json_string(json_text):
    match = re.search(r'("text":\s*")(.*?)(")', json_text, re.DOTALL)
    if match:
        fixed_text = match.group(2).replace("\n", "\\n")  # 改行のみエスケープ
        json_text = json_text[:match.start(2)] + fixed_text + json_text[match.end(2):]
    
    return json_text

def generate_story(scene, scene_name, pre_text):
    global scene_count
    scene_count += 1  # **シーン数を増やす**
    ending = ""

    if scene_name == "happy_end":
        ending = "ハッピーエンド"
    elif scene_name == "bad_end":
        ending = "バッドエンド"
    elif scene_name == "":
        scene_name = scene

    """シナリオを生成し、画像も生成する"""
    for attempt in range(MAX_RETRIES):  # **リトライ**
        # クライマックス前
        if scene_count == MAX_SCENES:
            prompt = f"""
            飛行機事故により無人島に漂着したプレイヤーと{heroine}の、サバイバルと恋愛を描くノベルゲームの、前回のストーリーに対するプレイヤーの選択の次の場面の「重大なことが起こるシーン」ストーリーを日本語で作成してください。(5文以内で)
            無人島でのサバイバル要素や、恋愛要素などを盛り込んでください。
            そして、そのシーンの背景画像を生成するためのプロンプトを英語で作成してください。(簡潔に)
            また、プレイヤーに提示する選択肢を2つ日本語で考えてください。

            前回のストーリー:{pre_text}
            プレイヤーの選択:{scene}
            {heroine}の性格:{person[heroine]["性格"]}

            出力フォーマット:
            ```
            {{"text": "ここに重大なことが起こるシーンのストーリー",
            "image_prompt": "ここに背景画像を生成するためのプロンプト",
            "choices": {{"scene_{scene_count}-1": "ここに選択肢1のテキスト", "scene_{scene_count}-2": "ここに選択肢2のテキスト"}}}}
            ```
            """

        elif scene_count > MAX_SCENES:
            # **クライマックスとエンディングの判定**
            if ending == "ハッピーエンド" or ending == "バッドエンド":
                prompt = f"""
                飛行機事故により無人島に漂着したプレイヤーと{heroine}の、サバイバルと恋愛を描くノベルゲームの、前回のストーリーに対するプレイヤーの選択の次の場面の「{ending}シーン」ストーリーを日本語で作成してください。(5文以内で)
                無人島でのサバイバル要素や、恋愛要素などを盛り込んでください。
                そして、そのシーンの背景画像を生成するためのプロンプトを英語で作成してください。(簡潔に)

                前回のストーリー:{pre_text}
                プレイヤーの選択:{scene}
                {heroine}の性格:{person[heroine]["性格"]}

                出力フォーマット:
                ```
                {{"text": "ここに最終話のストーリー",
                "image_prompt": "ここに背景画像を生成するためのプロンプト",
                "choices": {{"restart": "最初から"}}}}
                ```
                """

            else:
                prompt = f"""
                飛行機事故により無人島に漂着したプレイヤーと{heroine}の、サバイバルと恋愛を描くノベルゲームの、前回のストーリーに対するプレイヤーの選択の次の場面の「クライマックスシーン」ストーリーを日本語で作成してください。(5文以内で)
                無人島でのサバイバル要素や、恋愛要素などを盛り込んでください。
                そして、そのシーンの背景画像を生成するためのプロンプトを英語で作成してください。(簡潔に)
                また、プレイヤーに提示するハッピーエンドとバッドエンドに展開する選択肢を日本語で考えてください。

                前回のストーリー:{pre_text}
                プレイヤーの選択:{scene}
                {heroine}の性格:{person[heroine]["性格"]}

                出力フォーマット:
                ```
                {{"text": "ここにクライマックスシーンのストーリー",
                "image_prompt": "ここに背景画像を生成するためのプロンプト",
                "choices": {{"happy_end": "ここにハッピーエンドに展開する選択肢", "bad_end": "ここにバッドエンドに展開する選択肢"}}}}
                ```
                """

        else:
            """通常のシナリオ生成(クライマックスでない場合)"""
            prompt = f"""
            飛行機事故により無人島に漂着したプレイヤーと{heroine}の、サバイバルと恋愛を描くノベルゲームの、前回のストーリーに対するプレイヤーの選択の次の場面のストーリーを日本語で作成してください。(5文以内で)
            無人島でのサバイバル要素や、恋愛要素などを盛り込んでください。
            そして、そのシーンの背景画像を生成するためのプロンプトを英語で作成してください。(簡潔に)
            また、プレイヤーに提示する選択肢を2つ日本語で考えてください。

            前回のストーリー:{pre_text}
            プレイヤーの選択:{scene}
            {heroine}の性格:{person[heroine]["性格"]}

            出力フォーマット:
            ```
            {{"text": "ここに次の場面のストーリー",
            "image_prompt": "ここに背景画像を生成するためのプロンプト",
            "choices": {{"scene_{scene_count}-1": "ここに選択肢1のテキスト", "scene_{scene_count}-2": "ここに選択肢2のテキスト"}}}}
            ```
            """

        # llama3:8b または gemma:7b
        print("シナリオ生成開始")
        print(f"プロンプト(試行 {attempt + 1} 回目):", prompt)
        result = subprocess.run(
            ["ollama", "run", "llama3:8b", prompt],
            capture_output=True,
            text=True
        )

        text = result.stdout.strip()
        print(f"生成結果(試行 {attempt + 1} 回目):", text)  # デバッグ用

        # **JSON 部分を正しく抽出**
        match = re.search(r"```(?:json)?\n(.*?)\n```", text, re.DOTALL)
        json_text = match.group(1).strip() if match else text.strip()

        # **余分な `}` を削除**
        while json_text.count("{") < json_text.count("}"):
            json_text = json_text.rsplit("}", 1)[0]  # 最後の `}` を削除

        # **全角「」の前後に抜けた"を追加**
        json_text = json_text.replace(': 「', ': "「').replace(':「', ': "「')  # 「の前の"もれ
        json_text = json_text.replace('」,', '」",').replace('」 }', '」" }').replace('」}', '」"}')  # 」の後の"もれ
        json_text = json_text.replace('」\n}', '」"\n}')  # 」と\n}の間の"もれ
        json_text = json_text.replace('」",\n}', '」"\n}')  # 」",\n}の,削除

        # **「"""」を「"」にする**
        json_text = json_text.replace('"""', '"')

        # **「プレイヤー」を「あなた」にする**
        json_text = json_text.replace('プレイヤー', 'あなた')

        # **カンマ抜けの修正**
        json_text = re.sub(r'("text": "[^"]+)"\s+"image_prompt"', r'\1, "image_prompt"', json_text)
        json_text = re.sub(r'("image_prompt": "[^"]+)"\s+"choices"', r'\1, "choices"', json_text)

        # **': ""文字列",' を ': "文字列",' となるように正規表現による置換**
        json_text = re.sub(r':\s*""(.*?)"', r': "\1"', json_text)

        # **改行をエスケープ**
        json_text = fix_json_string(json_text)

        print("修正後の生成結果:", json_text)  # デバッグ用

        # **JSONとしてパース**
        try:
            story_data = json.loads(json_text)

            # **"choices" のKeyとValueを入れ替え(llama3:8bのイタズラ回避策)**
            if "choices" in story_data:
                new_choices = {value: key for key, value in story_data["choices"].items()}
                story_data["choices"] = new_choices

            if ending != "":
                story_data["text"] += "\n- 終わり -"

            # **画像を生成**
            #scene_name = f"scene_{len(story)}"
            image_path = generate_image(story_data["text"], scene_name, story_data["image_prompt"])
            story_data["image"] = image_path

            return story_data

        except json.JSONDecodeError as e:
            print("JSONDecodeError:", e)  # デバッグ用

    # **MAX_RETRIES 回試しても失敗した場合**
    return {"text": "シナリオの生成に失敗しました。再読み込みしてください。", "choices": {"最初から": "restart"}, "image": "static/error.png"}

# JSONファイルに保存(何かに利用したい時のために)
def save_to_json(data, filename="story.json"):
    with open(filename, "w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=4)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/story', methods=['POST'])
def get_story():
    data = request.json
    scene = data.get("scene", "start")
    global heroine
    global scene_count, story

    # keyに選択肢のテキストが入っている
    # 選択肢のストーリーtextも取得
    value_to_find = scene
    key = scene  # 見つからなかった時はscene使う
    pre_text = ""
    for k1,v1 in story.items():
        t = v1["text"]
        for k,v in v1["choices"].items():
            if v == value_to_find:
                key = k
                pre_text = t
                break

    if scene == "美咲" or scene == "花音" or scene == "涼子":
        heroine = key
        generate_image(heroine, "error", "Error screen for a visual novel game. Dark background with glitch effects.")  # **エラー画像を生成**

    if scene == "restart":
        # **ゲームをリセット**
        scene_count = 0
        story = {}
        static_story()
        save_to_json(story)
        return jsonify(story["start"])
    
    if scene in story:
        return jsonify(story[scene])
    
    # **AIで新しいシナリオを生成**
    generated_story = generate_story(key, scene, pre_text)  # keyに選択肢のテキストが入っている
    story[scene] = generated_story  # **新しいストーリーを保存**
    save_to_json(story)

    return jsonify(generated_story)

@app.route('/static/')
def get_image(filename):
    return send_from_directory("static", filename)

if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000, debug=True)

2.2 フロントエンド (index.html)

次に、templates/index.html を作成します。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>恋AIらんど -RenAIsland-</title>
    <style>
        body {
            font-family: 'Arial', 'cursive', sans-serif;
            background: linear-gradient(to bottom, #ffcccc, #ff99cc);
            color: #333;
            text-align: center;
            padding: 20px;
        }
        #game-container {
            max-width: 600px;
            margin: auto;
            background: rgba(255, 255, 255, 0.8);
            padding: 20px;
            border-radius: 15px;
            box-shadow: 0 0 15px rgba(255, 105, 180, 0.5);
            position: relative;
        }
        #story-image {
            width: 100%;
            height: auto;
            border-radius: 10px;
        }
        #character-image {
            position: absolute;
            bottom: 10px;
            right: 10px;
            width: 180px;
            height: auto;
        }
        #story-text {
            background: rgba(255, 255, 255, 0.9);
            padding: 15px;
            border-radius: 10px;
            font-size: 18px;
            margin-top: 10px;
        }
        .choice-btn {
            display: block;
            width: 80%;
            max-width: 500px;
            padding: 12px;
            margin: 8px auto;
            background-color: #ff6699;
            color: white;
            border: none;
            border-radius: 20px;
            cursor: pointer;
            font-size: 18px;
            transition: 0.3s;
        }
        .choice-btn:hover {
            background-color: #cc3366;
        }
    </style>
</head>
<body>
    <h1>恋AIらんど -RenAIsland-</h1>
    <div id="game-container">
        <img id="story-image" src="static/start.png" alt="シーン画像">
        <img id="character-image" src="" alt="キャラ画像" style="display: none;">
        <p id="story-text">ロード中...</p>
        <div id="choices"></div>
    </div>

    <script>
        let currentScene = "start";

        function loadStory(scene) {
            fetch("/story", {
                method: "POST",
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify({ scene: scene })
            })
            .then(response => response.json())
            .then(data => {
                document.getElementById("story-text").innerText = data.text;
                document.getElementById("story-image").src = data.image;
                
                // キャラクター画像があれば表示
                let charImage = document.getElementById("character-image");
                if (data.character_image) {
                    charImage.src = data.character_image;
                    charImage.style.display = "block";
                } else {
                    charImage.style.display = "none";
                }

                let choicesContainer = document.getElementById("choices");
                choicesContainer.innerHTML = "";

                for (let choice in data.choices) {
                    let button = document.createElement("button");
                    button.innerText = choice;
                    button.className = "choice-btn";
                    button.onclick = () => loadStory(data.choices[choice]);
                    choicesContainer.appendChild(button);
                }
            })
            .catch(error => console.error("エラー:", error));
        }

        window.onload = () => loadStory(currentScene);
    </script>
</body>
</html>

3. ゲームの実行

以下のコマンドでFlaskサーバーを起動します。

cd renaisland
source venv/bin/activate
python app.py

ブラウザで http://127.0.0.1:5000/ にアクセスするとゲームが表示されます。

スタート画面

実行するマシンによって、選択肢をクリックした後の応答に時間を要します。イライラして何度もクリックしないようにご注意ください。

ターミナルにデバッグ用のAI生成テキストが出力されるので気づくと思いますが、生成結果が出力フォーマットを守られていないことがあります。そのため、フォーマットエラー時は再生成をします。再生成を指定回数行ってもエラーの時はシナリオ作成エラーと表示します。

涼子

まとめ

本記事では、無人島サバイバル恋愛アドベンチャーゲームMacOS上に構築し、動作させるまでの手順を紹介しました。AIを活用したストーリーと画像生成を組み合わせ、動的なゲーム体験を実現できます。

Windows 10 で詳細な起動情報を表示する方法

Windows 10 で詳細な起動情報を表示する方法

Windows 10 では、Linux のような「verbose(冗長)」な起動モードは標準では用意されていませんが、いくつかの方法で詳細な起動情報を取得することができます。本記事では、起動時の詳細情報を表示・記録する方法を紹介します。

 

 

1. OSブート情報を有効にする

Windows の起動時にドライバのロード状況などを画面に表示する方法です。

設定手順

  1. [Win] + [R] を押し、「msconfig」と入力して Enter。
  2. ブート」タブを開く。
  3. 詳細オプション」をクリックし、「OSブート情報」にチェックを入れる。
  4. 「適用」→「OK」をクリックし、再起動。

再起動時に、ドライバの読み込み状況がテキストで表示されるようになります。

2. イベントビューアで起動ログを確認

確認手順

  1. [Win] + [X] を押して「イベントビューア」を開く。
  2. Windows ログ」→「システム」を開く。
  3. 「イベントID 100~199」のイベントをフィルタリング。
  4. 起動関連のエラーや詳細情報を確認。

特に イベントID 100(起動時間)イベントID 101(ブートプロセス詳細) に注目するとよいでしょう。

3. bootlog(ブートログ)を有効にする

設定手順

  1. 管理者権限で コマンドプロンプト を開く。
  2. 以下のコマンドを実行:
    bcdedit /set {current} bootlog Yes
  3. 再起動。
  4. C:\Windows\ntbtlog.txt にログが記録される。

この ntbtlog.txt を開くと、起動時にロードされたドライバの一覧を確認できます。

4. セーフモードで詳細な情報を確認

設定手順

  1. [Shift] を押しながら [再起動] をクリック。
  2. トラブルシューティング」→「詳細オプション」→「スタートアップ設定」→「再起動」。
  3. 再起動後、F8 を押して「セーフモード(またはログ記録付き)」を選択。

これにより、起動時に読み込まれるドライバやエラー情報が画面に表示されます。

5. デバッグモードを有効にする

設定手順

  1. [Win] + [R] → msconfig → 「ブート」タブ。
  2. 「詳細ブートオプション」で「デバッグ」オプションを有効にする。
  3. 再起動すると、デバッグ用のログが記録される。

デバッグモードは開発者向けの機能ですが、起動時の問題を解析するのに役立つ場合があります。

まとめ

Windows 10 で起動時の詳細な情報を取得する方法はいくつかあります。

方法 特徴
OSブート情報の表示 起動時のドライバ読み込み状況を画面に表示
イベントビューア 起動ログを後から確認可能
bootlog 記録 ntbtlog.txt にドライバ情報を記録
セーフモード システムメッセージがより多く表示される
デバッグモード 詳細なデバッグ情報を取得

起動のトラブルシューティングを行う際は、これらの方法を試してみてください。

ComfyUI 起動オプション

 

Intel Macに実行環境構築方法はこちら

 

yummac.hatenablog.jp

 

ComfyUI 起動オプションの使用方法:

usage: main.py [-h] [--listen [IP]] [--port PORT] [--tls-keyfile TLS_KEYFILE]
               [--tls-certfile TLS_CERTFILE] [--enable-cors-header [ORIGIN]]
               [--max-upload-size MAX_UPLOAD_SIZE]
               [--extra-model-paths-config PATH [PATH ...]]
               [--output-directory OUTPUT_DIRECTORY]
               [--temp-directory TEMP_DIRECTORY]
               [--input-directory INPUT_DIRECTORY] [--auto-launch]
               [--disable-auto-launch] [--cuda-device DEVICE_ID]
               [--cuda-malloc | --disable-cuda-malloc]
               [--force-fp32 | --force-fp16]
               [--fp32-unet | --fp64-unet | --bf16-unet | --fp16-unet | --fp8_e4m3fn-unet | --fp8_e5m2-unet]
               [--fp16-vae | --fp32-vae | --bf16-vae] [--cpu-vae]
               [--fp8_e4m3fn-text-enc | --fp8_e5m2-text-enc | --fp16-text-enc | --fp32-text-enc]
               [--force-channels-last] [--directml [DIRECTML_DEVICE]]
               [--oneapi-device-selector SELECTOR_STRING]
               [--disable-ipex-optimize]
               [--preview-method [none,auto,latent2rgb,taesd]]
               [--preview-size PREVIEW_SIZE]
               [--cache-classic | --cache-lru CACHE_LRU]
               [--use-split-cross-attention | --use-quad-cross-attention | --use-pytorch-cross-attention | --use-sage-attention]
               [--disable-xformers]
               [--force-upcast-attention | --dont-upcast-attention]
               [--gpu-only | --highvram | --normalvram | --lowvram | --novram | --cpu]
               [--reserve-vram RESERVE_VRAM]
               [--default-hashing-function {md5,sha1,sha256,sha512}]
               [--disable-smart-memory] [--deterministic] [--fast]
               [--dont-print-server] [--quick-test-for-ci]
               [--windows-standalone-build] [--disable-metadata]
               [--disable-all-custom-nodes] [--multi-user]
               [--verbose [{DEBUG,INFO,WARNING,ERROR,CRITICAL}]]
               [--log-stdout] [--front-end-version FRONT_END_VERSION]
               [--front-end-root FRONT_END_ROOT]
               [--user-directory USER_DIRECTORY]

 

ComfyUI Options:

Option Description
-h, --help Show this help message and exit
--listen [IP] Specify the IP address to listen on. Defaults to 127.0.0.1. Use "0.0.0.0,::" to listen on all IPv4 and IPv6.
--port PORT Set the listen port.
--tls-keyfile TLS_KEYFILE Path to TLS (SSL) key file. Enables TLS, makes app accessible at https://... requires --tls-certfile to function
--tls-certfile TLS_CERTFILE Path to TLS (SSL) certificate file. Enables TLS, makes app accessible at https://... requires --tls-keyfile to function
--enable-cors-header [ORIGIN] Enable CORS (Cross-Origin Resource Sharing) with optional origin or allow all with default '*'.
--max-upload-size MAX_UPLOAD_SIZE Set the maximum upload size in MB.
--extra-model-paths-config PATH [PATH ...] Load one or more extra_model_paths.yaml files.
--output-directory OUTPUT_DIRECTORY Set the ComfyUI output directory.
--temp-directory TEMP_DIRECTORY Set the ComfyUI temp directory (default is in the ComfyUI directory).
--input-directory INPUT_DIRECTORY Set the ComfyUI input directory.
--auto-launch Automatically launch ComfyUI in the default browser.
--disable-auto-launch Disable auto launching the browser.
--cuda-device DEVICE_ID Set the id of the cuda device this instance will use.
--cuda-malloc Enable cudaMallocAsync (enabled by default for torch 2.0 and up).
--disable-cuda-malloc Disable cudaMallocAsync.
--force-fp32 Force fp32 (If this makes your GPU work better please report it).
--force-fp16 Force fp16.
--fp32-unet Run the diffusion model in fp32.
--fp64-unet Run the diffusion model in fp64.
--bf16-unet Run the diffusion model in bf16.
--fp16-unet Run the diffusion model in fp16.
--fp8_e4m3fn-unet Store unet weights in fp8_e4m3fn.
--fp8_e5m2-unet Store unet weights in fp8_e5m2.
--fp16-vae Run the VAE in fp16, might cause black images.
--fp32-vae Run the VAE in full precision fp32.
--bf16-vae Run the VAE in bf16.
--cpu-vae Run the VAE on the CPU.
--fp8_e4m3fn-text-enc Store text encoder weights in fp8 (e4m3fn variant).
--fp8_e5m2-text-enc Store text encoder weights in fp8 (e5m2 variant).
--fp16-text-enc Store text encoder weights in fp16.
--fp32-text-enc Store text encoder weights in fp32.
--force-channels-last Force channels last format when inferencing the models.
--directml [DIRECTML_DEVICE] Use torch-directml.
--oneapi-device-selector SELECTOR_STRING Sets the oneAPI device(s) this instance will use.
--disable-ipex-optimize Disables ipex.optimize default when loading models with Intel's Extension for Pytorch.
--preview-method [none,auto,latent2rgb,taesd] Default preview method for sampler nodes.
--preview-size PREVIEW_SIZE Sets the maximum preview size for sampler nodes.
--cache-classic Use the old style (aggressive) caching.
--cache-lru CACHE_LRU Use LRU caching with a maximum of N node results cached. May use more RAM/VRAM.
--use-split-cross-attention Use the split cross attention optimization. Ignored when xformers is used.
--use-quad-cross-attention Use the sub-quadratic cross attention optimization. Ignored when xformers is used.
--use-pytorch-cross-attention Use the new pytorch 2.0 cross attention function.
--use-sage-attention Use sage attention.
--disable-xformers Disable xformers.
--force-upcast-attention Force enable attention upcasting, please report if it fixes black images.
--dont-upcast-attention Disable all upcasting of attention. Should be unnecessary except for debugging.
--gpu-only Store and run everything (text encoders/CLIP models, etc... on the GPU).
--highvram By default models will be unloaded to CPU memory after being used. This option keeps them in GPU memory.
--normalvram Used to force normal vram use if lowvram gets automatically enabled.
--lowvram Split the unet in parts to use less vram.
--novram When lowvram isn't enough.
--cpu To use the CPU for everything (slow).
--reserve-vram RESERVE_VRAM Set the amount of vram in GB you want to reserve for use by your OS/other software. By default some amount is reserved depending on your OS.
--default-hashing-function {md5,sha1,sha256,sha512} Allows you to choose the hash function to use for duplicate filename / contents comparison. Default is sha256.
--disable-smart-memory Force ComfyUI to aggressively offload to regular ram instead of keeping models in vram when it can.
--deterministic Make pytorch use slower deterministic algorithms when it can. Note that this might not make images deterministic in all cases.
--fast Enable some untested and potentially quality deteriorating optimizations.
--dont-print-server Don't print server output.
--quick-test-for-ci Quick test for CI.
--windows-standalone-build Windows standalone build: Enable convenient things that most people using the standalone windows build will probably enjoy (like auto opening the page on startup).
--disable-metadata Disable saving prompt metadata in files.
--disable-all-custom-nodes Disable loading all custom nodes.
--multi-user Enables per-user storage.
--verbose [{DEBUG,INFO,WARNING,ERROR,CRITICAL}] Set the logging level
--log-stdout Send normal process output to stdout instead of stderr (default).
--front-end-version FRONT_END_VERSION Specifies the version of the frontend to be used. This command needs internet connectivity to query and download available frontend implementations from GitHub releases. The version string should be in the format of: [repoOwner]/[repoName]@[version] where version is one of: "latest" or a valid version number (e.g. "1.0.0").
--front-end-root FRONT_END_ROOT The local filesystem path to the directory where the frontend is located. Overrides --front-end-version.
--user-directory USER_DIRECTORY Set the ComfyUI user directory with an absolute path.

 

ComfyUI 起動オプション:

オプション 説明
-h, --help このヘルプメッセージを表示して終了します
--listen [IP] リッスンするIPアドレスを指定します。デフォルトは127.0.0.1です。すべてのIPv4およびIPv6でリッスンするには"0.0.0.0,::"を使用します。
--port PORT リッスンポートを設定します。
--tls-keyfile TLS_KEYFILE TLSSSL)キー ファイルへのパス。TLSを有効にし、アプリをhttps://...でアクセス可能にします。動作には--tls-certfileが必要です。
--tls-certfile TLS_CERTFILE TLSSSL)証明書ファイルへのパス。TLSを有効にし、アプリをhttps://...でアクセス可能にします。動作には--tls-keyfileが必要です。
--enable-cors-header [ORIGIN] オプションのオリジンを指定してCORS(クロスオリジンリソース共有)を有効にするか、デフォルトの'*'ですべてを許可します。
--max-upload-size MAX_UPLOAD_SIZE 最大アップロードサイズをMB単位で設定します。
--extra-model-paths-config PATH [PATH ...] 1つ以上のextra_model_paths.yamlファイルを読み込みます。
--output-directory OUTPUT_DIRECTORY ComfyUIの出力ディレクトリを設定します。
--temp-directory TEMP_DIRECTORY ComfyUIの一時ディレクトリを設定します(デフォルトはComfyUIディレクトリ内)。
--input-directory INPUT_DIRECTORY ComfyUIの入力ディレクトリを設定します。
--auto-launch デフォルトのブラウザでComfyUIを自動的に起動します。
--disable-auto-launch ブラウザの自動起動を無効にします。
--cuda-device DEVICE_ID このインスタンスが使用するCUDAデバイスのIDを設定します。
--cuda-malloc cudaMallocAsyncを有効にします(torch 2.0以降ではデフォルトで有効)。
--disable-cuda-malloc cudaMallocAsyncを無効にします。
--force-fp32 fp32を強制します(これがGPUの動作を改善する場合は報告してください)。
--force-fp16 fp16を強制します。
--fp32-unet 拡散モデルをfp32で実行します。
--fp64-unet 拡散モデルをfp64で実行します。
--bf16-unet 拡散モデルをbf16で実行します。
--fp16-unet 拡散モデルをfp16で実行します。
--fp8_e4m3fn-unet unetの重みをfp8_e4m3fnで格納します。
--fp8_e5m2-unet unetの重みをfp8_e5m2で格納します。
--fp16-vae VAEをfp16で実行します(黒い画像が生成される可能性があります)。
--fp32-vae VAEを完全な精度のfp32で実行します。
--bf16-vae VAEをbf16で実行します。
--cpu-vae VAEをCPUで実行します。
--fp8_e4m3fn-text-enc テキストエンコーダの重みをfp8(e4m3fnバリアント)で格納します。
--fp8_e5m2-text-enc テキストエンコーダの重みをfp8(e5m2バリアント)で格納します。
--fp16-text-enc テキストエンコーダの重みをfp16で格納します。
--fp32-text-enc テキストエンコーダの重みをfp32で格納します。
--force-channels-last モデル推論時にチャンネルを最後に強制設定します。
--directml [DIRECTML_DEVICE] torch-directmlを使用します。
--oneapi-device-selector SELECTOR_STRING このインスタンスが使用するoneAPIデバイスを設定します。
--disable-ipex-optimize IntelのExtension for Pytorchを使用してモデルをロードする際のipex.optimizeを無効にします。
--preview-method [none,auto,latent2rgb,taesd] サンプラーノードのデフォルトプレビュー方法。
--preview-size PREVIEW_SIZE サンプラーノードの最大プレビューサイズを設定します。
--cache-classic 旧スタイル(積極的)キャッシュを使用します。
--cache-lru CACHE_LRU LRUキャッシュを使用し、最大N個のノード結果をキャッシュします。より多くのRAM/VRAMを使用する可能性があります。
--use-split-cross-attention 分割クロスアテンション最適化を使用します。xformers使用時には無視されます。
--use-quad-cross-attention 部分二乗クロスアテンション最適化を使用します。xformers使用時には無視されます。
--use-pytorch-cross-attention 新しいpytorch 2.0クロスアテンション機能を使用します。
--use-sage-attention sage attentionを使用します。
--disable-xformers xformersを無効にします。
--force-upcast-attention アテンションのアップキャストを強制有効化します。これが黒い画像の問題を修正する場合は報告してください。
--dont-upcast-attention アテンションのアップキャストをすべて無効にします。デバッグ以外では不要なはずです。
--gpu-only すべてをGPUに格納および実行します(テキストエンコーダー/CLIPモデルなど)。
--highvram デフォルトでは、モデルは使用後にCPUメモリにアンロードされます。このオプションはそれをGPUメモリに保持します。
--normalvram lowvramが自動的に有効になった場合に通常のvram使用を強制します。
--lowvram unetを部分に分割してvramの使用量を減らします。
--novram lowvramでも足りない場合に使用します。
--cpu すべてをCPUで使用します(遅い)。
--reserve-vram RESERVE_VRAM OS/他のソフトウェアで使用するために確保するvramの量をGB単位で設定します。デフォルトではOSによっていくつかの量が予約されます。
--default-hashing-function {md5,sha1,sha256,sha512} 重複したファイル名/内容の比較に使用するハッシュ関数を選択できます。デフォルトはsha256です。
--disable-smart-memory ComfyUIが可能な場合にモデルをvramに保持する代わりに通常のramに積極的にオフロードするよう強制します。
--deterministic pytorchが可能な場合に遅い決定的なアルゴリズムを使用します。ただし、これがすべての場合で画像を決定的にするわけではありません。
--fast 未テストで品質を劣化させる可能性のある最適化を有効にします。
--dont-print-server サーバー出力を表示しません。
--quick-test-for-ci CIのクイックテスト。
--windows-standalone-build Windowsスタンドアロンビルド:スタートアップ時にページを自動的に開くなど、スタンドアロンWindowsビルドを使用するほとんどのユーザーが楽しめる便利な機能を有効にします。
--disable-metadata ファイルにプロンプトメタデータを保存するのを無効にします。
--disable-all-custom-nodes すべてのカスタムノードの読み込みを無効にします。
--multi-user ユーザーごとのストレージを有効にします。
--verbose [{DEBUG,INFO,WARNING,ERROR,CRITICAL}] ログレベルを設定します
--log-stdout 通常のプロセス出力をデフォルトではなくstdoutに送信します。
--front-end-version FRONT_END_VERSION 使用するフロントエンドのバージョンを指定します。このコマンドには、GitHubリリースから利用可能なフロントエンド実装を照会してダウンロードするためのインターネット接続が必要です。バージョン文字列は以下の形式である必要があります:[repoOwner]/[repoName]@[version](例: "latest"または有効なバージョン番号"1.0.0")。
--front-end-root FRONT_END_ROOT フロントエンドが配置されているディレクトリへのローカルファイルシステムパス。--front-end-versionを上書きします。
--user-directory USER_DIRECTORY 絶対パスを使用してComfyUIユーザーディレクトリを設定します。

Intel MacでDiffusersインストールとAI画像生成のセットアップ方法

Intel MacでDiffusersを使ったAI画像生成のセットアップ方法

Intel Mac環境でPythonを使用して、DiffusersによるAI画像生成を実行する手順を紹介します。仮想環境を使用してパッケージ管理をしやすくし、最新のTorchビルドとともに必要なライブラリをインストールする方法を説明します。

1. Diffusersインストール

まず、Diffusers専用のディレクトリを作成し、仮想環境を構築します。

ステップ1: ディレクトリと仮想環境の作成

ターミナルを開き、以下のコマンドを順番に実行してください。

# diffusersディレクトリの作成と移動
mkdir diffusers
cd diffusers

# 仮想環境の作成
python3 -m venv venv

# 仮想環境の有効化
source venv/bin/activate

仮想環境を有効にすることで、他のプロジェクトへの影響を抑え、必要なライブラリだけをこの環境にインストールできます。

ステップ2: パッケージのインストール

次に、パッケージをインストールします。Diffusersとともに、Torchの最新nightlyビルド版を使用するため、以下のコマンドを実行します。

# pipのアップグレード
pip install --upgrade pip

# Torchのnightlyビルドをインストール
pip install --pre torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/nightly/cpu

# Diffusersおよび関連パッケージのインストール
pip install accelerate
pip install diffusers transformers

これで、Diffusersの実行環境が整いました。

2. AI画像生成ゲームの実行

 

yummac.hatenablog.jp

 

Diffusersを使用したAI画像生成ゲームを実行する準備が整ったら、ゲームコードをAI-MonsterBattle.pyとして保存します。保存先はdiffusersディレクトリです。

# AI-MonsterBattle.pyファイルの実行
python AI-MonsterBattle.py

コードが実行されると、DiffusersとStable Diffusion Pipelineに基づくAIモンスターがランダム生成され、バトルが始まります。

3. 実行時に発生する可能性のあるエラーと対処法

エラー1: numpyのバージョンに関するエラー

特定のnumpyバージョンでエラーが発生する場合は、以下のコマンドでnumpyをアンインストールし、互換性のあるバージョンに再インストールします。

pip uninstall numpy
pip install numpy==1.26.4

エラー2: LCMモジュールのエラー

Diffusersの利用時にLCMモジュールで「ValueError: PEFT backend is required for this method.」というエラーが発生する場合、peftモジュールを更新します。

pip install -U peft

これでIntel Mac上にDiffusers環境を構築し、AI画像生成を実行する準備が整いました。ぜひお試しください。