คำตอบสั้น
ฉันจะเพิ่ม web search ให้โมเดล OpenAI ด้วย function calling ได้อย่างไร?
ประกาศฟังก์ชัน search_web พร้อม JSON schema และเมื่อโมเดลเรียกมัน ให้ POST คำค้นหาไปที่ https://llmwebsearch.com/api/v1/search ของ LLMWebSearch ส่งคืนแหล่งอ้างอิงที่มีหมายเลข พร้อม 3 หน้าแรกเป็น Markdown ในรูปของ function_call_output โมเดลจะตอบและอ้างอิงแหล่งเหล่านั้น การค้นหาหนึ่งครั้งมีค่า 1 เครดิต จาก US$1.20/1K การค้นหา ณ ตุลาคม 2026 ไม่ต้อง KYC จ่ายด้วยคริปโต
สิ่งที่คุณต้องมี
| แพ็กเกจ | openai และ requests (หรือ openai-agents สำหรับเวอร์ชัน Agents SDK) |
|---|---|
| Keys | OPENAI_API_KEY สำหรับโมเดล LLMWEBSEARCH_API_KEY สำหรับการค้นหา |
| Model | โมเดลใดก็ได้ที่รองรับ function calling ตั้งค่าใน OPENAI_MODEL |
| API ที่ใช้ | Responses API: client.responses.create พร้อม tools และ input |
| การเรียกเก็บเงินฝั่งเรา | หนึ่งเครดิตจ่ายสำหรับการค้นหาหนึ่งครั้ง: ผลลัพธ์แบบจัดอันดับสูงสุด 20 รายการ โดยอ่านหน้าเว็บของ 3 รายการแรกและส่งกลับเป็น Markdown การอ่าน 4 ถึง 10 หน้าใช้ 2 เครดิต การเรียกที่จบลงด้วยข้อผิดพลาดไม่มีค่าใช้จ่าย |
schema ของ tool หน้าตาเป็นอย่างไร?
function tool มี name, description และ JSON Schema parameters เขียน description ให้ชัดเจน: tool คืนอะไร และควรอ้างอิงแหล่งด้วยหมายเลข สองพารามิเตอร์ก็เพียงพอสำหรับ agent ส่วนใหญ่: query และจำนวนผลลัพธ์อันดับต้นที่ต้องการแบบเต็ม read
โมเดลไม่เคยเห็น API key ของคุณ มันเพียงเสนอ arguments โค้ดของคุณเป็นผู้ตัดสินใจว่าจะเรียก API อย่างไรและส่งอะไรกลับไป
ลูปการเรียกทำงานอย่างไร?
ส่งข้อความของผู้ใช้พร้อม tools ถ้าการตอบกลับมี item ชนิด function_call ให้ parse JSON arguments ของแต่ละรายการ รันการค้นหา แล้วต่อท้าย function_call_output ด้วย call_id เดียวกัน จากนั้นเรียกโมเดลอีกครั้งพร้อมรายการ input ที่ยาวขึ้น เมื่อการตอบกลับไม่มี function call ข้อความของมันคือคำตอบ
ลูปด้านล่างหยุดหลังห้ารอบ เป็นการป้องกันโมเดลที่ค้นหาไม่หยุด คู่มือ function-calling ของ OpenAI อธิบาย item function_call และ function_call_output แบบเดียวกัน อ่านเมื่อ 22 ตุลาคม 2026
import json
import os
import requests
from openai import OpenAI
client = OpenAI()
MODEL = os.environ["OPENAI_MODEL"] # any model that supports function calling
SEARCH = "https://llmwebsearch.com/api/v1/search"
tools = [
{
"type": "function",
"name": "search_web",
"description": "Search the live web. Returns numbered sources with URLs; the first `read` include page text. Cite sources as [1], [2].",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "What to search for, as a person would type it."},
"read": {"type": "integer", "minimum": 0, "maximum": 10, "description": "How many top results to read in full."},
},
"required": ["query"],
"additionalProperties": False,
},
}
]
def search_web(query, read=3):
resp = requests.post(
SEARCH,
headers={"Authorization": "Bearer " + os.environ["LLMWEBSEARCH_API_KEY"]},
json={"q": query, "max_results": 5, "read": read, "max_chars": 5000},
timeout=60,
)
if resp.status_code != 200:
return "Search failed: " + resp.json().get("error", {}).get("code", str(resp.status_code))
parts = []
for i, r in enumerate(resp.json()["results"], start=1):
text = r["content"] if r["content_status"] == "ok" else "(snippet only) " + r["snippet"]
parts.append(f"[{i}] {r['title']} - {r['url']}\n{text}")
return "\n\n".join(parts)
input_list = [{"role": "user", "content": "How should I size a Postgres connection pool?"}]
for _ in range(5):
response = client.responses.create(model=MODEL, tools=tools, input=input_list)
calls = [item for item in response.output if item.type == "function_call"]
if not calls:
print(response.output_text)
break
input_list += response.output
for item in calls:
args = json.loads(item.arguments)
output = search_web(args["query"], int(args.get("read", 3)))
input_list.append({"type": "function_call_output", "call_id": item.call_id, "output": output})
มีเวอร์ชันที่สั้นกว่าด้วย Agents SDK ไหม?
มี OpenAI Agents SDK เปลี่ยนฟังก์ชัน Python เป็น tool ด้วย decorator และรันลูปการเรียกให้คุณ เอกสาร tools ของมันที่อ่านเมื่อ 22 ตุลาคม 2026 แสดง decorator @tool จาก agents.decorators โดย description มาจาก docstring และ description ของแต่ละ argument มาจากส่วน Args ของมัน หน้าเดียวกันยังกล่าวถึงรูปแบบ @function_tool ด้วย
Runner.run_sync รัน agent จนกว่าจะได้คำตอบสุดท้าย เรียก search_web บ่อยเท่าที่โมเดลขอ
import os
import requests
from agents import Agent, Runner
from agents.decorators import tool
@tool
def search_web(query: str, read: int = 3) -> str:
"""Search the live web and return numbered sources with their URLs.
Args:
query: What to search for, as a person would type it.
read: How many top results to read in full, from 0 to 10.
"""
resp = requests.post(
"https://llmwebsearch.com/api/v1/search",
headers={"Authorization": "Bearer " + os.environ["LLMWEBSEARCH_API_KEY"]},
json={"q": query, "max_results": 5, "read": max(0, min(read, 10)), "max_chars": 5000},
timeout=60,
)
resp.raise_for_status()
parts = []
for i, r in enumerate(resp.json()["results"], start=1):
text = r["content"] if r["content_status"] == "ok" else "(snippet only) " + r["snippet"]
parts.append(f"[{i}] {r['title']} - {r['url']}\n{text}")
return "\n\n".join(parts)
agent = Agent(
name="Researcher",
instructions="Answer from search_web results only and cite them as [1], [2].",
tools=[search_web],
)
result = Runner.run_sync(agent, "How should I size a Postgres connection pool?")
print(result.final_output)
ทำไมต้องใช้ API tool แทน web search ที่มีมาในตัวของ OpenAI?
ส่วนใหญ่เพื่อควบคุมว่าอะไรที่ model อ่านและค่าใช้จ่ายเท่าไร tool ของเราส่งแหล่งข้อมูลดิบให้โค้ดของคุณ พร้อม URL และข้อความในหน้าเว็บ คุณจึงตัดสินใจได้ว่าอะไรจะเข้าสู่ context บันทึก log ได้ และจัดเก็บได้ เราไม่ฝึกโมเดลใดๆ ด้วยคำค้นหาของคุณหรือข้อมูลที่ API ส่งกลับ และเราไม่เพิ่มกฎของเราเองต่อต้านการจัดเก็บผลลัพธ์; สิทธิ์ของเว็บไซต์ที่คุณอ่านหน้ายังคงมีผล
ราคายังคงที่ต่อการค้นหาแต่ละครั้ง แทนที่จะขึ้นกับว่า model อ่านเนื้อหาที่ดึงมามากแค่ไหน การเปรียบเทียบ built-in tools วางราคาต่อครั้งของ OpenAI, Anthropic, Google และอื่นๆ ไว้เคียงกัน พร้อมวันที่
ทำอย่างไรไม่ให้ model ค้นหามากเกินไป?
บอกใน instructions ว่า: ค้นหาหนึ่งครั้ง อ่านแหล่งข้อมูล แล้วค้นหาอีกครั้งเฉพาะเมื่อแหล่งข้อมูลขัดแย้งกันหรือไม่ตรงประเด็น จำกัดจำนวนรอบใน loop ของคุณเองเหมือนที่ script ข้างต้นทำด้วยค่าห้า
รักษา max_chars ให้พอประมาณ สามหน้าละ 5,000 ตัวอักษรคือประมาณ 4,000 tokens ต่อการค้นหาหนึ่งครั้ง และแต่ละรอบจะเพิ่มเข้าไปใน input ของการเรียก model ครั้งถัดไป
OpenAI function calling: คำถามที่พบบ่อย
ใช้ได้กับ Chat Completions API ไหม?
ได้ กับรูปแบบ tools แบบเก่าของ Chat Completions ซึ่ง function อยู่ใน object function และผลลัพธ์ส่งกลับมาเป็นข้อความ tool ตัวฟังก์ชันค้นหาเองไม่เปลี่ยน
model อ่านหน้าที่พบในแหล่งข้อมูลได้ไหม?
เพิ่มฟังก์ชันที่สอง read_urls ที่ส่ง URL ไปยัง https://llmwebsearch.com/api/v1/extract การอ่านหน้าเว็บที่คุณมี URL อยู่แล้วใช้ 1 เครดิตต่อกลุ่ม 3 หน้าที่เริ่มอ่านและส่งกลับพร้อมเนื้อหา สูงสุด 20 URL ต่อการเรียก; URL ที่ถูกปฏิเสธหรือล้มเหลวไม่ถูกนับ
ควรใช้ model ไหน?
model ใดก็ได้ที่รองรับ function calling ลองสักสองสามตัวกับคำถามของคุณเอง: คำตอบขึ้นกับแหล่งข้อมูลพอๆ กับตัว model และ model ที่เล็กกว่าก็มีค่าใช้จ่ายต่อรอบน้อยกว่า
แหล่งที่มา (2)
- Function calling — OpenAI API docs (read 2026-10-22)
- Tools (OpenAI Agents SDK) — OpenAI Agents SDK docs (read 2026-10-22)