Với việc ra mắt GPT-5, OpenAI đã mở rộng khả năng gọi công cụ/hàm trong API để bao gồm các lệnh gọi công cụ tự do (văn bản thô, không JSON), ràng buộc ngữ pháp qua Lark/CFG, danh sách công cụ cho phép, và cải thiện khả năng lập luận khi dùng công cụ. Kết hợp lại, những tính năng này biến GPT-5 thành một mô hình thực sự mang tính tác vụ; bạn có thể kết nối API, cơ sở dữ liệu và công cụ tùy chỉnh vào Responses API để tạo câu trả lời bám dữ liệu hoặc thậm chí tự động hóa quy trình công việc.
Trong hướng dẫn này, tôi sẽ trình bày về các công cụ dạng hàm, công cụ tùy chỉnh, ràng buộc ngữ pháp, danh sách công cụ cho phép và preamble, kèm ví dụ mã và giải thích rõ ràng về cách hoạt động cũng như thời điểm sử dụng.
Gọi hàm trong GPT-5: Là gì & Vì sao
Gọi hàm trong GPT-5 cho phép bạn tăng cường mô hình bằng dữ liệu và hành động của ứng dụng. Mô hình có thể quyết định khi nào gọi công cụ, còn bạn xử lý logic và trả kết quả để tạo phản hồi cuối cùng bám dữ liệu.
Các loại gọi hàm:
Công cụ hàm (JSON Schema): Cung cấp đầu vào/ra có cấu trúc để mô hình có thể gọi chính xác.
Công cụ tùy chỉnh (tự do): Cung cấp đầu vào/ra văn bản linh hoạt cho tích hợp phi cấu trúc.
Gọi hàm là gì?
GPT-5 hỗ trợ cả công cụ hàm có cấu trúc (dùng JSON Schema) và công cụ tùy chỉnh chấp nhận tải trọng văn bản tự do (như SQL, script, hoặc cấu hình) để tích hợp liền mạch với các runtime bên ngoài.
Công cụ hàm được định nghĩa bằng JSON Schema, đảm bảo mô hình hiểu chính xác các đối số cần truyền và cho phép xác thực đầu vào nghiêm ngặt. Bạn có thể đọc thêm trong hướng dẫn Gọi hàm OpenAI.
Vì sao dùng gọi hàm?
Linh hoạt: Công cụ tự do cho phép mô hình tạo đúng văn bản mà hệ thống của bạn cần, không bị ràng buộc bởi JSON cứng, lý tưởng cho mã, truy vấn hoặc cấu hình.
Độ tin cậy và kiểm soát: Công cụ hàm áp đặt đối số có cấu trúc, giúp tăng tính dự đoán và giảm lỗi phân tích cú pháp.
Quy trình tác vụ: GPT-5 được thiết kế cho các tác vụ công cụ đa bước, phức tạp và viết mã, khiến gọi công cụ trở thành tính năng trọng tâm.
Gọi hàm hoạt động thế nào?
Gửi prompt bao gồm tất cả công cụ sẵn có.
Mô hình phát lệnh gọi công cụ (kèm đối số hoặc văn bản tự do).
Ứng dụng của bạn thực thi công cụ (chạy hàm Python).
Trả kết quả từ công cụ về cho mô hình.
Mô hình sau đó phản hồi hoặc có thể gọi thêm công cụ.
Dùng công cụ hàm khi bạn muốn xác thực nghiêm ngặt và đối số kiểu rõ ràng, có thể dự đoán qua JSON Schema.
Dùng công cụ tùy chỉnh (tự do) khi runtime của bạn cần văn bản thô (như script, SQL, hoặc cấu hình) hoặc khi bạn cần lặp nhanh mà không cần schema.
Công cụ Hàm (JSON Schema): Gửi Dữ liệu Có cấu trúc
Sử dụng Công cụ Hàm với JSON Schema giúp bạn nhận kết quả có cấu trúc và có thể dự đoán từ mô hình. Mô hình đánh giá các công cụ bạn khai báo, quyết định khi nào sử dụng, đề xuất đối số được xác thực theo JSON, rồi thực thi hàm tương ứng trong mã của bạn.
Sau đó, bạn có thể yêu cầu mô hình tạo phản hồi chỉ dựa trên dữ liệu công cụ trả về, đảm bảo đầu ra bám dữ liệu, máy có thể đọc và dễ tích hợp.
Ví dụ sau minh họa một số khái niệm chính:
Khám phá công cụ và sinh đối số: Mô hình chọn công cụ phù hợp và tự động điền các đối số kiểu JSON của nó.
Vòng lặp thực thi công cụ: Ứng dụng của bạn thực thi công cụ được yêu cầu và gửi kết quả về cho mô hình.
Câu trả lời theo khuôn schema: Phản hồi cuối cùng dựa chặt chẽ trên đầu ra từ các công cụ, giảm sai lệch và đảm bảo độ tin cậy.
1. Thiết lập
Tạo tài khoản OpenAI và tạo khóa API trên bảng điều khiển. Trong bảng điều khiển, mở mục API, sau đó “View API keys” và nhấp “Create new secret key”.
Thêm phương thức thanh toán hoặc tín dụng vào tài khoản để có thể gọi API; mức sử dụng sẽ trừ vào số dư trả trước khi bạn gửi yêu cầu.
Lưu khóa API thành biến môi trường tên OPENAI_API_KEY trước khi khởi chạy ứng dụng.
Cài OpenAI Python SDK chính thức với pip install openai.
2. Định nghĩa công cụ
Bạn cung cấp danh sách công cụ với tên, mô tả và JSON Schema cho tham số. Schema giúp mô hình cung cấp đối số đúng chuẩn.
make_coffee yêu cầu một tham số chuỗi: coffee_type.
random_coffee_fact không nhận tham số (đối tượng rỗng). Các định nghĩa này được truyền qua đối số tools trong lệnh gọi API để mô hình biết những gì sẵn có.
import os
from openai import OpenAI
import json
client = OpenAI(api_key = os.environ["OPENAI_API_KEY"])
tools =[{"type":"function","name":"make_coffee","description":"Gives a simple recipe for making a coffee drink.","parameters":{"type":"object","properties":{"coffee_type":{"type":"string","description":"The coffee drink, e.g. espresso, cappuccino, latte"}},"required":["coffee_type"],},},{"type":"function","name":"random_coffee_fact","description":"Returns a fun fact about coffee.","parameters":{"type":"object","properties":{}}}]Được hỗ trợ bởi
3. Triển khai công cụ
Bạn triển khai các hàm Python thực sự thực hiện công việc:
make_coffee(coffee_type) trả về chuỗi công thức ngắn gọn theo đồ uống yêu cầu.
random_coffee_fact() trả về một payload thông tin thú vị nhỏ.
Cả hai đều trả về dict có thể tuần tự hóa JSON, rất phù hợp để đưa lại cho mô hình.
defmake_coffee(coffee_type):
recipes ={"espresso":"Grind fine, 18g coffee → 36g espresso in ~28s.","cappuccino":"Brew 1 espresso shot, steam 150ml milk, pour and top with foam.","latte":"Brew 1 espresso shot, steam 250ml milk, pour for silky texture.",}return{"coffee_type": coffee_type,"recipe": recipes.get(coffee_type.lower(),"Unknown coffee type!")}defrandom_coffee_fact():return{"fact":"Coffee is the second most traded commodity in the world, after oil."}Được hỗ trợ bởi
4. Bắt đầu hội thoại
Khởi tạo hội thoại với câu hỏi của người dùng: {"role": "user", "content": "How do I make a latte?"}
Mô hình có thể trả về các message bao gồm mục function_call, chẳng hạn make_coffee với {"coffee_type":"latte"}. Khi đó bạn nên nối các message của mô hình trở lại vào input_list: input_list += response.output. Cách này giúp duy trì trạng thái hội thoại cho lượt kế tiếp.
# Track used tools
used_tools =[]
input_list =[{"role":"user","content":"How do I make a latte?"}]
response = client.responses.create(
model="gpt-5",
tools=tools,input=input_list,)
input_list += response.outputĐược hỗ trợ bởi
5. Thực thi lệnh gọi công cụ và đính kèm đầu ra
Bạn nên lặp qua response.output và xác định các mục có item.type bằng "function_call". Với các mục này, phân tích item.arguments và chuyển yêu cầu đến các hàm Python của bạn.
Với hàm make_coffee, gọi bằng make_coffee(args["coffee_type"]). Với hàm random_coffee_fact, chỉ cần gọi random_coffee_fact().
Sau khi thực thi hàm, nối thêm một message function_call_output bao gồm các mục sau:
call_id (liên kết đầu ra này với yêu cầu của mô hình)
output (một chuỗi JSON của kết quả hàm).
for item in response.output:ifgetattr(item,"type","")=="function_call":
used_tools.append(item.name)
args = json.loads(item.arguments or"{}")if item.name =="make_coffee":
result = make_coffee(args["coffee_type"])elif item.name =="random_coffee_fact":
result = random_coffee_fact()else:
result ={"error":f"Unknown tool {item.name}"}
input_list.append({"type":"function_call_output","call_id": item.call_id,"output": json.dumps(result)})Được hỗ trợ bởi
6. Tạo câu trả lời cuối
Bạn thực hiện lệnh gọi client.responses.create lần hai, truyền input_list đã được cập nhật, hiện bao gồm đầu ra công cụ.
Biến used_tools ghi lại tên các công cụ xuất hiện trong lệnh gọi hàm của mô hình. Chúng ta sẽ dùng nó để hiển thị công cụ nào đã được dùng.
final = client.responses.create(
model="gpt-5",
tools=tools,input=input_list,
instructions="Answer using only the tool results.")print("Final output:\n", final.output_text)print("\n--- Tool Usage ---")for t in tools:
status ="USED ✅"if t["name"]in used_tools else"NOT USED ❌"print(f"{t['name']}: {status}")Được hỗ trợ bởi
Vì người dùng hỏi về latte, mô hình đã chọn make_coffee với coffee_type = "latte", mã của bạn thực thi hàm đó và phản hồi cuối cùng chỉ được xây dựng từ kết quả công cụ đó.
Final output:{"coffee_type":"latte","recipe":"Brew 1 espresso shot, steam 250ml milk, pour for silky texture."}--- Tool Usage ---
make_coffee: USED ✅
random_coffee_fact: NOT USED ❌Được hỗ trợ bởi
Công cụ Tùy chỉnh (Tự do): Gửi Văn bản Thô
Dùng công cụ tùy chỉnh tự do của GPT-5 để cho phép mô hình gửi trực tiếp văn bản thô tới công cụ của bạn, như mã, SQL, lệnh shell, hoặc CSV đơn giản, mà không cần JSON Schema.
Khả năng này vượt xa kiểu gọi hàm chỉ JSON trước đây, mang lại sự linh hoạt lớn hơn để tích hợp với executor, engine truy vấn hoặc bộ thông dịch ngôn ngữ chuyên biệt (DSL).
Ở chế độ tự do, mô hình tạo lệnh gọi công cụ tùy chỉnh với payload văn bản phi cấu trúc mà bạn có thể định tuyến đến runtime của mình. Sau đó bạn trả về kết quả để mô hình dùng khi hoàn thiện câu trả lời cho người dùng.
Chúng ta sẽ viết mã cho phép mô hình chọn công cụ phù hợp và trả về văn bản thô không cấu trúc làm đầu ra. Đầu ra này sau đó được truyền vào hàm Python để tạo kết quả. Cách này cho phép người dùng cung cấp nguyên liệu họ có và mô hình sẽ tạo công thức phù hợp với nhu cầu của họ.
Trong ví dụ mã này, chúng ta có:
Khởi tạo client OpenAI và định nghĩa một công cụ tùy chỉnh duy nhất tên meal_planner chấp nhận đầu vào văn bản thô.
Tạo hàm Python plan_meal nhận chuỗi nguyên liệu phân tách bằng dấu phẩy và trả về một ý tưởng bữa ăn.
Bắt đầu hội thoại với message của người dùng liệt kê nguyên liệu sẵn có.
Thực hiện lệnh gọi mô hình đầu tiên hướng dẫn GPT-5 gọi công cụ chỉ bằng danh sách nguyên liệu sạch, và nối đầu ra của mô hình vào lịch sử hội thoại.
Xác định lệnh gọi công cụ tùy chỉnh được phát ra và trích xuất chuỗi đầu vào thô phân tách bằng dấu phẩy.
Thực thi công cụ bằng cách truyền danh sách vào plan_meal, rồi gửi kết quả trở lại mô hình dưới dạng function_call_output được liên kết qua call_id.
Thực hiện lệnh gọi mô hình cuối để chuyển ý tưởng bữa ăn thô thành công thức ngắn gọn, từng bước, và in cả chi tiết lệnh gọi công cụ lẫn đầu ra cuối cùng.
from openai import OpenAI
import json
import random
client = OpenAI()# --- Custom tool ---
tools =[{"type":"custom","name":"meal_planner","description":"Takes ONLY a comma-separated list of ingredients and suggests a meal idea."}]# --- Fake meal planner ---defplan_meal(ingredients:str)->str:
ideas =[f"Stir-fry: {ingredients} with garlic & soy sauce.",f"One-pot rice: cook {ingredients} together in broth until fluffy.",f"Soup: simmer {ingredients} in stock with herbs.",f"Sheet-pan bake: roast {ingredients} at 200°C for ~20 min."]return random.choice(ideas)# --- Start conversation ---
messages =[{"role":"user","content":"I only have chicken, rice, and broccoli. Any dinner ideas?"}]# 1) Ask model with clear instruction
resp = client.responses.create(
model="gpt-5",
tools=tools,input=messages,
instructions="If the user mentions ingredients, call the meal_planner tool with ONLY a comma-separated list like 'chicken, rice, broccoli'.")
messages += resp.output
# 2) Find the tool call
tool_call =next((x for x in resp.output ifgetattr(x,"type","")=="custom_tool_call"),None)assert tool_call,"No tool call found!"# Get clean CSV input
ingredients_csv = tool_call.input.strip()# 3) Run the tool
meal_result = plan_meal(ingredients_csv)# 4) Send tool output back
messages.append({"type":"function_call_output","call_id": tool_call.call_id,"output": meal_result
})# 5) Final model response
final = client.responses.create(
model="gpt-5",
tools=tools,input=messages,
instructions="Turn the meal idea into a short recipe with 3-4 steps.")print("\n--- Tool Call ---")print("Name:", tool_call.name)print("Input:", ingredients_csv)print("Output:", meal_result)print("\n--- Final Output ---\n", final.output_text)Được hỗ trợ bởi
Kết quả là, chúng ta nhận được thống kê về công cụ đã dùng, bao gồm cài đặt, đầu vào và đầu ra. Bên cạnh đó, đầu ra cuối cùng cung cấp một công thức hoàn chỉnh để nấu món ăn.
--- Tool Call ---
Name: meal_planner
Input: chicken, rice, broccoli
Output: One-pot rice: cook chicken, rice, broccoli together in broth until fluffy.
--- Final Output ---
One-Pot Chicken, Rice & Broccoli
- Season bite-size chicken pieces with salt and pepper; sear in a little oil in a pot until lightly browned.
- Add 1 cup rinsed rice and 2 cups broth (or water + salt). Bring to a boil, then cover and simmer on low for12 minutes.
- Scatter 2 cups small broccoli florets on top, cover, and cook 5-7 more minutes until rice is fluffy and broccoli is tender.
- Rest 5 minutes off heat, fluff, and adjust seasoning. Optional: stir in a knob of butter or a splash of soy.Được hỗ trợ bởi
Ràng buộc Ngữ pháp (Lark): Ràng buộc Đầu ra Công cụ
GPT-5 hiện hỗ trợ ngữ pháp phi ngữ cảnh (CFG) để đảm bảo định dạng đầu ra được kiểm soát chặt chẽ.
Bằng cách áp dụng một ngữ pháp, như SQL hoặc DSL, vào phản hồi, GPT-5 đảm bảo đầu ra luôn tuân theo cấu trúc yêu cầu. CFG đặc biệt quan trọng cho quy trình tự động và các tác vụ quan trọng.
GPT-5 có thể dùng ngữ pháp được định nghĩa ở các định dạng như Lark để hạn chế đầu ra của công cụ trong quá trình sinh. Cách giải mã có ràng buộc này tăng độ tin cậy nhờ ngăn trôi định dạng và đảm bảo nhất quán cấu trúc.
Chúng ta sẽ viết mã để mô hình chọn một công cụ và chỉ xuất ra một biểu thức số học hợp lệ theo ngữ pháp; biểu thức này sau đó được đánh giá trong Python, kết quả được trả về hội thoại và phản hồi cuối cùng được trình bày rõ ràng bằng ngôn ngữ tự nhiên.
Trong ví dụ mã này, chúng ta có:
Khởi tạo client OpenAI và định nghĩa công cụ tùy chỉnh math_solver buộc phải chỉ xuất một biểu thức số học hợp lệ theo ngữ pháp (Lark CFG).
Bắt đầu hội thoại bằng câu hỏi toán học ngôn ngữ tự nhiên từ người dùng.
Thực hiện lệnh gọi mô hình đầu tiên hướng dẫn GPT-5 gọi math_solver với một biểu thức tuân theo ngữ pháp.
Xác định lệnh gọi công cụ và trích xuất chuỗi biểu thức thô từ payload của công cụ.
Đánh giá biểu thức cục bộ trong môi trường hạn chế để tạo kết quả cụ thể.
Trả kết quả thực thi công cụ về hội thoại, liên kết qua call_id ban đầu.
Thực hiện lệnh gọi mô hình cuối để trình bày kết quả đã đánh giá rõ ràng bằng ngôn ngữ tự nhiên.
from openai import OpenAI
import json
client = OpenAI()# --- Local fake evaluator ---defeval_expression(expr:str)->str:try:# Evaluate safely using Python's eval on restricted globals
result =eval(expr,{"__builtins__":{}},{})returnf"{expr} = {result}"except Exception as e:returnf"Error evaluating expression: {e}"# --- Custom tool with grammar constraint ---
tools =[{"type":"custom","name":"math_solver","description":"Solve a math problem by outputting ONLY a valid arithmetic expression.","format":{"type":"grammar","syntax":"lark","definition":r"""
start: expr
?expr: term
| expr "+" term -> add
| expr "-" term -> sub
?term: factor
| term "*" factor -> mul
| term "/" factor -> div
?factor: NUMBER
| "(" expr ")"
%import common.NUMBER
%ignore " "
"""},}]# --- User asks ---
msgs =[{"role":"user","content":"What is (12 + 8) * 3 minus 5 divided by 5?"}]# 1) First model call: GPT-5 must emit a grammar-valid expression
resp = client.responses.create(
model="gpt-5",
tools=tools,input=msgs,
instructions="Always call the math_solver tool with a grammar-valid arithmetic expression like '(12 + 8) * 3 - 5 / 5'.")
msgs += resp.output
tool_call =next(
x for x in resp.output
ifgetattr(x,"type","")in("custom_tool_call","tool_call","function_call"))
expr =getattr(tool_call,"input","")orgetattr(tool_call,"arguments","")print("\n=== Grammar-Constrained Expression ===")print(expr)# 2) Run the local evaluator
tool_result = eval_expression(expr)print("\n=== Tool Execution Result ===")print(tool_result)# 3) Return tool output
msgs.append({"type":"function_call_output","call_id": tool_call.call_id,"output": tool_result
})# 4) Final pass: GPT-5 presents answer nicely
final = client.responses.create(
model="gpt-5",input=msgs,
tools=tools,
instructions="Present the evaluated result clearly in natural language.")print("\n=== Final Output ===")print(final.output_text)Được hỗ trợ bởi
Như bạn thấy, mô hình đã chọn công cụ rồi tạo một biểu thức bị ràng buộc bởi ngữ pháp. Sau đó, nó được đưa qua hàm Python để tạo đáp án. Cuối cùng, chúng ta có câu trả lời đúng bằng ngôn ngữ tự nhiên.
=== Grammar-Constrained Expression ===(12 + 8) * 3 - 5 / 5=== Tool Execution Result ===(12 + 8) * 3 - 5 / 5=59.0=== Final Output ===59Được hỗ trợ bởi
Danh sách Công cụ Cho phép: Giới hạn an toàn những gì mô hình có thể dùng
Thiết lập allowed_tools cho phép bạn giới hạn mô hình vào một tập công cụ an toàn từ bộ công cụ đầy đủ. Điều này tăng tính dự đoán và ngăn lệnh gọi công cụ ngoài ý muốn, đồng thời vẫn cho mô hình sự linh hoạt trong phạm vi cho phép.
Bạn có thể cho mô hình chọn trong các công cụ được phép hoặc yêu cầu nó phải dùng một công cụ, phản chiếu hành vi “ép dùng công cụ” trong các stack khác và phù hợp với thực tiễn điều phối gọi công cụ.
Chúng ta sẽ viết mã cho phép một công cụ duy nhất, để mô hình chỉ gọi công cụ đó, chạy nó, đưa kết quả trở lại, rồi tạo bản tóm tắt ngắn gọn cho người dùng.
Lưu ý: Vui lòng tạo tài khoản Firecrawl miễn phí, tạo khóa API, lưu thành biến môi trường FIRECRAWL_API_KEY, và cài Firecrawl Python SDK bằng pip install firecrawl-py.
Trong ví dụ mã này, chúng ta có:
Định nghĩa bộ công cụ đầy đủ gồm cả dummy_web_search và firecrawl_search.
Giới hạn mô hình chỉ dùng firecrawl_search qua tool_choice = { type: "allowed_tools", mode: "required", tools: [...] }.
Thực hiện lệnh gọi mô hình lần đầu, ghi nhận tên lệnh gọi công cụ và đối số, và in ra để quan sát.
Khi firecrawl_search được gọi, giải tuần tự đối số, thực thi Firecrawl, chuyển phản hồi thành dict có thể tuần tự hóa JSON và trích phần dữ liệu an toàn.
Đưa kết quả công cụ trở lại hội thoại bằng function_call_output liên kết bởi call_id, rồi thực hiện lệnh gọi cuối để tóm tắt thành 3–4 gạch đầu dòng với liên kết Markdown.
Bao gồm nhánh dự phòng sẽ chạy công cụ giả (dù danh sách cho phép ngăn điều này trong lượt chạy này).
In câu trả lời cuối cùng bằng ngôn ngữ tự nhiên.
from openai import OpenAI
from firecrawl import Firecrawl
import json
import os
client = OpenAI()
firecrawl = Firecrawl(api_key=os.environ["FIRECRAWL_API_KEY"])# --- Full toolset ---
tools =[{"type":"function","name":"dummy_web_search","description":"A fake web search that always returns static dummy results.","parameters":{"type":"object","properties":{"query":{"type":"string"},"limit":{"type":"integer"}},"required":["query"]},},{"type":"function","name":"firecrawl_search","description":"Perform a real web search using Firecrawl.","parameters":{"type":"object","properties":{"query":{"type":"string"},"limit":{"type":"integer"}},"required":["query"]},},]# --- Dummy implementation ---defdummy_web_search(query, limit=3):return{"query": query,"results":[f"[Dummy] Result {i+1} for '{query}'"for i inrange(limit)]}# --- User asks ---
messages =[{"role":"user","content":"Find me the latest info about the stock market."}]# --- Restrict to Firecrawl only ---
resp = client.responses.create(
model="gpt-5",
tools=tools,input=messages,
instructions="Only the firecrawl_search tool is allowed. Do not use dummy_web_search.",
tool_choice={"type":"allowed_tools","mode":"required",# force Firecrawl"tools":[{"type":"function","name":"firecrawl_search"}],},)for item in resp.output:ifgetattr(item,"type","")in("function_call","tool_call"):print("\n--- Tool Call ---")print("Tool name:", item.name)print("Arguments:", item.arguments)if item.name =="firecrawl_search":
args = json.loads(item.arguments)# Firecrawl returns a SearchData object → convert it
results_obj = firecrawl.search(
query=args["query"],
limit=args.get("limit",3),)# 🔥 Convert to JSON-serializable dictifhasattr(results_obj,"to_dict"):
results = results_obj.to_dict()elifhasattr(results_obj,"dict"):
results = results_obj.dict()else:
results = json.loads(results_obj.json())ifhasattr(results_obj,"json")else results_obj
print("\n--- Firecrawl Raw Results ---")print(json.dumps(results, indent=2)[:500])# ✅ Extract only the data portion for summarization
safe_results = results.get("data", results)# Feed back to GPT
messages += resp.output
messages.append({"type":"function_call_output","call_id": item.call_id,"output": json.dumps(safe_results)# now safe})# Final pass
final = client.responses.create(
model="gpt-5",
tools=tools,input=messages,
instructions="Summarize the Firecrawl search results into 3-4 bullet points with clickable [Title](URL) links.")print("\n--- Final Natural Language Answer ---")print(final.output_text)elif item.name =="dummy_web_search":
args = json.loads(item.arguments)
results = dummy_web_search(args["query"], args.get("limit",3))print("\n--- Dummy Web Search Results ---")print(json.dumps(results, indent=2))Được hỗ trợ bởi
Mô hình đã chọn tìm kiếm Firecrawl và từ đó tạo phản hồi cuối cùng theo định dạng markdown.
Preamble: Hướng dẫn mô hình cách gọi công cụ
Preamble là phần giải thích ngắn mà mô hình tạo trước khi gọi công cụ, nêu rõ lý do gọi. Chúng tăng tính minh bạch, xây dựng niềm tin và cải thiện khả năng gỡ lỗi trong quy trình phức tạp. Bạn có thể bật bằng một hướng dẫn đơn giản như “giải thích trước khi gọi công cụ,” thường không làm tăng độ trễ đáng kể.
Chúng ta sẽ viết mã trong đó mô hình trước tiên tạo một dòng “Preamble:” ngắn giải thích vì sao nó gọi công cụ, sau đó gọi công cụ, bạn thực thi cục bộ, trả về kết quả, và mô hình tạo câu trả lời cuối cùng rõ ràng.
Trong ví dụ mã này, chúng ta có:
Khởi tạo client OpenAI và định nghĩa một công cụ hàm kiểu nghiêm ngặt (medical_advice) với JSON Schema.
Thêm hướng dẫn hệ thống yêu cầu mô hình xuất một dòng “Preamble:” trước mọi lệnh gọi công cụ.
Khởi tạo hội thoại bằng câu hỏi về triệu chứng của người dùng.
Thực hiện lệnh gọi mô hình đầu tiên để nhận cả preamble và lệnh gọi công cụ với đối số.
Trích xuất và thực thi công cụ cục bộ để tạo khuyến nghị.
Trả đầu ra của công cụ về mô hình, liên kết qua call_id.
Thực hiện lệnh gọi mô hình cuối để GPT‑5 trình bày kết quả ngắn gọn, dễ hiểu.
from openai import OpenAI
import json
import random
client = OpenAI()# --- Fake tool implementation ---defmedical_advice(symptom:str):
remedies ={"headache":"You can take acetaminophen (paracetamol) or ibuprofen, rest in a quiet room, and stay hydrated.","cough":"Drink warm fluids, use honey in tea, and consider over-the-counter cough syrup.","fever":"Use acetaminophen to reduce fever, stay hydrated, and rest. See a doctor if >39°C.",}return{"advice": remedies.get(symptom.lower(),"Please consult a healthcare provider for guidance.")}# --- Tool definition ---
tools =[{"type":"function","name":"medical_advice","description":"Provide safe, general over-the-counter advice for common symptoms.","parameters":{"type":"object","properties":{"symptom":{"type":"string"}},"required":["symptom"],"additionalProperties":False},"strict":True,}]# --- Messages (system preamble instruction) ---
messages =[{"role":"system","content":"Before you call a tool, explain why you are calling it in ONE short sentence prefixed with 'Preamble:'."},{"role":"user","content":"What should I take for a headache?"}]# 1) First call: expect preamble + tool call
resp = client.responses.create(model="gpt-5",input=messages, tools=tools)print("=== First Response ===")for item in resp.output:
t =getattr(item,"type",None)if t =="message":# Extract just the model's text
content =getattr(item,"content",None)
text =Noneifisinstance(content,list):
text ="".join([c.text for c in content ifhasattr(c,"text")])elif content:
text =str(content)if text:# ✅ Only print onceprint(text)if t in("function_call","tool_call","custom_tool_call"):print("Tool:",getattr(item,"name",None))print("Args:",getattr(item,"arguments",None))# Extract tool call
tool_call =next(x for x in resp.output ifgetattr(x,"type",None)in("function_call","tool_call","custom_tool_call"))
messages += resp.output
# 2) Execute tool locally
args = json.loads(getattr(tool_call,"arguments","{}"))
symptom = args.get("symptom","")
tool_result = medical_advice(symptom)# 3) Return tool result
messages.append({"type":"function_call_output","call_id": tool_call.call_id,"output": json.dumps(tool_result)})# 4) Final model call → natural answer
final = client.responses.create(model="gpt-5",input=messages, tools=tools)print("\n=== Final Answer ===")print(final.output_text)Được hỗ trợ bởi
Bạn có thể thấy trước khi gọi công cụ, mô hình cung cấp lời giải thích vì sao nó gọi công cụ. Điều này hữu ích cho khả năng quan sát và gỡ lỗi.
Tổng kết
GPT-5 là mô hình tiên tiến nhất của OpenAI tính đến nay, đặc biệt vượt trội trong viết mã và các quy trình dựa trên tác vụ. Những tính năng API mới nhất cho phép phát triển hệ thống cấp sản xuất một cách trọn vẹn, đơn giản.
Trong hướng dẫn này, bạn đã học cách:
Trả đầu ra có cấu trúc bằng Công cụ Hàm và JSON Schema để tự động hóa hạ nguồn đáng tin cậy.
Kích hoạt chế độ tự do với Công cụ Tùy chỉnh (văn bản thô), cho phép mô hình tạo mã, SQL, script shell và tệp CSV vượt ra ngoài chỉ các lệnh gọi JSON.
Ràng buộc định dạng bằng ngữ pháp Lark khi cần độ chính xác, như toán học, SQL hoặc DSL.
Giới hạn truy cập công cụ bằng danh sách cho phép (hoặc ép dùng một công cụ) để tăng an toàn, kiểm soát và tính quyết định.
Cải thiện tính minh bạch với preamble ngắn, để mô hình giải thích vì sao gọi công cụ cụ thể, hỗ trợ quan sát và gỡ lỗi.
Là một nhà khoa học dữ liệu được chứng nhận, tôi đam mê tận dụng công nghệ tiên tiến để tạo ra các ứng dụng học máy đổi mới. Với nền tảng vững chắc về nhận dạng giọng nói, phân tích và báo cáo dữ liệu, MLOps, AI hội thoại và NLP, tôi đã rèn giũa kỹ năng phát triển các hệ thống thông minh có thể tạo ra tác động thực sự. Bên cạnh chuyên môn kỹ thuật, tôi cũng là một người truyền đạt tốt, có khả năng chắt lọc các khái niệm phức tạp thành ngôn ngữ rõ ràng, súc tích. Nhờ đó, tôi trở thành một blogger được nhiều người quan tâm trong lĩnh vực khoa học dữ liệu, chia sẻ góc nhìn và kinh nghiệm với cộng đồng các chuyên gia dữ liệu ngày càng lớn. Hiện tại, tôi tập trung vào sáng tạo và biên tập nội dung, làm việc với các mô hình ngôn ngữ lớn để phát triển nội dung mạnh mẽ và hấp dẫn, giúp doanh nghiệp và cá nhân tận dụng tối đa dữ liệu của mình.
Hãy bắt đầu tạo ra các hệ thống trí tuệ nhân tạo bằng cách sử dụng các mô hình từ OpenAI. Hãy tìm hiểu cách sử dụng API của OpenAI để kích hoạt các mô hình GPT và Whisper của OpenAI.
Với việc ra mắt GPT-5, OpenAI đã mở rộng khả năng gọi công cụ/hàm trong API để bao gồm các lệnh gọi công cụ tự do (văn bản thô, không JSON), ràng buộc ngữ pháp qua Lark/CFG, danh sách công cụ cho phép, và cải thiện khả năng lập luận khi dùng công cụ. Kết hợp lại, những tính năng này biến GPT-5 thành một mô hình thực sự mang tính tác vụ; bạn có thể kết nối API, cơ sở dữ liệu và công cụ tùy chỉnh vào Responses API để tạo câu trả lời bám dữ liệu hoặc thậm chí tự động hóa quy trình công việc.
Trong hướng dẫn này, tôi sẽ trình bày về các công cụ dạng hàm, công cụ tùy chỉnh, ràng buộc ngữ pháp, danh sách công cụ cho phép và preamble, kèm ví dụ mã và giải thích rõ ràng về cách hoạt động cũng như thời điểm sử dụng.
Gọi hàm trong GPT-5: Là gì & Vì sao
Gọi hàm trong GPT-5 cho phép bạn tăng cường mô hình bằng dữ liệu và hành động của ứng dụng. Mô hình có thể quyết định khi nào gọi công cụ, còn bạn xử lý logic và trả kết quả để tạo phản hồi cuối cùng bám dữ liệu.
Các loại gọi hàm:
Gọi hàm là gì?
GPT-5 hỗ trợ cả công cụ hàm có cấu trúc (dùng JSON Schema) và công cụ tùy chỉnh chấp nhận tải trọng văn bản tự do (như SQL, script, hoặc cấu hình) để tích hợp liền mạch với các runtime bên ngoài.
Công cụ hàm được định nghĩa bằng JSON Schema, đảm bảo mô hình hiểu chính xác các đối số cần truyền và cho phép xác thực đầu vào nghiêm ngặt. Bạn có thể đọc thêm trong hướng dẫn Gọi hàm OpenAI.
Vì sao dùng gọi hàm?
Gọi hàm hoạt động thế nào?
Nguồn: Function calling - OpenAI API
Khi nào dùng Công cụ Hàm so với Công cụ Tùy chỉnh
Công cụ Hàm (JSON Schema): Gửi Dữ liệu Có cấu trúc
Sử dụng Công cụ Hàm với JSON Schema giúp bạn nhận kết quả có cấu trúc và có thể dự đoán từ mô hình. Mô hình đánh giá các công cụ bạn khai báo, quyết định khi nào sử dụng, đề xuất đối số được xác thực theo JSON, rồi thực thi hàm tương ứng trong mã của bạn.
Sau đó, bạn có thể yêu cầu mô hình tạo phản hồi chỉ dựa trên dữ liệu công cụ trả về, đảm bảo đầu ra bám dữ liệu, máy có thể đọc và dễ tích hợp.
Ví dụ sau minh họa một số khái niệm chính:
1. Thiết lập
pip install openai.2. Định nghĩa công cụ
Bạn cung cấp danh sách công cụ với tên, mô tả và JSON Schema cho tham số. Schema giúp mô hình cung cấp đối số đúng chuẩn.
make_coffeeyêu cầu một tham số chuỗi:coffee_type.random_coffee_factkhông nhận tham số (đối tượng rỗng). Các định nghĩa này được truyền qua đối sốtoolstrong lệnh gọi API để mô hình biết những gì sẵn có.3. Triển khai công cụ
Bạn triển khai các hàm Python thực sự thực hiện công việc:
make_coffee(coffee_type)trả về chuỗi công thức ngắn gọn theo đồ uống yêu cầu.random_coffee_fact()trả về một payload thông tin thú vị nhỏ.Cả hai đều trả về dict có thể tuần tự hóa JSON, rất phù hợp để đưa lại cho mô hình.
4. Bắt đầu hội thoại
Khởi tạo hội thoại với câu hỏi của người dùng: {
"role": "user", "content": "How do I make a latte?"}Mô hình có thể trả về các message bao gồm mục
function_call, chẳng hạnmake_coffeevới {"coffee_type":"latte"}. Khi đó bạn nên nối các message của mô hình trở lại vàoinput_list: input_list += response.output. Cách này giúp duy trì trạng thái hội thoại cho lượt kế tiếp.5. Thực thi lệnh gọi công cụ và đính kèm đầu ra
Bạn nên lặp qua
response.outputvà xác định các mục cóitem.typebằng"function_call". Với các mục này, phân tíchitem.argumentsvà chuyển yêu cầu đến các hàm Python của bạn.Với hàm
make_coffee, gọi bằngmake_coffee(args["coffee_type"]). Với hàmrandom_coffee_fact, chỉ cần gọirandom_coffee_fact().Sau khi thực thi hàm, nối thêm một message
function_call_outputbao gồm các mục sau:call_id(liên kết đầu ra này với yêu cầu của mô hình)output(một chuỗi JSON của kết quả hàm).6. Tạo câu trả lời cuối
Bạn thực hiện lệnh gọi
client.responses.createlần hai, truyềninput_listđã được cập nhật, hiện bao gồm đầu ra công cụ.Biến
used_toolsghi lại tên các công cụ xuất hiện trong lệnh gọi hàm của mô hình. Chúng ta sẽ dùng nó để hiển thị công cụ nào đã được dùng.Vì người dùng hỏi về latte, mô hình đã chọn
make_coffeevớicoffee_type = "latte", mã của bạn thực thi hàm đó và phản hồi cuối cùng chỉ được xây dựng từ kết quả công cụ đó.Công cụ Tùy chỉnh (Tự do): Gửi Văn bản Thô
Dùng công cụ tùy chỉnh tự do của GPT-5 để cho phép mô hình gửi trực tiếp văn bản thô tới công cụ của bạn, như mã, SQL, lệnh shell, hoặc CSV đơn giản, mà không cần JSON Schema.
Khả năng này vượt xa kiểu gọi hàm chỉ JSON trước đây, mang lại sự linh hoạt lớn hơn để tích hợp với executor, engine truy vấn hoặc bộ thông dịch ngôn ngữ chuyên biệt (DSL).
Ở chế độ tự do, mô hình tạo lệnh gọi công cụ tùy chỉnh với payload văn bản phi cấu trúc mà bạn có thể định tuyến đến runtime của mình. Sau đó bạn trả về kết quả để mô hình dùng khi hoàn thiện câu trả lời cho người dùng.
Chúng ta sẽ viết mã cho phép mô hình chọn công cụ phù hợp và trả về văn bản thô không cấu trúc làm đầu ra. Đầu ra này sau đó được truyền vào hàm Python để tạo kết quả. Cách này cho phép người dùng cung cấp nguyên liệu họ có và mô hình sẽ tạo công thức phù hợp với nhu cầu của họ.
Trong ví dụ mã này, chúng ta có:
meal_plannerchấp nhận đầu vào văn bản thô.plan_mealnhận chuỗi nguyên liệu phân tách bằng dấu phẩy và trả về một ý tưởng bữa ăn.plan_meal, rồi gửi kết quả trở lại mô hình dưới dạngfunction_call_outputđược liên kết quacall_id.Kết quả là, chúng ta nhận được thống kê về công cụ đã dùng, bao gồm cài đặt, đầu vào và đầu ra. Bên cạnh đó, đầu ra cuối cùng cung cấp một công thức hoàn chỉnh để nấu món ăn.
Ràng buộc Ngữ pháp (Lark): Ràng buộc Đầu ra Công cụ
GPT-5 hiện hỗ trợ ngữ pháp phi ngữ cảnh (CFG) để đảm bảo định dạng đầu ra được kiểm soát chặt chẽ.
Bằng cách áp dụng một ngữ pháp, như SQL hoặc DSL, vào phản hồi, GPT-5 đảm bảo đầu ra luôn tuân theo cấu trúc yêu cầu. CFG đặc biệt quan trọng cho quy trình tự động và các tác vụ quan trọng.
GPT-5 có thể dùng ngữ pháp được định nghĩa ở các định dạng như Lark để hạn chế đầu ra của công cụ trong quá trình sinh. Cách giải mã có ràng buộc này tăng độ tin cậy nhờ ngăn trôi định dạng và đảm bảo nhất quán cấu trúc.
Chúng ta sẽ viết mã để mô hình chọn một công cụ và chỉ xuất ra một biểu thức số học hợp lệ theo ngữ pháp; biểu thức này sau đó được đánh giá trong Python, kết quả được trả về hội thoại và phản hồi cuối cùng được trình bày rõ ràng bằng ngôn ngữ tự nhiên.
Trong ví dụ mã này, chúng ta có:
math_solverbuộc phải chỉ xuất một biểu thức số học hợp lệ theo ngữ pháp (Lark CFG).math_solvervới một biểu thức tuân theo ngữ pháp.call_idban đầu.Như bạn thấy, mô hình đã chọn công cụ rồi tạo một biểu thức bị ràng buộc bởi ngữ pháp. Sau đó, nó được đưa qua hàm Python để tạo đáp án. Cuối cùng, chúng ta có câu trả lời đúng bằng ngôn ngữ tự nhiên.
Danh sách Công cụ Cho phép: Giới hạn an toàn những gì mô hình có thể dùng
Thiết lập
allowed_toolscho phép bạn giới hạn mô hình vào một tập công cụ an toàn từ bộ công cụ đầy đủ. Điều này tăng tính dự đoán và ngăn lệnh gọi công cụ ngoài ý muốn, đồng thời vẫn cho mô hình sự linh hoạt trong phạm vi cho phép.Bạn có thể cho mô hình chọn trong các công cụ được phép hoặc yêu cầu nó phải dùng một công cụ, phản chiếu hành vi “ép dùng công cụ” trong các stack khác và phù hợp với thực tiễn điều phối gọi công cụ.
Chúng ta sẽ viết mã cho phép một công cụ duy nhất, để mô hình chỉ gọi công cụ đó, chạy nó, đưa kết quả trở lại, rồi tạo bản tóm tắt ngắn gọn cho người dùng.
Lưu ý: Vui lòng tạo tài khoản Firecrawl miễn phí, tạo khóa API, lưu thành biến môi trường
FIRECRAWL_API_KEY, và cài Firecrawl Python SDK bằngpip install firecrawl-py.Trong ví dụ mã này, chúng ta có:
dummy_web_searchvàfirecrawl_search.firecrawl_searchquatool_choice = { type: "allowed_tools", mode: "required", tools: [...] }.firecrawl_searchđược gọi, giải tuần tự đối số, thực thi Firecrawl, chuyển phản hồi thành dict có thể tuần tự hóa JSON và trích phần dữ liệu an toàn.function_call_outputliên kết bởicall_id, rồi thực hiện lệnh gọi cuối để tóm tắt thành 3–4 gạch đầu dòng với liên kết Markdown.Mô hình đã chọn tìm kiếm Firecrawl và từ đó tạo phản hồi cuối cùng theo định dạng markdown.
Preamble: Hướng dẫn mô hình cách gọi công cụ
Preamble là phần giải thích ngắn mà mô hình tạo trước khi gọi công cụ, nêu rõ lý do gọi. Chúng tăng tính minh bạch, xây dựng niềm tin và cải thiện khả năng gỡ lỗi trong quy trình phức tạp. Bạn có thể bật bằng một hướng dẫn đơn giản như “giải thích trước khi gọi công cụ,” thường không làm tăng độ trễ đáng kể.
Chúng ta sẽ viết mã trong đó mô hình trước tiên tạo một dòng “Preamble:” ngắn giải thích vì sao nó gọi công cụ, sau đó gọi công cụ, bạn thực thi cục bộ, trả về kết quả, và mô hình tạo câu trả lời cuối cùng rõ ràng.
Trong ví dụ mã này, chúng ta có:
medical_advice) với JSON Schema.“Preamble:”trước mọi lệnh gọi công cụ.call_id.Bạn có thể thấy trước khi gọi công cụ, mô hình cung cấp lời giải thích vì sao nó gọi công cụ. Điều này hữu ích cho khả năng quan sát và gỡ lỗi.
Tổng kết
GPT-5 là mô hình tiên tiến nhất của OpenAI tính đến nay, đặc biệt vượt trội trong viết mã và các quy trình dựa trên tác vụ. Những tính năng API mới nhất cho phép phát triển hệ thống cấp sản xuất một cách trọn vẹn, đơn giản.
Trong hướng dẫn này, bạn đã học cách:
Để tìm hiểu thêm về những gì bạn có thể làm với các công cụ khác nhau của OpenAI, tôi khuyến nghị học lộ trình kỹ năng OpenAI Fundamentals và khóa học Làm việc với OpenAI API.