🔧 AI Function Calling Made Simple
Right now, your AI can chat, generate images, transcribe audio, analyze files, synthesize speech, understand vision, and have voice conversations. But what if your AI could take real actions in the world?
Function calling opens up unlimited AI capabilities. Instead of just conversation, your AI can check weather, search databases, send emails, calculate complex math, interact with APIs, and perform any action you can code.
You’re about to learn exactly how to give your AI real-world superpowers through function calling.
🧠 Step 1: Understanding AI Function Calling
Section titled “🧠 Step 1: Understanding AI Function Calling”Before we write any code, let’s understand what function calling actually means and why it transforms your AI from a chat bot into an intelligent agent.
What AI Function Calling Actually Means
Section titled “What AI Function Calling Actually Means”AI function calling is like giving your AI hands to interact with the real world. Instead of just talking, your AI can actually perform actions - calling functions you define to get data, make calculations, or interact with external systems.
Real-world analogy: It’s like hiring an assistant who can not only answer questions, but also check your calendar, look up information, send messages, and complete tasks for you. Instead of just knowing about weather, they can actually check the weather API and give you current conditions.
Why Function Calling vs. Just Conversation
Section titled “Why Function Calling vs. Just Conversation”Your existing AI is smart but limited to conversation:
💬 Regular Chat - AI knows about weather but can’t check current conditions 🔧 Function Calling - AI can call weather API and get real-time data
💬 Regular Chat - AI can discuss math but might make calculation errors
🔧 Function Calling - AI can call calculator function for perfect accuracy
💬 Regular Chat - AI knows about databases but can’t query them 🔧 Function Calling - AI can execute database queries and return real data
Real-World Use Cases
Section titled “Real-World Use Cases”Think about all the actions your AI could perform with function calling:
- Weather checking - Get current conditions for any location
- Database queries - Look up customer information or product data
- Email sending - Compose and send emails based on conversation
- Calendar management - Check availability and schedule meetings
- Calculations - Perform complex math with perfect accuracy
- API integration - Connect to any external service or tool
Without function calling, your AI can only:
- Talk about things it knows from training (static knowledge)
- Make educated guesses (potentially inaccurate)
- Suggest what users should do manually (not helpful)
With function calling, your AI can:
- Get real-time data from any source
- Perform accurate calculations using specialized tools
- Take actions on behalf of users automatically
Function Calling Architecture
Section titled “Function Calling Architecture”Your function calling system will work in three steps:
🎯 Step 1: Define Functions - You create functions for specific tasks 🤖 Step 2: AI Decides - AI determines when and how to call functions ⚡ Step 3: Execute & Respond - Functions run and AI uses results
Example flow:
- User asks: “What’s the weather in Paris?”
- AI thinks: “I need current weather data, I’ll call the weather function”
- AI calls:
get_weather("Paris, France")
- Function returns:
{"temperature": 18, "condition": "partly cloudy"}
- AI responds: “It’s currently 18°C and partly cloudy in Paris”
🔧 Step 2: Adding Function Calling to Your Backend
Section titled “🔧 Step 2: Adding Function Calling to Your Backend”Let’s add function calling to your existing backend using the same patterns you learned in previous modules. We’ll add new routes to handle function-powered AI interactions.
Building on your foundation: You already have a working Node.js server with OpenAI integration. We’re simply adding function calling capabilities to what you’ve built.
Step 2A: Understanding Function Calling State
Section titled “Step 2A: Understanding Function Calling State”Before writing code, let’s understand what data our function calling system needs to manage:
// 🧠 FUNCTION CALLING STATE CONCEPTS:// 1. Available Functions - Tools the AI can use// 2. Function Definitions - Parameters and descriptions for each tool// 3. Function Execution - Running the actual function code// 4. Result Integration - Combining function results with AI responses// 5. Conversation Flow - Managing multi-step function calling workflows
Key function calling concepts:
- Tool Definitions: Describing available functions to the AI
- Parameter Validation: Ensuring function calls have correct inputs
- Execution Environment: Running functions safely and efficiently
- Result Formatting: Presenting function results clearly to users
Step 2B: Creating Function Implementations
Section titled “Step 2B: Creating Function Implementations”First, let’s create the actual functions our AI can call. Add this to your index.js
file:
// 🔧 FUNCTION IMPLEMENTATIONS: Real tools for AI to use
// Weather function (mock implementation - replace with real API)const get_weather = async (location) => { // In a real app, you'd call a weather API like OpenWeatherMap const mockWeatherData = { "paris, france": { temperature: 18, condition: "partly cloudy", humidity: 65 }, "new york, usa": { temperature: 22, condition: "sunny", humidity: 45 }, "tokyo, japan": { temperature: 15, condition: "rainy", humidity: 80 }, "london, uk": { temperature: 12, condition: "overcast", humidity: 70 } };
const locationKey = location.toLowerCase(); const weather = mockWeatherData[locationKey] || { temperature: 20, condition: "unknown", humidity: 50 };
return { location: location, temperature: weather.temperature, condition: weather.condition, humidity: weather.humidity, timestamp: new Date().toISOString() };};
// Calculator function for precise mathconst calculate = async (expression) => { try { // Simple math evaluation (in production, use a proper math parser) // This is a basic implementation - consider using libraries like math.js const result = Function(`"use strict"; return (${expression})`)();
if (typeof result !== 'number' || !isFinite(result)) { throw new Error('Invalid calculation result'); }
return { expression: expression, result: result, timestamp: new Date().toISOString() }; } catch (error) { return { expression: expression, error: "Invalid expression or calculation failed", timestamp: new Date().toISOString() }; }};
// Database query function (mock implementation)const query_database = async (query, table = "users") => { // Mock database data - replace with real database queries const mockData = { users: [ { id: 1, name: "Alice Johnson", email: "alice@example.com", role: "admin" }, { id: 2, name: "Bob Smith", email: "bob@example.com", role: "user" }, { id: 3, name: "Carol Davis", email: "carol@example.com", role: "moderator" } ], products: [ { id: 1, name: "Laptop", price: 999, category: "electronics" }, { id: 2, name: "Book", price: 25, category: "education" }, { id: 3, name: "Headphones", price: 150, category: "electronics" } ] };
const data = mockData[table] || [];
// Simple query simulation (in production, use proper SQL/NoSQL queries) let results = data;
if (query.includes("name")) { const searchTerm = query.match(/name.*['"](.*?)['"]/i)?.[1]; if (searchTerm) { results = data.filter(item => item.name.toLowerCase().includes(searchTerm.toLowerCase()) ); } }
return { query: query, table: table, results: results.slice(0, 5), // Limit results count: results.length, timestamp: new Date().toISOString() };};
// Function registry - maps function names to implementationsconst AVAILABLE_FUNCTIONS = { get_weather, calculate, query_database};
Step 2C: Adding the Function Calling Route
Section titled “Step 2C: Adding the Function Calling Route”Add this new endpoint to your existing index.js
file, right after your voice interaction routes:
// 🔧 FUNCTION CALLING ENDPOINT: Add this to your existing serverapp.post("/api/functions/chat", async (req, res) => { try { // 🛡️ VALIDATION: Check required inputs const { message, context = "[]" } = req.body;
if (!message?.trim()) { return res.status(400).json({ error: "Message is required", success: false }); }
console.log(`🔧 Function calling chat: ${message}`);
// 📝 CONVERSATION CONTEXT: Parse existing conversation history let conversationHistory = []; try { conversationHistory = JSON.parse(context); } catch (error) { console.log("Starting new conversation"); }
// 🛠️ FUNCTION DEFINITIONS: Define available tools for AI const tools = [ { type: "function", name: "get_weather", description: "Get current weather conditions for a given location.", parameters: { type: "object", properties: { location: { type: "string", description: "City and country, e.g. 'Paris, France' or 'New York, USA'" } }, required: ["location"], additionalProperties: false } }, { type: "function", name: "calculate", description: "Perform mathematical calculations with precision.", parameters: { type: "object", properties: { expression: { type: "string", description: "Mathematical expression to evaluate, e.g. '2 + 2' or '(10 * 5) / 2'" } }, required: ["expression"], additionalProperties: false } }, { type: "function", name: "query_database", description: "Query database for information about users or products.", parameters: { type: "object", properties: { query: { type: "string", description: "Search query to find information" }, table: { type: "string", enum: ["users", "products"], description: "Database table to search in" } }, required: ["query", "table"], additionalProperties: false } } ];
// 🤖 AI FUNCTION CALLING: Process with OpenAI Response API const response = await openai.responses.create({ model: "gpt-4.1", input: [ { role: "system", content: "You are a helpful AI assistant with access to real-time tools. Use the available functions when needed to provide accurate, up-to-date information. Always explain what you're doing when calling functions." }, ...conversationHistory, { role: "user", content: message.trim() } ], tools: tools });
// 🔄 FUNCTION EXECUTION: Handle any function calls let finalResponse = response.output_text; let functionCalls = [];
// Check if AI wants to call functions if (response.tool_calls && response.tool_calls.length > 0) { console.log(`🔧 AI requested ${response.tool_calls.length} function calls`);
for (const toolCall of response.tool_calls) { try { const functionName = toolCall.function.name; const functionArgs = JSON.parse(toolCall.function.arguments);
console.log(`🔧 Calling function: ${functionName} with args:`, functionArgs);
// Execute the function if (AVAILABLE_FUNCTIONS[functionName]) { const result = await AVAILABLE_FUNCTIONS[functionName](...Object.values(functionArgs));
functionCalls.push({ name: functionName, arguments: functionArgs, result: result, success: true });
// Create a follow-up request with function results const followUpResponse = await openai.responses.create({ model: "gpt-4.1", input: [ { role: "system", content: "You are a helpful AI assistant. A function was called and returned results. Use these results to provide a helpful response to the user." }, ...conversationHistory, { role: "user", content: message.trim() }, { role: "assistant", content: `I'll help you with that. Let me ${functionName === 'get_weather' ? 'check the weather' : functionName === 'calculate' ? 'calculate that' : 'look that up'}.` }, { role: "function", name: functionName, content: JSON.stringify(result) } ] });
finalResponse = followUpResponse.output_text;
} else { functionCalls.push({ name: functionName, arguments: functionArgs, error: "Function not available", success: false }); }
} catch (error) { console.error(`Function call error:`, error); functionCalls.push({ name: toolCall.function.name, error: error.message, success: false }); } } }
// 🔄 CONVERSATION UPDATE: Update conversation history const updatedHistory = [ ...conversationHistory, { role: "user", content: message.trim() }, { role: "assistant", content: finalResponse } ];
// 📤 SUCCESS RESPONSE: Send function calling results res.json({ success: true, message: finalResponse, function_calls: functionCalls, conversation_history: updatedHistory, available_functions: tools.map(tool => ({ name: tool.name, description: tool.description })), model: "gpt-4.1", timestamp: new Date().toISOString() });
} catch (error) { // 🚨 ERROR HANDLING: Handle function calling failures console.error("Function calling error:", error);
res.status(500).json({ error: "Failed to process function calling request", details: error.message, success: false }); }});
// 📋 FUNCTIONS LIST ENDPOINT: Get available functionsapp.get("/api/functions/list", (req, res) => { try { const functionList = [ { name: "get_weather", description: "Get current weather conditions for any location", parameters: ["location"], example: "get_weather('Paris, France')" }, { name: "calculate", description: "Perform precise mathematical calculations", parameters: ["expression"], example: "calculate('(25 * 4) + 10')" }, { name: "query_database", description: "Search database for users or products", parameters: ["query", "table"], example: "query_database('name Alice', 'users')" } ];
res.json({ success: true, functions: functionList, count: functionList.length, timestamp: new Date().toISOString() });
} catch (error) { console.error("Function list error:", error); res.status(500).json({ error: "Failed to get function list", details: error.message, success: false }); }});
Function breakdown:
- Function definitions - Tell AI what tools are available
- Message processing - Handle user requests with function calling capability
- Function execution - Run the requested functions with provided parameters
- Result integration - Combine function results with AI responses
- Conversation management - Maintain context across function calls
Your backend now supports:
- Text chat (existing functionality)
- Streaming chat (existing functionality)
- Image generation (existing functionality)
- Audio transcription (existing functionality)
- File analysis (existing functionality)
- Text-to-speech (existing functionality)
- Vision analysis (existing functionality)
- Voice interaction (existing functionality)
- Function calling (new functionality)
🔧 Step 3: Building the React Function Calling Component
Section titled “🔧 Step 3: Building the React Function Calling Component”Now let’s create a React component for function calling using the same patterns from your existing components.
Step 3A: Creating the Function Calling Component
Section titled “Step 3A: Creating the Function Calling Component”Create a new file src/FunctionCalling.jsx
:
import { useState, useRef, useEffect } from "react";import { Send, Zap, Database, Calculator, Cloud, MessageSquare, Download, Trash2 } from "lucide-react";
function FunctionCalling() { // 🧠 STATE: Function calling data management const [message, setMessage] = useState(""); // User input const [conversation, setConversation] = useState([]); // Chat history const [isProcessing, setIsProcessing] = useState(false); // Processing status const [availableFunctions, setAvailableFunctions] = useState([]); // Available tools const [error, setError] = useState(null); // Error messages const [functionCalls, setFunctionCalls] = useState([]); // Function execution history
const chatEndRef = useRef(null);
// 🔧 FUNCTIONS: Function calling logic engine
// Load available functions on component mount useEffect(() => { loadAvailableFunctions(); }, []);
// Auto-scroll to bottom of chat useEffect(() => { chatEndRef.current?.scrollIntoView({ behavior: "smooth" }); }, [conversation]);
// Load list of available functions const loadAvailableFunctions = async () => { try { const response = await fetch("http://localhost:8000/api/functions/list"); const data = await response.json();
if (data.success) { setAvailableFunctions(data.functions); } } catch (error) { console.error('Failed to load functions:', error); } };
// Send message with function calling capability const sendMessage = async () => { if (!message.trim() || isProcessing) return;
const userMessage = message.trim(); setMessage(""); setIsProcessing(true); setError(null);
// Add user message to conversation immediately const newConversation = [ ...conversation, { role: "user", content: userMessage, timestamp: new Date().toISOString() } ]; setConversation(newConversation);
try { // 📤 API CALL: Send to function calling endpoint const response = await fetch("http://localhost:8000/api/functions/chat", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ message: userMessage, context: JSON.stringify(conversation) }), });
const data = await response.json();
if (!response.ok) { throw new Error(data.error || 'Failed to process message'); }
// ✅ SUCCESS: Update conversation and function calls setConversation(data.conversation_history.map(msg => ({ ...msg, timestamp: new Date().toISOString() })));
// Track function calls if any were made if (data.function_calls && data.function_calls.length > 0) { setFunctionCalls(prev => [...prev, ...data.function_calls.map(call => ({ ...call, timestamp: new Date().toISOString(), message: userMessage }))]); }
} catch (error) { console.error('Function calling failed:', error); setError(error.message || 'Something went wrong while processing your message');
// Add error message to conversation setConversation(prev => [...prev, { role: "assistant", content: "I'm sorry, I encountered an error while processing your request. Please try again.", timestamp: new Date().toISOString(), error: true }]); } finally { setIsProcessing(false); } };
// Handle Enter key press const handleKeyPress = (e) => { if (e.key === "Enter" && !e.shiftKey && !isProcessing) { e.preventDefault(); sendMessage(); } };
// Clear conversation const clearConversation = () => { setConversation([]); setFunctionCalls([]); setError(null); };
// Download conversation with function calls const downloadConversation = () => { const exportData = { conversation: conversation, function_calls: functionCalls, available_functions: availableFunctions, timestamp: new Date().toISOString() };
const element = document.createElement('a'); const file = new Blob([JSON.stringify(exportData, null, 2)], { type: 'application/json' }); element.href = URL.createObjectURL(file); element.download = `function-calling-session-${Date.now()}.json`; document.body.appendChild(element); element.click(); document.body.removeChild(element); };
// Get function icon const getFunctionIcon = (functionName) => { switch (functionName) { case 'get_weather': return <Cloud className="w-4 h-4" />; case 'calculate': return <Calculator className="w-4 h-4" />; case 'query_database': return <Database className="w-4 h-4" />; default: return <Zap className="w-4 h-4" />; } };
// Format function result for display const formatFunctionResult = (result) => { if (typeof result === 'object') { return JSON.stringify(result, null, 2); } return String(result); };
// 🎨 UI: Interface components return ( <div className="min-h-screen bg-gradient-to-br from-cyan-50 to-blue-50 flex items-center justify-center p-4"> <div className="bg-white rounded-2xl shadow-2xl w-full max-w-6xl flex flex-col overflow-hidden">
{/* Header */} <div className="bg-gradient-to-r from-cyan-600 to-blue-600 text-white p-6"> <div className="flex items-center justify-between"> <div className="flex items-center space-x-3"> <div className="w-10 h-10 bg-white bg-opacity-20 rounded-full flex items-center justify-center"> <Zap className="w-5 h-5" /> </div> <div> <h1 className="text-xl font-bold">🔧 AI Function Calling</h1> <p className="text-cyan-100 text-sm">AI with real-world superpowers!</p> </div> </div>
<div className="text-right"> <p className="text-cyan-100 text-sm">{availableFunctions.length} functions available</p> <p className="text-cyan-200 text-xs">{functionCalls.length} calls made</p> </div> </div> </div>
{/* Available Functions Display */} <div className="p-4 bg-gray-50 border-b border-gray-200"> <h3 className="font-semibold text-gray-900 mb-3 flex items-center text-sm"> <Zap className="w-4 h-4 mr-2 text-cyan-600" /> Available Functions </h3>
<div className="grid grid-cols-1 md:grid-cols-3 gap-3"> {availableFunctions.map((func) => ( <div key={func.name} className="bg-white rounded-lg p-3 border border-gray-200"> <div className="flex items-center mb-1"> {getFunctionIcon(func.name)} <h4 className="font-medium text-gray-900 ml-2 text-sm">{func.name}</h4> </div> <p className="text-gray-600 text-xs">{func.description}</p> <code className="text-xs text-cyan-600 bg-cyan-50 px-2 py-1 rounded mt-1 block"> {func.example} </code> </div> ))} </div> </div>
{/* Chat Area */} <div className="flex-1 flex flex-col min-h-0"> <div className="flex-1 overflow-y-auto p-6 space-y-4"> {conversation.length === 0 ? ( <div className="text-center py-12"> <div className="w-16 h-16 bg-cyan-100 rounded-2xl flex items-center justify-center mx-auto mb-4"> <Zap className="w-8 h-8 text-cyan-600" /> </div> <h3 className="text-lg font-semibold text-gray-700 mb-2"> Ready for Function Calling! </h3> <p className="text-gray-600 max-w-md mx-auto mb-4"> Try asking me to check the weather, perform calculations, or query the database. </p> <div className="text-sm text-gray-500 space-y-1"> <p>💡 "What's the weather in Tokyo?"</p> <p>💡 "Calculate 15% of 250"</p> <p>💡 "Find user Alice in the database"</p> </div> </div> ) : ( <> {conversation.map((msg, index) => ( <div key={index} className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`} > <div className={`max-w-3xl px-4 py-3 rounded-lg ${ msg.role === 'user' ? 'bg-cyan-500 text-white' : msg.error ? 'bg-red-50 text-red-700 border border-red-200' : 'bg-gray-100 text-gray-900' }`} > <p className="whitespace-pre-wrap">{msg.content}</p> <p className="text-xs opacity-70 mt-1"> {new Date(msg.timestamp).toLocaleTimeString()} </p> </div> </div> ))}
{isProcessing && ( <div className="flex justify-start"> <div className="bg-gray-100 text-gray-900 px-4 py-3 rounded-lg"> <div className="flex items-center space-x-2"> <div className="w-2 h-2 bg-cyan-600 rounded-full animate-bounce"></div> <div className="w-2 h-2 bg-cyan-600 rounded-full animate-bounce" style={{animationDelay: '0.1s'}}></div> <div className="w-2 h-2 bg-cyan-600 rounded-full animate-bounce" style={{animationDelay: '0.2s'}}></div> <span className="text-sm">Processing and calling functions...</span> </div> </div> </div> )} <div ref={chatEndRef} /> </> )} </div>
{/* Function Calls Log */} {functionCalls.length > 0 && ( <div className="border-t border-gray-200 p-4 bg-gray-50"> <h4 className="font-semibold text-gray-900 mb-2 text-sm flex items-center"> <Database className="w-4 h-4 mr-2 text-cyan-600" /> Recent Function Calls ({functionCalls.length}) </h4> <div className="space-y-2 max-h-32 overflow-y-auto"> {functionCalls.slice(-3).map((call, index) => ( <div key={index} className="bg-white rounded p-2 border border-gray-200 text-xs"> <div className="flex items-center justify-between mb-1"> <div className="flex items-center"> {getFunctionIcon(call.name)} <span className="font-medium ml-1">{call.name}</span> <span className={`ml-2 px-2 py-0.5 rounded text-xs ${ call.success ? 'bg-green-100 text-green-700' : 'bg-red-100 text-red-700' }`}> {call.success ? 'Success' : 'Failed'} </span> </div> <span className="text-gray-500"> {new Date(call.timestamp).toLocaleTimeString()} </span> </div> {call.result && ( <pre className="text-xs text-gray-600 bg-gray-50 p-1 rounded overflow-hidden"> {formatFunctionResult(call.result).substring(0, 100)}... </pre> )} </div> ))} </div> </div> )}
{/* Error Display */} {error && ( <div className="border-t border-red-200 bg-red-50 p-4"> <p className="text-red-700 text-sm"> <strong>Error:</strong> {error} </p> </div> )}
{/* Input Area */} <div className="border-t border-gray-200 p-4"> <div className="flex items-center space-x-3"> <div className="flex-1"> <textarea value={message} onChange={(e) => setMessage(e.target.value)} onKeyPress={handleKeyPress} rows="2" placeholder="Ask me anything! I can check weather, calculate math, or query databases..." disabled={isProcessing} className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-cyan-500 focus:border-transparent transition-all duration-200 resize-none disabled:bg-gray-100" /> </div> <div className="space-y-2"> <button onClick={sendMessage} disabled={isProcessing || !message.trim()} className="px-6 py-3 bg-gradient-to-r from-cyan-600 to-blue-600 hover:from-cyan-700 hover:to-blue-700 disabled:from-gray-300 disabled:to-gray-300 text-white rounded-lg transition-all duration-200 flex items-center space-x-2 shadow-lg disabled:shadow-none" > <Send className="w-4 h-4" /> <span>Send</span> </button>
{conversation.length > 0 && ( <div className="flex space-x-1"> <button onClick={downloadConversation} className="p-2 bg-gray-100 text-gray-600 rounded-lg hover:bg-gray-200 transition-colors duration-200" title="Download conversation" > <Download className="w-4 h-4" /> </button> <button onClick={clearConversation} className="p-2 bg-red-100 text-red-600 rounded-lg hover:bg-red-200 transition-colors duration-200" title="Clear conversation" > <Trash2 className="w-4 h-4" /> </button> </div> )} </div> </div> </div> </div> </div> </div> );}
export default FunctionCalling;
Step 3B: Adding Function Calling to Navigation
Section titled “Step 3B: Adding Function Calling to Navigation”Update your src/App.jsx
to include the new function calling component:
import { useState } from "react";import StreamingChat from "./StreamingChat";import ImageGenerator from "./ImageGenerator";import AudioTranscription from "./AudioTranscription";import FileAnalysis from "./FileAnalysis";import TextToSpeech from "./TextToSpeech";import VisionAnalysis from "./VisionAnalysis";import VoiceInteraction from "./VoiceInteraction";import FunctionCalling from "./FunctionCalling";import { MessageSquare, Image, Mic, Folder, Volume2, Eye, Phone, Zap } from "lucide-react";
function App() { // 🧠 STATE: Navigation management const [currentView, setCurrentView] = useState("chat"); // Add 'functions' option
// 🎨 UI: Main app with navigation return ( <div className="min-h-screen bg-gray-100"> {/* Navigation Header */} <nav className="bg-white shadow-sm border-b border-gray-200"> <div className="max-w-7xl mx-auto px-4"> <div className="flex items-center justify-between h-16"> {/* Logo */} <div className="flex items-center space-x-3"> <div className="w-8 h-8 bg-gradient-to-r from-blue-500 to-purple-600 rounded-lg flex items-center justify-center"> <span className="text-white font-bold text-sm">AI</span> </div> <h1 className="text-xl font-bold text-gray-900">OpenAI Mastery</h1> </div>
{/* Navigation Buttons */} <div className="flex space-x-1 overflow-x-auto"> <button onClick={() => setCurrentView("chat")} className={`px-3 py-2 rounded-lg flex items-center space-x-2 transition-all duration-200 whitespace-nowrap ${ currentView === "chat" ? "bg-blue-100 text-blue-700 shadow-sm" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100" }`} > <MessageSquare className="w-4 h-4" /> <span>Chat</span> </button>
<button onClick={() => setCurrentView("images")} className={`px-3 py-2 rounded-lg flex items-center space-x-2 transition-all duration-200 whitespace-nowrap ${ currentView === "images" ? "bg-purple-100 text-purple-700 shadow-sm" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100" }`} > <Image className="w-4 h-4" /> <span>Images</span> </button>
<button onClick={() => setCurrentView("audio")} className={`px-3 py-2 rounded-lg flex items-center space-x-2 transition-all duration-200 whitespace-nowrap ${ currentView === "audio" ? "bg-blue-100 text-blue-700 shadow-sm" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100" }`} > <Mic className="w-4 h-4" /> <span>Audio</span> </button>
<button onClick={() => setCurrentView("files")} className={`px-3 py-2 rounded-lg flex items-center space-x-2 transition-all duration-200 whitespace-nowrap ${ currentView === "files" ? "bg-green-100 text-green-700 shadow-sm" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100" }`} > <Folder className="w-4 h-4" /> <span>Files</span> </button>
<button onClick={() => setCurrentView("speech")} className={`px-3 py-2 rounded-lg flex items-center space-x-2 transition-all duration-200 whitespace-nowrap ${ currentView === "speech" ? "bg-orange-100 text-orange-700 shadow-sm" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100" }`} > <Volume2 className="w-4 h-4" /> <span>Speech</span> </button>
<button onClick={() => setCurrentView("vision")} className={`px-3 py-2 rounded-lg flex items-center space-x-2 transition-all duration-200 whitespace-nowrap ${ currentView === "vision" ? "bg-indigo-100 text-indigo-700 shadow-sm" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100" }`} > <Eye className="w-4 h-4" /> <span>Vision</span> </button>
<button onClick={() => setCurrentView("voice")} className={`px-3 py-2 rounded-lg flex items-center space-x-2 transition-all duration-200 whitespace-nowrap ${ currentView === "voice" ? "bg-blue-100 text-blue-700 shadow-sm" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100" }`} > <Phone className="w-4 h-4" /> <span>Voice</span> </button>
<button onClick={() => setCurrentView("functions")} className={`px-3 py-2 rounded-lg flex items-center space-x-2 transition-all duration-200 whitespace-nowrap ${ currentView === "functions" ? "bg-cyan-100 text-cyan-700 shadow-sm" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100" }`} > <Zap className="w-4 h-4" /> <span>Functions</span> </button> </div> </div> </div> </nav>
{/* Main Content */} <main className="h-[calc(100vh-4rem)]"> {currentView === "chat" && <StreamingChat />} {currentView === "images" && <ImageGenerator />} {currentView === "audio" && <AudioTranscription />} {currentView === "files" && <FileAnalysis />} {currentView === "speech" && <TextToSpeech />} {currentView === "vision" && <VisionAnalysis />} {currentView === "voice" && <VoiceInteraction />} {currentView === "functions" && <FunctionCalling />} </main> </div> );}
export default App;
🧪 Testing Your Function Calling
Section titled “🧪 Testing Your Function Calling”Let’s test your function calling feature step by step to make sure everything works correctly.
Step 1: Backend Route Test
Section titled “Step 1: Backend Route Test”First, verify your backend routes work:
Test function calling endpoint:
curl -X POST http://localhost:8000/api/functions/chat \ -H "Content-Type: application/json" \ -d '{"message": "What is the weather in Paris?"}'
Test functions list endpoint:
curl http://localhost:8000/api/functions/list
Step 2: Full Application Test
Section titled “Step 2: Full Application Test”Start both servers:
Backend (in your backend folder):
npm run dev
Frontend (in your frontend folder):
npm run dev
Test the complete flow:
- Navigate to Functions → Click the “Functions” tab in navigation
- Review available functions → See weather, calculator, and database tools
- Test weather function → Ask “What’s the weather in Tokyo?”
- Test calculator function → Ask “Calculate 15% of 250”
- Test database function → Ask “Find user Alice in the database”
- Try complex requests → Ask “What’s the weather in Paris and calculate the tip for a $50 meal?”
- Review function calls → See detailed logs of function executions
- Download conversation → Export chat with function call history
Step 3: Error Handling Test
Section titled “Step 3: Error Handling Test”Test error scenarios:
❌ Invalid function: Ask AI to call non-existent function❌ Bad parameters: Provide invalid calculation expression❌ Network error: Disconnect internet during function call❌ Empty message: Try to send empty message
Expected behavior:
- Clear error messages displayed
- Graceful fallback when functions fail
- Conversation continues after errors
- Function call history preserved
✅ What You Built
Section titled “✅ What You Built”Congratulations! You’ve extended your existing application with complete AI function calling:
- ✅ Extended your backend with function definitions and execution
- ✅ Added React function calling component following the same patterns as your other features
- ✅ Implemented real-world AI tools for weather, calculations, and database queries
- ✅ Created function call tracking with detailed execution logs
- ✅ Added conversation management with function calling context
- ✅ Maintained consistent design with your existing application
Your application now has:
- Text chat with streaming responses
- Image generation with DALL-E 3 and GPT-Image-1
- Audio transcription with Whisper voice recognition
- File analysis with intelligent document processing
- Text-to-speech with natural voice synthesis
- Vision analysis with GPT-4o visual intelligence
- Voice interaction with GPT-4o Audio natural conversations
- Function calling with real-world tool integration
- Unified navigation between all features
- Professional UI with consistent TailwindCSS styling
Next up: You’ll learn about Web Search, where your AI can search the internet in real-time to get current information and answer questions about recent events.
Your OpenAI mastery application now has real-world superpowers! 🔧