จาก 0 ถึง AI Agent — บันทึกการเรียนรู้ผ่านโปรเจกต์จริง
ตอนที่ 3: นิยาม Tools ให้ Claude ใช้
ตอนที่แล้วเราเข้าใจแล้วว่า Tool Calling คืออะไร ตอนนี้เราจะมาดูว่า โค้ดจริงๆ เขียนยังไง
โฟกัสตอนนี้: บอก Claude ว่ามี tool อะไรให้ใช้บ้าง และกำหนด behavior ด้วย System Prompt
โครงสร้างโปรเจกต์
ask-my-docs/
├── ask.py ← โค้ดหลักทั้งหมด
├── .env ← API Key (อย่า commit!)
├── .gitignore
└── docs/ ← ใส่ไฟล์ .txt ที่อยากให้ AI อ่าน
├── python.txt
└── ...ไฟล์ที่เราสนใจตอนนี้คือ ask.py เปิดดูส่วนบนสุดก่อน:
import os
import anthropic
import json
from pathlib import Path
from dotenv import load_dotenv
from pydantic import BaseModel
from typing import List
load_dotenv()
client = anthropic.Anthropic()
DOCS_FOLDER = Path("./docs")ไม่มีอะไรซับซ้อน — import library, โหลด API Key, สร้าง client, กำหนดโฟลเดอร์เอกสาร
System Prompt: กำหนด “บุคลิก” ของ Agent
SYSTEM_PROMPT = """
You are a document assistant for Lewis University EIS team.
You help users find information from internal documents.
Rules:
- Always call list_files first to see what is available
- Only answer from the documents provided
- If the answer is not in the documents, say "I could not find this in the available documents" and stop
- Do not use your general knowledge to fill in missing information
"""System Prompt คือคำสั่งที่ส่งให้ Claude ก่อนทุกอย่าง — เหมือน “กฎของบ้าน”
สังเกต rule ที่สำคัญ:
💡 Prompt สำคัญมาก — Claude จะเชื่อฟัง instruction ใน system prompt ค่อนข้างดี การกำหนด rule ชัดเจนทำให้ Agent มีพฤติกรรมที่คาดเดาได้
นิยาม Tools: บอก Claude ว่ามีอะไรให้ใช้
นี่คือส่วนที่น่าสนใจที่สุด เราบอก Claude ว่ามี tool อะไรผ่าน list ของ dictionary:
tools = [
{
"name": "list_files",
"description": "List all available files in the docs folder",
"input_schema": {
"type": "object",
"properties": {},
"required": []
}
},
...
]แต่ละ tool มี 3 ส่วน:
Tool ที่ 1: list_files
{
"name": "list_files",
"description": "List all available files in the docs folder",
"input_schema": {
"type": "object",
"properties": {},
"required": []
}
}Tool นี้ง่ายมาก — ไม่ต้องรับ input อะไรเลย (properties ว่างเปล่า) แค่ขอให้ Claude เรียกแล้วจะได้รายชื่อไฟล์กลับไป
Tool ที่ 2: read_file
{
"name": "read_file",
"description": "Read the contents of a specific file in the docs folder",
"input_schema": {
"type": "object",
"properties": {
"filename": {
"type": "string",
"description": "The filename to read e.g. notes.txt"
}
},
"required": ["filename"]
}
}Tool นี้ต้องการ filename — Claude จะเลือกชื่อไฟล์จากที่ได้จาก list_files แล้วส่งมาให้เรา
สังเกตว่า description ของ filename มีตัวอย่างด้วย e.g. notes.txt — ช่วยให้ Claude รู้ว่าต้องส่ง format แบบไหน
Tool ที่ 3: return_answer (tool พิเศษ)
{
"name": "return_answer",
"description": "Return the final answer to the user in structured format",
"input_schema": {
"type": "object",
"properties": {
"answer": {"type": "string", "description": "The answer to the user's question"},
"source_files": {"type": "array", "items": {"type": "string"}, "description": "Files used to answer"},
"confidence": {"type": "string", "enum": ["high", "medium", "low"]},
"found_in_docs": {"type": "boolean", "description": "Was the answer found in the documents?"}
},
"required": ["answer", "source_files", "confidence", "found_in_docs"]
}
}Tool นี้ พิเศษ — มันไม่ได้ทำงานอะไรจริงๆ แต่เป็นวิธีบังคับให้ Claude ส่งคำตอบในรูปแบบที่เรากำหนด
แทนที่จะให้ Claude ตอบเป็นข้อความธรรมดา เราบอกว่า “ถ้าจะตอบ ต้องบอก 4 อย่างนี้เสมอ: คำตอบ, ไฟล์ที่ใช้, ความมั่นใจ, และเจอในเอกสารไหม”
💡 เทคนิคนี้เรียกว่า Structured Output via Tool — ดีกว่าการบอกให้ Claude “ตอบเป็น JSON” ตรงๆ เพราะ tool schema บังคับ format ได้เข้มงวดกว่า
Description สำคัญแค่ไหน?
ทดลองนึกดูว่าถ้าเราเปลี่ยน description ของ list_files จาก:
“List all available files in the docs folder”
เป็น:
“ls”
Claude อาจจะไม่รู้เลยว่าควรเรียก tool นี้เมื่อไหร่
description คือ “คำสั่ง” ที่ Claude อ่าน — ยิ่งชัด ยิ่งอธิบายดี Claude ยิ่งใช้ tool ได้ถูกต้อง
สรุปตอนที่ 3
เราบอก Claude ว่ามี tool อะไรผ่าน list ของ dictionary แต่ละ tool มี name, description และ input_schema
สิ่งที่น่าสนใจที่สุดคือ return_answer — tool ที่ไม่ได้ทำงานจริง แต่ใช้บังคับให้ Claude ตอบในรูปแบบที่เรากำหนด
ตอนหน้าเราจะดูว่าเมื่อ Claude ตัดสินใจเรียก tool แล้ว — โปรแกรมของเราจัดการยังไง
📚 Series: จาก 0 ถึง AI Agent — บันทึกการเรียนรู้ผ่านโปรเจกต์จริง
- ตอนที่ 1: เริ่มต้นกับ Anthropic API
- ตอนที่ 2: Tool Calling คืออะไร
- ตอนที่ 3: นิยาม Tools ให้ Claude ใช้ ← คุณอยู่ที่นี่
- ตอนที่ 4: Agent Loop — วนจนกว่าจะได้คำตอบ
- ตอนที่ 5: Pydantic กับ Structured Output
- ตอนที่ 6: รันจริง และสิ่งที่ได้เรียนรู้
Source code ทั้งหมดอยู่ที่ github.com/nipitpongpan/ask-my-docs
Leave a Reply to Pydantic กับ Structured Output – น้ากวาง – Na Kwang Cancel reply