OpenAI の APIからRAGをつかえるようにExcel VBA を修正した話

前回、下記の通り Excel VBA から OpenAI の Response API を使えるようにしました。

そこで今回は1歩先に進めて、Excel VBAからRAG連携するように改修しましたのでここにその内容を記録しておきます。

主に修正したのは下記の4箇所です。

修正①:RAGで使用するVector Store IDの設定

Vector Store IDについては以下の回で取得したものを設定しています。

修正②:max_output_tokensの変更

Response APIにてRAGを使うようになりOpenAIからのレスポンスが大きくなってきたので値を2000から10000に大きくしています。

修正③:OpenAIへのリクエストに tools を追加

OpenAIへのリクエストの中に以下のJSONを追加し、file_search を行うようにしています。

  "tools": [
{
"type": "file_search",
"vector_store_ids": [
"vs_xxxxxxxxx"
]
}
]

修正④:JsonConverterを使う形に変更

Response APIにてRAGを使うようになりOpenAIからのJSONが複雑、かつUnicodeエスケープ化されて返ってくるようになったので、JsonConverterを利用するように変更しています。

上記3つを修正した結果は以下の通りです。

Option Explicit

Const API_URL As String = "https://api.openai.com/v1/responses"

'★①RAGで使用するVector Store ID
Const VECTOR_STORE_ID As String = "vs_xxxxxxxxxx"

Sub ApplyAddressCorrection()
Dim apiKey As String
Dim text As String
Dim response As String
Dim responseArray() As String
Dim ws As Worksheet
Dim i As Long

Set ws = ActiveSheet
ws.Range("B5").CurrentRegion.ClearContents

apiKey = Environ("OPENAI_API_KEY")

If apiKey = "" Then
MsgBox "OpenAI APIキーが設定されていません。", vbCritical
Exit Sub
End If


text = ws.Range("B2").Value & ws.Range("B3").Value

'★②max_output_tokensを2000から10000に変更
'★③OpenAIへのリクエストに tools を追加
text = _
"{""model"":""gpt-5-nano""," & _
"""max_output_tokens"":10000," & _
"""input"":""" & text & """," & _
"""tools"":[{" & _
"""type"":""file_search""," & _
"""vector_store_ids"":[""" & VECTOR_STORE_ID & """]" & _
"}]}"

response = sendAPIRequest(API_URL, text, apiKey)

Debug.Print response

response = ExtractResponseText(response)

ws.Range("B5").Value = response

response = Replace(response, "\n", vbLf)
If ws.Range("D5").Value = "する" Then response = Replace(response, "。", "。" & vbLf)
responseArray = Split(response, vbLf)
For i = 0 To UBound(responseArray)
ws.Range("B" & 5 + i).Value = responseArray(i)
Next i
End Sub

Function sendAPIRequest(url As String, text As String, apiKey As String) As String
Dim request As Object
Set request = CreateObject("MSXML2.XMLHTTP")
request.Open "POST", url, False
request.setRequestHeader "Content-Type", "application/json"
request.setRequestHeader "Authorization", "Bearer " & apiKey
request.send text
sendAPIRequest = request.responseText
End Function

'★④JsonConverterを使う形に変更
Function ExtractResponseText(response As String) As String

Dim json As Object
Dim outputItem As Variant
Dim contentItem As Variant

On Error GoTo ErrorHandler

'JSON文字列を解析
Set json = JsonConverter.ParseJson(response)

'output配列を順番に確認
For Each outputItem In json("output")

'messageタイプを探す
If outputItem("type") = "message" Then

'content配列を確認
For Each contentItem In outputItem("content")

'output_textを探す
If contentItem("type") = "output_text" Then

'textを取得
ExtractResponseText = contentItem("text")
Exit Function

End If

Next contentItem

End If

Next outputItem

'output_textが見つからなかった場合
ExtractResponseText = response
Exit Function

ErrorHandler:

ExtractResponseText = response

End Function

実際にこれを実行したところ、以下のような結果となりました。

OpenAIのAPIをつかってRAGを行う為に検索対象のファイルを準備してみた

題名のとおり、OpenAIのAPIをつかってRAGを行う為に検索対象のファイルを準備してみました。

大まかな流れは以下の通りです。

① 検索対象ファイルを作成

② File APIへアップロード

  File IDを取得

③ Vector Storeを作成

  Vector Store IDを取得

④ File IDをVector Storeへ登録

   Responses APIからFile Search

1.検索対象ファイルを作成

とりあえず今回は以下の料理レシピを作成し、RAGとして登録してみることにしました。なお最初、別のデータをcsvで登録しようとしたのですがなぜかうまくいかなかったので、マークダウンファイル(recipe.md)として作成しました。

# 鶏の照り焼き

##材料
鶏もも肉 300g
しょうゆ 大さじ2
みりん 大さじ2
砂糖 大さじ1

##所要時間
約20分


# 親子丼

##材料
鶏もも肉 150g
卵 2個
玉ねぎ 1/2個
しょうゆ 大さじ1
みりん 大さじ1

##所要時間
約15分

2.File APIへアップロード

対象ファイルを作成したら、まずは下記の curl コマンドを利用し、OpenAIのFile APIにアップロードします。

なお、$OPENAI_API_KEYでは環境編集として設定した API_Keyを読み込んでいます。また、purposeのところは色々な指定ができるようですが、今回は user_data (RAGなどの一般的なファイル利用に使える目的)としています。

curl https://api.openai.com/v1/files \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-F purpose="user_data" \
-F file="@recipe.md"

うまくいくと以下のような回答が返ってきますので、”file-xxxxxxxxxxxxxxxx”(File ID)をメモしておきます。

{
"id": "file-xxxxxxxxxxxxxxxx",
"object": "file",
"bytes": 1234,
"created_at": 1750000000,
"filename": "recipe.md",
"purpose": "user_data"
}

3.Vector Storeを作成

次に以下の curlコマンドを実行し、Vector Storeを作ります。

curl.exe https://api.openai.com/v1/vector_stores `
-H "Authorization: Bearer $env:OPENAI_API_KEY" `
-H "Content-Type: application/json" `
-d '{\"name\":\"料理レシピRAG\"}'

こちらもうまくいくと以下のような回答が返ってくるので”vs_xxxxxxxxxxxxx”(Vector Store ID)をメモしておきます。

{
"id": "vs_xxxxxxxxxxxxx",
"object": "vector_store",
"name": "料理レシピRAG",
...
}

4.File IDをVector Storeへ登録

最後にこれまでで取得した”file-xxxxxxxxxxxxxxxx”(File ID)と”vs_xxxxxxxxxxxxx”(Vector Store ID)を使い、File IDをVector Storeへ登録します。

curl.exe https://api.openai.com/v1/vector_stores/vs-xxxxxxxx/files `
-H "Authorization: Bearer $env:OPENAI_API_KEY" `
-H "Content-Type: application/json" `
-d '{\"file_id\":\"file-xxxxxxxx\"}'

成功すると以下のような回答が返ってきます。

{
"id": "file-xxxxxxxxx",
"object": "vector_store.file",
"status": "in_progress",
"vector_store_id": "vs_xxxxxxxxx",
"created_at": 1750000000
}

なお、このとき大概の場合 “status”: “in_progress”となっているので、完了を確認するには以下のコマンドを続けて実行します。

curl.exe https://api.openai.com/v1/vector_stores/vs-xxxxxxxx/files/file-xxxxxxxx `
-H "Authorization: Bearer $env:OPENAI_API_KEY"

これで”status”: “completed”となっていれば完了です。

ちなみに冒頭で書いたように最初 csvで登録しようとしたら failed となったので、正しく登録できたかどうか”status”: “completed”になるまで確認したほうがよさそうです。

補足(ファイル一覧取得)

OpenAI APIには「Vector Storeに登録されたファイル一覧」を取得するAPIがあります。

curl.exe https://api.openai.com/v1/vector_stores/vs-xxxxxxxx/files `
-H "Authorization: Bearer $env:OPENAI_API_KEY"

これを実行すると以下のような回答が得られ、Vector Store内のファイル一覧を取得することが可能です。

{
"object": "list",
"data": [
{
"id": "file-xxxxxxxx",
"object": "vector_store.file",
"status": "completed"
}
]
}