Gemini API で財務書類を「怪しさ判定」する:スコア付き出力の設計

個人開発の EDINET 分析ツールでは、取得した有価証券報告書の PDF を Gemini に渡して「怪しさ判定」をさせている。 単なる要約ではなく、3段階のスコア(normal / caution / danger) を返させる設計にしたので、その仕組みをまとめる。 なぜスコアが必要か 毎日数十〜数百件の書類が提出される。全部読むのは無理なので、AI に「これは要注意」かどうかを仕分けさせたい。 スコアが danger の書類だけ Discord 通知を飛ばす、といった使い方ができる。 プロンプト設計 プロンプトの末尾に必ずスコアを出力させるよう指示する: 分析の最後に必ず以下の形式でスコアを出力してください: SCORE:normal # 特に問題なし SCORE:caution # 気になる点あり・要確認 SCORE:danger # 重大なリスクの可能性 Gemini はマークダウン形式で分析テキストを返した後、最終行に SCORE:danger のような文字列を出力する。 PDF を渡す方法 @google/generative-ai SDK では PDF を base64 で渡せる: const model = genAI.getGenerativeModel({ model: 'gemini-2.5-flash' }) const result = await model.generateContent([ { inlineData: { mimeType: 'application/pdf', data: pdfBuffer.toString('base64'), }, }, { text: prompt }, ]) 最大 50MB まで渡せるが、大きすぎるとトークン消費が跳ね上がるので注意。 スコアのパース 正規表現で SCORE: 以降を抽出: ...

May 24, 2026 · 1 min

CloudflareアラートをWorker + Gemini APIでDiscordに要約通知する

Cloudflareの通知をDiscord Webhookに流していたら、通知が大量に届くようになってしまった。重要なアラートが埋もれるので、Cloudflare Workers + Gemini APIで要約してから投稿するようにした。 方針 Cloudflareの通知設定で追加できるアラートはとりあえず全部有効にしている。各アラートが実際に役立つかは様子を見ながら判断する予定。 ただしセキュリティアラートはだいたい30分に数回届いたため、現時点では通知をスキップするようにした。それ以外のアラートは引き続き通知して様子見中。 構成 Cloudflare Alert → Worker受信 → フィルタリング(スキップ対象なら早期リターン) → Gemini API で日本語要約 → Discord Webhook に送信 前提 Cloudflare WorkersにDiscord Webhook通知のWorkerが既にある Google AI StudioのAPIキーを持っている モデル選定 Geminiのモデルは料金帯がいくつかある。 gemini-2.5-pro > gemini-2.5-flash > gemini-2.5-flash-lite Cloudflareアラートの要約程度であれば gemini-2.5-flash-lite で十分。一番安い。 最新のモデル名は公式ドキュメントで確認すること。 https://ai.google.dev/gemini-api/docs/models 実装 フィルタリングの考え方 頻度の高いアラートはWorker側でスキップできるようにしている。SKIP_ALERT_TYPES に列挙したタイプが一致した場合、Gemini APIを呼ばずに早期リターンする。不要なAPI呼び出しも減るのでコスト面でも良い。 どのアラートがどの alert_type を持つかはCloudflareの公式ドキュメントで確認できる。 https://developers.cloudflare.com/notifications/notification-available/ Worker コード // スキップしたいアラートタイプ(頻度が高くて邪魔なものを列挙) const SKIP_ALERT_TYPES = [ "security_alerts", // セキュリティアラート:30分に数回来るので無効化中 ]; async function summarizeWithGemini(apiKey, input) { const prompt = `以下のCloudflareアラートを日本語で3行以内に要約してください。重要度(🔴高/🟡中/🟢低)も判定してください。\n\n${input}`; const res = await fetch( `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-lite-preview-06-17:generateContent?key=${apiKey}`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ contents: [{ parts: [{ text: prompt }] }] }) } ); const data = await res.json(); console.log("Gemini response:", JSON.stringify(data)); return data.candidates?.[0]?.content?.parts?.[0]?.text || "要約失敗"; } export default { async fetch(request, env) { if (request.method !== "POST") { return new Response("ok"); } let body; try { body = await request.json(); } catch { return new Response("invalid json", { status: 400 }); } // アラートタイプによるフィルタリング const alertType = body.text?.alert_type || body.alert_type || ""; if (SKIP_ALERT_TYPES.some(t => alertType.includes(t))) { console.log(`Skipped alert type: ${alertType}`); return new Response("skipped"); } // Geminiには常にbody全体を渡す const input = JSON.stringify(body).slice(0, 500); const summary = await summarizeWithGemini(env.GEMINI_API_KEY, input); const message = { username: "Cloudflare", embeds: [{ title: body.text?.title || body.text?.description || "Cloudflare Notification", description: summary, color: 0xF6821F, timestamp: new Date().toISOString() }] }; await fetch(env.DISCORD_WEBHOOK, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(message) }); return new Response("ok"); } } シークレット登録 wrangler secret put GEMINI_API_KEY wrangler secret put DISCORD_WEBHOOK 動作確認 curl -X POST https://<your-worker>.workers.dev \ -H "Content-Type: application/json" \ -d '{"text": {"title": "テスト通知", "description": "これはテストです"}}' スキップ確認: ...

April 12, 2026 · 2 min

AI コーディングエージェントを飼い慣らす:最強の「AGENTS.md」の書き方

AI コーディングエージェントを飼い慣らす:最強の「AGENTS.md」の書き方 近年、Gemini、Claude、Aider といった「自律型 AI コーディングエージェント」が開発現場に浸透しつつあります。彼らは指示一つでファイル構成を理解し、コードを書き、テストを実行して修正まで行います。 しかし、エージェントを使い始めた多くのエンジニアが直面するのが、**「AI エージェントの暴走」**です。 型定義を面倒くさがって any を連発する プロジェクト独自のディレクトリ構造を無視して勝手に utils/ を作る vitest --watch などの終了しないコマンドを叩いてフリーズする 指示していないリファクタリングを始めて関係ないファイルを壊す これらの問題を防ぎ、エージェントを「熟練のペアプロ相手」に変える魔法のファイル、それが AGENTS.md です。本記事では、AI エージェントに守らせるべきルールを定義する AGENTS.md の書き方と、その設計思想を徹底解説します。 なぜ AGENTS.md が必要なのか AI エージェントは、人間が数年かけて培った「プロジェクトの阿吽の呼吸」を知りません。 エージェントに与えられるコンテキスト(ファイル内容や履歴)は有限であり、その中で彼らは「最も確率的に正しそうな推論」を行います。その結果、彼らはしばしば**「最も楽な道(=技術的負債を生む道)」**を選んでしまいます。 AGENTS.md をプロジェクトのルートに配置する理由は、**「エージェントの推論空間に強制的な制約(ガードレール)を設けるため」**です。 なぜその設計にしたか:外部メモリとしての役割 エージェントは毎回ゼロベースで思考するわけではありませんが、多くのファイルを見すぎることで逆に重要なルールを見失う(ロスト・イン・ザ・ミドル現象)ことがあります。AGENTS.md という明確なルールブックを定義し、エージェントの起動時やタスク開始時に必ず読み込ませることで、思考のブレを最小限に抑えることができます。 AGENTS.md に書くべき内容の 4 つの分類 効果的な AGENTS.md は、以下の 4 つのセクションで構成するのがベストプラティスです。 禁止事項 (Prohibitions): 致命的なエラーや環境のハングを防ぐ 命名規則・コーディング基準 (Standards): コードの品質を一定に保つ アーキテクチャ原則 (Architecture): システムの整合性を維持する テスト・検証方針 (Testing): 修正の正しさを担保する それぞれのセクションについて、具体的な記述例を見ていきましょう。 1. 禁止事項 (Prohibitions) エージェントが最もやりがちな「環境破壊」を防ぐための最重要セクションです。 ルール 理由(なぜその設計にするか) インタラクティブコマンドの禁止 npm init や git commit (メッセージ入力待ち) など、ユーザー入力を待つコマンドは CLI エージェントをフリーズさせます。 Watch Mode の禁止 vitest --watch 等はプロセスが終了しないため、エージェントが「完了」を検知できなくなります。 any 型の原則禁止 AI は型の整合性を取るのが面倒になると any で逃げようとします。これは長期的な保守性を著しく低下させます。 勝手な依存関係の追加禁止 package.json を書き換えて新しいライブラリを入れる行為は、セキュリティやビルドサイズに影響するため、人間の許可を必須にします。 実例コード ## 禁止事項 - **コマンド実行**: - `vi`, `nano`, `top` などのインタラクティブなコマンドは実行しない。 - `npm start`, `vitest --watch` などの終了しないプロセスは背景実行 (`&`) するか、単発実行モードを使用すること。 - **TypeScript**: - `any` 型の使用は厳禁。どうしても必要な場合はコメントで理由を明記すること。 - **Git**: - ユーザーの明示的な指示なしに `git commit` や `git push` を行わない。 2. 命名規則・コーディング基準 (Standards) プロジェクトの「見た目」と「一貫性」を守るためのルールです。ここを疎かにすると、エージェントは自分の得意なスタイル(多くの場合、学習データで最も多いスタイル)で書き始めてしまいます。 ...

March 28, 2026 · 2 min

Gemini CLIでExpo Todoアプリを爆速開発した話

やりたかったこと WSL2 環境で Expo を使った Todo アプリを作りたい。ただし、UI ライブラリの選定やナビゲーション設定など、細かい作業は Gemini に任せて効率化したい。 GEMINI.md でルール管理 プロジェクトルートに GEMINI.md を作成し、Gemini に従ってほしいルールを記載しました。 # Gemini AI Coding Rules ## Expo/React Native Specific - Use Expo SDK compatible packages only - Prefer `npx expo install` over `npm install` - Use functional components with hooks ## Expo Specific Rules - Use `@expo/vector-icons` instead of `react-native-vector-icons` - Never use packages that require native linking ## Tech Stack (Fixed) - Expo with TypeScript - React Native Paper for UI - AsyncStorage for persistence このファイルを事前に作っておくことで、Gemini が一貫した品質のコードを生成してくれます。 ...

January 31, 2026 · 2 min

GEMINI.mdでAIに開発履歴を管理させる方法

問題:AIは過去の失敗を忘れる Gemini や ChatGPT などの AI にコード生成を依頼するとき、こんな問題がありませんか? 同じミスを何度も繰り返す 前回指摘したルールを忘れる プロジェクト固有の制約を無視する 毎回「Expo では react-native-vector-icons じゃなくて @expo/vector-icons を使って」と指示するのは面倒です。 解決策:GEMINI.md でルールを管理 プロジェクトルートに GEMINI.md ファイルを作成し、AI に従ってほしいルールをすべて記載します。 # Gemini AI Coding Rules ## General Principles - Always provide complete, working code - Include all necessary imports - Add TypeScript types for all functions ## Expo/React Native Specific - Use Expo SDK compatible packages only - Prefer `npx expo install` over `npm install` ## Expo Specific Rules - Use `@expo/vector-icons` instead of `react-native-vector-icons` - Import example: `import { MaterialCommunityIcons } from '@expo/vector-icons';` AI に指示を出すときは、必ず「GEMINI.md を読んでから実装して」と伝えます。 ...

January 31, 2026 · 3 min