# Tool calling และ JSON output กับโมเดล open-weight

> Function calling กับโมเดล open-weight ในรูปแบบ OpenAI: tools, tool_choice, ลูปการเรียกและตอบกลับ และ response_format สำหรับผลลัพธ์ JSON ที่ถูกต้อง

- URL: https://llmwithcrypto.com/th/docs/tool-calling/
- อัปเดตล่าสุด: 2026-10-23
- ผู้เผยแพร่: LLMwithCrypto (https://llmwithcrypto.com)

โมเดลสามารถขอให้โค้ดของคุณรันฟังก์ชัน แล้วนำผลลัพธ์ไปใช้ในคำตอบ หรือจะตอบกลับเป็นออบเจกต์ JSON ที่โปรแกรมของคุณอ่านได้โดยตรง ทั้งสองแบบใช้รูปแบบคำขอของ OpenAI และทั้งสองขึ้นอยู่กับโมเดลที่คุณเลือก

**คำตอบสั้น — tool calling บน LLMwithCrypto ทำงานอย่างไร?**

ส่งฟังก์ชันของคุณใน `tools` ในรูปแบบ OpenAI เมื่อโมเดลต้องการเรียกฟังก์ชัน **LLMwithCrypto** จะคืนค่า `finish_reason: "tool_calls"` พร้อมชื่อฟังก์ชันและอาร์กิวเมนต์แบบ JSON โค้ดของคุณรันฟังก์ชันนั้นแล้วส่งผลลัพธ์กลับเป็นข้อความ `tool` สำหรับคำตอบแบบมีโครงสร้าง `response_format: {"type": "json_object"}` จะขอ JSON ที่ถูกต้อง ทั้งสองทำงานบนโมเดลที่รองรับ ตามเอกสาร ณ วันที่ 23 ตุลาคม 2026

## โมเดลใดรองรับ tools และ JSON?

Streaming ใช้ได้กับทุกโมเดล; tool calling และ JSON output ขึ้นอยู่กับสิ่งที่แต่ละโมเดลรองรับเอง

ทดสอบสคีมาของคุณเองบนโมเดลที่คุณวางแผนจะใช้ก่อนที่จะพึ่งพามัน โมเดลที่ไม่รองรับ tools จะตอบเป็นข้อความธรรมดาแทนการเรียกฟังก์ชัน ส่วนโมเดลที่ไม่รองรับโหมด JSON จะคืนค่าข้อผิดพลาด `400` สำหรับ `response_format`

## ลูปคืออะไร?

1. **อธิบายฟังก์ชัน** — แต่ละ tool มี name, description ที่โมเดลอ่านเพื่อตัดสินใจว่าเมื่อใดควรใช้ และ parameters เป็น JSON Schema
2. **ส่งบทสนทนาพร้อม tools** — โมเดลจะตอบเป็นข้อความ หรือหยุดด้วย finish_reason: "tool_calls" พร้อมการเรียกหนึ่งครั้งหรือมากกว่าใน message.tool_calls
3. **รันแต่ละการเรียก** — แปลง function.arguments (สตริง JSON) รันฟังก์ชันของคุณ และอย่าเชื่ออาร์กิวเมนต์โดยไม่ตรวจสอบ: ตรวจสอบให้เหมือนกับอินพุตของผู้ใช้ทั่วไป
4. **ส่งผลลัพธ์กลับ** — ต่อท้ายข้อความของ assistant แล้วเพิ่มข้อความ tool หนึ่งข้อความต่อการเรียกหนึ่งครั้ง พร้อม tool_call_id และผลลัพธ์เป็นข้อความ เรียก API อีกครั้ง ทำซ้ำจนกว่าโมเดลจะตอบเป็นข้อความ

*Python: ลูป tool แบบสมบูรณ์กับ gpt-oss-120b*

```python
import json
import os

from openai import OpenAI

client = OpenAI(
    base_url="https://llmwithcrypto.com/api/v1",
    api_key=os.environ["LLMWITHCRYPTO_API_KEY"],
)

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_order_status",
            "description": "Return the delivery status of an order.",
            "parameters": {
                "type": "object",
                "properties": {"order_id": {"type": "string"}},
                "required": ["order_id"],
            },
        },
    }
]


def get_order_status(order_id):
    return {"order_id": order_id, "status": "shipped", "eta": "2026-10-25"}


messages = [{"role": "user", "content": "Where is my order A-1042?"}]
while True:
    resp = client.chat.completions.create(model="gpt-oss-120b", messages=messages, tools=tools, max_tokens=300)
    msg = resp.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)
        result = get_order_status(**args)
        messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})

```

## การเรียก tool ในคำตอบมีหน้าตาอย่างไร?

ข้อความของ assistant ไม่มีข้อความ มีอาร์เรย์ `tool_calls` และตัวเลือกสิ้นสุดด้วย `finish_reason: "tool_calls"` อาร์กิวเมนต์มาเป็นสตริง JSON ไม่ใช่ออบเจกต์ id และจำนวนด้านล่างเป็นเพียงตัวอย่าง

*คำตอบที่ขอให้เรียกฟังก์ชัน (ตัวอย่าง)*

```json
{
  "id": "chatcmpl-3c9d27e1",
  "object": "chat.completion",
  "created": 1792742400,
  "model": "gpt-oss-120b",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": null,
        "tool_calls": [
          {
            "id": "call_7f31",
            "type": "function",
            "function": {
              "name": "get_order_status",
              "arguments": "{\"order_id\": \"A-1042\"}"
            }
          }
        ]
      },
      "finish_reason": "tool_calls"
    }
  ],
  "usage": {
    "prompt_tokens": 118,
    "completion_tokens": 22,
    "total_tokens": 140
  }
}

```

## ฉันควบคุมเวลาใช้ tools ได้อย่างไร?

- **`"tool_choice": "auto"`** (ค่าเริ่มต้นเมื่อตั้ง `tools`): โมเดลเป็นผู้ตัดสินใจ
- **`"tool_choice": "none"`**: โมเดลตอบเป็นข้อความแม้จะมี tools ระบุไว้
- **`"tool_choice": "required"`**: โมเดลต้องเรียก tool อย่างน้อยหนึ่งตัว
- **`{"type": "function", "function": {"name": "get_order_status"}}`**: โมเดลต้องเรียก tool ตัวนั้นตัวเดียว

คำจำกัดความของ tool ทุกตัวถูกส่งเป็นอินพุตในทุกการเรียก ดังนั้นคำอธิบายที่ยาวและ tools จำนวนมากจะเพิ่มจำนวนโทเค็นอินพุต เก็บคำอธิบายให้สั้นและส่งเฉพาะ tools ที่ขั้นตอนนั้นต้องการ

## ฉันจะได้ JSON ที่ถูกต้องกลับมาได้อย่างไร?

ตั้ง `response_format` เป็น `{"type": "json_object"}` และอธิบายคีย์ที่คาดหวังใน system message: โหมด JSON รับประกันว่าคำตอบแปลงค่าได้ ไม่ได้รับประกันว่าจะมีคีย์ที่คุณต้องการ ตั้ง `temperature` ให้ต่ำเพื่อผลลัพธ์ที่เสถียร และตรวจสอบออบเจกต์ที่แปลงแล้วในโค้ดก่อนใช้งาน

*Node.js: คำตอบ JSON ด้วย response_format*

```javascript
import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://llmwithcrypto.com/api/v1',
  apiKey: process.env.LLMWITHCRYPTO_API_KEY,
});

const resp = await client.chat.completions.create({
  model: 'gpt-oss-120b',
  messages: [
    { role: 'system', content: 'Reply with a JSON object {"sentiment": "positive" | "negative" | "neutral", "reason": string}.' },
    { role: 'user', content: 'The delivery was late but support fixed it in an hour.' },
  ],
  response_format: { type: 'json_object' },
  temperature: 0.2,
  max_tokens: 150,
});
const result = JSON.parse(resp.choices[0].message.content);
console.log(result.sentiment, '-', result.reason);

```

## Tools และ JSON: คำถามที่พบบ่อย

### การเรียก tool มีค่าใช้จ่ายเพิ่มหรือไม่?

ไม่มีค่าธรรมเนียมของตัวเอง คำจำกัดความของ tool การเรียก และผลลัพธ์ที่คุณส่งกลับ ล้วนเป็นโทเค็นที่คิดค่าบริการเหมือนโทเค็นอื่นๆ คุณจ่ายต่อ token จากยอดคงเหลือ: input และ output tokens ถูกนับด้วย tokenizer ของโมเดลนั้นเองและคิดตามราคาของโมเดลนั้นต่อ 1M tokens การเรียกที่จบด้วย error ไม่มีค่าใช้จ่าย

### โมเดลเรียกหลาย tools พร้อมกันได้หรือไม่?

โมเดลบางตัวคืนค่ามากกว่าหนึ่งการเรียกใน `tool_calls` รันทั้งหมดและส่งข้อความ `tool` หนึ่งข้อความต่อการเรียกหนึ่งครั้งก่อนคำขอถัดไป

### API รันฟังก์ชันของฉันหรือไม่?

ไม่ โมเดลเพียงระบุว่าจะเรียกฟังก์ชันใดและด้วยอาร์กิวเมนต์ใด โค้ดของคุณเป็นตัวรัน ไม่มีสิ่งใดถูกเรียกใช้ฝั่งเรา และไม่มีสิ่งใดจากการแลกเปลี่ยนถูกจัดเก็บ: เราไม่เก็บ prompts ของคุณหรือคำตอบของโมเดล: เมื่อส่งคำตอบแล้ว ข้อความนั้นก็หายไป แต่ละครั้งที่เรียกจะเหลือ log หนึ่งบรรทัดซึ่งมีเวลา บัญชี โมเดล และจำนวน token แล้วลบออกหลัง 30 วัน

---

LLMwithCrypto: LLMwithCrypto คือ LLM API ที่เข้ากันได้กับ OpenAI สำหรับโมเดล open-weight — DeepSeek V4 Pro, DeepSeek V4.1 Flash, DeepSeek R1, Qwen3.5 397B A17B, Qwen3 235B A22B Instruct, gpt-oss-120b, gpt-oss-20b, GLM-4.7, Llama 3.3 70B Instruct, Gemma 4 31B, Mistral Large 3, Mistral Small 4 — จ่ายต่อ token จากยอดคงเหลือคริปโตแบบเติมเงิน ในราคาต่ำกว่าค่ามัธยฐานของโฮสต์สาธารณะ 5% ไม่ต้อง KYC: ไม่ต้องใช้บัตรประชาชน ไม่ต้องเซลฟี่ ไม่ต้องใช้เอกสาร ไม่มีการเก็บ prompt และ output
