BubbleでOpenAI「Responses API+File Search」を実装する完全ガイド

Bubble

この記事のゴール

  • Bubble だけで 自前の知識データ(PDF/TXT等)を検索して回答 させる。
  • 知識データに無ければWeb検索も併用 して回答させる。
  • エラーになりやすい API Connector の具体設定とJSON例 を網羅。

この記事を手順どおり進めれば “動く” ところまで行けます。


全体像(アーキテクチャ)

ユーザー ─▶ Bubble(API Connector)
          ├─▶ Files API:ファイルをOpenAIへアップロード
          ├─▶ Vector Stores API:ベクターストア作成・ファイル登録
          └─▶ Responses API:
                 ・File Searchツールで社内文書を検索
                 ・必要ならWeb Searchツールでネット検索
                 ・最終回答を返却

事前準備

  • OpenAI APIキーを取得(環境変数やBubbleのSecretsに保存推奨)
  • Bubbleプラグイン API Connector をインストール
  • (任意)ファイルをアップロードさせるための File Uploader 要素を用意

用語整理

用語役割ざっくり説明
Files API生ファイルアップロードPDF/TXTなどをOpenAIに送る
Vector Storeインデックス格納庫ファイルを分割・埋め込みして検索できる状態にする箱
File Search内蔵ツールVector Storeに入っている文書から関連箇所を検索
Responses API本体モデル呼び出し+ツール実行+回答生成
Web Search内蔵ツール必要に応じてインターネット検索を実行

実装ステップ一覧

  1. Files API:ファイルをアップロード → file_id を取得
  2. Vector Store 作成vs_id を取得
  3. Vector Store にファイルを紐付けfile_id を登録)
  4. (必要なら)ステータス確認ポーリングin_progresscompleted になるまで待つ
  5. Responses API
    • ファイルのみ検索(File Search ツールだけ)
    • ファイル+Web検索(Web Search ツールも追加)
  6. 回答テキストを表示/保存

1. Files API:ファイルアップロード

API Connector 設定例

  • Name: fileUpload
  • Use as: Action / Data type: JSON
  • Method: POST
  • URL: https://api.openai.com/v1/files
  • Headers:
    • Authorization: Bearer YOUR_API_KEY
  • Body type: Form-data
    • Param1: purpose (text) = assistants
    • Param2: file (file) = FileUploader の value(Send file ✓)

purposeresponse を入れると 400 エラーになります。必ず assistants

レスポンス例

{
  "object": "file",
  "id": "file-QLQLjixUpfsuP5Zr6xqJCX",
  "purpose": "assistants",
  "filename": "manual.pdf",
  "bytes": 11877,
  "status": "processed"
}

この id(例:file-QLQL...)を保存します。


2. Vector Store 作成

  • Name: vectorStore_create
  • Method: POST
  • URL: https://api.openai.com/v1/vector_stores
  • Headers: Authorization: Bearer YOUR_API_KEY, Content-Type: application/json
  • Body (raw JSON):
{ "name": "MyKB" }

返却の id(例:vs_6884...)を保存。


3. Vector Store にファイルを追加

単一ファイル(最も簡単)

  • Name: vs_add_file
  • Method: POST
  • URL: https://api.openai.com/v1/vector_stores/[vs_id]/files
    • [vs_id] はパラメータ化。Initialize時に一旦実値を入れる。
  • Headers: Authorization: Bearer ..., Content-Type: application/json
  • Body:
{ "file_id": "file-QLQLjixUpfsuP5Zr6xqJCX" }

レスポンス例(最初は status: "in_progress"

{
  "id": "file-QLQLjixUpfsuP5Zr6xqJCX",
  "object": "vector_store.file",
  "status": "in_progress"
}

4. ステータス確認(ポーリング)

  • Name: vs_get_file_status
  • Method: GET
  • URL: https://api.openai.com/v1/vector_stores/[vs_id]/files/[file_id]
  • Headers: Authorization だけでOK

statuscompleted になったら検索に使えます。Bubbleでは Backend workflow(API Workflow)で数秒おきに再実行するのが楽です。


5-A. 回答取得:ファイルだけで検索する

API Connector 設定(Responses API)

  • Name: responses_ask_local
  • Method: POST
  • URL: https://api.openai.com/v1/responses
  • Headers: Authorization: Bearer ..., Content-Type: application/json
  • Body (raw JSON):
{
  "model": "gpt-4o-mini",
  "input": "<質問文>",
  "tools": [
    {
      "type": "file_search",
      "vector_store_ids": ["<vs_id>"],
      "max_num_results": 3
    }
  ]
}

max_num_results: 取り出すチャンク上限(3〜8くらいで調整)。

レスポンスの取り出し
response.output_text 相当の場所をBubbleでパースします。公式SDKと違い、Raw JSON内の output[0].content[0].text.value 等を使うことになります(仕様は随時変わるため、Initialize時に確認)。


5-B. 回答取得:ファイル+Web検索も使う

ファイルに無いときだけWeb検索させたいなら、ツールを2つ指定します。

{
  "model": "gpt-4o-mini",
  "input": "<質問文>",
  "tools": [
    {
      "type": "file_search",
      "vector_store_ids": ["<vs_id>"],
      "max_num_results": 3
    },
    { "type": "web_search" }
  ]
}

web_search_options など未サポート項目を入れると 400 エラーになります。必要最小限でOK。

優先順位を明示したいときのプロンプト例

まずVector Store内の情報だけで回答してください。該当が無い場合のみweb_searchツールを使い、上位2〜3件を要約して補足してください。見つからない場合は「見つからない」と答えてください。

2段階方式(アプリ側制御)も有効

1回目:File Searchだけで投げる → 返答が空/曖昧なら
2回目:Web Searchも付けて再質問


6. 画面表示・保存

  • Bubbleのテキスト要素に APIレスポンスのフィールドをバインド
  • チャット履歴を作るなら DB に質問・回答・参照ファイルIDを保存
  • 引用元(annotations)のURLやファイル名を表示して透明性UP

エラー対策まとめ

症状原因対処
400 invalid_jsonJSONにコメント/余計なカンマコメント禁止、末尾カンマ削除
400 purpose エラーpurposeassistants 以外assistants に修正
400 unknown_parameter未対応フィールド(例: web_search_options)そのキーを削除
401 UnauthorizedAuthorizationヘッダー不備/キー違いBearer <space> API_KEY を再確認
“issue getting the file”Data typeをFileにしていた/Send file未チェックData type=JSON、Send file✓

応用:複数Vector Store/メタデータフィルタ

  • vector_store_ids は配列。用途や部門ごとにVSを分け、配列で渡すだけ。
  • 1つのVector Storeに集約してもOK。その場合はファイル登録時に metadata を付け、metadata_filter で絞り込む実装(現状SDKが楽、BubbleでもJSONで可)。

参考プロンプト集

  • ファイルのみ回答 添付ファイル群に含まれる情報だけを使って回答してください。根拠が無ければ「該当情報なし」と答えてください。
  • ファイル優先+Web補完 まずVector Store内の情報だけで回答し、無い場合にのみweb_searchを実行して補足してください。検索結果はURLを明記し、3件以内に要約してください。

まとめ

  • Bubbleでも ノーコードでRAG(簡易版) が組める。
  • ポイントは API Connectorでの正しいJSON/ヘッダー設定ポーリング
  • Web検索を混ぜるときは toolsweb_search を追加するだけ
  • 精度とコストは max_num_results やプロンプト、ファイル分割戦略でチューニング。

必要なら:

  • Backend workflow の設定スクショ付き手順
  • BubbleのJSON整形Tips(:format as JSON-safe など)
  • SupabaseやCloudflare Workerを中継にした高度実装
    も追記できます。お気軽にどうぞ!