Response APIのWeb Search機能をPHPで実装:最新情報を取得できるチャットボットの作り方
作成日:2025.03.17
更新日:2025.03.24
Response APIの新機能"Web Search"を使って、インターネット上の最新情報を取得できるチャットボットを作ります。PHPによる実装方法や、APIレスポンスの処理方法など、実用的な内容をコード例とともに解説していきます
前回の記事、OpenAIの新APIを使ってみた:Response APIによるチャットボットをPHPで実装に続いて、今回も引き続き Response API を使ってみます。
今回は、Web Search の機能を利用して、チャットボットがWebから情報を取得して回答するようにしてみます。
Web Search とは
AIモデルがインターネット上の最新情報にアクセスし、リアルタイムで最新のデータを含む応答を生成する機能です。
Web Searchツールを使用することで、AIモデルはインターネット上の最新情報をリアルタイムで取得し、ユーザーの質問に対してより信頼性の高い応答を提供できます。
ツールは、特定のキーワードや質問に基づいてWeb上の情報を検索し、結果をAIモデルに提供します。
Web Search の実装
Web Search の実装は、前回の記事で作成したチャットボットのコードをベースに行います。
前回作成した chat.php の createResponse
関数を以下のように変更します。
// Response API 実行
function createResponse($message) {
// リクエストデータの作成
$data = array(
'input' => $message,
'model' => 'gpt-4o-mini',
'temperature' => 0.8,
'instructions' => 'あなたは将棋のプロ棋士の対局情報を提供するAIアシスタントです。ユーザーの質問に対して、Web検索を行い、最新の将棋のプロ棋士の対局情報を提供します。',
'tool_choice' => 'required',
);
// previous_response_id がセッションに存在する場合、リクエストデータに追加
if(isset($_SESSION['previous_response_id'])) {
$data['previous_response_id'] = $_SESSION['previous_response_id'];
}
// リクエストデータに Web Search のツールを追加
$functions = array();
$functions[] = array(
'type' => 'web_search_preview',
'user_location' => array(
'type' => 'approximate',
'city' => 'Nara',
'country' => 'JP',
'timezone' => 'Asia/Tokyo',
),
);
$data['tools'] = $functions;
// リクエストデータをJSON形式に変換
$json_data = json_encode($data);
// curl でリクエスト送信
$url = 'https://api.openai.com/v1/responses';
$headers = array(
'Content-Type: application/json',
"Authorization: Bearer ".OPENAI_API_KEY
);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json_data);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 300);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 300);
$api_response = curl_exec($ch);
if($api_response === false){
echo 'Curl error: ' . curl_error($ch);
exit;
}
curl_close($ch);
$apiresult = json_decode($api_response);
if (json_last_error() !== JSON_ERROR_NONE) {
die('APIレスポンスの解析に失敗しました: ' . json_last_error_msg());
}
return $apiresult;
}
前回からの変更点は、主にリクエストデータの作成時の処理です。
- instructions
- カスタムインストラクションの内容を、「あなたは将棋のプロ棋士の対局情報を提供するAIアシスタントです。ユーザーの質問に対して、Web検索を行い、最新の将棋のプロ棋士の対局情報を提供します。」と変更しました。
今回使用しているモデルgpt-4o-mini
の知識のカットオフは、2023年10月1日となっていますが(※OpenAIのドキュメント参照)、Web Search の機能を使用することで、それ以降の知識を必要とする質問にも答えられるようになります。 - tool_choice
- tool_choice を 'required' と指定しました。
これにより、ツールの使用が必須となり、必ずWeb Search の機能を使用して回答するようになります。 - tools
- tools に Web Search を指定しました。
Web Search は、以下のパラメータで指定します。- type
- ツールの種類を指定します。
Web Search の場合は、'web_search_preview' と指定します。 - user_location
- ユーザーの位置情報を指定します。指定しないと、デフォルトで
country: US
が指定されるので、日本のユーザーが利用することを想定する場合は、ちゃんと指定しておいた方が検索の精度が良くなるかも?- type: approximate (固定値)
- city: 都市名(フリーテキスト)
- country: 国名(ISO 3166-1 alpha-2)
- timezone: IANAタイムゾーン
- search_context_size
- ツールが応答を作成するために Web から取得するコンテキストの量を制御します。
今回は指定していませんが、low
、medium
、high
のいずれかを指定することができます。
指定しない場合は、デフォルトでmedium
が指定されます。
コンテキストサイズは、そのままAPI利用料金に影響します。もちろんコンテキストサイズを大きくすると、API利用料金が高くなります。
※参考:Pricing - OpenAI API
これで、チャットボットがWeb Search の機能を使用して回答するようになります。
動作確認
動作確認のため、チャットボットに以下のような質問をしてみます。
今期の叡王戦の挑戦者候補は?
すると、チャットボットがWeb Search の機能を使用して以下のように回答しました。
第10期叡王戦の挑戦者候補は、2025年3月14日時点で以下の通りです。
- **準決勝進出者**:
- 斎藤慎太郎八段
- 糸谷哲郎八段
これらの棋士が挑戦者決定戦で対局し、勝者が伊藤匠叡王への挑戦権を獲得します。
なお、藤井聡太七冠は準決勝で糸谷八段に敗れ、挑戦者決定戦進出を逃しました。
([ameblo.jp](https://ameblo.jp/syougichan/entry-12887796015.html?utm_source=openai))
最新の対局結果や詳細な情報は、将棋連盟の公式サイトや主要なニュースサイトでご確認いただけます。
見事に正しい情報を回答してくれました(「準決勝進出者」という言葉がおかしいですが)。
ちなみに、Web Search の機能を使用しない場合は、以下のように回答しました。
今期の叡王戦の挑戦者候補については、公式な情報を確認する必要がありますが、最近の将棋界では若手棋士が注目されていますね。もし特定の選手に興味があれば、その選手についてお話ししましょうか?
すんごい当たり障りのないことだけ言ってきて、なんかじわじわ笑える。
API のレスポンスについて
Web Search の機能を使用した場合、API のレスポンスに以下のようなデータが含まれています。
(前略)
"output":[
{
"type":"web_search_call",
"id":"ws_1234567890",
"status":"completed"
},
{
"type":"message",
"id":"msg_1234567890",
"status":"completed",
"role":"assistant",
"content":[
{
"type":"output_text",
"text":"AIのレスポンステキスト",
"annotations":[
{
"type":"url_citation",
"start_index":1,
"end_index":10,
"url":"https://example.com/source1?utm_source=openai",
"title":"参照URLのタイトル"
},
{
"type":"url_citation",
"start_index":11,
"end_index":20,
"url":"https://example.com/source2?utm_source=openai",
"title":"参照URLのタイトル"
}
]
}
]
}
]
(後略)
annotations
には、Web Search の結果から抽出した情報が含まれています。
- type
- Web Search の場合は
url_citation
となります。 - start_index
content->text
内でURLを引用した箇所の開始位置が入ります。- end_index
content->text
内でURLを引用した箇所の終了位置が入ります。- url
- 参照URLが入ります。
- title
- 参照URLのタイトルが入ります。
これらのデータを元に、content->text
内でURLを参照した箇所にリンクを挿入したりすることができます。
前回の記事で利用した chat.php
を以下のように変更します。
// Response API のリクエスト・レスポンスデータの取得
$response = createResponse($message);
// レスポンスをデータベースに保存
if(isset($response->output)){
foreach($response->output as $output){
if(isset($output->type) && $output->type == 'message'){
$content = $output->content[0]->text;
// annotations を取得
if(isset($output->content[0]->annotations)){
$annotations = $output->content[0]->annotations;
// リンクを挿入
$content = insertLink($content, $annotations);
}
$stmt = $conn->prepare("INSERT INTO chat_history (role, message, raw_data) VALUES ('assistant', ?, ?)");
$stmt->bind_param("ss", $content, json_encode($response));
if (!$stmt->execute()) {
die('クエリの実行に失敗しました: ' . $stmt->error);
}
$stmt->close();
break;
}
}
}else{
die('APIレスポンスの形式が不正です');
}
// リンクを挿入する関数
function insertLink($content, $annotations){
// annotations の配列を逆順にソート
$annotations = array_reverse($annotations);
// 文章の末尾から順にリンクを挿入
foreach($annotations as $annotation){
if(!isset($annotation->type) || $annotation->type != 'url_citation') continue;
$content = mb_substr($content, 0, $annotation->start_index, 'UTF-8') .
'[ <a href="'.htmlspecialchars($annotation->url, ENT_QUOTES, 'UTF-8').'"
target="_blank"
rel="noopener noreferrer">' .
htmlspecialchars($annotation->title, ENT_QUOTES, 'UTF-8') .
'</a> ]' .
mb_substr($content, $annotation->end_index, null, 'UTF-8');
}
return $content;
}
これで、Web Search の機能を使用した場合、レスポンスに含まれるURLをリンクに変換して表示することができるようになります。
array_reverse
で $annotations
の配列を逆順にソートしているのは、文章の末尾から順にリンクを挿入していかないと、文字数がずれてリンクの挿入位置がおかしくなってしまうためです。
まとめ
- Web Search の機能を使用することで、チャットボットがWebから情報を取得して回答するようになります。
annotations
の値を元に、API のレスポンスに含まれるURLをリンクに変換して表示することができます。
次回は、File Search の機能を利用して、チャットボットがあらかじめ用意したファイルを参照して回答するようにしてみようと思います。
File Search 機能を実装する
2025.03.18追記
File Search 機能を実装する方法については、Response APIのFile Search機能をPHPで実装:ファイルから情報を取得できるチャットボットの作り方を参照。
Function calling を実装する
2025.03.24追記
Function callingを実装する方法については、PHPで実装する Response API と Function Calling を活用したチャットボットの開発ガイドを参照

奈良市を拠点に、25年以上の経験を持つフリーランスWebエンジニア、阿部辰也です。
これまで、ECサイトのバックエンド開発や業務効率化システム、公共施設の予約システムなど、多彩なプロジェクトを手がけ、企業様や制作会社様のパートナーとして信頼を築いてまいりました。
【制作会社・企業様向けサポート】
Webシステムの開発やサイト改善でお困りの際は、どうぞお気軽にご相談ください。小さな疑問から大規模プロジェクトまで、最適なご提案を心を込めてさせていただきます。
ぜひ、プロフィールやWeb制作会社様向け業務案内、一般企業様向け業務案内もご覧くださいね。
PHPで実装する Response API と Function Calling を活用したチャットボットの開発ガイド
2025.03.24
PHPでOpenAIのResponse APIとFunction Calling機能を活用し、チャットボットにタスク管理機能を実装する方法を解説します。モデルとの再帰的な対話処理や、独自関数によるタスク登録・照会など、具体的なコード例を通して段階的に解説します。
Response APIのFile Search機能をPHPで実装:ファイルから情報を取得できるチャットボットの作り方
2025.03.18
OpenAIのResponse APIに新しく追加されたFile Search機能を使って、ファイルから情報を取得できるチャットボットをPHPで実装する方法を解説します。Vector Storeの作成から、実際のコード例まで、ステップバイステップで説明していきます。
OpenAIの新APIを使ってみた:Response APIによるチャットボットをPHPで実装
2025.03.16
OpenAIが新たに発表したResponse APIを使用して、PHPでシンプルなチャットボットを実装してみました。Chat Completions APIとの違いや、実装時のポイントを、実際のコード例と共に解説します。特に会話履歴の管理方法の違いに注目して、両APIの特徴を比較しています。
GPTのfunction callingを活用した関数呼び出し入門
2023.11.23
OpenAI APIのfunction calling機能を使えば、GPTに特定の関数を呼び出させることで、複雑なタスクの自動化が可能になります。本記事では、PHPを用いた基本的な関数指定の方法やレスポンス処理のフローを詳しく解説。日記投稿を例に、APIの設定から応答データの再利用まで実践的なスクリプトを紹介します。