GEMINI LABEN
NANOLITE — Nano Banana 2 Liteが登場しました。Googleで最も速く、最もコスト効率の高いGemini Imageモデルで、軽量な画像生成を安く回したい用途に向いていますOMNIFLASH — Gemini Omni Flashがpublic previewになりました。ネイティブにマルチモーダルなモデルで、企業や開発者が独自の動的な動画ワークフローを構築できますAGENTS — Managed Agentsが拡張されました。background: trueでサーバー側の非同期実行とポーリング、リモートMCPサーバー連携、対話をまたぐ認証情報のリフレッシュに対応しますMEMORY — Memory BankのIngestEvents APIが一般提供になりました。イベントの取り込みとメモリ生成を分離し、コンテンツを継続的にストリームできますTHROUGHPUT — Provisioned Throughputで、同一モデル・同一リージョンに対して最大7件の保留オーダーを提出できるようになりましたDEPRECATE — 画像生成モデルは8月17日に、Gemini Enterprise Agent PlatformのGrok 4.1系は8月20日に停止される予定ですNANOLITE — Nano Banana 2 Liteが登場しました。Googleで最も速く、最もコスト効率の高いGemini Imageモデルで、軽量な画像生成を安く回したい用途に向いていますOMNIFLASH — Gemini Omni Flashがpublic previewになりました。ネイティブにマルチモーダルなモデルで、企業や開発者が独自の動的な動画ワークフローを構築できますAGENTS — Managed Agentsが拡張されました。background: trueでサーバー側の非同期実行とポーリング、リモートMCPサーバー連携、対話をまたぐ認証情報のリフレッシュに対応しますMEMORY — Memory BankのIngestEvents APIが一般提供になりました。イベントの取り込みとメモリ生成を分離し、コンテンツを継続的にストリームできますTHROUGHPUT — Provisioned Throughputで、同一モデル・同一リージョンに対して最大7件の保留オーダーを提出できるようになりましたDEPRECATE — 画像生成モデルは8月17日に、Gemini Enterprise Agent PlatformのGrok 4.1系は8月20日に停止される予定です
記事一覧/API / SDK
API / SDK/2026-05-27中級

Gemini API で個人ブログの内部リンク整合性を2ヶ月チェックさせた所感

Lab 系4サイトの内部リンク整合性チェックを2ヶ月 Gemini に任せて運用した実装メモ。grep だけでは拾えなかった文脈不一致を Gemini 2.5 Flash でどう仕分けたか、運用コストとつまずいた点を書きました。

Gemini API191Gemini 2.5 Flash5個人開発91内部リンク運用自動化2コンテンツ品質

Lab 系の 4 サイトを並行運用していると、記事数が増えるほど厄介になる作業が一つあります。MDX 本文に書いた内部リンクが、実在する記事を指しているかどうかの確認です。Claude Lab と Gemini Lab だけで合わせて 1,700 本近く、4 サイト合計では 3,000 本を超える記事があり、Markdown 本文の中に ~ 形式のリンクが散在しています。ビルド時にいくつかの仕組みで弾くことはできますが、それでも拾い切れない日があります。

この内部リンクの整合性チェックを、2 ヶ月ほど Gemini 2.5 Flash に任せてみました。期待した精度には届かない場面もありましたが、運用に組み込むと「自分では絶対に気づかない種類の不整合」を拾ってくれるという発見がありました。今日はその実装と、運用してみて見えてきた所感をまとめます。

なぜ Gemini に任せたか

最初は単純な grep スクリプトで充分だと思っていました。コンテンツディレクトリから /articles/(category)/(slug) 形式の文字列を全部抽出し、対応する MDX ファイルが実在するかを確認すれば終わりです。実際、それで 95% のケースは弾けます。

ところが残りの 5% に、機械的なファイル存在チェックだけでは見抜けないものが混ざります。例を 3 つ挙げます。

  1. リンク先のスラッグは実在するが、書いている文脈とまったく関連しない記事を指している
  2. アンカーテキストが「Gemini Code Assist の導入」なのに、リンク先は「Gemini for Workspace の請求設定」になっている
  3. 同じトピックを扱った記事が 3 本ある中で、最新版ではない古い記事に飛ばしている

このあたりは「文脈を読む」必要があり、grep の領分を越えます。両家の祖父が宮大工だったこともあって、組み上げたものが何十年も残るかどうかは細部の仕舞いで決まる、という感覚が体に残っています。リンクの精度は読者の信頼に直結するので、ここに時間を使うのは惜しくないと判断しました。

構成

実装は単純です。記事ごとにリンクを抽出し、リンク先記事の冒頭と現在記事の前後文脈を一緒に Gemini に渡し、関連度を JSON で返してもらいます。

import google.generativeai as genai
import re, pathlib, json
 
MODEL = "gemini-2.5-flash"
LINK_RE = re.compile(r"\[([^\]]+)\]\(/articles/([^/]+)/([^)]+)\)")
 
def collect_links(article_path: pathlib.Path):
    text = article_path.read_text(encoding="utf-8")
    return [
        (m.group(1), m.group(2), m.group(3), text)
        for m in LINK_RE.finditer(text)
    ]
 
def review_link(anchor, category, slug, body, target_excerpt):
    prompt = f"""
あなたは技術ブログのエディタです。次のリンクの妥当性を JSON で返してください。
 
アンカーテキスト: {anchor}
元記事の前後200字: {body[:200]}
リンク先記事の冒頭400字: {target_excerpt[:400]}
 
評価軸:
- relevance: 0.0〜1.0 の数値(文脈関連性)
- anchor_match: true/false(アンカーがリンク先の内容と一致するか)
- replacement_hint: 不一致なら何に置き換えるべきかの示唆(文字列、なければ空)
 
JSON だけを返してください。
"""
    model = genai.GenerativeModel(
        MODEL,
        generation_config={"response_mime_type": "application/json"},
    )
    resp = model.generate_content(prompt)
    return json.loads(resp.text)

response_mime_type="application/json" を有効にしておくと、後段の json.loads で詰まることがほとんどなくなります。最初は gemini-2.5-pro で全リンクを回していましたが、判定の質と単価のバランスを見ると Flash のほうがこの用途には合いました。Pro に再投票させるのは relevance が 0.3〜0.7 のグレーゾーンに入った 5% 程度に絞り、明確な不一致は Flash で即決しています。

判定結果は YAML ログとして書き出し、サイトごとの _link_review/YYYY-MM-DD.yml に貯めています。同じ URL を翌日にもう一度回すような無駄を避けるため、過去 7 日間に判定済みのリンクはスキップする仕掛けを足しました。

2ヶ月運用して見えたこと

毎晩 02:30 JST にバッチで走らせ、当日 push された記事の内部リンクだけを対象にしています。4 サイト合算で 1 日あたりおよそ 60〜80 リンク。token 単価で見るとひと月 1,000 円前後で済んでいます。個人開発の運用費としては許容範囲です。

明確な誤判定もありました。Gemini は同義語に厳しすぎる傾向があり、「Function Calling」と「ツール呼び出し」を別物として扱ってしまう日があります。閾値を緩めると今度はノイズが増える。このバランス調整は今も手で詰めている最中です。

一方で、想定以上の収穫もありました。たとえば「公式ドキュメントへの外部リンクが古いバージョンの URL を指している」というケースを、内部リンクのチェック中に副次的に拾ってくれたことがあります。プロンプトには「内部リンクの妥当性を見て」としか書いていないのですが、リンク先の冒頭を読み込んだ際に「このページは古いと注釈が出ています」と Gemini が返してきました。これは grep ではまず気づけません。

もう一つ、自分の記事の癖を Gemini に客観視してもらえた点も収穫でした。「同じ記事で『個人開発』『個人事業』『インディーデベロッパー』を混在させている」「アンカーテキストにスラッグそのまま使っている箇所がある」といった指摘が、レビュー結果のメタコメントとして時折出てきます。指示していないのに拾ってくれる、というのは Pro よりも Flash の方が頻度が高かったように感じます。

自分の運用に取り入れるなら

同じ仕組みを試したい場合、いきなり全記事に流すのではなく、まず直近 1 ヶ月の記事に絞ることをお勧めします。古い記事までスコープを広げると、過去の自分が書いた文体や用語の揺れに引っ張られて、Gemini の判定が安定しません。

もう一つ大事だと感じたのは、判定結果を「自動修正」ではなく「レビュー候補リスト」として書き出すことです。テキストの差し替えは最終的に人の目で確認した方が安全で、特に技術用語の精度を保ちたいブログでは差し戻しの判断は自分でやる方がしっくり来ます。私は朝のコーヒーを淹れている数分で前夜のレビュー候補リストに目を通し、明らかな不一致だけその場で修正する運用に落ち着きました。

コスト管理の面では、gemini-2.5-flash-lite も一度試しました。単価は確かに安いのですが、文脈関連性の判定がブレやすく、relevance のスコアが 0.5 付近に偏る傾向が出ました。リンク整合性チェックのように「白黒つけたい」用途では、Flash で固定したほうが結果的に運用が楽でした。

次に取り組むこと

次は同じパイプラインを Crashlytics のクラッシュレポート分類に流用しようと考えています。Claude in Chrome で取得した日次レポートを Gemini に投げて、影響範囲と緊急度を分類させる仕組みです。2014 年から個人でアプリを出してきて、何度かクラッシュ対応が後手に回った苦い経験があるので、ここは自動化の優先度が高い領域だと感じています。

リンク整合性チェックは目立たない作業ですが、地味に効きます。読者がリンクをクリックして「期待した内容と違う」と感じる回数が少しでも減れば、それは結果的に検索エンジンが評価する滞在時間にも返ってくるはずです。同じような運用をされている方の参考になれば嬉しいです。最後までお読みいただきありがとうございました。

シェア

お読みいただきありがとうございます

Gemini Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

API / SDK2026-06-20
Gemini のモデル非推奨を CI で先回りして止める仕組み
ハードコードされた Gemini モデルIDを CI で走査し、シャットダウン期限が近いものを残り日数つきで検知して赤くする仕組みを、動くコードで組み立てます。
API / SDK2026-05-06
Gemini 2.5 Flash を1ヶ月使い続けた個人開発者の正直レポート — 費用・速度・品質の実態
個人開発者がGemini 2.5 Flashを1ヶ月間実運用した費用・速度・品質の実態レポート。無料枠の消費ペース、Pro切り替えの判断基準、コスト最小化コードまで実測値で解説します。
API / SDK2026-07-19
静止画か短い動画か — Nano Banana 2 Lite と Omni Flash のコスト桁差で機能の置き所を決める
壁紙アプリの目玉アセットを静止画にするか短い動画にするかで手が止まったとき、決め手になったのは好みではなくコストの桁でした。Nano Banana 2 Lite と Omni Flash の単価を同じ土俵に並べ、動く意思決定関数まで落とし込みます。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →