Amazonのアソシエイトとして、当ブログは適格販売により収入を得ています。
この記事は、Geminiとの相談結果が多分に含まれています。
利用する場合は、自己責任でお願いします。
記事の内容は以下のシステムでテストされています。
Ubuntu24.04.4LTS
Ryzen7 8700G(Radeon 780M)
メインメモリ96GB(4800MT/s)
最近はCodexやClaudeCode、GeminiSparkなどクラウドサービスのAIエージェントがありますね。
クラウドAIはかなりのコストを掛けているだけあって性能は抜群です。
ただ自分としては、せっかくPCを自前で用意しているのだから、自分のPCの中だけで完結するエージェントを作ってみたくて、以前からAIエージェントの構築に取り組んでいました。
こういったローカルでAIエージェントを使う理由を挙げれば、「クラウドデータセンターに情報を渡さない」「サブスクリプションの料金がかからない」とかいろいろありますが、自分としてはただの好奇心なのでそういった理由はありません。
10〜20年前は、PCを新調したら今までやっていた重たい3Dゲームを動かし「フレームレートがいくら上がった」みたいなことで一喜一憂していましたが、最近はゲームをやらなくなってきたのでその代わりといったところです。
最初は「vscode + cline」でやろうと思っていたのですが、最小限の機能しかもたない「Pi Coding Agent」に必要な機能を加えていく方が、より理解が深まると考えました。
と、いうわけで「Pi Coding Agent」を扱っていきます。
どんなことにAIエージェントを使うか
どんなことにAIエージェントを使うのかはひとそれぞれでしょう。
今回自分は「ネット上の情報をひろって、それをローカルAIの知識にする」というのをやっていこうと思います。
RAG(Retrieval-Augmented Generation)というやつですね。
ただ、この流れの全部をひとつの記事にすると長くなりすぎるので、今回はネットから情報を拾って「book-to-skill」の概念を使って要約するところまでやります。
流れは5つのステップに別れます。
- Webからの情報の取得
- 情報の構造化
- 構造化されたスキルデータのベクトル化 → 保存
- 検索拡張生成(RAG: Retrieval-Augmented Generation)
- Pi Coding Agentに利用してもらう
最終的に得た知識をエージェントに利用してもらおうと思っています。
チャットで反応するだけではつまらないですし。
今回は「Webからの情報の取得」と「情報の構造化」までやりますね。
最後にllama.cppで簡易テストしてみます。
Pi Coding Agentをインストール
本記事で扱う「Pi(正式名称)」は、便宜上「Pi Coding Agent」と呼ばれることも多いツールです。
本記事では「Pi Coding Agent」で統一します。
ではインストール方法です。
#!/bin/bash
# 1. nvm(Node Version Manager)のインストール
# ※バージョン(v0.40.6)は執筆時点のものです。エラーが出る場合は公式GitHubを確認してください。
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.6/install.sh | bash
# パスを即時反映
source ~/.bashrc
# 2. Node.jsのインストール(常に最新の安定版が入るオプションを使用)
nvm install --lts
# 3. Pi Coding Agentのインストール
npm install -g @earendil-works/pi-coding-agent
# 4. Piの設定ディレクトリ作成
mkdir -p ~/.pi/agent
# 5. ローカルLLM(llama.cpp)の接続設定
cat << 'EOF' > ~/.pi/agent/models.json
{
"providers": {
"llama-cpp": {
"baseUrl": "http://127.0.0.1:8080/v1",
"api": "openai-completions",
"apiKey": "none",
"models": [
{
"id": "gemma-4-26B-A4B-it",
"contextWindow": 262144
}
]
}
}
}
EOF
# 6. Piコーディングの拡張機能(必要な場合)
npm install -g pi-llama-cpp
cat << 'EOF' > ~/.pi/agent/config.json
{
"plugins": [
"pi-llama-cpp"
],
"llamaCpp": {
"serverUrl": "http://127.0.0.1:8080"
}
}
EOF
echo "インストールと設定が完了しました。'pi' コマンドで起動してください。"バージョンは、インストールする時期によってちがいますので

上のリンクで確認してください。
記事を書いている時点での最新が(v0.40.6)となっています。
「5. ローカルLLM(llama.cpp)の接続設定」から先は、自分のllama.cppの環境です。
使っている学習モデルが「gemma-4-26B-A4B-it-qat-GGUF」となっています。
「”baseUrl”: “http://127.0.0.1:8080/v1″」はllama.cppに合わせています。
クラウドAIを使う場合はここは違ってきます。
「”contextWindow”: 262144」は、LLMをエージェントで使う場合、
ネットでのベンチマークでよく見る「4096」とかに設定してしまうと、あっという間にトークンを使い果たしてしまうため、「gemma-4-26b-a4b」の持つ最大値を当てています。
「もっと少なくても大丈夫」という人は、減らしてください。
パフォーマンスの観点からみても少なくした方が生成も速くなるでしょう。
llama.cppのインストールと起動
llama.cppのインストールいついてはこちらの記事を参考にしてください。
今回はvulkanで動かします。
ROCmは導入がメンドイですね・・・。
起動コマンドは、
LOCATE="/media/test/semi_4TB/99_LLMモデル/quantize/gemma-4-26B-A4B-it-qat-GGUF"
MODEL="gemma-4-26B-A4B-it-qat-UD-Q4_K_XL.gguf"
MTP="mtp-gemma-4-26B-A4B-it.gguf"
MMPROJ="mmproj-F16.gguf"
# vulkan -----------------------------------------------------
./llama.cpp/build-vulkan/bin/llama-server -m $LOCATE/$MODEL --port 8080 --host 127.0.0.1 --jinja --reasoning on --spec-draft-model $LOCATE/$MTP --spec-type draft-mtp --spec-draft-n-max 1 --mmproj $LOCATE/$MMPROJ --parallel 1 -ctk q8_0 -ctv q8_0 -fa on -b 2048 -ub 2048
起動コマンドの補足です。
- –reasoning on
- モデルに思考させるかどうか。「off」で動作は高速化しますが、ルール(後述します)を平気で破ったりします。安定動作のため「on」。
- –spec-draft-model (モデルのパス) –spec-type draft-mtp –spec-draft-n-max 1
- ドラフトモデルを配置することで投機的デコードを有効化します。
- 予測トークン数を「1」にしていますが、自分の環境では増やしても速度は上がりませんでした。安定性のため「1」にしています。
- –mmproj (モデルのパス)
- AIエージェントに画像認識の機能を持たせるため。
- 今回の記事で画像認識は使いませんが、今後使うときのために設定
- メモリを圧迫するので、節約したい方は削除して下さい。
- –parallel 1
- 通常この数値を指定しない場合「4」が自動的に設定されます。
- この設定だと、リクエストを同時に4つまで並列でこなせるようになるそうですが、コンテキストを4つに分散することにもなるらしい。
- 個人で使うAIエージェントの場合、シリアルな処理で十分だと思うので「1」に設定しています。
- -ctk q8_0 -ctv q8_0
- コンテキストの量子化設定です。
- 「-ctv」はq4にしても良いみたいですが、「-ctk」は下げないほうが良いとのこと。
- 自分はメインメモリが豊富なのでこの設定です。
- -fa on
- フラッシュアテンションの設定。これを削除しても基本的に「on」になりますが、一応設定。
- -b 2048 -ub 2048
- 「-b」はコンテキストを運ぶ量、「-ub」はコンテキストを処理する量だそうです。
- 推論よりプロンプト処理の速度に影響するようです。使うシステムに適当に合わせてください。
コンテキスト長は設定していません。
コンテキスト長は設定しない場合、モデルの持つ最大値が設定されます。
gemma-4の場合は26万です。
自分はllama.cppを好んで使いますが、「LMStudio」等の方が扱いやすいと思います。
時間があれば、こちらを使った場合も追記します。
Pi Coding Agentにルールを教える
クラウドAIの場合は、適当なプロンプトでも「よしなに」処理してくれますが(「いい感じにして」みたいな)、gemma-4のようなローカルLLMだとあんまり適当だとなにをしでかすかわかりません。
なので、しっかりとルールを設けてあげます。
ルールはマークダウンファイル(〜.mdみたいなやつ)で設定します。
今回使ったのは、
- AGENTS.md(AIの行動規範とプロジェクト定義)
- AIが常に参照する「システムプロンプト」や「ルールブック」として機能します。
- TODO.md(自律化のためのステップ管理)
- AIに「今何をすべきか」を順番に実行させるためのファイルです。
- EXTRACTION_PROMPT.md
- 今回は「book-to-skill」の概念にそってスキルを作ってもらうために設定しました。
- Webから拾ってきた情報をただのテキストファイルにするのではなく、要約し構造化することで、後でエージェントが情報を引っ張りやすくする概念らしい。
- ごめんなさい、まだ良くわかっていません。
以上の3つです。
あ、普通はWebからの情報を取得する場合javascriptとかを使うらしいのですが、自分はjavascriptをまったく知らないので、今回はpythonで書いてもらいます。
AGENTS.md
# Role
あなたは優秀なPythonエンジニアであり、データ抽出のスペシャリストです。
目的指向で動き、コードを書く前に計画を立て、テスト駆動で開発を進めます。
# Environment
- OS: Ubuntu 24.04 LTS
- CPU: Ryzen 7 8700G
- RAM: 96GB
- GPU: ディスクリートGPUなし(CPUベースでの処理を前提とする)
- 仮想環境・パッケージ管理: `uv` を厳格に使用すること。
# Project Goal: Web-to-Skill Extractor
ウェブ上の記事から情報を取得し、単なるHTMLのダンプではなく「意味のあるテキスト構造」として抽出・保存するツールを作成します。
最終的には、別ファイル `EXTRACTION_PROMPT.md` の定義に従ってデータを構造化(book-to-skillの思想の応用)することが目標です。
# User Interaction and Execution Permissions
- **言語設定:** 思考(Thought)プロセスは英語で行っても構いませんが、ユーザーとのチャット(Chat)の出力は必ず日本語で行ってください。
- **自動実行の許可:** 現在のプロジェクトフォルダ内における `uv` を使用した環境構築(インストール等)、ファイルの作成・修正、およびスクリプトの実行については、ユーザーの許可を求めずに自動(自律的)で行ってください。
- **事前の許可が必要な操作:** `sudo` を伴うコマンドの実行や、現在のプロジェクトフォルダより外側(上位ディレクトリなど)へのアクセス・ファイル操作を行う場合は、勝手に実行せず必ず事前にユーザーへ許可を求めてください。
- **コードのチャット出力制限:** ファイルへの自動書き込み・実行とは別に、チャット画面上に直接長文のコードを出力して提示したい場合は、これまで通り勝手に出力せず「コードを出力しますか?『はい』『いいえ』」と事前に尋ねてください。
# Technical Guidelines
1. **仮想環境の操作**:
- パッケージの追加には必ず `uv add <package>` を使用してください。
- スクリプトの実行には必ず `uv run <script.py>` を使用してください。
- 決して `pip install` や生の `python` コマンドを使用しないでください。
2. **抽出アプローチ**:
- 以前のような非効率なツール(単純な正規表現や標準ライブラリのみの力技)は避けてください。
- 記事本文の抽出には、ノイズ(広告、ナビゲーション等)を自動除去できるモダンなライブラリ(例: `trafilatura` 等)の採用を検討し、堅牢な処理を実装してください。
3. **ファイル出力とコンソール出力の制限(重要)**:
- 取得したデータは、人間が読みやすく後段のAI処理に回しやすいマークダウン形式(.md)またはテキスト形式(.txt)で `output/` ディレクトリ等に保存してください。
- **スクリプトのテスト実行時、長文のテキスト(Webページの本文など)をそのまま `print()` で標準出力に出さないでください。** ターミナルが長文で埋め尽くされると、あなた自身(AI)のコンテキスト上限を超えてシステムがクラッシュする原因になります。確認のために出力が必要な場合は、`print(content[:200] + "...")` のように最初の200文字程度にスライスしてください。
# Workflow Rules
1. 常に `TODO.md` を読み、現在のタスク(未完了の最上位項目)を特定してください。
2. タスクを実行するために必要なコードを書き、`uv run` でテストを実行してください。
3. エラーが発生した場合は、ログを解析し、自己修復を行ってから再テストしてください。
4. テストが成功し、タスクの目的が達成されたら、`TODO.md` の該当項目にチェックボックス `[x]` を入れ、次のタスクに進んでください。
5. ユーザーからの明示的な指示がない限り、勝手に `TODO.md` の範囲外の新しい機能を実装しないでください。TODO.md
# Web-to-Skill Extractor 開発ステップ
## Phase 1: 基礎的なWeb情報取得ツールの構築
- [ ] 1. プロジェクトの初期化
- [ ] 2. コア抽出ロジックの実装
- [ ] 3. テストの実行
- [ ] 4. ファイル保存機能の追加
## Phase 2: LLMによる構造化・解析機能(book-to-skill化)の実装
- [ ] 5. LLM通信用パッケージの追加
- ローカルのllama.cppサーバーと通信するために、`uv add openai` を実行してOpenAI公式パッケージを追加する。
- [ ] 6. LLM連携ロジックの実装
- Phase 1で抽出したテキストと、プロジェクトルートにある `EXTRACTION_PROMPT.md` の内容を読み込む。
- OpenAI互換API(ベースURL: `http://localhost:8080/v1`、ダミーAPIキー)を使用して、ローカルのLLMに処理をリクエストする関数を作成する。
- [ ] 7. 実行フローの統合と保存機能の拡張
- メインスクリプトを修正し、「Web抽出 → LLM解析」の連携フローを構築する。
- LLMから返ってきた結果を `{title}_skill.md` のような別ファイルとして `output/` に保存する。
- [ ] 8. 最終テストの実行
- 再度任意のURLでテストを行い、LLMによって構造化されたMarkdownファイルが正常に生成されるか確認する。
- ※引き続き、長文のコンソール出力(`print()`)は避けること。EXTRACTION_PROMPT.md
# Instruction
あなたは「情報」を「実践可能なスキル」にコンパイルする熟練の知識抽出エンジニアです。
入力されたWeb記事のテキストから、単なる要約(Summary)ではなく、読者が具体的な行動に移せる「スキルセット(Skill)」として以下の構造で抽出・再編成してください。
記事内の広告、筆者の個人的な雑談、ナビゲーションなどのノイズは完全に無視し、価値のある情報のみに焦点を当ててください。
# Output Structure
以下のMarkdownフォーマットに厳密に従って出力してください。
## 1. コア・コンセプト (Core Concept)
- この記事が主張している最も重要な「考え方」や「フレームワーク」に名前を付け、その本質を1〜2文で定義してください。
## 2. 適用トリガー (When to Use)
- どのような状況、課題に直面したとき、またはどのような文脈でこの知識を呼び出して使うべきか、具体的な条件を箇条書きで抽出してください。
## 3. 実践ステップ (Actionable Steps)
- この知識を実際に適用するための具体的な手順を、論理的な順序(Step 1, Step 2...)で抽出してください。抽象的な精神論ではなく、物理的・具体的な行動に落とし込んでください。
## 4. アンチパターン (Anti-Patterns)
- 著者が警告している「やってはいけないこと」「よくある失敗」「この手法が機能しない条件」を抽出してください。
## 5. インサイト (Key Insights)
- 単なる事実の羅列を超えた、著者の深い洞察や、パラダイムシフトを起こすような強力な引用・考え方を1〜2点抽出してください。それでは、エージェントを動かすためのプロジェクトフォルダを作っていきます。
# プロジェクトディレクトリの作成と移動
mkdir -p $HOME/install/tool_creation_test
cd $HOME/install/tool_creation_test
# uvで仮想環境を初期化
uv initルートディレクトリに「install/tool_creation_test」というフォルダが出来ると思うので、以下のようにファイルを配置。

AIエージェントを動かそう!
この、「tool_creation_test」ディレクトリでターミナルを開き、「pi」コマンドで「Pi Coding Agent」を立ち上げ、以下のプロンプトでAIエージェントを動かしていきます。
Webから情報を拾ってきたテキストを構造化するツール自体を、AIエージェントに作ってもらいます。
が、まずはちゃんとWebから情報が引っ張ってこれるかテストします。
これを「フェーズ1」とします。
現在のディレクトリにある `AGENTS.md` と `TODO.md` を読み込んで、ルールと現在のタスクを理解してください。
今回は「Phase 1: 基礎的なWeb情報取得ツールの構築」に完全集中して開発を行います。
(※注意:Phase 2のLLMによる構造化・解析機能は次回実装します。今回はLLMに関する処理を一切実装せず、Webからノイズのない純粋な本文テキストを抽出して保存する機能のみを完成させてください。)
開発中の自律テストには、以下のURLを使用してください:

ドラゴンクエスト - Wikipedia
AGENTS.mdで許可されている自動実行の権限(uv環境でのインストールやファイル操作など)を活用し、自律的に開発とテストループを進めてください。各ステップが完了するごとに `TODO.md` にチェックを入れ、Phase 1の完了を目指してください。それでは開始してください。ちなみにテストとして拾ってくる情報は以下です。

なつかしの「ドラクエ1」。では、いってみましょう!
メインメモリの使用量が大変なことになっています。



次はフェーズ2。
プロンプトは以下のとおりで実行しています。
現在のディレクトリにある TODO.md と EXTRACTION_PROMPT.md を新しく読み込んで、内容を理解してください。
今回は「Phase 2: LLMによる構造化・解析機能(book-to-skill化)の実装」に完全集中して開発を行います。
【LLM(llama.cpp)サーバーの接続情報】
このツールが内部でLLMを呼び出すための設定です。
- ライブラリ: `openai` を使用
- base_url: "http://127.0.0.1:8080/v1"
- api_key: "dummy" (ローカルなので適当な文字列でOK)
- model: "default" (何でもOK)
開発中の自律テストには、引き続き以下のURLを使用してください:

ドラゴンクエスト - Wikipedia
※注意:AGENTS.mdのルール通り、長文のコンソール出力(print)を行うとあなた自身がクラッシュしてしまうため、処理結果の全体は必ずファイル保存のみにとどめ、コンソールには進捗や要約(最初の200文字程度)のみを表示してください。
それでは、TODO.mdのPhase 2(ステップ5以降)を自律的に進めてください。各ステップが完了するごとにTODO.mdにチェックを入れてください。開始してください。長いのでふたつに分けました。


llama.cppでテスト
出来上がった「〜raw.md」と「〜skill.md」を使ってllama.cppがちゃんと読めるかテストしてみます。
「.md」ファイルは自分にはただのテキストファイルにしか見えないので、そりゃllama.cppも読めるだろと思うのですが、ここで躓いたらこのさき上手くいくはずありませんからね。
ということで、テストしている動画です。
途中「〜raw.md」と「〜skill.md」ファイルの読み込みにかなりの時間がかかります。
その時は「2:19」まで飛ばしてください。
最後に
今回はここまでですが、Ryzen7 8700Gの内蔵GPUでも一応ローカルAIエージェントとして動くことがわかりました。
内蔵GPUの性能はメインメモリとの転送帯域幅で決まるところがありますが、自分が使っているのは「4800MT/s」と多分DDR5としては最遅です。
ただ、使用量は32GBを超えていたので容量には注意です。
特に最近はメモリがバカ高いので。
今回は以上です。




コメント