受託開発の保守担当が、過去の設計書と変更管理の記録から改修する機能の記載と変更の経緯を探し、影響調査に根拠付きで使う
改修依頼を受けた保守担当が、過去の設計書・仕様書と変更管理のチケットから、対象機能の記載箇所と変更の経緯を探します。結果は文書名・版・章とチケット番号の付いた一覧で返り、影響調査の材料になります。
- 生成AI
- Azure OpenAI Service/Claude/Gemini
- AIサービス
- Azure AI/Google Document AI/Google Vertex AI/OpenSearch
- 対象業界
- IT・SaaS/自治体/製造/金融
- 対象部門
- 情報システム/研究開発
- 対象業務
- 情報検索/書類作成
- 主な課題
- 属人化している/引き継ぎができていない/情報が見つからない
- AIで行う処理
- 検索(RAG)
- 主な効果
- 判断支援/属人化解消/検索時間短縮
- 導入難易度
- ★★★★☆
- 実装レベル
- 本格構成
- 費用感
- RAG・個別開発(大)
- 人間の確認
- 条件付き
01導入前 / 導入後の業務フロー
- 顧客から改修依頼のチケットが起票される
- 担当者が案件フォルダを開き、ファイル名から関係しそうな設計書を探す
- 設計書を1つずつ開き、機能IDや画面名で検索して、記載箇所を探す
- 版が複数ある設計書は、どれが最新かを更新日時と中身で確かめる
- Redmine でキーワード検索し、過去の関連チケットを探して、コメントを読む
- 分からないところは、そのシステムを長く担当している人に聞く
- 記載箇所と経緯を影響調査メモにまとめ、見積に回す
- 人担当者が社内の検索画面に、改修依頼のチケット番号を入れる
- 自動検索画面が Redmine からチケットの本文を取り、案件(顧客とシステム)を特定する
- 自動生成AIが改修依頼の本文から、機能ID・画面名・テーブル名・業務用語を検索語として取り出す
- 自動Azure AI Search で、その案件の範囲に絞って、設計書とチケットをハイブリッド検索する
- 自動生成AIが検索結果だけを根拠に、記載箇所の一覧と変更の経緯の時系列をまとめ、見つからなかった項目を書き出す
- 人担当者が出典を開いて記載を確かめ、足りない観点を追加で検索する
- 人担当者がソースコード上の影響を確かめ、影響調査メモを仕上げる
- 自動仕上がったメモをチケットに添付し、どの出典を採用したかを記録する
各工程の詳しい説明を読む
- 顧客から改修依頼のチケットが起票される
- 担当者が案件フォルダを開き、ファイル名から関係しそうな設計書を探す
- 設計書を1つずつ開き、機能IDや画面名で検索して、記載箇所を探す
- 版が複数ある設計書は、どれが最新かを更新日時と中身で確かめる
- Redmine でキーワード検索し、過去の関連チケットを探して、コメントを読む
- 分からないところは、そのシステムを長く担当している人に聞く
- 記載箇所と経緯を影響調査メモにまとめ、見積に回す
(a)どこに書いてあるかが分からない。 1つの機能の仕様が、画面設計書、帳票設計書、テーブル定義書、バッチ設計書に分かれて書かれています。ファイル名で探し、開いて検索し、無ければ次を開くのが3番目の中身です。Excelのファイル内の検索はシートごとで、シートが数十ある設計書では見落とします。
(b)経緯を知る人がいない。 5番目のチケット検索は、タイトルと本文の文字が一致しないと引っかかりません。「締め処理の例外」で探しても、当時のチケットが「月末バッチのエラー対応」というタイトルなら出てきません。 結局、6番目の「知っている人に聞く」に頼りますが、その人は異動や退職でいなくなっていきます。
(c)調べ方が人によって違う。 ベテランはテーブル定義書まで見に行き、新しい担当者は画面設計書で止まります。見積の精度もそれに引きずられます。
(d)古い版を見てしまう。 更新日時が新しいものが最新とは限らず、実装と食い違ってから気づくことがあります。
- 【人】 担当者が社内の検索画面に、改修依頼のチケット番号を入れる
- 【自動】 検索画面が Redmine からチケットの本文を取り、案件(顧客とシステム)を特定する
- 【自動】 生成AIが改修依頼の本文から、機能ID・画面名・テーブル名・業務用語を検索語として取り出す
- 【自動】 Azure AI Search で、その案件の範囲に絞って、設計書とチケットをハイブリッド検索する
- 【自動】 生成AIが検索結果だけを根拠に、記載箇所の一覧と変更の経緯の時系列をまとめ、見つからなかった項目を書き出す
- 【人】 担当者が出典を開いて記載を確かめ、足りない観点を追加で検索する
- 【人】 担当者がソースコード上の影響を確かめ、影響調査メモを仕上げる
- 【自動】 仕上がったメモをチケットに添付し、どの出典を採用したかを記録する
6番目と7番目が、この設計の分かれ目です。 AIのまとめは影響調査メモの下書きではなく、出典の地図です。 担当者は出典を1つずつ開いて確かめ、影響を判断します。ソースコード上の影響は、この構成の範囲外です。 設計書に書かれていない実装の都合は、コードを見るしかありません。
4番目で案件の範囲に絞るのを、検索画面ではなく検索の仕組みに持たせているのも意図してのことです。 画面の作りに任せると、作り直しのたびに絞り込みが外れる危険があります。
02今回想定するシステム構成
案件フォルダ(設計書・仕様書) Redmine(変更管理のチケット) │ 定期的に Blob Storage へ複製 │ REST API で取得(夜間) ▼ ▼ Azure AI Document Intelligence 取り込みの処理 (レイアウトモデル、Markdown で出力) (チケット本文・コメント・関連コミット) ▼ ▼ Azure AI Search ── インデクサーとスキルセット(分割と埋め込み)/プッシュでの登録 │ 案件ID・顧客のグループID・文書種別・版・最新版かどうか を持つ ▼ 検索画面 ──【トリガー】担当者がチケット番号を入れる ├──▶ Azure OpenAI ── 検索語の取り出し ├──▶ Azure AI Search ── 案件で絞ったハイブリッド検索 └──▶ Azure OpenAI ── 出典付きの記載一覧と経緯の時系列 ▼ 【人が出典を確かめ、コードを見て、影響調査メモを仕上げる】
| 役割 | 想定する製品 | 代替候補 |
|---|---|---|
| 検索基盤 | Azure AI Search(ハイブリッド検索、セキュリティ フィルター) | Amazon OpenSearch Service、Vertex AI Search(Agent Search) |
| OCR | Azure AI Document Intelligence(レイアウトモデル。紙の設計書のスキャンとOffice文書の構造化) | Google Document AI |
| 埋め込み | Azure OpenAI(text-embedding-3-large) | 検索基盤が対応する他の埋め込みモデル |
| 生成AI | Azure OpenAI(Microsoft Foundry)(検索語の取り出しと出典付きのまとめ) | Claude API、Gemini API |
| 保管 | Azure Blob Storage(設計書の複製) | SharePoint |
| 変更管理 | Redmine(REST API) | Backlog、Jira |
ファイルサーバーと Redmine は、今あるものをそのまま使います。 足すのは、Blob Storage への複製、検索のインデックス、取り込みの処理、検索画面です。設計書の置き場所や書き方は変えません。
土台になるのは、Azure AI Search のハイブリッド検索です。 全文検索とベクトル検索を1つの要求で並列に実行し、結果を逆ランク融合(RRF)でまとめます。製品コード、高度に専門的な用語、日付、人の名前のように完全一致が要るクエリではキーワード検索が強い、とされています。機能ID「SCR-0412」やテーブル名「T_SEIKYU_MEISAI」は完全一致で、「締め処理の例外」は意味の近さで探す、という両方が要る題材です。
日本語の文章には、言語アナライザーを設定します。 日本語はスペースで単語が区切られないため、既定のアナライザーでは文字列全体が1つのトークンになりうるとされています。ja.microsoft か ja.lucene を、インデックスの作成時に設定します。
03どうやって実装するのか
処理の起点を決める
検索は、担当者が検索画面にチケット番号を入れたときに動きます。 改修依頼のすべてに自動で走らせると、見積の対象にならない問い合わせにも検索がかかり、結果を誰も見ません。影響調査を始めると決めた人が、始めたときに動かします。
インデックスの更新は別の流れで、定期的に動かします。
| 対象 | きっかけ | 中身 |
|---|---|---|
| 設計書・仕様書 | 毎晩、案件フォルダから Blob Storage へ差分を複製し、インデクサーをスケジュールで実行 | 新しい版の追加、ファイルの変更 |
| Redmine のチケット | 毎晩、前回以降に更新されたチケットを REST API で取り、インデックスへ登録 | 本文、コメント、関連コミット、関連チケット |
インデクサーはスケジュールで動かすことが推奨されています。 変更されたドキュメントや、スロットリングで取りこぼしたドキュメントを拾うためです。埋め込みモデルの呼び出しが上限に達したときの再試行も、スケジュール実行に任せます。
入力データを集める
| データ | 中身 | 取得元 |
|---|---|---|
| 改修依頼 | チケットの本文、案件、起票日、依頼者 | Redmine の REST API |
| 設計書・仕様書 | 画面・帳票・テーブル・バッチ・インターフェースの設計書。版ごとのファイル | Blob Storage の複製 |
| 過去のチケット | 本文、コメントと変更の履歴、関連するコミット、関連するチケット | Redmine の REST API |
| 案件の台帳 | 案件ID、顧客、システム名、担当グループ、設計書のフォルダの場所 | 自社で持つ案件の一覧 |
| 文書の台帳 | ファイルごとの文書種別、版、最新版かどうか | 案件ごとに整える一覧 |
質を決めるのは、いちばん下の文書の台帳です。 ファイル名の「最終」「修正」からは最新版を決められません。案件ごとに、どのファイルが今の正本かを一覧にします。 全案件を一度に整える必要はなく、改修依頼の多い案件から始めます。
チケットは本文だけでなく、コメントと関連コミットまで取ります。 経緯の多くはコメントの議論に残り、「この条件を足したのは〇〇の障害のため」という一文が、本文ではなく途中のコメントにあります。
データの取得方法を決める
Redmine のチケットは、2段階で取ります。 一覧の取得(GET /issues.json)で、updated_on に前回の取得日時以降を指定し、status_id=* で完了したものも含めて取ります。一覧の取得で include に指定できるのは attachments と relations で、コメントと変更の履歴(journals)や関連コミット(changesets)は1件ずつの取得(GET /issues/[id].json)で指定します。 ページ送りは offset と limit で行います。認証はAPIキーです。
設計書は、レイアウトモデルで構造化してからインデックスに入れます。 レイアウトモデルはPDF、画像、Word、Excel、PowerPoint、HTMLに対応し、抽出したテキストを Markdown で出力できます。見出しや表の構造が残るので、章や節の単位で分割しやすくなります。
| 文書の形 | 扱い | 注意 |
|---|---|---|
| Word の設計書 | Markdown で出力し、見出しで分割 | 埋め込みの画像は対象外 |
| Excel の設計書 | ワークシートごとに1ページとして扱い、シート名を出典に持たせる | XLSXではテーブルの分析がサポートされない |
| 紙の設計書のスキャン(PDF) | OCRで読み取り、見出しで分割 | 古い案件ほど多い |
Excel の注意が、この題材でいちばん大事です。 レイアウトモデルは、入力ファイルがXLSXの場合、テーブルの分析をサポートしないとされています。テキストは取れますが、表の行と列の構造は返りません。 項目一覧の表が主体のテーブル定義書は、1行を「項目名:型:桁:説明」の1文に組み直してから登録します。 列の見出しと値の対応が切れると、検索で当たっても読めない断片になります。
分割と埋め込みは、統合ベクトル化で行います。 インデクサーが Blob Storage から取り、Text Split スキルで分割し、AzureOpenAIEmbedding スキルでベクトルにします。クエリ時は、同じ埋め込みモデルのベクトライザーで検索語をベクトルにします。Redmine のチケットはインデクサーの対象ではないので、取り込みの処理がベクトルまで作って、プッシュで登録します。
AIへ渡す前に整形する
- 案件と顧客の付与 … すべてのチャンクに、案件ID、顧客のグループID、文書種別を付けます。付かないチャンクは登録しません
- 版の付与 … 文書の台帳から版と「最新版かどうか」を付けます。台帳に無いファイルは「版不明」とします
- 出典の付与 … ファイル名、シート名または章・節の見出し、ページを付けます
- Excel の表の組み直し … テーブル定義書などの表は、1行を1文に組み直します
- チケットの整形 … 本文とコメントを日付順に並べ、コメントごとに番号と日付を付けて分割します。関連コミットの番号と、関連チケットの番号も持たせます
- 定型文の除去 … 設計書の表紙、改訂履歴の空欄、チケットの自動通知の文言を除きます
- 重複の扱い … 同じ内容のファイルが複数の版で残っていても消さず、版の情報で区別します
1番目を省かないでください。 案件IDの付かないチャンクは、どの案件の検索にも出てこないか、すべての案件の検索に出てくるかのどちらかになります。後者は顧客の情報が混ざる事故です。
7番目で古い版を消さないのは、経緯のためです。 「v2.0 まではこの条件が無かった」ことは、古い版を見ないと分かりません。最新版を優先して返し、古い版は経緯の材料として別に返します。
AIに処理させる
生成AIにさせるのは2つです。 改修依頼から検索語を取り出すことと、検索結果だけを根拠に出典付きの一覧と時系列をまとめることです。
| 段階 | させること | させないこと |
|---|---|---|
| 検索語の取り出し | 機能ID、画面名、帳票名、テーブル名、業務用語、依頼の要点を取り出す | 依頼に無い機能を推測で足す |
| 記載箇所の一覧 | 検索結果のうち、対象機能について書かれた箇所を、出典ごとに要点と引用で並べる | 検索結果に無い仕様を書く |
| 経緯の時系列 | チケットとコメントから、いつ、何が、なぜ変わったかを日付順に並べる | 理由が書かれていない変更に理由を補う |
| 見つからなかった項目 | 依頼の要点のうち、記載が見つからなかったものを書き出す | 見つからないことを「影響なし」と書く |
| AIにさせないこと | 理由 |
|---|---|
| 影響範囲の最終判断 | 担当者がコードと合わせて決める |
| 改修の工数や難易度の見積 | 見積は担当者と営業の仕事 |
| 古い版と最新版の食い違いを、どちらが正しいか決めること | 実装を確かめないと決められない |
| 別の案件の設計書を参考にすること | 顧客の情報が混ざる。検索の範囲で閉じる |
表の右下が、いちばん起きやすい失敗です。 「〇〇テーブルへの影響」について何も見つからないと、生成AIは「影響はないと考えられます」と書きたがります。見つからなかったのは、書かれていないからか、探し方が足りないからかのどちらかで、どちらも影響が無いことを意味しません。
指示内容を固定する
あなたは受託開発の保守担当の調査を手伝う立場です。
次の【検索結果】だけを根拠に、改修依頼の対象機能について、
設計書の記載箇所と、過去の変更の経緯をまとめてください。
【改修依頼の要点】{request_points}
例: ["請求明細の締め日を月末以外にも設定できるようにしたい"]
【検索結果】{search_results}
各要素に chunk_id、文書名、版、最新版かどうか、シート名または章・節、本文がある
【厳守事項】
- 検索結果に書かれていないことを書かないでください。
一般的な設計の知識で補わないでください。
- すべての記載に、根拠にした chunk_id を付けてください。
chunk_id を付けられない記載は書かないでください。
- 引用は検索結果の本文から、そのまま写してください。言い換えないでください。
- 最新版でない文書の記載は、current_spec ではなく history に入れてください。
- 最新版と古い版で記載が食い違っていても、どちらが正しいかを判断しないでください。
conflicts に両方の chunk_id を並べてください。
- 変更の理由は、チケットやコメントに書かれている場合だけ書いてください。
書かれていなければ reason は「記載なし」としてください。
- 改修依頼の要点のうち、記載が見つからなかったものは not_found に入れてください。
「影響なし」「関係ない」と書かないでください。
- 影響範囲の結論、工数、難易度を書かないでください。
「chunk_id を付けられない記載は書かない」が、この指示の要です。 出典の無い一文は、担当者が確かめようがありません。確かめられない記載を混ぜるくらいなら、書かせないほうが安全です。
「引用を言い換えない」も同じ理由です。 言い換えた瞬間に、設計書の原文との照合ができなくなります。設計書の言い回しは、そのまま検索語として次の検索にも使えます。
出力形式を固定する
次の形のJSONで受け取ります。 Azure OpenAI の構造化出力で、このスキーマに従わせます。すべてのフィールドを必須にし、省略可能な値は null との共用体型で表し、オブジェクトには additionalProperties: false を設定します。
{
"ticket_id": "",
"project_id": "",
"current_spec": [
{ "point": "", "summary": "", "quote": "", "chunk_id": "",
"doc": "", "version": "", "location": "" }
],
"history": [
{ "date": "", "what_changed": "", "reason": "", "source_ticket": "",
"journal_no": null, "chunk_id": "" }
],
"conflicts": [ { "point": "", "chunk_ids": [] } ],
"not_found": [ { "point": "", "queries_tried": [] } ]
}
1つ目の理由は、出典を機械的に検証できることです。 chunk_id が検索結果に含まれていたかを、受け取った側で突き合わせます。検索結果に無い chunk_id が1つでもあれば、その回答は捨てて出し直させます。
2つ目は、not_found に試した検索語を残せることです。 担当者は、AIが何で探して見つからなかったのかを見て、別の言い方で探し直すか、本当に書かれていないと判断するかを決められます。
3つ目は、history の journal_no で、チケットのどのコメントかまで戻れることです。
システムへ連携する
| つなぎ先 | 方式 | 内容 |
|---|---|---|
| Redmine | REST API(APIキー) | 改修依頼の取得、夜間の差分の取り込み |
| Blob Storage | 案件フォルダからの定期の複製 | 設計書の置き場 |
| Azure AI Document Intelligence | API呼び出し | 設計書の Markdown 化と、スキャンのOCR |
| Azure AI Search | インデクサー、ドキュメントの登録API、検索API | インデックスの更新と検索 |
| Azure OpenAI | API呼び出し | 検索語の取り出し、まとめ、埋め込み |
| Redmine(結果) | REST API | 仕上げた影響調査メモをチケットに添付 |
Redmine への書き込みは、担当者が仕上げたメモの添付だけです。 AIのまとめをそのままチケットに書き込みません。顧客が見るチケットに、確かめていない記載が残ります。
検索は、セキュリティ フィルターで絞ります。 インデックスに顧客のグループIDを持つ Collection(Edm.String) のフィールドを作って filterable にし、retrievable は false にします。検索のたびに group_ids/any(g:search.in(g, '...')) のフィルターを付け、 担当者が属するグループの文書だけを返します。
ただし、Azure AI Search はこのパターンでユーザーを認証しません。 セキュリティ プリンシパルは単なる文字列で、フィルターを付けるのは検索画面の側の責任です。 検索画面は、利用者の Microsoft Entra のグループを取り、案件の台帳と突き合わせてからフィルターを組み立てます。フィルターを付けない検索の経路を作らないことを、設計の決まりにします。
人が確認する
担当者が確かめるのは、出典です。 まとめの文章ではなく、current_spec と history の各行の出典を開き、引用が本当にそこにあるかを見ます。
current_specの出典を開く … 引用がその文書・その版・その場所にあるかを見ますconflictsを確かめる … 古い版と最新版の食い違いは、実装を見て決めますnot_foundを見て探し直す … 別の言い方で検索するか、書かれていないと判断します- ソースコードを確かめる … 設計書に無い実装の都合は、コードで確かめます
- 影響調査メモを仕上げる … 採用した出典を残して、チケットに添付します
3番目が、いちばん人の力の要るところです。 「書かれていない」と判断するには設計書の癖を知る必要があり、新しい担当者はここだけベテランに見てもらいます。
目標は、1件あたり35分です。 出典の確認に15分、not_found の探し直しに10分、コードの確認とメモの仕上げに10分という想定です。コードの確認に時間がかかる改修では35分を超えます。
例外に対処する
| 起きること | 対応 |
|---|---|
| チケットから案件を特定できない | 検索を止め、担当者に案件を選ばせる。案件なしで検索しない |
| 担当者が案件のグループに属していない | 検索せず、アクセスの申請を案内する |
| 文書の台帳に無いファイルが当たる | 「版不明」として返し、台帳への登録を促す |
検索結果に無い chunk_id が出力に含まれる | 回答を捨てて出し直させる。続けば検索結果だけを返す |
| 検索結果が少なすぎる | 検索語を担当者に見せ、言い換えを足して再検索する |
| Excel の表が崩れて読めない断片になる | 前処理の組み直しの対象に足す |
| 埋め込みモデルの呼び出しが上限に達する | インデクサーの再試行に任せ、スケジュール実行で拾う |
| Redmine の API が応答しない | 前回の取り込みの時点のインデックスで検索し、その旨を表示する |
上の2行が、この構成でいちばん重い例外です。 どちらも、案件の範囲が決まらないまま検索が走ることを止めるためのものです。範囲が決まらないときは、結果を出さないのが正しい動作です。
記録を残す
- 検索した日時、担当者、チケット番号、案件ID、付けたセキュリティ フィルター
- 取り出した検索語と、検索結果の
chunk_idの一覧 - 生成AIが返したJSONの全文と、
chunk_idの検証の結果 - 担当者が採用した出典と、採用しなかった出典
- 仕上がった影響調査メモと、チケットに添付した日時
- インデクサーの実行の記録と、取り込みに失敗したファイル
1行目でフィルターを残すのは、後から確かめるためです。 顧客から「当社の情報が他社の調査に使われていないか」と問われたとき、どの検索がどの範囲で行われたかを示せるようにしておきます。
4行目は、検索の質を上げる材料です。 採用されなかった出典が多い文書は、分割の仕方か、文書の台帳の版の付け方に問題があります。
04実装レベルの3段階
最小構成は1案件しか扱えず、 顧客ごとに範囲を閉じる仕組みもありません。確かめるための段階です。 半自動化で、1件90分が55分程度になります。 設計書の記載箇所を探す時間は大きく減りますが、チケットを探して読む時間が残ります。本格構成で35分になり、この段階が本記事の想定です。 差が大きいのは、経緯の調べが、チケットのコメントを1件ずつ読む手作業だからです。 段階を飛ばさないでください。 半自動化を数か月使うと、どの案件の文書の台帳が足りないか、どの設計書の分割が悪いかが分かります。そこを直してからチケットを足すほうが、検索の精度が早く上がります。
05工数削減シミュレーション
導入後 120件 × 35分 ÷ 60 = 70 時間/月
自社条件で導入効果を整理したい方へ
このユースケースを自社に当てはめた場合の前提値と削減見込みを、業務ヒアリングをもとに整理します。
06向いている企業・向いていない企業
- 複数の顧客から受託したシステムを長年保守しており、改修依頼のたびに、担当者が過去の設計書・仕様書と変更管理の記録を探して影響を調べている受託開発の会社や、社内の情報システム部門。設計書がExcelやWordで案件ごとのフォルダに残り、版が重なっている場合。変更の経緯がRedmineなどのチケットに記録されていて、APIで取り出せる場合。開発当時の担当者が異動・退職して、経緯を聞ける人がいない場合。
- 設計の情報がすでにリポジトリ上の文書やコードのコメントに一元化され、検索で足りている場合。保守しているシステムが1つで、設計書が数十ファイルに収まる場合。なお、改修の影響範囲を最終的に決めること、ソースコード上の影響を確かめることは、この構成では代替できません。
07最小構成で試す方法
- 改修依頼の多い1つの案件を選び、その案件の設計書から20ファイルと、過去2年分のチケットを書き出す
- 先月の改修依頼から5件を選び、当時の影響調査メモを用意する
- 社内で利用が認められている生成AIの、ファイルを読み込んで答える機能に、1の設計書とチケットの書き出しを入れる
- 5件の改修依頼の本文を渡し、「この資料だけを根拠に、対象機能の記載箇所をファイル名と場所付きで並べてください。見つからないものは見つからないと書いてください」と指示する
- 出てきた一覧を、当時の影響調査メモと突き合わせる
5件は必ずやってください。 インデックスを作る前に、自社の設計書の書き方で、どこまで当たるかを確かめます。
| 出てきた内容 | 判断 |
|---|---|
| 当時のメモとほぼ同じ記載箇所が、場所付きで出た | インデックスの構築に進む |
| 記載箇所は出るが、古い版の記載が混ざる | 文書の台帳が先。構成は有効 |
| テーブル定義書の記載が、ほとんど当たらない | Excel の表の組み直しが先。 AIの問題ではない |
3行目が出たら、 テーブル定義書を1行1文に書き直して入れ直し、どこまで当たるかを見てください。
08実装時につまずきやすいポイント
| 問題 | 対策 |
|---|---|
| 他の顧客の設計書が検索結果に混ざる | すべての検索にセキュリティ フィルターを付ける。 フィルターの無い経路を作らない |
| 見つからなかったことを「影響なし」と書く | not_found に入れさせ、影響の結論を書かせない |
| 出典の無い一文が混ざる | chunk_id を検証し、検索結果に無いものがあれば捨てる |
| 古い版の記載を今の仕様として返す | 文書の台帳で最新版を決め、古い版は history に入れる |
| Excel のテーブル定義書が当たらない | XLSXはテーブル分析の対象外。1行1文に組み直す |
| 機能IDやテーブル名で当たらない | ハイブリッド検索にし、キーワード側で完全一致を拾う |
| 日本語の文章が1つのトークンになる | ja.microsoft か ja.lucene を設定する。作成時に決める |
| チケットの経緯が取れない | 一覧の取得では journals を指定できない。1件ずつの取得で取る |
| 埋め込みの呼び出しが上限に達する | インデクサーをスケジュールで動かし、再試行に任せる |
| 案件IDの付かないチャンクがある | 付かないものは登録しない |
| AIのまとめをそのままチケットに書き込む | 担当者が仕上げたメモだけを添付する |
上の3行が、この構成の失敗のほとんどです。 どれも「AIが答えを出す」と考えた瞬間に起きます。この構成のAIは、出典の地図を作る係です。
09セキュリティ・AIガバナンス上の注意点
この構成で扱うデータ: 顧客から受託したシステムの設計書・仕様書、テーブルの定義、インターフェースの仕様、障害と改修の記録です。いずれも顧客の営業秘密にあたりうる情報で、保守契約の秘密保持の条項の対象です。
- 顧客との契約で、クラウドの検索と生成AIの利用を確かめる … 設計書を Azure のサービスに入れることが、保守契約の秘密保持の条項や再委託の取り決めに沿うかを、顧客ごとに確かめます。 認められない顧客の案件は、インデックスに入れません
- 顧客ごとに検索の範囲を閉じる … セキュリティ フィルターを、検索画面の側で必ず付けます。Azure AI Search はこのパターンでユーザーを認証しないため、 付ける責任は自社の仕組みにあります
retrievableを外すことをセキュリティの仕組みと考えない … グループIDのフィールドを返さない設定は、内容を隠す仕組みでもフィールド単位のセキュリティでもないとされています。守るのは、すべての検索に付けるフィルターです- 生成AIに渡すのは検索結果の範囲だけにする … 設計書の全文を渡しません。その検索で絞り込まれたチャンクだけを渡します
- 影響範囲の判断をAIに任せない … AIのまとめは材料です。見積と顧客への説明の根拠になるメモは、担当者が出典を確かめて書きます。 契約が終わった顧客の文書をインデックスからいつ消すかも決めておきます
誤りが起きた場合のリスクは、他の顧客の情報を見せることと、見つからなかったことを影響なしとして見積に進むことの2つです。 前者はフィルターの付け忘れで起き、後者は not_found を設けないと起きます。どちらも、仕組みの決まりとして閉じます。
10まず何から始めるか
1週目:1案件の台帳を作る
改修依頼のいちばん多い案件を1つ選び、設計書のファイルごとに文書種別、版、最新版かどうかを一覧にします。Redmine のその案件のチケットを、REST API で書き出せるかも確かめます。
2週目:5件で試す
選んだ案件の設計書20ファイルとチケットの書き出しを、生成AIのファイル読み込みの機能に入れ、先月の改修依頼5件で記載箇所を出させます。当時の影響調査メモと突き合わせ、見つからなかったものを「影響なし」と書いていないかを最優先で見ます。
3週目:インデックスを作る
Azure AI Search に、その案件の設計書のインデックスを作ります。日本語のアナライザーを設定し、案件IDとグループIDのフィールドを最初から入れます。 Excel のテーブル定義書は、1行1文に組み直してから入れます。
4週目:検索画面をつなぐ
チケット番号から案件を特定し、フィルターを付けて検索し、出典付きの一覧を返すところまで作ります。この時点では Redmine のチケットは入れず、設計書の記載箇所だけを出します。 担当者3名に使ってもらい、採用された出典の割合を数えます。
2か月目: Redmine のチケットの取り込みと経緯の時系列を足します。3か月目以降: 案件を順に増やし、1件90分が何分になったかを実測します。改修依頼の多い10案件まで広げ、新しい担当者がベテランに聞かずに影響調査メモの下書きまで進めた時点で、この構成は完成です。
11関連ユースケース
12この仕組みを理解するための記事
13技術仕様の確認日・参考情報
| 確認した内容 | 情報源 | 確認日 |
|---|---|---|
| ハイブリッド検索が全文検索とベクトル検索を1つの要求で並列に実行し、逆ランク融合(RRF)で結果をまとめること。製品コード、専門用語、日付、人の名前のような完全一致が要るクエリではキーワード検索が強いこと。フィルターを併用できること。セマンティック ランク付けは省略可能であること | Microsoft Learn: ハイブリッド検索の概要 | 2026-10-06 |
| 統合ベクトル化で、インデクサーがデータを取り、Text Split スキルで分割し、AzureOpenAIEmbedding スキル(text-embedding-3-large など)でベクトル化すること。クエリ時は同じ埋め込みモデルのベクトライザーを使うこと。インデクサーをスケジュールで実行することが推奨され、埋め込みモデルのスロットリングに再試行があること。データの分割(Text Split スキル)が無料であること | Microsoft Learn: 統合ベクター化の概要 | 2026-10-06 |
セキュリティ フィルターが、グループIDの Collection(Edm.String) フィールド(filterable を true、retrievable を false)と search.in のフィルターで結果を絞ること。セキュリティ プリンシパルによる認証や認可はなく、プリンシパルは単なる文字列であること。retrievable を false にすることはコンテンツの難読化やフィールド レベルのセキュリティではないこと。mergeOrUpload でグループの一覧を更新できること | Microsoft Learn: セキュリティ フィルター パターン | 2026-10-06 |
| 日本語ではスペースが単語の区切りではなく、言語に依存しないアナライザーでは文字列全体が1つのトークンになりうること。日本語のアナライザーとして ja.microsoft と ja.lucene があること。アナライザーはインデックスの作成時、データの読み込み前に設定すること | Microsoft Learn: 文字列フィールドに言語アナライザーを追加する | 2026-10-06 |
| レイアウトモデルがPDF、画像、Word、Excel、PowerPoint、HTMLに対応し、抽出したテキストを Markdown で出力できること。Excel はワークシートごとに1ページ単位であること。入力がXLSXの場合はテーブルの分析がサポートされないこと。Office文書の埋め込みの画像はサポートされないこと | Microsoft Learn: ドキュメント レイアウト分析 | 2026-10-06 |
Redmine の REST API で、一覧の取得(GET /issues.json)に offset・limit・updated_on・status_id=* を指定できること。一覧の取得の include は attachments と relations、1件の取得(GET /issues/[id].json)の include は journals・changesets・relations などであること。APIキーで認証できること | Redmine: Rest Issues | 2026-10-06 |
設計書をクラウドの検索や生成AIに入れてよいかは、顧客との保守契約の条項に従ってください。 本記事は、製品の公開仕様で確認できた範囲だけを扱っています。
実装ステータス:構成例。 公開仕様に基づいて設計した構成であり、当社で実際に構築・検証したものではありません。工数の数値はモデル条件による試算です。
自社の業務に使えるAI活用候補を整理します
このユースケース(UC-0464)についてのご相談はこちらから。
