Azure AI SearchのDB取り込みでハマったら読むといい記事

## はじめに
Azure OpenAIを利用してRAGをやるときのデータ取り込みは各定義の不一致でエラーが
出やすいので、ハマりやすい部分を中心にどのように合わせればいいのかをまとめました。

なお、こちらの記事でテンプレが提供されています。
https://qiita.com/tuneyukkie/items/db16d929475c10a6a57d

テンプレを使って楽に取り込みを行ってもらいつつ、脳死で作業してうまくいかなったときに、こちらをみてハマる前にさくっと修正してもらえることを願って、書いてみました。
 
## AI Search概要
上記記事よりお借りします👏

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566513/1070c663-6eb8-0e50-4090-cf2587dd1b15.png)

## 各リソース定義
イメージしてもらいやすいようにサンプルを用意しました。
#### sample(json) qa-index
上図と同じfield名になっています
```
{
  "name": "qa-index",
  "fields": [
    { "name": "id", "type": "Edm.String", "key": true },
    { "name": "question", "type": "Edm.String" },
    { "name": "answer", "type": "Edm.String" },
    { "name": "url", "type": "Edm.String" },
    { "name": "embedding", "type": "Collection(Edm.Double)" }
  ]
}
```

 #### sample(json) qa-indexer
 dataSourceName、targetIndexName、skillsetNameは名前通り
 データセット、インデックス、スキルセットを指定します。
 （データセットにてデータファイルの格納されたコンテナファイルを指定します）

fieldMappingsとoutputFieldMappingsはGUIでindexerを作成した時点では空になります。

fieldMappingsはdataSourceから取得したquestion,answer,url fieldをindexの各フィールドにマッピングします。fieldMappingsを指定しないと、indexerはdataSourceのfieldを使用して、indexの同じ名前のfieldにマッピングしようとします。つまり、dataSourceとindexのfiled名が一致していれば、空でも問題ありません。今回は空でも問題ありませんが、明示的に指定している形になります。

outputFieldMappingsはskill-setで作成したembeddingをindexのembedding fieldにマッピングしています。skill-setのoutputで指定した名前とindexのfiled名が一致していれば、outputFieldMappingsは空でも問題ありません。今回は空でも問題ありませんが、明示的に指定している形になります。

```
{
  "name": "qa-indexer",
  "dataSourceName": "qa-datasource",
  "targetIndexName": "qa-index",
  "skillsetName": "qa-skillset",
  "fieldMappings": [
    { "sourceFieldName": "question", "targetFieldName": "question" },
    { "sourceFieldName": "answer", "targetFieldName": "answer" },
    { "sourceFieldName": "url", "targetFieldName": "url" }
  ],
  "outputFieldMappings": [
    { "sourceFieldName": "/document/embedding", "targetFieldName": "embedding" }
  ]
}
```

#### sample(json) qa-skillset
/document/answerからテキストデータを取得します。
/answerはデータファイル内のanswewr fieldを示しています。
/document/はAzure Cognitive Searchでのデータ処理のコンテキストを表しています（固定）

skillsetによって生成されたembeddingは
qa-indexerのoutputFieldMappingsにてqa-indexのembedding fieldにマッピングされており
qa-indexのembedding fieldに格納されます。

```
{
  "name": "qa-skillset",
  "skills": [
    {
      "@odata.type": "#Microsoft.Skills.Text.AzureOpenAIEmbeddingSkill",
      "name": "answer-embedding-skill",
      "description": "Generates embeddings for the answer field.",
      "context": "/document",
      "inputs": [
        {
          "name": "text",
          "source": "/document/answer"
        }
      ],
      "outputs": [
        {
          "name": "embedding",
          "targetName": "embedding"
        }
      ],
      "resourceUri": "https://your-resource-name.openai.azure.com",
      "deploymentId": "text-embedding-3-small",
      "apiKey": "your-api-key",
      "modelName": "text-embedding-3-small",
      "dimensions": 1536
    }
  ]
}
```

#### sample　データファイル(CSV)
今回データファイル内のfieldはindexと統一しました。
統一していれば、indexerでのfieldMappings指定が必須でなくなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566513/ee095db7-3514-cf0b-fc29-abea2bd8bd93.png)

indexとindexer、skill-setの各定義をマッピングすると次のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566513/58d6bed4-5a6b-64f2-7012-26669a11df91.png)

## まとめ

・indexerのfieldMappingsとoutputFieldMappingsがハマりポイント。
・fieldMappingsはデータファイル内のfield名とindexのfield名を統一させていれば記述不要。
・outputFieldMappingsはskill-setの出力名とindexのfield名を統一させていれば記述不要。
・それぞれのfield名が異なる場合はfieldMappings、outputFieldMappingsでマッピングさせてあげる。

indexer実行時にうまくいかなったときは、あわてず定義が正しいかチェックしてみましょう！