「AIに頼む」から一歩進んで、AIが先に動いて“用意しておく” 世界へ。
ここでは、LM Studioを トリガー(合図)→ ポリシー(判断)→ アクション(実行) の3レイヤで自動化し、人間が触る前に下ごしらえが終わる状態を作ります。
いまの現在地と、ここで目指す地点
- これまで:RAGで“あなたの知識を参照できるAI”をローカル構築、APIで外部接続も完了
- これから:スケジュール/イベント/監視をトリガーにして、AIが自律的に用意(草案・要約・アラート・草稿化)
設計の骨格:たった3要素だけでOK
- Trigger(いつ動く?)
- 時間:cron/Windowsタスク(毎朝7:30)
- 変更:フォルダ新規PDF・RSS更新・Notion更新
- Webhook:Slackで絵文字を付けた/GitHub Issue作成 など - Policy(動かすか?何を狙うか?)
- ルール:新着PDFは3ページ超なら要約、タイトル案3本、引用元付き
- 品質:温度0.2、RAG参照オン、NGワード/機密のマスク - Action(何を残す?)
- WordPressに非公開ドラフト作成
- Slackへ要点+URL通知
- 失敗時はリトライ&ログ
まずは 1トリガー×1ポリシー×1アクション の最小系から始め、成功したら枝を増やすのが王道。
最小ワークフロー(完成版)
シナリオ: ~/inbox/papers/ にPDFを置いたら、
→ RAGで要約+見出し案+引用 を作り
→ WordPressに非公開ドラフトを自動作成
→ Slackに通知
1) 監視(Trigger)
- mac/Linux:
fswatch/watchdog - Windows: タスクスケジューラ+簡易スクリプト
2) LM Studio呼び出し(Policy)
http://localhost:1234/v1/chat/completions(OpenAI互換)- モデルはRAG紐づけのものをUIでLoad済みに
3) WordPressドラフト作成(Action)
- REST API:
POST /wp-json/wp/v2/posts - ステータス:
draft
そのまま動かせる最小Python(監視なし・単発実行)
新着PDFの要約 → WordPressにドラフト作成。
※監視は後段に追加。値は環境に合わせて置換ください。
# pip install requests
import requests, json, base64, pathlib
LM_BASE = "http://localhost:1234/v1"
MODEL = "llama-3-8b-instruct" # LM StudioでLoad中
WP_BASE = "https://your-blog.example"
WP_USER = "your_user"
WP_APP_PW = "your_application_password" # WPのアプリPW推奨
PDF_PATH = "/path/to/new.pdf"
def read_pdf_text(p):
# まずは簡易。画像PDFは事前にOCR推奨(第3話のとおり)
# ここではダミーでファイル名だけ参照し、RAGで本文参照させる前提。
return f"対象ドキュメント: {pathlib.Path(p).name}"
def ask_lm(prompt):
url = f"{LM_BASE}/chat/completions"
payload = {
"model": MODEL,
"messages": [
{"role":"system","content":"あなたは日本語の要約アシスタントです。事実性と引用元明記を重視してください。"},
{"role":"user","content": prompt}
],
"temperature": 0.2
}
r = requests.post(url, json=payload, timeout=120)
r.raise_for_status()
return r.json()["choices"][0]["message"]["content"]
def to_wordpress(title, content_md):
auth = base64.b64encode(f"{WP_USER}:{WP_APP_PW}".encode()).decode()
headers = {"Authorization": f"Basic {auth}",
"Content-Type": "application/json"}
payload = {"title": title, "content": content_md, "status": "draft"}
r = requests.post(f"{WP_BASE}/wp-json/wp/v2/posts", headers=headers, data=json.dumps(payload), timeout=60)
r.raise_for_status()
return r.json().get("link")
if __name__ == "__main__":
context = read_pdf_text(PDF_PATH)
prompt = f"""
あなたはRAGが紐づいたローカルAIです。登録済みドキュメントを参照し、
次のPDFについて以下を日本語で出力してください。
# 出力仕様(Markdown)
- H1: 要約タイトル(20字以内)
- 箇条書き3点の要点(具体・数値・引用セクション)
- 引用: どの章/ページに該当かを括弧で明示(例: p.12「章タイトル」)
- 記事草案(見出し構造 H2/H3、導入200字、結論200字)
PDFヒント: {context}
""".strip()
result = ask_lm(prompt)
# タイトル一行目を抽出(H1行想定)
first_line = result.splitlines()[0].strip("# ").strip()
link = to_wordpress(first_line or "RAG要約ドラフト", result)
print("Draft:", link or "(draft created)")
RAGが効く条件:LM Studio UIで該当PDFをDocsに登録し、そのDocsを使うKnowledge Sourceを選んだ状態でモデルをLoadしておくこと。
監視(Trigger)を足す
Linux/macOS(Python watchdog):
pip install watchdog
# file_watch.py
import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import subprocess, pathlib
WATCH_DIR = "/path/to/inbox/papers"
class Handler(FileSystemEventHandler):
def on_created(self, event):
if not event.is_directory and event.src_path.lower().endswith(".pdf"):
print("New PDF:", event.src_path)
# 上の単発スクリプトを呼び出す想定(引数でパス渡すよう改造してもOK)
subprocess.run(["python", "your_single_run_script.py", event.src_path], check=False)
if __name__ == "__main__":
obs = Observer()
obs.schedule(Handler(), WATCH_DIR, recursive=False)
obs.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
obs.stop()
obs.join()
Windows
- 「タスク スケジューラ」で5分ごと実行(新着のみ処理はスクリプト側で判定)
- もしくは
watchdog同様に常駐
事故を防ぐ運用ルール(超重要・3点)
- 非公開ドラフト運用
本公開は必ず人間の目で通す(見出し調整・引用の正確性チェック) - ログ & リトライ
失敗時は再実行(ネットワーク・PDF品質・RAG未選択を検知) - 人間が“最後の5%を磨く”
AIは下ごしらえ担当。結論の責任は人間(ここが差別化)
量産・拡張のアイデア
- RSSトリガー:あなたの監視したいサイトのRSSを巡回 → AI要約+WPドラフト
- Slackトリガー:チャンネルに 📌 を付けた投稿だけ収集 → 週報ドラフト
- Notionトリガー:指定データベースの更新 → 要点抽出→ドラフト
どれも「トリガーが違うだけ」で、Policy(プロンプト)と Action(ドラフト化)は共通。
スクリプトは1本を関数化して使い回せます。
この記事の要点(まとめ)
- Trigger/Policy/Action の3階建てで、AIが先に動く状態を作る
- 最小構成は「フォルダ監視 → RAG要約 → WPドラフト」
- ローカル完結:漏洩ゼロ・APIコストゼロ
- 非公開ドラフトを人間が磨くことで、速度×品質×安全を両立

