この記事のゴール
- 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 | 内蔵ツール | 必要に応じてインターネット検索を実行 |
実装ステップ一覧
- Files API:ファイルをアップロード →
file_idを取得 - Vector Store 作成 →
vs_idを取得 - Vector Store にファイルを紐付け(
file_idを登録) - (必要なら)ステータス確認ポーリング:
in_progress→completedになるまで待つ - Responses API:
- ① ファイルのみ検索(File Search ツールだけ)
- ② ファイル+Web検索(Web Search ツールも追加)
- 回答テキストを表示/保存
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 ✓)
- Param1:
※
purposeにresponseを入れると 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
status が completed になったら検索に使えます。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_json | JSONにコメント/余計なカンマ | コメント禁止、末尾カンマ削除 |
| 400 purpose エラー | purpose が assistants 以外 | assistants に修正 |
| 400 unknown_parameter | 未対応フィールド(例: web_search_options) | そのキーを削除 |
| 401 Unauthorized | Authorizationヘッダー不備/キー違い | 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検索を混ぜるときは
toolsにweb_searchを追加するだけ。 - 精度とコストは
max_num_resultsやプロンプト、ファイル分割戦略でチューニング。
必要なら:
- Backend workflow の設定スクショ付き手順
- BubbleのJSON整形Tips(:format as JSON-safe など)
- SupabaseやCloudflare Workerを中継にした高度実装
も追記できます。お気軽にどうぞ!