生成AIを利用してQNAPのContainerStation Dockerにメンション時のみ反応するGEMINI AI Discord Botを設置する

QNAP ContainerStationのUbuntu 22.04でDiscord Botを設置できた

AWS LightsailのUbuntu 22.04で設置できたのであればQNAP ContainerStationのUbuntu 22.04でも設置できるのでは、ということで試してみたらうまくいったので書いておきます。

前回記事と重複しますが、最初から最後まで手順を記載します。

Discord Botの作成・Discord Bot Tokenの発行

  1. Discordに登録してチャンネルを作成します。
  2. Discord Developer Portal でアプリケーションを作成します。
  3. Botを作成し、Bot Tokenを取得します。
  4. Botに必要な権限 (メッセージの読み取り、送信など) を付与します。
  5. Botをサーバーに招待します。

Discordのチャンネル作成はリンク先を参照してください。

ボイスチャンネルを作成すると、音声通話(映像も可能)とチャットが使用できるようになります。

network.mobile.rakuten.co.jp

Discord botを作成します。

Botの作り方はリンク先をご参考に。

qiita.com

Botを作成した後、まず最初にInstallationのタブでInstall LinkをNoneに設定しておきます。こうしないと非公開Botに設定できないので。

権限を設定します。scopesの基本はbot、その他はご自由に。Bot permissionsはTEXTとVOICEを適宜。

一番右下のボタンを押してURLをコピーして、ブラウザのアドレス欄にペーストするとチャットにbotが呼び出せます。

次に左側のタブのBotのページで設定します。

PublicBotは必ずoffに設定しておきます。Publicのままにしておいて、どこかのチャットにBotが呼び出されて大量のやりとりが発生するとGEMINI使用の費用請求をされたり、こちらのチャットの内容が漏洩する可能性があるので、Publicのままにはしないでおきましょう。

中段の「Privileged Gateway Intents」はPresence Intent・Server Members Intent・Message Content Intentをオンにしておきます。

下段のText Permissionsは画像でチェックされているあたりにチェックを入れておきます。

設定が終わったら、「Token」の下にあるReset Tokenボタンを押します、Discordのパスワードが要求されるので、パスワードを入力した後、Tokenの値をメモ帳にでも保存しておきます。

保存しておかないと、閲覧できなくなって新しいTokenを発行するしかなくなるので注意してください。

GEMINI APIの発行

aistudio.google.com

  1. Gemini API (Google AI Studio API) を有効にします。
  2. APIキーを取得します。

リンク先にアクセスします。

なお、GoogleWorkspaceの契約をしていないとAPI発行ができないかもしれません。

上段のみチェックして同意する。

「キー APIキーの作成」ボタンを押す。

GEMINIのAPIキーが生成されるので、コピーボタンを押してメモ帳などに保存しておきます。

QNAPのContainerStationをインストールして仮想環境を作成

QNAPでUbuntu(Linux)の仮想環境を作成する必要があるので、ContainerStationをインストールして、Ubuntu 22.04の仮想環境を作成します。

App Centerをクリック。

ユーティリティのContainerStationをインストール。

ホーム画面にContainerStationが追加されるのでクリックして起動。

アプリテンプレートのUbuntu 22.04 Dockerコンテナをデプロイ。
LXDだと、ログイン時にIDとパスワードを要求されるのですが、root/admin系の一般的なデフォルトパスワード、QNAPで使用しているIDとパスワードを試してみましたが全部ダメでログインが不可能でした。ネットで調べた情報も古いものしかなく、そこに書かれていたIDとパスワードで試してみてもログイン不可。QNAPのサイトでも言及がないので、あきらめました。

デプロイできたら、コンテナをクリックして、DOCKER横の「名前」の下をクリック(最初のデプロイで名前を変更していないなら、ubuntu-1になっています)。

ターミナルをアタッチをクリック。

ターミナルが表示されるので、コマンド等を入力していきます。

QNAP ContainerStationでGEMINIを利用したDiscord Botを動作させる(成功)

コンソールに、以下のコマンド等を入力していきます。

コピーして、コンソール上でマウスの右クリック→貼り付けとやるとコマンド等がコピーできるので、必要に応じてリターンキーを押して実行してください。

AWSのときと異なっているのは、AWSではsudo~としていたんですがQNAPではsudo不要になっています。

export DEBIAN_FRONTEND=noninteractive && \

apt update -y && \
apt upgrade -y && \
apt install -y python3-venv python3-pip tzdata && \
echo 'export PATH=$PATH:/home/ubuntu/.local/bin' >> ~/.bashrc && \
source ~/.bashrc && \
apt update -y && \
apt install -y python3 python3-pip && \
pip install nest_asyncio && \
pip install discord.py && \
pip install -q -U google-generativeai && \
ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
dpkg-reconfigure --frontend noninteractive tzdata

引用部分は各引用部分ごとのまとまりなので、折り返し部分で切ったりせずにまとめてコピーしてペーストしてください。

echo "export GOOGLE_API_KEY='実際のGOOGLE_API_KEYに書き換えてください'" > set_env.sh

echo "export DISCORD_BOT_TOKEN='実際のDISCORD_BOT_TOKENに書き換えてください'" >> set_env.sh

ここが重要で、 実際のGOOGLE_API_KEYに書き換えてください のところをメモしたAPIキーに書き換え、 実際のDISCORD_BOT_TOKENに書き換えてください のところをメモしたDiscord Tokeに書き換えをしてから、コピーしてペーストして実行してください。なお、前の ' と後の '" はそのままにしておく必要があります。

ここに実際のAPIキー/Tokenを入れないと絶対にうまく動きません。

chmod +x set_env.sh && source set_env.sh

ここまでがプログラム設置前段階。

Discord Bot用プログラム

cat > your_script.py << 'EOF'
import os
import nest_asyncio
import discord
import google.generativeai as genai
import asyncio

# Google Generative AI の設定
genai.configure(api_key=os.environ["GOOGLE_API_KEY"])
model = genai.GenerativeModel('gemini-2.0-pro-exp')

# Discord クライアントのセットアップ
intents = discord.Intents.default()
intents.message_content = True
discord_client = discord.Client(intents=intents)

def split_text(text, chunk_size=1500):
    """テキストをチャンクに分割します。"""
    return [text[i:i+chunk_size] for i in range(0, len(text), chunk_size)]

# ユーザーごとのチャット履歴を保存する辞書
chat_histories = {}

@discord_client.event
async def on_ready():
    print(f'Logged in as {discord_client.user}')
    print(f"Bot's mention string: <@{discord_client.user.id}>")
    print(f"google-generativeai version: {genai.__version__}")

@discord_client.event
async def on_message(message):
    if message.author == discord_client.user:
        return
    if message.author.bot:
        return

    mention_string = f"<@{discord_client.user.id}>"
    if message.content.startswith(mention_string + " "):
        input_text = message.content[len(mention_string) + 1:].strip()

        user_id = message.author.id
        if user_id not in chat_histories:
            chat_histories[user_id] = model.start_chat(history=[])
        chat = chat_histories[user_id]

        await message.channel.send("---")

        try:
            # --- 堅牢な非同期処理 (タスクの作成) ---
            async def send_and_process():
                response = await chat.send_message_async(input_text)
                # ここでは条件付き await は不要。常にタスクを await する。
                for chunk in split_text(response.text):
                    await message.channel.send(chunk)

            await send_and_process() # コルーチンを直接実行

        except Exception as e:
            await message.channel.send(f"Error: {e}")
            print(f"Full traceback: {e.__traceback__}")  # より詳細なエラー情報

nest_asyncio.apply()
discord_client.run(os.environ['DISCORD_BOT_TOKEN'])
EOF

ここまでを全部コピーして、コンソールに貼り付けてリターンキーを押してください。

なおこのプログラムは以下のサイトを参考にしました。

note.com

もとのプロクラムだと、チャットに入力した内容全部にAIが反応するのでメンション(@~とチャット内でAIに呼びかけた場合)のみ反応するように変更しています。

Discord Botをサービスとして動かす

サーバー側でサービスとして動かすことで、Discord Botが恒久的に作動するようになります。そのため、以下の内容をコンソールにコピーしてペーストします。

cat > /set_env_and_script_runner.sh << 'EOF'
#!/bin/bash

# 無限ループ
while true; do
    echo "Starting your_script.py at $(date)"
    
    # 環境変数の読み込み
    if [ -f /set_env.sh ]; then
        source /set_env.sh
    else
        echo "set_env.sh not found!" >&2
        exit 1
    fi
    
    # スクリプトの実行
    if ! python3 /your_script.py; then
        echo "your_script.py crashed with exit code $? at $(date). Restarting in 10 seconds..." >&2
    fi
    
    # 5秒待機
    sleep 5
done
EOF

最後にこのスクリプトを実行します。

nohup bash /set_env_and_script_runner.sh > /var/log/set_env_and_script_runner.log 2>&1 &

AWSではsystemdを使用しましたが、QNAPのUbuntu 22.04 Dockerではsystemdが使えないので、スクリプトを無限ループさせる方法でサービス同様の実行をさせています。

サービスが実行されているか確認するには、以下のコマンドを実行します。

ps aux | grep set_env_and_script_runner.sh

動いていればこんな風に表示されます。

最後に、QNAPを再起動したときにこのスクリプトを自動的に実行させるように設定。

export DEBIAN_FRONTEND=noninteractive && \
apt update -y && \
apt install -y cron && \
service cron start && \
(crontab -l 2>/dev/null; echo "@reboot nohup bash /set_env_and_script_runner.sh > /var/log/set_env_and_script_runner.log 2>&1 &") | crontab -

GEMINIが日本語以外で返答する場合の対処法

理由はよくわからないんですが、GEMINIからの回答でローマ字が入ったり英語が加わったりすることがあるかもしれません。

このときは、「日本語だけで回答して」等、チャット内で回答言語の明示をすればその後は日本語のみで回答するようになります。

生成AIでAmazonWebServeceにメンション時のみ反応するGEMINI AI Discord Botを開発・設置する

skypeのサービス終了に伴いDiscordに移行

所内での事務連絡にskypeを使っていましたが、2025/5にskypeのサービスが終了するということで、Discordのボイスチャットに移行することにしました。

他サービスも検討しましたが、①メールアドレスのみで登録可能で登録時に電話番号不要、②ボイスチャット(三者通話)が時間無制限、③チャット履歴がログアウトしたあとも数ヶ月分は確認できる、という要件を満たすのはDiscordのみでした。

DiscordでAIを使いたい

個人的にMicrosoft CoPilotやGoogle GEMINIを使用していますが、チャット内でシームレスにAIを利用できると便利だろうなということで、GEMINI AI Botを設置することにしました。

Discord Botの作成・Discord Bot Tokenの発行

  • Discordに登録してチャンネルを作成します。
  • Discord Developer Portal でアプリケーションを作成します。
  • Botを作成し、Bot Tokenを取得します。
  • Botに必要な権限 (メッセージの読み取り、送信など) を付与します。
  • Botをサーバーに招待します。

 

Discordのチャンネル作成はリンク先を参照してください。

ボイスチャンネルを作成すると、音声通話(映像も可能)とチャットが使用できるようになります。

network.mobile.rakuten.co.jp

Discord botを作成します。

Botの作り方はリンク先をご参考に。

qiita.com

Botを作成した後、まず最初にInstallationのタブでInstall LinkをNoneに設定しておきます。こうしないと非公開Botに設定できないので。

権限を設定します。scopesの基本はbot、その他はご自由に。Bot permissionsはTEXTとVOICEを適宜。

一番右下のボタンを押してURLをコピーして、ブラウザのアドレス欄にペーストするとチャットにbotが呼び出せます。

次に左側のタブのBotのページで設定します。

PublicBotは必ずoffに設定しておきます。Publicのままにしておいて、どこかのチャットにBotが呼び出されて大量のやりとりが発生するとGEMINI使用の費用請求をされたり、こちらのチャットの内容が漏洩する可能性があるので、Publicのままにはしないでおきましょう。

中段の「Privileged Gateway Intents」はPresence Intent・Server Members Intent・Message Content Intentをオンにしておきます。

下段のText Permissionsは画像でチェックされているあたりにチェックを入れておきます。

設定が終わったら、「Token」の下にあるReset Tokenボタンを押します、Discordのパスワードが要求されるので、パスワードを入力した後、Tokenの値をメモ帳にでも保存しておきます。

保存しておかないと、閲覧できなくなって新しいTokenを発行するしかなくなるので注意してください。

GEMINI APIの発行

aistudio.google.com

  • Gemini API (Google AI Studio API) を有効にします。
  • APIキーを取得します。

 

リンク先にアクセスします。

なお、GoogleWorkspaceの契約をしていないとAPI発行ができないかもしれません。

上段のみチェックして同意する

「キー APIキーの作成」ボタンを押す

GEMINIのAPIキーが生成されるので、コピーボタンを押してメモ帳などに保存しておきます。

QNAPでDiscord Botを動作させる・GoogleColaboでDiscord Botを動作させる(いずれも失敗)

最初は事務所内で使用しているQNAP NASのcontainer station(仮想環境)でubuntu 22.04を動作させて後記引用するBotとは別のBotを動かすつもりでしたが、これが何度やってもどうにもダメで、CoPilotに提示された方法を全て試してもエラーが解消できなかったので諦めました。

かといってBot用マシンを一個立てた上で最後までエラーが出てもつらいので、次にGoogleColaboでBotを動かしてみました。

しかし設定した後でわかったんですが、GoogleColaboは一定時間ごとに環境設定・プログラムが更地にされてしまうので、恒久的なBot設定には向いてなかったですね。

ただGoogleColaboで環境設定して、プログラムを試験的に走らせてみてエラーが出るとエラー対策したコードをすぐに提示してくれるので、GoogleColaboでテストとして運用してみて、うまくいったら恒久的なサーバーに移行するのがいいのかもしれません。

という訳で、GoogleColaboでエラーが解消されるまでコードを訂正して、AmazonWebService(AWS) Lightsailに移行しました。

AmazonWebService LightsailでGEMINIを利用したDiscord Botを動作させる(成功)

Discord Botを設置するという検索をすると無料サーバー等が出てくるのですが、設置までトラブルが多い印象なので、有料ですが低価格で一番手堅いAmazon Web Service(AWS) Lightsailを利用します。有料といっても他のDiscord Botサーバーでも最低利用料金が5ドルのようなので、同じ費用なら一番しっかりしてるAWSがいいと思います。設定時の原因不明トラブルで時間取られたくないですし。

aws.amazon.com

タイトルでは最低月額料金が月額3.5ドルになってますが、IPv4だと最低料金が月額5ドルです。

少なくとも今回設置するDiscord Botのプログラムでは5ドルのプランで十分なので、このプランを導入します。

Instance locationはTOKYO、PlatformはLinux/Unix、OperatingSystem OnlyでUbuntu 22.04LTSを選択しました。ただよく考えたらDiscordのサーバーとGEMINIのサーバーがどっちも北米にあるとしたら、Instance locationは北米を指定したほうが反応が多少よくなるのかもしれません。それとも日本ユーザーの場合にはどっちも国内のサーバーなんですかね。

コンソールにアクセスしたら、「すべてのサービスを表示」をクリック。Lightsailの契約をしたらLightsailだけにアクセスするんじゃないんですね。ちょっと最初わからなかった。

左上のLightsailをクリックすると、Lightsailアクセスできるので、インスタンスを一個作成します。

以下、PlatformはLinux/Unix、OperatingSystemはUbuntu 22.04LTSを前提としています。他のバージョンなりで試すときにエラーが出たらCoPilotにでも聞いてください。私に聞かれてもわかりませんので……。

また、以下の設定はコンソールにログインした後にディレクトリを移動したり作ったりしない・rootユーザーのまま(つまり全部コンソールログイン時のまま何もいじらず設定もしない)実行することが前提です。一つの仮想環境に一つのBotなら整理とか必要ないのでこれでいいんじゃないかと思います。例によって気になる人はCoPilotに聞いて頑張って書き換えてください。

以下、引用部分をコンソールにコピーしてペーストすればGEMINIのDiscord Botが動きます。

まず実行環境を設定

「SSHを利用して接続」ボタンを押すと、ブラウザでコンソールが開きます。わざわざソフトとかインストールしなくていいので大変便利。

コンソールに、以下のコマンド等を入力していきます。

コピーして、コンソール上でマウスの右クリック→貼り付けとやるとコマンド等がコピーできるので、必要に応じてリターンキーを押して実行してください。

sudo apt update -y && \
sudo apt upgrade -y && \
sudo apt install -y python3-venv python3-pip python3 tzdata && \
echo 'export PATH=$PATH:/home/ubuntu/.local/bin' >> ~/.bashrc && \
source ~/.bashrc && \
sudo pip install -q nest_asyncio discord.py && \
sudo pip install -q -U google-generativeai && \
sudo ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
sudo dpkg-reconfigure --frontend noninteractive tzdata

引用部分は各引用部分ごとにひとまとまりなので、折り返し部分で切ったりせずにまとめてコピーしてペーストしてください。なんか実行内容が重複してるんじゃないかとか言われそうですが、わかっている人はうまいことやってください。

なお途中で「WARNING: Running pip as the 'root' user can result in broken permissions and~」という警告が出ますが、無視して問題ないです。問題ないと言い切っていいのかはどうかと思いますし、CoPilotには仮想環境で設定しろと言われたのですが、そもそもAWSの環境自体が仮想環境でそこにさらに仮想環境作って実行しようとするとかえってうまくいかないんじゃないかと思います(QNAPは仮想環境上で実行しようとして失敗した)。

警告は出たんですが、少なくともこのあとのBot実行に問題はありませんし、Discord Botだけ実行させている分には大丈夫だと思います。もし他のサービスも実行したいとなったら、記憶領域にも相当余裕があるので別に仮想環境立ててやればいいんじゃないかと。

echo "export GOOGLE_API_KEY='実際のGOOGLE_API_KEYに書き換えてください'" > set_env.sh

echo "export DISCORD_BOT_TOKEN='実際のDISCORD_BOT_TOKENに書き換えてください'" >> set_env.sh

ここが重要で、 実際のGOOGLE_API_KEYに書き換えてください のところをメモしたAPIキーに書き換え、 実際のDISCORD_BOT_TOKENに書き換えてください のところをメモしたDiscord Tokeに書き換えをしてから、コピーしてペーストして実行してください。なお、前の ' と後の '" はそのままにしておく必要があります。

ここに実際のAPIキー/Tokenを入れないと絶対にうまく動きません。

chmod +x set_env.sh && source set_env.sh

ここまでがプログラム設置前段階。

Discord Bot用プログラム

cat > your_script.py << 'EOF'
import os
import nest_asyncio
import discord
import google.generativeai as genai
import asyncio

# Google Generative AI の設定
genai.configure(api_key=os.environ["GOOGLE_API_KEY"])
model = genai.GenerativeModel('gemini-2.0-pro-exp')

# Discord クライアントのセットアップ
intents = discord.Intents.default()
intents.message_content = True
discord_client = discord.Client(intents=intents)

def split_text(text, chunk_size=1500):
    """テキストをチャンクに分割します。"""
    return [text[i:i+chunk_size] for i in range(0, len(text), chunk_size)]

# ユーザーごとのチャット履歴を保存する辞書
chat_histories = {}

@discord_client.event
async def on_ready():
    print(f'Logged in as {discord_client.user}')
    print(f"Bot's mention string: <@{discord_client.user.id}>")
    print(f"google-generativeai version: {genai.__version__}")

@discord_client.event
async def on_message(message):
    if message.author == discord_client.user:
        return
    if message.author.bot:
        return

    mention_string = f"<@{discord_client.user.id}>"
    if message.content.startswith(mention_string + " "):
        input_text = message.content[len(mention_string) + 1:].strip()

        user_id = message.author.id
        if user_id not in chat_histories:
            chat_histories[user_id] = model.start_chat(history=[])
        chat = chat_histories[user_id]

        await message.channel.send("---")

        try:
            # --- 堅牢な非同期処理 (タスクの作成) ---
            async def send_and_process():
                response = await chat.send_message_async(input_text)
                # ここでは条件付き await は不要。常にタスクを await する。
                for chunk in split_text(response.text):
                    await message.channel.send(chunk)

            await send_and_process() # コルーチンを直接実行

        except Exception as e:
            await message.channel.send(f"Error: {e}")
            print(f"Full traceback: {e.__traceback__}")  # より詳細なエラー情報

nest_asyncio.apply()
discord_client.run(os.environ['DISCORD_BOT_TOKEN'])
EOF

ここまでを全部コピーして、コンソールに貼り付けてリターンキーを押してください。

なおこのプログラムは以下のサイトを参考にしました。

note.com

ただもとのプロクラムだと、チャットに入力した内容全部にAIが反応するのでメンション(@~とチャット内でAIに呼びかけた場合)のみ反応するように変更しています。

全てのチャットに返答するような設定だとAIの返答で埋め尽くされて人間同士のコミュニケーションも阻害されかねないので、複数人で使うことが目的のチャットであればAIはメンション時のみ反応にした方がいいと思いますね。チャット内に人間が1人のみなら、メンションせずともAIが全部反応するようなプログラムのほうがいいんでしょうけど。

それとmodel = genai.GenerativeModel('gemini-2.0-pro-exp')とGemini 2.0 Proを使うような指定をこちらではしているんですが、これは結構怪しいです。

Google側でどのモデルを使うか制御している雰囲気で、こちらで指定してもあんまり意味ないかもしれません。

一応調べたところ、現時点ではgoogle-generativeaiでは以下リストアップされていましたが、明示的にユーザー側で指定できているのかは未知数です。

models/gemini-1.0-pro-vision-latest
models/gemini-pro-vision
models/gemini-1.5-pro-latest
models/gemini-1.5-pro-001
models/gemini-1.5-pro-002
models/gemini-1.5-pro
models/gemini-1.5-flash-latest
models/gemini-1.5-flash-001
models/gemini-1.5-flash-001-tuning
models/gemini-1.5-flash
models/gemini-1.5-flash-002
models/gemini-1.5-flash-8b
models/gemini-1.5-flash-8b-001
models/gemini-1.5-flash-8b-latest
models/gemini-1.5-flash-8b-exp-0827
models/gemini-1.5-flash-8b-exp-0924
models/gemini-2.0-flash-exp
models/gemini-2.0-flash
models/gemini-2.0-flash-001
models/gemini-2.0-flash-exp-image-generation
models/gemini-2.0-flash-lite-001
models/gemini-2.0-flash-lite
models/gemini-2.0-flash-lite-preview-02-05
models/gemini-2.0-flash-lite-preview
models/gemini-2.0-pro-exp
models/gemini-2.0-pro-exp-02-05
models/gemini-exp-1206
models/gemini-2.0-flash-thinking-exp-01-21
models/gemini-2.0-flash-thinking-exp
models/gemini-2.0-flash-thinking-exp-1219
models/learnlm-1.5-pro-experimental
models/gemma-3-27b-it

Discord Botをサービスとして動かす

サーバー側でサービスとして動かすことで、Discord Botが恒久的に作動するようになります。そのため、以下の内容をコンソールにコピーしてペーストします。

sudo bash -c 'cat > /etc/systemd/system/your_script.service << EOF
[Unit]
Description=Your Script Service
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/home/ubuntu
ExecStart=/usr/bin/bash -c "source /home/ubuntu/set_env.sh && /usr/bin/python3 /home/ubuntu/your_script.py"
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF'

最後にこのサービスを実行します。

sudo systemctl daemon-reload && sudo systemctl start your_script.service && sudo systemctl enable your_script.service

サービスが実行されているか確認するには、以下のコマンドを実行します。

sudo systemctl status your_script.service

動いていればこんな風に表示されます。メモリ使用量は100Mもありませんし、CPUもほとんど使用していないので、5ドルプランで十分なのが確認できます。まあDiscord ChatのテキストデータをGoogleに流して、Googleから返ってきた内容をDiscord Chatに送信するブリッジのような役割なので、そんなにメモリもCPUパワーもいりませんよね。

コンソールに戻るには、Ctrl+Cで戻れます。

もしファイル等書き換えてサービスを再起動させたい場合は、以下のコマンドを実行。

sudo systemctl restart your_script.service

GEMINIが日本語以外で返答する場合の対処法

理由はよくわからないんですが、GEMINIからの回答でローマ字が入ったり英語が加わったりすることがあるかもしれません。

このときは、「日本語だけで回答して」等、チャット内で回答言語の明示をすればその後は日本語のみで回答するようになります。

たぶん費用がかかります

GEMINI APIは従量制で一定の費用がかかるようです(ただあんまりはっきりしていない)。とはいえ、メンション時のみ作動させるような設定だとそんなに多額にならないのではないかと思いますが。

プログラムの変更はGoogleColabo・GEMINI・CoPilotで行ないました

GoogleColaboで実行したところ、エラーが出たのでGoogleColaboのSuggestに従って変更。

その後、メンションした場合のみ反応するようGEMINIに指示してコードを変更。

これでメンション時のみ反応するように変更できたけれども、Botの回答に「Error: object GenerateContentResponse can't be used in 'await' expression」というエラーが出てしまったのでGEMINIに手直しするよう指示してコードを修正するも同様のエラーが出続けたため修正指示をしたところ「もし、前回の包括的な修正後も "Error: object GenerateContentResponse can't be used in 'await' expression" エラーが まだ 発生する場合、非常に特殊な、そして Colab 環境自体の内部に存在する、より深いレベルの競合が問題である可能性が極めて高いです。前回のバージョンのコードを 正確に 実装していれば、現時点ではコードの問題である可能性は 非常に 低いです。」とさじを投げられてしまう。

仕方ないのでCoPilotにコードとエラーを示したところ、ちゃんと動作するプログラムのコードを提示された(つまりGEMINIの回答が間違っていてコードの問題だった)のが、前述したプログラムになります。

AIはちまちま使っているんですが、コード生成はCoPiloのほうが一段レベルが高い感じしますね。 

なお私はわずかにコードを読める程度で、コードを書くのは非常に簡易なVBA以外は無理な人間なんですが、AIを使うとここまでできてしまうので、本業ではない作業については特にAI活用の利点が大きいとは感じています。

土地賃貸借の法定更新において更新料の支払いは必要か(結論:更新料の特約の有無および法定更新の際の合意内容による)

土地賃貸借契約において、賃貸期間満了の際に地主が契約更新を拒絶しても、地主に正当事由がなければ賃貸借契約は更新されます。

では、法定更新の際に、更新料の支払いが必要になるのでしょうか。

賃貸借契約の更新が当事者間の合意によってなされたのであればその際に更新料支払いが合意されたかどうか結論が定まるので問題ありません。

しかし、法定更新の際には当事者間の合意によらずに更新がされるので、更新料の取扱がどうなるのか問題となります。

まず、基本となる土地賃貸借契約に更新料の定めがない場合にも、賃借人に更新料支払義務が発生するのでしょうか。

この点、賃貸人の請求があれば当然に賃借人に更新料支払義務が生ずる旨の商慣習ないし事実たる慣習があるかないかという形で争われてきました。

しかし、最判昭和51.1.1により、賃貸借契約に更新料の定めがない場合に法定更新されたときには更新料の支払義務はないということで決着がついています(実務裁判例 借地借家契約における各種特約の効力18ページ)。

次に、基本となる土地賃貸借契約に更新料の定めがある場合に、賃借人に更新料支払義務が発生するのでしょうか。

そもそも更新料支払特約が無効ではないかという主張もありますが、更新料の額が著しく高額であるなど、賃借人に一方的に不利益を与える事情がない限り更新料支払特約は有効と考えられています(東京高判昭和58.7.19、借地借家事件処理マニュアル 118ページ)。

その上で、法定更新の際にも更新料支払いが必要になるかは、賃貸借契約において法定更新の際にも更新料支払義務があると当事者間で合意されていたかどうかで結論が異なります(更新料支払を肯定した東京地判平22.8.26・東京地判平9.6.5・東京地判平4.1.23、更新料支払を否定した東京地判平22.7.16・東京地判平9.1.28・東京地判平4.1.8・京都地判平16.5.18)。

つまり、賃貸人としては法定更新になってしまう場合に備えて、契約書には「本件賃貸借契約が、法定更新を含め更新される場合には、借主は貸主に対して更新料として金○○万円を契約更新時に支払う」というような文言にしておく必要があるということになります。

被相続人が生前保有していた有価証券をどうやって調査するか(結論:弁護士会照会または証券保管振替機構への開示請求)

亡くなった被相続人が生前、有価証券(株式・社債)を保有していた様子があるが、利用していた証券会社の支店が不明であったり、場合によっては証券会社さえわからない場合や、相続人の一部しか詳細がわかっていない場合があります。

この場合、有価証券の詳細が不明な相続人はどのようにして調査をすれば良いのでしょうか。

弁護士に依頼をしていて、利用していた証券会社が判明している場合は、戸籍・相続関係図・依頼者の委任状添付で本店に対して全店照会を弁護士会照会で行うことが考えられます。

相続人または代理人弁護士が単に店舗に問い合わせをするだけですと、ほかの支店で管理している場合には回答が得られず、かなりの手間になります。

しかし、本店に対して全店照会をすると、一般的にはどこの支店で取扱をしていたかを含めて回答が得られます。

この場合、金融機関は相続が発生していることがわかる資料及び委任状が添付されていることが回答の条件になりますので、添付資料として相続関係図を含めて必要になります。

もし利用している金融機関すら不明な場合には、株式会社証券保管振替機構の開示請求を利用することが考えられます。上場株式等に限定されますが、どの金融機関で取り扱っているのか等含めて、被相続人が生前保有していた有価証券につき資料を取得できます。

相続関係についての資産洗い出しは経験と知識が必要な分野で、弁護士によって遺産分割の結果が異なることもありえるので、代理人依頼の際には気をつけてもいいかもしれません。

相続の際、債務整理を試みた後に相続放棄できるか(結論:債務整理を試みたことが単純承認となり放棄が成立しない可能性がある)

相続の際に、被相続人に財産はあるが返済が必要な借り入れ等もあり、借り入れを金融機関に少なくしてもらって(一種の債務整理)多少でも財産を相続できればそのまま相続し、借り入れが減らずに返済義務を負うような自体になれば相続放棄するようなことは可能なのでしょうか。

このような場合、債務整理が単純承認事由にあたるか、すなわち民法921条1号の「処分」に債務整理が含まれるかということになりますが、新注釈民法(19)相続(1)543ページ以下だと「処分」の解説は主に債権側のことしか書いていません。

ただ「法律用語としての「処分」は、例えば相続財産の売却等の財産の現状や性質を変化させる行為をいう。……本号の適用によって単純承認の効果を発生させるのであるから、それを正当化するためには、それ相応の理由が要求されるべきである。ゆえに、本号が適用されるためには、相続人が自己のために相続が開始した事実を知りながら相続財産を処分したか、あるいは少なくとも相続人が被相続人の死亡した事実を確実に予想しながらあえてその処分をしたことを要する。」とされています。

債務整理も財産の現状や性質を変化させる行為であり、債務整理をするということは支払意思があることの証左ですから、「処分」にあたると思われます。

なお、被相続人が賃借人で相続人が賃借権確認訴訟を提起・追行した事例では処分性が肯定されています(東京高判平元・3・27高民集42巻1号74頁)。

同条3号では、民法921条3号にいう相続財産には相続償務も含まれ、限定承認をした相続人が消極財産を悪意で財産目録に記載しなかったときも単純承認したとみなされるとされた事例(最判昭61・3・20民集40・2・450、判時1198・106)があり(相続における承認・放棄の実務-Q&Aと事例183ページ以下)、債務につき相続財産に含まれるということは1号も同様かと思われます。

この事例は限定承認後の単純承認ですが、放棄前の1号でも同様に考えられる可能性は高いと思われます。

では債務整理した後に「相続放棄」申述ができないかというと、申述自体は可能です。申述時に家裁が単純承認事由があったかを審査することはしていないからです。

そして債権者から訴訟提起された際に、債権者からの債務相続に基づく相続放棄が抗弁となり、債権者は単純承認がされていたことを再抗弁として主張することになります。

債務整理をいったんしていたら、債権者から訴訟提起等される可能性はかなり高いといわざるをえません。

放棄するなら債務整理しない、債務整理するなら相続する(債務整理をする場合は放棄できない)前提で方向性を定めるべきでしょう。

Elgato Key Lightの接続はパソコンソフトを使うとうまくいく

Elgato Key Lightの設定ソフトへの接続は、一番最初はパソコン用ソフトで接続設定をすると、その後はスマートフォン等のソフトで機器の確認・設定が可能になります。

以前Elgato Key Lightの初期設定方法(スマートフォンでの制御ソフトへの接続)を書きましたが、どうもいまいち接続がうまくいかないことがあるようです。

www.toridelaw.com

しかし、パソコン用ソフト(当職はWindows用ソフトを使用)を使うと確実に初期設定が可能で、いったん接続さえできてしまえばスマートフォン用ソフトからも確認・設定・制御が可能になります。

Elgato Key Lightを設置した後、パソコン用ソフトをインストールします。

www.elgato.com

リンク先のSELECT YOUR PRODUCTSで使用機器を選択し、パソコンに合わせてWindowsかMacを選択してソフトウェアをダウンロード・インストールします。

インストールすると、Windowsの場合はタスクバーに常駐アイコンが表示されるので、左クリックして小さいウィンドウを表示させます。

ウィンドウが表示されたら、左上の+ボタンをクリックします。

+ボタンがコントロールする機器の追加ボタンで、感知範囲内にある機器を自動的に検出してくれます。

機器検出後、機器の選択・無線LAN設定(パスワード入力)画面になるので、指示に従い必要事項を入力します。

いったん機器が無線LAN接続できれば、あとはスマートフォンからでも確認・設定・制御ができるようになります。

スマートフォン用ソフトではスマートフォン側の問題なのかソフト側の問題か不明ですが、どうも接続がうまくいかないという事例が散見されます。

パソコン用ソフトで初期設定をする方法だと、いまのところ失敗したことがないので、いまいち不安定・最初の接続設定がうまくいかない方は、試してみてください。

相続人間で相続に争いがある場合に債務者は供託できるか(結論:供託はできない)

相続人の範囲がはっきりしていて,各相続人の所在も判明しているが,相続人間で具体的な相続金額について争いがある場合に,債務者は誰にいくら払えばよいのか,または供託してしまったほうがよいのでしょうか。

例として,相続人が2人(各法定相続分は2分の1),被相続人の債務者は契約代金200万円を被相続人に払う予定であった場合を考えます。

相続人間で寄与分や特別受益に争いがあり,具体的な相続金額が定まっていない場合に,債務者としてはどのようにすればよいのか迷うと思います。

このとき,相続人各人への支払額が不明であるとして,債権者不確知を理由とする供託ができるようにも思えますが,これは法務局が供託の受付をしてくれません。

理由としては,相続人の範囲が明確であれば法定相続分の算定はでき,かつ所在も判明していれば履行の提供も可能であるため,債権者不確知の要件に該当しないためです。

この点,このような場合に供託ができると記述している弁護士の記事もあるようですが,法務局の実務上不可能なので,誤りということになります。

なお,受領拒絶の場合には供託はできますが,前記の場合には法定相続分の2分の1である100万円を拒絶した部分についてのみ供託することができ,受領をした相続人の部分については供託することはできません(なお二人とも受領拒絶をした場合には二件の供託が必要になる)。

法定相続分での履行の提供があれば,他の相続人から法定相続分よりも実際の相続金額が少ないと言われている相続人は受取をしてしまうでしょうから,他方相続人は受領拒絶したり供託してもらう意味はないということになります。

このような場合には,遺産分割調停の申立を行い,遺産分割調停申立事件を本案として財産の管理人選任の申立を行い,財産の保全をすることになります(家事事件における保全処分の実務と書式111ページ)。