Function Calling (Gọi hàm) là một trong những tính năng quan trọng nhất khi làm việc với các mô hình AI. Nó cho phép model gọi các API bên ngoài, truy vấn database, hay thực hiện các tác vụ phức tạp theo cách có cấu trúc. Trong bài viết này, tôi sẽ chia sẻ kinh nghiệm thực chiến khi migrate từ OpenAI Function Calling sang Google Gemini Function Calling, đồng thời so sánh chi tiết về định dạng request/response giữa hai nền tảng.

Bảng so sánh tổng quan: HolySheep vs API chính thức vs Relay Services

Tiêu chí Google API chính thức OpenAI API Relay services khác HolySheep AI
Gemini Function Calling ✅ Hỗ trợ đầy đủ ❌ Không có ⚠️ Hỗ trợ một phần ✅ Native support
Chi phí Gemini 2.5 Flash $2.50/MTok - $2.30-3.00/MTok $2.50/MTok
Chi phí GPT-4.1 - $8/MTok $7.50-9.00/MTok $8/MTok
Độ trễ trung bình 80-150ms 100-200ms 120-250ms <50ms
Thanh toán Card quốc tế Card quốc tế Card/PayPal WeChat/Alipay/Credit Card
Tín dụng miễn phí $0 $5 $0-5 Có khi đăng ký
Tỷ giá USD only USD only USD only ¥1 = $1 (85%+ tiết kiệm)

Tại sao cần so sánh Function Calling giữa OpenAI và Gemini?

Trong quá trình phát triển nhiều dự án AI cho khách hàng tại Việt Nam và quốc tế, tôi nhận thấy rằng 80% developer ban đầu quen thuộc với OpenAI Function Calling. Khi cần tích hợp Gemini để tận dụng chi phí thấp hơn (Gemini 2.5 Flash chỉ $2.50/MTok so với GPT-4o $15/MTok), họ gặp khó khăn vì định dạng hoàn toàn khác biệt.

Điểm mấu chốt: OpenAI dùng cấu trúc tools[], còn Gemini dùng function_declarations[]. Sự khác biệt này ảnh hưởng đến cách bạn parse response và xử lý lỗi.

Định dạng Function Calling: OpenAI vs Gemini chi tiết

1. Cấu trúc Request (OpenAI)

import requests

OpenAI Function Calling - Request format

response = requests.post( "https://api.holysheep.ai/v1/chat/completions", headers={ "Authorization": f"Bearer YOUR_HOLYSHEEP_API_KEY", "Content-Type": "application/json" }, json={ "model": "gpt-4.1", "messages": [ {"role": "user", "content": "Cho tôi biết thời tiết ở Hà Nội"} ], "tools": [ { "type": "function", "function": { "name": "get_weather", "description": "Lấy thông tin thời tiết theo thành phố", "parameters": { "type": "object", "properties": { "city": { "type": "string", "description": "Tên thành phố (VD: Hà Nội, TP.HCM)" }, "unit": { "type": "string", "enum": ["celsius", "fahrenheit"], "description": "Đơn vị nhiệt độ" } }, "required": ["city"] } } } ], "tool_choice": "auto" } ) data = response.json() print(data)

2. Cấu trúc Request (Gemini)

import requests

Gemini Function Calling - Request format (KHÁC BIỆT rõ rệt)

response = requests.post( "https://api.holysheep.ai/v1/chat/completions", headers={ "Authorization": f"Bearer YOUR_HOLYSHEEP_API_KEY", "Content-Type": "application/json" }, json={ "model": "gemini-2.5-flash", "messages": [ {"role": "user", "content": "Cho tôi biết thời tiết ở Hà Nội"} ], # Gemini dùng function_declarations thay vì tools[] "tools": [ { "type": "function", "function": { "name": "get_weather", "description": "Lấy thông tin thời tiết theo thành phố", "parameters": { "type": "object", "properties": { "city": { "type": "string", "description": "Tên thành phố" }, "unit": { "type": "string", "enum": ["celsius", "fahrenheit"] } }, "required": ["city"] } } } ] # ⚠️ Gemini KHÔNG có tool_choice trong request # Mà dùng forced_tool_choice trong tool_config } ) data = response.json() print(data)

3. Parse Response và xử lý Function Call

import json

def handle_function_calls(response_data, model_type="gemini"):
    """
    Xử lý function calls từ response
    Hỗ trợ cả OpenAI và Gemini format
    """
    
    # Kiểm tra xem có function call không
    if response_data.get("finish_reason") == "tool_calls":
        tool_calls = response_data.get("tool_calls", [])
        
        for tool_call in tool_calls:
            # OpenAI dùng: tool_call["function"]["name"]
            # Gemini dùng: tool_call["function"]["name"] (GIỐNG NHAU)
            function_name = tool_call["function"]["name"]
            arguments = json.loads(tool_call["function"]["arguments"])
            
            print(f"🔧 Gọi function: {function_name}")
            print(f"📦 Arguments: {arguments}")
            
            # Xử lý theo function name
            if function_name == "get_weather":
                result = get_weather_api(arguments["city"], arguments.get("unit", "celsius"))
                return result
            
            elif function_name == "get_exchange_rate":
                result = get_exchange_rate_api(arguments["from"], arguments["to"])
                return result
    
    # Không có function call - trả về content thường
    return response_data.get("content", "")


def get_weather_api(city, unit):
    """Mock weather API"""
    return {
        "city": city,
        "temperature": 28,
        "unit": unit,
        "condition": "Nắng có mưa rào",
        "humidity": 75
    }

def get_exchange_rate_api(from_currency, to_currency):
    """Mock exchange rate API"""
    rates = {
        ("USD", "VND"): 24500,
        ("EUR", "VND"): 26500,
        ("CNY", "VND"): 3400
    }
    return {"from": from_currency, "to": to_currency, "rate": rates.get((from_currency, to_currency), 0)}


Sử dụng với response thực tế

example_response = { "id": "chatcmpl-gemini-123", "model": "gemini-2.5-flash", "finish_reason": "tool_calls", "tool_calls": [ { "id": "tool_001", "type": "function", "function": { "name": "get_weather", "arguments": '{"city": "Hà Nội", "unit": "celsius"}' } } ] } result = handle_function_calls(example_response, model_type="gemini") print(f"✅ Kết quả: {result}")

Bảng so sánh chi tiết: OpenAI vs Gemini Function Calling

Aspect OpenAI Google Gemini
Field name tools: [] tools: [] (GIỐNG nhau)
Tool config tool_choice: "auto"|"none"|{object} tool_config: {forced_tool_choice: {...}}
Force function {"type": "function", "function": {"name": "fn_name"}} {forced_tool_choice: {function: {name: "fn_name"}}}
Response field tool_calls[].function.arguments (JSON string) tool_calls[].function.arguments (JSON string)
Finish reason "tool_calls" "tool_calls" hoặc "STOP"
Multi-function Parallel calling được Cần tool_config.parallel_tool_calls: true
Streaming Hỗ trợ qua stream: true Function calls trong stream cần xử lý khác

Code hoàn chỉnh: Multi-turn conversation với Function Calling

import requests
import json
from typing import List, Dict, Any

class AIClient:
    """Universal AI Client hỗ trợ cả OpenAI và Gemini Function Calling"""
    
    def __init__(self, api_key: str, base_url: str = "https://api.holysheep.ai/v1"):
        self.api_key = api_key
        self.base_url = base_url
        self.conversation_history: List[Dict] = []
    
    def chat(
        self, 
        message: str, 
        model: str = "gemini-2.5-flash",
        tools: List[Dict] = None,
        tool_config: Dict = None
    ) -> Dict:
        """
        Gửi message và xử lý function calls tự động
        """
        
        # Thêm user message vào history
        self.conversation_history.append({
            "role": "user", 
            "content": message
        })
        
        payload = {
            "model": model,
            "messages": self.conversation_history,
        }
        
        # Thêm tools nếu có
        if tools:
            payload["tools"] = tools
        
        # Gemini-specific: tool_config
        if tool_config:
            payload["tool_config"] = tool_config
        
        # Gọi API
        response = requests.post(
            f"{self.base_url}/chat/completions",
            headers={
                "Authorization": f"Bearer {self.api_key}",
                "Content-Type": "application/json"
            },
            json=payload
        )
        
        result = response.json()
        
        # Kiểm tra function call
        if "choices" in result and result["choices"]:
            choice = result["choices"][0]
            
            if choice.get("finish_reason") == "tool_calls":
                # Có function call - xử lý và gọi lại
                tool_results = self._process_tool_calls(
                    choice.get("tool_calls", [])
                )
                
                # Thêm assistant message và tool results vào history
                self.conversation_history.append({
                    "role": "assistant",
                    "content": None,
                    "tool_calls": choice.get("tool_calls", [])
                })
                
                for tr in tool_results:
                    self.conversation_history.append(tr)
                
                # Gọi lại để model tạo response cuối cùng
                return self._get_final_response(model)
            
            # Không có function call - trả về content
            return {"content": choice["message"]["content"]}
        
        return result
    
    def _process_tool_calls(self, tool_calls: List[Dict]) -> List[Dict]:
        """Xử lý các function calls"""
        results = []
        
        for tool_call in tool_calls:
            func_name = tool_call["function"]["name"]
            args = json.loads(tool_call["function"]["arguments"])
            
            print(f"🔧 Gọi function: {func_name} với args: {args}")
            
            # Mock implementation - thay bằng logic thực tế
            if func_name == "get_weather":
                result = {"temperature": 30, "condition": "Nắng", "city": args["city"]}
            elif func_name == "calculate":
                result = {"result": eval(f"{args['a']} {args['operator']} {args['b']}")}
            else:
                result = {"error": "Unknown function"}
            
            results.append({
                "role": "tool",
                "tool_call_id": tool_call["id"],
                "content": json.dumps(result)
            })
        
        return results
    
    def _get_final_response(self, model: str) -> Dict:
        """Gọi lại model sau khi xử lý tool results"""
        response = requests.post(
            f"{self.base_url}/chat/completions",
            headers={
                "Authorization": f"Bearer {self.api_key}",
                "Content-Type": "application/json"
            },
            json={
                "model": model,
                "messages": self.conversation_history
            }
        )
        
        result = response.json()
        
        if "choices" in result and result["choices"]:
            final_content = result["choices"][0]["message"]["content"]
            self.conversation_history.append({
                "role": "assistant",
                "content": final_content
            })
            return {"content": final_content}
        
        return result
    
    def reset(self):
        """Reset conversation history"""
        self.conversation_history = []


============== SỬ DỤNG ==============

Khởi tạo client

client = AIClient(api_key="YOUR_HOLYSHEEP_API_KEY")

Định nghĩa functions

weather_tools = [ { "type": "function", "function": { "name": "get_weather", "description": "Lấy thông tin thời tiết", "parameters": { "type": "object", "properties": { "city": {"type": "string"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]} }, "required": ["city"] } } } ]

Ví dụ conversation

print("=== Multi-turn Function Calling Demo ===") response = client.chat( message="Thời tiết ở Hà Nội thế nào?", model="gemini-2.5-flash", tools=weather_tools ) print(f"🤖 Response: {response['content']}")

Tiếp tục conversation

response2 = client.chat( message="Ủa, vậy TP.HCM thì sao?", model="gemini-2.5-flash", tools=weather_tools ) print(f"🤖 Response 2: {response2['content']}")

Lỗi thường gặp và cách khắc phục

Lỗi 1: "Invalid request - missing required parameter 'tools'"

Mô tả lỗi: Khi gọi Gemini với tool_config nhưng không truyền tools[]

# ❌ SAI - thiếu tools khi dùng tool_config
response = requests.post(
    "https://api.holysheep.ai/v1/chat/completions",
    headers={"Authorization": f"Bearer {api_key}"},
    json={
        "model": "gemini-2.5-flash",
        "messages": [...],
        # THIẾU tools[] - LỖI!
        "tool_config": {
            "function_calling_config": {
                "mode": "ANY"
            }
        }
    }
)

✅ ĐÚNG - phải có cả tools và tool_config

response = requests.post( "https://api.holysheep.ai/v1/chat/completions", headers={"Authorization": f"Bearer {api_key}"}, json={ "model": "gemini-2.5-flash", "messages": [...], "tools": [ { "type": "function", "function": { "name": "my_function", "parameters": {...} } } ], # tool_config phải đi KÈM với tools "tool_config": { "function_calling_config": { "mode": "ANY" } } } )

Lỗi 2: JSON parse error khi đọc arguments

Mô tả lỗi: Gemini trả về arguments có thể là string hoặc object tùy version

import json

def safe_parse_arguments(arguments):
    """
    Xử lý an toàn việc parse arguments
    Tránh lỗi: JSONDecodeError khi arguments đã là dict
    """
    
    # Nếu đã là dict - trả về trực tiếp
    if isinstance(arguments, dict):
        return arguments
    
    # Nếu là string - parse thành dict
    if isinstance(arguments, str):
        try:
            return json.loads(arguments)
        except json.JSONDecodeError:
            # Thử loại bỏ escape characters
            return json.loads(arguments.replace("'", '"'))
    
    raise ValueError(f"Không parse được arguments: {type(arguments)}")


Sử dụng

tool_call = { "id": "tool_001", "function": { "name": "get_weather", "arguments": '{"city": "Hà Nội"}' # String } } args = safe_parse_arguments(tool_call["function"]["arguments"]) print(f"City: {args['city']}") # ✅ Không lỗi

Lỗi 3: Model không gọi function (always returns text)

Mô tả lỗi: Model chỉ trả về text thay vì gọi function đã định nghĩa

# Nguyên nhân thường gặp:

1. Description quá ngắn - model không hiểu khi nào cần gọi

❌ Description quá ngắn

"parameters": { "name": "search", "description": "Tìm kiếm" # KHÔNG ĐỦ }

✅ Description chi tiết với ví dụ

"parameters": { "name": "search", "description": "Tìm kiếm sản phẩm trong database. " "Gọi khi user hỏi về sản phẩm, giá cả, tồn kho. " "Ví dụ: 'tìm iPhone 15', 'giá MacBook bao nhiêu'" }

2. Model không nhận đủ context

✅ Luôn thêm context rõ ràng

messages = [ { "role": "system", "content": "Bạn là trợ lý bán hàng. Khi user hỏi về sản phẩm, " "LUÔN gọi function search_product." }, { "role": "user", "content": "Có iPhone 15 không?" } ]

3. Dùng tool_choice sai

❌ Tắt hoàn toàn function calling

"tool_choice": "none"

✅ Cho phép tự động quyết định

"tool_choice": "auto"

Phù hợp / không phù hợp với ai

✅ Nên dùng Gemini Function Calling khi:

❌ Nên dùng OpenAI khi:

Giá và ROI

Model Giá Input/MTok Giá Output/MTok So sánh tiết kiệm với HolySheep
Gemini 2.5 Flash $2.50 $2.50 Tiết kiệm 85%+
với tỷ giá ¥1=$1
GPT-4.1 $8.00 $24.00
Claude Sonnet 4.5 $15.00 $75.00 ❌ Đắt gấp 6x
DeepSeek V3.2 $0.42 $1.68 💡 Rẻ nhất nhưng tính năng hạn chế

Tính toán ROI thực tế:

Vì sao chọn HolySheep AI

Trong quá trình vận hành nhiều dự án AI, tôi đã thử qua hầu hết các relay services và API providers. Đăng ký tại đây để trải nghiệm những ưu điểm vượt trội:

Kết luận và khuyến nghị

Việc so sánh và migrate giữa OpenAI và Gemini Function Calling không khó nếu bạn nắm được những điểm khác biệt chính:

  1. Điểm giống nhau: Cấu trúc tools[], tool_calls[] response format
  2. Điểm khác biệt: Gemini dùng tool_config thay vì tool_choice
  3. Best practice: Viết wrapper class hỗ trợ cả hai format để linh hoạt switch models

Với mức giá Gemini 2.5 Flash chỉ $2.50/MTok, việc migrate từ GPT-4.1 sang Gemini có thể tiết kiệm đến 69% chi phí mà vẫn đảm bảo chất lượng function calling tốt.

Nếu bạn đang tìm kiếm giải pháp API AI với chi phí thấp, độ trễ thấp và hỗ trợ thanh toán địa phương, HolySheep AI là lựa chọn tối ưu.

👉 Đăng ký HolySheep AI — nhận tín dụng miễn phí khi đăng ký