[{"content":"","date":"6月 2, 2026","externalUrl":null,"permalink":"/en/tags/binary-tree/","section":"Tags","summary":"","title":"Binary Tree","type":"tags"},{"content":"","date":"2026年6月2日","externalUrl":null,"permalink":"/ja/","section":"Hassenfeld","summary":"","title":"Hassenfeld","type":"page"},{"content":"","date":"2026年6月2日","externalUrl":null,"permalink":"/ja/series/leetcode/","section":"Series","summary":"","title":"LeetCode","type":"series"},{"content":"","date":"2026年6月2日","externalUrl":null,"permalink":"/ja/tags/leetcode/","section":"Tags","summary":"","title":"LeetCode","type":"tags"},{"content":"二分木は、以下を含みます：\nノード要素； 子ノードを指すポインタ Left； もう一方の子ノードを指すポインタ Right。 LeetCodeにおける木の表現方法：\nstruct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) {} }; leetcode104. 二分木の最大深さ # int maxDepth(TreeNode* root) { if(root==nullptr){ return 0; } return max(maxDepth(root-\u0026gt;left),maxDepth(root-\u0026gt;right))+1; } 最初は左右の子木の深さを再帰的に計算します #再帰 max() は最大深さ +1 を返します leetcode226. 二分木の反転 # TreeNode* invertTree(TreeNode* root) { if(root==nullptr){ return nullptr; } TreeNode* temp; temp=root-\u0026gt;left; root-\u0026gt;left=root-\u0026gt;right; root-\u0026gt;right=temp; invertTree(root-\u0026gt;left); invertTree(root-\u0026gt;right); return root; } 二分木を再帰的にトラバースし、各ノードの左右の子ノードを入れ替えることで、二分木の鏡像（ミラー）を生成することを検討します。\n時間計算量：O(n) 空間計算量：O(n) leetcode101. 対称な二分木 # bool isSymmetric(TreeNode* root) { if(root==nullptr){ return true; } return isMirror(root-\u0026gt;left,root-\u0026gt;right); } bool isMirror(TreeNode* root1,TreeNode* root2){ if(root1==nullptr\u0026amp;\u0026amp;root2==nullptr){ return true; } if(root1==nullptr||root2==nullptr||root1-\u0026gt;val!=root2-\u0026gt;val){ return false; } return(isMirror(root1-\u0026gt;left,root2-\u0026gt;right)\u0026amp;\u0026amp;isMirror(root1-\u0026gt;right,root2-\u0026gt;left)); } 時間計算量：O(n) 空間計算量：O(n) 関数 isSymmetric() :\n特殊ケースの処理：根ノード root が空の場合は、直接 true を返します。 戻り値：isMirror(root-\u0026gt;left, root-\u0026gt;right) の結果。 関数 isMirror()：\nまず、現在の左右の2つのノードが対称条件を満たしているか判断します。 次に、これら2つのノードの子ノードである L.left と R.right が対称か、また L.right と R.left が対称かを判断します。 #再帰 ![[対称二分木.png|697]] ","date":"2026年6月2日","externalUrl":null,"permalink":"/ja/posts/20260602-leetcode.binarytree/","section":"記事","summary":"","title":"LeetCode.二分木","type":"posts"},{"content":"","date":"2026年6月2日","externalUrl":null,"permalink":"/ja/series/","section":"Series","summary":"","title":"Series","type":"series"},{"content":"","date":"2026年6月2日","externalUrl":null,"permalink":"/ja/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":"","date":"2026年06月02日","externalUrl":null,"permalink":"/tags/%E4%BA%8C%E5%8F%89%E6%A0%91/","section":"Tags","summary":"","title":"二叉树","type":"tags"},{"content":"","date":"2026年6月2日","externalUrl":null,"permalink":"/ja/tags/%E4%BA%8C%E5%88%86%E6%9C%A8/","section":"Tags","summary":"","title":"二分木","type":"tags"},{"content":"単方向連結リストの各ノード（node）は構造体ポインタであり、以下を含みます：\nノードの要素データ； 次のノードのポインタアドレス。 LeetCodeにおける連結リストの表現方法：\nstruct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(nullptr) {} }; leetcode206. 連結リストの反転 # 反復法 # ListNode* reverseList(ListNode* head) { ListNode *head_prev = nullptr, *head_next; while (head) { head_next = head-\u0026gt;next; head-\u0026gt;next = head_prev; head_prev = head; head = head_next; } return head_prev; } 時間計算量：O(n) 空間計算量：O(1) 再帰法 # ListNode* reverseList(ListNode* head, ListNode* head_prev = nullptr) { if (head == nullptr) { return head_prev; } ListNode* head_next = head-\u0026gt;next; head-\u0026gt;next = head_prev; return reverseList(head_next, head); } 時間計算量：O(n) 空間計算量：O(n) return reverseList(head_next, head);\nこれは末尾再帰形式です。 #末尾再帰 #再帰 「次に処理するノード」(head_next) を新しい head として渡します。 「現在のノード」(head) を次回の再帰の head_prev として渡します。 ノート 反復法では、ListNode *head_prev = nullptr は関数内部にあります。再帰法では、ListNode *head_prev = nullptr は関数の引数内にあります。 ・反復法：今回の関数呼び出し内でのみ存在し、呼び出しは一度きりです。 ・再帰法：各再帰レベル（各関数呼び出し）がそれぞれの head_prev を持ちます。\nleetcode234. 回文連結リスト # 快慢ポインタ法（速いポインタと遅いポインタ） # 反転リストの問題を解いた直後だったので、連結リストの後半部分を反転させ、前半部分と後半部分が同じかどうかを比較する方法を思いつきました。連結リストを配列に格納してから回文比較を行う方がコード量は少なくなりますが、快慢ポインタ法の利点は明らかです：O(n) の追加空間（メモリ）を避けることができます。\nbool isPalindrome(ListNode* head) { if(head==nullptr||head-\u0026gt;next==nullptr){ return true; } ListNode* head1=head; // head1: 遅いポインタ ListNode* head2=head; // head2: 速いポインタ while(head2!=nullptr\u0026amp;\u0026amp;head2-\u0026gt;next!=nullptr){ head1=head1-\u0026gt;next; head2=head2-\u0026gt;next-\u0026gt;next; } ListNode* secondHalf=reverseList(head1,nullptr); ListNode* p1=head; ListNode* p2=secondHalf; bool flag=true; while(p2!=nullptr){ if(p1-\u0026gt;val!=p2-\u0026gt;val){ flag=false; break; } p1=p1-\u0026gt;next; p2=p2-\u0026gt;next; } return flag; } ListNode* reverseList(ListNode* head,ListNode *head_prev = nullptr) { ListNode *head_next; if(head==nullptr){ return head_prev; } head_next=head-\u0026gt;next; head-\u0026gt;next=head_prev; return reverseList(head_next,head); } ","date":"2026年6月1日","externalUrl":null,"permalink":"/ja/posts/20260601-leetcode.list/","section":"記事","summary":"","title":"LeetCode.リスト","type":"posts"},{"content":"","date":"6月 1, 2026","externalUrl":null,"permalink":"/en/tags/list/","section":"Tags","summary":"","title":"List","type":"tags"},{"content":"","date":"2026年6月1日","externalUrl":null,"permalink":"/ja/tags/%E3%83%AA%E3%82%B9%E3%83%88/","section":"Tags","summary":"","title":"リスト","type":"tags"},{"content":"","date":"2026年06月01日","externalUrl":null,"permalink":"/tags/%E9%93%BE%E8%A1%A8/","section":"Tags","summary":"","title":"链表","type":"tags"},{"content":"","date":"2026年5月3日","externalUrl":null,"permalink":"/ja/tags/agent/","section":"Tags","summary":"","title":"Agent","type":"tags"},{"content":" GrantGo 概要 # GrantGoは、24時間いつでも利用可能な助成金・補助金申請のアシスタントです。複雑な政策を分かりやすく解説し、申請プロセスをスムーズに進めるお手伝いをします。登録、ユーザープロフィール（画像）の作成、助成金相談、書類の事前審査などをより簡単に行うことができ、自分に最適な助成金の機会を効率的に見つけることが可能です。また、ユーザープロフィール、政策解釈、申請手順、書類チェックを一つのワークスペースに統合しており、「分からない、見つからない、書類漏れが不安」という状態を、「分かる、できる、早く終わる」へと変えるサポートをします。\nGrantGoへ Hassenfeld-hub/GrantGo Vue 0 0 GrantGo の機能 # ログイン・新規登録 # ホームページから「ログイン」または「無料体験」をクリックしてログインページへ移動します。 新規ユーザーはメールアドレス + パスワードで登録し、ログインできます。 プロフィールの充実 # 個人プロフィールの入力が必要です：最終学歴、卒業年度、現在の勤務地・居住都市、社会保険加入月数、就業状況、地元戸籍の有無、婚歴・育児状況、起業意向、業界の方向性など。 都市選択は3段階（省/市/区・県）の連動型で、省レベルまたは市レベルでの停止も可能です。 「保存してマッチング開始」をクリックするとワークスペースに入り、システムが自動的に初回プロフィールマッチングを開始します。 ワークスペース # 左側 履歴ダイアログ：会話の確認、切り替え、削除が可能。「新規作成」もサポート。 中央 AI 相談室：AIと対話し、助成金のマッチング提案、政策の解説、手続きに関する疑問の解決が可能です。 右側 PDF 解析：書類をアップロードしてAIによる事前審査を行い、マッチング度、資料チェック、プロセス進捗を表示します。 上部バーで左右のサイドパネルを折りたたみ、閲覧スペースを広げることができます。 インテリジェントなQ\u0026amp;A # 高マッチング助成金 システムが個人プロフィールに基づいて、マッチング度の高い助成金カードを返します。 助成金カードの内容：助成金名、適用地域、マッチング度、金額、条件説明。 申請ガイドを見るをクリックすると、その助成金の詳細な申請ガイドが生成されます。 申請ガイド 申請ガイドには、概要、申請URL、行政情報URL、相談電話番号、必要書類、手続きの手順が含まれます。 フローチャート生成をクリックし、視覚的な手続きルートを確認できます。 チェックリスト表示をクリックし、書類をチェックして準備状況を管理できます。 自由対話\n相談したい内容をいつでも入力でき、GrantGoが回答します。 PDF事前審査\nPDFファイル（卒業証明書、社保証明など）のアップロードに対応。 アップロード後、システムが解析を行い、状態をリアルタイムで表示（アップロード中、解析中、完了/失敗）。 解析完了後、マッチング度、必要書類のチェック結果、プロセスタイムラインの提案を確認できます。 技术架构 # フロントエンド (Frontend) コアフレームワーク: Vue 3 + Vite + TypeScript 状態管理: Pinia (マルチセッション Chat 管理、ユーザー状態) ルーティング: Vue Router UI \u0026amp; スタイル: Tailwind CSS v4 + 独自デザイン (Inter フォント) 特色ライブラリ: markdown-it, mermaid, dompurify (安全レンダリング) 業務バックエンド (Backend - Go) コアフレームワーク: Gin (Go 1.25) データベース \u0026amp; ORM: PostgreSQL / SQLite + GORM リアルタイム通信: Gorilla WebSocket (ストリーム対話処理) 認証: JWT 認証 + CSRF 保護 主な役割：ユーザー認証、プロフィールデータ、地域ツール、バックエンドデータの集約、WebSocket 転送、セキュリティミドルウェアとレート制限の処理。 AI サービス (Backend - Python) コアフレームワーク: FastAPI + Uvicorn AI 核心庫: LangChain, OpenAI API (DeepSeek 等と互換) 文档与向量库: PyMuPDF, ChromaDB, Redis 主な役割：純粋なLLM会話モード、System Promptの戦略制御、フォーマット済みJSONカード生成、RAG検索（バックアップ/セーフティリンク）およびPDF解析。 ","date":"2026年5月3日","externalUrl":null,"permalink":"/ja/posts/20260503-grantgo/","section":"記事","summary":"GrantGo AI 技術解説","title":"GrantGo AI","type":"posts"},{"content":"","date":"2026年5月3日","externalUrl":null,"permalink":"/ja/tags/grantgo-ai/","section":"Tags","summary":"","title":"GrantGo AI","type":"tags"},{"content":" 情報 以下の内容は Anthropic 公式サイトの技術記事を転載し、AI によって翻訳されたものです。原文の全文は、こちらのリンクからご覧いただけます：https://www.anthropic.com/engineering/building-effective-agents\n私たちは、あらゆる業界で LLM エージェントを構築している数十のチームと協力してきました。一貫して、最も成功している実装は、複雑なフレームワークではなく、シンプルで構成可能なパターンを使用しています。\n過去 1 年間、私たちは大言語モデル (LLM) エージェントを構築している数十のチームと協力してきました。一貫して、最も成功した実装は、複雑なフレームワークや特殊なライブラリを使用したものではありませんでした。代わりに、それらはシンプルで構成可能なパターンを使用して構築されていました。\n本記事では、お客様との協力や自社でのエージェント開発から学んだ教訓を共有し、開発者が効果的なエージェントを構築するための実践的なアドバイスを提供します。\nエージェントとは何か？ # 「エージェント」はいくつかの方法で定義されます。あるお客様は、エージェントを、さまざまなツールを使用して複雑なタスクを長期間自律的に実行する完全自律型システムと定義しています。また、定義済みのワークフローに従うより規定的な実装を指すためにこの用語を使用する方もいます。Anthropic では、これらすべてのバリエーションをエージェント型システム (agentic systems) と分類していますが、アーキテクチャとしてワークフロー (workflows) とエージェント (agents) を明確に区別しています。\nワークフロー：LLM とツールが定義済みのコードパスを通じてオーケストレーションされるシステム。 エージェント：LLM が自身のプロセスやツール使用を動的に指示し、タスクの達成方法を自ら制御するシステム。 以下では、これら両方のタイプのエージェント型システムについて詳しく説明します。付録 1（「エージェントの例」）では、お客様がこの種のシステムに特に価値を見出した 2 つの領域について説明します。\nエージェントをいつ使うべきか（あるいは使うべきでないか） # LLM を使用してアプリケーションを構築する際は、まず最もシンプルな解決策を探し、必要な場合にのみ複雑さを増していくことを推奨します。これは、エージェント型システムをまったく構築しないことを意味する場合もあります。エージェント型システムは、多くの場合、タスクのパフォーマンス向上のためにレイテンシとコストを犠牲にします。このトレードオフがいつ理にかなうかを検討する必要があります。\n高い複雑さが正当化される場合、ワークフローは定義の明確なタスクに対して予測可能性と一貫性を提供します。一方、エージェントは柔軟性とモデル駆動型の意思決定が大規模に必要とされる場合に適した選択肢となります。しかし、多くのアプリケーションでは、検索（retrieval）とコンテキスト内での例示を用いて単一の LLM コールを最適化するだけで十分です。\nフレームワークの使用時期と方法 # エージェント型システムの構築を容易にするフレームワークは多数存在します：\nClaude Agent SDK AWS Strands Agents SDK Rivet: ドラッグアンドドロップで LLM ワークフローを構築できる GUI ツール Vellum: 複雑なワークフローを構築・テストするための別の GUI ツール これらのフレームワークは、LLM の呼び出し、ツールの定義と解析、呼び出しの連結など、標準的な低レベルのタスクを簡素化することで、簡単に使い始めることができます。しかし、抽象化レイヤーが追加されることで、背後にあるプロンプトやレスポンスが見えにくくなり、デバッグが困難になることがよくあります。また、シンプルな構成で十分な場合に不必要な複雑さを加えたくなる誘惑にも駆られます。\n開発者の皆様には、まず LLM API を直接使用することをお勧めします。多くのパターンは数行のコードで実装可能です。フレームワークを使用する場合は、その内部コードを理解するようにしてください。内部の挙動に関する誤った推測は、よくあるエラーの原因です。\nサンプルの実装については、Cookbook をご覧ください。\n構成要素、ワークフロー、エージェント # このセクションでは、本番環境で見られる一般的なエージェント型システムのパターンについて詳しく説明します。まず、基礎となる構成要素である「拡張 LLM」から始め、シンプルな構成ワークフローから自律型エージェントへと、段階的に複雑さを増していきます。\n構成要素：拡張 LLM # エージェント型システムの基本要素は、検索、ツール、メモリなどの機能（拡張）を加えた LLM です。現在のモデルは、自ら検索クエリを生成し、適切なツールを選択し、保持すべき情報を決定するなど、これらの機能を能動的に活用できます。\n拡張 LLM\n実装においては、これらの能力を特定のユースケースに合わせて調整すること、およびモデルに対して使いやすく文書化されたインターフェースを提供することの 2 点に重点を置くことをお勧めします。最近リリースされた Model Context Protocol (MCP) を使用すると、サードパーティ製ツールのエコシステムを簡単に統合できます。\n以下では、各 LLM 呼び出しがこれらの拡張機能にアクセスできることを前提とします。\nワークフロー：プロンプト・チェイニング (Prompt chaining) # プロンプト・チェイニングは、タスクを一連のステップに分解し、各 LLM 呼び出しが前の呼び出しの出力を処理する手法です。プロセスが軌道に乗っていることを確認するために、中間ステップにプログラム的なチェック（下図の \u0026ldquo;gate\u0026rdquo;）を追加できます。\nプロンプト・チェイニング・ワークフロー\nいつこのワークフローを使うべきか： タスクが固定のサブタスクに容易かつ明確に分解できる場合に最適です。主な目標は、各 LLM 呼び出しをより簡単なタスクにすることで、精度の向上を図ることです。\n有用な例：\nマーケティングコピーを生成し、それを別の言語に翻訳する。 文書の構成案を作成し、基準を満たしているかチェックした上で、その構成案に基づいて文書を執筆する。 ワークフロー：ルーティング (Routing) # ルーティングは、入力を分類し、それを専門のフォローアップタスクに振り分けます。このワークフローにより、関心の分離（Separation of Concerns）が可能になり、より専門的なプロンプトを構築できます。\nルーティング・ワークフロー\nいつこのワークフローを使うべきか： 複雑なタスクにおいて、明確に分けられたカテゴリが存在し、分類が LLM や従来のアルゴリズムによって正確に行える場合に適しています。\n有用な例：\n異なる種類のカスタマーサービスへの問い合わせ（一般的な質問、返金リクエスト、技術サポート）を、それぞれ異なる下流のプロセス、プロンプト、ツールに振り分ける。 簡単な質問は低コストな Claude 4.5 Haiku に、複雑な質問は Claude 4.5 Sonnet にルーティングしてパフォーマンスを最適化する。 ワークフロー：並列化 (Parallelization) # LLM が同時にタスクに取り組み、その出力をプログラムで集約する手法です。主に 2 つのバリエーションがあります：\nセクショニング：タスクを独立したサブタスクに分解して並列実行する。 投票 (Voting)：同じタスクを複数回実行し、多様な出力を得る。 並列化ワークフロー\nいつこのワークフローを使うべきか： 並列処理によって速度を向上させたい場合や、高い信頼性を得るために複数の視点や試行が必要な場合に効果的です。\n有用な例：\nセクショニング：ガードレールとして、あるモデルインスタンスがユーザーの回答を処理する一方で、別のインスタンスで不適切な内容がないかチェックする。 投票：コードの脆弱性をチェックする際、複数のプロンプトでレビューし、問題が見つかった場合にフラグを立てる。 ワークフロー：オーケストレーター・ワーカー (Orchestrator-workers) # 中央の LLM が動的にタスクを分解し、ワーカー LLM に割り当て、結果を合成するワークフローです。\nオーケストレーター・ワーカー・ワークフロー\nいつこのワークフローを使うべきか： 必要なサブタスクが予測できない複雑なタスク（プログラミングなど）に適しています。並列化との主な違いは、サブタスクが事前に定義されているのではなく、オーケストレーターによって動的に決定される柔軟性にあります。\nワークフロー：エバリュエーター・オプティマイザー (Evaluator-optimizer) # 一つの LLM が回答を生成し、別の LLM が評価とフィードバックを提供してループを回します。\nエバリュエーター・オプティマイザー・ワークフロー\nいつこのワークフローを使うべきか： 明確な評価基準があり、反復的な改善が測定可能な価値をもたらす場合に特に効果的です。\nエージェント (Agents) # LLM が複雑な入力の理解、推論と計画、ツールの信頼性の高い使用、エラーからの回復といった主要な能力において成熟するにつれ、エージェントが本番環境で登場し始めています。エージェントは自律的に計画を立てて行動し、実行中は環境からの「グラウンドトゥルース（事実）」を確認しながら進みます。\n自律型エージェント\nいつエージェントを使うべきか： 固定のパスをハードコードできない開放的な問題に適しています。自律性はコストやエラーの蓄積を伴う可能性があるため、サンドボックス環境での広範なテストが不可欠です。\n(付録などは必要に応じて省略または要約されています。)\n","date":"2026年4月28日","externalUrl":null,"permalink":"/ja/posts/20260428-02.buildingeffectiveagents/","section":"記事","summary":"","title":"02.Building Effective Agents","type":"posts"},{"content":"","date":"2026年4月28日","externalUrl":null,"permalink":"/ja/series/anthropic/","section":"Series","summary":"","title":"Anthropic","type":"series"},{"content":"","date":"2026年4月28日","externalUrl":null,"permalink":"/ja/tags/anthropic/","section":"Tags","summary":"","title":"Anthropic","type":"tags"},{"content":"","date":"2026年4月28日","externalUrl":null,"permalink":"/ja/tags/workflow/","section":"Tags","summary":"","title":"Workflow","type":"tags"},{"content":"","date":"2026年4月27日","externalUrl":"https://grantgo.hassenfeld.org/","permalink":"/ja/projects/grantgo/","section":"プロジェクト","summary":"GrantGo：AI搭載のスマート申請補助アシスタント。的確なユーザー評価から提出書類の事前審査まで、全プロセスをサポートします。登録をよりシンプルに、相談をより効率的に。手続きの無駄を省き、あなたに最適な助成金のチャンスをスピーディーに見つけ出します。","title":"GrantGo","type":"projects"},{"content":"","date":"2026年4月27日","externalUrl":null,"permalink":"/ja/projects/","section":"プロジェクト","summary":"","title":"プロジェクト","type":"projects"},{"content":" 情報 以下の内容は Anthropic 公式サイトの技術記事を転載し、AI によって翻訳されたものです。原文の全文は、こちらのリンクからご覧いただけます：https://www.anthropic.com/engineering/contextual-retrieval\nAI モデルが特定のコンテキストで有用であるためには、背景知識へのアクセスが必要になることがよくあります。例えば、カスタマーサポートのチャットボットにはそのビジネス特有の知識が必要ですし、法律分析ボットには膨大な過去の判例の知識が必要です。\n開発者は通常、検索拡張生成（RAG）を使用して AI モデルの知識を強化します。RAG は、ナレッジベースから関連情報を取得し、それをユーザーのプロンプトに追加することで、モデルの回答を大幅に向上させる手法です。問題は、従来の RAG ソリューションが情報をエンコードする際にコンテキストを削除してしまうため、システムがナレッジベースから関連情報を取得できなくなることがよくある点です。\n本記事では、RAG における検索ステップを劇的に改善する方法を紹介します。この手法は「Contextual Retrieval（コンテキスト検索）」と呼ばれ、「Contextual Embeddings」と「Contextual BM25」という 2 つのサブテクニックを使用します。この手法により、検索の失敗を 49% 削減でき、リランキング（reranking）と組み合わせることで 67% 削減することができます。これらは検索精度の大きな改善を意味し、下流のタスクにおけるパフォーマンス向上に直結します。\nClaude を使用した独自の Contextual Retrieval ソリューションは、こちらのクックブックで簡単にデプロイできます。\n単に長いプロンプトを使用することについての注意点 # 時には最もシンプルな解決策が最善であることもあります。ナレッジベースが 200,000 トークン（約 500 ページの資料）未満の場合は、RAG や同様の手法を必要とせず、ナレッジベース全体をモデルに渡すプロンプトに含めるだけで済みます。\n数週間前、私たちは Claude 向けに プロンプト・キャッシュ（prompt caching） をリリースしました。これにより、このアプローチが大幅に高速化され、コスト効率も向上しました。開発者は API 呼び出しの間で頻繁に使用されるプロンプトをキャッシュできるようになり、遅延を 2 倍以上短縮し、コストを最大 90% 削減できます（動作については プロンプト・キャッシュ・クックブック をご覧ください）。\nただし、ナレッジベースが成長するにつれて、よりスケーラブルなソリューションが必要になります。そこで Contextual Retrieval の出番です。\nRAG 入門：より大規模なナレッジベースへのスケーリング # コンテキストウィンドウに収まらない大規模なナレッジベースの場合、RAG が標準的なソリューションとなります。RAG は以下の手順でナレッジベースを前処理します：\nナレッジベース（文書の「コーパス」）を、通常数百トークン以下の小さなテキストチャンク（チャンク）に分解する。 エンベディングモデルを使用して、これらのチャンクを意味をコード化したベクトルエンベディングに変換する。 これらのエンベディングを、セマンティックな類似性による検索が可能なベクトルデータベースに保存する。 実行時にユーザーがモデルにクエリを入力すると、ベクトルデータベースを使用して、クエリとのセマンティックな類似性に基づいた関連性の高いチャンクを見つけます。その後、最も関連性の高いチャンクが生成モデルに送信されるプロンプトに追加されます。\nエンベディングモデルはセマンティックな関係を捉えることには優れていますが、重要な完全一致を見逃すことがあります。幸いなことに、このような状況で役立つ古いテクニックがあります。BM25（Best Matching 25）は、語彙マッチングを使用して正確な単語やフレーズの一致を見つけるランキング関数です。一意の識別子や専門用語を含むクエリに対して特に効果的です。\nBM25 は TF-IDF（Term Frequency-Inverse Document Frequency）の概念に基づいています。TF-IDF は、単語が集まり（コレクション）の中の文書にとってどれほど重要かを測定します。BM25 は、文書の長さを考慮し、語の出現頻度に飽和関数を適用することでこれを改善し、一般的な単語が結果を独占するのを防ぎます。\nセマンティックエンベディングが失敗するケースで BM25 が成功する例を挙げます：ユーザーがテクニカルサポートのデータベースで「エラーコード TS-999」を検索したとします。エンベディングモデルは一般的なエラーコードに関するコンテンツを見つけるかもしれませんが、正確な「TS-999」の一致を見逃す可能性があります。BM25 はこの特定のテキスト文字列を探して、関連するドキュメントを特定します。\nRAG ソリューションは、以下の手順でエンベディングと BM25 のテクニックを組み合わせることで、最も適用可能なチャンクをより正確に取得できます：\nナレッジベース（ドキュメントの「コーパス」）を小さなテキストチャンクに分解する。 これらのチャンクに対して TF-IDF エンコーディングとセマンティックエンベディングを作成する。 BM25 を使用して、完全一致に基づいたトップチャンクを見つける。 エンベディングを使用して、セマンティックな類似性に基づいたトップチャンクを見つける。 ランクフュージョン（rank fusion）の手法を用いて、(3) と (4) の結果を組み合わせて重複を除去する。 上位 K 個のチャンクをプロンプトに追加して回答を生成する。 BM25 とエンベディングモデルの両方を活用することで、従来の RAG システムは、正確な用語マッチングと広範なセマンティックな理解を両立させ、より包括的かつ正確な結果を提供できます。\nエンベディングと BM25 の両方を使用して情報を取得する標準的な RAG システム。\nこのアプローチにより、単一のプロンプトに収まる範囲をはるかに超えた膨大なナレッジベースに対しても、コスト効率よくスケーリングできます。しかし、これらの従来の RAG システムには大きな技術的限界があります。それは、コンテキスト（文脈）を破壊してしまうことがよくある点です。\n従来の RAG におけるコンテキストの課題 # 従来の RAG では、効率的な検索のためにドキュメントは通常小さなチャンクに分割されます。このアプローチは多くのアプリケーションで機能しますが、個々のチャンクに十分なコンテキストが欠けている場合に問題が生じる可能性があります。\n例えば、ナレッジベースに財務情報（米国 SEC 提出書類など）が含まれており、次のような質問を受けた場合を想像してください：「ACME Corp の 2023 年第 2 四半期の売上成長率は？」\n関連するチャンクには次のようなテキストが含まれているかもしれません：「同社の売上は前四半期比で 3% 増加しました。」 しかし、このチャンク単体ではどの会社を指しているのか、どの期間のことなのかが特定されておらず、正しい情報を取得したり、情報を効果的に使用したりすることが困難になります。\nContextual Retrieval（コンテキスト検索）の導入 # Contextual Retrieval は、エンベディング（「Contextual Embeddings」）および BM25 インデックス作成（「Contextual BM25」）の前に、各チャンクにチャンク固有の説明的なコンテキストを付加することで、この問題を解決します。\nSEC 提出書類の例に戻りましょう。チャンクがどのように変換されるかの例を以下に示します：\noriginal_chunk = \u0026#34;The company\u0026#39;s revenue grew by 3% over the previous quarter.\u0026#34; contextualized_chunk = \u0026#34;This chunk is from an SEC filing on ACME corp\u0026#39;s performance in Q2 2023; the previous quarter\u0026#39;s revenue was $314 million. The company\u0026#39;s revenue grew by 3% over the previous quarter.\u0026#34; 検索を改善するためにコンテキストを使用するアプローチは過去にも提案されています。それらには、チャンクに一般的なドキュメントの要約を追加する（実験では効果が限定的）、仮想ドキュメントエンベディング（Hypothetical Document Embedding）、要約ベースのインデックス作成などが含まれます。これらの手法は、本記事で提案されているものとは異なります。\nContextual Retrieval の実装 # もちろん、ナレッジベース内の数万、数百万のチャンクに手動でアノテーションを付けるのは大変な作業です。Contextual Retrieval を実装するために、私たちは Claude を活用します。モデルに対し、ドキュメント全体のコンテキストを使用してチャンクを説明する、簡潔でチャンク固有のコンテキストを提供するよう指示するプロンプトを作成しました。各チャンクのコンテキスト生成には、以下の Claude 3 Haiku プロンプトを使用しました：\n\u0026lt;document\u0026gt; {{WHOLE_DOCUMENT}} \u0026lt;/document\u0026gt; Here is the chunk we want to situate within the whole document \u0026lt;chunk\u0026gt; {{CHUNK_CONTENT}} \u0026lt;/chunk\u0026gt; Please give a short succinct context to situate this chunk within the overall document for the purposes of improving search retrieval of the chunk. Answer only with the succinct context and nothing else. 生成されるコンテキストテキストは通常 50〜100 トークンで、エンベディング作成や BM25 インデックス作成の前にチャンクの冒頭に付加されます。\n前処理の流れは以下のようになります：\nContextual Retrieval は検索精度を向上させる前処理技術です。\nContextual Retrieval の導入に興味がある方は、こちらのクックブック から始めていただけます。\nプロンプト・キャッシュによるコスト削減 # Contextual Retrieval は、冒頭に述べた Claude 特有のプロンプト・キャッシュ機能により、低コストで実現可能です。プロンプト・キャッシュにより、チャンクごとに参照ドキュメントを渡す必要はありません。ドキュメントを一度キャッシュに読み込み、その後は以前にキャッシュされたコンテンツを参照するだけです。チャンクを 800 トークン、ドキュメントを 8,000 トークン、コンテキスト指示を 50 トークン、各チャンクのコンテキストを 100 トークンと想定すると、コンテキスト化されたチャンクを作成するためのワンタイムコストは、100 万ドキュメントトークンあたりわずか 1.02 ドル です。\n","date":"2026年4月25日","externalUrl":null,"permalink":"/ja/posts/20260425-01.introducingcontextualretrieval/","section":"記事","summary":"","title":"01.Introducing Contextual Retrieval","type":"posts"},{"content":"","date":"2026年4月25日","externalUrl":null,"permalink":"/ja/tags/rag/","section":"Tags","summary":"","title":"RAG","type":"tags"},{"content":"","date":"2026年4月20日","externalUrl":null,"permalink":"/ja/posts/20260420-00.introduction/","section":"記事","summary":"","title":"00.Introduction","type":"posts"},{"content":"","date":"2026年4月20日","externalUrl":null,"permalink":"/ja/tags/ai/","section":"Tags","summary":"","title":"AI","type":"tags"},{"content":"","date":"2026年4月20日","externalUrl":null,"permalink":"/ja/tags/llm/","section":"Tags","summary":"","title":"LLM","type":"tags"},{"content":" 私について # Hassenfeldです。ソフトウェア工学を専攻する学部生です。現在は新しい知識や技術を絶えず学び、探求し続けています……\n技術スタック # Languages # Frameworks \u0026amp; Libraries # 学歴 # 大学：大連理工大学、立命館大学 高校：浙江省杭州第二中学 趣味 # バスケットボール、バレーボール、サイクリング、プラモ屋、写真撮影、ドラマ好き……\nこのサイトについて # 当サイトは静的サイト生成器 Hugo を基盤に構築され、UI には Blowfish テーマを採用しています。ソースコードは GitHub で管理し、GitHub Actions を活用した CI/CD ワークフローを通じて GitHub Pages にデプロイしています。ドメインの管理および解析は Cloudflare を利用しています。\n","date":"2026年3月25日","externalUrl":null,"permalink":"/ja/about/","section":"Hassenfeld","summary":"","title":"について","type":"page"},{"content":"","date":"2026年3月25日","externalUrl":null,"permalink":"/ja/posts/","section":"記事","summary":"","title":"記事","type":"posts"},{"content":" ウェブサイトの作成 # Hugo\u0026amp; Blowfishで初めてウェブサイトを作りました。\n当サイトは静的サイト生成器 Hugo を基盤に構築され、UI には Blowfish テーマを採用しています。ソースコードは GitHub で管理し、GitHub Actions を活用した CI/CD ワークフローを通じて GitHub Pages にデプロイしています。ドメインの管理および解析は Cloudflare を利用しています。\n\u0026mdash;26.3.22\n","date":"2026年3月22日","externalUrl":null,"permalink":"/ja/posts/20260325-stationbuilt/","section":"記事","summary":"","title":"ウェブサイトの作成","type":"posts"},{"content":"","date":"2026年2月16日","externalUrl":"/works/happySpringFestival2026/","permalink":"/ja/projects/happyspringfestival2026/","section":"プロジェクト","summary":"願いの壁を照らし、新たな年の希望を共に書き記しましょう！","title":"2026 新春おめでとう","type":"projects"},{"content":"","date":"2025年12月31日","externalUrl":"/works/happyNewYear2026/index.html","permalink":"/ja/projects/happynewyear2026/","section":"プロジェクト","summary":"指先で触れると、花火が咲いて新年をお迎えします！","title":"2026 新年おめでとう","type":"projects"},{"content":"","externalUrl":null,"permalink":"/ja/authors/","section":"Authors","summary":"","title":"Authors","type":"authors"},{"content":"","externalUrl":null,"permalink":"/ja/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"}]