KYC不要 — 身分証、自撮り、書類は不要です。暗号資産で支払い: BTC, USDT, USDC, ETH, SOL, LTC
言語: 日本語
APIキーを取得

ドキュメント · Function calling · ツール利用 · Python

OpenAI function calling: 60行のPythonでGoogle検索ツールを作る

google_search関数をモデルに説明し、要求された検索を実行し、結果を返します。スキーマは純粋なJSON Schemaなので、Claudeや他のツール呼び出し対応モデルにもそのまま使えます。

最終更新:

簡潔な回答

OpenAIモデルにWeb検索ツールを渡すには?

toolsでJSON Schemaを使ってgoogle_search関数を宣言し、ループします。モデルがtool_callsを返したら、各検索をhttps://serpcrypto.com/api/v1/searchで実行し、結果をtoolメッセージとして追加することを、回答が返るまで繰り返します。SerpCryptoは成功した検索1回につき1クレジットを、$0.30/1K検索から、暗号資産で支払い、KYC不要で課金します。

ツールスキーマはどのような形ですか?

関数ツールには名前、説明、JSON Schemaでのparametersがあります。モデルが見るのはこの3つだけなので、説明にはツールが何を返すか、いつ使うかを書く必要があります。必須はqueryだけで、countryとlanguageは任意で、コードではデフォルトでUS Englishになります。

ツール定義(Chat Completions形式)
{
  "type": "function",
  "function": {
    "name": "google_search",
    "description": "Search Google for current information. Returns the top results with title, link and snippet. Use it for facts newer than your training data.",
    "parameters": {
      "type": "object",
      "properties": {
        "query": { "type": "string", "description": "The search query, as a person would type it." },
        "gl": { "type": "string", "description": "Two-letter country code of the results, e.g. us, gb, de." },
        "hl": { "type": "string", "description": "Language code, e.g. en, de, pt-BR." }
      },
      "required": ["query"]
    }
  }
}

ツール呼び出しループはどのように動作しますか?

toolsとともに質問を送信します。応答にtool_callsが含まれている場合は、それぞれを実行し、assistantメッセージと、該当するtool_call_idを持つ各呼び出しごとのtoolメッセージを1つずつ追加してから、モデルを再度呼び出します。応答にツール呼び出しが含まれていない場合、それが最終回答です。

以下のループは3回の検索後に停止します。モデルが検索を続けてもクレジットを保護するための上限であり、3回の検索でほとんどの事実質問に回答できます。

search_agent.py
"""Tool-calling loop: the model asks for searches, this code runs them on SerpCrypto."""
import json
import os

import requests
from openai import OpenAI

client = OpenAI()  # reads OPENAI_API_KEY
MODEL = os.environ["OPENAI_MODEL"]  # any OpenAI chat model with tool calling
API_URL = "https://serpcrypto.com/api/v1/search"

TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "google_search",
            "description": "Search Google for current information. Returns the top results with title, link and snippet.",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {"type": "string", "description": "The search query."},
                    "gl": {"type": "string", "description": "Two-letter country code, e.g. us."},
                    "hl": {"type": "string", "description": "Language code, e.g. en."},
                },
                "required": ["query"],
            },
        },
    }
]


def google_search(query, gl="us", hl="en"):
    r = requests.get(
        API_URL,
        params={"q": query, "gl": gl, "hl": hl},
        headers={"Authorization": "Bearer " + os.environ["SERPCRYPTO_API_KEY"]},
        timeout=90,
    )
    if r.status_code != 200:
        return f"Search failed with HTTP {r.status_code}."
    items = r.json().get("organic_results", [])[:5]
    return "\n\n".join(f"{x['title']}\n{x['link']}\n{x.get('snippet', '')}" for x in items) or "No results."


def ask(question, max_searches=3):
    messages = [{"role": "user", "content": question}]
    for _ in range(max_searches + 1):
        reply = client.chat.completions.create(model=MODEL, messages=messages, tools=TOOLS)
        msg = reply.choices[0].message
        if not msg.tool_calls:
            return msg.content
        messages.append(msg)
        for call in msg.tool_calls:
            args = json.loads(call.function.arguments)
            messages.append({"role": "tool", "tool_call_id": call.id, "content": google_search(**args)})
    return "Stopped: search limit reached."


print(ask("Which countries changed their data protection laws in 2026? Cite sources."))

同じスキーマはClaudeや他のモデルでも動作しますか?

はい、異なるラッパーを使えば動作します。Claudeのtool useは、nameとdescriptionの隣に、input_schemaの下で同じJSON Schemaを受け取ります。他の多くのtool-calling APIもパラメータにJSON Schemaを受け付けます。変わるのは外側のフィールド名だけです。検索関数自体は、SerpCrypto endpointを呼び出すだけなので変わりません。

Claude向けの同じツール(Messages API)
{
  "name": "google_search",
  "description": "Search Google for current information. Returns the top results with title, link and snippet.",
  "input_schema": {
    "type": "object",
    "properties": {
      "query": { "type": "string", "description": "The search query." },
      "gl": { "type": "string", "description": "Two-letter country code, e.g. us." },
      "hl": { "type": "string", "description": "Language code, e.g. en." }
    },
    "required": ["query"]
  }
}

ツールはモデルに何を返すべきですか?

リンク付きの短いテキストです。タイトル、リンク、スニペットを含む5件の結果で、モデルが回答し引用するのに通常は十分です。完全なJSONを返すこともできますが、トークン消費が増え、モデルが読むノイズも増えます。

モデルにGoogle自身の要約を見せたい場合は、存在する場合にAI Overviewのテキストを追加し、回答が概要ではなくページを引用できるようソースリンクを保持してください。

検索コストを予測可能にするには?

ツール呼び出しを数えます。成功した呼び出し1回が1クレジットです。ループのように質問ごとの検索回数に上限を設け、各呼び出しをその検索クエリとともにログに記録すれば、モデルが何を求めているかを確認できます。100,000検索パックでは料金は$0.56/1K検索、そしてプリペイドの検索クレジットに有効期限はありません。未使用の検索は、使用するまでアカウントに残りますです。

エラーは課金されません:1クレジット = 1回の成功した検索リクエストで、対応するすべてのエンジンで結果の1ページを返します。失敗したリクエストは課金されません。

Function callingの質問

Chat Completionsの代わりにResponses APIを使えますか?

はい。Responses APIは同じJSON Schemaでfunctionツールを受け取り、各ツールのトップレベルにname、description、parametersを置きます。検索関数とループの考え方は変わりません。

モデルプロバイダー組み込みのWeb検索を使わないのはなぜですか?

組み込みの検索ツールは独自のソースと設定を選びます。SerpCrypto上のfunctionを使えば、選択した国と言語のGoogle検索結果を、ログに記録できるJSONとして、検索ごとの既知の料金で取得できます。

モデルは国を選択できますか?

はい。glはツールのパラメータなので、モデルは質問からそれを設定できます。例えば、イギリスに関する質問ならgbです。国名が含まれない質問に備えて、コードにデフォルト値を設定しておいてください。

検索APIキーの取得にクレジットカードは必要ですか?

いいえ。SerpCryptoクレジットはBTC, USDT, USDC, ETH, SOL, LTCで支払い、身分証も自撮りも書類も不要です。アカウント番号でログイン。メールは任意です。

$0.30/1K検索から · KYC不要

APIキーを取得