<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>AI | じじぃの引出し</title>
	<atom:link href="https://www.kazuban.com/blog/category/ai/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.kazuban.com/blog</link>
	<description>なにかしら、皆さんの参考になれば幸いです！</description>
	<lastBuildDate>Mon, 08 Jun 2026 04:35:09 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>

<image>
	<url>https://www.kazuban.com/blog/wp-content/uploads/2020/05/cropped-ICON-1-32x32.png</url>
	<title>AI | じじぃの引出し</title>
	<link>https://www.kazuban.com/blog</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>WordPress の「バックアップ・リストア」BASHスクリプト</title>
		<link>https://www.kazuban.com/blog/rokeylinux9-7-wordpress-backup/</link>
					<comments>https://www.kazuban.com/blog/rokeylinux9-7-wordpress-backup/#respond</comments>
		
		<dc:creator><![CDATA[kazuban]]></dc:creator>
		<pubDate>Sun, 07 Jun 2026 06:28:26 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[IT]]></category>
		<category><![CDATA[Linux (CentOS、Rocky、Ubuntu)]]></category>
		<category><![CDATA[BASH]]></category>
		<category><![CDATA[RockyLinux9.7]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[バックアップ]]></category>
		<category><![CDATA[リストア]]></category>
		<category><![CDATA[自宅サーバー]]></category>
		<guid isPermaLink="false">https://www.kazuban.com/blog/?p=12790</guid>

					<description><![CDATA[バックアップ・リストアの記事は、以前こちらでも紹介しました 目次 新しいBASHデバッグshellcheckset コマンドスクリプト構成WordPress_Config_Data.sh : 変数設定Wp-Backup. [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">バックアップ・リストアの記事は、以前こちらでも紹介しました </p>


<a href="https://www.kazuban.com/blog/rokeylinux9-3-wordpress-backup/" title="RockyLinux9.３で自宅サーバーを再構築V07・WordPress のバックアップとリストア" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img decoding="async" width="160" height="90" src="https://www.kazuban.com/blog/wp-content/uploads/2023/12/wordpress-backup-restore-160x90.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://www.kazuban.com/blog/wp-content/uploads/2023/12/wordpress-backup-restore-160x90.png 160w, https://www.kazuban.com/blog/wp-content/uploads/2023/12/wordpress-backup-restore-120x68.png 120w, https://www.kazuban.com/blog/wp-content/uploads/2023/12/wordpress-backup-restore-320x180.png 320w" sizes="(max-width: 160px) 100vw, 160px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">RockyLinux9.３で自宅サーバーを再構築V07・WordPress のバックアップとリストア</div><div class="blogcard-snippet internal-blogcard-snippet">引越しするには、旧環境のデータをバックアップし、新環境へリストアします。WordPress のバックアップとリストアの方法を説明し、自動バックアップするスクリプトを作成します。バックアップ・リストアができると、引越しだけでなく、トラブル時にも以前の状態まで戻せます。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img decoding="async" src="https://www.google.com/s2/favicons?domain=https://www.kazuban.com/blog" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">www.kazuban.com</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2024.01.08</div></div></div></div></a>



  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-2" checked><label class="toc-title" for="toc-checkbox-2">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">新しいBASH</a></li><li><a href="#toc2" tabindex="0">デバッグ</a><ol><li><a href="#toc3" tabindex="0">shellcheck</a></li><li><a href="#toc4" tabindex="0">set コマンド</a></li></ol></li><li><a href="#toc5" tabindex="0">スクリプト構成</a><ol><li><a href="#toc6" tabindex="0">WordPress_Config_Data.sh : 変数設定</a></li><li><a href="#toc7" tabindex="0">Wp-Backup.sh : データベース＆WordPressコンテンツのバックアップ</a></li><li><a href="#toc8" tabindex="0">MariaDB_Backup.sh : データベースバックアップ（Wp-Backup.shから呼ばれる）</a></li><li><a href="#toc9" tabindex="0">Wp-Content_Backup.sh : WordPressコンテンツバックアップ（Wp-Backup.shから呼ばれる）</a></li><li><a href="#toc10" tabindex="0">Wp-Restore.sh : データベース＆WordPressコンテンツの復元</a></li><li><a href="#toc11" tabindex="0">MariaDB_Restore.sh データベース復元（Wp-Restore.shから呼ばれる）</a></li><li><a href="#toc12" tabindex="0">Wp-Content_Restore.sh: WordPressコンテンツ復元（Wp-Restore.shから呼ばれる）</a></li><li><a href="#toc13" tabindex="0">Header.sh : デバッグモード仕様（変数 DEBUG=1 で有効）</a></li><li><a href="#toc14" tabindex="0">Tidyup_backfile.sh : バックアップファイルの整理（引数：対象ディレクトリ・保存日数）</a></li></ol></li><li><a href="#toc15" tabindex="0">自動バックアップ</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">新しいBASH</span></h2>



<p class="wp-block-paragraph">前回のスクリプトは、<a href="https://www.kazuban.com/blog/mirror-site-v2/#toc9">2020年に紹介した</a>コマンド操作をネット情報を参考にスクリプト化しましたが、今回はこのスクリプトをAIに投げて、最新のBASH構文への変換を教えてもらいながら作成しました。<br>投稿のスクリプト類はちょっと長くなりましたが、全てコピペできるようにしました。<br>また、開発途中ではBASHで一行づつのデバッグもやってみました。</p>



<h2 class="wp-block-heading"><span id="toc2">デバッグ</span></h2>



<p class="wp-block-paragraph">編集はVSCodeを利用したので、デバッグプラグインもインストールしてみましたが、あまり思ったように動いてくれませんでした。<br>AIに聞いてみると、BASH自体にも、構文チェックやステップデバッグができる機能があるようです</p>



<h3 class="wp-block-heading"><span id="toc3">shellcheck</span></h3>



<p class="wp-block-paragraph"><span class="inline-button-white-black"><code>shellcheck [スクリプト名.sh]</code></span>のようにコマンド実行するだけで、スクリプトのバグや構文エラーを簡単にチェックできます。<br>パッケージ名は、キャメルケース的書き方「<strong>S</strong>hell<strong>C</strong>heck」になるので注意が必要です</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-db8e023e6e1cfc0bb1ea28937edb3636"><code>sudo dnf install ShellCheck</code></pre>



<p class="wp-block-paragraph">もしパッケージが見つからない場合には、EPELリポジトリが有効になっていない可能性があるのでEPELを有効化した上で再度インストール</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-fdb162245c5ae88b8bde6aff6981db8a"><code>sudo dnf install epel-release
sudo dnf install ShellCheck</code></pre>



<p class="wp-block-paragraph">shellcheck は、スクリプトのバグや構文エラーを検出してエラーコードと共に表示してくれます。<br>標準では致命的でない場合でも警告を出してくるのでちょっとうるさく感じる事もありますが、<br>エラーコードをAIに聞くことでより安全なコードの書き方の学習にもなります</p>



<h3 class="wp-block-heading"><span id="toc4">set コマンド</span></h3>



<p class="wp-block-paragraph">Bashの <code>set</code> コマンドは、シェルの動作やオプションを設定・変更するためのコマンドです。<br>主にスクリプトの安全運転モードやデバッグのために、シェルの冒頭でオプションと組み合わせて使用されます<br>・set -euo pipefail<br>実務でよく使われる定番のオプション<br>これにより、スクリプト実行時のバグや予期せぬトラブルを大幅に減らせます<br><br>・<strong><code>set -x</code></strong>: デバッグ開始<br>実行されるコマンドや変数の展開結果をすべて画面（標準エラー出力）に表示<br><br>・<strong><code>set +x</code></strong>: デバッグ開始<br>実行トレース出力を停止<br><br>・trap &#8216;read -p &#8220;STEP> &#8221; &lt; /dev/tty&#8217; DEBUG<br>実行中、すべてのコマンドを実行する直前で指定文字（STEP>）プロンプトで一時停止<br><br>・export PS4=&#8217;+ ${LINENO}: &#8216;<br>デバッグモード（<code>set -x</code>）で実行されるコマンドを表示する際、そのコマンドのスクリプトでの行番号を出力に含める設定</p>



<p class="wp-block-paragraph">これらコードをスクリプト上部で実行しておくことで、シェルスクリプトのバグの原因特定が早くなります。<br>サンプルコードを書いてみました。</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-575fb2a5323ae743d77eedbdc438c478"><code>#!/bin/bash

set -euo pipefail
# --- debug mode: DEBUGGING=1 で有効 ---
DEBUGGING=1

if &#91;&#91; $DEBUGGING == "1" ]]; then
  echo "Debug mode is 'true' !! "
  export PS4='+ ${LINENO}: '
  set -x
  trap 'read -p "STEP> " &lt; /dev/tty' DEBUG
else
  echo "Debug mode is 'false' !! "
fi

# テスト用コード
echo "最初の処理"
x=10
y=20
result=$((x + y))
echo "結果は $result"</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph">このコードを実行すると、デバッグの状況が体験できます</p>



<p class="wp-block-paragraph">次に今回作成したWordPressのバックアップ＆リストアのスクリプトを紹介します<br>デバッグコードは、Header.sh に別スクリプトにして、呼び出す形式にしました。</p>



<h2 class="wp-block-heading"><span id="toc5">スクリプト構成</span></h2>



<p class="wp-block-paragraph">WordPressのバックアップは、大きく分けて「ファイル（サーバー内のデータ）」と「データベース（MySQL/MariaDB）」の2つが必要になります。<br>前回スクリプトは、昔の経験とネット検索を参考に、自分で作成しましたが<br>今回は、BASHもかなり進化しているみたいなので、AIのサポートで最新の構文で書き直しました。<br>バックアップファイルやスクリプトの構成は<br>・「ユーザーホーム」内に、「Backup」ディレクトリを作成<br>・「Backup」内に、「WordPress」と「bin」ディレクトリを作成<br>・「WordPress」内にWordPress パッケージをインストールしたディレクトリ名（筆者環境では「blog」）を作成します<br>・「blog」内に、データベースとサーバー内データのバックアップを保存します<br>・「bin」内に実行スクリプトを保存します</p>



<pre class="wp-block-preformatted">.[ユーザーホームディレクトリ]<br>├── Backup #「バックアップデータを保存する」<br>│   ├── WordPress #「WordPerss関連データ」<br>│   │   └── blog #「blog内のバックアップデータ」<br>│   │       ├── 20260530-MariaDB.bak       # データベースバックアップ<br>│   │       ├── 20260530-Wp-content.tar.gz # WordPressコンテンツ<br>│   │       ├── mariadb_backup.log<br>│   │       └── wp_backup.log<br>│   ├── bin #「スクリプト」<br>│   │   ├── Header.sh                #「デバッグ用のスクリプト」<br>│   │   ├── MariaDB_Backup.sh        #「データベースのバックアップ」<br>│   │   ├── MariaDB_Restore.sh       #「データベースのリストア」<br>│   │   ├── Tidyup_backfile.sh       #「バックアップデータの整理」<br>│   │   ├── WordPress_Config_Data.sh #「バックアップ環境の設定」<br>│   │   ├── Wp-Backup.sh             #「バックアップ用メインスクリプト」<br>│   │   ├── Wp-Content_Backup.sh     #「WordPressデータのバックアップ」<br>│   │   ├── Wp-Content_Restore.sh    #「WordPressデータのリストア」<br>│   │   └── Wp-Restore.sh            #「リストア用メインスクリプト」</pre>



<h3 class="wp-block-heading"><span id="toc6">WordPress_Config_Data.sh : 変数設定</span></h3>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-7499046ee69558135b4281b890568874"><code>#!/bin/bash
#  WoredPressバックアップ設定ファイル
#    WordPress_Config_Data.sh    2026/05 by Kazuban
#------------------------------------
export USER="kazuban"
export USER_DIR="/home/${USER}"
export SUB_DIR="blog"
export DOCUMEN_ROOT="/home/www/html"
#----- MariaDB ----------------------
export MYSQL_ROOT_PASSWD="hogehoge_passwd"
export DATABASE="WpDb"
export MYSQL_USER="WpAdmin"
export MYSQL_USER_PASSWD="WpPasswd"
#----- WordPress --------------------
export WP_CONTENT_DIR="wp-content"
export WP_CONTENT_FILENAME="Wp-content"
export WP_CONTENT_PATH="/home/www/html/${SUB_DIR}/${WP_CONTENT_DIR}"
export WP_CONTENT_OWNER="apache:apache"</code></pre>



<h3 class="wp-block-heading"><span id="toc7">Wp-Backup.sh : データベース＆WordPressコンテンツのバックアップ</span></h3>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-3e684ce3afa6a29508f003665ce57d7a"><code>#!/bin/bash
#  WoredPress のバックアップ
#    データベース(Mysql)とサーバーデータ(wp-content)
#  Wp-Backup.sh    2026/05 by Kazuban
#------------------------------------
#--- debug mode, set "DEBUG=1". -----
export DEBUG=
#------------------------------------
export CALLER_SCRIPT="$0"
#export SCRIPT_DIR=$(dirname "$(realpath "$0")")
#shellscriptで警告でたので、AIに聞くとこの書き方が安全らしい
SCRIPT_DIR=$(dirname "$(readlink -f "${BASH_SOURCE&#91;0]}")")
export SCRIPT_DIR
#------------------------------------
source "${SCRIPT_DIR}/Header.sh"
source "${SCRIPT_DIR}/WordPress_Config_Data.sh"
export BACKUP_DIR="${USER_DIR}/Backup/WordPress/${SUB_DIR}"
#---- MariaDB -----------------------
export MYSQL_BACKUP_SCRIPT="${SCRIPT_DIR}/MariaDB_Backup.sh"
export MYSQL_LOG="${BACKUP_DIR}/mariadb_backup.log"
#---- WordPress ---------------------
#export BACKUP_SOURCE_DIR="${DOCUMEN_ROOT}/${SUB_DIR}/wp-content"
export WP_BACKUP_SCRIPT="${SCRIPT_DIR}/Wp-Content_Backup.sh"
export BACKUP_SOURCE_DIR="${DOCUMEN_ROOT}/${SUB_DIR}/${WP_CONTENT_DIR}"
export WP_LOG="${BACKUP_DIR}/wp_backup.log"
#------------------------------------
export TIDY_UP_SCRIPT="${SCRIPT_DIR}/Tidyup_backfile.sh"
export DAYS_AGO="5"
#-----　関数定義 -----------------------
user_dir=$(pwd)
echo $user_dir
# スクリプト終了時に実行させたい場合はここで再定義
cleanup() {
#  echo "Wp-Backup 終了処理"
  :
}
check_backup_dir(){
  #$BACKUP_DIRが存在しない場合には作成
  mkdir -p $BACKUP_DIR 
}
cmd_mariadb()   { check_backup_dir; $MYSQL_BACKUP_SCRIPT; }
cmd_wordpress() { check_backup_dir; $WP_BACKUP_SCRIPT; }
cmd_all()       { cmd_mariadb; cmd_wordpress; }
cmd_help() {
  echo "--- WordPress Backup Script ---"
  echo "Directory: ${SCRIPT_DIR}"
  echo "Usage: $0 {db|wp|all|help}"
  echo "  db   = データベース(MariaDB)"
  echo "  wp   = Word Press (Wp-Content)"
  echo "  all  = db + wp"
  echo "  help = オプション"
}

#-----　メインプログラム　-------------
#------------------------------------
case "${1:-}" in
  db)        cmd_mariadb   ;;
  wp)        cmd_wordpress ;;
  all)       cmd_all       ;;
  help|"")   cmd_help      ;;
  *)
    echo "Unknown command: $1"
    cmd_help
    exit 1
    ;;
esac
</code></pre>



<h3 class="wp-block-heading"><span id="toc8">MariaDB_Backup.sh : データベースバックアップ（Wp-Backup.shから呼ばれる）</span></h3>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-64a5ce5d8d3b788c20534c9eacfd6d5f"><code>#!/bin/bash
#  WoredPress のデータベースバックアップ
#    MariaDB_Backup.sh    2026/05 by Kazuban
#------------------------------------
# 直接実行ガード（呼び出し元スクリプトからのみ実行可）
if &#91;&#91; -z "${CALLER_SCRIPT:-}" ]]; then
  echo "直接実行はできません。"
  echo "&#91;WP-Backup.sh db] から呼び出してください。"
  exit 1
fi
#------------------------------------
source "${SCRIPT_DIR}/Header.sh"
#------------------------------------
# --- 関数定義 ---
usage() {
  echo "使用方法: ${SCRIPT_NAME:-$(basename "$0")}"
  echo "  データベース(MariaDB)をバックアップし、古いファイルを整理します。"
  exit 0
}

log() {
  local message="$1"
  echo "$(date '+%Y-%m-%d %H:%M:%S') ${message}" | tee -a "${MYSQL_LOG}"
}

failed() {
  echo "エラー: $1" &gt;&amp;2
  log "ERROR: $1"
  exit 1
}

# バックアップファイル名を生成する（同名ファイルがあれば連番を付加）
make_filename() {
  local date_str
  date_str=$(date '+%Y%m%d')
  local basename="-MariaDB.bak"
  local filename="${date_str}${basename}"
  local i=1
  while &#91;&#91; -e "${BACKUP_DIR}/${filename}" ]]; do
    filename="${date_str}-${i}${basename}"
    (( i++ )) || true
  done
  echo "${filename}"
}

# --- ヘルプ ---
if &#91;&#91; "${1:-}" == "-?" || "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
  usage
fi

# --- 事前チェック ---
&#91;&#91; -d "${BACKUP_DIR}" ]]      || failed "バックアップ先が見つかりません: ${BACKUP_DIR}"
&#91;&#91; -x "${TIDY_UP_SCRIPT}" ]]  || failed "整理スクリプトが見つかりません: ${TIDY_UP_SCRIPT}"

# --- ファイル名決定 ---
FILENAME=$(make_filename)
BACKUP_PATH="${BACKUP_DIR}/${FILENAME}"

# --- バックアップ実行 ---
log "MariaDB バックアップ開始: ${FILENAME}"
echo "MariaDB を ${FILENAME} にバックアップします。"

if mariadb-dump \
    --user="${MYSQL_USER}" \
    --password="${MYSQL_USER_PASSWD}" \
    --host=localhost \
    --all-databases \
    --single-transaction \
    --quick \
    &gt; "${BACKUP_PATH}" \
    2&gt;&gt; "${MYSQL_LOG}"; then
  log "バックアップ成功: ${FILENAME} ($(du -sh "${BACKUP_PATH}" | cut -f1))"
else
  failed "mariadb-dump コマンドが失敗しました"
fi

# --- 古いファイルの整理 ---
log "古いバックアップを整理します（${DAYS_AGO} 日以前）"
"${TIDY_UP_SCRIPT}" "${BACKUP_DIR}" "${DAYS_AGO}"

log "MariaDB バックアップ完了"
echo "MariaDB Backup Complete."</code></pre>



<h3 class="wp-block-heading"><span id="toc9">Wp-Content_Backup.sh : WordPressコンテンツバックアップ（Wp-Backup.shから呼ばれる）</span></h3>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-41a22cc8c585189660e126f42ec94376"><code>#!/bin/bash
#  wp-content ディレクトリのバックアップスクリプト
#    WP-content_Backup.sh    2026/05 by Kazuban
#------------------------------------
# 直接実行ガード（呼び出し元スクリプトからのみ実行可）
if &#91;&#91; -z "${CALLER_SCRIPT:-}" ]]; then
  echo "直接実行はできません。"
  echo "&#91;WP-Backup.sh wp] から呼び出してください。"
  exit 1
fi
#------------------------------------
readonly SCRIPT_NAME="$(basename "$0")"
#------------------------------------
source "${SCRIPT_DIR}/Header.sh"
#------------------------------------
# スクリプト終了時に実行させたい場合はここで再定義
cleanup() {
#  echo "Wp-Backup 終了処理"
  :
}
#------------------------------------
# --- 関数定義 ---
usage() {
  echo "使用方法: ${SCRIPT_NAME}"
  echo "  wp-content ディレクトリをバックアップし、古いファイルを整理します。"
  exit 0
}

log() {
  local message="$1"
  echo "$(date '+%Y-%m-%d %H:%M:%S') ${message}" | tee -a "${WP_LOG}"
}

failed() {
  echo "エラー: $1" &gt;&amp;2
  log "ERROR: $1"
  exit 1
}

# バックアップファイル名を生成する（同名ファイルがあれば連番を付加）
make_filename() {
  local date_str
  date_str=$(date '+%Y%m%d')
  local basename="-Wp-content.tar.gz"
  local filename="${date_str}${basename}"
  local i=1
  while &#91;&#91; -e "${BACKUP_DIR}/${filename}" ]]; do
    filename="${date_str}-${i}${basename}"
    (( i++ )) || true
  done
  echo "${filename}"
}

# --- ヘルプ ---
if &#91;&#91; "${1:-}" == "-?" || "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
  usage
fi

# --- 事前チェック ---
&#91;&#91; -d "${BACKUP_DIR}" ]]   || failed "バックアップ先が見つかりません: ${BACKUP_DIR}"
&#91;&#91; -d "${BACKUP_SOURCE_DIR}" ]]  || failed "バックアップ元が見つかりません: ${BACKUP_SOURCE_DIR}"
&#91;&#91; -x "${TIDY_UP_SCRIPT}" ]]  || failed "整理スクリプトが見つかりません: ${TIDY_UP_SCRIPT}"

# --- ファイル名決定 ---
FILENAME=$(make_filename)
DEST="${BACKUP_DIR}/${FILENAME}"

# --- バックアップ実行 ---
log "WordPress バックアップ開始:"
log "${BACKUP_SOURCE_DIR} → ${DEST}"
echo "WordPress Backup Starting..."

#echo "バックアップファイル：${DEST}"
#echo "sudo chown ${USER}: ${DEST}"
#exit 1
if sudo tar \
    --create \
    --gzip \
    --file="${DEST}" \
    "${BACKUP_SOURCE_DIR}"; then # \
    #2&gt;&gt; "${WP_LOG}"; then
  echo "バックアップファイル：${DEST}"
  echo "sudo chown ${USER}: ${DEST}"
  sudo chown ${USER}: ${DEST}
  log "バックアップ成功: ${FILENAME} ($(du -sh "${DEST}" | cut -f1))"
else
  failed "tar コマンドが失敗しました"
fi

# --- 古いファイルの整理 ---
log "古いバックアップを整理します（${DAYS_AGO} 日以前）"
"${TIDY_UP_SCRIPT}" "${BACKUP_DIR}" "${DAYS_AGO}"

log "WordPress バックアップ完了"
echo "WordPress Backup Complete."</code></pre>



<h3 class="wp-block-heading"><span id="toc10">Wp-Restore.sh : データベース＆WordPressコンテンツの復元</span></h3>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-3d9f5d54fd4be61dae1b88182aa57068"><code>#!/bin/bash
#  WoredPress の復元
#    データベース(Mysql)とサーバーデータ(wp-content)
#  Wp-Restore.sh    2026/05 by Kazuban
#------------------------------------
#--- debug mode, set "DEBUG=1". -----
export DEBUG=
#------------------------------------
export CALLER_SCRIPT="$0"
#export SCRIPT_DIR=$(dirname "$(realpath "$0")")
SCRIPT_DIR=$(dirname "$(readlink -f "${BASH_SOURCE&#91;0]}")")
export SCRIPT_DIR
#------------------------------------
source "${SCRIPT_DIR}/Header.sh"
source "${SCRIPT_DIR}/WordPress_Config_Data.sh"
export BACKUP_DIR="${USER_DIR}/Backup/WordPress/${SUB_DIR}"
#---- MariaDB -----------------------
export MYSQL_RESTORE_SCRIPT="${SCRIPT_DIR}/MariaDB_Restore.sh"
export PRE_BACKUP_FILE="Pre-Backup.bak"
#---- WordPress ---------------------
export WP_RESTORE_SCRIPT="${SCRIPT_DIR}/Wp-Content_Restore.sh"
#------------------------------------
export PRE_BACKUP="Y"    # リストア前に現行 wp-content を退避するか Y/N
#-----　関数定義 -----------------------
#user_dir=$(pwd)
#echo $user_dir
# スクリプト終了時に実行させたい場合はここで再定義
cleanup() {
#  echo "Wp-Backup 終了処理"
  :
}
check_backup_dir(){
  if &#91; ! -d $BACKUP_DIR ]; then
    echo "バックアップディレクトリがありません！"
    exit 0 
  fi
}
cmd_mariadb()   { check_backup_dir; $MYSQL_RESTORE_SCRIPT; }
cmd_wordpress() { check_backup_dir; $WP_RESTORE_SCRIPT; }
cmd_all()       { cmd_mariadb; cmd_wordpress; }
cmd_help() {
  echo "--- WordPress Restor Script ---"
  echo "Directory: ${SCRIPT_DIR}"
  echo "Usage: $0 {db|wp|all|help}"
  echo "  db   = データベース(MariaDB)"
  echo "  wp   = Word Press (Wp-Content)"
  echo "  all  = db + wp"
  echo "  help = オプション"
}

#-----　メインプログラム　-------------
#------------------------------------
case "${1:-}" in
  db)        cmd_mariadb   ;;
  wp)        cmd_wordpress ;;
  all)       cmd_all       ;;
  help|"")   cmd_help      ;;
  *)
    echo "Unknown command: $1"
    cmd_help
    exit 1
    ;;
esac
</code></pre>



<h3 class="wp-block-heading"><span id="toc11">MariaDB_Restore.sh データベース復元（Wp-Restore.shから呼ばれる）</span></h3>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-a28f7d7ec979e0758768f998ce7ea057"><code>#!/bin/bash
#  WoredPress のデータベース復元スクリプト
#    MariaDB_Restore.sh    2026/05 by Kazuban
#------------------------------------
# 直接実行ガード（呼び出し元スクリプトからのみ実行可）
if &#91;&#91; -z "${CALLER_SCRIPT:-}" ]]; then
  echo "直接実行はできません。"
  echo "&#91;WP-Backup.sh db] から呼び出してください。"
  exit 1
fi
# --- debug mode: DEBUG=1 で有効 ---
#DEBUG=
PRE_BACKUP="Y"   # リストア前にバックアップを取るか Y/N
PRE_BACKUP_FILE="Pre-Backup.bak"
#------------------------------------
export SCRIPT_DIR=$(dirname "$(realpath "$0")")
#------------------------------------
source "${SCRIPT_DIR}/Header.sh"
source "${SCRIPT_DIR}/WordPress_Config_Data.sh"
#export BACKUP_DIR="${USER_DIR}/Backup/WordPress/${SUB_DIR}"
#------------------------------------

# ---- 関数定義 ---------------------------------------
# バックアップファイルの一覧を配列に格納する
load_backup_files() {
  BACKUP_FILES=()
  while IFS= read -r f; do
    BACKUP_FILES+=("$(basename "$f")")
  #done &lt; &lt;(find "${BACKUP_DIR}" -maxdepth 1 -name "*.bak" | sort)
  done &lt; &lt;(find "${BACKUP_DIR}" -maxdepth 1 -name "*-MariaDB.bak" | sort)
}

# 番号付きリストを表示する
list_backups() {
  echo "--------------------"
  echo "バックアップディレクトリ: ${BACKUP_DIR}"
  echo "--------------------"

  # --- # は個数を表し、&#91;@] は配列のすべての要素
  if &#91;&#91; ${#BACKUP_FILES&#91;@]} -eq 0 ]]; then
    echo "（バックアップファイルが見つかりません）"
  else
    local i=1
    for f in "${BACKUP_FILES&#91;@]}"; do
      printf "  &#91;%d] %s\n" "$i" "$f"
      (( i++ )) || true   # set -e 対策: (( )) は 0 になると終了コード 1 を返すため
    done
  fi
  echo "--------------------"
}

# 入力値（番号 or ファイル名）からファイル名を解決して返す
resolve_input() {
  local input="$1"

  # 数字のみ → 番号として解釈
  if &#91;&#91; "$input" =~ ^&#91;0-9]+$ ]]; then
    local idx=$(( input - 1 ))
    if (( idx &lt; 0 || idx >= ${#BACKUP_FILES&#91;@]} )); then
      echo "エラー: 番号 ${input} は範囲外です（1〜${#BACKUP_FILES&#91;@]}）" >&amp;2
      exit 1
    fi
    echo "${BACKUP_FILES&#91;$idx]}"
  else
    # 文字列 → ファイル名として解釈（リスト内に存在するか確認）
    local f
    for f in "${BACKUP_FILES&#91;@]}"; do
      if &#91;&#91; "$f" == "$input" ]]; then
        echo "$f"
        return
      fi
    done
    echo "エラー: ファイルが見つかりません: ${input}" >&amp;2
    exit 1
  fi
}

# 対話形式でファイルを選択させる
select_backup_file() {
  local selected=""
  while &#91;&#91; -z "$selected" ]]; do
    read -r -p "番号またはファイル名を入力してください (q で終了): " INPUT
    case "$INPUT" in
      &#91;qQ])
        kill -USR1 $$    # 親プロセス（スクリプト自身）にシグナルを送る
        exit 1;;
      "")   echo "入力してください" ;;
      *)    selected=$(resolve_input "$INPUT") ;;
    esac
  done
  echo "$selected"
}

usage() {
  echo "使い方: $(basename "$0") &#91;バックアップファイル名 or 番号]"
  echo "  引数なしで起動すると対話形式で選択できます。"
  echo "--------------------"
  list_backups
  exit 1
}

run_pre_backup() {
  local date_str
  date_str=$(date '+%Y%m%d-%H%M')
  local pre_backup_path="${BACKUP_DIR}/${date_str}-${PRE_BACKUP_FILE}"

  echo "--------------------"
  echo "-- 事前バックアップを開始します... --"

  #mysqldump \
  mariadb-dump \
    --user="${MYSQL_USER}" \
    --password="${MYSQL_USER_PASSWD}" \
    --host=localhost \
    --all-databases \
    --single-transaction \
    --quick \
    > "${pre_backup_path}"

  echo "-- 事前バックアップ完了: ${pre_backup_path} --"
  echo "--------------------"
}

run_restore() {
  local backup_file="${BACKUP_DIR}/${1}"

  echo "--------------------"
  echo "-- リストア対象: ${1} --"
  echo "-- データベース: ${DATABASE} --"
  echo "--------------------"

  read -r -p "リストアを実行しますか？ (y/n): " YN
  case "${YN}" in
    &#91;yY])
      echo "-- リストアを開始します... --"
      #mysql \
      mariadb \
        --user=root \
        --password="${MYSQL_ROOT_PASSWD}" \
        "${DATABASE}" \
        &lt; "${backup_file}"
      echo "-- リストア完了 --"
      ;;
    &#91;nN])
      kill -USR1 $$    # 親プロセス（スクリプト自身）にシグナルを送る
      exit 0
      echo "-- 中止しました --"
      exit 0
      ;;
    *)
      echo "エラー: y または n を入力してください" >&amp;2
      exit 1
      ;;
  esac
}

# ----- メイン処理 --------------------------------------------

# バックアップディレクトリの存在確認
if &#91;&#91; ! -d "${BACKUP_DIR}" ]]; then
  echo "エラー: バックアップディレクトリが存在しません: ${BACKUP_DIR}" >&amp;2
  exit 1
fi

# ファイル一覧をグローバル配列に読み込む
# declare 変数の属性やタイプ -a 「配列(Array)」
declare -a BACKUP_FILES
load_backup_files

# ヘルプ
if &#91;&#91; "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
  usage
fi

# ファイル選択：引数あり → 解決、なし → 対話形式
if &#91;&#91; $# -gt 0 ]]; then
  list_backups
  SELECTED_FILE=$(resolve_input "$1")
else
  list_backups
  SELECTED_FILE=$(select_backup_file)
fi

echo "-- 選択されたファイル: ${SELECTED_FILE} --"

# 事前バックアップ
if &#91;&#91; "${PRE_BACKUP}" =~ ^&#91;Yy]$ ]]; then
  run_pre_backup
fi

# リストア実行
run_restore "${SELECTED_FILE}"
</code></pre>



<h3 class="wp-block-heading"><span id="toc12">Wp-Content_Restore.sh: WordPressコンテンツ復元（Wp-Restore.shから呼ばれる）</span></h3>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-fef61f113342594a7adec7d5d6d3a478"><code>#!/bin/bash
#  wp-content ディレクトリの復元スクリプト
#    WP-Content_Restore.sh    2026/05 by Kazuban
#------------------------------------
# 直接実行ガード（呼び出し元スクリプトからのみ実行可）
if &#91;&#91; -z "${CALLER_SCRIPT:-}" ]]; then
  echo "直接実行はできません。"
  echo "&#91;WP-Backup.sh db] から呼び出してください。"
  exit 1
fi
# --- debug mode: DEBUG=1 で有効 ---
#export DEBUG=
PRE_BACKUP="Y"    # リストア前に現行 wp-content を退避するか Y/N
#------------------------------------
export SCRIPT_DIR=$(dirname "$(realpath "$0")")
#------------------------------------
source "${SCRIPT_DIR}/Header.sh"
source "${SCRIPT_DIR}/WordPress_Config_Data.sh"
#------------------------------------

# --- 関数定義 ---
# バックアップファイルの一覧を配列に格納する
load_backup_files() {
  BACKUP_FILES=()
  cmd="find ${BACKUP_DIR} -maxdepth 1 -name *-${WP_CONTENT_DIR}.tar.gz"  #${WP_CONTENT_DIR}
  while IFS= read -r f; do
    BACKUP_FILES+=("$(basename "$f")")
  done &lt; &lt;(find "${BACKUP_DIR}" -maxdepth 1 -name "*-${WP_CONTENT_FILENAME}.tar.gz" | sort)
}

# 番号付きリストを表示する
list_backups() {
  echo "--------------------"
  echo "バックアップディレクトリ: ${BACKUP_DIR}"
  echo "--------------------"

  if &#91;&#91; ${#BACKUP_FILES&#91;@]} -eq 0 ]]; then
    echo "（バックアップファイルが見つかりません）" >&amp;2
  else
    local i=1
    for f in "${BACKUP_FILES&#91;@]}"; do
      printf "  &#91;%d] %s\n" "$i" "$f"
      (( i++ )) || true   # set -e 対策: (( )) は 0 になると終了コード 1 を返すため
    done
  fi
  echo "--------------------"
}

# 入力値（番号 or ファイル名）からファイル名を解決して返す
resolve_input() {
  local input="$1"

  # 数字のみ → 番号として解釈
  if &#91;&#91; "$input" =~ ^&#91;0-9]+$ ]]; then
    local idx=$(( input - 1 ))
    if (( idx &lt; 0 || idx >= ${#BACKUP_FILES&#91;@]} )); then
      echo "エラー: 番号 ${input} は範囲外です（1〜${#BACKUP_FILES&#91;@]}）" >&amp;2
      exit 1
    fi
    echo "${BACKUP_FILES&#91;$idx]}"
  else
    # 文字列 → ファイル名として解釈（リスト内に存在するか確認）
    local f
    for f in "${BACKUP_FILES&#91;@]}"; do
      if &#91;&#91; "$f" == "$input" ]]; then
        echo "$f"
        return
      fi
    done
    echo "エラー: ファイルが見つかりません: ${input}" >&amp;2
    exit 1
  fi
}

# 対話形式でファイルを選択させる
select_backup_file() {
  local selected=""
  while &#91;&#91; -z "$selected" ]]; do
    read -r -p "番号またはファイル名を入力してください (q で終了): " INPUT
    case "$INPUT" in
      &#91;qQ])
        kill -USR1 $$
        exit 1 ;;
      "")   echo "入力してください" ;;
      *)    selected=$(resolve_input "$INPUT") ;;
    esac
  done
  echo "$selected"
}

# 使い方表示
usage() {
  echo "使い方: $(basename "$0") &#91;バックアップファイル名 or 番号]"
  echo "  引数なしで起動すると対話形式で選択できます。"
  echo "--------------------"
  list_backups
  exit 1
}

# 既存 wp-content を日付付きディレクトリ名にリネームして退避する
run_pre_backup() {
  local date_str
  date_str=$(date '+%Y%m%d-%H%M')
  local backup_path="${WP_CONTENT_PATH}-${date_str}.bak"

  echo "--------------------"
  echo "-- 事前バックアップ（退避）を開始します... --"
  echo "-- ${WP_CONTENT_PATH} → ${backup_path} --"
  sudo mv "${WP_CONTENT_PATH}" "${backup_path}"
  echo "-- 事前バックアップ完了 --"
  echo "--------------------"
}

# リストア実行
run_restore() {
  local backup_file="${BACKUP_DIR}/$1"
  local work_dir
  #work_dir=$(mktemp -d) #添付ディレクトリの利用
  work_dir=$BACKUP_DIR

  echo "--------------------"
  echo "-- リストア対象: $1 --"
  echo "-- 展開先 (${WP_CONTENT_DIR}): ${WP_CONTENT_PATH} --"
  echo "--------------------"

  read -r -p "リストアを実行しますか？ (y/n): " YN
  case "${YN}" in
    &#91;yY])
      echo "-- リストアを開始します... --"

      # 1. アーカイブ内の wp-content の階層数を確認
      echo "-- 展開中: ${backup_file} --"
      local wp_path strip_count

      list=$(tar tzf "${backup_file}")
      wp_path=$(echo "$list" | grep -m1 "${WP_CONTENT_DIR}/$" || true)
      echo "------ $wp_path --------"
      if &#91;&#91; -z "${wp_path}" ]]; then
        echo "エラー: アーカイブ内に ${WP_CONTENT_DIR} ディレクトリが見つかりません" >&amp;2
        exit 1
      fi
      # パスの / の数から除去する階層数を算出
      # 例: home/www/html/sweb01/wp-content/ → スラッシュ5個 → strip=4
      strip_count=$(echo "${wp_path}" | tr -cd '/' | wc -c)
      strip_count=$(( strip_count - 1 ))
      echo $strip_count
      #exit 1
      if &#91;&#91; $strip_count &lt; 0 ]]; then
        echo "エラー: 階層がありません" >&amp;2
        #echo "エラー: アーカイブ内に wp-content ディレクトリが見つかりません"
        exit 1
      fi
      #DIR="${work_dir}/wp-content"
      DIR=${work_dir}
      echo "${DIR}がない場合には作成します"
      mkdir -p "$DIR"
      # --strip-components で wp-content/ を作業ディレクトリ直下に展開
      tar xvzf "${backup_file}" -C "${DIR}" \
        --strip-components="${strip_count}"
      ls -la $DIR

      # 所定の場所に配置してオーナーを設定
      echo sudo mv "${work_dir}/${WP_CONTENT_DIR}" "${WP_CONTENT_PATH}"
      echo sudo chown -R "${WP_CONTENT_OWNER}" "${WP_CONTENT_PATH}/"
      sudo mv "${work_dir}/${WP_CONTENT_DIR}" "${WP_CONTENT_PATH}"
      sudo chown -R "${WP_CONTENT_OWNER}" "${WP_CONTENT_PATH}/"

      echo "-- リストア完了 --"
      # スクリプト終了時に作業ディレクトリを削除
      #trap 'rm -rf "${work_dir}"' EXIT

      ;;
    &#91;nN])
      kill -USR1 $$
      exit 0
      ;;
    *)
      echo "エラー: y または n を入力してください" >&amp;2
      exit 1
      ;;
  esac
}
cleanup() {
  echo Clean up!!
  echo ${BACKUP_DIR}
  #read -r -p "${BACKUP_DIR}/${WP_CONTENT_DIR} 削除しますか？ (Y/N): " INPUT
  #  case "$INPUT" in
  #    &#91;Yy])
  #      rm -rf "${BACKUP_DIR}/${WP_CONTENT_DIR}"  
  #  esac
}

# --- メイン処理 ---

# バックアップディレクトリの存在確認
if &#91;&#91; ! -d "${BACKUP_DIR}" ]]; then
  echo "エラー: バックアップディレクトリが存在しません: ${BACKUP_DIR}" >&amp;2
  exit 1
fi

# ファイル一覧をグローバル配列に読み込む
declare -a BACKUP_FILES
load_backup_files

# ヘルプ
if &#91;&#91; "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
  usage
fi

# ファイル選択：引数あり → 解決、なし → 対話形式
if &#91;&#91; $# -gt 0 ]]; then
  list_backups
  SELECTED_FILE=$(resolve_input "$1")
else
  list_backups
  SELECTED_FILE=$(select_backup_file)
fi

echo "-- 選択されたファイル: ${SELECTED_FILE} --"

# 事前バックアップ（現行 wp-content の退避）
if &#91;&#91; "${PRE_BACKUP}" =~ ^&#91;Yy]$ ]]; then
  run_pre_backup
fi

# リストア実行
run_restore "${SELECTED_FILE}"</code></pre>



<h3 class="wp-block-heading"><span id="toc13">Header.sh : デバッグモード仕様（変数 DEBUG=1 で有効）</span></h3>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-f6fe5a69aecaa3ebf64dfc0071ef4ec8"><code>#!/bin/bash
#
#  Header.sh    2026/05 by AI &amp; Kazuban
#  共通ヘッダー: source で読み込んで使う
#  使い方: source "${SCRIPT_DIR}/Header.sh"
#
#------------------------------------
#-e：失敗で停止：#-u：未定義変数禁止:#pipefail：パイプの途中も検知
set -euo pipefail

# --- traps ---
trap 'echo "-- 中止しました --"; exit 0' USR1
trap 'echo "Error at line $LINENO"; exit 1' ERR
trap cleanup EXIT

# cleanup は呼び出し元スクリプトで上書き可能
cleanup() {
  :
}

# --- debug mode: DEBUG=1 で有効 ---
export DEBUG=${DEBUG:-0}
if &#91;&#91; "$DEBUG" == "1" ]]; then
  echo "Debug mode is 'true' !! "
  export PS4='+ ${LINENO}: '
  set -x
  trap 'read -p "STEP> " &lt; /dev/tty' DEBUG
else
  echo "Debug mode is 'false' !! "
fi
</code></pre>



<h3 class="wp-block-heading"><span id="toc14">Tidyup_backfile.sh : バックアップファイルの整理（引数：対象ディレクトリ・保存日数）</span></h3>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-9c8922dee15a171fe661e7414cd13d49"><code>#!/bin/bash
# Delete $DAY days ago from backup
#
#  Tidyup_backfile.sh  by AI &amp; Kazuban 2026/05
#                default 10 days ago
#
#------------------------
# delete_backup - バックアップファイルを整理するスクリプト
# 使用方法: delete_backup &#91;削除対象ディレクトリ] &#91;何日前まで残すか]

#set -euo pipefail
#--- for debag ----------------------
#--- デバッグモード（DEBUG=1 で有効）---
#if &#91;&#91; "${DEBUG:-0}" == "1" ]]; then
#  export PS4='+ ${LINENO}: '
#  set -x
#  trap 'read -p "STEP> " &lt; /dev/tty' DEBUG
#fi

readonly SCRIPT_NAME="$(basename "$0")"

usage() {
    echo "使用方法: ${SCRIPT_NAME} &lt;削除対象ディレクトリ> &#91;保持日数]"
    echo "  削除対象ディレクトリ  : バックアップファイルのあるディレクトリ"
    echo "  保持日数              : 何日前までのファイルを残すか (デフォルト: 10)"
    exit 1
}

# --- 引数チェック ---
if &#91;&#91; $# -lt 1 || "$1" == "-?" || "$1" == "-h" || "$1" == "--help" ]]; then
    usage
fi

TARGET_DIR="$1"
DAYS="${2:-10}"

# --- 数値チェック ---
if ! &#91;&#91; "$DAYS" =~ ^&#91;0-9]+$ ]]; then
    echo "エラー: 保持日数には正の整数を指定してください: ${DAYS}" >&amp;2
    exit 1
fi

# --- ディレクトリ存在チェック ---
if &#91;&#91; ! -d "$TARGET_DIR" ]]; then
    echo "エラー: ディレクトリが見つかりません: ${TARGET_DIR}" >&amp;2
    exit 1
fi

# --- 削除基準日を算出 ---
DEL_DATE="$(date --date="${DAYS} days ago" +%Y%m%d)"
echo "削除基準日: ${DEL_DATE} より前のファイルを削除します (保持日数: ${DAYS}日)"

# --- 対象ファイルの処理 ---
# 数字始まりのファイル名から先頭8桁(YYYYMMDD)を取得して重複排除
while IFS= read -r file_date; do
    if &#91;&#91; "$file_date" &lt; "$DEL_DATE" ]]; then
        echo "削除: ${TARGET_DIR}/${file_date}*"
        rm -f -- "${TARGET_DIR}/${file_date}"*
    fi
done &lt; &lt;(
    ls -- "$TARGET_DIR" \
        | grep -E '^&#91;0-9]' \
        | awk '{ print substr($0, 1, 8) }' \
        | sort -u
)

echo "完了"</code></pre>



<h2 class="wp-block-heading"><span id="toc15">自動バックアップ</span></h2>



<p class="wp-block-paragraph"><a href="https://www.kazuban.com/blog/rokeylinux9-3-wordpress-backup/#toc10">こちらでも、紹介していますが</a>、「crontab」に下記のように設定する事で、毎日２時に自動バックアップできるようになります</p>



<pre class="wp-block-code"><code>00 2 * * *        /home/kazuban/Backup/bin/Wp-Backup.sh all</code></pre>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.kazuban.com/blog/rokeylinux9-7-wordpress-backup/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Python正規表現に挑戦 ― Fanuc系NCブロックをNCワードに分解させる</title>
		<link>https://www.kazuban.com/blog/python-regex/</link>
		
		<dc:creator><![CDATA[kazuban]]></dc:creator>
		<pubDate>Thu, 05 Feb 2026 00:40:01 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[NC]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[G-Code]]></category>
		<category><![CDATA[ＮＣデータ]]></category>
		<category><![CDATA[NCプログラム]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[正規表現]]></category>
		<guid isPermaLink="false">https://www.kazuban.com/blog/?p=12021</guid>

					<description><![CDATA[このサイトでは、NCデータの解析・変換などの自作アプリを公開しています。これまでは C++Builder で自作ライブラリを作成し開発してきました。独学ゆえに効率や可読性など課題は沢山ありますが、いまさら見直す気にもなり [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">このサイトでは、<a href="https://www.kazuban.com/blog/free_soft/">NCデータの解析・変換などの自作アプリを公開</a>しています。<br>これまでは C++Builder で自作ライブラリを作成し開発してきました。<br>独学ゆえに効率や可読性など課題は沢山ありますが、いまさら見直す気にもなりません。<br>最近は Python の学習もかねてNCデータ解析ライブラリのpythonへの移行を考えています。<br>AI の登場で、素人でも高度なコードを得られる時代になりましたが、意味を理解せずに使うのはやはり危険ですし、プログラミングスキルは向上しません。<br>この記事を書くきっかけは<br>「Fanuc系NCブロックをNCワードに分割させる、pythonスクリプトをだして」<br>へのAIの回答に正規表現が使われていた事から始まりました<br>本記事では、「一見意味不明な呪文のような正規表現」を理解して行く過程を記事にしました。</p>




  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-4" checked><label class="toc-title" for="toc-checkbox-4">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">正規表現</a><ol><li><a href="#toc2" tabindex="0">概要</a></li><li><a href="#toc3" tabindex="0">1. 文字列とリテラル</a></li><li><a href="#toc4" tabindex="0">2. メタ文字（特別な意味を持つ記号）</a><ol><li><a href="#toc5" tabindex="0">具体例</a></li></ol></li><li><a href="#toc6" tabindex="0">3. 繰り返し回数の指定（量指定子）</a><ol><li><a href="#toc7" tabindex="0">具体例</a></li></ol></li><li><a href="#toc8" tabindex="0">4. 文字クラス</a></li><li><a href="#toc9" tabindex="0">5. 代表的なエスケープシーケンス</a></li><li><a href="#toc10" tabindex="0">6. エスケープが必要な記号</a></li><li><a href="#toc11" tabindex="0">補足</a></li></ol></li><li><a href="#toc12" tabindex="0">ファナック系、NCデータ構造</a><ol><li><a href="#toc13" tabindex="0">
「ワード」＝「アドレス」+「数字・数値」
「ブロック」＝「ワード」の集まり
「NCデータ」＝「ブロック」の集まり
</a></li></ol></li><li><a href="#toc14" tabindex="0">ブロックから正規表現でワードに分解する</a><ol><li><a href="#toc15" tabindex="0">アドレスと数字抽出</a></li><li><a href="#toc16" tabindex="0">さらに、アドレスと数字を分けて抽出したい場合</a></li><li><a href="#toc17" tabindex="0">軸（X,Y,Z・・）の小数点にも対応させる</a></li><li><a href="#toc18" tabindex="0">複雑な正規表現の可読性を高める</a></li><li><a href="#toc19" tabindex="0">さらにちょっと特殊な、G や M　コードにも対応させてみます</a></li><li><a href="#toc20" tabindex="0">正規表現のraw文字列の変数化</a></li></ol></li><li><a href="#toc21" tabindex="0">まとめ</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">正規表現</span></h2>



<p class="wp-block-paragraph">正規表現の情報は、ネット上に豊富にあると思うので、詳細は検索してみてください。<br>下記は「正規表現」の説明をAIに聞いてみた回答です</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<h3 class="wp-block-heading"><span id="toc2"><a>概要</a></span></h3>



<p class="wp-block-paragraph">本チャットログでは、「正規表現（Regular Expression）」の基本要素について、最小限かつ代表的な機能に絞って説明している。主な用途は文字列の検索・置換・抽出であり、「文字列パターンを表現する小さな言語」として位置付けている。</p>



<h3 class="wp-block-heading"><span id="toc3"><a>1. </a>文字列とリテラル</span></h3>



<ul class="wp-block-list">
<li>abc
<ul class="wp-block-list">
<li>文字列「abc」にそのままマッチするパターン。</li>
</ul>
</li>
</ul>



<h3 class="wp-block-heading"><span id="toc4"><a>2. </a>メタ文字（特別な意味を持つ記号）</span></h3>



<ul class="wp-block-list">
<li>. : 任意の1文字</li>



<li>^ : 行頭</li>



<li>$ : 行末</li>



<li>* : 直前要素の0回以上の繰り返し</li>



<li>+ : 直前要素の1回以上の繰り返し</li>



<li>? : 直前要素の0回または1回</li>



<li>| : OR（または）</li>



<li>() : グループ化・キャプチャ</li>
</ul>



<h4 class="wp-block-heading"><span id="toc5"><a>具体例</a></span></h4>



<ul class="wp-block-list">
<li>a.*b
<ul class="wp-block-list">
<li>「a」で始まり「b」で終わる行全体にマッチ（間の文字列は任意長）</li>
</ul>
</li>



<li>colou?r
<ul class="wp-block-list">
<li>color または colour にマッチ（u がある/ない両方に対応）。</li>
</ul>
</li>
</ul>



<h3 class="wp-block-heading"><span id="toc6"><a>3. </a>繰り返し回数の指定（量指定子）</span></h3>



<ul class="wp-block-list">
<li>{n} : ちょうど n 回</li>



<li>{n,} : n 回以上</li>



<li>{n,m} : n〜m 回</li>
</ul>



<h4 class="wp-block-heading"><span id="toc7"><a>具体例</a></span></h4>



<ul class="wp-block-list">
<li>\d{3}-\d{4}
<ul class="wp-block-list">
<li>123-4567 のような「数字3桁-数字4桁」形式にマッチ。</li>
</ul>
</li>
</ul>



<h3 class="wp-block-heading"><span id="toc8"><a>4. </a>文字クラス</span></h3>



<ul class="wp-block-list">
<li>[abc] : a か b か c のいずれか1文字</li>



<li>[^abc] : a,b,c 以外の1文字</li>



<li>[0-9] : 数字</li>



<li>[A-Za-z] : 英字（大文字・小文字）</li>
</ul>



<h3 class="wp-block-heading"><span id="toc9"><a>5. </a>代表的なエスケープシーケンス</span></h3>



<p class="wp-block-paragraph">多くの処理系で共通して使われるもの。</p>



<ul class="wp-block-list">
<li>\d : 数字 [0-9]</li>



<li>\w : 単語構成文字（英数字 + _）</li>



<li>\s : 空白文字（スペース・タブ・改行など）</li>



<li>\D : 非数字（\d 以外）</li>



<li>\W : 非単語構成文字（\w 以外）</li>



<li>\S : 非空白文字（\s 以外）</li>
</ul>



<h3 class="wp-block-heading"><span id="toc10"><a>6. </a>エスケープが必要な記号</span></h3>



<p class="wp-block-paragraph">次の文字はメタ文字として特別な意味を持つため、そのままの記号として扱うにはバックスラッシュでエスケープする必要がある。</p>



<ul class="wp-block-list">
<li>対象文字
<ul class="wp-block-list">
<li>. * + ? ^ $ ( ) [ ] { } | \</li>
</ul>
</li>



<li>使用例<ul><li>\. : ドットそのものにマッチ</li></ul>
<ul class="wp-block-list">
<li>\? : 疑問符そのものにマッチ</li>
</ul>
</li>
</ul>



<h3 class="wp-block-heading"><span id="toc11"><a>補足</a></span></h3>



<p class="wp-block-paragraph">ここまでが「基本の道具」としての正規表現の要素一式であり、今後はこれらを組み合わせて「メールアドレスの簡易チェック」など、実用的なパターン作成にも応用できると示唆している。</p>
</blockquote>



<p class="wp-block-paragraph">個別でみれば、なんとなくわかる気もしますが、これが組み合わさると、まったく呪文です<br>ただ、いろんなパターンの質問とAIの回答を照らし合わせると、なんとなく理解できてくるので、正規表現にかぎらず、AIは言語学習資料としても本当に役立ちます。</p>



<h2 class="wp-block-heading"><span id="toc12">ファナック系、NCデータ構造</span></h2>



<p class="wp-block-paragraph">NCデータの分析ソフトを検討する場合、NCデータ構造の知識は必須です<br>NCデータの知識がないまま、AIの回答だけで進めると、間違いなく後々苦労します<br>ファナック系のプログラム構造は、下記記事でも紹介しています</p>



<figure class="wp-block-embed is-type-wp-embed"><div class="wp-block-embed__wrapper">

<a href="https://www.kazuban.com/blog/nc-gcode-01/#toc2" title="NCプログラム／プログラム構造" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img decoding="async" width="203" height="180" src="https://www.kazuban.com/blog/wp-content/uploads/2019/11/NcData-1.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://www.kazuban.com/blog/wp-content/uploads/2019/11/NcData-1.png 879w, https://www.kazuban.com/blog/wp-content/uploads/2019/11/NcData-1-300x266.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2019/11/NcData-1-768x681.png 768w" sizes="(max-width: 203px) 100vw, 203px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">NCプログラム／プログラム構造</div><div class="blogcard-snippet internal-blogcard-snippet">最近の投稿は、覚書きとしても残しておきたかったので、素人ながらLinux系の投稿が連続していましたが、今回は気分を変えて、今まで携わってきたＮＣ関連の記事を書こうと思います。ＮＣプログラムとは？ＮＣ工作機械のコントローラへの指令の集まりです。プログラムとありますが、ファナック系は基本的には命令コード...</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://www.kazuban.com/blog" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">www.kazuban.com</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2019.11.30</div></div></div></div></a>
</div></figure>



<h3 class="wp-block-heading has-text-align-left"><span id="toc13">
「ワード」＝「アドレス」+「数字・数値」<br>
「ブロック」＝「ワード」の集まり<br>
「NCデータ」＝「ブロック」の集まり
</span></h3>



<p class="wp-block-paragraph">NCブロックからNCアドレスを抽出する課題なので、NCコードを少し復習しておきます</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="262" src="https://www.kazuban.com/blog/wp-content/uploads/2019/11/図1-1024x262.png" alt="" class="wp-image-1338" srcset="https://www.kazuban.com/blog/wp-content/uploads/2019/11/図1-1024x262.png 1024w, https://www.kazuban.com/blog/wp-content/uploads/2019/11/図1-300x77.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2019/11/図1-768x197.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2019/11/図1.png 1385w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">ブロックの末尾は制御器では「EOB」ですが、PC側では改行コードになります<br>改行コードはOSにより変わりますが、基本的にアスキー形式での転送で大丈夫だと思います<br>NCデータの最小単位は、「ワード」と呼ばれていて、<br>「アルファベット一文字」+「数字、符号、小数点」が一塊になっている要素です<br>例えば「G02」とか「X-12.345」の構成です。<br>先頭のアドレス文字で機械への指令の種類を表し、ワードで具体的な指令になります<br>この「ワード」が集まり、一行の構成になった文字列が「ブロック」と呼ばれます<br>さらに、「ブロック」が複数行あつまって、NCデータになります<br>CAM利用の場合、作成したNCデータファイルをNC機械へ転送し加工動作を制御します<br>分析ソフトを検討する場合、まずはNCデータをブロックに、ブロックをワードに分解したほうが整理しやすいです<br>今回の課題では、<span class="marker-under-red">正規表現</span>を利用して<span class="marker-under">「ブロック」を「ワード」に分解する</span>コードを作成します<br>やりたい事をAIに投げかけると、それなりの回答をもらえます。<br>ただ、ＮＣコードのように、機種依存や複雑な表現がある場合、AIへすべて完ぺきなコードを期待してもなかなか思うような回答は得られません。<br>また、最初は良くても開発を進めていくうちに、改造したくなる場合もあります<br>やはり、ある程度の理解は必要です。</p>



<h2 class="wp-block-heading"><span id="toc14">ブロックから正規表現でワードに分解する</span></h2>



<p class="wp-block-paragraph">具体的に正規表現を書き、「ワード」に分解した結果と照らし合わせながら理解を進めようと思います<br>「ワード」＝「大文字アルファベット一文字」+「数字」なので、一番単純な正規表現のパターンは、&#8221;[A-Z]\d&#8221;になります<br>また、正規表現パターンで、文字列から部分文字列を抽出するのに、AIは「re.findall関数」を教えてくれました<br>（findall関数についての詳細は、ネット検索やAIに聞いてみてください）<br>サンプル文字列は複数のパターンを織り交ぜた、&#8221;G0G1G00 G03M3 T102M30&#8243;　でやってみます<br>（文字列並びのみのサンプルで、NCデータとしては意味ありません）</p>



<h3 class="wp-block-heading"><span id="toc15">アドレスと数字抽出</span></h3>



<pre class="wp-block-code"><code>import re

block = "G0G1G00 G03M3 T102M30" # サンプルNCブロック文字列
words = re.findall(r"<strong>&#91;A-Z]\d</strong>", block)
print(f"{words}")

#---------- 結果 --------------
#&#91;'G0', 'G1', 'G0', 'G0', 'M3', 'T1', 'M3']</code></pre>



<p class="wp-block-paragraph">ちょっと期待とは違いますが、とりあえずは、アドレスと数字がリストで取り出せました<br>たった一行で分解された文字列リストが作成されました、すごいですね～<br>一文字づつ文字列操作で処理させたら、結構なコード量になっていると思います<br>ただ、「\d」としたため、「数字は<strong>一文字</strong>」しか抽出してくれませんでした<br>ここで「\d{2}」としてみると、「数字二文字」のみ取り出してくれます<br>今回の例ですべて取り出すには「\d{1,3}」とすればすべてヒットします<br>「\d+」でも同様の結果になりますが、こちらの方は文字数制限はなくなります<br>今回のサンプルでは、&#8221;[A-Z]\d+&#8221;で行こうと思います<br>ちなみに、「\d{0}」とすると、アドレスのみ取り出せます。</p>



<pre class="wp-block-code"><code>import re

block = "G0G1G00 G03M3 T102M30" # サンプルNCブロック文字列
words = re.findall(r"<strong>&#91;A-Z]\d+</strong>", block)
print(f"{words}")

#---------- 結果 --------------
#&#91;'G0', 'G1', 'G00', 'G03', 'M3', 'T102', 'M30']</code></pre>



<h3 class="wp-block-heading"><span id="toc16">さらに、アドレスと数字を分けて抽出したい場合</span></h3>



<p class="wp-block-paragraph">グループ化と呼ばれる（丸括弧）でパターンを囲むと「tuple」として分離してくれます<br>抽出した後の処理内容によっては、こちらが便利かもしれません</p>



<pre class="wp-block-code"><code>import re

block = "G0G1G00 G03M3 T102M30" # サンプルNCブロック文字列
words = re.findall(r"<strong>(&#91;A-Z])(\d+)</strong>", block)
print(f"{words}")
for addr, val in words:
    print(f"addr={addr}:val={val}")

#---------- 結果 --------------
#&#91;('G', '0'), ('G', '1'), ('G', '00'), ('G', '03'), ('M', '3'), ('T', '102'), ('M', '30')]
#addr=G:val=0
#addr=G:val=1
#addr=G:val=00
#addr=G:val=03
#addr=M:val=3
#addr=T:val=102
#addr=M:val=30</code></pre>



<h3 class="wp-block-heading"><span id="toc17">軸（X,Y,Z・・）の小数点にも対応させる</span></h3>



<p class="wp-block-paragraph">ここまでは、GやMコードでしたが、軸指令に対応するには、<span class="marker-under">符号や小数点</span>も考慮する必要があります<br>余談ですがプログラミング初心者の場合勘違いしやすいのが、<span class="marker-under-red"><strong>数字</strong>と<strong>数値</strong>の違い</span>です。<br>「12.23」の場合、<strong>数値</strong>としては「12 + 0.23」のように演算ができますが、<br><strong>数字</strong>の場合は、「1」「2」「.」「2」「3」と途中に「.」があるだけのただの数字文字の連続です<br>正規表現の場合も、数字・符号・小数点の<strong>文字の集まり</strong>として処理するので、数値で考えてしまうと期待と違う結果になり、悩む事になります<br>さて、文字を意識してサンプル文字列データに軸指令を追加して、上記のコードで実行してみます</p>



<pre class="wp-block-code"><code>import re

block = "G90G01 <strong>X12.5Y+20.3Z-5.63</strong>F1000" # サンプルNCブロック文字列
words = re.findall(r"<strong>&#91;A-Z]\d+</strong>", block)
print(f"{words}")

#---------- 結果 --------------
#&#91;'G90', 'G01', 'X12', 'F1000']</code></pre>



<p class="wp-block-paragraph">やはりこのコードでは、±符号と小数点が入るとマッチしないので、省かれてしまいますね<br>まず符号に対応するためにはアドレス「A-Z」の後に[+-]を追加します</p>



<pre class="wp-block-code"><code>import re

block = "G90G01 X12.5Y+20.3Z-5.63F1000" # サンプルNCブロック文字列
words = re.findall(r"<strong>&#91;A-Z]&#91;+-]\d+</strong>", block)
print(f"{words}")

#---------- 結果 --------------
#&#91;'Y+20', 'Z-5']</code></pre>



<p class="wp-block-paragraph">これでは、符号「+-」が必須に判断され符号付の文字列しかヒットしませんでした<br>符号文字は<span class="marker-under">「無くてもいい」</span>の意味で<span class="marker-under"><strong>[+-]?</strong></span>としてみます</p>



<pre class="wp-block-code"><code>import re

block = "G90G01 X12.5Y+20.3Z-5.63F1000" # サンプルNCブロック文字列
words = re.findall(r"<strong>&#91;A-Z]&#91;+-]?\d+</strong>", block)
print(f"{words}")

#---------- 結果 --------------
#&#91;'G90', 'G01', 'X12', 'Y+20', 'Z-5', 'F1000']</code></pre>



<p class="wp-block-paragraph">符号部分を<span class="marker">[+-]?</span> とすることで、符号がなくてもマッチするようになりました<br>次に小数点とそれ以下にも対応させてみましょう<br>NC制御器は、数値として扱いますが、文字としての小数点の扱いは結構面倒です。<br>小数点がある場合、ない場合、小数点から始まる場合、小数点で終わる場合・・など<br>まずは、小数点の有無に対応させるため、「<strong>\d+\.\d+</strong>」を考えましたが、<br>この場合、小数点がないとマッチしなくなります<br>そこで「？を付加」すれば「無くてもいい」にも対応できます</p>



<pre class="wp-block-code"><code>import re

block = "G90G01 X12.5Y+20.3Z-5.63F1000" # サンプルNCブロック文字列
words = re.findall(r"<strong>&#91;A-Z]&#91;+-]?\d+\.?\d+</strong>", block)
print(f"{words}")

#---------- 結果 --------------
&#91;'G90', 'G01', 'X12.5', 'Y+20.3', 'Z-5.63', 'F1000']
</code></pre>



<p class="wp-block-paragraph">だいぶ理想に近づいてきましたが、「X.124」や「23.」など、小数点での始まりや終わりには対応できません<br>サンプル文字列に追加して確かめてみましょう</p>



<pre class="wp-block-code"><code>import re

block = "G90G01 X12.50Y+20.3Z-5.63 <span class="marker"><strong>I.5 J22.</strong></span>F1000" # サンプルNCブロック文字列
words = re.findall(r"<strong>&#91;A-Z]&#91;+-]?\d+\.?\d+"</strong>, block)
print(f"{words}")

#---------- 結果 --------------
#&#91;'G90', 'G01', 'X12.50', 'Y+20.3', 'Z-5.63', '<span class="marker-red">J22</span>', 'F1000</code></pre>



<p class="wp-block-paragraph">やはり、「I.5」にはマッチせず「J22.」の「.」は省かれていますね<br>ここも余談ですが、NCで「<strong>22.</strong>」を「<strong>22</strong>」に変換してしまった場合、制御器によってはとんでもない事になりかねないので十分意識しておく必要があります。<br><br>整理してみると</p>



<ul class="wp-block-list">
<li>[A-Z]：NCコードのアドレス</li>



<li>[+-]?：必須ではない、符号</li>



<li>\d+：複数個の数字<br>ここまでで、「Gコード」「Mコード」には対応できている</li>



<li>\.?：小数点は必須でない</li>



<li>\d+：複数個の数字</li>
</ul>



<p class="wp-block-paragraph">やはり、「小数点で終わる」場合「\.?」なので、省略されてしまいますね<br>ではどうすればいのか？<br>AIに聞いたところ、グループ化と言う方法があり、&#8221;( )&#8221;で囲む事で、一塊としてでマッチングのルール設定できるようです<br>ただし、&#8221;( )&#8221;では、囲みごとに分割されタプルのリストとして抽出されます<br>グループごとに分割させたくない場合には<span class="marker-under"><strong>&#8220;(?: )</strong>&#8220;で囲む</span>仕様があり<span class="marker-under">非キャプチャグループ</span>と呼ばれマッチングのルールには使用するが分割はされないようです。<br>今回の例では、分割させたくないので、&#8221;<strong>(?: )</strong>&#8220;を使ってみます<br>最後の「\d+：複数個の数字」をグループ化して、必須ではない複数個の数字として設定します</p>



<pre class="wp-block-code"><code>import re

block = "G90G01 X12.50Y+20.3Z-5.63 <span class="marker"><strong>I.5 J22.</strong></span>F1000" # サンプルNCブロック文字列
words = re.findall(r"&#91;A-Z]&#91;+-]?\d+\.?<strong>(?:\d+)?</strong>", block)
print(f"{words}")

#---------- 結果 --------------
#&#91;'G90', 'G01', 'X12.50', 'Y+20.3', 'Z-5.63', '<span class="marker"><strong>J22.</strong></span>', 'F1000']</code></pre>



<p class="wp-block-paragraph">これで、「22.」には対応できました。次は、小数点で始まる「.5」の場合です。<br>ここまででも、結構な呪文になっているのに、さらに複雑になりそうです。<br>ここもAIに相談すると、グループの中で（A | B）の書式で「AまたはB」とマッチング範囲の選択ができるようで、この書式での書き方を教えてくました</p>



<pre class="wp-block-code"><code>import re

block = "G90G01 X12.50Y+20.3Z-5.63 <span class="marker"><strong>I.5 J22.</strong></span>F1000" # サンプルNCブロック文字列
words = re.findall(r"&#91;A-Z]&#91;+-]?(?:<span class="marker-under-blue">\d+\.\d+</span><strong>|</strong><span class="marker-under">\d+\.</span><strong>|</strong><span class="marker-under-red">\.\d+</span><strong>|</strong>\d+)", block)
print(f"{words}")

#---------- 結果 --------------
#&#91;'G90', 'G01', 'X12.50', 'Y+20.3', 'Z-5.63', <span class="marker"><strong>'I.5'</strong>, <strong>'J22.'</strong></span>, 'F1000']</code></pre>



<ul class="wp-block-list">
<li>[A-Z]：NCコードのアドレス</li>



<li>[+-]?：必須ではない、符号</li>



<li>&#8212; ここからグループ化 &#8212;</li>



<li>\d+\.\d+：数字+小数点+数字<br>または</li>



<li>\d+\.：数字+小数点<br>または</li>



<li>\.\d+:小数点+数字<br>または</li>



<li>\d+：複数個の数字のみ</li>
</ul>



<p class="wp-block-paragraph">書き方は他にもあると思いますが、グループ化して、マッチさせたいパターンを一つ一つORで区切るこの方法は私には理解しやすかったです</p>



<h3 class="wp-block-heading"><span id="toc18">複雑な正規表現の可読性を高める</span></h3>



<p class="wp-block-paragraph">いちおう動作はしましたが、ここまでくると、読みにくいですね～<br>可読性を高める方法として、さらにAIが「re.VERBOSE」を提案してくれました<br>具体的に、上記のコードを書き替えてみます<br>パターンを一行づつに分割できて、行ごとにコメントも追記できるので、複雑になってもわかりやすくなります</p>



<pre class="wp-block-code"><code>pattern = re.compile(
    r"""
    &#91;A-Z]        # A-Zアドレス
    &#91;+-]?         # 符号
    (?:           # 小数点処理、非キャプチャグループ
      \d+\.\d+      # 数字、小数点、数字
      |\d+\.        # または、数字、小数点
      |\.\d+        # または、小数点、数字
      |\d+          # または、数字のみ
    )
    """,
    re.VERBOSE,
)
words = pattern.findall(block)
print(f"{words}")

#---------- 結果 --------------
#&#91;'G90', 'G01', 'X12.50', 'Y+20.3', 'Z-5.63', 'I.5', 'J22.', 'F1000']</code></pre>



<h3 class="wp-block-heading"><span id="toc19">さらにちょっと特殊な、G や M　コードにも対応させてみます</span></h3>



<p class="wp-block-paragraph">通常、NCワードは「アドレス＋数字」ですが、拡張されたワーク座標系指令やサブプロ呼び出しなどちょっと特殊な構成のコードもあります<br>全てに対応は難しいと思いますが、「G54.1P1」や「M98P100」などにも対応してみようと思います。<br>これら対応するためには、上記のパターンでは処理できないのでパターンを追加します<br>やはり、可読性が上がる、re.VERBOSE を利用します</p>



<pre class="wp-block-code"><code>block = (
    "G05P10000 G90G01 X12.50Y+20.3Z-5.63 I.5 J22.F1000 G54 G54.1P12 M98P1100 M198 P2299"
)
pattern = re.compile(
    r"""
    # --- 特殊構成、G54.1P12 / M98P1234　など---
    &#91;GM]          # G や M アドレス
    \d+(?:\.\d+)? # 54　や　54.1 
    \s*P\d+       # スペースとP文字と数字
    # --- 通常のアドレス+数字 ----
    |&#91;A-Z]        # A-Zアドレス
    &#91;+-]?         # 符号
    # --- 小数点対応 ----
    (?:           # 非キャプチャグループ
      \d+\.\d+      # 数字、小数点、数字
      |\d+\.        # または、数字、小数点
      |\.\d+        # または、小数点、数字
      |\d+          # または、数字のみ
    )
    """,
    re.VERBOSE,
)
words = pattern.findall(block)
print(f"{words}")

#---------- 結果 --------------
#&#91;'G05P10000', 'G90', 'G01', 'X12.50', 'Y+20.3', 'Z-5.63', 'I.5', 'J22.', 'F1000', 'G54', 'G54.1P12', 'M98P1100', 'M198 P2299']</code></pre>



<p class="wp-block-paragraph">どうにかできました。<br>次の課題は「G04X10.」とかにも対応したいと思っていますが、これ以上条件が増えると大変です<br>正規表現パターンを変数化できれば、もう少しわかりやすいと思います</p>



<h3 class="wp-block-heading"><span id="toc20">正規表現のraw文字列の変数化</span></h3>



<p class="wp-block-paragraph">AIに聞いてみました。さすがAI、できますよ！との回答をもらいました<br>AIの回答を参考に上記コードを書き直してみました。</p>



<pre class="wp-block-code"><code>block = (
    "G05P10000 G90G01 X12.50Y+20.3Z-5.63 I.5 J22.F1000 G54 G54.1P12 M98P1100 M198 P2299"
)
num = r"&#91;+-]?(?:\d+\.\d+|\d+\.|\.\d+|\d+)"  # +12.123|-24.|.56|30
g54_1 = r"&#91;GM]\d+(?:\.\d+)?\s*P\d+\.?"      # G54.1P1 M98P1122
nomal = r"&#91;A-Z]"  # 通常のアドレス
pattern = re.compile(
    rf"""     
    {g54_1}         # G54.1P1 , M98P1122
    #----------------------
    |{nomal}{num}   # G01 , X-12.356
    """,
    re.VERBOSE,
)
words = pattern.findall(block)
#---------- 結果 --------------
#&#91;'G05P10000', 'G90', 'G01', 'X12.50', 'Y+20.3', 'Z-5.63', 'I.5', 'J22.', 'F1000', 'G54', 'G54.1P12', 'M98P1100', 'M198 P2299']</code></pre>



<p class="wp-block-paragraph">なるほど、だいぶ見やすくなりました<br>今後の仕様変更にも対応しやすくなったと思います<br>興味ある方は是非、「G04X10.」への対応もやってみてください。</p>



<h2 class="wp-block-heading"><span id="toc21">まとめ</span></h2>



<p class="wp-block-paragraph">これまでも単純な正規表現に触れる機会はありましたが、複雑な記述はまるで「呪文」のようで、敬遠していました。 <br>しかし、正規表現は文字列操作において非常に強力な武器になります。<br>独学ではやる気なしでしたが、AIと対話する事で、ある程度は理解できてきました。<br> 今後もAIと対話しながら一歩ずつ分析していくことで、正規表現だけでなく、プログラミング言語全体の理解力も深めていけると感じています。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Fusion360 APIでTkinterを使ってみた。単純UIならこれでよくない？ボタンクリックでXYZ軸の基準線を作図するFusionスクリプトを実行させてみた</title>
		<link>https://www.kazuban.com/blog/python-api-tkinter01/</link>
		
		<dc:creator><![CDATA[kazuban]]></dc:creator>
		<pubDate>Fri, 09 Jan 2026 04:52:45 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[Fusion360]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://www.kazuban.com/blog/?p=11788</guid>

					<description><![CDATA[少し前から、Python 学習の一環として AI に相談しながら Fusion 360 の API を触っており、その過程を以前の記事で紹介しました。 この記事では、Fusionの標準APIの2D スケッチで頻繁に使うオ [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">少し前から、Python 学習の一環として AI に相談しながら Fusion 360 の API<strong> </strong>を触っており、その過程を以前の記事で紹介しました。</p>



<figure class="wp-block-embed is-type-wp-embed"><div class="wp-block-embed__wrapper">

<a href="https://www.kazuban.com/blog/fusion-python-api/" title="Fusion360  Python API 再挑戦！AIの力を借りて、sketchなど基本ライブラリを作ってみた。" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="160" height="90" src="https://www.kazuban.com/blog/wp-content/uploads/2025/07/fusion-python-api-160x90.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/07/fusion-python-api-160x90.png 160w, https://www.kazuban.com/blog/wp-content/uploads/2025/07/fusion-python-api-120x68.png 120w, https://www.kazuban.com/blog/wp-content/uploads/2025/07/fusion-python-api-320x180.png 320w" sizes="(max-width: 160px) 100vw, 160px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">Fusion360  Python API 再挑戦！AIの力を借りて、sketchなど基本ライブラリを作ってみた。</div><div class="blogcard-snippet internal-blogcard-snippet">Aiと言う強い味方を得て、Fusion API に再挑戦しています。pythonの学習もかねて、skrtch関連の関数をライブラリ化しています。筆者の環境では、正常に動作しています。コピペで利用可。Aiに教えてもらわないと、作成できなかった実例をレポートしています。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://www.kazuban.com/blog" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">www.kazuban.com</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2025.07.09</div></div></div></div></a>
</div></figure>



<p class="wp-block-paragraph">この記事では、Fusionの標準APIの2D スケッチで頻繁に使うオブジェクトをカプセル化しライブラリとしてまとめてみました。<br>Fusion 360 はパラメトリックモデリングを前提としているため、まずラフに図形を描き、あとから寸法線や拘束を追加して形状を詰めていく、という作業フローが基本です。<br>試行錯誤しながら設計を煮詰めていく用途では非常に強力な手法ですが、CAM 作業のように、すでに図面や数値が確定している場合には、この手順がやや回りくどく感じることもあります。<br>またFusion 360 には原点の概念はありますが、原点を強く意識しないモデリング手法であるため、「図面ありき」の CAM 作業では、座標原点を通る中心線作図から始めるようにしています<br>ところが、この最初に描いた中心線も拘束や固定を忘れると、気づかないうちに移動させてしまい、後工程で大きなトラブルになることがあります。</p>



<p class="has-watery-red-background-color has-background has-medium-font-size wp-block-paragraph" style="border-width:1px"><strong>固定された座標軸を、簡単かつ確実に作図したい</strong><br>　　──まずこれが、スクリプト作成を始めたきっかけです。</p>



<p class="wp-block-paragraph">また、スケッチ平面に対して高低差のある傾いた線を引きたい場合や、<br>平面からの異なる高さに円を描きたい場合なども、標準操作では少し手間がかかります。<br>前回作成したライブラリでは、直線や円といったシンプルな作図であれば、<span class="marker-under-blue">数値を引数として渡す</span>だけで描画できるところまでは実現しています。<br>ただし、実用面を考えると、やはり <span class="marker-under-red">GUI ダイアログ形式で数値入力できる仕様にしたい</span>というのが今回の取り組みです。</p>




  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-6" checked><label class="toc-title" for="toc-checkbox-6">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">Fusion API標準機能のコマンド UIでダイアログ仕様</a></li><li><a href="#toc2" tabindex="0">単純入力フォームに、tkinter を使ってみる</a><ol><li><a href="#toc3" tabindex="0">中心線作図スクリプト</a></li></ol></li><li><a href="#toc4" tabindex="0">表示されたボタンをクリックして、関数を実行するスクリプト</a><ol><li><a href="#toc5" tabindex="0">ボタンクリックで起動させる、tk.Button　の　command　オプション</a></li><li><a href="#toc6" tabindex="0">関数名の () の有無による違い</a><ol><li><a href="#toc7" tabindex="0">1. かっこがない場合 (cmd1)</a></li><li><a href="#toc8" tabindex="0">2. かっこがある場合 (cmd1())</a></li></ol></li><li><a href="#toc9" tabindex="0">lambda（ラムダ式）を使う</a></li></ol></li><li><a href="#toc10" tabindex="0">Tkinterは、Autodesk 非公式</a><ol><li><a href="#toc11" tabindex="0">Fusion API で、tkinter を使用する場合の注意点</a></li><li><a href="#toc12" tabindex="0">run(context) の context引数 は必須</a></li></ol></li><li><a href="#toc13" tabindex="0">数値入力ダイアログで、座標軸を作図するスクリプトをボタンで起動</a><ol><li><a href="#toc14" tabindex="0">サンプルスクリプトのダウンロードと使い方</a></li></ol></li><li><a href="#toc15" tabindex="0">第一弾、終了</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">Fusion API標準機能のコマンド UIでダイアログ仕様</span></h2>



<p class="wp-block-paragraph">Fusion API には、コマンドに付随する入力ダイアログ機能が標準で用意されており、テキストボックスやドロップダウンリスト、スライダーといった一般的な UI 要素を利用できます。<br>これらの UI 要素は <strong>Command Inputs </strong>オブジェクトを使って定義します。<br>コマンドが作成される際に呼び出される CommandCreated イベントハンドラ内で Command Inputs を作成し、コマンドの入力ダイアログに表示する入力フィールドを定義します。<br>その後、Execute イベントハンドラ内で、ユーザーがダイアログ上で入力した値を取得し、処理を実行します。<br>このように Fusion API のコマンドはイベント駆動で構成されており、各イベントハンドラを通して入力値を扱う必要があります。<br>とりあえずコード化してみましたが、初級者の私にとっては処理の流れを理解するのが難解でとりあえずネット情報やAIを参考に作成してみました<br>下記は、標準コマンドダイアログへの入力値を<a href="https://www.kazuban.com/blog/fusion-python-api/#toc16">上記で紹介している</a>「lib_2d.draw_center_line(x, y, z)スクリプトに取り込んでＸ，Ｙ，Ｚ座標軸線を作図させるスクリプトです</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="311" height="170" src="https://www.kazuban.com/blog/wp-content/uploads/2025/12/CommandDialog-e1767571988839.png" alt="" class="wp-image-11807" style="width:285px" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/12/CommandDialog-e1767571988839.png 311w, https://www.kazuban.com/blog/wp-content/uploads/2025/12/CommandDialog-e1767571988839-300x164.png 300w" sizes="(max-width: 311px) 100vw, 311px" /></figure>



<p class="wp-block-paragraph">class CommonAddinFramework:<br>　&#8221;&#8221;&#8221;<br>　Fusion 360 アドインの共通フレームワーククラス。<br>　ダイアログの表示、入力値の取得および指定された描画コールバック関数の実行を管理<br>　&#8221;&#8221;&#8221;<br>　def __init__(<br>　　self,<br>　　command_id: str,<br>　　button_name: str,<br>　　description: str,<br>　　input_defaults: dict,<br>　　drawing_callback,<br>　):<br><br>・・・・<br>・・・・</p>



<p class="wp-block-paragraph"><a href="https://www.kazuban.com/blog/fusion-api-commandhandler/" target="_blank">コード全体を表示</a></p>
</blockquote>



<h2 class="wp-block-heading"><span id="toc2">単純入力フォームに、tkinter を使ってみる</span></h2>



<p class="wp-block-paragraph">上記でFusion標準のコマンドUIを使って、寸法入力で座標軸線を作画できるようになりましたが、今後機能を増やしていくには、やはりイベント処理ではわかり辛く煩わしく感じますし、ネット上の情報も少ないです<br>そこで、Python標準のtkinterを使ってみました<br>tkinterはpython標準ライブラリなので、さすがにこちらは、情報豊富です</p>



<h3 class="wp-block-heading"><span id="toc3">中心線作図スクリプト</span></h3>



<p class="wp-block-paragraph">かなりAIに助けてもらいましたが<br><a href="https://www.kazuban.com/blog/fusion-python-api/#toc16">上記記事内</a>で作成した中心線スクリプトに入力数値を渡すダイアログをtkinterを利用して作成してみました。<br>最初にメッセージ表示の「label」を配置して、「entry」で設定値入力ボックスを配置<br>さらに、固定とコンストラクション設定用の「Checkbutton」を配置して作成ボタンで、作図させる仕様です</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="372" height="282" src="https://www.kazuban.com/blog/wp-content/uploads/2025/12/tkinter-center-line.png" alt="" class="wp-image-11809" style="width:285px" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/12/tkinter-center-line.png 372w, https://www.kazuban.com/blog/wp-content/uploads/2025/12/tkinter-center-line-300x227.png 300w" sizes="(max-width: 372px) 100vw, 372px" /></figure>



<p class="wp-block-paragraph"># &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br># ダイアログクラス <br># &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br>class DialogPanel(tk.Tk):<br>　def __init__(<br>　　self,<br>　　input_defaults: Dict[str, float],<br>　　construction,<br>　　fixed,<br>　):<br><br>・・・・<br>・・・・</p>



<p class="wp-block-paragraph"><a href="https://www.kazuban.com/blog/draw-centerline-by-tkinter/" target="_blank">コード全体を表示</a></p>
</blockquote>



<p class="wp-block-paragraph">この「DialogPanel」クラスをアレンジして、直線や円などを作図する入力ダイアログも追加作成していきます。<br>このスクリプトをFuisonの「スクリプトとアドイン」に登録すれば、作図スクリプトをダイレクト数値入力仕様で実行できるようになります。<br>私的には、FusionAPIのCommand Inputsよりもわかりやすいです。</p>



<h2 class="wp-block-heading"><span id="toc4">表示されたボタンをクリックして、関数を実行するスクリプト</span></h2>



<p class="wp-block-paragraph">いくつかコマンドダイアログを作成していくと、いちいち「スクリプトとアドイン」へ登録するのも面倒になってきます。<br>FusionAPIでもFusionタスクバーにコマンド実行プルダウンを追加できるようですが、これもまた敷居が高いです。<br>今回は、tkinterでメニュー用パネルを作成し、そのメニューボタンで作図スクリプトを起動できれば、メニューだけの登録で済みます。</p>



<h3 class="wp-block-heading"><span id="toc5">ボタンクリックで起動させる、tk.Button　の　command　オプション</span></h3>



<p class="wp-block-paragraph">ボタンクリックで関数を実行させるには「command」オプションに関数名を渡すと実行できます</p>



<pre class="wp-block-code"><code># 起動させたい関数
def <strong><span class="marker-red">cmd1()</span></strong>:
    print("Function is cmd1().")
・・・
・・・
# ボタンクリックで、「def cmd1()」関数を起動する
tk.Button(
        root,
        text="Execute_command01",
        <strong>command=<span class="marker-red">cmd1</span></strong>
)</code></pre>



<p class="wp-block-paragraph">ここで初心者の筆者が疑問に感じたのが、「<strong>command=cmd1</strong>」の書き方です<br>関数名は「cmd1()」なのに、「commandオプション」には&#8221;( )&#8221;が付かないようです<br>この関数名の&#8221;( )&#8221;の有無について、AIに聞いてみました</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<h3 class="wp-block-heading"><span id="toc6">関数名の <code>()</code> の有無による違い</span></h3>



<h4 class="wp-block-heading"><span id="toc7">1. かっこがない場合 (<code>cmd1</code>)</span></h4>



<p class="wp-block-paragraph">かっこがない場合、それは<strong>関数そのもの（オブジェクト）</strong> を指します。これは「<strong>関数というデータ</strong>」として扱われます。</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><td><strong>意味</strong></td><td><strong>関数そのものを指す（データ）</strong></td></tr></thead><tbody><tr><td>例</td><td><code>data = { "menu1": cmd1 }</code></td></tr><tr><td>目的</td><td>関数を<strong>変数に代入</strong>したり、<code>tk.Button</code> の <code>command</code> のように<strong>他の関数に引数として渡す</strong>とき。</td></tr><tr><td>動作</td><td><strong>処理はまだ実行されない</strong>。ただ関数の場所を渡すだけ。</td></tr></tbody></table></figure>



<h4 class="wp-block-heading"><span id="toc8">2. かっこがある場合 (<code>cmd1()</code>)</span></h4>



<p class="wp-block-paragraph">かっこがある場合、それは<strong>関数の実行（呼び出し）</strong> を意味します。</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><td><strong>意味</strong></td><td><strong>関数の処理を今すぐ実行する</strong></td></tr></thead><tbody><tr><td>例</td><td><code>cmd1()</code></td></tr><tr><td>目的</td><td>関数に書かれている<strong>処理をすぐに実行</strong>し、その<strong>戻り値（結果）</strong> を受け取るとき。</td></tr><tr><td>動作</td><td><strong>すぐに処理が実行される</strong>。もし戻り値があれば、その結果が残る。</td></tr></tbody></table></figure>
</blockquote>



<p class="wp-block-paragraph">なるほど～<br>&#8220;( )&#8221;がない場合には、C言語での<strong>ポインタ渡し</strong>のようなイメージですかね<br>&#8220;( )&#8221;を付けると、「すぐに実行される」との事なので、<br>クリック後実行させたい、「tk.Button」の「command」オプションには、使えないですね<br>したがってTkinterのcommand は、<strong><span class="marker-under-red">引数なし</span></strong><span class="marker-under-red">で呼び出せるものを要求</span>すると言うことになります<br>では、引数や戻り値を利用したい関数を実行するにはどうするか？</p>



<h3 class="wp-block-heading"><span id="toc9">lambda（ラムダ式）を使う</span></h3>



<p class="wp-block-paragraph">lambda は、短い無名関数（名前のない一時的な関数）を簡単に作るためのPythonの機能ですが、デフォルト引数を設定できるけど、実行時には引数なしで呼び出されるようです<br>したがって、「tk.Button」の「command」に利用できます<br>具体的には、<mark style="background-color:#fdf2f2" class="has-inline-color">「lambda 引数1,引数2…：引数を使った処理」</mark>のように記述します</p>



<pre class="wp-block-code"><code>def exec(function, msg):
    function(msg)
・・・・・・
・・・・・・
command = lambda <strong>msg</strong>="button click!", <strong>func</strong>=cmd1: exec(<strong>func, msg</strong>)</code></pre>



<p class="wp-block-paragraph">このように、関数：execに、func, msg　の引数を渡せば<br>「func名」の関数に「引数msg」を渡して実行できます<br>簡単な、サンプルコードを書いてみました</p>



<pre class="wp-block-code"><code>"""Execute a function on button click."""

import traceback
import adsk.core
import adsk.fusion

# import adsk.cam

import tkinter as tk


def disp_message(msg: str):
    app = adsk.core.Application.get()
    ui = app.userInterface
    ui.messageBox(f"{msg}")


def print_cmd1():
    disp_message("lambda is not used.")


def print_cmd2(msg: str):
    disp_message(msg)


def exec(function, msg):
    function(msg)


def run(context):
# def run():
    root = tk.Tk()
    label1 = tk.Label(
        root,
        text="Click the button.",
        bg="light cyan",
    )
    label1.pack()
    # ---------------------------------
    tk.Button(
        root,
        text="Execute1",
        command=<span class="bold-red">print_cmd1</span>,
    ).pack(side=tk.LEFT, padx=10, pady=10)
    # ---------------------------------
    tk.Button(
        root,
        text="Execute2",
        command=<span class="bold-red">lambda m="center button click!", f=print_cmd2: exec(f, m)</span>,
    ).pack(side=tk.LEFT, padx=10, pady=10)
    # ---------------------------------
    tk.Button(
        root,
        text="Execute3",
        command=<span class="bold-red">lambda m="right button click!", f=print_cmd2: exec(f, m)</span>,
    ).pack(side=tk.LEFT, padx=10, pady=10)
    root.mainloop()
</code></pre>



<p class="wp-block-paragraph">こんな感じで、「ボタン」を並べれば、ボタンクリック仕様のコマンド実行メニューが作成できそうです</p>



<h2 class="wp-block-heading"><span id="toc10">Tkinterは、Autodesk 非公式</span></h2>



<p class="wp-block-paragraph">「tk.Button」と「lambda」で、メニューダイアログが作れそうです<br><a href="#toc3">上記で紹介</a>した座標軸センターラインを作図するスクリプトを実行するダイアログを作成してみます<br>ところが、Tkinterの使用は、Autodeskは非公式のようなので注意が必要です</p>



<h3 class="wp-block-heading"><span id="toc11">Fusion API で、tkinter を使用する場合の注意点</span></h3>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">・Tkinterの使用は、Autodesk 非公式<br>・Tkinter が <code>root.mainloop()</code> で動作中は Fusion 本体の操作は一切できなくなる <br>・Mac + Tkinter は挙動が不安定なことがある<br>・Tkinterウィンドウを閉じた時に不安定になる場合がある<br>・最悪、タスクマネージャーでFusion 強制終了</p>
</blockquote>



<p class="wp-block-paragraph">やはり、Autodesk側としては、あまり推奨はしていないようです<br>常駐ツールやモーダルな本格的ダイアログはやめたほうがよさそうです<br>今回作成中も、閉じる時に「Script Error」が出たり、強制終了の必要に迫られたりしましたが、数値入力や条件入力の簡易パネルとして、<span class="marker-under-red">開いたら閉じて、Fusionに制御を返す</span>ような単純な処理であれば利用できると思っています。<br></p>



<h3 class="wp-block-heading"><span id="toc12">run(context) の context引数 は必須</span></h3>



<p class="wp-block-paragraph">python学習もかねて、いろいろ簡単なコードを書きました。<br>コードが悪いと、Fusionを強制終了させざるを得ない場合もありましたが、普通に問題なく動作しているのに、パネルの「×ボタン」で終了時に、Fusionのコマンドエリアに「SCRIPT ERROR」が出た事もありました。<br>これの原因究明には結構時間がかかりました。<br>上記のサンプルコードでも、run(context)の「context」は使っていないからと、<br>省略すると（「def run():」）「SCRIPT ERROR」になり、なにも動作しない状態になります<br>やはり、FusionAPIがどこかで使っていて、必須なようです<br>「×」での「SCRIPT ERROR」は終了時の警告のみなので、無視しようとも思いましたが、気味が悪いので、とりあえずAIにもいろいろも相談しましたが、的確な回答はもらえませんでした。<br>例えば下記コードで終了時に「SCRIPT ERROR」になります。<br>引数に「tk.Tk()型」を渡しました。結局、この引数が原因でした</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">def run1(root):<br>　&nbsp; &nbsp; label1 = tk.Label(root , text=&#8221;Click the button.&#8221;)<br>　　・・・・<br>　　・・・・<br><br>master = tk.Tk()<br>run1(master)</p>
</blockquote>



<p class="wp-block-paragraph">Fusionの「スクリプトとアドイン」で、「スクリプトまたはアドインを作成」を選択すると、自動的にサンプルスクリプトが作成されるので、そちらを参考にしてみました。<br>Fusionで自動作成された、run関数の中身は下記のようになっています</p>



<pre class="wp-block-code"><code>def run(_context: str):
    """This function is called by Fusion when the script is run."""

    try:
        # Your code goes here.
        ui.messageBox(f'"{app.activeDocument.name}" is the active Document.')
    except:  #pylint:disable=bare-except
        # Write the error message to the TEXT COMMANDS window.
        app.log(f'Failed:\n{traceback.format_exc()}')</code></pre>



<p class="wp-block-paragraph">引数は「_context: str」となっています。<br>以前のサンプルコードには、「str」のような型ヒントはなかったように記憶していますが<br>「str」なので引数の型は「文字列型」を期待しているようです。<br>このサンプルでも「_context」はどこにも使われていないように見えますが、やはりFusionAPI側では必須なのでしょう<br>ちなみにデフォルトでは「_context: str」と、型ヒントでは「文字列型」となっていますが、下記コードを追加して調べてみました</p>



<pre class="wp-block-code"><code>    ui.messageBox(f"type={type(_context)}")
    ui.messageBox(f"{_context}")</code></pre>



<p class="wp-block-paragraph">そのタイプと内容を表示させてみると</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">type=<strong>&lt;class &#8216;dict&#8217;&gt;</strong><br><strong>{&#8216;IsApplicationStartup&#8217;: False}</strong></p>
</blockquote>



<p class="wp-block-paragraph">このように、「辞書型」になっていました。<br>詳細はわかりませんが、メイン関数の第一引数はFusionが使うので、別の引数を使いたい場合には、追加の形をとったほうがよさそうです<br>この部分を変更すると正常に終了するようになりました。<br>pythonのこういった型のあいまいな部分にも、まだまだ慣れないです</p>



<h2 class="wp-block-heading"><span id="toc13">数値入力ダイアログで、座標軸を作図するスクリプトをボタンで起動</span></h2>



<p class="wp-block-paragraph">さて、上記で紹介した「中心線作図スクリプト」を、ボタンクリックで動作させるダイアログを作成してみようと思います。<br>ただし、このスクリプトは、<a href="https://www.kazuban.com/blog/fusion-python-api/">以前紹介した記事</a>内のライブラリ「<a href="https://www.kazuban.com/blog/fusion-python-api/#toc15">lib_util.py</a>」「<a href="https://www.kazuban.com/blog/fusion-python-api/#toc16">lib_2d.py</a>」を利用するので、もし試してみたい場合にはそちらも必要になります<br>下記に全部含まれたコードをダウンロードできるようにしておきますので、興味ある方がいらっしゃれば試してみてください。</p>



<pre class="wp-block-code"><code>"""Execute a function on button click."""

import adsk.core
import adsk.fusion
import os, sys, importlib, traceback
import tkinter as tk

import tkinter.font as tkFont
from typing import Optional, List, Dict, Any

current_dir = os.path.dirname(os.path.abspath(__file__))
script_dir = os.path.dirname(current_dir)  # C:\FusionAPI\Scripts
sys.path.append(script_dir)
# library import
"""
C:\FusionAPI\Scripts
│
├─library
│  ├─lib_util.py
│  ├─lib_2d.py
├─test
│  ├─menu.py (This script)
"""
from library import lib_util, lib_2d


##---------------------------
def disp_message(msg: str):
    lib_util.disp_message(msg)


# ------------------------------------------------------------------
# ダイアログクラス
# ------------------------------------------------------------------
class DialogPanel(tk.Tk):
    """センターライン作画ダイアログ"""

    def __init__(
        self,
        input_defaults: Dict&#91;str, float],
        construction,
        fixed,
    ):
        super().__init__()
        # self.my_font = None
        self.input_defaults = input_defaults
        self.x_width: float = 0.0
        self.y_width: float = 0.0
        self.z_width: float = 0.0
        self.construction: bool = construction
        self.fixed: bool = fixed
        self.widths: dict&#91;str, tk.DoubleVar] = {}
        self._create_widgets()

    def _simple_frame(self, **kwargs) -&gt; tk.Frame:
        # Fontインスタンスを作成
        self.my_font = tkFont.Font(family="Arial", size=10, weight="normal")
        """単純フレームを作成し、ウィンドウ全体に展開"""
        master = self
        frame = tk.Frame(master, **kwargs)
        master.title("Center Line")
        frame.pack(fill="both", expand=True, padx=5, pady=5)
        return frame

    def _create_widgets(self):
        """全てのUI要素を作成"""
        # 全体を包む単一のフレーム
        self.main_frame = self._simple_frame(relief="ridge", bd=5)

        # ------------------
        # 0. トップメッセージ
        # ------------------
        row_idx = 0
        top_frame = tk.Frame(self.main_frame)
        top_frame.grid(row=row_idx, column=0, columnspan=3, pady=10)
        tk.Label(
            top_frame,
            text="各軸の長さを指定してください。\n作成したくない軸は「0.0」にしてください",
            bg="light cyan",
            font=self.my_font,
        ).pack()
        # ------------------
        # 1～3 各軸幅入力ボックス
        # ------------------

        row_idx += 1
        # 事前設定のラベルとデフォルト値
        for label, default in self.input_defaults.items():
            tk.Label(
                self.main_frame,
                text=label,
                font=self.my_font,
            ).grid(
                row=row_idx,
                column=0,
                sticky="e",
            )
            var = tk.DoubleVar(value=default)
            ent = tk.Entry(
                self.main_frame,
                font=self.my_font,
                textvariable=var,
                width=10,
                bg="lightyellow",
                # bg="ivory",
            )
            ent.grid(row=row_idx, column=1)
            self.widths&#91;label] = var
            row_idx += 1
        # ------------------
        # 4. 要素固定チェック
        # ------------------
        row_idx += 1
        # self.fixed_check = tk.BooleanVar(value=True)
        self.fixed_check = tk.BooleanVar(value=self.fixed)
        check_button = tk.Checkbutton(
            self.main_frame,
            text="要素固定",
            variable=self.fixed_check,
            font=self.my_font,
        )
        check_button.grid(row=row_idx, column=0, padx=5, pady=5, sticky="w")
        # self.construction_check = tk.BooleanVar(value=True)
        self.construction_check = tk.BooleanVar(value=self.construction)
        check_button = tk.Checkbutton(
            self.main_frame,
            text="コンストラクション",
            variable=self.construction_check,
            font=self.my_font,
        )
        check_button.grid(row=row_idx, column=1, padx=5, pady=5, sticky="w")

        # ------------------
        # 5. 最終確定ボタン
        # ------------------
        row_idx += 1
        # ボタンを格納するボトムフレーム
        bottom_frame = tk.Frame(self.main_frame)
        bottom_frame.grid(row=row_idx, column=0, columnspan=3, pady=10)

        tk.Button(
            bottom_frame, text="作成実行", font=self.my_font, command=self.get_data
        ).pack(side=tk.LEFT, padx=10)
        tk.Button(
            bottom_frame, text="閉じる", font=self.my_font, command=self.destroy
        ).pack(side=tk.LEFT, padx=10)

    def get_data(self):
        """入力データを取り出す"""
        v: List = &#91;]
        for value in self.widths.values():
            v.append(value.get())
        self.x_width = float(v&#91;0])
        self.y_width = float(v&#91;1])
        self.z_width = float(v&#91;2])
        self.fixed = self.fixed_check.get()
        self.construction = self.construction_check.get()
        self.destroy()


##--------------------------------------------------------------
##--------------------------------------------------------------
def diarog_test(master):
    """センターライン作画"""
    if master:
        master.quit()  # mainloop を終了させる
        master.destroy()
    input_defaults = {
        "X軸長さ": 50.0,
        "Y軸長さ": 50.0,
        "Z軸長さ": 10.0,
    }
    # 線種指定
    construction = True
    fixed = True

    app = DialogPanel(input_defaults, construction, fixed)
    app.mainloop()
    wx = app.x_width
    wy = app.y_width
    wz = app.z_width
    construction = app.construction
    fixed = app.fixed
    try:
        lib_2d.draw_center_line(wx, wy, wz, construction, fixed)
    except:
        disp_message("Failed:\n{}".format(traceback.format_exc()))


# ---- Action command after button click ----------


def print_cmd1():
    disp_message("lambda is not used.")


def print_cmd2(msg: str):
    disp_message(msg)


def exec(function, msg):
    function(msg)


def on_closing(root):
    """Processing when the window's 'x' button is pressed"""
    disp_message("I'll close now!")
    root.quit()  # Terminate the mainloop
    root.destroy()  # Releases window resources.


def button(root: tk.Tk):
    # Window close action
    root.protocol("WM_DELETE_WINDOW", lambda: on_closing(root))
    label1 = tk.Label(root, text="Click the button you like.", bg="light cyan")
    label1.pack()
    tk.Button(root, text="Message1", command=print_cmd1).pack(
        side=tk.LEFT, padx=10, pady=10
    )
    tk.Button(
        root,
        text="Message2",
        command=lambda m="Lambda specification!", f=print_cmd2: exec(f, m),
    ).pack(side=tk.LEFT, padx=10, pady=10)
    tk.Button(
        root,
        text="Draw center line",
        command=lambda tk=root, f=diarog_test: exec(f, tk),
    ).pack(side=tk.LEFT, padx=10, pady=10)
    root.mainloop()


def run(context: dict):  # {'IsApplicationStartup': False}
    root = tk.Tk()
    root.attributes("-topmost", True)  # Bring Window To Top
    button(root)
</code></pre>



<h3 class="wp-block-heading"><span id="toc14">サンプルスクリプトのダウンロードと使い方</span></h3>



<p class="wp-block-paragraph">ダウンロードと使用方法は下記を参考にしてください<br>この例では、展開されたトップフォルダ「FusinAPI_kazuban」を「Cドライブ」の直下に、コピーする方法で説明していますが、任意の場所でかまいません<br>ただし、<span class="marker-under">Fusionが立ち上がった状態</span>では、キャッシュの影響で「library」内のスクリプトがうまく読み込めない事があります<br><span class="marker-under-red">コピー後に、Fusionを起動する</span>方がトラブル少ないです。<br>そのトップフォルダ下の「Scripts」、その下の「library」「menyu01」内のスクリプトを使用します<br>全ての使用ライブラリも含めたZIPファイルは下記からのダウンロードできます</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="348" height="125" src="https://www.kazuban.com/blog/wp-content/uploads/2026/01/python-api-tkinter01.png" alt="" class="wp-image-11941" srcset="https://www.kazuban.com/blog/wp-content/uploads/2026/01/python-api-tkinter01.png 348w, https://www.kazuban.com/blog/wp-content/uploads/2026/01/python-api-tkinter01-300x108.png 300w" sizes="(max-width: 348px) 100vw, 348px" /></figure>



<div class="wp-block-file"><a id="wp-block-file--media-11c24981-b4de-424e-be88-7ef09c825cf3" href="https://www.kazuban.com/blog/wp-content/uploads/2026/01/FusinAPI_kazuban.zip">FusinAPI_kazuban</a><a href="https://www.kazuban.com/blog/wp-content/uploads/2026/01/FusinAPI_kazuban.zip" class="wp-block-file__button wp-element-button" download aria-describedby="wp-block-file--media-11c24981-b4de-424e-be88-7ef09c825cf3">ダウンロード</a></div>



<pre class="wp-block-preformatted">C:\FusinAPI_kazuban<br>└─Scripts<br>    ├─library<br>        └─lib_2d.py<br>        └─lib_util.py<br>    └─menyu01<br>        └─menu.py</pre>



<p class="wp-block-paragraph">・ダウンロード後展開した「FusinAPI_kazuban」を適当なフォルダへコピー<br>・Fusionの「スクリプトとアドイン」から「menyu01」を選択する<br>・正常に登録されると、スクリプトが実行できます</p>



<figure class="wp-block-video"><video height="1028" style="aspect-ratio: 1496 / 1028;" width="1496" controls src="https://www.kazuban.com/blog/wp-content/uploads/2026/01/python-api-tkinter01.mp4"></video></figure>
</blockquote>



<h2 class="wp-block-heading"><span id="toc15">第一弾、終了</span></h2>



<p class="wp-block-paragraph">とりあえず、Autodesk Fusion からtkinterオブジェクトのパネルを表示し、ボタンに割り当てられたスクリプト動作をさせる事ができました。<br>数値入力用ボタンでは、tkinterへの入力値をFusionAPIに渡し、作図させる事ができるようになりました<br>次回は、もう少し作図スクリプトとメニューを充実させていきたいと思います</p>





<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
		
		<enclosure url="https://www.kazuban.com/blog/wp-content/uploads/2026/01/python-api-tkinter01.mp4" length="9464158" type="video/mp4" />

			</item>
		<item>
		<title>2025/10月から、自宅サーバーのPostFixからプロバイダー経由のメール送信ができなくなった！</title>
		<link>https://www.kazuban.com/blog/postfix_new_setting/</link>
		
		<dc:creator><![CDATA[kazuban]]></dc:creator>
		<pubDate>Sat, 04 Oct 2025 06:36:58 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[Linux (CentOS、Rocky、Ubuntu)]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[postfix]]></category>
		<category><![CDATA[smtp]]></category>
		<category><![CDATA[生成Ai]]></category>
		<guid isPermaLink="false">https://www.kazuban.com/blog/?p=11507</guid>

					<description><![CDATA[外部からのログイン時や、ブログのバックアップ時など自動的にEメールが届くように設定していますが、今月（2025/10）に入ってからメールが届かなくなっていました。既存設定は下記で記事にしましたが、送信メール専用の運用です [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">外部からのログイン時や、ブログのバックアップ時など自動的にEメールが届くように設定していますが、今月（2025/10）に入ってからメールが届かなくなっていました。<br>既存設定は下記で記事にしましたが、送信メール専用の運用です</p>



<figure class="wp-block-embed is-type-wp-embed"><div class="wp-block-embed__wrapper">

<a href="https://www.kazuban.com/blog/rockylinux9-3-postfix/" title="RockyLinux9.３で自宅サーバーを再構築V08・postfix で送信専用メールサーバー構築" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="160" height="90" src="https://www.kazuban.com/blog/wp-content/uploads/2023/12/postfix-160x90.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://www.kazuban.com/blog/wp-content/uploads/2023/12/postfix-160x90.png 160w, https://www.kazuban.com/blog/wp-content/uploads/2023/12/postfix-120x68.png 120w, https://www.kazuban.com/blog/wp-content/uploads/2023/12/postfix-320x180.png 320w" sizes="(max-width: 160px) 100vw, 160px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">RockyLinux9.３で自宅サーバーを再構築V08・postfix で送信専用メールサーバー構築</div><div class="blogcard-snippet internal-blogcard-snippet">このサイトには「お問い合わせフォーム」を設定していますし、起動しているサーバーがエラーなどの連絡を発信する場合もあります。重要なメールもあるので、メインのメールアドレスへ配信させる設定を行います。今回は、サーバー側から、配信するのみの設定を行います</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://www.kazuban.com/blog" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">www.kazuban.com</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2024.01.08</div></div></div></div></a>
</div></figure>



<p class="wp-block-paragraph">この設定により、このブログサイトへの、「お問い合わせ」も設置できているのですが、この不具合では、「お問い合わせ」もこちらに届きません<br>う～ん、困った。</p>




  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-8" checked><label class="toc-title" for="toc-checkbox-8">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">こんな時ほど、Aiに相談だぁ！</a><ol><li><a href="#toc2" tabindex="0">Aiのエラー内容の整理</a><ol><li><a href="#toc3" tabindex="0">主な原因候補</a></li></ol></li><li><a href="#toc4" tabindex="0">確認方法</a><ol><li><a href="#toc5" tabindex="0">状況まとめ</a></li></ol></li><li><a href="#toc6" tabindex="0">解決方法</a></li><li><a href="#toc7" tabindex="0">解決策（おすすめ）</a><ol><li><a href="#toc8" tabindex="0">プロバイダのSMTPサーバを経由する（最も現実的）</a></li></ol></li><li><a href="#toc9" tabindex="0">整理すると</a></li></ol></li><li><a href="#toc10" tabindex="0">設定方法</a><ol><li><a href="#toc11" tabindex="0">認証情報ファイルを作成</a></li><li><a href="#toc12" tabindex="0">Postfix設定ファイルを修正</a></li><li><a href="#toc13" tabindex="0">ハッシュ化して権限設定</a></li><li><a href="#toc14" tabindex="0">Postfix再起動</a></li><li><a href="#toc15" tabindex="0">テスト送信</a></li><li><a href="#toc16" tabindex="0">確認</a></li><li><a href="#toc17" tabindex="0">後日、Gmailへの転送がNGになった</a><ol><li><a href="#toc18" tabindex="0">ここも、AIに聞いてみる</a></li></ol></li><li><a href="#toc19" tabindex="0">AIが問題点指摘</a><ol><li><a href="#toc20" tabindex="0">A. kazuban.com のDNSにSPFレコードを追加（推奨）</a></li></ol></li></ol></li><li><a href="#toc21" tabindex="0">正常にもどった</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">こんな時ほど、Aiに相談だぁ！</span></h2>



<p class="wp-block-paragraph">最初は、ググってみましたが、なかなか的確なサイトにぶち当たりません。<br>Aiに聞いてみよう！<br>ChatGPT と Gemini 2.5Flash に同じ質問をしてみましたが、ほぼ同じ回答内容でしたが<br>ChatGPTのほうが、みやすく感じます<br>ただ、ChatGPTは次から次に、逆質問をしてくるのが、ちょっとウザいかも・・・</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">rocky linux9 で自宅サーバーを運用していますが、2025/10月からサーバーからのメールが送信できなくなりました sudo cat /var/log/maillog | grep -i error を実行してみると、下記エラーがでます。原因はなんでしょう？ <br>sudo cat /var/log/maillog | grep -i error<br>（エラー内容）<br>・<br>・</p>
</blockquote>



<p class="wp-block-paragraph">それにしても、エラー内容をそのまま突っ込めるのは、今までの検索では考えられないですね。</p>



<h3 class="wp-block-heading"><span id="toc2">Aiのエラー内容の整理</span></h3>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">ログのエラー内容を整理すると：<br>Postfix が プロバイダ<strong> のメールサーバ (mx.hogehoge.com) に TCP ポート 25 で接続しようとしてタイムアウト</strong>しています。</p>



<h4 class="wp-block-heading"><span id="toc3">主な原因候補</span></h4>



<p class="wp-block-paragraph"><strong>１０月からであれば、原因とは考えにくいですが・・・</strong><br>Rocky Linux の <code>firewalld</code> やルーターで 25番ポートのアウトバウンドが塞がれた可能性。</p>



<p class="wp-block-paragraph"><strong>プロバイダ側のポート25ブロック</strong><br>2025年現在、多くの ISP（特に家庭向け回線）はスパム対策のため <strong>ポート25を塞いでいる</strong> ことが多いです。<br>それまでは通っていたけど、2025年10月から「送信ポリシー変更」でブロックされた可能性があります。</p>



<p class="wp-block-paragraph"><strong>プロバイダ 側の受信制限</strong><br>プロバイダ の受信サーバが外部からの直接SMTPを拒否するようになった可能性があります。</p>



<p class="wp-block-paragraph"><strong>ファイアウォール / サーバ側の設定</strong><br>個人宅サーバからの直接送信を受け付けない運用に切り替えた可能性。<br></p>
</blockquote>



<h3 class="wp-block-heading"><span id="toc4">確認方法</span></h3>



<p class="wp-block-paragraph">自宅サーバーからプロバイダメールサーバーへ直接接続できるか試す</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-0eae8bd16b748755037f75239f8fa78c"><code>telnet mx.hogehoge.com 25</code></pre>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">もしタイムアウトするなら → 回線側（ISPやプロバイダ）で遮断。<br>もし「220〜」の応答があれば → Postfixの設定やファイアウォールの問題。</p>
</blockquote>



<p class="wp-block-paragraph">結果、telnet mx.hogehoge.com 25 が応答なし（タイムアウト）でした。<br>ということは、サーバー側(Postfix)の問題ではなく、回線側で25番ポートがブロックされている可能性が非常に高いと言うことのようです。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<h4 class="wp-block-heading"><span id="toc5">状況まとめ</span></h4>



<ul class="wp-block-list">
<li>以前は送れた → 2025年10月から送れなくなった</li>



<li>ログでは「Connection timed out」</li>



<li>telnet も通らない</li>
</ul>



<p class="wp-block-paragraph">👉 これは「ISP（プロバイダ 側）が <strong>自宅回線からの直接25番SMTP送信を禁止</strong> に切り替えた」ケースに一致します。<br>最近は迷惑メール対策で家庭向け回線ではほぼ標準でブロックされます。</p>
</blockquote>



<h3 class="wp-block-heading"><span id="toc6">解決方法</span></h3>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">１．プロバイダのメールサーバ経由（SMTPリレー / smarthost）<br>　・Postfix の <code>relayhost</code> 設定でプロバイダの SMTP サーバ（587 or 465ポート）を使う<br>２．外部のメールリレーサービスを利用<br>　・SendGrid, Gmail SMTP relay, AWS SES など<br>３．自宅サーバではなく VPS 経由で送信<br>　・自宅サーバからVPSへ転送して、VPSから外へ送信。</p>
</blockquote>



<h3 class="wp-block-heading"><span id="toc7">解決策（おすすめ）</span></h3>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<h4 class="wp-block-heading"><span id="toc8">プロバイダのSMTPサーバを経由する（最も現実的）</span></h4>



<p class="wp-block-paragraph">Postfix で <strong>「スマートホスト」設定</strong>をして、<code>smtp.hogehoge.com:587</code> 経由で送信するのがベストです。（25番ではなく 587 番（Submission ポート）がベスト）</p>
</blockquote>



<p class="wp-block-paragraph">まずは、 外部からの直接配送(mx) ではなく、 認証付きの送信サーバ(smtp) なら接続できるかの確認</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-d1ed62bd845bdfc34561e26dc69787d7"><code>telnet smtp.hogehoge.com 25
telnet smtp.hogehoge.com 587</code></pre>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">結果、両方とも接続できました<br>telnet smtp.hogehoge.com 587<br> Trying 000.000.000.0… Connected to smtp.hogehoge.com. Escape character is &#8216;^]&#8217;. <br> 220 hogehoge.com ESMTP server ready Sat, 4 Oct 2025 15:42:22 +0900</p>
</blockquote>



<h3 class="wp-block-heading"><span id="toc9">整理すると</span></h3>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">mx.hogehoge.com:25 → タイムアウト（接続できない）<br>smtp.hogehoge.com:25 → 接続できる（220応答あり）<br>smtp.hogehoge.com:587 → 接続できる（220応答あり）<br>つまり：<br>プロバイダ は 外部からの直接配送(mx) を制限している<br>代わりに 認証付きの送信サーバ(smtp) なら 25 でも 587 でも受け付けている<br>じゃあどっちを使うべき？<br>587（submission ポート） が推奨です（標準仕様で「認証あり専用の送信ポート」）<br>25番で smtp.nifty.com に直接送ることもできますが、将来的にブロックされる可能性が高いです。<br>なので、Postfixの relayhost を smtp.hogehoge.com:587 にして、SMTP認証を通す設定がベストです。</p>
</blockquote>



<h2 class="wp-block-heading"><span id="toc10">設定方法</span></h2>



<h3 class="wp-block-heading"><span id="toc11">認証情報ファイルを作成</span></h3>



<p class="wp-block-paragraph">/etc/postfix/sasl_passwd　ファイルを作成し、アドレスとパスワードを追記：<br>「プロバイダのメールアドレス」：「アドレスパスワード」</p>



<ol class="wp-block-list">
<li></li>
</ol>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-cf5ee98bcd0014075216e4ea91b22a3d"><code>&#91;smtp.hogehoge.com]:587 myaddress@hogehoge.com:mypasswd</code></pre>



<h3 class="wp-block-heading"><span id="toc12">Postfix設定ファイルを修正</span></h3>



<p class="wp-block-paragraph">/etc/postfix/main.cf の末尾あたりに下記追記：</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-13556aa4e80564c4f005081ef9c9d542"><code># hogehoge の SMTP サーバをリレーに指定
relayhost = &#91;smtp.hogehoge.com]:587

# SMTP認証を有効化
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous

# TLS を使用
smtp_use_tls = yes
smtp_tls_security_level = may
smtp_tls_note_starttls_offer = yes
</code></pre>



<h3 class="wp-block-heading"><span id="toc13">ハッシュ化して権限設定</span></h3>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-38c8a71e92c7c150706dc97f7dbaf633"><code>sudo postmap /etc/postfix/sasl_passwd
sudo chmod 600 /etc/postfix/sasl_passwd*</code></pre>



<h3 class="wp-block-heading"><span id="toc14">Postfix再起動</span></h3>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-3c331cc5949776159db7c4e811fd490b"><code>sudo systemctl restart postfix</code></pre>



<h3 class="wp-block-heading"><span id="toc15">テスト送信</span></h3>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-c98fe1de8a8672232244379c1692715a"><code>echo "This is a test mail" | mail -s "Postfix smtp test" myaddress@hogehoge.com</code></pre>



<h3 class="wp-block-heading"><span id="toc16">確認</span></h3>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">/var/log/maillog を確認して、status=sent になれば成功</p>
</blockquote>



<h3 class="wp-block-heading"><span id="toc17">後日、Gmailへの転送がNGになった</span></h3>



<p class="wp-block-paragraph">後日、バックアップサーバーの立ち上げをやっていて、GmailへのテストメールがNGになった</p>



<pre class="wp-block-code"><code> echo "This is a test mail to gmail" | mail -s "Postfix smtp test2" hogehoge@gmail.com</code></pre>



<h4 class="wp-block-heading"><span id="toc18">ここも、AIに聞いてみる</span></h4>



<p class="wp-block-paragraph">Gmailで該当メールを開いて <strong>「︙」→「メッセージのソースを表示」</strong> し、以下の行を確認してみてください：</p>



<pre class="wp-block-code"><code>Authentication-Results: mx.google.com;
   spf=pass  ← ここがfailだとアウト
   dkim=pass ← ここがfailだとアウト</code></pre>



<p class="wp-block-paragraph">その結果を教えてもらえれば、どこが問題か特定できます！</p>



<pre class="wp-block-code"><code>Authentication-Results: nifty.com;
    dmarc=none header.from=kazuban.com;
    dkim=none;
    spf=fail smtp.mailfrom=kazuban.com;
    sender-id=Fail (pra) header.From=kazuban.com</code></pre>



<p class="wp-block-paragraph">原因が明確になりました！</p>



<h3 class="wp-block-heading"><span id="toc19">AIが問題点指摘</span></h3>



<p class="wp-block-paragraph"><strong><code>spf=fail</code></strong> → <code>kazuban.com</code> のDNSにSPFレコードがないか、Niftyのサーバーが許可されていないNiftyのSMTP経由で送っているのに、Fromアドレスが <code>@kazuban.com</code> なので、<br>「kazuban.comのSPF的にNiftyは許可されてないよ」とGmailに判断されています。</p>



<h4 class="wp-block-heading"><span id="toc20">A. <strong>kazuban.com のDNSにSPFレコードを追加</strong>（推奨）</span></h4>



<pre class="wp-block-preformatted">種別     ホスト名          内容<br>TXT      @ （または空欄）<code>  v=spf1 include:nifty.com ~all</code></pre>



<p class="wp-block-paragraph">設定後、反映に<strong>数分〜数時間</strong>かかる場合があります。確認コマンドはこちら：</p>



<pre class="wp-block-code"><code>dig TXT kazuban.com | grep spf</code></pre>



<p class="wp-block-paragraph"><code>v=spf1 include:nifty.com ~all</code> が表示されれば成功です。</p>



<h2 class="wp-block-heading"><span id="toc21">正常にもどった</span></h2>



<p class="wp-block-paragraph">いまさらですが、Aiはすごいですね<br>ちょっと前までは、プロンプトが重要とか言われていましたが、最近ではあまり感じません<br>普通に個人の言葉で、質問すれば、かなり理解してくれます<br>もしかすると、サポート会社などへ、電話質問するよりも簡単かもしれません<br>理解力と分析力は、はるかに人間を超えているように思います</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>ファナック・カスタムマクロの展開をAiにやってもらう！</title>
		<link>https://www.kazuban.com/blog/custom-macro-with-ai/</link>
		
		<dc:creator><![CDATA[kazuban]]></dc:creator>
		<pubDate>Sat, 02 Aug 2025 02:50:55 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[NC]]></category>
		<category><![CDATA[カスタムマクロ]]></category>
		<category><![CDATA[CAM]]></category>
		<category><![CDATA[ファナック]]></category>
		<category><![CDATA[生成Ai]]></category>
		<guid isPermaLink="false">https://www.kazuban.com/blog/?p=11441</guid>

					<description><![CDATA[最近は、CAMの充実もあって、カスタムマクロの利用もかなり減少しいていると思います。ただ、穴などの基本的な加工の場合、座標値入力だけで加工できるのでうまく使えば、かなり重宝します。マシニングセンターを、操作フライス盤的な [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">最近は、CAMの充実もあって、カスタムマクロの利用もかなり減少しいていると思います。<br>ただ、穴などの基本的な加工の場合、座標値入力だけで加工できるのでうまく使えば、かなり重宝します。<br>マシニングセンターを、操作フライス盤的な使い方で利用する事もできます。</p>




  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-10" checked><label class="toc-title" for="toc-checkbox-10">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">カスタムマクロの欠点</a><ol><li><a href="#toc2" tabindex="0">プログラミングの難易度</a></li><li><a href="#toc3" tabindex="0">デバッグの複雑さ</a></li></ol></li><li><a href="#toc4" tabindex="0">そうだ、Aiに展開してもらおう！</a><ol><li><a href="#toc5" tabindex="0">課題データ</a></li><li><a href="#toc6" tabindex="0">Aiの回答</a><ol><li><a href="#toc7" tabindex="0">プログラム全体の概要</a></li><li><a href="#toc8" tabindex="0">O1000: 主プログラム</a></li><li><a href="#toc9" tabindex="0">O6000: 面取りマクロプログラム</a></li><li><a href="#toc10" tabindex="0">O6100: 穴位置プログラム</a></li><li><a href="#toc11" tabindex="0">まとめ</a></li></ol></li><li><a href="#toc12" tabindex="0">完成</a></li><li><a href="#toc13" tabindex="0">シミュレーション</a></li></ol></li><li><a href="#toc14" tabindex="0">まとめ</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">カスタムマクロの欠点</span></h2>



<p class="wp-block-paragraph">Google で「カスタムマクロ欠点」で検索してみると、下記のAi概要が最上部に表示されました<br>話は変わりますが、最近では通常検索でもAi回答が出てくるようになりましたね。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph"><strong>AI による概要</strong></p>



<p class="wp-block-paragraph">カスタムマクロは、NCプログラムの効率化や自動化に役立つ一方で、いくつかの欠点も存在します。主な欠点としては、<mark>プログラミングの難易度、デバッグの複雑さ、互換性の問題、そして過度な依存によるリスク</mark>などが挙げられます。</p>



<p class="has-light-grey-background-color has-background wp-block-paragraph"><strong>カスタムマクロの欠点</strong></p>



<ul class="wp-block-list">
<li><strong>プログラミングの難易度:</strong>カスタムマクロは、通常のNCプログラムよりも複雑なロジックを記述する必要があるため、習得に時間がかかり、プログラミングの難易度が高いです。特に、条件分岐やループ処理を多用する場合、複雑さが増し、エラーが発生しやすくなります。</li>



<li><strong>デバッグの複雑さ:</strong>カスタムマクロのデバッグは、通常のNCプログラムよりも難易度が高いです。変数の値の変化や処理の流れを追跡するのが難しく、エラーの原因特定に時間がかかることがあります。また、マクロプログラムが複雑になるほど、デバッグ作業はさらに困難になります。</li>



<li><strong>互換性の問題:</strong>カスタムマクロは、使用するNC工作機械や制御装置の種類によって、互換性の問題が発生する可能性があります。同じマクロプログラムでも、機械が異なると正しく動作しない場合や、エラーが発生する場合があります。そのため、マクロプログラムを作成する際には、互換性を考慮する必要があります。</li>



<li><strong>過度な依存によるリスク:</strong>カスタムマクロに過度に依存すると、マクロプログラムの変更や修正が必要になった場合に、他の作業に影響が出たり、生産性が低下する可能性があります。また、マクロプログラムの作成者が不在になった場合、保守や管理が困難になるというリスクもあります。</li>
</ul>



<p class="wp-block-paragraph">その他の考慮事項</p>



<ul class="wp-block-list">
<li><strong>マクロプログラムの可読性:</strong>カスタムマクロは、可読性の高い書き方を心がける必要があります。コメントを適切に記述し、変数名や処理の流れを分かりやすくすることで、他の人がマクロプログラムを理解しやすくなります。</li>



<li><strong>マクロプログラムのバージョン管理:</strong>カスタムマクロは、バージョン管理を行うことで、変更履歴を把握し、必要に応じて以前のバージョンに戻すことができます。</li>



<li><strong>マクロプログラムのテスト:</strong>カスタムマクロは、実際に機械を動かす前に、シミュレーション環境などで十分にテストを行う必要があります。これにより、エラーの発生を未然に防ぎ、安全に運用することができます。</li>
</ul>



<p class="wp-block-paragraph">これらの欠点や考慮事項を踏まえ、カスタムマクロの導入を検討する必要があります。</p>
</blockquote>



<p class="wp-block-paragraph">なるほど・・<a href="https://www.kazuban.com/blog/category/nc/custom-macro/">ここのサイトでもいくつか取り上げていますが</a>、まさに同意見です。<br></p>



<h3 class="wp-block-heading"><span id="toc2"><strong>プログラミングの難易度</strong></span></h3>



<p class="wp-block-paragraph">マクロは数多く作成してきましたが<br>機械の制御器に処理させる言語になるので、どうしても、一般的なプログラミング言語と比較すると、中途半端で可読性は悪くなってしまします。<br>ちなみに、レダース(Roeders）機は、独自開発されたプログラミング言語ライクな言語です。<br>加工動作のGコードのサブプロ部分と、その動作部分を管理するメインプロ部分を分離する事を基本で開発されているように感じています。<br>特にWindowsソフトウェアとして開発された言語なので、自動化や多数個など、複雑なメインプロを開発する場合でもかなり楽です。</p>



<h3 class="wp-block-heading"><span id="toc3"><strong>デバッグの複雑さ</strong></span></h3>



<p class="wp-block-paragraph">このサイトでも、何度か書いていますが、一番は変数の制限が可読性を悪くしているように思います。<br>筆者は通常のGコードだけであれば、<a href="https://www.trycut.com/">TRYCUT</a> と言うシミュレーションソフトを使っていますが、TRYCUTにはマクロ展開機能が付いていません。<br>シミュレートできないので、マクロのデバッグはエディタやプリントアウトして目視で追っかけ確認ますがかなかな面倒で、リスクもあります。<br>社内設備機械で、一台だけマクロも含めたシミュレート機能がある制御器があるので、確認のためだけに、その機械を起動させる場合もあります。<br>大人しく、マクロ機能付きのシミュレータを購入したら・・・の意見もあると思いますが、マクロ利用頻度から検討すると、どうしても費用対効果の面で無理があります。</p>



<h2 class="wp-block-heading"><span id="toc4">そうだ、Aiに展開してもらおう！</span></h2>



<p class="wp-block-paragraph">前回、Fusion python API を、Aiに教わったらすごかった・・を記事にしました</p>



<figure class="wp-block-embed is-type-wp-embed"><div class="wp-block-embed__wrapper">

<a href="https://www.kazuban.com/blog/fusion-python-api/" title="Fusion360  Python API 再挑戦！AIの力を借りて、sketchなど基本ライブラリを作ってみた。" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="160" height="90" src="https://www.kazuban.com/blog/wp-content/uploads/2025/07/fusion-python-api-160x90.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/07/fusion-python-api-160x90.png 160w, https://www.kazuban.com/blog/wp-content/uploads/2025/07/fusion-python-api-120x68.png 120w, https://www.kazuban.com/blog/wp-content/uploads/2025/07/fusion-python-api-320x180.png 320w" sizes="(max-width: 160px) 100vw, 160px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">Fusion360  Python API 再挑戦！AIの力を借りて、sketchなど基本ライブラリを作ってみた。</div><div class="blogcard-snippet internal-blogcard-snippet">Aiと言う強い味方を得て、Fusion API に再挑戦しています。pythonの学習もかねて、skrtch関連の関数をライブラリ化しています。筆者の環境では、正常に動作しています。コピペで利用可。Aiに教えてもらわないと、作成できなかった実例をレポートしています。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://www.kazuban.com/blog" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">www.kazuban.com</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2025.07.09</div></div></div></div></a>
</div></figure>



<p class="wp-block-paragraph">Fusion API は、一般的なpython言語構文やライブラリだけでなく、独自のオブジェクトを絡み合わせて開発していくので、そのパッケージの理解だけでも大変です。<br>それを、Aiに聞いたら、サンプルコードを出してくれたり、自作したコードを添削してくれたりと、驚きでした。<br>そこで上の記事を書いてたら、ピ～ンときました。<br>「そうだ、Fusion APIのパッケージを瞬時に解読できるなら、カスタムマクロなら簡単に解読してくれるかも！」</p>



<h3 class="wp-block-heading"><span id="toc5">課題データ</span></h3>



<p class="wp-block-paragraph">課題NCデータは、以前記事にした、下記ページのデータをそのまま使ってみようと思います</p>



<figure class="wp-block-embed is-type-wp-embed"><div class="wp-block-embed__wrapper">

<a href="https://www.kazuban.com/blog/chamfering-with-g66/" title="カスタムマクロ、G66モーダル呼び出しで固定サイクルを自作してみる。" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="228" height="180" src="https://www.kazuban.com/blog/wp-content/uploads/2022/05/Chamfer01.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://www.kazuban.com/blog/wp-content/uploads/2022/05/Chamfer01.png 878w, https://www.kazuban.com/blog/wp-content/uploads/2022/05/Chamfer01-300x237.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2022/05/Chamfer01-768x607.png 768w" sizes="(max-width: 228px) 100vw, 228px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">カスタムマクロ、G66モーダル呼び出しで固定サイクルを自作してみる。</div><div class="blogcard-snippet internal-blogcard-snippet">前回、カスタムマクロプログラムの例として、ハイデンハインサイクルをマクロ化する例を紹介しました。ハイデンハインサイクルに比べると、ファナック固定サイクルの機能は非常に貧弱ですが、カスタムマクロを自作する事で、無限に拡張する事が可能です。今回は、カスタムマクロのモーダル呼び出し「G66」を利用して、穴...</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://www.kazuban.com/blog" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">www.kazuban.com</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2022.05.30</div></div></div></div></a>
</div></figure>



<p class="wp-block-paragraph">穴の面取りを輪郭加工で行うマクロです。<br>メインプロ「O1000」に加工条件や面取り条件を変数で定義して、G66モーダル呼び出しで「O6000」の面取り加工マクロを呼び出し、指定位置「O6100」で面取りを行うプログラムです<br>若干変数での計算式もあります。</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-ada81581cdb38d9e779798ad0caed857"><code>こちらのファナックマクロを展開してください
%
O1000
( Chamfering Program Ver1.0 By kazuban )&nbsp;
G90G00G17G40G80G49&nbsp;
(++++++++++++++++++++)&nbsp;
#1=54 (WORK ORIGIN)
#2=10 (Tool Number)
#3=#2 (H Number)
#4=0.5(Tool Diameter)
#5=2300 (Spindle Speed)
#6=200 (Feed)
#7=8 (Coolant)
#8=0.0(Surface Coordinat)
#9=50.0 (Initial Point)&nbsp;
#10=5.0 (R Point)
(++++++++++++++++++++)&nbsp;
#11=12.0 (Hole Diameter)
#12=1.0 (Chamfer)
#13=0.5 (Offset)
(++++++++++++++++++++)&nbsp;
#30=6000 (Macro program No)
#31=6100 (Position program No)
(++++++++++++++++++++)&nbsp;
N0001
G#1
T#2
M06
G90G00X0Y0&nbsp;
G43Z&#91;#8+#9]H#3
( Chamfer Process )
S#5M03&nbsp;
M#7
(----------------------------)
(B:#2=#8 : Surface Coordinat)&nbsp;
(C:#3=#9 : Initial Point)&nbsp;
(I:#4=#10 : R Point)&nbsp;
(J:#5=#12 : Chamfer)&nbsp;
(K:#6=#13 : Offset)
(D:#7=#4 : Tool Dia)
(E:#8=#11 : Hole Dia)
(F:#9=#6 : Feed)
(++++++++++++++++++++)&nbsp;
G66 P&#91;#30] B&#91;#8] C&#91;#9] I&#91;#10] J&#91;#12] K&#91;#13] D&#91;#4] E&#91;#11] F&#91;#6]
M98P&#91;#31]
G67
G90G00Z&#91;#8+#9]
M09
M05
G91G28Z0&nbsp;
G91G49Z0&nbsp;
G90M05&nbsp;
( End of Process )
M30
%
%
O6000
( Chamfering Macro Ver1.0 By kazuban )&nbsp;
(+++++++++++++++++++)
#1=&#91;#8/2-&#91;#6+#7/2]] (circle radius)
(+++++++++++++++++++)
(B:#2 : Surface Coordinat)&nbsp;
(C:#3 : Initial Point)&nbsp;
(I:#4 : R Point)&nbsp;
(J:#5 : Chamfer)&nbsp;
(K:#6 : Offset)
(D:#7 : Tool Dia)
(E:#8 : Hole Dia)
(F:#9 : Feed)
(+++++++++++++++++++)
G90G00G17
Z&#91;#2+#3]&nbsp;
Z&#91;#2+#4]&nbsp;
G01Z&#91;#2-&#91;#6+#5]]F&#91;#9]&nbsp;
G91X&#91;#1]
G03X-&#91;#1*2]I-&#91;#1]J0.&nbsp;
X&#91;#1*2]I&#91;#1]J0.
G01X-&#91;#1]&nbsp;
G90G00Z&#91;#2+#3]&nbsp;
M99
%
%
O6100
( Hole Position )
X-35.Y55.
X-50.Y55.
X10.Y10.&nbsp;
M99
%</code></pre>



<p class="wp-block-paragraph">このデータをそのまま、「Gemini 2.5 Flash」に突っ込んで、展開をお願いしてみました。</p>



<h3 class="wp-block-heading"><span id="toc6">Aiの回答</span></h3>



<p class="wp-block-paragraph">G66仕様で、G66への変数渡しが「#変数」そのままでないので、作者が見直す時も結構面倒ですが、Aiは瞬時に分析してくれました。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">提供されたFANUCマクロプログラムを解析し、その内容を以下に解説します。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><span id="toc7"><strong>プログラム全体の概要</strong></span></h4>



<p class="wp-block-paragraph">このマクロは、複数の穴の面取り加工を自動化するために設計されています。主プログラム (<code>O1000</code>) で加工条件を設定し、マクロプログラム (<code>O6000</code>) で実際の面取り動作を実行、そしてもう一つのプログラム (<code>O6100</code>) で穴の位置情報を呼び出す、という構成になっています。</p>



<h4 class="wp-block-heading"><span id="toc8"><strong>O1000: 主プログラム</strong></span></h4>



<p class="wp-block-paragraph">このプログラムは、加工に必要な初期設定と、マクロ呼び出しを行います。</p>



<ul class="wp-block-list">
<li><strong>初期設定:</strong>
<ul class="wp-block-list">
<li><code>#1=54 (WORK ORIGIN)</code>: ワーク原点の位置を<code>#1</code>に設定。</li>



<li><code>#2=10 (Tool Number)</code>: 工具番号を<code>#2</code>に設定。</li>



<li><code>#4=0.5(Tool Diameter)</code>: 工具径を<code>#4</code>に設定。</li>



<li><code>#5=2300 (Spindle Speed)</code>: 主軸回転速度を<code>#5</code>に設定。</li>



<li><code>#6=200 (Feed)</code>: 送り速度を<code>#6</code>に設定。</li>



<li><code>#11=12.0 (Hole Diameter)</code>: 穴の直径を<code>#11</code>に設定。</li>



<li><code>#12=1.0 (Chamfer)</code>: 面取り量を<code>#12</code>に設定。</li>



<li><code>#13=0.5 (Offset)</code>: 工具のオフセット量を<code>#13</code>に設定。</li>
</ul>
</li>



<li><strong>マクロ呼び出し:</strong>
<ul class="wp-block-list">
<li><code>G66 P[#30] ...</code>: ここで、面取りマクロプログラム<code>O6000</code>（<code>#30</code>）を呼び出しています。</li>



<li><code>B[#8] C[#9]...</code>: マクロに渡す引数を設定しています。
<ul class="wp-block-list">
<li><code>B[#8]</code>: 面取り加工の開始基準となる<strong>ワーク表面座標</strong>。</li>



<li><code>C[#9]</code>: 加工前の待機位置である<strong>初期点</strong>。</li>



<li><code>I[#10]</code>: 加工開始前の<strong>退避点（R点）</strong>。</li>



<li><code>J[#12]</code>: <strong>面取り量</strong>。</li>



<li><code>K[#13]</code>: <strong>オフセット量</strong>。</li>



<li><code>D[#4]</code>: <strong>工具径</strong>。</li>



<li><code>E[#11]</code>: <strong>穴径</strong>。</li>



<li><code>F[#6]</code>: <strong>送り速度</strong>。</li>
</ul>
</li>



<li><code>M98 P[#31]</code>: 穴の位置情報を記述したプログラム<code>O6100</code>（<code>#31</code>）を呼び出します。これにより、<code>O6100</code>に記述された各座標で、<code>G66</code>で指定されたマクロが繰り返して実行されます。</li>
</ul>
</li>
</ul>



<h4 class="wp-block-heading"><span id="toc9"><strong>O6000: 面取りマクロプログラム</strong></span></h4>



<p class="wp-block-paragraph">このプログラムは、<code>O1000</code>から渡された情報をもとに、実際の面取り加工を行います。</p>



<ul class="wp-block-list">
<li><strong>面取り加工の半径計算:</strong>
<ul class="wp-block-list">
<li><code>#1=[#8/2-[#6+#7/2]]</code>: この式は、面取り加工を行う円弧の半径を計算しています。
<ul class="wp-block-list">
<li><code>#8/2</code>: 穴の半径。</li>



<li><code>#6</code>: 面取り量。</li>



<li><code>#7/2</code>: 工具の半径。</li>



<li><strong>結果:</strong> <strong>面取り加工する円弧の半径 = (穴の半径) &#8211; (面取り量) &#8211; (工具の半径)</strong></li>
</ul>
</li>
</ul>
</li>



<li><strong>加工シーケンス:</strong>
<ol start="1" class="wp-block-list">
<li><code>G90G00G17</code>: 絶対指令、早送り、XY平面選択。</li>



<li><code>Z[#2+#3]</code>、<code>Z[#2+#4]</code>: Z軸を初期点、R点へと移動。</li>



<li><code>G01Z[#2-[#6+#5]]F[#9]</code>: Z軸を<strong>面取り深さ</strong>まで切り込みながら移動します。</li>



<li><code><strong>G91</strong>X[#1]</code>: <span class="marker-under-red">ワーク座標を基準</span>に、計算された半径分だけX軸を移動。円弧加工の開始位置に移動します。</li>



<li><code>G03X-[#1*2]I-[#1]J0.</code>: 半径<code>#1</code>の円弧で、左回りに<strong>180度円弧切削</strong>。</li>



<li><code>X[#1*2]I[#1]J0.</code>: さらに、半径<code>#1</code>の円弧で、左回りに<strong>180度円弧切削</strong>。これにより、1周分の面取り加工が完了します。</li>



<li><code>G01X-[#1]</code>: 円弧加工の開始位置から中心に戻ります。</li>



<li><code>G90G00Z[#2+#3]</code>: Z軸を初期点に戻します。</li>



<li><code>M99</code>: マクロプログラムの終了。主プログラム（<code>O1000</code>）に戻ります。</li>
</ol>
</li>
</ul>



<h4 class="wp-block-heading"><span id="toc10"><strong>O6100: 穴位置プログラム</strong></span></h4>



<p class="wp-block-paragraph">このプログラムは、加工する穴のXY座標をリストアップしています。</p>



<ul class="wp-block-list">
<li><code>X-35.Y55.</code>: 1つ目の穴の座標。</li>



<li><code>X-50.Y55.</code>: 2つ目の穴の座標。</li>



<li><code>X10.Y10.</code>: 3つ目の穴の座標。</li>
</ul>



<p class="wp-block-paragraph">これらの座標は、<code>O1000</code>の<code>M98 P[#31]</code>によって順番に読み込まれ、それぞれの位置で<code>O6000</code>の面取り加工が実行されます。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><span id="toc11"><strong>まとめ</strong></span></h4>



<p class="wp-block-paragraph">このプログラムは、以下のような処理フローで動作します。</p>



<ol start="1" class="wp-block-list">
<li>主プログラム<code>O1000</code>がスタートします。</li>



<li>工具交換、初期位置決め、主軸回転、クーラントONなど、準備が完了します。</li>



<li><code>O6100</code>に記述された最初の座標（X-35.Y55.）に移動します。</li>



<li><code>G66</code>によって<code>O6000</code>の面取りマクロが呼び出されます。</li>



<li>マクロ内で計算されたパスで、面取り加工が行われます。</li>



<li>面取り加工が完了すると、<code>O1000</code>に戻ります。</li>



<li><code>O6100</code>の次の座標（X-50.Y55.）に移動します。</li>



<li>再び<code>O6000</code>が呼び出され、面取り加工が行われます。</li>



<li>この繰り返し処理が<code>O6100</code>の最後まで行われます。</li>



<li>全ての加工が終了すると、クーラントOFF、主軸停止、安全位置への退避が行われ、プログラムが終了します。</li>
</ol>



<p class="wp-block-paragraph">この構成は、複数の同じ形状の加工を効率的に行うための、NCプログラミングの典型的な手法です。プログラムを分割することで、位置情報や加工条件の変更が容易になります。</p>
</blockquote>



<p class="wp-block-paragraph">丁寧な解説ですが、<strong>加工シーケンス:</strong>４．の<span class="marker-under-red">「ワーク座標を基準</span>」と言うのがちょっと間違っていますね・・<br>無料版だからでしょうか？<br>でも、きちんとGコードに展開してくれれば、問題ないですから<br>再度、一般的なGコードへの展開をお願いすると・・・</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">%<br>O1000_EXPANDED<br>( Chamfering Program Expanded Version )</p>



<p class="wp-block-paragraph">G90 G00 G17 G40 G80 G49&nbsp;</p>



<p class="wp-block-paragraph">( Tool and Spindle Setup )<br>T10 M06&nbsp;<br>G90 G00 X0 Y0&nbsp;<br>G43 Z[0.0+50.0] H10<br>S2300 M03&nbsp;<br>M08</p>



<p class="wp-block-paragraph">( &#8212; Hole 1 at X-35. Y55. &#8212; )<br>G90 G00 X-35. Y55.<br>G00 Z[0.0+50.0]<br>G00 Z[0.0+5.0]<br>G01 Z[0.0-[1.0+0.5]] F200<br>G91 X[12.0/2-[1.0+0.5/2]]<br>G03 X-[[12.0/2-[1.0+0.5/2]]2] I-[12.0/2-[1.0+0.5/2]] J0. X[[12.0/2-[1.0+0.5/2]]2] I[12.0/2-[1.0+0.5/2]] J0.<br>G01 X-[12.0/2-[1.0+0.5/2]]<br>G90 G00 Z[0.0+50.0]</p>



<p class="wp-block-paragraph">( &#8212; Hole 2 at X-50. Y55. &#8212; )<br>・<br>・<br>・以下省略</p>
</blockquote>



<p class="wp-block-paragraph">G66呼び出しの部分も、きちんと、展開してくれました。<br>さらに、[]内で、変数を数値に置き換えた計算式で表現してくれています。<br>おそらく、[]を認識できるコントローラであれば、このまま動作すると思いますが、トライカットは動作してくれないので、再度、[]内の計算式部分を、実数値に変換をお願いしました。</p>



<h3 class="wp-block-heading"><span id="toc12">完成</span></h3>



<p class="wp-block-paragraph">以下が完成したデータです</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-66754072bbded3ae612360f6496ca273"><code>%
O1000
( Chamfering Program Expanded Numeric Version )

G90 G00 G17 G40 G80 G49&nbsp;

( Tool and Spindle Setup )
T10 M06&nbsp;
G90 G00 X0 Y0&nbsp;
G43 Z50.0 H10
S2300 M03&nbsp;
M08

( Chamfering Path Calculation )
( Hole Diameter: 12.0 )
( Chamfer: 1.0 )
( Tool Diameter: 0.5 )
( Offset: 0.5 )
( Radius for cutting: 12.0/2 - 1.0 - 0.5/2 = 6.0 - 1.0 - 0.25 = 4.75 )
( Cutting Depth: 1.0 + 0.5 = 1.5 )

( --- Hole 1 at X-35. Y55. --- )
G90 G00 X-35. Y55.
G00 Z50.0
G00 Z5.0
G01 Z-1.5 F200
G91 X4.75
G03 X-9.5 I-4.75 J0.
X9.5 I4.75 J0.
G01 X-4.75
G90 G00 Z50.0

( --- Hole 2 at X-50. Y55. --- )
G90 G00 X-50. Y55.
G00 Z50.0
G00 Z5.0
G01 Z-1.5 F200
G91 X4.75
G03 X-9.5 I-4.75 J0.
X9.5 I4.75 J0.
G01 X-4.75
G90 G00 Z50.0

( --- Hole 3 at X10. Y10. --- )
G90 G00 X10. Y10.
G00 Z50.0
G00 Z5.0
G01 Z-1.5 F200
G91 X4.75
G03 X-9.5 I-4.75 J0.
X9.5 I4.75 J0.
G01 X-4.75
G90 G00 Z50.0

( End of Program )
M09
M05
G91 G28 Z0
G91 G49 Z0
G90 M05
M30
%
</code></pre>



<h3 class="wp-block-heading"><span id="toc13">シミュレーション</span></h3>



<p class="wp-block-paragraph">さっそく、シミュレーションしてみましょう！</p>



<figure class="wp-block-video"><video height="852" style="aspect-ratio: 1032 / 852;" width="1032" controls src="https://www.kazuban.com/blog/wp-content/uploads/2025/08/macro-trycut.mp4"></video></figure>



<p class="wp-block-paragraph">正常に動作しました。</p>



<h2 class="wp-block-heading"><span id="toc14">まとめ</span></h2>



<p class="wp-block-paragraph">やっぱり、Aiはすごいです。<br>座標値を変数で置き換えている程度のマクロであれば、エクセルやスクリプト言語などで、比較的簡単に変換できるかもしれませんが、計算式が入ってくると格段に難易度が上がります。<br>さらに、G66などのマクロ呼出しになると、引数への変数渡しに癖があるので、PC上での目視確認においても結構面倒です。<br>以前、マクロの変換ソフトの作成も考えた事もありますが、難易度高くで止めました。<br>今回のように、Aiに展開してもらえれば、手持ちのシミュレータで動作確認できるので、かなり気軽にマクロに取り組めると思います<br>それに、今回使用したAiは、「Gemini 2.5flash」で基本無料で利用できます。<br>ちょっと、間違った回答もありましたが、Fusion API の質問も含めて、制限が出ることはなかったです。「chatGPT」無料版では、制限に引っかかりました。</p>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
		
		<enclosure url="https://www.kazuban.com/blog/wp-content/uploads/2025/08/macro-trycut.mp4" length="2284942" type="video/mp4" />

			</item>
		<item>
		<title>Fusion360  Python API 再挑戦！AIの力を借りて、sketchなど基本ライブラリを作ってみた。</title>
		<link>https://www.kazuban.com/blog/fusion-python-api/</link>
		
		<dc:creator><![CDATA[kazuban]]></dc:creator>
		<pubDate>Tue, 08 Jul 2025 20:01:00 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[Fusion360]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[AIとのやり取り]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://www.kazuban.com/blog/?p=11250</guid>

					<description><![CDATA[数年前、Fusion360のPython APIに少しだけ触れたことがあります。当時はPython自体が初めてで、構文の違いに戸惑いました。C言語に慣れていた私には、インデントでブロックを作る点や、変数・関数に型の宣言が [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">数年前、Fusion360のPython APIに少しだけ触れたことがあります。<br>当時はPython自体が初めてで、構文の違いに戸惑いました。<br>C言語に慣れていた私には、インデントでブロックを作る点や、変数・関数に型の宣言が不要な点など、なかなか馴染めませんでした。<br>さらに、Fusion独自のオブジェクトや関数の使い方を調べる必要があり、作業のハードルは思った以上でした。<br><a href="https://qiita.com/reisyu/items/84aa97117439e4962bbf">こちらのブログ記事</a>や<a href="https://kantoku.hatenablog.com/archive/category/Fusion360API?page=20">「Kantoku」さんのサイト</a>を参考にしながら少しだけ進めてみたのですが、残念ながら長続きせず中断してしまいました。</p>



<p class="wp-block-paragraph">ところが昨年、AI（生成AI）が大きく注目されるようになり、「これを使ってみるか？」と再び興味がわきました。<br>試しにFusion向けのコードをAIに聞いてみると、実際に動作するスクリプトを提案してくれて、少しやる気が復活…<br>しかしそれも一時的で、またもや放置状態に。</p>



<figure class="wp-block-embed is-type-wp-embed"><div class="wp-block-embed__wrapper">

<a href="https://www.kazuban.com/blog/generative-ai-for-fusion360/" title="話題の『生成Ai』に、Fusion360のPythonスクリプトをきいてみた" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="160" height="90" src="https://www.kazuban.com/blog/wp-content/uploads/2024/01/generative-ai-160x90.jpg" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://www.kazuban.com/blog/wp-content/uploads/2024/01/generative-ai-160x90.jpg 160w, https://www.kazuban.com/blog/wp-content/uploads/2024/01/generative-ai-120x68.jpg 120w, https://www.kazuban.com/blog/wp-content/uploads/2024/01/generative-ai-320x180.jpg 320w" sizes="(max-width: 160px) 100vw, 160px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">話題の『生成Ai』に、Fusion360のPythonスクリプトをきいてみた</div><div class="blogcard-snippet internal-blogcard-snippet">最近『生成Ai』を触り始めました。今までの、検索に比べても、非常に便利です。できる事の幅が広すぎて、ついていけませんが、プログラムコードも出力してくれるようです。いままで手を付けていなかった、Fusion360のPythonスクリプトを質問してみました。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://www.kazuban.com/blog" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">www.kazuban.com</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2024.01.27</div></div></div></div></a>
</div></figure>



<p class="wp-block-paragraph">そして今回！<br>AIもさらに進化してきた今こそ、もう一度挑戦してみようと思い立ちました。<br>本記事では、Fusion360 Python API に再び取り組み始めた記録と、コーディングへのAIの活用事例をレポートしています。<br>例題として、Fusion APIの基本ライブラリを作成しましたので、利用できそうであれば、利用していただければ幸いです。</p>



<p class="wp-block-paragraph">なお、より高度なスクリプトや実践的な例に興味がある方は、<a href="https://kantoku.hatenablog.com/archive/category/Fusion360API?page=20">「Kantoku」さんのサイト</a>に素晴らしい資料が公開されていますので、ぜひチェックしてみてください。</p>




  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-12" checked><label class="toc-title" for="toc-checkbox-12">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">今回の目標：スケッチ関連の基本ライブラリを作る</a></li><li><a href="#toc2" tabindex="0">Aiの実力を試してみる</a><ol><li><a href="#toc3" tabindex="0">fusionのpython API で直線を引くコード</a><ol><li><a href="#toc4" tabindex="0">ローカルLLM</a></li><li><a href="#toc5" tabindex="0">オンラインLLM</a></li></ol></li><li><a href="#toc6" tabindex="0">コンポネントやスケッチのアクティブな状態を把握</a><ol><li><a href="#toc7" tabindex="0">現状がスケッチモードかどうかの判定</a></li></ol></li></ol></li><li><a href="#toc8" tabindex="0">python特有な構文</a></li><li><a href="#toc9" tabindex="0">Fusion スクリプトをライブラリ化する</a><ol><li><a href="#toc10" tabindex="0">ライブラリの登録場所とpythonでの実装方法</a></li><li><a href="#toc11" tabindex="0">実行スクリプトと同じレベルのスクリプトをインポートするには？</a></li></ol></li><li><a href="#toc12" tabindex="0">ライブラリ利用方法</a></li><li><a href="#toc13" tabindex="0">ライブラリを利用して、X,Y,Zの座標軸にセンターラインを描く</a><ol><ol><li><a href="#toc14" tabindex="0">CenterLine.py</a></li><li><a href="#toc15" tabindex="0">lib_util.py</a></li><li><a href="#toc16" tabindex="0">lib_2d.py</a></li></ol></li></ol></li><li><a href="#toc17" tabindex="0">注意点</a></li><li><a href="#toc18" tabindex="0">まとめ</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">今回の目標：スケッチ関連の基本ライブラリを作る</span></h2>



<p class="wp-block-paragraph">Python言語は、ほとんど初心者ですが、ネット情報やAiを参考にコードをコピペするだけでは、なかなか覚えられないと思っています。<br>そこで、基本的なコードをライブラリ化する事で、少しは理解も深まるかと思い、まずはスケッチ周りの基本コードをライブラリ化してみようと思います</p>



<h2 class="wp-block-heading"><span id="toc2">Aiの実力を試してみる</span></h2>



<p class="wp-block-paragraph">さっそく、何種類かのLLMに質問してみました。</p>



<h3 class="wp-block-heading"><span id="toc3">fusionのpython API で直線を引くコード</span></h3>



<h4 class="wp-block-heading"><span id="toc4">ローカルLLM</span></h4>



<p class="wp-block-paragraph">ローカルの場合、私の環境では、レスポンス的に30bぐらいが実用できる限界です。<br>そこで、「gemma-3-27b」「qwen3-32b」で試してみます</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">「fusionのpython API で直線を引くコードをだして」</p>
</blockquote>



<p class="wp-block-paragraph">最初に、「import adsk.core, adsk.fusion, traceback」など<span class="marker-under">Fusion特有のパッケージをインポート</span>しするコードを出してくれるので、なかなかいいな！と思っていましたが、実際にFusionで実行してみても正常動作しませんでした。<br>特に、CAD画面上にメッセージを出力する場合、「ui.messageBox」を利用しますが、一般的なpythonの「print」文を使ったりしています。<br>また、私の環境で30bクラスのLLMでは、<span class="marker-under-blue">回答に５分以上</span>かかりました。<br>文章をまとめたり、翻訳したりの場合では、8bクラスでもいい回答をもらえますが、Fusion API のPython場合はちょっとマイナーなのかもしれません<br>参考にはなると思いますが、<span class="marker-under-red">私</span><span class="marker-under-red">の</span><span class="marker-under-red">環境</span><span class="marker-under-red">では</span><span class="marker-under-red">ちょっとレスポンスが悪いです</span>。</p>



<h4 class="wp-block-heading"><span id="toc5">オンラインLLM</span></h4>



<p class="wp-block-paragraph">次に、オンラインの「chatGPT」と「gemini」で試してみました。<br><span class="marker-under">「chatGPT」も「gemini」も、正常に動作しました</span>。<br>ただし、ログインしないと、会話履歴や共有できないので、ログインしたほうがいいと思います。<br>制限がある場合がありますが、そこそこ無料利用できます。<br>やはり、さすがです。回答レスポンスも早いです。<br>今回の質問では、<a href="https://www.kazuban.com/blog/generative-ai-for-fusion360/#toc6">一年前に、出してくれたコードとほとんど同じコードをだしてくれました。</a><br>一年前は、「bard(gemini)」のコードは、正常動作しないコードでしたが、現在の「gemini」は問題ないコードを出してくれます。<br>個人的は、ローカルLLMを使いたい気持ちがあるのですが、開発作業では、やはりレスポンスは重要なので、今後の学習はオンラインLLMを利用しようと思います。<br>まずは「Gemini 2.5Flash」を利用してみて、いい回答が出なかった場合には、「chatGPT」や「Gemini 2.5Pro」を使おうと思います</p>



<h3 class="wp-block-heading"><span id="toc6">コンポネントやスケッチのアクティブな状態を把握</span></h3>



<p class="wp-block-paragraph"><a href="https://www.kazuban.com/blog/generative-ai-for-fusion360/#toc6">上記の直線を描くサンプルコード</a>では、ルートコンポネントに新しいスケッチを作成し、そのスケッチに直線を引いています。<br>もう少し、実践的な動作にしたいです。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<ul class="wp-block-list">
<li>スケッチモードであれば、そのスケッチに・・</li>



<li>スケッチモードでない場合、ルートにこだわらず、アクティブなコンポネントに新しいスケッチを作成しそのスケッチに・・</li>
</ul>
</blockquote>



<p class="wp-block-paragraph">これを実現させるには、まず<span class="marker-under">現状のアクティヴな状態を把握する</span>必要があります<br>アクティブなコンポーネントを見つける関数はすぐ見つかりましたが、<span class="marker-under-red">スケッチのモード判定方法はなかなか見つか</span><span class="marker-under-red">らず</span>Aiのお陰でどうにかなりそうです。<br>こういった汎用的だけど苦労した処理を、ライブラリ化しておくと、後々便利だと思います</p>



<h4 class="wp-block-heading"><span id="toc7">現状がスケッチモードかどうかの判定</span></h4>



<p class="wp-block-paragraph">何度かgemini に聞いてみたところ、「<strong>activeEditObject」</strong>「<strong>activeEnvironment</strong>」を使用する方法があるとの回答をもらいました。<br>ただし、Ai としては、<span class="marker-under-red">「<strong>activeEditObject</strong>」を推奨</span>するとの事でした</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-461f21f5f0623461ac160a0a7c456f79"><code>import adsk.core
import adsk.fusion

def is_sketch_mode_active():
    """
    現在スケッチモード（いずれかのスケッチが編集中）かどうかを判定します。

    Returns:
        bool: スケッチモードであれば <strong>True</strong>、そうでなければ <strong>False</strong>。
        adsk.fusion.Sketch: アクティブなスケッチオブジェクト（スケッチモードの場合）。
    """
    try:
        app = adsk.core.Application.get()
        
        # 現在編集中のオブジェクトを取得
        active_object = app.activeEditObject

        # 編集中のオブジェクトがスケッチ（Sketch）であるかを確認
        if active_object and <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-yellow-color">isinstance(active_object, adsk.fusion.Sketch):</mark>
            return <strong>True</strong>, active_object
        else:
            return <strong>False</strong>, None

    except:
        return False, None

# --- 実行例 ---
def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui = app.userInterface

        is_active, active_sketch = is_sketch_mode_active()

        if is_active:
            ui.messageBox(f'はい、現在スケッチモードです。\nアクティブなスケッチ: {active_sketch.name}')
        else:
            ui.messageBox('いいえ、現在スケッチモードではありません。')

    except:
        if ui:
            ui.messageBox('エラーが発生しました。')</code></pre>



<p class="wp-block-paragraph">判定で、「<span class="marker-under-red">isinstance()</span>」関数を使っています。<br>これは、自力では、なかなか探せなかったと思います。恐るべし、Aiです。</p>



<h2 class="wp-block-heading"><span id="toc8">python特有な構文</span></h2>



<p class="wp-block-paragraph">Aiが出してくれた、サンプルコードを見ると、C言語とは違う書き方が結構出てきます<br>例えば</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">return<strong> True , active_object</strong></p>
</blockquote>



<p class="wp-block-paragraph">のように、複数変数を返す事ができて、取り出しは、下記のように「,」で区切って利用できるのですね</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph"><strong>is_active , active_sketch</strong> = is_sketch_mode_active()</p>
</blockquote>



<p class="wp-block-paragraph">C++言語では、最近ではstd::tupleが利用できるみたいですが、それを知らない私は、classを使ったりしていますが、こちらのほうが、面倒ないですね。<br>「if文」も「<strong>三項演算子</strong>」と呼ばれている構文が結構使われていました。</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-6adc7d18a4400a93e3504e1accf22d81"><code>design = get_design()
return <strong><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-yellow-color">design.activeComponent if design else None</mark></strong></code></pre>



<p class="wp-block-paragraph">C言語にも「三項演算子」はありますが、if文のほうが、分かりやすいかも・・<br>配列系も、多種類があるようで、Aiが出してくれたサンプルでも結構多用しています</p>



<pre class="wp-block-code"><code>plane = plane.lower()
planes_map = {
    "xy": component.xYConstructionPlane,
    "xz": component.xZConstructionPlane,
    "yz": component.yZConstructionPlane
}   
base_plane = planes_map.get(plane)</code></pre>



<p class="wp-block-paragraph">この「<strong>.get(plane)</strong>」はなんだ？<br>と思いましたが、これもAiに聞くと、すぐに説明してくれました。<br><strong>planes_map[plane]</strong>でもアクセスできるようですが、<span class="marker-under-red"><strong>get()</strong>を使うと<strong>plane</strong>が存在しない場合安全に</span>デフォルト値（<code><strong>None</strong></code>または指定した値）を返してくれるようです。<br>本当にすぐに教えてくれるので、私のような独学の場合、参考書などをめくるよりも、言語の理解は数段速くなるでしょうね～</p>



<h2 class="wp-block-heading"><span id="toc9">Fusion スクリプトをライブラリ化する</span></h2>



<p class="wp-block-paragraph">Fusion では、「ユーティリティ」⇒「アドイン」⇒「スクリプトとアドイン」⇒「+」で新規にスクリプトを作成できます</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="754" height="572" src="https://www.kazuban.com/blog/wp-content/uploads/2025/07/NewScript.png" alt="" class="wp-image-11300" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/07/NewScript.png 754w, https://www.kazuban.com/blog/wp-content/uploads/2025/07/NewScript-500x379.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/07/NewScript-300x228.png 300w" sizes="(max-width: 754px) 100vw, 754px" /></figure>



<p class="wp-block-paragraph">このダイアログの「<strong>フォルダの場所</strong>」に「<strong>名前</strong>」に入力のフォルダを作成し、その中に「<strong>名前.py</strong>」で実行スクリプトが作成されます。<br>「フォルダの場所」はデフォルトでは、かなり深いので、私は「D:\Fusion360\Scripts」のようにシンプルな場所に変更しています。<br>また、この場所は、<span class="marker-under">「基本設定」⇒「一般」⇒「API」</span>でデフォルトを変更できます<br>ただし、ここでの設定箇所に<span class="marker-under-red">「Scripts」は自動作成</span>されるので、<span class="marker-under-red">「D:\Fusion360」</span>になります</p>



<p class="wp-block-paragraph">Fusionスクリプトは、Fusionオブジェクトモデルを介して、利用したいオブジェクトのコマンドを記述します。<br>したがって、スクリプトを作成するには、各オブジェクトの情報が必要となり、かなり複雑です。</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="677" height="437" src="https://www.kazuban.com/blog/wp-content/uploads/2025/07/Sketch-2.png" alt="" class="wp-image-11332" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/07/Sketch-2.png 677w, https://www.kazuban.com/blog/wp-content/uploads/2025/07/Sketch-2-500x323.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/07/Sketch-2-300x194.png 300w" sizes="(max-width: 677px) 100vw, 677px" /></figure>



<p class="wp-block-paragraph"><br>今回は、Pythonの学習も兼ねて、Fusionのスケッチ関連オブジェクトをカプセル化したライブラリを作成したいと思います。</p>



<h3 class="wp-block-heading"><span id="toc10">ライブラリの登録場所とpythonでの実装方法</span></h3>



<p class="wp-block-paragraph">ライブラリフォルダは、Fusionが自動作成する、「Scripts」内の自作スクリプトと同じレベルに登録したいと思います</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">D:\Fusion360\Scripts<br>├── 新規スクリプト<br>├── CenterLine # 自作スクリプト<br>│ └── CenterLine.py # X,Y,Zの軸のセンターラインを作成する<br>│<br>├── library # 作成ライブラリ登録フォルダ<br>│ ├── <em>_init_</em>.py # 空ファイル（必要らしい）<br>│ ├── lib_util.py # Component &amp; Sketch 関連関数<br>│ └── lib_2d.py # 点や直線を作成（今後、円、円弧なども追加予定）<br></p>
</blockquote>



<p class="wp-block-paragraph">私の環境では、このようなイメージです。<br>「library」フォルダ内に「lib_util.py」「lib_2d.py」スクリプトを作成<br>「lib_util.py」は、Component や sketch を提供する基本関数を記述します<br>「lib_2d.py」は、点や直線を扱う関数を作成しますが、<span class="marker-under">「<strong>lib_util.py</strong>」の関数も利用します</span><br>今回はこの二つのライブラリを利用して、 X,Y,Zの軸のセンターラインを作成する「CenterLine /CenterLine.py」スクリプトを作成します</p>



<h3 class="wp-block-heading"><span id="toc11">実行スクリプトと同じレベルのスクリプトをインポートするには？</span></h3>



<p class="wp-block-paragraph">インポートするコードもわからないので、さっそくAiに聞いてみました<br>上記の構造をAiに渡して、実行スクリプト「CenterLine.py」から「lib_util.py」の関数を利用するコードを聞いてみました<br>この場合、正確なディレクトリ構造を取得する事が必要だと言うことで下記コードを教えてもらいました。</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-99ee604cd6fe96d6d4cf1c7e56b1ef5c"><code>current_dir = os.path.dirname(os.path.abspath(__file__))
script_dir = os.path.dirname(current_dir)</code></pre>



<p class="wp-block-paragraph">この構成はよくライブラリや設定ファイルを<span class="marker-under">相対パスで読み込むときの定番のコード</span>のようです<br>もう少し、詳しく説明してもらいました。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">_file_：現在実行中のPythonスクリプトのファイルパス<br>os.path.abspath(__file__)：絶対パスに変換<br>os.path.dirname(…)：そのファイルが属するディレクトリを取得<br><br>D:/Fusion360/Scripts/<br>├── library/<br>│ └── __init__.py # モジュールの初期化用<br>│ └── lib_util.py<br>│ └── lib_2d.py<br>├── CenterLine/<br>│ └── CenterLine.py ← 実行スクリプト</p>



<p class="wp-block-paragraph">__file__ → &#8220;./CenterLine/CenterLine.py&#8221;<br>abspath(__file__) → &#8220;D:/Fusion360/Scripts/library/CenterLine/CenterLine.py&#8221;<br>current_dir → &#8220;D:/Fusion360/Scripts/library/CenterLine&#8221;<br>script_dir → &#8220;D:/Fusion360/Scripts/library&#8221;</p>
</blockquote>



<p class="wp-block-paragraph">このコードで、ライブラリのディレクトリを取り出し、<br>「sys.path.append(script_dir)」でpythonが内部でモジュール検索時に、指定ディレクトリを追加するの意味のようです<br>この設定後に、「from library import lib_util」コードで「library」ディレクトリ内の「lib_util.py」内の関数を使用できるようになります<br>具体的には、下記になります</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-8e2a343bbae44e922fe021104cc52319"><code>import os, sys

current_dir = os.path.dirname(os.path.abspath(__file__))
script_dir = os.path.dirname(current_dir)
sys.path.append(script_dir)
from <strong>library </strong>import <strong>lib_util</strong></code></pre>



<p class="wp-block-paragraph">これで、新規作成したスクリプトに、このコードを追加すると、「lib_util」内の関数が使えます<br>さらに「lib_2d.py」ライブラリも、「lib_util.py」の関数も利用しますが、こちらは、<span class="marker-under">「lib_util.py」と同じディレクトリ内</span>なので、「script_dir = os.path.dirname(current_dir)」のコードは<span class="marker-under-red">不要</span>になりますね</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-6f026c1782e213cab59b1b4af17510bf"><code>import os, sys
current_dir = os.path.dirname(os.path.abspath(__file__))
<s><strong>#</strong> script_dir = os.path.dirname(current_dir)</s>
sys.path.append(current_dir)
import lib_util
</code></pre>



<p class="wp-block-paragraph">実際には結構時間がかかったのですが、これで、やっとライブラリが使えるようになりました。<br>本当、Ai様様です。<br>Aiの進歩で、コーディングの勉強は不要だとの意見もありますが、やっぱりコードの意味の理解は必要だと思います。<br>たぶん、Aiもそう思っているのでしょう！詳しいコメントを日本語で追記してくれます。<br>「あなたの言葉でコメントつけるから、覚えてね！」と言ってる気がします。<br>Ai利用でプログラミングの学習速度は、以前よりも圧倒的に速くなると思います</p>



<h2 class="wp-block-heading"><span id="toc12">ライブラリ利用方法</span></h2>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">./Scripts/<br>├── 新規スクリプト/ # &lt;&#8212;&#8212;&#8211; Fusion ダイアログで作成<br>│ └── 新規スクリプト.py<br>├── library/ #&lt;&#8212;&#8212;&#8212; Scripts/ 直下に作成<br>│ └── __init__.py # &lt;&#8212;&#8211; 空ファイル追加作成、モジュールの初期化用<br>│ └── lib_util.py # &lt;&#8212;&#8212;- ライブラリファイル<br>│ └── lib_2d.py # &lt;&#8212;&#8212;- ライブラリファイル<br>└── CenterLine/ # &lt;&#8212;&#8212;- 自作スクリプト用<br>│ └── CenterLine.py # &lt;&#8212;&#8212;- 自作スクリプトファイル<br>└─────── </p>
</blockquote>



<p class="wp-block-paragraph">イメージ的には、このようになります。<br>Fusionで「スクリプトまたはアドイン作成」を実行すると、設定ダイアログが表示され、設定した「フォルダの場所」へ設定した名前のフォルダが自動作成され、さらにその中に、設定した名前.py の実行ファイルが作成されます。</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="558" height="224" src="https://www.kazuban.com/blog/wp-content/uploads/2025/07/add-ins.png" alt="" class="wp-image-11358" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/07/add-ins.png 558w, https://www.kazuban.com/blog/wp-content/uploads/2025/07/add-ins-500x201.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/07/add-ins-300x120.png 300w" sizes="(max-width: 558px) 100vw, 558px" /></figure>



<p class="wp-block-paragraph">今回紹介のライブラリは、Fusionで設定した「フォルダの場所」の直下に「library」の名前でフォルダを作成し、さらに「library」の直下に、「__init__.py」「lib_util.py」「lib_2d.py」を作成します<br>「__init__.py」は、空ファイルですが、Aiが言うには、ライブラリを利用する際必要みたいです。<br>「lib_util.py」「lib_2d.py」も一旦空ファイルを作っておいて、下記コードをコピペして保存します</p>



<h2 class="wp-block-heading"><span id="toc13">ライブラリを利用して、X,Y,Zの座標軸にセンターラインを描く</span></h2>



<p class="wp-block-paragraph">まずは、Fusion 「スクリプトとアドイン」で、新規スクリプトを作成します<br>ここでは「CenterLine」という名前にしました。<br>これで、「./Scripts」ディレクトリ内に、「CenterLine/CenterLine.py」が作成されています。<br>CenterLine.pyファイルの内容を、下記コードで上書きして保存します</p>



<h4 class="wp-block-heading"><span id="toc14">CenterLine.py</span></h4>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-669094fb191368c9558d98db4e1a51f8"><code>"""This file acts as the main module for this script."""

import traceback
import adsk.core
import adsk.fusion
# import adsk.cam

import os, sys, importlib
#library import
current_dir = os.path.dirname(os.path.abspath(__file__))
script_dir = os.path.dirname(current_dir)
sys.path.append(script_dir)
from library import lib_util,lib_2d

def run(context):
    try:
        lib_2d.draw_center_line(100,100,100)
 
    except:
        lib_util.disp_message('Failed:\n{}'.format(traceback.format_exc()))
</code></pre>



<p class="wp-block-paragraph">下記が、ライブラリ用スクリプトファイルです</p>



<h4 class="wp-block-heading"><span id="toc15">lib_util.py</span></h4>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-e25baaca05132da85fad5d0dc35a19a0"><code>import adsk.core, adsk.fusion, adsk.cam, traceback
from typing import Tuple, Optional

#このライブラリは
#Fusionが作成するスクリプトと同じディレクトリに置かれる事を想定している
#使用する場合には、下記コードにより読み込みパスを追加する
"""
import os, sys, importlib
current_dir = os.path.dirname(os.path.abspath(__file__))
script_dir = os.path.dirname(current_dir)
sys.path.append(script_dir)
from library import lib_util
"""
# ---------------------
## Get Fusion object
# ---------------------
def get_app():
    return adsk.core.Application.get()
def get_design():
    app = get_app() 
    return adsk.fusion.Design.cast(app.activeProduct)
def get_ui():
    app = get_app() 
    return app.userInterface

# ---------------------
## メッセージ表示
# ---------------------
def disp_message(msg: str):
    """ユーザーにメッセージボックスを表示"""
    ui = get_ui()
    if ui:
        ui.messageBox(msg)

# ---------------------
## Component &amp; Sketch Functions
# ---------------------
# /////////////////////////////////////////////////////////////
def get_root_component() -&gt; Optional&#91;adsk.fusion.Component]:
    """ルートコンポーネントを返す"""
    design = get_design()
    return design.rootComponent if design else None

# /////////////////////////////////////////////////////////////
def get_active_component() -&gt; Optional&#91;adsk.fusion.Component]:
    """現在アクティブなコンポーネントを返す"""
    design = get_design()
    return design.activeComponent if design else None

# /////////////////////////////////////////////////////////////
def create_new_component(name: str = 'New_Component') -&gt; Optional&#91;adsk.fusion.Component]:
    """新しいコンポーネントを作成し、アクティブなコンポーネントの配下に追加"""
    component = get_active_component()
    if not component:
        component = get_root_component()
    
    if not component:
        disp_message('コンポーネントが見つかりません。デザインがアクティブか確認してください。')
        return None
    
    try:
        occurrences = component.occurrences
        new_occurrence = occurrences.addNewComponent(adsk.core.Matrix3D.create())
        new_component = new_occurrence.component
        new_component.name = name
        return new_component
    except Exception:
        disp_message(f'新しいコンポーネントの作成に失敗しました:\n{traceback.format_exc()}')
        return None

# /////////////////////////////////////////////////////////////
def get_parent_sketch(obj: any) -&gt; Optional&#91;adsk.fusion.Sketch]:
    """指定されたオブジェクトの親スケッチを取得"""
    return obj.parentSketch if hasattr(obj, 'parentSketch') else None

# /////////////////////////////////////////////////////////////
def create_new_sketch(name: str = 'New_Sketch', plane: str = 'xy') -&gt; Optional&#91;adsk.fusion.Sketch]:
    """指定された平面に新しいスケッチを作成"""
    component = get_active_component()
    if not component:
        component = get_root_component()
    
    if not component:
        disp_message('スケッチを作成するコンポーネントが見つかりません。')
        return None
    
    plane = plane.lower()
    planes_map = {
        "xy": component.xYConstructionPlane,
        "xz": component.xZConstructionPlane,
        "yz": component.yZConstructionPlane
    }
    
    base_plane = planes_map.get(plane)
    if not base_plane:
        disp_message(f"サポートされていない平面: '{plane}' 'xy', 'xz', 'yz' のいずれかを選択してください。")
        return None
        
    try:
        sketches = component.sketches
        sketch = sketches.add(base_plane)
        sketch.name = name
        return sketch
    except Exception:
        disp_message(f'新しいスケッチの作成に失敗しました:\n{traceback.format_exc()}')
        return None

# /////////////////////////////////////////////////////////////
def is_sketch_mode_active() -&gt; Tuple&#91;bool, Optional&#91;adsk.fusion.Sketch]]:
    """現在スケッチモードがアクティブであるかを確認し、スケッチオブジェクトを返す"""
    app = get_app()
    active_object = app.activeEditObject
    # is_instance() を使うことで、より安全に型チェックを行う
    if isinstance(active_object, adsk.fusion.Sketch):
        return True, active_object
    else:
        return False, None

# /////////////////////////////////////////////////////////////
def get_sketch() -&gt; Optional&#91;adsk.fusion.Sketch]:
    """アクティブなスケッチを返す、アクティブでない場合は新しいスケッチを作成"""
    is_active, sketch = is_sketch_mode_active()
    if not is_active:
        sketch = create_new_sketch()
    return sketch
</code></pre>



<h4 class="wp-block-heading"><span id="toc16">lib_2d.py</span></h4>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-be5884e5b0d369633af538947edd4e83"><code>import adsk.core, adsk.fusion, adsk.cam, traceback
from typing import Tuple, Optional

# 利用するlib_utilは、このライブラリと同じディレクトリ
import os, sys, importlib
current_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.append(current_dir)
import lib_util

# ---------------------
## カスタム、点基本クラス
# ---------------------
# /////////////////////////////////////////////////////////////
class kPoint:
    """3D空間の点を表す基本クラス"""
    def __init__(self, x: float, y: float, z: float = 0.0):
        self.x = x
        self.y = y
        self.z = z

# ---------------------
## カスタム、スケッチ点クラス
# ---------------------
# /////////////////////////////////////////////////////////////
class kSketchPoint(kPoint):
    """Fusion 360 のスケッチ点として使用される座標を、単位とスケッチ平面に応じて変換するクラス"""
    def __init__(self, x: float = 0.0, y: float = 0.0, z: float = 0.0, sketch: Optional&#91;adsk.fusion.Sketch] = None, unit: str = "mm"):
        unit = unit.lower()
        # 単位変換係数を辞書で管理
        scale_factors = {"mm": 0.1, "cm": 1.0, "m": 10.0}
        scale = scale_factors.get(unit, 1.0) # 存在しない単位は1.0 (cm) を使用

        if not sketch:
            sketch = lib_util.get_sketch() # スケッチが指定されていなければ、アクティブなスケッチを取得

        # スケッチ平面に応じて座標系を調整 (XZ平面はY軸が下向き)
        # 参照平面が'XZ'の場合は、y座標を反転させる
        # これはFusion 360の座標系の癖に対応
        direction_y = -1.0 if sketch and sketch.referencePlane.name == "XZ" else 1.0
        
        # 単位と座標系による方向を調整
        converted_x = x * scale
        converted_y = y * scale * direction_y
        converted_z = z * scale
        
        super().__init__(converted_x, converted_y, converted_z)
        self.sketch = sketch
        self.unit = unit
        
# ---------------------
## Sketch Geometry Creation Functions
# ---------------------
# /////////////////////////////////////////////////////////////
def is_equal_sketch_points(sp1: adsk.fusion.SketchPoint, sp2: adsk.fusion.SketchPoint, tolerance: float = 0.0001) -&gt; bool:
    """2つのスケッチ点が指定された許容差内で同じ位置にあるかどうかを判断"""
    # ジオメトリオブジェクトの距離を比較
    distance = sp1.geometry.distanceTo(sp2.geometry)
    return distance &lt; tolerance

# /////////////////////////////////////////////////////////////
def create_sketch_point(x: float = 0, y: float = 0, z: float = 0, sketch: Optional&#91;adsk.fusion.Sketch] = None) -&gt; Optional&#91;adsk.fusion.SketchPoint]:
    """指定された座標にスケッチ点を作成"""
    if not sketch:
        sketch = lib_util.get_sketch()
    
    if not sketch:
        lib_util.disp_message('スケッチがアクティブでないか、新しいスケッチの作成に失敗しました。')
        return None
        
    try:
        # kSketchPoint を使用して単位と平面を考慮した座標を取得
        converted_point = kSketchPoint(x, y, z, sketch)
        # adsk.core.Point3D オブジェクトを作成
        point3d = adsk.core.Point3D.create(converted_point.x, converted_point.y, converted_point.z)
        # スケッチに点を追加
        sketchPoint = sketch.sketchPoints.add(point3d)
        return sketchPoint
    except Exception:
        lib_util.disp_message(f'スケッチ点の作成に失敗しました:\n{traceback.format_exc()}')
        return None

# /////////////////////////////////////////////////////////////
def create_line_from_sketchpoints(sp1: adsk.fusion.SketchPoint, sp2: adsk.fusion.SketchPoint, construction: bool = False, fixed: bool = False) -&gt; Optional&#91;adsk.fusion.SketchLine]:
    """2つの既存のスケッチ点から直線を作成"""
    # 同じスケッチに属しているかチェック
    if lib_util.get_parent_sketch(sp1) != lib_util.get_parent_sketch(sp2):
        lib_util.disp_message('2つの点は異なるスケッチに属しています。')
        return None
        
    # 2つの点が同じ位置にあるかチェック
    if is_equal_sketch_points(sp1, sp2):
        lib_util.disp_message('2つの点が同じ位置にあります。直線を作成できません。')
        return None
        
    sketch = lib_util.get_parent_sketch(sp1)
    if not sketch:
        lib_util.disp_message('親スケッチが見つかりません。')
        return None
        
    try:
        line = sketch.sketchCurves.sketchLines.addByTwoPoints(sp1, sp2)
        line.isConstruction = construction
        line.isFixed = fixed
        return line
    except Exception:
        lib_util.disp_message(f'直線（スケッチ点から）の作成に失敗しました:\n{traceback.format_exc()}')
        return None

# /////////////////////////////////////////////////////////////
def create_line_from_coordinate(x1: float, y1: float, z1: float, x2: float, y2: float, z2: float, sketch: Optional&#91;adsk.fusion.Sketch] = None, construction: bool = False, fixed: bool = False) -&gt; Optional&#91;adsk.fusion.SketchLine]:
    """座標から直接、スケッチ直線を作成"""
    if not sketch:
        sketch = lib_util.get_sketch()

    if not sketch:
        return None

    # ヘルパー関数を利用して点を先に作成
    p1 = create_sketch_point(x1, y1, z1, sketch)
    p2 = create_sketch_point(x2, y2, z2, sketch)
    
    if p1 and p2:
        return create_line_from_sketchpoints(p1, p2, construction, fixed)
    else:
        lib_util.disp_message('直線を作成するための点の作成に失敗しました。')
        return None

# /////////////////////////////////////////////////////////////
def create_line_from_points(p1: kPoint, p2: kPoint, sketch: Optional&#91;adsk.fusion.Sketch] = None, construction: bool = False, fixed: bool = False) -&gt; Optional&#91;adsk.fusion.SketchLine]:
    """カスタム `kPoint` オブジェクトからスケッチ直線を作成"""
    if not sketch:
        sketch = lib_util.get_sketch()
    
    if not sketch:
        return None
        
    return create_line_from_coordinate(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, sketch, construction, fixed)

# /////////////////////////////////////////////////////////////
def draw_center_line(widthX=100,widthY=100,widthZ=100):
    """センターライン作成"""
    widthX = 100 if widthX == 0 else widthX
    widthY = 100 if widthY == 0 else widthY
    widthZ = 100 if widthZ == 0 else widthZ
    wx=widthX/2
    wy=widthY/2
    wz=widthZ/2
    sketch = lib_util.get_sketch()
    xp1 = kPoint(-wx,0)
    xp2 = kPoint(wx,0)
    yp1 = kPoint(0,-wy)
    yp2 = kPoint(0,wy)
    zp1 = kPoint(0,0,-wz)
    zp2 = kPoint(0,0,wz)
    create_line_from_points(xp1,xp2,sketch,True,True) #X Axis
    create_line_from_points(yp1,yp2,sketch,True,True) #Y Axis
    create_line_from_points(zp1,zp2,sketch,True,True) #Z Axis
</code></pre>



<h2 class="wp-block-heading"><span id="toc17">注意点</span></h2>



<p class="wp-block-paragraph">実は、まだ解決できていない注意点があります<br>通常のライブラリ使用では問題ないと思いますが、Fusionでライブラリを利用したスクリプトを実行後、<span class="marker-under-red">ライブラリ内スクリプトを編集しても、編集内容が反映されません。</span><br>Aiに聞いてみると、Fusionの仕様でキャッシュが優先されているとの事です<br>キャッシュクリアのコードも教えてもらいましたが、現状では反映されません。<br><span class="marker-under-red">ライブラリの編集を反映させるには、Fusionを再起動</span>させるとキャッシュがクリアされ反映されます<br>ライブラリを試行錯誤している場合でも、ちょっと面倒です。<br>いい方法は、ないのかなぁ～？？</p>



<h2 class="wp-block-heading"><span id="toc18">まとめ</span></h2>



<p class="wp-block-paragraph">pythonはド素人なので、勉強もかねて、Ai にコーディングを教えてもらいながら、FusionのComponentやsketch、直線作成などの関数をライブラリ化してみました。<br>Fusionオブジェクトモデルは、広範囲で奥が深いので、探すのも大変です。<br>よく使いそうな関数を、まとめたので、少しは取り組みやすくなるのではないか？と思っています。<br>今後も進化させようと思っていますが、Aiがなかったら、ここまで完成できなかったと思います。<br>ここで紹介しているコードも、一旦自分なりに作成したスクリプトを、Aiに張り付けて、添削してもらったコードを再編集したものです。<br>関数名やコメントの書き方なども、pythonの慣習を教えてもらい参考にしています</p>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>AIに教えてもらいながら、どうにかUbuntu上の Docker EngineでDifyをサーバー化できた。</title>
		<link>https://www.kazuban.com/blog/ubuntu-dockerengine-dify/</link>
		
		<dc:creator><![CDATA[kazuban]]></dc:creator>
		<pubDate>Mon, 05 May 2025 01:17:22 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[IT]]></category>
		<category><![CDATA[Linux (CentOS、Rocky、Ubuntu)]]></category>
		<category><![CDATA[AIとのやり取り]]></category>
		<category><![CDATA[Dify]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[ubuntu24]]></category>
		<category><![CDATA[wsl]]></category>
		<guid isPermaLink="false">https://www.kazuban.com/blog/?p=11029</guid>

					<description><![CDATA[前回までで、「Docker Engine」の設定は完了しています。今回は、「Docker」で「Dify」を起動させサーバー化が目的です。実現するにあたって、かなりAIに助けてもらったので、そのやり取りも紹介しています。  [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><a href="https://www.kazuban.com/blog/wsl-ubuntu-dockerengine/">前回までで、「Docker Engine」の設定は完了しています。</a><br>今回は、「Docker」で「Dify」を起動させサーバー化が目的です。<br>実現するにあたって、かなりAIに助けてもらったので、そのやり取りも紹介しています。</p>




  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-14" checked><label class="toc-title" for="toc-checkbox-14">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">Difyをクローン化</a><ol><li><a href="#toc2" tabindex="0">gitの確認</a></li><li><a href="#toc3" tabindex="0">Gitでdifyをクローン化する</a></li></ol></li><li><a href="#toc4" tabindex="0">Difyコンテナ起動</a><ol><li><a href="#toc5" tabindex="0">docker compose upでエラー発生！AIに聞いてみる。</a></li></ol></li><li><a href="#toc6" tabindex="0">Dify起動</a><ol><li><a href="#toc7" tabindex="0">初期画面</a></li><li><a href="#toc8" tabindex="0">Difyの動作と試用</a></li></ol></li><li><a href="#toc9" tabindex="0">Difyを自動起動</a></li><li><a href="#toc10" tabindex="0">Difyをサーバー化して、他のPCからもアクセスさせる</a><ol><li><a href="#toc11" tabindex="0">DifyPCのIPアドレス調査</a></li><li><a href="#toc12" tabindex="0">Windowsのアドレスからは、アクセスできない。</a></li><li><a href="#toc13" tabindex="0">docker ps コマンドで実行中のコンテナーを提出</a></li><li><a href="#toc14" tabindex="0">ファイヤーウォールとポートフォワーディング設定</a><ol><li><a href="#toc15" tabindex="0">１．ファイアウォール開放 (ポート 80):</a></li><li><a href="#toc16" tabindex="0">2．ポートフォワーディング設定 (ポート 80):</a></li><li><a href="#toc17" tabindex="0">アクセスできた～</a></li></ol></li></ol></li><li><a href="#toc18" tabindex="0">DifyにLLMを設定して、カスタムチャット環境を構築</a><ol><li><a href="#toc19" tabindex="0">DifyにLLMの設定方法</a><ol><li><a href="#toc20" tabindex="0">オンラインLLMの登録</a></li><li><a href="#toc21" tabindex="0">LM Studio モデルの登録</a></li><li><a href="#toc22" tabindex="0">Ollama　モデルの登録</a></li></ol></li></ol></li><li><a href="#toc23" tabindex="0">あとがき</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">Difyをクローン化</span></h2>



<h3 class="wp-block-heading"><span id="toc2">gitの確認</span></h3>



<p class="wp-block-paragraph">difyをクローン化するのに、「git」を利用するので、「git」のインストール状況を確認します。<br>windows ターミナルを開き、wsl を起動し、「git -v」で状況を確認します。</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-6c280a658549c20db340281f1ee6bbdb"><code>PS C:\Users\hogehoge2&gt; wsl

$ git -v
git version 2.43.0
インストールされていない場合には、インストール
$ sudo apt update
$ sudo apt install git</code></pre>



<h3 class="wp-block-heading"><span id="toc3">Gitでdifyをクローン化する</span></h3>



<p class="wp-block-paragraph">「git clone ・・」でクローン化を実行すると、カレントディレクト下「dify」ディレクトリへソースコードがクローン化されます。<br>windowsターミナルで、「wsl」を実行し、ubuntu環境へ入ると、デフォルトでは、winndowsユーザーのディレクトリへセットされた状態で起動します。<br>好みの問題だと思いますが、この場所へ「dify」環境を作成してもいいと思いますが、筆者はubuntuのユーザーホームディレクトリ下に作成しようと思います。<br>wsl、ubuntuプロンプトで、「cd」を実行すると、ユーザーのホームディレクトリへ移動します。<br>その場所で「git clone・・」すると、そのディレクトリ直下に「dify」さらにその下に「docker」ディレクトリが作成されています。<br>「ls」コマンドで確認できます。<br>「dify/docker」ディレクトリへ「cd」コマンドで移動しておきます。<br>「pwd」コマンドで、現在のディレクトリが確認できます。</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-ad68e176018c4225a713c543c2c82523"><code>hogehoge2@hoge-PC:/mnt/c/Users/hogehoge2$
$ cd
$ git clone https://github.com/langgenius/dify.git
Cloning into 'dify'...
remote: Enumerating objects: 153846, done.
remote: Counting objects: 100% (536/536), done.
remote: Compressing objects: 100% (359/359), done.
remote: Total 153846 (delta 396), reused 178 (delta 177), pack-reused 153310 (from 3)
Receiving objects: 100% (153846/153846), 87.73 MiB | 5.07 MiB/s, done.
Resolving deltas: 100% (111131/111131), done.
$ ls
dify
$ cd dify/docker/
$ pwd
/home/hogehoge2/dify/docker</code></pre>



<h2 class="wp-block-heading"><span id="toc4">Difyコンテナ起動</span></h2>



<p class="wp-block-paragraph">「git clone」を実行したディレクトリに、「dify/docker」ディレクトリが作成されています。<br>その中に「.env.example」のサンプル環境変数ファイルが作成されています。<br>通常ファイルは「ls」コマンドで確認できますが。「.」で始まるファイルは表示されません。<br>その場合「ls -la」コマンドを実行すると、表示されます。<br>コピーは「cp &lt;オリジナルファイル名&gt;　&lt;複写ファイル名&gt;」で複写できます。<br>「.env.example」ファイルを、正式な環境変数「.env」としてコピーし、「docker compose」コマンドで、コンテナを起動させます。</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-69212d483fca0e2e7f0922dbf0b0ff47"><code>$ pwd
/home/hogehoge2/dify/docker
$ cp .env.example .env
$ docker compose up -d
&#91;+] Running 80/80    
✔ web Pulled             149.7s
✔ sandbox Pulled         221.1s
 ✔ ssrf_proxy Pulled      88.2s
 ✔ db Pulled             224.4s
 ✔ worker Pulled         402.2s
 ✔ plugin_daemon Pulled  404.6s
 ✔ nginx Pulled           36.4s
 ✔ weaviate Pulled       225.1s
 ✔ redis Pulled          221.2s
 ✔ api Pulled            402.2s
&#91;+] Running 12/12
 ✔ Network docker_default             Created    0.1s
 ✔ Network docker_ssrf_proxy_network  Created    0.0s
 ✔ Container docker-web-1             Started    3.7s
 ✔ Container docker-ssrf_proxy-1      Started    4.0s
 ✔ Container docker-sandbox-1         Started    3.7s
 ✔ Container docker-redis-1           Started    3.7s
 ✔ Container docker-weaviate-1        Started    3.7s
 ✔ Container docker-db-1              Healthy    10.7s
 ✔ Container docker-worker-1          Started    9.3s
 ✔ Container docker-plugin_daemon-1   Started    9.3s
 ✔ Container docker-api-1             Started    9.5s
 ✔ Container docker-nginx-1           Started    10.0s
</code></pre>



<h3 class="wp-block-heading"><span id="toc5">docker compose upでエラー発生！AIに聞いてみる。</span></h3>



<p class="wp-block-paragraph">上記は正常な例ですが、古いPCをテストマシンとして利用した時、「docker compose up」で下記エラーがでた事がありました。</p>



<blockquote class="wp-block-quote has-vivid-red-color has-watery-red-background-color has-text-color has-background has-link-color wp-elements-663148c1df4e9167eb9abd3e83e97fcc is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">dependency failed to start: container docker-db-1 is unhealthy</p>
</blockquote>



<p class="wp-block-paragraph">この時もgeminiに聞いてみたところ、「docker logs docker-db-1」でログを確認してくれとの事なので、ログを直接貼り付けると、</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-3 sbs-line sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon" style="--cocoon-custom-background-color:#fff7cc"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://www.kazuban.com/blog/wp-content/uploads/2025/04/Robot-icon.png" alt="Ai" class="speech-icon-image"/></figure><div class="speech-name">Ai</div></div><div class="speech-balloon has-background has-watery-yellow-background-color">
<p class="wp-block-paragraph">ログを見る限り、データベースの初期化自体は正常に完了しています (<code>PostgreSQL init process complete; ready for start up.</code>)。 その後の起動プロセスも進んでいますが、<strong><code>2025-04-29 00:02:07.998 UTC [557] FATAL: the database system is starting up</code></strong> という致命的なエラーが出力されています。</p>



<p class="wp-block-paragraph">このエラーは、PostgreSQLサーバーが起動してリカバリなどの内部処理を行っている最中に、外部からの接続要求（この場合はおそらくDockerのヘルスチェックや、依存するDifyコンテナからの初期接続試行）があった場合に発生することがあります。</p>



<p class="wp-block-paragraph">つまり、データベースサーバー自体は最終的に <code>database system is ready to accept connections</code> の状態になりますが、Dockerのヘルスチェックがサーバーの準備が完全に整う前に接続を試み、上記の <code>FATAL</code> エラーを受け取ってしまい、それが原因でコンテナが <code>unhealthy</code> と判定されている可能性が高いです。<br><br><strong>解決策:</strong></p>



<p class="wp-block-paragraph">Dockerのヘルスチェック設定を調整し、データベースが完全に起動して接続可能になるまで、チェックを待つように設定を変更するのが最も有効な対策です。</p>



<p class="wp-block-paragraph"><strong>データベースサービス (db または postgresql) の <code>healthcheck</code> 設定を見つける:</strong> <br><code>services</code> のセクションにある、データベースコンテナに対応するサービス定義（通常は <code>db</code> という名前）を探します。その中に <code>healthcheck</code> というブロックがあるはずです。<br><br><strong>YAML</strong><br><code>services: </code><br><br><code>db: # ... その他の設定 ...</code><br><code>  healthcheck: # ここに設定があります </code><br>　　・<br><code>    test: ["CMD-EXEC", "pg_isready -U &lt;db_user&gt; -d &lt;db_name&gt;"] # 例 </code><br><code>    interval: 10s </code><br><code>    timeout: 5s </code><br><code>    retries: 5 </code><br><code>    start_period: 30s # &lt;-- この値を調整します</code></p>



<p class="wp-block-paragraph"><strong><code>docker-compose.yml</code> を開く:</strong> Difyを起動するために使用している <code>docker-compose.yml</code> ファイルをテキストエディタで開きます。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-5 sbs-flat sbp-r sbis-cb cf block-box not-nested-style cocoon-block-balloon" style="--cocoon-custom-background-color:#dddddd"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://www.kazuban.com/blog/wp-content/themes/cocoon-master/images/ojisan.png" alt="じじぃ" class="speech-icon-image"/></figure><div class="speech-name">じじぃ</div></div><div class="speech-balloon has-background has-light-grey-background-color">
<p class="wp-block-paragraph">docker-compose.yamlを確認した所、「<code>start_period:</code>」の設定がありません。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-3 sbs-line sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon" style="--cocoon-custom-background-color:#fff7cc"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://www.kazuban.com/blog/wp-content/uploads/2025/04/Robot-icon.png" alt="Ai" class="speech-icon-image"/></figure><div class="speech-name">Ai</div></div><div class="speech-balloon has-background has-watery-yellow-background-color">
<p class="wp-block-paragraph"><code>start_period</code> が指定されていない場合、コンテナが起動を開始すると同時にヘルスチェックが始まります。今回のデータベースのログで見たように、起動直後の一時的な準備期間中に接続を試みると <code>FATAL: the database system is starting up</code> のようなエラーが発生することがあります。</p>



<p class="wp-block-paragraph"><code>interval: 1s</code> と非常に短い間隔でチェックが実行されるため、データベースが完全に準備できる前に多くのチェックが走ってしまい、すぐにリトライ回数（<code>retries: 60</code>）を使い果たして <code>unhealthy</code> と判定されてしまう可能性が高いです。</p>



<p class="wp-block-paragraph"><strong>解決策:</strong></p>



<p class="wp-block-paragraph"><code>start_period</code> を追加し、必要に応じて <code>interval</code> も調整しましょう。</p>



<ol class="wp-block-list">
<li><strong><code>healthcheck</code> 設定に <code>start_period</code> を追加する:</strong> データベースが起動して準備ができるまでの猶予期間として、<code>start_period</code> を設定します。<br>例えば <code>30s</code> または <code>60s</code> (30秒または60秒) を指定します。 <br><strong>YAML</strong><br><code>services: </code><br><code>db: # ... その他の設定 ... </code><br><br><code>  healthcheck: </code><br><code>    test: [ 'CMD', 'pg_isready', '-h', 'db', '-U', '${PGUSER:-postgres}', '-d', '${POSTGRES_DB:-dify}' ] </code><br><code>    interval: 5s # 例: 毎秒ではなく5秒ごとにチェックに緩和 </code><br><code>    timeout: 3s </code><br><code>    retries: 10 # 例: リトライ回数を調整 (intervalを長くすればretriesは少なくても良い) </code><br><code>    start_period: 60s # &lt;- この行を追加 (例: 60秒待つ)</code> <br><br><strong>ポイント:</strong> <code>start_period</code> の間は、ヘルスチェックが失敗してもコンテナは <code>starting</code> 状態のままとなり、<code>unhealthy</code> とは判定されません。<code>start_period</code> が経過した後に初めて、ヘルスチェックの失敗が <code>unhealthy</code> の判定に使われます。</li>



<li><strong><code>interval</code> も少し長めにすることをお勧めします:</strong> <code>interval: 1s</code> は開発時などに素早く確認したい場合には便利ですが、本番に近い環境や安定性を重視する場合は <code>5s</code> や <code>10s</code> に設定することが一般的です。これにより、データベースへの不要な負荷も軽減されます。</li>



<li><strong><code>docker-compose.yml</code> を保存する。</strong></li>



<li><strong>Docker Compose を再起動する:</strong> 変更を反映させるために、コンテナを再作成して起動します。</li>
</ol>
</div></div>



<p class="wp-block-paragraph">アドバイス通りに、編集して再度「docker compose up -d」を実行すると、正常になりました。<br>いやぁ～、AIさまさま、ですね～<br>おそらく、ネット検索では、解決できなかったと思います。<br>ただし、古いPCだったのが、一番の原因かもしれません。<br>５年ほど前のPCでは、このエラーはでなかったので、レアなケースかもしれませんが、AIの利用例として紹介しました。</p>



<h2 class="wp-block-heading"><span id="toc6">Dify起動</span></h2>



<h3 class="wp-block-heading"><span id="toc7">初期画面</span></h3>



<p class="wp-block-paragraph">「docker compose up」が正常に終了すると、Webブラウザで「http://localhost/install」へアクセスすると「dify」の初期設定が開きます</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="755" src="https://www.kazuban.com/blog/wp-content/uploads/2025/04/dify-localhost-800x755.png" alt="" class="wp-image-11052" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/04/dify-localhost-800x755.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/dify-localhost-500x472.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/dify-localhost-300x283.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/dify-localhost-768x725.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/dify-localhost.png 1200w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<h3 class="wp-block-heading"><span id="toc8">Difyの動作と試用</span></h3>



<p class="wp-block-paragraph">とりあえず、起動しました。<br>以前このサイトでも説明していますが、<a href="https://www.kazuban.com/blog/dify-lmstudio/#toc1">簡単なチャットボットを作成</a>し試してみます。<br>LLMモデルはオンラインの「gemini」を登録し、動作を確認できました。<br>オンラインであれば、「LM Studio」や「Ollama」など、ローカルLLMを利用するアプリは必要ないので、すぐに確認できます。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="571" src="https://www.kazuban.com/blog/wp-content/uploads/2025/04/dify-fist-try-800x571.png" alt="" class="wp-image-11056" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/04/dify-fist-try-800x571.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/dify-fist-try-500x357.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/dify-fist-try-300x214.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/dify-fist-try-768x548.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/dify-fist-try.png 1577w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<h2 class="wp-block-heading"><span id="toc9">Difyを自動起動</span></h2>



<p class="wp-block-paragraph"><span class="marker-under">Difyを動作させるには、Dockerが起動していなくてはいけません。</span><br>それには、WSL上で、ubuntuも起動している必要があります。<br>手動でやる場合、</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">・windowsターミナル起動<br>・wslコマンドで、ubuntuターミナル起動<br>・ubuntuターミナルでカレントディレクトリを、Difyのクローンディレクトリに移動<br>・「docker compose up -d」 コマンド実行</p>
</blockquote>



<p class="wp-block-paragraph">このような手順が必要ですが、問題なのは、<span class="marker-under-red">ターミナルを閉じるとdockerも終了してしまう</span>ことです<br>Difyを使うには、dockerが起動していなくてはいけません。<br>windowsアプリの「docker desktop」であれば、標準で自動起動設定だったと思いますし、起動後もシステムトレイのアイコンで起動が確認できます。右ボタンで状態確認や終了も簡単です。<br>ubuntu経由の場合には、GUIでの確認ができないので、ここが面倒なところですね～。<br>自動起動方法をいろいろ調べると、windowsバッチファイルを作成し、スタートアップフォルダに登録する事で、windows起動時に、自動起動できそうです。<br>ただ、<br>「コマンドプロンプト　⇒　ubuntuターミナル　⇒　docker」<br>のタスクが必要で、<span class="marker-under-red">ターミナルは開いた状態にしておく</span>必要があります。<br>このようなバッチファイルを作りたいですが、どんなコードにすればいいのか・・？<br>うまいコードを考え付かなかったので、difyの試しもかねて起動しているチャットボットで設定しているgeminiに考えてもらいました。</p>



<pre class="wp-block-code has-black-color has-watery-yellow-background-color has-text-color has-background has-link-color wp-elements-28b6e40086f38030cefb644c1904cdfc"><code>@echo off
title Starting Dify via WSL

echo Starting WSL and navigating to ~/dify/docker...
echo Running 'docker compose up -d'...
echo WSL window will remain open after commands.

REM WSLを起動し、bashシェル内でコマンドを実行します。
REM cd ~          : ホームディレクトリに移動 (念のため)
REM cd ./dify/docker : dify/docker ディレクトリに移動
REM docker compose up -d : docker compose をバックグラウンドで起動
REM exec bash     : 上記コマンド実行後、インタラクティブなbashシェルを開始して終了させない
wsl.exe -e bash -c "cd ~/dify/docker &amp;&amp; docker compose up -d &amp;&amp; echo '--- Dify containers started (or attempted to start) ---' &amp;&amp; exec bash"

echo WSL window launched. This batch window can be closed if desired.
REM pause REM Optionally uncomment this line to keep the batch window open until a key is pressed</code></pre>



<p class="wp-block-paragraph">すごいです。<br>ほとんど実際の起動には影響がない「REM」や「echo」文がほとんどですが、<br>「REM」文を使っての説明文や、「echo」での実行中のメッセージにも手抜きがないですね！<br>このコードをコピーしてエディターで、「start_dify.bat」というファイルで保存しました。<br>バッチファイルの単独実行では問題ありませんでした。<br>後はこのファイルのショートカットを、スタートアップフォルダへコピーするだけです。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">・上記の作成したバッチファイルを、適当は場所へ保存します<br>　私は、ユーザーフォルダ「C:\Users\「ユーザー」」へ保存しました。<br>・次に、このファイルのショートカットを作成します。<br>・このショートカットを「スタートアップフォルダ」へ保存します。<br>　スタートアップフォルダは、エクスプローラーのアドレスバーへ「shell:startup」と入力すると開くことができます。</p>
</blockquote>



<div class="wp-block-media-text is-stacked-on-mobile is-vertically-aligned-top"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="622" height="989" src="https://www.kazuban.com/blog/wp-content/uploads/2025/04/startup-folder.png" alt="" class="wp-image-11070 size-full" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/04/startup-folder.png 622w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/startup-folder-500x795.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/startup-folder-300x477.png 300w" sizes="(max-width: 622px) 100vw, 622px" /></figure><div class="wp-block-media-text__content">
<p class="wp-block-paragraph">特に必須ではないですが、ターミナルは起動状態にさせるので邪魔になる場合、作成したショートカットファイルを、マウス右ボタンで「プロパティ」を開きます。<br>「プロパティ」の「ショートカット」タブの<span class="marker-under">「実行時の大きさ」を「最小化」</span>に設定すると、起動時にタスクバーに最小化状態で起動できます。</p>
</div></div>



<p class="wp-block-paragraph">これで、再起動すると、自動起動したターミナルはタスクバーへ最小化状態ですが、環境によっては起動途中の場合があるので、すぐに使用したい場合には、一度開いてDockerの状態を確認したほうがいいと思います。<br>正常に起動できると、Webブラウザのアドレスバーに「http://localhost/install」でdifyが起動できます。<br>場合によっては、「http://localhost/signin」にリダイレクトされる場合もあります</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="732" src="https://www.kazuban.com/blog/wp-content/uploads/2025/04/localhost-signin-800x732.png" alt="" class="wp-image-11073" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/04/localhost-signin-800x732.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/localhost-signin-500x458.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/localhost-signin-300x275.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/localhost-signin-768x703.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/04/localhost-signin.png 875w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<p class="wp-block-paragraph">この画面が開くと、ローカルPCでは、Difyを利用する事ができますが、<span class="marker-under">今回はサーバーとして利用したい</span>ので、<span class="marker-under-red">LAN上の別のPCからのアクセスも必要</span>です。</p>



<h2 class="wp-block-heading"><span id="toc10">Difyをサーバー化して、他のPCからもアクセスさせる</span></h2>



<p class="wp-block-paragraph">同じLAN上であっても、「localhost」では、他のPCではアクセスできません。<br><a href="https://www.kazuban.com/blog/wsl-ubuntu-dockerengine/#toc15">前回後半で少し話題にしました</a>が、「windowsホスト」「WSL(ubuntu)」「Docker」と複雑な通信環境なので面倒です。</p>



<h3 class="wp-block-heading"><span id="toc11">DifyPCのIPアドレス調査</span></h3>



<p class="wp-block-paragraph">IPアドレスは、windowsターミナルでは「ipconfig」コマンド<br>WSLターミナルでは、「ip addr」で確認できます。<br>この情報を、Aiに添付して聞いてみました。</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-3 sbs-line sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon" style="--cocoon-custom-background-color:#fff7cc"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://www.kazuban.com/blog/wp-content/uploads/2025/04/Robot-icon.png" alt="Ai" class="speech-icon-image"/></figure><div class="speech-name">Ai</div></div><div class="speech-balloon has-background has-watery-yellow-background-color">
<p class="wp-block-paragraph">詳細な情報ありがとうございます！ipconfig と ip a の結果から状況がより明確になりました。<br>原因の特定<br>・Windows ホスト:<br>　あなたの Windows PC の Wi-Fi アダプターには 192.168.0.94 という IP アドレスが割り当てられています。<br>　これはご自宅などの LAN 内の IP アドレスです。<br>・WSL (Ubuntu):<br>　Windows Subsystem for Linux (WSL) 環境内の Ubuntu には、eth0 インターフェースに 172.31.226.6 という IP アドレスが割り当てられています。<br>　これは WSL が使用する仮想ネットワーク内の IP アドレスです。</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-3 sbs-line sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon" style="--cocoon-custom-background-color:#fff7cc"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://www.kazuban.com/blog/wp-content/uploads/2025/04/Robot-icon.png" alt="Ai" class="speech-icon-image"/></figure><div class="speech-name">Ai</div></div><div class="speech-balloon has-background has-watery-yellow-background-color">
<p class="wp-block-paragraph">WSL2 環境で Docker コンテナを動かしている場合、Windows ホストからそのコンテナ内のサービスにアクセスするには、通常以下のいずれかのアドレスを使用します。<br>１．localhost: <br>　Windows ホストのブラウザで http://localhost/chat/&#8230;と入力する。<br>　WSL2 は localhost 経由でのポートフォワーディングをサポートしています。 <br>　（これが最も一般的な方法です）<br>２．WSL の IP アドレス: http://172.31.226.6/chat/&#8230;<br>　(今回アクセスできている方法)<br><br>・http://192.168.0.94/chat/&#8230; でアクセスできないのは、WSL2 と Docker のネットワークアーキテクチャ上、自然なことです。<br>サービスが Windows ホストの物理的な IP アドレスに直接公開されているわけではないためです。<br>・もし、LAN 内の他の PC (例: 192.168.0.100) からもこの Dify 環境にアクセスしたい場合は、追加の設定が必要になる可能性があります:<br><br>１．Windows ファイアウォールの設定: Windows のファイアウォールで、外部からのポート 80 (または Dify が使用しているポート) への着信接続を許可する必要があります。<br>２．ポートフォワーディング (状況による): WSL2 のネットワーク設定によっては、Windows ホストの 192.168.0.94 のポート 80 へのアクセスを、WSL の 172.31.226.6 のポート 80 へ転送する設定が必要になる場合があります。<br>これは 「netsh interface portproxy」 コマンドなどで設定できますが、まずは localhost や WSL の IP でアクセスできることを確認するのが先決です。<br><br>要約:<br>・Windows ホストからアクセスする場合: http://localhost/chat/… または http://172.31.226.6/chat/… を使用してください。<br>・http://192.168.0.94/chat/&#8230; でアクセスできないのは仕様であり、問題ではありません。<br></p>
</div></div>



<h3 class="wp-block-heading"><span id="toc12">Windowsのアドレスからは、アクセスできない。</span></h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-5 sbs-flat sbp-r sbis-cb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://www.kazuban.com/blog/wp-content/themes/cocoon-master/images/ojisan.png" alt="じじぃ" class="speech-icon-image"/></figure><div class="speech-name">じじぃ</div></div><div class="speech-balloon">
<p class="wp-block-paragraph">http://localhost や http://172.31.226.6 からはアクセスできています。<br>今回は、LAN上の別のPCからhttp://192.168.0.94 にアクセスしたいため、自分PCで試したら、アクセスできませんでした</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-3 sbs-line sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon" style="--cocoon-custom-background-color:#fff7cc"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://www.kazuban.com/blog/wp-content/uploads/2025/04/Robot-icon.png" alt="Ai" class="speech-icon-image"/></figure><div class="speech-name">Ai</div></div><div class="speech-balloon has-background has-watery-yellow-background-color">
<p class="wp-block-paragraph">なるほど、LAN上の他のPCからアクセスできるようにしたい、ということですね。承知いたしました。</p>



<p class="wp-block-paragraph">ご自身のPC (<code>192.168.0.94</code>) から <code>http://192.168.0.94/chat/...</code> にアクセスできなかったのは、まさにその設定がまだされていないためです。Windowsホストのネットワーク(<code>192.168.0.x</code>) と WSL内部のネットワーク (<code>172.31.x.x</code>) は分離されており、外部（LANを含む）から直接WSL内のサービスにアクセスするには、「ポートフォワーディング（ポート転送）」という設定が必要になります。</p>



<p class="wp-block-paragraph"><strong>設定手順</strong></p>



<p class="wp-block-paragraph">以下の手順を<strong>管理者権限</strong>で実行してください。</p>



<ol class="wp-block-list">
<li><strong>Difyが使用しているポートを確認 (重要):</strong>
<ul class="wp-block-list">
<li>まず、DifyがWSL内でどのポート番号で待ち受けているか確認します。HTTPなので通常は <strong>80番</strong> ですが、Dockerの設定によっては異なるポート（例: 3000番など）がホスト(WSL)に公開されている場合があります。</li>



<li>Docker Composeを使っている場合は <code>docker-compose.yml</code> ファイルの <code>ports:</code> セクションを確認してください。例えば <code>ports: - "80:80"</code> や <code>ports: - "3000:80"</code> のようになっています。左側の数字がWSL側で公開されているポート番号です。</li>



<li><code>docker ps</code> コマンドを実行しても確認できます。<code>PORTS</code> 列に <code>0.0.0.0:80-&gt;80/tcp</code> や <code>0.0.0.0:3000-&gt;80/tcp</code> のように表示されます。<code>0.0.0.0:</code> の後の数字がWSL側で公開されているポート番号です。</li>



<li><strong>以降の説明では、Difyがポート <code>80</code> を使用していると仮定します。もし異なるポート（例: 3000）だった場合は、コマンド内の <code>80</code> をその番号に読み替えてください。</strong></li>
</ul>
</li>



<li><strong>Windows ファイアウォールでポートを開放:</strong>
<ul class="wp-block-list">
<li>LAN内の他のPCからのアクセスを許可するために、WindowsのファイアウォールでDifyが使用するポート（ここでは80番）を開ける必要があります。</li>



<li><strong>管理者としてPowerShellを開き</strong>、以下のコマンドを実行します。<br><code>powershell New-NetFirewallRule -DisplayName "Allow Dify Access from LAN" -Direction Inbound -LocalPort 80 -Protocol TCP -Action Allow</code><br><em>(もしコマンドプロンプトを使いたい場合は、管理者として開き <code>netsh advfirewall firewall add rule name="Allow Dify Access from LAN" dir=in action=allow protocol=TCP localport=80</code> を実行)</em></li>
</ul>
</li>



<li><strong>ポートフォワーディングの設定:</strong>
<ul class="wp-block-list">
<li>Windowsホスト (<code>192.168.0.94</code>) のポート80に来た通信を、WSL (<code>172.31.226.6</code>) のポート80に転送するように設定します。</li>



<li><strong>管理者としてPowerShell（またはコマンドプロンプト）を開き</strong>、以下のコマンドを実行します。 <code>powershell netsh interface portproxy add v4tov4 listenport=80 listenaddress=0.0.0.0 connectport=80 connectaddress=172.31.226.6</code>
<ul class="wp-block-list">
<li><code>listenport=80</code>: Windows側で外部からの接続を待ち受けるポート番号。</li>



<li><code>listenaddress=0.0.0.0</code>: Windowsの全てのIPアドレス（<code>192.168.0.94</code> を含む）で待ち受ける設定。特定のIP (<code>192.168.0.94</code>) だけを指定することも可能です。</li>



<li><code>connectport=80</code>: 転送先のWSL内でDifyが待ち受けているポート番号。</li>



<li><code>connectaddress=172.31.226.6</code>: 転送先のWSLのIPアドレス。</li>
</ul>
</li>
</ul>
</li>



<li><strong>動作確認:</strong>
<ul class="wp-block-list">
<li>設定後、まずご自身のPCのブラウザから <code>http://192.168.0.94/chat/84aj9r6azPSYjXt8</code> にアクセスできるか試してください。 (ポートが80以外の場合は <code>http://192.168.0.94:ポート番号/chat/...</code> のように指定)</li>



<li>アクセスできれば、LAN内の他のPCからも同じアドレス (<code>http://192.168.0.94/chat/...</code>) でアクセスできるはずです。</li>
</ul>
</li>
</ol>



<p class="wp-block-paragraph"><strong>注意点:</strong></p>



<ul class="wp-block-list">
<li><strong>WSLのIPアドレスの変動:</strong> WSLを再起動すると、WSLのIPアドレス (<code>172.31.226.6</code>) が変わる可能性があります。もしアクセスできなくなった場合は、<code>ip a</code> コマンドでWSLの新しいIPアドレスを確認し、手順3のポートフォワーディング設定を一度削除して再作成する必要があります。
<ul class="wp-block-list">
<li>削除コマンド: <code>netsh interface portproxy delete v4tov4 listenport=80 listenaddress=0.0.0.0</code></li>



<li>再作成コマンド: (新しい <code>connectaddress</code> を指定して再度実行)</li>
</ul>
</li>



<li><strong>管理者権限:</strong> ファイアウォールとポートフォワーディングの設定には管理者権限が必要です。</li>



<li><strong>ポート番号:</strong> Difyが使用しているポート番号を正確に確認し、コマンド内の <code>80</code> を適宜修正してください。</li>
</ul>



<p class="wp-block-paragraph">この手順で、LAN内の他のPCからアクセスできるようになるはずです。試してみてください。</p>
</div></div>



<h3 class="wp-block-heading"><span id="toc13"><em>docker ps コマンドで実行中のコンテナーを提出</em></span></h3>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-5 sbs-flat sbp-r sbis-cb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://www.kazuban.com/blog/wp-content/themes/cocoon-master/images/ojisan.png" alt="じじぃ" class="speech-icon-image"/></figure><div class="speech-name">じじぃ</div></div><div class="speech-balloon">
<p class="wp-block-paragraph">docker ps では下記になっています。<br>$ docker ps<br>・・<br>・<br>・</p>
</div></div>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-3 sbs-line sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon" style="--cocoon-custom-background-color:#fff7cc"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://www.kazuban.com/blog/wp-content/uploads/2025/04/Robot-icon.png" alt="Ai" class="speech-icon-image"/></figure><div class="speech-name">Ai</div></div><div class="speech-balloon has-background has-watery-yellow-background-color">
<p class="wp-block-paragraph"><code>docker ps</code> の出力結果、ありがとうございます。</p>



<p class="wp-block-paragraph">コンテナ <code>docker-nginx-1</code> の <code>PORTS</code> 列にご注目ください。</p>



<pre class="wp-block-code"><code>PORTS
0.0.0.0:80-&gt;80/tcp, &#91;::]:80-&gt;80/tcp, 0.0.0.0:443-&gt;443/tcp, &#91;::]:443-&gt;443/tcp</code></pre>



<p class="wp-block-paragraph">これは、以下のことを意味しています。</p>



<ul class="wp-block-list">
<li><code>0.0.0.0:80-&gt;80/tcp</code>: WSLホスト（<code>172.31.226.6</code> など）の <strong>ポート 80</strong> (HTTP) へのTCP接続を、<code>docker-nginx-1</code> コンテナ内部のポート 80 に転送する。</li>



<li><code>[::]:80-&gt;80/tcp</code>: 上記のIPv6版。</li>



<li><code>0.0.0.0:443-&gt;443/tcp</code>: WSLホストの <strong>ポート 443</strong> (HTTPS) へのTCP接続を、<code>docker-nginx-1</code> コンテナ内部のポート 443 に転送する。</li>



<li><code>[::]:443-&gt;443/tcp</code>: 上記のIPv6版。</li>
</ul>



<p class="wp-block-paragraph"><code>docker-web-1</code> コンテナ自体は内部的にポート 3000 を使っていますが、外部（WSLホスト）からのアクセスは <code>docker-nginx-1</code> コンテナがポート 80 (HTTP) と 443 (HTTPS) で受け付けています。Nginx がリバースプロキシとして動作し、リクエストを <code>docker-web-1</code> や <code>docker-api-1</code> などに振り分けている構成です。</p>



<p class="wp-block-paragraph"><strong>結論</strong></p>



<p class="wp-block-paragraph">あなたが LAN 上の他の PC からアクセスしたい <strong>HTTP</strong> のポート番号は <strong>80</strong> です。</p>



<p class="wp-block-paragraph">したがって、先ほどのポートフォワーディング設定のコマンドは、ポート番号 <code>80</code> を使って実行してください。</p>



<ol class="wp-block-list">
<li><strong>ファイアウォール開放 (ポート 80):</strong> <code>New-NetFirewallRule -DisplayName "Allow Dify Access from LAN (HTTP)" -Direction Inbound -LocalPort 80 -Protocol TCP -Action Allow</code></li>



<li><strong>ポートフォワーディング設定 (ポート 80):</strong><br><code>powershell netsh interface portproxy add v4tov4 listenport=80 listenaddress=0.0.0.0 connectport=80 connectaddress=172.31.226.6</code></li>
</ol>



<p class="wp-block-paragraph">これで、 <code>http://192.168.0.94</code> (ポート80は省略可能) でアクセスできるはずです。</p>



<p class="wp-block-paragraph">もし将来的にHTTPS (<code>https://192.168.0.94</code>) でアクセスしたい場合は、同様にポート <code>443</code> 用のファイアウォールルールとポートフォワーディング設定を追加する必要があります。</p>
</div></div>



<h3 class="wp-block-heading"><span id="toc14">ファイヤーウォールとポートフォワーディング設定</span></h3>



<p class="wp-block-paragraph"><span class="marker-under-red">ファイアウォールを開放</span>し、<span class="marker-under-red">ポートフォワーディング設定をしろ</span>、のアドバイスです。<br>教わったコードを実行してみます。</p>



<h4 class="wp-block-heading"><span id="toc15">１．ファイアウォール開放 (ポート 80):</span></h4>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-2a1baa688c4d7f0081410424df4fffa6"><code>PowerShell
PS C:\Users\hoge2&gt;　New-NetFirewallRule -DisplayName "Allow Dify Access from LAN (HTTP)" -Direction Inbound -LocalPort 80 -Protocol TCP -Action Allow</code></pre>



<p class="wp-block-paragraph">コントロールパネル→システムとセキュリティ→windows Defender ファイアウォール→詳細設定<br>受信の規則で<br>コマンドで指定したAllow Dify Access from LAN(HTTP)が設定されているのが、確認できます。<br>コマンドではなく、この画面で、GUI設定する事もできます。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="638" src="https://www.kazuban.com/blog/wp-content/uploads/2025/05/defender-800x638.png" alt="" class="wp-image-11155" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/05/defender-800x638.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/05/defender-500x399.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/05/defender-300x239.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/05/defender-768x612.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/05/defender.png 1200w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<h4 class="wp-block-heading"><span id="toc16">2．ポートフォワーディング設定 (ポート 80):</span></h4>



<p class="wp-block-paragraph">管理者権限のPowerShell の、「netsh」コマンドで設定します。</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-407ff20f71ed0d5d65d19b8abe74f839"><code>PowerShell（管理者）
PS C:\Users\hoge2&gt; netsh interface portproxy add v4tov4 listenport=80 listenaddress=0.0.0.0 connectport=80 connectaddress=172.31.226.6</code></pre>



<p class="wp-block-paragraph">「netsh interface portproxy show v4tov4」で確認できます。</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-3b28731fc08b3c287046ad304f896c2a"><code>PS C:\Users\hoge2&gt; netsh interface portproxy show v4tov4
ipv4 をリッスンする:         ipv4 に接続する:
Address         Port        Address         Port
--------------- ----------  --------------- ----------
0.0.0.0         80          172.31.226.6    80</code></pre>



<h4 class="wp-block-heading"><span id="toc17">アクセスできた～</span></h4>



<p class="wp-block-paragraph">これで無事に「http://192.168.0.94/instal」でアクセスできました。<br>LAN上の別のPCからも、アクセス確認できました。<br>おそらく、ネット検索では、ここまで的確なアドバイスを見つけるのは至難の業だと思います。<br>ちょっと前までは、言語生成AIをうまく使うには、プロンプトが重要だと言われていましたが、最近の言語生成AIはかなり言語の理解力が向上していると感じます。<br>上記のじじぃの質問でもわかりますが、ほとんど「プロンプト」など意識していません。<br>とにかくわからない事やPCからの出力を、自分の言葉で質問しているだけです。<br>それでもかなり的確な回答をくれます。<br>たまには、間違った回答もありますが、それでエラーが発生した場合、<span class="marker-under">そのエラーやログをそのまま突っ込めば</span>、新たな回答をくれます。<br>すごい時代になりました。</p>



<h2 class="wp-block-heading"><span id="toc18">DifyにLLMを設定して、カスタムチャット環境を構築</span></h2>



<p class="wp-block-paragraph">やっとDifyサーバーが起動できました。</p>



<div class="wp-block-media-text is-stacked-on-mobile"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="407" height="690" src="https://www.kazuban.com/blog/wp-content/uploads/2025/05/select-llm.png" alt="" class="wp-image-11167 size-full" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/05/select-llm.png 407w, https://www.kazuban.com/blog/wp-content/uploads/2025/05/select-llm-300x509.png 300w" sizes="(max-width: 407px) 100vw, 407px" /></figure><div class="wp-block-media-text__content">
<p class="wp-block-paragraph">次に、このDifyにLLMモデルを設定することで、チャットボットをはじめカスタムLLMアプリを開発する事ができるようになります。<br>左図の例では、<br>一番上の「Gemini」はオンラインで公開されているLLMです。<br>二番目は、「LM Studio」でダウンロードしたローカルLLMです。<br>三番目は、「Ollama」で読み込んでいるローカルLLMです。<br>このように、「Dify」ではオンライン、ローカルあまり意識せず、使用するLLMを自由にカスタマイズできます。</p>
</div></div>



<h3 class="wp-block-heading"><span id="toc19">DifyにLLMの設定方法</span></h3>



<p class="wp-block-paragraph">ネット上でも、多くの情報があると思いますが、このサイトでも以前の記事で紹介しています。</p>



<h4 class="wp-block-heading"><span id="toc20"><a href="https://www.kazuban.com/blog/dify-lmstudio/#toc3">オンラインLLMの登録</a></span></h4>



<figure class="wp-block-embed is-type-wp-embed"><div class="wp-block-embed__wrapper">

<a href="https://www.kazuban.com/blog/dify-lmstudio/#toc3" title="ローカルでDifyとLM_Studio を連携させ、ローカルでチャットボットを作る。" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="160" height="90" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dify_LMStudio-160x90.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dify_LMStudio-160x90.png 160w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dify_LMStudio-120x68.png 120w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dify_LMStudio-320x180.png 320w" sizes="(max-width: 160px) 100vw, 160px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">ローカルでDifyとLM_Studio を連携させ、ローカルでチャットボットを作る。</div><div class="blogcard-snippet internal-blogcard-snippet">LM StudioとDifyをローカルで連携させたのでレポートします。記事を書いている時に、Dify設定にLM Studioのプラグインを発見したので、そちらの設定も追加してます。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://www.kazuban.com/blog" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">www.kazuban.com</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2025.03.23</div></div></div></div></a>
</div></figure>



<h4 class="wp-block-heading"><span id="toc21"><a href="https://www.kazuban.com/blog/dify-lmstudio/#toc6">LM Studio モデルの登録</a></span></h4>



<figure class="wp-block-embed is-type-wp-embed"><div class="wp-block-embed__wrapper">

<a href="https://www.kazuban.com/blog/dify-lmstudio/#toc6" title="ローカルでDifyとLM_Studio を連携させ、ローカルでチャットボットを作る。" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="160" height="90" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dify_LMStudio-160x90.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dify_LMStudio-160x90.png 160w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dify_LMStudio-120x68.png 120w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dify_LMStudio-320x180.png 320w" sizes="(max-width: 160px) 100vw, 160px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">ローカルでDifyとLM_Studio を連携させ、ローカルでチャットボットを作る。</div><div class="blogcard-snippet internal-blogcard-snippet">LM StudioとDifyをローカルで連携させたのでレポートします。記事を書いている時に、Dify設定にLM Studioのプラグインを発見したので、そちらの設定も追加してます。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://www.kazuban.com/blog" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">www.kazuban.com</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2025.03.23</div></div></div></div></a>
</div></figure>



<h4 class="wp-block-heading"><span id="toc22"><a href="https://www.kazuban.com/blog/dify-ollama/#toc6">Ollama　モデルの登録</a></span></h4>



<figure class="wp-block-embed is-type-wp-embed"><div class="wp-block-embed__wrapper">

<a href="https://www.kazuban.com/blog/dify-ollama/#toc6" title="DifyとOllamaを連携させ、ローカルチャットボット環境を作る" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="160" height="90" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dify_Ollama-160x90.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dify_Ollama-160x90.png 160w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dify_Ollama-120x68.png 120w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dify_Ollama-320x180.png 320w" sizes="(max-width: 160px) 100vw, 160px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">DifyとOllamaを連携させ、ローカルチャットボット環境を作る</div><div class="blogcard-snippet internal-blogcard-snippet">前回はLM StudioとDifyの連携でしたが、今回は、Ollamaと連携させてみました。どちらもそれぞれ特徴があるので、使い分けてもいいと思います。私的には、スタンドアローンで使うならLM Studio。Difyとの連携であればOllama かな？と思っています。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://www.kazuban.com/blog" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">www.kazuban.com</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2025.03.30</div></div></div></div></a>
</div></figure>



<h2 class="wp-block-heading"><span id="toc23">あとがき</span></h2>



<p class="wp-block-paragraph">Windowsアプリ「Docker Desktop」を使わず、「Ubuntu」にインストールした「Docker Engine」で「Dify」をサーバー化する方法を紹介しました。<br>「Docker Desktop」はWindows環境向けのツールであり、構築の手間は比較的少ないですが、Ubuntuサーバー上で動作させる際は、仮想化環境の設定やネットワーク通信の複雑さが生じるため、トラブルシューティングがやや難しくなります。<br>今回は、AIのアシストにより、Difyサーバーを構築することができました。<br>設定プロセスだけでなく、AIを活用した実践例として、このやり取りもご参考にしていただければ幸いです。</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>DifyとOllamaを連携させ、ローカルチャットボット環境を作る</title>
		<link>https://www.kazuban.com/blog/dify-ollama/</link>
		
		<dc:creator><![CDATA[kazuban]]></dc:creator>
		<pubDate>Sat, 29 Mar 2025 23:22:16 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[IT]]></category>
		<category><![CDATA[Dify]]></category>
		<category><![CDATA[Ollama]]></category>
		<category><![CDATA[チャットボット]]></category>
		<category><![CDATA[ローカルLLM]]></category>
		<guid isPermaLink="false">https://www.kazuban.com/blog/?p=10632</guid>

					<description><![CDATA[前回は、DifyとLM Studioを連携させて、ローカル環境を作成しました。ただし、LM Studioは、完全にオープンライセンスではないようで、企業で使用する場合には、確認が必要です。Ollamaのほうが、自由に使え [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">前回は、<strong>Dify</strong>と<strong>LM Studio</strong>を連携させて、ローカル環境を作成しました。<br>ただし、LM Studioは、完全にオープンライセンスではないようで、企業で使用する場合には、確認が必要です。<br>Ollamaのほうが、自由に使えそうです。<br>ただし、いろいろなLLMを試してみたり、チャットが主な目的な場合には、LM Studioのほうが、GUIでの操作ができるので、初心者はLM Studioが取りつきやすいと思います。<br>特に、使用ＰＣスペックでの動作推測やモデルの詳細などは、分かりやすいです。<br>Difyと連携させて利用する場合では、繋がってしまえば、あまり違いはないかもしれません。<br>いろんなモデルをLM Studioでの試してみて、気に入ったモデルをOllama経由でDify連携の使い方もありかな、と思います。</p>




  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-16" checked><label class="toc-title" for="toc-checkbox-16">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">インストール</a></li><li><a href="#toc2" tabindex="0">モデルをダウンロードして起動</a></li><li><a href="#toc3" tabindex="0">Difyとの連携</a></li><li><a href="#toc4" tabindex="0">Windows 環境変数の編集</a><ol><li><a href="#toc5" tabindex="0">Ollama用、環境変数の追加</a></li><li><a href="#toc6" tabindex="0">Dify にもモデルを登録する</a></li></ol></li><li><a href="#toc7" tabindex="0">あとがき</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">インストール</span></h2>



<p class="wp-block-paragraph">OllamaをWindowsにインストールするには、<a href="https://ollama.com/download/windows">下記サイトから</a>インストール実行ファイル「OllamaSetup.exe」をダウンロード・実行でインストールできます。</p>



<div class="wp-block-media-text is-stacked-on-mobile"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="745" height="621" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/download01.png" alt="" class="wp-image-10804 size-full" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/download01.png 745w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/download01-500x417.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/download01-300x250.png 300w" sizes="(max-width: 745px) 100vw, 745px" /></figure><div class="wp-block-media-text__content">
<p class="wp-block-paragraph">インストール完了後、何事もなく終了ますが、スタートメニューには登録され、タスクバーの「隠れているインジケータ」にアイコンがあれば起動しています。<br>コマンドプロンプトなどを開いて、「ollama ーーhelp」コマンドで確認してみます。</p>



<p class="wp-block-paragraph"></p>
</div></div>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-86dcacdbec62004d37fbd6dca50367b5"><code>PS C:\Users\hoge&gt; <strong>ollama --help</strong>
Large language model runner

Usage:
  ollama &#91;flags]
  ollama &#91;command]

Available Commands:
  serve       Start ollama
  create      Create a model from a Modelfile
  show        Show information for a model
  run         Run a model
  stop        Stop a running model
  pull        Pull a model from a registry
  push        Push a model to a registry
  list        List models
  ps          List running models
  cp          Copy a model
  rm          Remove a model
  help        Help about any command

Flags:
  -h, --help      help for ollama
  -v, --version   Show version information

Use "ollama &#91;command] --help" for more information about a command.
PS C:\Users\hoge&gt;</code></pre>



<p class="wp-block-paragraph">エラーが出なければ、無事に動作しています。<br>「ollama ーーversion」でバージョンを確認できます。</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-bc0fb3908fbf723d66701c0558b774e8"><code>PS C:\Users\hoge&gt; <strong>ollama --version</strong>
ollama version is 0.6.2</code></pre>



<h2 class="wp-block-heading"><span id="toc2">モデルをダウンロードして起動</span></h2>



<p class="wp-block-paragraph">LLMを利用するにいは、公開されているモデルを下記から確認、ダウンロードできます。<br><a href="https://ollama.com/search">https://ollama.com/search</a><br>一覧から、利用したいモデル名をクリックすると、さらに「1b」「4b」など、モデルサイズで数種類でてきます。<br>一般的に小さい方が、性能は低い傾向にありますが、レスポンスはよくなります。<br>自分の環境で、レスポンスと相談して、大きいモデルがいいと思います。<br>LM Studio の場合、<a href="https://www.kazuban.com/blog/lm-studio-first-try/#toc5">自分のＰＣスペックとの相性をある程度アイコンで表示</a>してくれますが、Ollamaでは、とりあえず試してみて・・になるのかな～？<br>LM Studioで体験しておくと、自分の環境でも大丈夫なモデルサイズは察しがつきます。</p>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="600" data-id="10814" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/ollama-models-800x600.png" alt="" class="wp-image-10814" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/ollama-models-800x600.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/ollama-models-500x375.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/ollama-models-300x225.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/ollama-models-768x576.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/ollama-models.png 1024w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="601" data-id="10810" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/ollama-models01-800x601.png" alt="" class="wp-image-10810" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/ollama-models01-800x601.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/ollama-models01-500x375.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/ollama-models01-300x225.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/ollama-models01-768x577.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/ollama-models01.png 1024w" sizes="(max-width: 800px) 100vw, 800px" /></figure>
</figure>



<p class="wp-block-paragraph">ターミナルで「<strong>ollama run </strong>[<em>モデル名</em>]」でダウンロード後実行できます。<br>モデル名は、ダウンロードサイトのコピーアイコン<img loading="lazy" decoding="async" width="24" height="25" class="wp-image-10792" style="width: 24px;" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/copy_icon.png" alt="">を利用するとモデル名をクリップボードへコピーできるので便利です。</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-a170e2946e94ec5938c3f995bac076db"><code>PS C:\Users\hoge&gt; <strong>ollama run gemma3:4b</strong>
pulling manifest
pulling aeda25e63ebd... 100% ▕███████████▏ 3.3 GB
pulling e0a42594d802... 100% ▕███████████▏  358 B
pulling dd084c7d92a3... 100% ▕███████████▏ 8.4 KB
pulling 3116c5225075... 100% ▕███████████▏   77 B
pulling b6ae5839783f... 100% ▕███████████▏  489 B
verifying sha256 digest
writing manifest
success
&gt;&gt;&gt; 始めまして
はじめまして！こちらこそ、ご挨拶ありがとうございます。

何か私にできることはありますか？ 例えば、

*   何か質問に答える
*   文章を作成する
*   アイデアを出し合う
*   ただおしゃべりする

など、どんなことでも構いません。😊

&gt;&gt;&gt; Send a message (/? for help)</code></pre>



<p class="wp-block-paragraph">「&gt;&gt;&gt; <span class="cocoon-custom-text-1">Send a message (/? for help)</span>」のプロンプトがでると、会話ができます。<br><span class="marker-under-red">会話の終了は<strong>「/bye」</strong></span>です。</p>



<h2 class="wp-block-heading"><span id="toc3">Difyとの連携</span></h2>



<p class="wp-block-paragraph">前回、<a href="https://www.kazuban.com/blog/dify-lmstudio/#toc8">「LM Studio」との連携で、LM Studioプラグインの設定方法</a>と、ほとんど同じです。</p>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-large"><a href="https://www.kazuban.com/blog/wp-content/uploads/2025/03/model-provider01.png"><img loading="lazy" decoding="async" width="800" height="518" data-id="10821" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/model-provider01-800x518.png" alt="" class="wp-image-10821" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/model-provider01-800x518.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/model-provider01-500x324.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/model-provider01-300x194.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/model-provider01-768x497.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/model-provider01.png 1024w" sizes="(max-width: 800px) 100vw, 800px" /></a></figure>



<figure class="wp-block-image size-large"><a href="https://www.kazuban.com/blog/wp-content/uploads/2025/03/model-provider02.png"><img loading="lazy" decoding="async" width="800" height="518" data-id="10820" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/model-provider02-800x518.png" alt="" class="wp-image-10820" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/model-provider02-800x518.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/model-provider02-500x324.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/model-provider02-300x194.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/model-provider02-768x497.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/model-provider02.png 1024w" sizes="(max-width: 800px) 100vw, 800px" /></a></figure>
</figure>



<p class="wp-block-paragraph">「設定」の「モデルプロバイダー」から「Ollama」プラグインをインストールします。<br>インストールが完了したら、再度「設定」の「モデルプロバイダー」「Ollamaモデル」に「モデルを追加」で<a href="#toc2">上記でダウンロードした</a>モデルと「URL（ＩPアドレス）」を設定します。<br>ダウンローズ済みモデルは、ターミナルから「ollama list」コマンドで確認できます</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-4560adfa84aede7277cd41712e345324"><code>PS C:\Users\hoge&gt; <strong>ollama list</strong>
NAME           ID              SIZE      MODIFIED
llama3.2:1b    baf6a787fdff    1.3 GB    8 minutes ago
gemma3:4b      c0494fe00251    3.3 GB    26 minutes ago
PS C:\Users\hoge&gt; <strong>ollama run llama3.2:1b</strong>
&gt;&gt;&gt; /bye
PS C:\Users\hoge&gt;
</code></pre>



<p class="wp-block-paragraph">また、「Base URL」は「ollama」が動作している、PCの「IPアドレス」に「<span class="marker-under-red">:11434</span>」のポート番号を付加して設定します。<br>ただし、URLが<span class="marker-under">LAN上の他のPCのIP（localhost以外の場合）でエラーが発生</span>してしまう場合、下記の「環境変数の編集」を試してみてください。<br>正常に「保存」が終了すると、<a href="https://www.kazuban.com/blog/dify-lmstudio/#toc7">前回記事の「LM Studio」の場合と同様に</a>、Difyで利用するモデルとして選択できるようになります。</p>



<h2 class="wp-block-heading"><span id="toc4">Windows 環境変数の編集</span></h2>



<p class="wp-block-paragraph">「Ollama」の環境変数について、geminiに聞いて、下記回答をもらいました。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Ollamaの環境変数についてですね。Ollamaは、ローカルで大規模言語モデル（LLM）を実行するためのツールであり、いくつかの環境変数を使用してその動作をカスタマイズできます。主な環境変数は以下の通りです。</p>



<ul class="wp-block-list">
<li><strong>OLLAMA_HOST</strong>:
<ul class="wp-block-list">
<li>Ollamaがリッスンするホストアドレスを指定します。デフォルトは<code>127.0.0.1</code>であり、ローカルマシンからの接続のみを受け付けます。ネットワーク上の他のマシンからOllamaにアクセスできるようにするには、この変数を<code>0.0.0.0</code>に設定します。</li>
</ul>
</li>



<li><strong>OLLAMA_MODELS</strong>:
<ul class="wp-block-list">
<li>モデルの重みを保存するディレクトリのパスを指定します。デフォルトでは、Ollamaは特定のデフォルトディレクトリにモデルを保存しますが、この変数を使用して別の場所を指定できます。これにより、モデルファイルを別のドライブやディレクトリに保存することができます。</li>
</ul>
</li>



<li><strong>OLLAMA_ORIGINS</strong>:
<ul class="wp-block-list">
<li>クロスオリジンリクエストを許可するオリジンを指定します。OLLAMA APIをWebアプリケーションから利用する場合に設定します。</li>
</ul>
</li>



<li><strong>OLLAMA_DEBUG</strong>:
<ul class="wp-block-list">
<li>デバッグモードを有効にします。Ollamaのデバッグ情報を表示する場合に設定します。</li>
</ul>
</li>
</ul>



<p class="wp-block-paragraph">これらの環境変数を設定することで、Ollamaの動作を柔軟に制御できます。環境変数の設定方法は、オペレーティングシステムによって異なります。</p>



<ul class="wp-block-list">
<li><strong>Windows</strong>:
<ul class="wp-block-list">
<li>「システム環境変数の編集」から設定します。</li>
</ul>
</li>



<li><strong>macOS / Linux</strong>:
<ul class="wp-block-list">
<li>ターミナルから<code>export</code>コマンドを使用して一時的に設定するか、<code>.bashrc</code>や<code>.zshrc</code>などのファイルに記述して永続的に設定します。また、サービスとしてOllamaを実行している場合は、systemdの設定ファイルに環境変数を記述します。</li>
</ul>
</li>
</ul>



<p class="wp-block-paragraph">より詳細な情報や具体的な設定方法については、Ollamaの公式ドキュメントや関連するオンラインリソースを参照することをおすすめします。</p>
</blockquote>



<p class="wp-block-paragraph">他のサイトをみると、環境変数を設定しないでも、正常に動作しているような記事も見かけましたし、「<strong>OLLAMA_HOST</strong>」だけ設定している記事もありました。<br>筆者の場合も、「<strong>OLLAMA_HOST</strong>」だけで正常に動作ましたが、「<strong>OLLAMA_ORIGINS</strong>」も設定しました。<br>また、「<strong>OLLAMA_MODELS</strong>」を設定すると、デフォルト（Cドライブ）以外にモデルを保存できます</p>



<h3 class="wp-block-heading"><span id="toc5">Ollama用、環境変数の追加</span></h3>



<p class="wp-block-paragraph">環境変数を行う前には、「ollama」は終了しておきましょう。<br>タスクバー右の「^」ボタン「隠れているインジケーター」から、Ollamaアイコン右クリック「Quit Ollama」でも終了できます。<br>Windows検索バーに「<strong>環境変数</strong>」と入力すると「<span class="marker-under-red"><strong>システム環境変数の編集</strong></span>」が見つかるので、「環境変数」ボタンをクリックして上段の「<strong>ユーザー環境変数</strong>」の「<strong>新規</strong>」で環境変数を追加します。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="479" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/environment_-variables-800x479.png" alt="" class="wp-image-10831" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/environment_-variables-800x479.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/environment_-variables-500x299.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/environment_-variables-300x180.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/environment_-variables-768x460.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/environment_-variables-1536x920.png 1536w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/environment_-variables.png 1622w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">OLLAMA_HOST : 0.0.0.0<br>OLLAMA_ORIGINS : *<br>OLLAMA_MODELS : D:\Ollama_Models</p>
</blockquote>



<p class="wp-block-paragraph">ただし、「OLLAMA_MODELS」の設定は、注意が必要です。<br>環境変数追加前に、ダウンロードしたモデルは、自働的には移動してはくれません。<br><span class="marker-under">再度、ダウンロード</span>するか、デフォルトでは<br>「<strong>C:\Users\</strong>[ユーザー]<strong>\.ollama\models</strong>」の下に登録されているので、環境変数変更前に指定フォルダへコピーしておくと、反映されると思いますが、試してはいません。<br>環境変数変更後でも、Ollamaを起動する前に、設定したフォルダへ移動してもいいかもしれません。<br>環境変数の編集が適応されているかは、下記で確認できます。<br><span class="marker-under"><strong>コマンドプロンプト</strong>と<strong>PowerShell</strong>で指令が違うので注意してください。</span></p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-c7c40c73e4e678be78649e5675edb001"><code>★コマンドプロンプト
C:\Users\hoge&gt;echo %OLLAMA_HOST%
0.0.0.0

C:\Users\hoge&gt;echo %OLLAMA_MODELS%
D:\Ollama_Models

C:\Users\hoge&gt;echo %OLLAMA_ORIGINS%
*

★PowerShell
PS C:\Users\hoge&gt; $env:OLLAMA_HOST
0.0.0.0

PS C:\Users\hoge&gt; $env:OLLAMA_MODELS
D:\Ollama_Models

PS C:\Users\hoge&gt; $env:OLLAMA_ORIGINS
*</code></pre>



<h3 class="wp-block-heading"><span id="toc6">Dify にもモデルを登録する</span></h3>



<p class="wp-block-paragraph">モデルフォルダを変更した場合には、「<strong>ollama list</strong>」コマンドで確認できます。<br>正常に変更されていれば、<span class="marker-under-red">再度「Olama」を起動</span>して、「Dify」の「Ollama」モデルのプラグイン設定で追加できるようになります。<br><a href="https://www.kazuban.com/blog/dify-lmstudio/#toc8">追加方法は、LM Studio 編を参考にしてください。</a></p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="333" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/ollama_plugin_add-800x333.png" alt="" class="wp-image-10853" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/ollama_plugin_add-800x333.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/ollama_plugin_add-500x208.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/ollama_plugin_add-300x125.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/ollama_plugin_add-768x320.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/ollama_plugin_add.png 1009w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<p class="wp-block-paragraph">追加したモデルは、Difyで作成するアプリから、ollamaを利用できるようになります。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="486" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/ollama_model_select-800x486.png" alt="" class="wp-image-10854" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/ollama_model_select-800x486.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/ollama_model_select-500x304.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/ollama_model_select-300x182.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/ollama_model_select-768x466.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/ollama_model_select.png 1248w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<h2 class="wp-block-heading"><span id="toc7">あとがき</span></h2>



<p class="wp-block-paragraph">これで、完全ローカルで、DifyからOllamaも利用できるようになりました。<br>筆者の環境では、「Windows環境変数の編集」が必要だったので、少し戸惑いましたが、どうにか利用できるようになりました。<br>LM Studioがいいのか？Ollamaがいいのか？は、自分の環境や使い勝手で使い分けてください。<br>選択肢があるというのは、いいことだと思います。<br>さぁ、いよいよ、Difyの勉強を始められる環境は出来上がりましたが・・・・<br>ちょっと、Docker Desktop の環境なのが気になっています。<br>WSLでUbuntu24.04を起動させた環境か、現在稼働中のLinuxマシンか・・・<br>いずれにしても、linux環境で立ち上げてみたくなってきました。<br></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>ローカルでDifyとLM_Studio を連携させ、ローカルでチャットボットを作る。</title>
		<link>https://www.kazuban.com/blog/dify-lmstudio/</link>
		
		<dc:creator><![CDATA[kazuban]]></dc:creator>
		<pubDate>Sat, 22 Mar 2025 23:40:15 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[IT]]></category>
		<category><![CDATA[Dify]]></category>
		<category><![CDATA[LM-Studio]]></category>
		<category><![CDATA[チャットボット]]></category>
		<category><![CDATA[ローカルLLM]]></category>
		<guid isPermaLink="false">https://www.kazuban.com/blog/?p=10639</guid>

					<description><![CDATA[以前の記事で、LM Studioを利用して、ローカル環境でLLMを利用する方法を紹介しました。また前回、生成Aiアプリを比較的簡単に開発できる、Difyをローカルで起動させてみました。今回はこのDifyとLM Studi [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><a href="https://www.kazuban.com/blog/lm-studio-first-try/">以前の記事で、LM Studioを利用して、ローカル環境でLLMを利用する方法</a><br>を紹介しました。<br><a href="https://www.kazuban.com/blog/dify-install/">また前回、生成Aiアプリを比較的簡単に開発できる、Difyをローカルで起動</a><br>させてみました。<br>今回はこのDifyとLM Studioを連携させ、完全ローカル環境で生成Aiアプリを開発する環境設定を作ってみます。<br>筆者はDifyは超初心者なので、Difyでのアプリ開発に興味あるかたはネットをチェックしてみてください。<br>ここでは、DifyとローカルLLMと連携する方法を紹介します。</p>




  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-18" checked><label class="toc-title" for="toc-checkbox-18">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">Difyで簡単なチャットボット作る</a></li><li><a href="#toc2" tabindex="0">モデルを登録する</a><ol><li><a href="#toc3" tabindex="0">オンラインLLM gemini の登録</a></li><li><a href="#toc4" tabindex="0">ローカルLLM LM Studio の登録</a><ol><li><a href="#toc5" tabindex="0">LM Studio をサーバーモードにする</a></li><li><a href="#toc6" tabindex="0">DifyでLM Studio のモデルを利用する</a></li></ol></li><li><a href="#toc7" tabindex="0">LM Studio サーバーのモデル使用</a></li><li><a href="#toc8" tabindex="0">LM Studio のモデルプロバイダーが追加されてる・・・</a></li></ol></li><li><a href="#toc9" tabindex="0">あとがき</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">Difyで簡単なチャットボット作る</span></h2>



<p class="wp-block-paragraph">まずは、Difyで一番簡単なチャットボットを作成する流れを説明します。<br><a href="https://www.kazuban.com/blog/dify-install/">前回までで</a>、Difyをインストールして「<a href="http://localhost/install">http://localhost/install</a>」でアカウント作成を行いました。<br>ログインすると、「最初から作成」でアプリが作成できるようになります。</p>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-3 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="577" data-id="10697" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/dify_fist01-800x577.png" alt="" class="wp-image-10697" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/dify_fist01-800x577.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/dify_fist01-500x360.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/dify_fist01-300x216.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/dify_fist01-768x554.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/dify_fist01.png 860w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="609" data-id="10698" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/dify_fist02-800x609.png" alt="" class="wp-image-10698" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/dify_fist02-800x609.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/dify_fist02-500x381.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/dify_fist02-300x228.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/dify_fist02-768x585.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/dify_fist02.png 860w" sizes="(max-width: 800px) 100vw, 800px" /></figure>
</figure>



<p class="wp-block-paragraph">とりあえずチャットボットを選択し、「アプリのアイコンと名前」と「説明」は任意で入力します<br>「作成する」で、次の画面へ進みます。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="461" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/dify_fist03-800x461.png" alt="" class="wp-image-10656" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/dify_fist03-800x461.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/dify_fist03-500x288.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/dify_fist03-300x173.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/dify_fist03-768x443.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/dify_fist03-1536x885.png 1536w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/dify_fist03-120x68.png 120w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/dify_fist03.png 1780w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<p class="wp-block-paragraph">ここで、右上の設定から、使用したいモデルを選択する事で、このモデルと会話するチャットアプリが作れますが、<span class="marker-under">事前に使用するLLMモデルの登録が必要</span>です。<br>ここでは、事前にオンラインのgeminiモデルを登録しておいたので、geminiの複数モデルが選択できるようになっています。<br>違うモデルで何種類か作成し公開すれば、簡単に違うモデルと会話できるアプリが作成できます。<br>ただしこれは、<span class="marker-under-red">ローカルではなくオンライン環境</span>になります。<br>ここで、LM_Studioで動作させてさせている、ローカルLLMを登録すれば、ローカルLLMと会話できるようになります。</p>



<h2 class="wp-block-heading"><span id="toc2">モデルを登録する</span></h2>



<p class="wp-block-paragraph">Difyはとても機能が多く非常に興味的なアプリなので、筆者ももう少し取り組んでみたいと思っていますが、まずはローカル環境でいろいろ試せる環境を作ります。</p>



<h3 class="wp-block-heading"><span id="toc3">オンラインLLM gemini の登録</span></h3>



<p class="wp-block-paragraph">まずは、ローカルではないですが、Googleのgeminiを利用してみます。<br>利用するには、geminiプラグインのインストールが必要です。<br>プラグインは、<span class="inline-button-blue">右上のユーザー名</span>から出てくるプルダウンで「設定」を選択すると、<br>左サイドに「設定」の項目が表示されます。<br>その下段のモデルプロバイダーで登録します</p>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-4 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-large" style="margin-top:var(--wp--preset--spacing--50);margin-right:0;margin-bottom:var(--wp--preset--spacing--50);margin-left:0"><a href="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin01.png"><img loading="lazy" decoding="async" width="800" height="720" data-id="10662" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin01-800x720.png" alt="" class="wp-image-10662" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin01-800x720.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin01-500x450.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin01-300x270.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin01-768x692.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin01.png 1346w" sizes="(max-width: 800px) 100vw, 800px" /></a></figure>



<figure class="wp-block-image size-large" style="margin-top:var(--wp--preset--spacing--80);margin-right:0;margin-bottom:var(--wp--preset--spacing--80);margin-left:0"><img loading="lazy" decoding="async" width="800" height="469" data-id="10664" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin02-800x469.png" alt="" class="wp-image-10664" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin02-800x469.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin02-500x293.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin02-300x176.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin02-768x450.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin02.png 861w" sizes="(max-width: 800px) 100vw, 800px" /></figure>
</figure>



<p class="wp-block-paragraph">インストールしたいモデル（今回は、Gemini）を探してインストールします。<br>インストールは私の環境では結構時間がかかりました。<br>インストール中でも画面にあまり変化がないので<span class="marker-under-blue">完了したタイミングを見逃しがち</span>ですが、<br>右上のプラグインアイコンがこの状態は、<img loading="lazy" decoding="async" width="120" height="42" class="wp-image-10708" style="width: 120px;" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/plugin-install01.png" alt=""><span class="marker-under">インストール中</span>です<br>完了すると<img loading="lazy" decoding="async" width="140" height="46" class="wp-image-10709" style="width: 140px;" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/plugin-install02.png" alt=""><span class="marker-under-red">このアイコンになります</span>ので、待ちます。<br>次に、インストール後Geminiを使用するには、API-KEYのセットアップが必要です。</p>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-5 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-large" style="margin-right:var(--wp--preset--spacing--20);margin-left:var(--wp--preset--spacing--20)"><img loading="lazy" decoding="async" width="800" height="469" data-id="10664" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin02-800x469.png" alt="" class="wp-image-10664" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin02-800x469.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin02-500x293.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin02-300x176.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin02-768x450.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin02.png 861w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<figure class="wp-block-image size-large" style="margin-top:var(--wp--preset--spacing--30);margin-right:0;margin-bottom:var(--wp--preset--spacing--30);margin-left:0"><img loading="lazy" decoding="async" width="800" height="395" data-id="10680" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin03-1-800x395.png" alt="" class="wp-image-10680" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin03-1-800x395.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin03-1-500x247.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin03-1-300x148.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin03-1-768x379.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin03-1.png 1163w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<figure class="wp-block-image size-large" style="margin-top:var(--wp--preset--spacing--40);margin-bottom:var(--wp--preset--spacing--40)"><img loading="lazy" decoding="async" width="800" height="369" data-id="10681" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin04-800x369.png" alt="" class="wp-image-10681" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin04-800x369.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin04-500x230.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin04-300x138.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin04-768x354.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin04.png 970w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<figure class="wp-block-image size-large" style="margin-top:0;margin-right:var(--wp--preset--spacing--30);margin-bottom:0;margin-left:var(--wp--preset--spacing--30)"><img loading="lazy" decoding="async" width="800" height="421" data-id="10682" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin05-800x421.png" alt="" class="wp-image-10682" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin05-800x421.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin05-500x263.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin05-300x158.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin05-768x405.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin05.png 1027w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<figure class="wp-block-image size-large" style="margin-top:var(--wp--preset--spacing--20);margin-right:var(--wp--preset--spacing--20);margin-bottom:var(--wp--preset--spacing--20);margin-left:var(--wp--preset--spacing--20)"><img loading="lazy" decoding="async" width="800" height="379" data-id="10683" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin06-800x379.png" alt="" class="wp-image-10683" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin06-800x379.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin06-500x237.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin06-300x142.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin06-768x364.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin06.png 1146w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="404" data-id="10684" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin07-800x404.png" alt="" class="wp-image-10684" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin07-800x404.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin07-500x252.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin07-300x151.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin07-768x388.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin07.png 1084w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<figure class="wp-block-image size-large" style="margin-top:var(--wp--preset--spacing--60);margin-right:var(--wp--preset--spacing--30);margin-bottom:var(--wp--preset--spacing--60);margin-left:var(--wp--preset--spacing--30)"><img loading="lazy" decoding="async" width="800" height="254" data-id="10685" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin08-800x254.png" alt="" class="wp-image-10685" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin08-800x254.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin08-500x159.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin08-300x95.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin08-768x244.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin08.png 1159w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<figure class="wp-block-image size-large" style="margin-top:var(--wp--preset--spacing--40);margin-bottom:var(--wp--preset--spacing--40)"><img loading="lazy" decoding="async" width="730" height="337" data-id="10673" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin09.png" alt="" class="wp-image-10673" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin09.png 730w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin09-500x231.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin09-300x138.png 300w" sizes="(max-width: 730px) 100vw, 730px" /></figure>



<figure class="wp-block-image size-large" style="margin-top:var(--wp--preset--spacing--30);margin-bottom:var(--wp--preset--spacing--30)"><img loading="lazy" decoding="async" width="728" height="388" data-id="10686" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin10.png" alt="" class="wp-image-10686" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin10.png 728w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin10-500x266.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin10-300x160.png 300w" sizes="(max-width: 728px) 100vw, 728px" /></figure>



<figure class="wp-block-image size-large" style="margin-top:var(--wp--preset--spacing--60);margin-bottom:var(--wp--preset--spacing--60)"><img loading="lazy" decoding="async" width="728" height="333" data-id="10675" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin11.png" alt="" class="wp-image-10675" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin11.png 728w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin11-500x229.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini_plugin11-300x137.png 300w" sizes="(max-width: 728px) 100vw, 728px" /></figure>
</figure>



<p class="wp-block-paragraph">APIキーが正常に設定されると、「右上のユーザ」⇒「設定」⇒「モデルプロバイダー」で設定済みのモデルとして表示されます。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="122" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini-ApiKEY-800x122.png" alt="" class="wp-image-10704" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini-ApiKEY-800x122.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini-ApiKEY-500x76.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini-ApiKEY-300x46.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini-ApiKEY-768x117.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/gemini-ApiKEY.png 934w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<p class="wp-block-paragraph">ただし、私の環境では、<span class="marker-under">正常に設定できた</span>とメッセージがでたのに、<span class="marker-under">ここに表示されていない事</span>がありました、その場合、<span class="marker-under-red">もう一度モデルプロバイダー一覧から再度インストール</span>すると表示されました。<br>この場合、インストール時間は殆どかかりません。<br>これで、上の例のように、使用モデルとして選択できるようになります。</p>



<h3 class="wp-block-heading"><span id="toc4">ローカルLLM LM Studio の登録</span></h3>



<p class="wp-block-paragraph">Geminiはオンラインクラウド上のLLMですが、いよいよローカルLLMと連携させます。</p>



<h4 class="wp-block-heading"><span id="toc5">LM Studio をサーバーモードにする</span></h4>



<p class="wp-block-paragraph">DifyとLM Studioを連携するには、まず、LM Studioをサーバーモードで動作させます。<br>まず左サイドバーのDeveloperアイコン<img loading="lazy" decoding="async" width="35" height="34" class="wp-image-10712" style="width: 35px;" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/developer-icon.png" alt="">で、開発者モードに入り、</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="496" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server01-800x496.png" alt="" class="wp-image-10713" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server01-800x496.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server01-500x310.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server01-300x186.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server01-768x477.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server01.png 1054w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<p class="wp-block-paragraph">その横の<span class="inline-button-green">スイッチ</span>で「Static Running」状態に設定すれば、サーバーモードで動作しています。<br>次に、Difyに提供する、モデルを「Select a model load」で<span class="marker-under-red">ダウンロード済みのモデル</span>から選択します。<br>２個のモデルをロードしてみました。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="396" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server02-800x396.png" alt="" class="wp-image-10718" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server02-800x396.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server02-500x247.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server02-300x148.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server02-768x380.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server02.png 1456w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<p class="wp-block-paragraph">この状態であれば、Difyでロードしたモデルを使用できるようになります。<br>ただし、LM Studioをクローズすると、モデルも使用できなくなってしまいます。<br>右下の<span class="inline-button-black">歯車マーク</span>で設定画面に入り</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="506" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server03-800x506.png" alt="" class="wp-image-10721" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server03-800x506.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server03-500x317.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server03-300x190.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server03-768x486.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server03-1536x972.png 1536w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server03.png 1943w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<p class="wp-block-paragraph">「Enable Local LLM Service」にチェックすれば、クローズしてもサーバー状態を維持します。</p>



<h4 class="wp-block-heading"><span id="toc6">DifyでLM Studio のモデルを利用する</span></h4>



<p class="has-watery-red-background-color has-background wp-block-paragraph"><em>この記事を書いている時に自分でも再作業をしていたら、<a href="#toc8">「LM Studio」用のプラグインが公開されている</a>のに気が付きました。<br>これから説明する「OpneAI-API-compatible」よりも、わかりやすそうです。<br>たぶん公開は最近だと思うので、不具合がないとも言えませんが、もし、こだわりがなければ、「LM Studio」プラグインの方が簡単だと思います</em></p>



<p class="wp-block-paragraph">ここでは、書き始めていた「OpneAI-API-compatible」の説明を行います。<br>geminiの時と同様に、「モデルプロバイダー」の「設定」で対応しているプラグインをインストールします。<br>LM Studioが利用するには<span class="marker-under-red">「OpneAI-API-compatible」</span>をインストールします。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="636" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server05-800x636.png" alt="" class="wp-image-10725" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server05-800x636.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server05-500x398.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server05-300x239.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server05-768x611.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server05.png 1184w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<p class="wp-block-paragraph">インストールが完了したら、「モデルを追加」で、モデル名と<br>LM Studio サーバーの「URL」＋<span class="marker-under-red">「/V1」</span>を設定します。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="1289" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server06-800x1289.png" alt="" class="wp-image-10727" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server06-800x1289.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server06-500x805.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server06-300x483.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server06-768x1237.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server06.png 933w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<p class="wp-block-paragraph">モデル名とLM Studio のURL は、「LM Studio」の画面から、<img loading="lazy" decoding="async" width="30" height="31" class="wp-image-10792" style="width: 30px;" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/copy_icon.png" alt="">「コピー」アイコンで、クリップボードへコピーすれば、ペーストできます。<br>ただし、「API endpoint URL」は<span class="marker-under-red">「URL」の後ろに「/V1」が必要</span>です。<br>「/V1」がなくても、正常に保存できる場合がありますが、実際に<span class="marker-under">チャットする時にエラーになりますので忘れないでください。</span><br>「LM Studio」に何種類がモデルがロードされている場合、ここでも複数設定しておくと、Dify側で複数のモデルを使分ける事ができます</p>



<h3 class="wp-block-heading"><span id="toc7">LM Studio サーバーのモデル使用</span></h3>



<p class="wp-block-paragraph">ここまで完了すると、Dify側でのモデル選択で利用できるようになっています。<br><a href="#toc1">上記の「gemini」モデル一覧の下</a>に、追加されているので、ここで選択する事でつかえるようになります。</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="719" height="920" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server09.png" alt="" class="wp-image-10732" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server09.png 719w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server09-500x640.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM_Studio_Server09-300x384.png 300w" sizes="(max-width: 719px) 100vw, 719px" /></figure>



<h3 class="wp-block-heading"><span id="toc8">LM Studio のモデルプロバイダーが追加されてる・・・</span></h3>



<p class="wp-block-paragraph">この記事を書いていて、Difyを触っていて気が付いたのですが、「モデルプロバイダー」一覧に「LM Studio」が入っていました。<br></p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="466" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM-Studio-Model-Providers-800x466.png" alt="" class="wp-image-10734" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM-Studio-Model-Providers-800x466.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM-Studio-Model-Providers-500x292.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM-Studio-Model-Providers-300x175.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM-Studio-Model-Providers-768x448.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM-Studio-Model-Providers.png 981w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<p class="wp-block-paragraph">筆者が見落としていただけなのか？ちょっと前にはなかったと思います。<br>そういう理由で、「OpneAI-API-compatible」を利用したのですが、「LM Studio」のほうが、名前からして分かりやすいですね。<br>試しに、インストールしてみたところ、問題なく使用できました。<br>ただ、「OpneAI-API-compatible」では、「API endpoint URL」で、「LM Studioサーバー」の「URL」とその後ろに「/V1」が必要でしたが、こちらは<span class="marker-under-red">「Base URL」の設定項目で「URL」のみ</span>でOKです。<br>この設定も、わかりやすいです。</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="787" height="1002" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM-Studio-Model-Providers-setting.png" alt="" class="wp-image-10735" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM-Studio-Model-Providers-setting.png 787w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM-Studio-Model-Providers-setting-500x637.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM-Studio-Model-Providers-setting-300x382.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/LM-Studio-Model-Providers-setting-768x978.png 768w" sizes="(max-width: 787px) 100vw, 787px" /></figure>



<h2 class="wp-block-heading"><span id="toc9">あとがき</span></h2>



<p class="wp-block-paragraph">ついに、ローカル上で、ローカル上のLLMモデルを利用した、チャットアプリ開発環境が完成しました。<br>企業で使うには、ライセンスの確認も必要ですし、動作させるPCのスペックは大きくなると思いますが、個人や少人数で使う場合、簡単に試しながら、気軽にDifyの学習ができるようになります。</p>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>話題のDifyをインストールしてみた。失敗談あり。</title>
		<link>https://www.kazuban.com/blog/dify-install/</link>
		
		<dc:creator><![CDATA[kazuban]]></dc:creator>
		<pubDate>Sat, 15 Mar 2025 08:14:52 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[IT]]></category>
		<category><![CDATA[Dify]]></category>
		<category><![CDATA[チャットボット]]></category>
		<category><![CDATA[ローカル]]></category>
		<guid isPermaLink="false">https://www.kazuban.com/blog/?p=10515</guid>

					<description><![CDATA[LM Studio は、簡単にローカルで複数のLLMを試す事ができる便利なアプリです以前、このサイトでも記事にしました。 Difyは、チャットボットなど、AIアプリを比較的簡単に作成する事ができるアプリですが、LM St [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">LM Studio は、簡単にローカルで複数のLLMを試す事ができる便利なアプリです<br>以前、このサイトでも記事にしました。</p>



<figure class="wp-block-embed is-type-wp-embed"><div class="wp-block-embed__wrapper">

<a href="https://www.kazuban.com/blog/lm-studio-first-try/" title="LM Studio、ChatGPTのような大規模言語モデル（LLM）をローカルで簡単に動かせる時代が来た" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="180" height="180" src="https://www.kazuban.com/blog/wp-content/uploads/2025/01/CreatAmuse4-1.png" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/01/CreatAmuse4-1.png 2048w, https://www.kazuban.com/blog/wp-content/uploads/2025/01/CreatAmuse4-1-500x500.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/01/CreatAmuse4-1-800x800.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/01/CreatAmuse4-1-300x300.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/01/CreatAmuse4-1-768x768.png 768w" sizes="(max-width: 180px) 100vw, 180px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">LM Studio、ChatGPTのような大規模言語モデル（LLM）をローカルで簡単に動かせる時代が来た</div><div class="blogcard-snippet internal-blogcard-snippet">LM Studio を体験してみました。簡単に、ローカルPCでAiとチャットできます。機密性の情報を扱う場合には、ローカルなので安全性は高まります文章を要約したり、レポート作成してもらったり、正確な回答が必要でない場合には、使えそうです。プログラムなど正確性が必要な場合には、オンラインのほうがよさそうです。</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://www.kazuban.com/blog" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">www.kazuban.com</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2025.01.01</div></div></div></div></a>
</div></figure>



<p class="wp-block-paragraph"><br>Difyは、チャットボットなど、AIアプリを比較的簡単に作成する事ができるアプリですが、LM Studioと連携する事で、ローカルでのチャットボットが作れそうです。<br>今回は、まずDifyを起動させてみました。<br>Difyの詳しい使用方法は、ネット上に沢山情報があるので、検索してみてください。<br>筆者もこれから触ってみて、記事にできそうであれば、レポートしたいと思います<br>Difyの立ち上げはそれほど難しくはないですが、ちょっと余計な事して、思うように動作せず、かなり悩んでしまったので、覚書かねて、レポートします。</p>




  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-20" checked><label class="toc-title" for="toc-checkbox-20">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">Difyをローカルで立ち上げる</a><ol><li><a href="#toc2" tabindex="0">WSL2インストール</a><ol><li><a href="#toc3" tabindex="0">Linux 用 Windows サブシステム 機能の有効化</a></li><li><a href="#toc4" tabindex="0">WSL更新</a></li></ol></li><li><a href="#toc5" tabindex="0">Git のインストール</a></li><li><a href="#toc6" tabindex="0">Docker Desktopインストール</a><ol><li><a href="#toc7" tabindex="0">インストール</a></li><li><a href="#toc8" tabindex="0">セットアップ</a></li></ol></li><li><a href="#toc9" tabindex="0">Difyのインストール</a><ol><li><a href="#toc10" tabindex="0">GitアプリでGithubで公開されている、difyのコードをクローン化する </a></li></ol></li></ol></li><li><a href="#toc11" tabindex="0">Difyが動き出した</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">Difyをローカルで立ち上げる</span></h2>



<p class="wp-block-paragraph">Difyは、クラウド上にも、Webアプリサービスが提供されており、サブスクで利用することもできます<a href="https://cloud.dify.ai/signin">https://cloud.dify.ai/signin</a><br>ただ、オープンソースも公開されており、個人PCでクローン化すれば、無料で制限なく使用できますが、通常のwindowsインストールとは、ちょっと違う作業が必要です。</p>



<ul class="wp-block-list">
<li>「WSL2」環境の構築</li>



<li>「Git」のインストール</li>



<li>「Docker　Desktop」のインストール</li>



<li>「Docker」で「Dify」をクローン化して利用可能にする</li>
</ul>



<p class="wp-block-paragraph">もともとは、Linux環境で開発されたソフトウェアなので、通常のWindowsアプリをインストールするよりも、コマンド作業も出てくるので、戸惑う事もありますが、一ステップずつやっていけば、意外と簡単です。</p>



<h3 class="wp-block-heading"><span id="toc2">WSL2インストール</span></h3>



<h4 class="wp-block-heading"><span id="toc3">Linux 用 Windows サブシステム 機能の有効化</span></h4>



<p class="wp-block-paragraph">「Docker」は「<strong>W</strong><em>indows</em> <strong>S</strong><em>ubsystem for</em> <strong>L</strong><em>inux</em>」上で動作するので、WSLの環境が必要です。<br>最近のPCであれな、デフォルトで有効になっているのかもしれませんが、古い場合事前の設定が必要です。<br>WSLの環境ができていなくても、機能が有効になっていれば「Docker Desktop」のインストーラがやってくれますが、警告メッセージや更新作業などの要求がでる場合があるので、事前にWSL環境を作っておいたほうがいいと思います。</p>



<p class="wp-block-paragraph">WSLの環境ですが、古いマシンの場合、場合よっては、BIOSでの仮想マシン有効設定が必要な場合もあるようです。<br>古いマシンを利用する場合には、事前に調査しておいたほうがいいと思います。<br>BIOS的に、仮想マシンが有効であれば、</p>



<p class="has-watery-red-background-color has-background wp-block-paragraph">コントロールパネル　⇒　プログラム　⇒<br>　　　　⇒　「プログラム機能：windowsの機能の有効化または無効化」</p>



<p class="wp-block-paragraph">で、「Linux用Windiwsサブシステム」と「仮想マシンプラットフォーム」にチェックをいれます、</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="688" height="738" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/wsl-install01.png" alt="" class="wp-image-10532" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/wsl-install01.png 688w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/wsl-install01-500x536.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/wsl-install01-300x322.png 300w" sizes="(max-width: 688px) 100vw, 688px" /></figure>



<p class="wp-block-paragraph">「OK」ボタンを押すと、自動的に必要なファイルを検索し、構築してくれます。<br>作業が終了したら、WIndowsを再起動します。</p>



<h4 class="wp-block-heading"><span id="toc4">WSL更新</span></h4>



<p class="wp-block-paragraph">再起動後は、「コマンドプロンプト」でアップデートしておきます。</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-1474aabfc6a6a54d94f92d3da70f8e9c"><code>C:\Users\hogehoge&gt;wsl --update
更新プログラムを確認しています。
Linux 用 Windows サブシステムをバージョンに更新しています: 2.4.12。</code></pre>



<h3 class="wp-block-heading"><span id="toc5">Git のインストール</span></h3>



<p class="wp-block-paragraph">「Git」は、Windowsのインストーラが用意されているので、比較的簡単にインストールできます。<br><a href="https://git-scm.com/downloads/win">こちらにアクセス</a>し、「Click here to download 」でダウンロードして実行します。<br>いろいろ選択するダイアログが出てきますが、私はダウンロード先を「Dドライブ」に変更しただけで、すべてデフォルトでインストールしました。</p>



<h3 class="wp-block-heading"><span id="toc6">Docker Desktopインストール</span></h3>



<p class="wp-block-paragraph">「Docker」は、複数の開発環境を、パッケージにしてアプリを実行できるアプリです。<br>環境ごとに、ハードウェアを用意する必要がないので、特に開発側ではよく使われているようです。<br>Difyを動かすには、「Dify」環境を「Docker」内でパッケージ化して、動作させます。<br>「Docker Desktop」は、Windowsインストーラも用意されているので、比較的簡単にインストールできます。<br>ただし、完全無料ではありません。<br>下記を超える規模の企業で利用する場合、利用回数制限やサブスク型有料になります。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">個人・従業員250人未満かつ年間収益1,000万ドル以下の企業</p>
</blockquote>



<p class="wp-block-paragraph">実際の動作環境は、裏で「Docker Engine」が働いているようで、こちらだけであれば、オープンソースで公開されています。<br>ただし、こちらは、Linuxでのコマンド操作が必要になりそうです。<br>ちょっと興味もありますが、まずは「Docker Desktop」で進めます</p>



<h4 class="wp-block-heading"><span id="toc7">インストール</span></h4>



<p class="wp-block-paragraph"><a href="https://www.docker.com/get-started/">こちらに、アクセスし</a>、「Download Docker Desktop」から「Download for Windows-AMD64」をダウンロードし実行ます。<br>Windowsの警告などのメッセージがでる事もありすが、許可すると確認の画面が出てきます<br>「OK」でインストールが始まります。</p>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-6 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-large"><a href="https://www.kazuban.com/blog/wp-content/uploads/2025/02/01Configration.png"><img loading="lazy" decoding="async" width="800" height="554" data-id="10442" src="https://www.kazuban.com/blog/wp-content/uploads/2025/02/01Configration-800x554.png" alt="" class="wp-image-10442" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/02/01Configration-800x554.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/02/01Configration-500x346.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/02/01Configration-300x208.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/02/01Configration-768x532.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/02/01Configration.png 884w" sizes="(max-width: 800px) 100vw, 800px" /></a></figure>



<figure class="wp-block-image size-large"><a href="https://www.kazuban.com/blog/wp-content/uploads/2025/02/02インストールスター路.png"><img loading="lazy" decoding="async" width="800" height="554" data-id="10443" src="https://www.kazuban.com/blog/wp-content/uploads/2025/02/02インストールスター路-800x554.png" alt="" class="wp-image-10443" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/02/02インストールスター路-800x554.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/02/02インストールスター路-500x346.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/02/02インストールスター路-300x208.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/02/02インストールスター路-768x532.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/02/02インストールスター路.png 884w" sizes="(max-width: 800px) 100vw, 800px" /></a></figure>



<figure class="wp-block-image size-large"><a href="https://www.kazuban.com/blog/wp-content/uploads/2025/02/03インストール終了.png"><img loading="lazy" decoding="async" width="800" height="554" data-id="10444" src="https://www.kazuban.com/blog/wp-content/uploads/2025/02/03インストール終了-800x554.png" alt="" class="wp-image-10444" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/02/03インストール終了-800x554.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/02/03インストール終了-500x346.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/02/03インストール終了-300x208.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/02/03インストール終了-768x532.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/02/03インストール終了.png 884w" sizes="(max-width: 800px) 100vw, 800px" /></a></figure>
</figure>



<p class="wp-block-paragraph">終了すると、再起動要求がない場合には不要かもしれませんが、念のため再起動しておきましょう。<br>Windowsが再起動すると、上記の「Configuration」⇒「Add shortcut desktop」にチェックを入れておいた場合、デスクトップに「Docker」のショートカットが作られていると思います。<br>もし作られていない場合、PCの環境が管理者権限を必要としているかもしれません。<br>通常は、ショートカットのアイコンで起動できますが、作られていない場合、タスクメニューからでも起動できます。<br>ただし、ショートカットが作られなかった場合、管理者権限で実行しないと、正常に起動しない場合もあります。<br>管理者権限での起動の場合、下記の説明と違ってくるかもしれませんので、ご了承ください。</p>



<h4 class="wp-block-heading"><span id="toc8">セットアップ</span></h4>



<p class="wp-block-paragraph">最初の起動では、タコやクジラのイラストの画面が立ち上げります。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="501" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dockerboot01-800x501.png" alt="" class="wp-image-10552" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dockerboot01-800x501.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dockerboot01-500x313.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dockerboot01-300x188.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dockerboot01-768x481.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dockerboot01.png 1196w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<p class="wp-block-paragraph">これは、<a href="#toc7">上記でも少し説明した、</a>ライセンスに関しての注意事項です。<br>個人使用や指定規模未満の企業であれば「Accept」で次へ進みます。</p>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-7 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-large is-style-bottom-margin-6em has-bottom-margin"><a href="https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dockerboot02.png"><img loading="lazy" decoding="async" width="844" height="684" data-id="10553" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dockerboot02.png" alt="" class="wp-image-10553"/></a></figure>



<figure class="wp-block-image size-large is-style-bottom-margin-1em has-bottom-margin"><a href="https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dockerboot03.png"><img loading="lazy" decoding="async" width="779" height="829" data-id="10554" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dockerboot03.png" alt="" class="wp-image-10554"/></a></figure>



<figure class="wp-block-image size-large is-style-bottom-margin-7em has-bottom-margin" style="margin-top:0;margin-right:0;margin-bottom:0;margin-left:0"><a href="https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dockerboot04.png"><img loading="lazy" decoding="async" width="800" height="412" data-id="10555" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dockerboot04-800x412.png" alt="" class="wp-image-10555" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dockerboot04-800x412.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dockerboot04-500x258.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dockerboot04-300x155.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dockerboot04-768x396.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dockerboot04-1536x791.png 1536w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/Dockerboot04.png 1902w" sizes="(max-width: 800px) 100vw, 800px" /></a></figure>
</figure>



<p class="wp-block-paragraph">「Welcom_to_Docker」と「Welcom Survey」は「Skip」でも大丈夫です。<br>無事に次に進むと、「Containers」の説明などへのリンクが表示されます。<br>これで、「Docker Desktop」のインストールは完了しています。<br>次にいよいよ、「Dify」をクローン化して使えるようにしていきます。<br>クローン化は、ターミナルでコマンドを入力して実行しますが、「コマンドプロンプト」や「PowerShell」を開いてもいいし、最後の画面右下の「&gt;_Terminal」も利用できます。</p>



<h3 class="wp-block-heading"><span id="toc9">Difyのインストール</span></h3>



<p class="wp-block-paragraph">「Docker」を使って「Dify」を起動させるには、次の操作を行います</p>



<ul class="wp-block-list">
<li>GitHub に公開されている dify プロジェクトのソースコードをダウンロードし、複製する。</li>



<li>Docker Composeというツールを使って複製されたアプリの構築と起動する。</li>
</ul>



<h4 class="wp-block-heading"><span id="toc10">GitアプリでGithubで公開されている、difyのコードをクローン化する </span></h4>



<p class="wp-block-paragraph">「PowerShell」などのターミナルを開き、次のコマンドを実行します。</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-995fcdb6ae5d4bcb80000aac1e1e8bff"><code>git clone https://github.com/langgenius/dify.git</code></pre>



<p class="wp-block-paragraph">このコマンドを実行すると、カレントディレクトリに、「dify」、さらにその下に「docker」ディレクトリが作成され、「docker」内に、difyがクローン化されます。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph"><span class="marker-red">★ここで、失敗談</span><br><br>カレントディレクトリと言う考えが良くなかったようで、カレントに入るのであれば、カレントを変更すれば、Dドライブなどにもインストールできるな！<br>と、勝手に思ってしまいました。<br>通常のアプリのインストールでも、なるべくCドライブへは入れないようにしています。<br>試しに、クローン化前に、ターミナルから「ch」コマンドでカレントディレクトリを変更し、やってみたところ正常にクローン化され、その後の「Docker Compose」も「Dify」も正常に動作しているように見えました。<br>しかし、Difyを触っていて、LLMの「APIキー」の認証がうまくいきませんでした。<br>「Dify」の動作自体は正常だったので、「APIキー」の認証方法が悪いのか？と結構悩みましたが、デフォルトの設定がWindowsでログインしているユーザーのホームディレクトリを想定しるとすれば、「APIキー」がうまく書き込めない可能性も考えられます。<br>設定用のYAMLファイルや、環境変数を編集する事で、正常にできそうではありますが、慣れないうちは、ログインユーザーフォルダでの作業がよさそうです。</p>
</blockquote>



<p class="wp-block-paragraph">それでは、ターミナルを開いた状態で、クローン化していきます。</p>



<pre class="wp-block-code has-cocoon-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-2fb373169b3abd0b99c967511f59e862"><code>PS C:\Users\hoge&gt; git clone https://github.com/langgenius/dify.git
Cloning into 'dify'...
remote: Enumerating objects: 146709, done.
remote: Counting objects: 100% (800/800), done.
remote: Compressing objects: 100% (440/440), done.
Receiving objects:  5% (7336/146709), 3.07 MiB | 6.10 MiB/s, done.
Receiving objects:  6% (8803/146709), 3.07 MiB | 6.10 MiB/s, done.
            ・ 
            ・ </code></pre>



<p class="wp-block-paragraph">これで、「C:\Users\hoge」直下に「dify」、さらにその下に「docker」ディレクトリが作成され、その中に必要なファイル群が作成されてます。<br>作成されたファイル群には、環境ファイルのサンプルも入っているので、そのファイルをコピーし、必要あれば、編集して、アプリのパッケージ（コンテナ）を生成します。<br>まずディレクトリを「dify\docker」に移動し、その中に作成されている、サンプル環境変数を正式な環境変数としてコピーし、「docker compose」コマンドで、コンテナを起動させます。</p>



<pre class="wp-block-code"><code>環境ファイルサンプル「.env.example」を、「.env」の名前でコピーし
「docker compose」コマンドで、コンテナを操作します

PS C:\Users\hoge&gt;cd dify\docker
PS C:\Users\hoge\dify\docker&gt; copy .env.example .env
PS C:\Users\hoge\dify\docker&gt; docker compose up -d</code></pre>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="685" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/DockerCompose02-800x685.png" alt="" class="wp-image-10577" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/DockerCompose02-800x685.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/DockerCompose02-500x428.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/DockerCompose02-300x257.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/DockerCompose02-768x657.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/DockerCompose02.png 1074w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<p class="wp-block-paragraph">ちなみに、AIに「docker compose up」は何者なのか？聞いてみました。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph"><code>docker compose up -d</code> コマンドは、Docker Compose ファイルに従って、コンテナをデバッグモードで起動・実行するコマンドです。<br><strong>解説:</strong><br><code>docker-compose</code>: Docker Compose を使うためのツール。複数のコンテナとそれらの依存関係を管理するためのファイル（docker-compose.yml）を読み込み、その定義に基づいてコンテナを操作します。<br><code>up</code>: Docker Compose ファイルに従ってコンテナを起動するコマンドです。<br><code>-d</code>: デバッグモードで実行することを意味します。このオプションを使えば、コンテナがバックグラウンドで動作し、ターミナルからは出力されなくなります。<br><strong><code>docker compose up -d</code> を実行すると:</strong><br><code>docker-compose.yml</code> ファイルを読み込みます。<br>定義されている各サービス (アプリケーション) のためのコンテナを起動します。<br>サービス間の依存関係を自動的に解決し、必要な順序でコンテナを立ち上げます。<br>バックグラウンドでコンテナが動作を開始します。<br><strong>使用例:</strong><br><code>docker-compose.yml</code> ファイル内に複数のアプリケーションが定義されており、それらが互いに連携して動作する場合に便利です。例えば、ウェブサーバーとデータベースの連携などを設定する際に役立ちます。</p>
</blockquote>



<p class="wp-block-paragraph">らしいです。<br>さて、正常に完了すると、Webブラウザで下記アドレスにアクセスすると、Difyが起動します。</p>



<pre class="wp-block-code"><code>http:&#47;&#47;localhost/install</code></pre>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="800" height="657" src="https://www.kazuban.com/blog/wp-content/uploads/2025/03/localhost_install01-800x657.png" alt="" class="wp-image-10580" style="width:840px;height:auto" srcset="https://www.kazuban.com/blog/wp-content/uploads/2025/03/localhost_install01-800x657.png 800w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/localhost_install01-500x410.png 500w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/localhost_install01-300x246.png 300w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/localhost_install01-768x630.png 768w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/localhost_install01-1536x1261.png 1536w, https://www.kazuban.com/blog/wp-content/uploads/2025/03/localhost_install01.png 1585w" sizes="(max-width: 800px) 100vw, 800px" /></figure>



<h2 class="wp-block-heading"><span id="toc11">Difyが動き出した</span></h2>



<p class="wp-block-paragraph">やっと動き出しました。<br>いらん事しなけりゃ、簡単でしたが、結構悩んでしまいました。<br>Difyは、まだ触り始めですが、チャットだけでなく、AIを利用したいろいろなアプリを自分で作成きそうです。<br>次は、DifyとLM Studioを連携させて、ローカルLLMでのチャットボットを作ろうと思います。<br>ローカルであれば、セキュリティ的なリスクもかなり少なりますし、オンラインLLMを使用する場合の制限や課金も抑える事ができると思います。</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
