技術資料

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 が指定されるので、日本のユーザーが利用することを想定する場合は、ちゃんと指定しておいた方が検索の精度が良くなるかも?
search_context_size
ツールが応答を作成するために Web から取得するコンテキストの量を制御します。
今回は指定していませんが、lowmediumhigh のいずれかを指定することができます。
指定しない場合は、デフォルトで 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機能を活用し、チャットボットにタスク管理機能を実装する方法を解説します。モデルとの再帰的な対話処理や、独自関数によるタスク登録・照会など、具体的なコード例を通して段階的に解説します。

OpenAI API PHP

Response APIのFile Search機能をPHPで実装:ファイルから情報を取得できるチャットボットの作り方

2025.03.18

OpenAIのResponse APIに新しく追加されたFile Search機能を使って、ファイルから情報を取得できるチャットボットをPHPで実装する方法を解説します。Vector Storeの作成から、実際のコード例まで、ステップバイステップで説明していきます。

OpenAI API PHP

OpenAIの新APIを使ってみた:Response APIによるチャットボットをPHPで実装

2025.03.16

OpenAIが新たに発表したResponse APIを使用して、PHPでシンプルなチャットボットを実装してみました。Chat Completions APIとの違いや、実装時のポイントを、実際のコード例と共に解説します。特に会話履歴の管理方法の違いに注目して、両APIの特徴を比較しています。

OpenAI API PHP

GPTのfunction callingを活用した関数呼び出し入門

2023.11.23

OpenAI APIのfunction calling機能を使えば、GPTに特定の関数を呼び出させることで、複雑なタスクの自動化が可能になります。本記事では、PHPを用いた基本的な関数指定の方法やレスポンス処理のフローを詳しく解説。日記投稿を例に、APIの設定から応答データの再利用まで実践的なスクリプトを紹介します。

OpenAI API PHP

阿部辰也へのお仕事の依頼・お問い合わせ

軽いご相談もお気軽にどうぞ!

個人情報の取り扱いについて *必須 プライバシーポリシーをご確認いただき、同意いただける場合は「同意する」にチェックをしてください。

keyboard_double_arrow_up
TOP