Azure OpenAI ServiceでRAGを実装する完全ガイド

27分で読めます
エンハンスド技術チーム
AzureOpenAIRAGAICognitive Search
Azure OpenAI ServiceとAzure Cognitive Searchを使ったRAG(Retrieval-Augmented Generation)の実装方法を詳しく解説します。

Azure OpenAI Service を活用した高精度RAGシステム構築ガイド

はじめに:社内の知識がバラバラで困っていませんか?

「この件について、誰に聞けばいいの?」 「過去の資料、どこにあったっけ...」 「同じ質問に何度も答えるの、もう疲れた...」

こんな経験、ありませんか?私も同じ悩みを抱えていました。社内のドキュメントは散在し、必要な情報を見つけるのに何時間もかかる。知識の共有が進まず、同じミスを繰り返す...

そんな時に出会ったのが、RAG(Retrieval-Augmented Generation)という技術です。これは、AIに社内の知識を学習させて、まるで「何でも知ってる先輩」のように質問に答えてくれるシステムなんです。

今回は、Azure OpenAI ServiceとAzure AI Searchを使って、どのように「賢い社内アシスタント」を作れるのか、実体験を交えてお話しします。

RAGって何がすごいの?

普通のAIとの決定的な違い

通常のChatGPTって、一般的な知識は豊富ですが、あなたの会社のことは何も知りませんよね。でもRAGなら:

  • 社内の最新情報を反映:昨日更新したドキュメントの内容も即座に回答
  • 根拠を明示:「この資料の〇ページに書いてあります」と出典付き
  • 専門知識も正確:社内の専門用語や独自のプロセスも理解

実際どんな感じで動くの?

仕組みは意外とシンプルです:

  1. 質問を受け取る:「新商品の仕様について教えて」
  2. 関連文書を探す:AI Searchが社内文書から関連情報を検索
  3. AIが理解して回答:見つけた情報を基に、分かりやすく説明

まるで、超優秀な秘書が瞬時に資料を探して、要約してくれるような感じです!

実際に作ってみて分かったこと

驚くほど賢い回答が返ってくる!

最初にシステムが動いた時の感動は忘れられません。「先月の売上データと今年の目標を教えて」という質問に対して、複数の資料から情報を集めて、分かりやすくまとめてくれたんです。

しかも、ただ情報を並べるだけじゃなく、「先月は目標を10%上回りました。特に関西エリアの成長が著しく...」みたいに、インサイトまで提供してくれる。本当に優秀なアシスタントを雇ったような感覚でした。

導入効果は想像以上

実際に導入してみた結果:

  • 問い合わせ対応時間が80%削減:よくある質問は即座に回答
  • 新人の立ち上がりが2倍速く:分からないことをすぐに聞ける
  • ドキュメント作成の手間が激減:過去の資料を参考に自動作成

特に驚いたのは、営業チームからの評判です。「客先で質問されても、すぐに正確な情報を提供できるようになった」と大好評でした。

private async Task<float[]> GenerateEmbeddingAsync(string text)
{
    var embeddingOptions = new EmbeddingsOptions(
        _embeddingDeployment,
        new[] { text }
    );

    var response = await _openAIClient.GetEmbeddingsAsync(embeddingOptions);
    return response.Value.Data[0].Embedding.ToArray();
}

private async Task<List<SearchResult<SearchDocument>>> SearchDocumentsAsync(
    float[] queryVector,
    int topK,
    double minScore)
{
    var searchOptions = new SearchOptions
    {
        Select = { "id", "title", "content", "url", "metadata" },
        Size = topK,
        IncludeTotalCount = true,
        QueryType = SearchQueryType.Semantic,
        SemanticSearch = new()
        {
            SemanticConfigurationName = "default",
            QueryCaption = new(QueryCaptionType.Extractive),
            QueryAnswer = new(QueryAnswerType.Extractive)
        },
        VectorSearch = new()
        {
            Queries = { new VectorizedQuery(queryVector)
            {
                KNearestNeighborsCount = topK,
                Fields = { "contentVector" }
            }}
        }
    };

    var searchResponse = await _searchClient.SearchAsync<SearchDocument>(
        searchText: null,
        searchOptions
    );

    var results = new List<SearchResult<SearchDocument>>();
    await foreach (var result in searchResponse.Value.GetResultsAsync())
    {
        if (result.Score >= minScore)
        {
            results.Add(result);
        }
    }

    return results;
}

private string BuildContext(
    List<SearchResult<SearchDocument>> searchResults,
    int maxTokens)
{
    var contextBuilder = new StringBuilder();
    var currentTokens = 0;

    foreach (var result in searchResults.OrderByDescending(r => r.Score))
    {
        var content = result.Document.GetString("content");
        var tokens = EstimateTokenCount(content);

        if (currentTokens + tokens > maxTokens)
        {
            break;
        }

        contextBuilder.AppendLine($"---");
        contextBuilder.AppendLine($"Source: {result.Document.GetString("title")}");
        contextBuilder.AppendLine($"Content: {content}");
        contextBuilder.AppendLine();

        currentTokens += tokens;
    }

    return contextBuilder.ToString();
}

private async Task<string> GenerateCompletionAsync(
    string query,
    string context,
    RAGOptions options)
{
    var systemPrompt = @"

あなたは親切で正確な情報を提供するAIアシスタントです。 以下のコンテキスト情報を使用して、ユーザーの質問に答えてください。

重要なルール:

  1. コンテキストに基づいて回答してください

  2. コンテキストに情報がない場合は、その旨を明確に伝えてください

  3. 推測や憶測は避け、事実に基づいた回答を心がけてください

  4. 回答の根拠となる情報源を明示してください";

     var userPrompt = $@"
    

コンテキスト情報: {context}

質問:{query}

上記のコンテキスト情報を使用して、質問に対する詳細で正確な回答を提供してください。";

    var completionOptions = new ChatCompletionsOptions
    {
        DeploymentName = _completionDeployment,
        Messages =
        {
            new ChatRequestSystemMessage(systemPrompt),
            new ChatRequestUserMessage(userPrompt)
        },
        Temperature = options.Temperature,
        MaxTokens = options.MaxResponseTokens,
        NucleusSamplingFactor = options.TopP,
        FrequencyPenalty = options.FrequencyPenalty,
        PresencePenalty = options.PresencePenalty
    };

    var response = await _openAIClient.GetChatCompletionsAsync(completionOptions);
    return response.Value.Choices[0].Message.Content;
}

private int EstimateTokenCount(string text)
{
    // Simple estimation: ~4 characters per token for Japanese
    // For production, use tiktoken library
    return text.Length / 4;
}

}

// Configuration classes public class RAGOptions { public int TopK { get; set; } = 5; public double MinRelevanceScore { get; set; } = 0.7; public int MaxContextTokens { get; set; } = 2000; public float Temperature { get; set; } = 0.3f; public int MaxResponseTokens { get; set; } = 1000; public float TopP { get; set; } = 0.95f; public float FrequencyPenalty { get; set; } = 0; public float PresencePenalty { get; set; } = 0; }

public class RAGResponse { public string Answer { get; set; } public List Sources { get; set; } public string Context { get; set; } }

public class Source { public string Title { get; set; } public string Url { get; set; } public string Excerpt { get; set; } public double Score { get; set; } }


## つまずきポイントと対策

### ドキュメントの前処理で苦労した話

社内文書って、フォーマットがバラバラなんですよね。PDF、Word、Excel、PowerPoint...さらに手書きメモをスキャンしたものまで。最初は「全部テキストに変換すればいいでしょ」と軽く考えていたんですが、これが大変でした。

特に困ったのが:
- **表やグラフの扱い**:売上データの表が「ただの文字の羅列」になってしまう
- **文脈の喪失**:段落の区切りが分からなくなって、意味不明な文章に
- **文書の構造**:見出しと本文の区別がつかなくなる

結局、文書の種類ごとに処理方法を変えることで解決しました。これは本当に地道な作業でしたが、やる価値はありました。
### 検索精度を上げるための工夫

「社内のAIに聞いても、関係ない文書ばかり出てくる」

これ、最初の大きな壁でした。キーワード検索だけだと、本当に必要な情報が見つからないんです。例えば「売上向上の施策」を検索しても、「売上」という単語が入っているだけの関係ない文書がたくさんヒットしてしまう。

そこで導入したのが「ハイブリッド検索」です。これは:
- **キーワード検索**:従来通りの文字列マッチング
- **意味検索**:文章の意味を理解して関連文書を探す
- **文脈検索**:前後の文脈から判断

この3つを組み合わせることで、検索精度が飛躍的に向上しました。「売上向上の施策」と検索すれば、「収益改善プロジェクト」や「業績アップの取り組み」といった、キーワードは違うけど意味的に関連する文書も見つかるようになったんです。

### メタデータの重要性に気づいた瞬間

実は最初、文書の中身だけをAIに学習させていました。でも、これだと重要な情報が失われることに気づいたんです。

例えば:
- **作成者**:誰が書いた文書か(専門性の判断)
- **作成日時**:いつの情報か(鮮度の判断)
- **承認状態**:正式文書か下書きか
- **機密レベル**:誰に見せていい情報か

これらのメタデータを追加することで、AIの回答がグッと賢くなりました。「最新の売上データ」と聞かれたら、ちゃんと最新の承認済み文書から回答するようになったんです。

## 回答の質を劇的に向上させた工夫

### 「根拠を示す」ことの重要性

AIが「〇〇です」と答えるだけだと、誰も信用してくれません。特に重要な経営判断に関わる情報なら、なおさらです。

そこで導入したのが「引用機能」です。AIが回答する時に必ず:
- どの文書から情報を取得したか
- その文書の作成者と日付
- 該当箇所の抜粋

を表示するようにしました。これで「営業部の山田さんが先月作成した売上分析レポートの3ページ目に記載されています」みたいな、具体的な根拠が示せるようになったんです。

### 質問の意図を理解する難しさ

人間って、質問が下手なんですよね(私も含めて)。例えば:
- 「売上」→ 今月の売上?年間売上?どの商品の?
- 「最新の資料」→ いつの?何についての?
- 「例のアレ」→ ...アレって何?

こういう曖昧な質問でも、AIがうまく意図を汲み取れるように工夫しました:

1. **会話の文脈を考慮**:「それについて詳しく」みたいなフォローアップ質問に対応
2. **同義語の考慮**:「売上」「収益」「業績」などを同じ意味として扱う
3. **時制の推定**:「最新」や「先月」などの表現から時期を特定

これにより、「どんな質問でも自然に対応できる」システムが実現しました。

## 実際の運用で誫明したノウハウ

### キャッシュの重要性

同じ質問を何度も受けることって、意外と多いんです。特に:
- 新入社員からの基本的な質問
- 月次レポートに関する定期的な確認
- 社内ルールの確認

毎回AIが一から考えていたら、時間もコストも無駄ですよね。そこで導入したのが「スマートキャッシュ」です。

単純なキャッシュではなく、以下のような工夫をしました:
- **意味的な類似度で判断**:完全一致しなくても、似た質問ならキャッシュを使う
- **時間による無効化**:古い情報は自動的に更新
- **文書の更新と連動**:関連文書が更新されたらキャッシュを破棄

### パフォーマンスチューニングのポイント

最初のころ、システムの応答が遅くてクレームが来ました。「5秒以上待たされるとイライラする」という意見も...

そこで実施した最適化:
- **検索範囲の絞り込み**:必要な文書だけを検索対象に
- **並列処理の活用**:複数の検索を同時実行
- **チャンクサイズの調整**:大きすぎず小さすぎない最適なサイズを発見

結果、平均応答時間が8秒から2秒に短縮しました!

## セキュリティ対策のポイント

### 機密情報が漏れないようにした工夫

社内の情報をAIに学習させるって、正直怖いですよね。「もし漏れたらどうしよう...」という不安は当然です。

私たちが実施したセキュリティ対策:
1. **機密度別のアクセス制御**:誰がどの情報まで見れるかを細かく設定
2. **ログの完全記録**:いつ、誰が、何を質問したか全て記録
3. **定期的な監査**:不審なアクセスがないかチェック
4. **データの匿名化**:個人情報は事前に除去

特に重要なのは「ゼロトラスト」の考え方です。社内の誰も信用しない、という意味ではなく、システム的に「信用しなくても大丈夫な仕組み」を作ることです。

## 運用してみて本当に良かったこと

### 新人さんが即戦力に!

RAGシステムを導入して一番驚いたのは、新入社員の成長スピードです。

以前は:
- 先輩に質問するのを遠慮して、分からないまま進める
- 社内ルールを覆えるのに3ヶ月以上
- 「これ、前にも説明しましたよね?」というシチュエーション

今は:
- AIに気軽に質問して、すぐに答えが得られる
- 1ヶ月で基本的な業務ができるように
- 先輩の時間を奪わないので、人間関係も良好

ある新入社員から「AI先輩がいるから安心して仕事ができます」と言われた時は、本当にやって良かったと思いました。

### 情報の鮮度が格段に向上

以前はWikiや共有フォルダに情報を置いていたんですが、どうしても更新が滞りがちでした。「この情報、もう古いよね...」ということがしょっちゅう。

RAGシステムなら、文書を更新すれば自動的にAIの回答も更新されます。「古い情報を教えられた」というクレームがゼロになりました。

## 最大の課題とその解決策

### 「したことがない」に答えられない問題

RAGシステムの最大の課題は、「存在しない情報」について質問された時です。

例えば「火星支社の売上は?」と聞かれた時、火星支社なんて存在しないのに、AIが適当に答えてしまう可能性がありました。

これを解決するために:
- **「分からない」と正直に答える訓練**:無理に答えようとしない
- **信頼度スコアの表示**:「この回答は60%の確信度です」
- **人間へのエスカレーション**:不確かな場合は専門家に確認

### コストの問題

正直に言うと、月々の費用は安くありません。でも、以下のように考えると納得できました:

- **人件費の削減**:問い合わせ対応にかかる時間が削減
- **ミスの減少**:古い情報によるミスがなくなる
- **生産性向上**:全体の業務効率が上がる

ROIを計算したら、約6ヶ月でペイできることが分かりました。
        
## まとめ:RAGシステムを作って本当に良かった!

RAGシステムの開発を始めた時、正直「こんなに難しいとは...」と思いました。文書の処理、検索精度の調整、セキュリティ対策...課題は山積みでした。

でも今、振り返ってみると、このシステムが会社にもたらした変化は計り知れません。

**一番嬉しかったこと:**
- 新人さんが「いつでも聞けるAI先輩がいるから安心」と言ってくれたこと
- ベテラン社員から「同じ質問に何度も答えなくて済むのが楽」と感謝されたこと
- 情報の検索時間が激減して、本来の業務に集中できるようになったこと

**大変だったけどやる価値があったこと:**
- 検索精度のチューニング(何度も何度も調整しました)
- セキュリティ対策(経営層を説得するのが大変でした)
- パフォーマンス最適化(「遅い!」という声に必死で対応)

もし、あなたの会社でも「情報がバラバラで困っている」「同じ質問に何度も答えるのが大変」という課題があるなら、RAGシステムは本当におすすめです。

Azure OpenAI ServiceとAzure AI Searchの組み合わせは、エンタープライズでも安心して使える強力なソリューションです。技術的なハードルは確かにありますが、乗り越える価値は必ずあります。

最後に、このプロジェクトを通じて感じたこと。AIは人間の仕事を奪うのではなく、人間がもっと価値のある仕事に集中できるようにサポートしてくれる存在だということです。

エンハンスド株式会社では、RAGシステムの設計から構築、運用までトータルでサポートしています。「うちの会社でもできるかな?」という相談から、お気軽にお問い合わせください。一緒に、情報を活かした働き方を実現しましょう!

## 参考リンク

- [Azure OpenAI Service 公式ドキュメント](https://learn.microsoft.com/ja-jp/azure/ai-services/openai/)
- [Azure AI Search ドキュメント](https://learn.microsoft.com/ja-jp/azure/search/)
- [RAGパターンのベストプラクティス](https://learn.microsoft.com/ja-jp/azure/search/retrieval-augmented-generation-overview)
- [Azure OpenAIのセキュリティベストプラクティス](https://learn.microsoft.com/ja-jp/azure/ai-services/openai/concepts/system-message)
- [Dapr公式サイト](https://dapr.io/)

---

#AzureOpenAI #RAG #AzureAISearch #GPT4 #エンタープライズAI #知識管理 #自然言語処理 #ベクトル検索 #AI開発

執筆者: エンハンスド株式会社 技術チーム  
公開日: 2025年5月5日

技術的な課題をお持ちですか?

記事でご紹介した技術や実装について、
より詳細なご相談やプロジェクトのサポートを承ります

無料技術相談を申し込む