以下の記事の続きです。
はじめに
2025/12/21 にポケフォリオというサイトをリリースしました。
ポケモンランクマッチのパーティの構築記事ブログを登録、検索できるサイトになります。
この記事では、URL登録機能について、解説します。
URL登録機能にはAIエージェントを構築して、登録作業を自動化しています。
作ったもの
構築記事(元記事)を読み込んで、概要ページを作成します。
イメージは↓のように文字だけの記事から画像付きのページが出来上がります。

仕組みとしてはユーザーがURLを登録する形を取っています。
詳細画面を見る記事の概要が出来上がります。

ついでに英語も出来上がります。

苦労ポイント
- 概要記事を表示するための仕組み
- 精度を上げること
- AIとルールベースの組み合わせ
概要記事を表示するための仕組み(django)
AIが解析したものを単に表示すると、統一性がないサイトになると思い、まずは表示する仕組みを作りました。
ポケモン、アイテム、わざなど決まっている要素については初期データとして整備し、それぞれにidを付与して記事はidを登録する方式にしました。
idは以下のイメージです。
[
{"id":1,"japanese_name":"フシギダネ","japanese_forme_name":"","english_name":"Bulbasaur","english_forme_name":""},
{"id":2,"japanese_name":"フシギソウ","japanese_forme_name":"","english_name":"Ivysaur","english_forme_name":""},
{"id":3,"japanese_name":"フシギバナ","japanese_forme_name":"","english_name":"Venusaur","english_forme_name":""},
....
{"id":1252,"japanese_name":"モモワロウ","japanese_forme_name":"","english_name":"Pecharunt","english_forme_name":""}
]
[
{"id":1,"japanese_name":"とくせいガード","english_name":"Ability Shield"},
{"id":2,"japanese_name":"きゅうこん","english_name":"Absorb Bulb"},
{"id":3,"japanese_name":"だいこんごうだま","english_name":"Adamant Crystal"},
{"id":4,"japanese_name":"こんごうだま","english_name":"Adamant Orb"},
{"id":5,"japanese_name":"バンジのみ","english_name":"Aguav Berry"},
{"id":6,"japanese_name":"ふうせん","english_name":"Air Balloon"},
....
]
[
{"id":1,"japanese_name":"あくまのキッス","english_name":"Lovely Kiss"},
{"id":2,"japanese_name":"あなをほる","english_name":"Dig"},
{"id":3,"japanese_name":"あばれる","english_name":"Thrash"},
....
{"id":920,"japanese_name":"レイジングブル","english_name":"Raging Bull"}
]
例えば、パーティ記事は以下のようなイメージになる
(ポケモンid、アイテムid、わざ1のid、わざ2のid、わざ3のid、わざ4のid...)×6体
※管理用の画面はDjangoにデフォルトでついているものになります。管理用の画面が強力であることがDjangoの選定理由です。
ではこのポチポチ登録する作業をAIにやらせようとしましたが、課題がありました。
精度を上げること
AIにやらせたいこととしては、以下の通り
- AIにて記事を分析
- データを構造化
- サイトで定義したIDを特定しサイトに登録
これが非常に難しかった。
検証した順に、概要的に解説します。
まずはRAGで検証(Open AI Agent SDK + gpt-4o-mini)
まず最初に、すべてのidが記載されたJSONをベクターストア化(いわゆるRAG)してAIに参照させましたが、精度は体感50%も正解しないものでした
次にポケモン、アイテム、わざのそれぞれのJSONを分割し、役割分担する形にもしましたが、精度は体感70%程度でした
詳しい構成は、記事にしています。
さらに、コストが非常にかかるという問題がありました。ベクターストアの読み込みにかなり大きなトークンを消費しました。(当時は、gpt-4o-miniで検証)
1記事40円と、とても運用に耐えるものではなかったです。(家計に直撃)
※RAGという技術が悪いというわけでなく、用途が違っていたということです。
APIで都度データをとる方式(LangChain + Gemini-2.5-flash)
次はAPIでサイトから必要なものだけ取得する方式にしました。
まずは、AIにポケモン名をAPI経由で検索させます。
{
"pokemon_id": 35,
"national_number": 23,
"national_sub_number": 0,
"name": "アーボ",
}
そのポケモンidからそのポケモンに関連のあるidをAPI経由取得します。
{
"pokemon_id": 35,
"name": "アーボ",
"forme_name": "",
"type1_name": "どく",
"type2_name": null,
"abilities": [
{"ability_id": 22, "ability_name": "いかく"},
{"ability_id": 61, "ability_name": "だっぴ"},
{"ability_id": 127, "ability_name": "きんちょうかん"}
],
"moves": [
{"move_id": 142, "move_name": "まきつく"},
{"move_id": 109, "move_name": "にらみつける"},
{"move_id": 101, "move_name": "どくばり"}
]
}
このデータをプロンプトに入れることで、ノイズが減ります。
具体的にいうと、"アーボ"は"10まんボルト"を覚えないので、idデータを与えないということです。
必要な情報だけ与えるということにより以下の効果がありました。
- トークンコストの最適化(1記事40円から1円程度へ)
- 精度の向上(体感70%から90%へ)
APIは一部だけ一般に公開しています。
https://poke-trainerslink.com/ja/gen9/api/docs/
※JWT認証が実装されており、実際にAIで利用しているものは使えません。
MCPサーバーは構築していません。LangCheinで、APIを叩くツールを定義しています。理由はMCPを利用するメリットがないからです。
AIの使い方
全てを自律的にAIで対応させることはしませんでした。
今回は、やることが決まっているので、AIに自律的にタスク分解してもらう必要はないです。(逆にハルシネーションリスクになります。)
メリットとして
- ユーザーデータなど誤って欲しくない情報は、AIに与えずに処理をすることが可能。
- スクリプト的に動かせるので、定期実行も容易にできる。
があります。
この仕組みで記事からデータの構造化をしていました。
最後におまけ
AI構築フレームワークはOpen AI Agent SDKからLangCheinに乗り換えています。
Geminiの方が安かったというのもありますが、真の目的は、
AIモデルごとの性能評価することです。
正直ベンチマークで評価されているのはみますが、実感湧かないので、もっと身近な例で語りたいと思いました。
AIモデルの比較ならOpen AIが開発しているものを使うとフェアな評価にならないと思い、LangCheinに変更しました。
AIが登録した後、ユーザーが修正できるようにし、その修正ログを取得しています。
修正ログから、長文が苦手、idの指定が苦手とかそういうことがわかると思っています。
最後にめっちゃおまけ
サイトリリースしましたが、広告をつけたくないです。
- AIに聞く場合、ページが開かないため、広告での収益に将来性がない
- UXの低下
私の経済的な体力次第でサービス存続が決まるかも…



