# OpenAI function calling: read_url tool สำหรับโมเดลของคุณ

> OpenAI function calling ด้วย read_url tool: JSON schema และลูป Python ที่เปลี่ยนลิงก์เป็น Markdown สะอาดสำหรับโมเดล ไม่ต้อง KYC จ่ายด้วยคริปโต

- URL: https://webreaderapi.com/th/docs/openai/
- อัปเดตล่าสุด: 2026-10-22
- ผู้เผยแพร่: WebReaderAPI (https://webreaderapi.com)

อธิบายฟังก์ชันหนึ่งตัว คือ `read_url` แล้วเรียกใช้เมื่อโมเดลขอ โมเดลเลือกเองว่าจะอ่านหน้าไหน โค้ดของคุณเรียก API แล้วส่ง Markdown กลับไป schema เดียวกันใช้ได้กับโมเดลอื่นที่รองรับ tool calling

**คำตอบสั้น — ทำอย่างไรให้โมเดล OpenAI อ่านหน้าเว็บด้วย function calling?**

ประกาศฟังก์ชัน `read_url` ในลิสต์ `tools` แล้วรันลูป: เมื่อโมเดลคืน tool call ให้เรียก endpoint `/read` ของ **WebReaderAPI** พร้อม URL แล้วส่ง Markdown กลับไปเป็นข้อความ `tool` แต่ละหน้าใช้ 1 เครดิต หรือ 2 เครดิตถ้าใช้เบราว์เซอร์ เริ่มต้นที่ US$0.07/1K หน้า ณ เดือนตุลาคม 2026 ไม่ต้อง KYC จ่ายด้วยคริปโต

## schema ของ read_url หน้าตาเป็นอย่างไร?

สองพารามิเตอร์ก็พอ: `url` ที่จะอ่าน (required) และ `max_chars` แบบไม่บังคับที่ให้โมเดลย่อหน้าเว็บยาวๆ ได้ ส่วน description คือส่วนสำคัญที่สุด: บอกโมเดลว่าเครื่องมือนี้คืนอะไรและใช้เมื่อไร เขียนให้ตรงข้อเท็จจริงและสั้น

เราเรียกเครื่องมือนี้ว่า `read_url` แทน `web_fetch` เพื่อเลี่ยงการชนกับเครื่องมือที่บาง agent runtime มีอยู่แล้วในชื่อนั้น

*นิยามของเครื่องมือ*

```json
{
  "type": "function",
  "function": {
    "name": "read_url",
    "description": "Read a public web page and return its main content as Markdown, with its title and source URL. Use it when the user gives a link or when a page must be read to answer.",
    "parameters": {
      "type": "object",
      "properties": {
        "url": { "type": "string", "description": "The http or https address of the page." },
        "max_chars": { "type": "integer", "description": "Most characters to return, 1000 to 500000. Default 20000." }
      },
      "required": ["url"],
      "additionalProperties": false
    }
  }
}
```

## ลูป tool calling ทำงานอย่างไร?

ส่งบทสนทนาพร้อมลิสต์ `tools` ถ้าคำตอบมี tool call ให้รันแต่ละตัว เพิ่มผลลัพธ์เป็นข้อความที่มี role `tool` และ `tool_call_id` ที่ตรงกัน แล้วถามโมเดลอีกครั้ง เมื่อคำตอบกลับมาโดยไม่มี tool call นั่นคือคำตอบสุดท้าย

จำกัดจำนวนรอบไว้ สามหรือสี่รอบก็เพียงพอสำหรับคำถามเกี่ยวกับหน้าเว็บไม่กี่หน้า และเพดานนี้ช่วยปกป้องคุณจากโมเดลที่ขออ่านเพิ่มไม่หยุด

*Python: ลูปเต็มพร้อมแพ็กเกจ openai*

```python
import json
import os

import requests
from openai import OpenAI

READ_URL = {
    "type": "function",
    "function": {
        "name": "read_url",
        "description": "Read a public web page and return its main content as Markdown, with its title and source URL.",
        "parameters": {
            "type": "object",
            "properties": {
                "url": {"type": "string", "description": "The http or https address of the page."},
                "max_chars": {"type": "integer", "description": "Most characters to return. Default 20000."},
            },
            "required": ["url"],
            "additionalProperties": False,
        },
    },
}


def read_url(url, max_chars=20000):
    resp = requests.get(
        "https://webreaderapi.com/api/v1/read",
        headers={"Authorization": "Bearer " + os.environ["WEBREADER_API_KEY"]},
        params={"url": url, "max_chars": max_chars},
        timeout=75,
    )
    body = resp.json()
    if resp.status_code != 200:
        return "Could not read the page: " + body["error"]["code"]
    return "# " + (body.get("title") or url) + "\nSource: " + body["final_url"] + "\n\n" + body["markdown"]


client = OpenAI()
model = os.environ.get("OPENAI_MODEL", "gpt-4.1-mini")
messages = [{"role": "user", "content": "What does https://example.com/blog/first-post announce? Answer in two sentences."}]

for _ in range(4):
    reply = client.chat.completions.create(model=model, messages=messages, tools=[READ_URL])
    msg = reply.choices[0].message
    if not msg.tool_calls:
        print(msg.content)
        break
    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": read_url(**args)})

```

## ทำอย่างไรให้ใช้ token และค่าใช้จ่ายน้อยลง?

มีการตั้งค่าสามอย่างที่สำคัญ ตั้ง `max_chars` ให้พอเหมาะ ประมาณ 8,000 ถึง 20,000 ตัวอักษรต่อหน้า เพราะทุกตัวอักษรที่ส่งกลับจะถูกโมเดลอ่าน เปิด `main_content=true` แบบค่าเริ่มต้นไว้ เพื่อให้เมนูและส่วนท้ายไม่หลุดเข้า context และจำกัดลูปตามข้างบน เพื่อไม่ให้คำถามเดียวกระตุ้นการอ่านหลายสิบครั้ง

ฝั่งเรา คิดค่าบริการต่อหน้า ไม่ใช่ต่อตัวอักษร: 1 เครดิต = อ่าน 1 หน้าโดยไม่ใช้เบราว์เซอร์; 2 เครดิตเมื่อหน้านั้นต้องใช้เบราว์เซอร์เพื่อเรนเดอร์ JavaScript คำขอที่ล้มเหลว หรือที่ robots.txt ของเว็บไซต์ปฏิเสธ จะไม่ถูกคิดเครดิต ผู้ช่วยฝ่ายซัพพอร์ตที่อ่าน 300 หน้าต่อวันใช้ประมาณ 9,000 เครดิตต่อเดือน อยู่ใน 10,000 หน้า (US$3.75)

## schema ใช้ได้กับโมเดลอื่นไหม?

ได้ โดยแก้ wrapper เล็กน้อย API แบบ tool calling ส่วนใหญ่รับ JSON Schema สำหรับพารามิเตอร์ พร้อมชื่อและ description ของเครื่องมือ ดังนั้น `read_url` ย้ายข้ามผู้ให้บริการได้เลย [หน้า MCP](https://webreaderapi.com/th/docs/mcp/) แพ็กฟังก์ชันเดียวกันสำหรับไคลเอนต์ที่พูด Model Context Protocol และ [หน้า LangChain](https://webreaderapi.com/th/docs/langchain/) ห่อให้ใช้กับ agent ของ LangChain และ LlamaIndex

## โมเดลควรเห็นอะไรเมื่อหน้าเว็บถูกปฏิเสธ?

ประโยคสั้นๆ ชัดเจน อย่างที่ลูปข้างบนคืนค่า: "Could not read the page: blocked_by_robots" โมเดลรับมือได้ดีและหันไปใช้แหล่งอื่นหรือแจ้งผู้ใช้ เราเคารพ robots.txt: crawler ของเราระบุตัวเองว่า WebReaderAPI ทำตามกฎที่เขียนไว้สำหรับมันหรือสำหรับ robot ทั้งหมด และจะไม่อ่านหน้าที่เว็บไซต์ไม่อนุญาต หน้าที่ถูกปฏิเสธจะไม่ถูกคิดเครดิต หากเว็บไซต์ปฏิเสธคำขอของเรา เราจะส่งคำตอบของเว็บนั้นกลับไป: เราไม่แก้ CAPTCHA ไม่เข้าสู่ระบบบัญชี และไม่พยายามหลบเลี่ยงการบล็อกหรือ paywall การปฏิเสธเหล่านี้ไม่ใช้เครดิตเลย

## Function calling: คำถามที่พบบ่อย

### ต้องใช้ Responses API หรือ Chat Completions?

ตัวอย่างใช้ Chat Completions พร้อมพารามิเตอร์ `tools` นิยามฟังก์ชันเดียวกันและ body `read_url` เดียวกันใช้ได้กับอินเทอร์เฟซ OpenAI อื่นที่รับ function tools มีแค่ลูปรอบๆ ที่เปลี่ยน

### โมเดลอ่านหลายหน้าในรอบเดียวได้ไหม?

ได้ คำตอบหนึ่งอาจมี tool call หลายตัว ลูปจะรันแต่ละตัวและคืนผลลัพธ์ทั้งหมดก่อนถามโมเดลอีกครั้ง ตั้ง `max_chars` ให้ต่ำลงเมื่อโมเดลอ่านหลายหน้าพร้อมกัน

### API key ถูกส่งให้โมเดลเห็นไหม?

ไม่ key อยู่ใน environment ของโค้ดคุณ โมเดลเห็นแค่ชื่อเครื่องมือ description และข้อความที่ฟังก์ชันของคุณคืนค่า

### หน้าเว็บที่ถูกปฏิเสธคิดค่าใช้จ่ายเท่าไร?

ไม่มีเลย 1 เครดิต = อ่าน 1 หน้าโดยไม่ใช้เบราว์เซอร์; 2 เครดิตเมื่อหน้านั้นต้องใช้เบราว์เซอร์เพื่อเรนเดอร์ JavaScript คำขอที่ล้มเหลว หรือที่ robots.txt ของเว็บไซต์ปฏิเสธ จะไม่ถูกคิดเครดิต

---

WebReaderAPI: WebReaderAPI คือ API อ่านหน้าเว็บสำหรับ AI agent ที่แปลงหน้าเว็บสาธารณะใด ๆ เป็น Markdown สะอาด จ่ายด้วยคริปโตโดยไม่ต้องอัปโหลดบัตรประชาชน เครดิตแบบเติมเงินเริ่มต้นที่ US$0.07/1K หน้า ไม่มีวันหมดอายุ และเคารพ robots.txt ไม่ต้อง KYC — ไม่ต้องใช้บัตรประชาชน ไม่ต้องเซลฟี่ ไม่ต้องเอกสาร จ่ายด้วยคริปโต
