2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

定型的な返信をスマホから済ませたい

日常生活では、内容そのものよりも体裁を整えることに時間がかかる返信が意外に多くあります。予定の確認、受領の連絡、依頼への了承、丁寧な断りなど、メールでもチャットでも、要件は単純なのに文章だけはそれなりに整える必要があります。

こうした返信のたびに汎用 LLM を開き、「このメッセージに丁寧に返信して」「この点だけ伝えて」と説明するのは手間です。自宅ならローカル LLM も使えますが、外出中にスマートフォンから返したい場面では使えません。

そこで、受信文を貼り付けるだけで日本語の返信案を作る reply-writer を作りました[1]。必要な場合だけ数行の指示を加え、生成された文章をコピーして、人間が確認して送信するための小さな Web アプリケーションです。

処理の流れは次のとおりです。

受信文を貼り付ける
↓
必要なら返信方針を書く
↓
返信案を生成する
↓
コピーする
↓
内容を確認して自分で送信する

メールクライアントやチャットサービスとは連携しません。Gmail、Outlook、LINE などからメッセージを取得する機能も、生成した文章を自動送信する機能もありません。用途を「返信文を作る」ところまでに限定しています。

ai-digest と sizu-writer の構成を返信作成に使う

reply-writer の構成は、以前作った ai-digest[2] や、その生成 API 周りを整理した実装[3][4]、さらに sizu-writer[5] と共通しています。

生成処理を Flask から分離し、Web 画面と CLI から同じ生成コアを呼び出します。生成先は特定ベンダーへ固定せず、OpenAI 互換 Chat Completions API を話すサービスを設定で指定します。

スマートフォン
  ↓ HTTPS
Apache
  ↓
127.0.0.1:8091
  ↓
gunicorn
  ↓
Flask
  ↓
Generation Core
  ↓
OpenAI 互換 API

sizu-writer が短いメモから投稿文を作るのに対し、reply-writer は受信文から返信文を作ります。入出力は違いますが、「入力を渡す」「生成結果だけを受け取る」「最後の操作は人間が行う」という境界は同じです。

reply-writer をインストールする

必要な Python は 3.9 以降です。リポジトリの .python-version3.11 なので、本稿では Python 3.11 の環境を使います。

git clone https://github.com/id774/reply-writer.git
cd reply-writer
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
cp .env.example .env
chmod 600 .env

最初に単体テストを実行します。

.venv/bin/python -m unittest discover -s tests

このテストは生成 API へ接続せず、API トークンも必要としません。ここで失敗する場合は、生成 API の設定ではなく、Python 環境や依存関係を先に確認できます。

生成 API を設定する

.env では、少なくとも次の 4 項目を指定します。

GENERATION_BACKEND
GENERATION_API_TOKEN
GENERATION_BASE_URL
GENERATION_MODEL

reply-writer は、この 4 項目に既定の接続先を持ちません。設定が不足している場合は起動を拒否します。受信文をどこへ送るのかを設定なしで決めないためです。

さくらの AI Engine を使う

今回は、さくらの AI Engine が提供する OpenAI 互換 Chat Completions API を利用します[6]。設定例は次のとおりです。

GENERATION_BACKEND=openai-compatible
GENERATION_API_TOKEN=<UUID>:<secret>
GENERATION_BASE_URL=https://api.ai.sakura.ad.jp/v1
GENERATION_MODEL=<利用するモデル名>
GENERATION_RESPONSE_MODE=prompt-json
GENERATION_MAX_RETRIES=0

GENERATION_BASE_URL/v1 までを指定します。/chat/completions は OpenAI クライアント側が付加するため、設定値には含めません。

GENERATION_MODEL には、その時点で利用するモデル名を設定します。利用可能なモデルはサービス側で変わり得るため、リポジトリには固定値を持たせていません。

GENERATION_MAX_RETRIES=0 は、1 回の生成操作を 1 回の API 要求に対応させるための設定です。失敗時に別の生成先へ切り替える処理もありません。どのサービスへ受信文を送ったのかを曖昧にしない構成にしています。

.env には API トークンが入るため、chmod 600 のまま運用します。

CLI で返信生成を確認する

Web 画面を使う前に、CLI から生成できることを確認します。実際のメールではなく、架空の文面を message.txt に保存します。

先日はありがとうございました。
来週水曜日の 15 時から打ち合わせをお願いできますでしょうか。
よろしくお願いいたします。

次のコマンドで返信案を生成します。

python cli.py generate --message message.txt

通常は受信文だけで生成できます。返信内容に条件を加えたい場合だけ、別ファイルに方針を書きます。

水曜日は難しいため、木曜日の同じ時間を提案する。
python cli.py generate \
  --message message.txt \
  --direction direction.txt

CLI と Web 画面は同じ生成コアと同じプロンプトを使います。CLI で生成できれば、API 接続と文章生成が正常であることを Web 画面とは分けて確認できます。

Web 画面から返信を作る

開発用サーバーは次のコマンドで起動できます。

.venv/bin/python app.py

既定では 127.0.0.1:8091 で待ち受けます。

ブラウザで入力画面を開き、受信文を貼り付けます。特に指定がなければ返信方針は空欄のまま生成します。件名がある形式では件名と本文が分かれて表示され、それぞれコピーできます。

ここでアプリケーションが行うのは生成までです。宛先の選択や送信は行わないため、生成結果を元のメールやチャットへ貼り付け、内容を確認してから送信します。

サーバーで動かしてスマートフォンから使う

本来の用途は、外出中にスマートフォンから使うことです。サーバーでは gunicorn を systemd で動かし、その前段を Apache にします。

サービスを起動したら、まずローカルのヘルスチェックを確認します。

sudo systemctl status reply-writer
curl -s http://127.0.0.1:8091/healthz

/healthz は Flask アプリケーションが起動していることだけを確認するもので、生成 API には接続しません。ここが通って生成だけ失敗する場合は、API トークン、GENERATION_BASE_URL、モデル名など生成側の設定を確認します。

Apache 側の設定を変更した場合は、構文を確認してから再読み込みします。

sudo apachectl configtest
sudo systemctl reload apache2

標準の配備例では /reply/ 配下へ公開します。

https://<host>/reply/

最後に Wi-Fi ではなく携帯回線からこの URL を開き、架空の受信文を貼り付け、返信案をコピーできれば一連の経路を確認できます。

入力する内容には境界を置く

reply-writer は受信文、追加指示、生成結果をアプリケーションのログへ記録しません。履歴保存用のデータベースも持ちません。

一方で、返信を生成するためには入力した文章を設定済みの生成 API へ送ります。ローカル保存しないことと、外部サービスへ送信しないことは別です。

そのため、自分では機微情報を入力する用途には使っていません。予定確認や一般的な依頼への返信など、外部の生成 API へ渡して問題ない内容について、形式的な返信を手早く整える用途に限定しています。

また、スマートフォンから使えるようにサーバーへ公開する場合も、アプリケーションを無認証で公開する必要はありません。Basic 認証、IP 制限、VPN など、既存環境に合うアクセス制御を Apache 側へ置きます。メールサービスの認証情報を reply-writer に持たせる必要はありません。

まとめ

reply-writer で解消したかったのは、高度なメール処理ではなく、定型的な返信のたびに汎用 LLM へ同じ説明を繰り返す手間です。

受信文を貼り、必要な場合だけ返信方針を書き、生成結果をコピーするところまでを専用の Web アプリケーションにしました。送信や履歴管理まで自動化しないので、仕組みも操作も小さいままです。

外出中でもスマートフォンから開き、受信文を貼り付ける短い操作で体裁の整った返信案を作れます。この程度の用途であれば、汎用的な対話画面を毎回使うより、処理を専用化した小さな道具のほうが扱いやすいと考えています。

参考文献

  1. id774, reply-writer(2026-08-10). https://github.com/id774/reply-writer
  2. id774, AI 論文とニュースを日次でまとめる ai-digest を作った(2026-07-31). https://blog.id774.net/entry/2026/07/31/5164/
  3. id774, さくらの AI Engine の Anthropic 互換 API で ai-digest を動かす(2026-07-31). https://qiita.com/ynakayama/items/d486fc70c8a29f5f765c
  4. id774, ai-digest v1.2 をリリースして設定体系と日次運用を改善した(2026-08-05). https://qiita.com/ynakayama/items/b5e0dda6c12514cbbeb0
  5. id774, sizu-writer(2026-08-04). https://github.com/id774/sizu-writer
  6. さくらインターネット, 利用手順(2026-05-20). https://manual.sakura.ad.jp/cloud/ai-engine/02-howto.html
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?