1
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?

URL を登録したら AI が動くアプリを作った話(LangChain × Django)

1
Last updated at Posted at 2025-12-21

以下の記事の続きです。

はじめに

2025/12/21 にポケフォリオというサイトをリリースしました。
ポケモンランクマッチのパーティの構築記事ブログを登録、検索できるサイトになります。

この記事では、URL登録機能について、解説します。
URL登録機能にはAIエージェントを構築して、登録作業を自動化しています。

作ったもの

構築記事(元記事)を読み込んで、概要ページを作成します。
イメージは↓のように文字だけの記事から画像付きのページが出来上がります。
image.png

仕組みとしてはユーザーがURLを登録する形を取っています。

①ユーザーが記事URLを登録します
※規約等書いています。
スクリーンショット 2025-12-21 19.39.56.png

②AIが分析しパーティが登録されます。
image.png

詳細画面を見る記事の概要が出来上がります。
image.png
ついでに英語も出来上がります。
image.png

苦労ポイント

  • 概要記事を表示するための仕組み
  • 精度を上げること
  • AIとルールベースの組み合わせ

概要記事を表示するための仕組み(django)

AIが解析したものを単に表示すると、統一性がないサイトになると思い、まずは表示する仕組みを作りました。

ポケモン、アイテム、わざなど決まっている要素については初期データとして整備し、それぞれにidを付与して記事はidを登録する方式にしました。

idは以下のイメージです。

pokemon.json
[
    {"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":""}
]
item.json
[
    {"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"},
    ....
]
move.json
[
    {"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体

管理用の画面からぽちぽち選択すると
image.png

以下が出来上がるという仕組みになり。統一感が出ました。
image.png

※管理用の画面は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に対応させる方針です。
image.png

今回は、やることが決まっているので、AIに自律的にタスク分解してもらう必要はないです。(逆にハルシネーションリスクになります。)

メリットとして

  • ユーザーデータなど誤って欲しくない情報は、AIに与えずに処理をすることが可能。
  • スクリプト的に動かせるので、定期実行も容易にできる。

があります。

この仕組みで記事からデータの構造化をしていました。

最後におまけ

AI構築フレームワークはOpen AI Agent SDKからLangCheinに乗り換えています。
Geminiの方が安かったというのもありますが、真の目的は、

AIモデルごとの性能評価することです。

正直ベンチマークで評価されているのはみますが、実感湧かないので、もっと身近な例で語りたいと思いました。

AIモデルの比較ならOpen AIが開発しているものを使うとフェアな評価にならないと思い、LangCheinに変更しました。

AIが登録した後、ユーザーが修正できるようにし、その修正ログを取得しています。
修正ログから、長文が苦手、idの指定が苦手とかそういうことがわかると思っています。

最後にめっちゃおまけ

サイトリリースしましたが、広告をつけたくないです。

  • AIに聞く場合、ページが開かないため、広告での収益に将来性がない
  • UXの低下
    私の経済的な体力次第でサービス存続が決まるかも…
1
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
1
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?