OPENAIのAPIでWebSearchやってみた【GASから実行できるようにした】

## 初めに
OpenAIのAPIで、WebSearchができるようになっていたので、GASから実行できる仕組みを整えてみました〜

## やり方
フローとしては、
1. AWSのLambdaでOpenAIのライブラリを実行できるようにする
2. LambdaにAPIを叩くロジックを作成
3. GASから叩けるようにする

って感じです。

### 1. AWSのLambdaでOpenAIのライブラリを実行できるようにする
以下の記事を参考にLayerを作成してみました。
https://qiita.com/__DASHi__/items/b03d3efd401260d8add4?fbclid=IwZXh0bgNhZW0CMTEAAR2Akx3BH6_uDvMAOH_DNs3GPlFdJA-ht9julVzzZLgbxHefcvKC6OGaTXM_aem_ZOaQlFuLl4e4EJ6Wb4qo2A

この手順で作成したLayerを今回使用するLambdaに反映しました。

### 2. LambdaにAPIを叩くロジックを作成
今回はpythonでロジックを作成しました。
いかが、コードです。

```python
import json
import openai

# OpenAIのクライアント設定（APIキーをセット）
client = openai.OpenAI(
    api_key="ここにAPIキーを入力、環境変数に設定してもいい"
)


def search_web(query):
    """Web検索を使って最新情報を取得する関数"""
    response = client.chat.completions.create(
        model="gpt-4o-search-preview",
        web_search_options={
            "search_context_size": "medium",  # 検索深度
            "user_location": {
                "type": "approximate",
                "approximate": {
                    "country": "JP",  # 地域
                },
            },
        },
        messages=[{"role": "user", "content": query}],
    )
    print(response)

    return response.choices[0].message.content


def lambda_handler(event, context):
    print(event)
    # 'body'がJSON文字列として渡されている場合、まずそれをパースする
    body = json.loads(event.get("body"))
    
    # パース後に'data'を取得
    query = body.get("data")

    result = search_web(query)
    # TODO implement
    print(result)
    return result

```

### 3. GASから叩けるようにする
最後にスプレッドシートのデータからGASで上記のLambdaを実行できるようにしました。
GASのコードは以下

```javascript
function sendDataToLambda() {
  // スプレッドシートとシートの取得
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('GPT');  // 対象シート名を指定
  const values = sheet.getRange('A1:A' + sheet.getLastRow()).getValues();  // A列のデータを取得

  // Lambda関数のURL
  const lambdaUrl = '';  // あなたのLambda関数のURLを指定

  // 処理した結果を保存するための配列
  let results = [];

  // 各行のデータをLambda関数に送信
  values.forEach(function(row, index) {
    const data = row[0];  // A列の各セルの値
    console.log(data)

    // Lambda関数へのPOSTリクエスト
    const options = {
      'method': 'post',
      'contentType': 'application/json',
      'payload': JSON.stringify({ 'data': data })  // Lambdaに送信するデータをJSON形式で指定
    };

    // HTTPリクエストをLambdaに送信
    const response = UrlFetchApp.fetch(lambdaUrl, options);

    // レスポンスの内容を取得
    let responseText = response.getContentText();
    console.log(responseText);

    // '*'を除去する
    const cleanedResponseText = responseText.replace(/\*/g, '');

    // 結果を配列に追加
    results.push(cleanedResponseText);

    // 50件ごとにC列に結果を書き込む
    if ((index + 1) % 50 === 0 || index === values.length - 1) {
      // 最初の書き込みで行番号が1未満にならないように修正
      const startRow = Math.max(1, index - 48); // 行番号は1以上に調整

      // C列に結果を一度に書き込む
      sheet.getRange(startRow, 3, results.length, 1).setValues(results.map(function(result) { return [result]; }));

      // 結果をリセット（次の50件に向けて）
      results = [];
    }
  });
}

```

今回はA列に書いたプロンプトをもとにWeb Searchを行って回答を作成し、C列に回答を吐き出すシステムにしました。

 ## 最後に
 簡単に実行できるようになっており、びっくりしました笑
 ドキュメント以下に載せておくので、色々試してみてください。
 https://platform.openai.com/docs/guides/tools-web-search?api-mode=responses