Note記事のURLまたはユーザー名を入力し、ローカルLLMが新しい記事の下書きを生成するWebアプリケーションです。
今後の大規模改修方針は ADR 0001 と 3フェーズ実装計画 に整理しています。単一フォームで記事を生成する方式から、文体分析、記事条件の一問一答、記事生成と評価の3フェーズへ移行します。
ADR 0001 を踏まえた次の進化方針は ADR 0002 — Multi-Persona, Multi-Format Article Generation と Multi-persona / multi-format 実装計画 にまとめています。てりすけ本人と架空キャラ「宇宙野クラウディア」を別人格として扱い、note / cor-jp.com ブログ / Zenn / Qiita / ホームページHTML を切り替え可能にします。
実装 issue と ADR の対応、各層の責務、テスト条件は Issue and ADR guardrails にまとめています。現在のアプリ化後の引き継ぎ、起動方法、main昇格チェックリストは Note Maker app handoff に整理しています。次に着手する実装順は Next implementation cut に整理しています。
- Note記事URLまたはユーザー名からの記事生成
- キーワード、テーマ、読者層の指定
- 文体、トーン、目標文字数、記事目的の指定
- 記事構成のカスタマイズ
- マークダウン形式での出力、プレビュー、コピー
- フロントエンド: HTML, CSS, JavaScript
- バックエンド: Go
- LLM runtime: Evo X2 Ollama OpenAI互換API over Tailnetをprimary、Evo X2 llama.cppと作業端末ローカル llama.cppをfallback
- 主要モデル:
gemma4:e2b(文体/ソース整理)、qwen3.6:27b(深掘り質問)、gemma4:31b(日本語下書き)、gemma4:latest(最終検証) - Note取得: 公開記事ページ/RSS優先、非公式APIは互換フォールバック
- Go 1.23以上
- llama.cpp の
llama-server - Gemma4 31B Q4_K_M を動かせるメモリまたはVRAM
ggml-org/gemma-4-31B-it-GGUF の Q4_K_M は約18.7GB級のモデルです。初回ダウンロードとモデルロードには時間がかかります。
.env を作成します。
cp .env.example .env.env.example の既定値:
PORT=8080
LLAMACPP_BASE_URL=http://127.0.0.1:8081/v1
LLAMACPP_MODEL=gemma4:31b通常利用は launcher 経由を推奨します。launcher は空いているローカルポートを選び、Evo X2 Tailnet の primary LLM health を確認し、Go サーバーをビルドして起動し、終了時に子プロセスを停止します。既定では Mac 側のローカル fallback LLM は起動しません。
make launcherまたは mise を使う場合:
mise run launchermake app も同じ launcher を起動する alias です。
起動後はブラウザが自動で開きます。終了するときは launcher を実行したターミナルで Ctrl-C を押します。PORT が使用中の場合は、既定で次の空きポートを選びます。固定ポートで失敗させたい場合は ./scripts/launcher.sh --strict-port を使います。
launcher の既定保存先:
- macOS:
~/Library/Application Support/Note Maker - Linux/その他:
$XDG_DATA_HOME/note-makerまたは~/.local/share/note-maker
この配下に app_config.json、workflow_store.json、logs/、ビルド済みサーバーバイナリを置きます。保存先を変える場合は NOTE_MAKER_DATA_DIR=/path/to/dir make launcher または ./scripts/launcher.sh --data-dir /path/to/dir を指定します。
Evo X2 Tailnet が到達不能な場合、既定ではアプリを起動しません。UIだけを起動したい検証時は make launcher-status で状態を確認し、必要に応じて ./scripts/launcher.sh --allow-degraded を使います。ローカル llama-server を明示的に起動して primary として使う場合だけ、次を実行します。
make launcher-localllama-server の場所やモデルを変える場合は .env の LLAMA_SERVER、LLAMACPP_HF_REPO、LLAMACPP_HF_FILE、LLAMACPP_MODEL を変更します。
launcher 自体の検証:
make launcher-check従来の scripts/dev.sh は残しています。LLM_RUNTIME=local を明示した検証では llama-server と Go サーバーをまとめて起動できます。
make devブラウザで http://localhost:8080 にアクセスします。終了するときは Ctrl-C で両方のプロセスを停止できます。
Evo X2 の Ollama を使う場合は、Tailscale VPN/MagicDNS 上の OpenAI互換APIを primary とし、Mac側のローカルLLMは起動しません。fallback は順番を固定します。
- Evo X2 Ollama OpenAI互換API:
http://evo-x2.tailb30e58.ts.net/v1 - Evo X2 llama.cpp OpenAI互換API:
http://evo-x2.tailb30e58.ts.net/llama/v1 - 最終手段の作業端末ローカル llama.cpp:
http://127.0.0.1:8081/v1
前提として、利用端末が同じ Tailnet に参加しており、Evo X2 の Caddy/OpenAI互換APIが Tailnet 内から到達できる必要があります。これにより、SSH の個別認証や端末ごとの port forward に依存せず、他の許可済みデバイスからも同じ Evo X2 を利用できます。
make evo-x2または mise を使う場合:
mise trust
mise run evo-x2既定では Tailnet 上の http://evo-x2.tailb30e58.ts.net/v1 に接続します。モデルを変える場合は .env.evo-x2.example を参考に LLM_MODEL、STYLE_LLM_MODEL、BRIEF_LLM_MODEL、ARTICLE_LLM_MODEL、DRAFT_LLM_MODEL、VERIFY_LLM_MODEL を設定してください。120B級のモデルを使う場合は LLM_TIMEOUT_SECONDS を長めに設定します。
画面上部の「設定」から、フェーズ別に使うモデルと一問一答の質問を変更できます。質問は選択したペルソナと出力形式に応じた固定テンプレートが表示され、追加質問も下書き生成のブリーフに含まれます。
文体分析結果、取材セッションの回答、完成ブリーフは WORKFLOW_STORE_PATH にJSONとして永続化されます。既定値は data/workflow_store.json です。
保存方式は設定画面の「保存方式」から選べます。UIで変更した内容は data/app_config.json に保存され、サーバー再起動後に反映されます。SQLiteを選んだ場合の既定パスは data/workflow_store.db です。JSON store は互換性のため既定のまま残しています。
開発・検証で強制したい場合は WORKFLOW_STORE_DRIVER=sqlite を指定できます。この環境変数がある場合、設定画面では保存方式がロック表示になります。
フェーズ別モデルの目安:
STYLE_LLM_MODEL: Note記事取得後の文体ガイド整理用。既定は軽量なgemma4:e2b。BRIEF_LLM_MODEL: 深掘り質問生成用。既定は推論力重視のqwen3.6:27b。ARTICLE_LLM_MODEL: 旧/api/generate用。既定は軽量なgemma4:e2b。DRAFT_LLM_MODEL: 一問一答後の最終下書き生成用。既定は日本語下書き品質重視のgemma4:31b。VERIFY_LLM_MODEL: 下書き後の最終一貫性チェック用。既定は軽量なgemma4:latest。EVO_X2_TAILNET_HOST: Tailnet/MagicDNS 上の Evo X2 ホスト名です。既定値はevo-x2.tailb30e58.ts.net。EVO_X2_LLM_BASE_URL: Evo X2 Ollama primary の OpenAI互換APIです。既定値はhttp://evo-x2.tailb30e58.ts.net/v1。LLM_FALLBACK_BASE_URLS: カンマ区切りの fallback chain です。既定は Evo X2 llama.cpp、最後にローカル llama.cpp。STYLE_LLM_FALLBACK_MODELSなど: fallback endpoint ごとのモデル名をカンマ区切りで指定します。
Tailnet primary の接続確認だけ行う場合:
make evo-x2-modelsSSH tunnel を使った個人端末向け診断を行う場合だけ、明示的に SSH ターゲットを使います。これはアプリの primary 経路ではありません。
make evo-x2-ssh-models3,000字前後の統合シナリオを Evo X2 で実行する場合:
make scenario-evo-x2このシナリオは文体分析、一問一答、深掘り、下書き生成を通し、文体スコア80点以上と一定以上の本文量を確認します。
Evo X2 primary とは別に、作業端末上で既に起動済みの llama.cpp fallback だけを検証する場合は専用ターゲットを使います。このターゲットは Ollama や llama-server を起動せず、Evo X2 への fallback chain も無効化します。
まず plan/report だけを作る場合:
make scenario-local-llamacpp-fallback実際に draft 生成まで走らせる場合は、誤って Evo X2 primary 検証と混同しないように明示的な gate が必要です。LOCAL_LLAMACPP_FALLBACK_BASE_URL は loopback の OpenAI互換 /v1 endpoint だけを受け付けます。
RUN_LOCAL_LLAMACPP_FALLBACK_SCENARIO=1 \
LOCAL_LLAMACPP_FALLBACK_BASE_URL=http://127.0.0.1:8081/v1 \
LOCAL_LLAMACPP_FALLBACK_MODEL=qwen3:30b-a3b \
LOCAL_LLAMACPP_FALLBACK_LOAD_FLAGS='--host 127.0.0.1 --port 8081 --alias qwen3:30b-a3b --reasoning off ...' \
make scenario-local-llamacpp-fallback結果は tmp/local_llamacpp_fallback/report.md と tmp/local_llamacpp_fallback/report.json に記録されます。Issue #36 の合格条件は score >= 82.0、keyword_overlap >= 70、runes >= 2800 です。記録テンプレートは docs/validation/issue-36-local-llamacpp-fallback-template.md です。
Gemma4 31B を llama-server で起動します。
llama-server \
--hf-repo ggml-org/gemma-4-31B-it-GGUF \
--hf-file gemma-4-31B-it-Q4_K_M.gguf \
--alias gemma4:31b \
--host 127.0.0.1 \
--port 8081別ターミナルでGoサーバーを起動します。
go run ./cmd/serverブラウザで http://localhost:8080 にアクセスします。
リクエスト:
{
"note_url": "https://note.com/example/n/n123",
"username": "",
"keywords": ["AI", "生産性"],
"theme": "中小企業におけるローカルLLM活用",
"target_audience": "中小企業の経営者",
"exclusions": "過度に専門的な数式",
"style_choice": "ですます調",
"tone_choice": "客観的",
"word_count": 1500,
"article_purpose": "情報提供",
"desired_content": "具体例を含める",
"introduction_points": "読者の課題",
"main_points": "導入手順と注意点",
"conclusion_message": "小さく試す重要性"
}note_url または username のどちらかと、theme が必須です。
成功レスポンス:
{
"draft": "生成されたMarkdown本文"
}draft はNoteにそのまま貼り付けやすいよう、# タイトル から始まるMarkdown本文だけを返します。モデルが前置きやコードフェンスを返した場合は、サーバー側で正規化またはエラーとして扱います。
エラーレスポンス:
{
"error": {
"code": "ARTICLE_GENERATION_FAILED",
"message": "Failed to generate article",
"details": "..."
}
}llama-server の /v1/models を呼び、利用可能なローカルモデルIDを返します。
- このアプリケーションはGoogle Gemini APIを使用しません。
- Note本文取得は公開ページとRSSを優先します。note.comの非公式APIは仕様変更や利用制限のリスクがあります。
- 生成された記事は参考として使用し、公開前に必ず内容を確認してください。
MIT