Function Calling Guide¶
Lexilux provides comprehensive support for OpenAI-compatible function calling (also known as tool use), allowing models to request execution of specific functions during chat completions.
Overview¶
Function calling enables models to:
Request execution of specific functions with structured arguments
Process function results and generate contextual responses
Support multiple tools in a single request (parallel function calling)
Combine function calls with regular text generation
Basic Function Calling¶
Defining Tools¶
Define tools using FunctionTool with JSON Schema parameters:
from lexilux import FunctionTool
get_weather_tool = FunctionTool(
name="get_weather",
description="Get current weather for a location",
parameters={
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name, e.g. Paris"
},
"units": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Temperature units"
}
},
"required": ["location"]
}
)
Making Requests with Tools¶
Pass tools to the chat client:
from lexilux import Chat
chat = Chat(
base_url="https://api.example.com/v1",
api_key="your-key",
model="gpt-4"
)
messages = [{"role": "user", "content": "What's the weather in Paris?"}]
result = chat(messages, tools=[get_weather_tool])
# Check if model requested tool calls
if result.has_tool_calls:
for tool_call in result.tool_calls:
print(f"Function: {tool_call.name}")
print(f"Arguments: {tool_call.get_arguments()}")
Executing Tool Calls¶
Use helper functions to execute tools and continue the conversation:
from lexilux import execute_tool_calls, create_conversation_history
# Define your actual function implementations
def get_weather(location: str, units: str = "celsius") -> str:
# Your implementation here
return f"Weather in {location}: 22°{units}"
# Execute tool calls
tool_responses = execute_tool_calls(
result,
{"get_weather": get_weather}
)
# Create conversation history
history = create_conversation_history(messages, result, tool_responses)
# Get final response
final_result = chat(history, tools=[get_weather_tool])
print(final_result.text)
Complete Workflow Example¶
Here’s a complete example showing the full workflow:
from lexilux import Chat, FunctionTool, execute_tool_calls, create_conversation_history
# 1. Define tools
tools = [
FunctionTool(
name="get_weather",
description="Get current weather for a location",
parameters={
"type": "object",
"properties": {
"location": {"type": "string"},
"units": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["location"]
}
),
FunctionTool(
name="get_time",
description="Get current time for a timezone",
parameters={
"type": "object",
"properties": {
"timezone": {"type": "string"}
},
"required": ["timezone"]
}
)
]
# 2. Define function implementations
def get_weather(location: str, units: str = "celsius") -> str:
return f"Weather in {location}: 22°{units}"
def get_time(timezone: str) -> str:
from datetime import datetime
# Implementation here
return f"Time in {timezone}: {datetime.now().isoformat()}"
functions = {
"get_weather": get_weather,
"get_time": get_time,
}
# 3. Make request
chat = Chat(base_url="...", api_key="...", model="gpt-4")
messages = [{"role": "user", "content": "What's the weather and time in Paris?"}]
result = chat(messages, tools=tools)
# 4. Execute and continue
if result.has_tool_calls:
tool_responses = execute_tool_calls(result, functions)
history = create_conversation_history(messages, result, tool_responses)
final_result = chat(history, tools=tools)
print(final_result.text)
Controlling Tool Usage¶
Tool Choice¶
Control when and how the model uses tools with the tool_choice parameter:
from lexilux import ToolChoice
# Auto mode (default) - model decides
result = chat(messages, tools=[tool], tool_choice="auto")
# Required mode - model must call at least one tool
result = chat(messages, tools=[tool], tool_choice="required")
# Specific function - model must call this function
result = chat(messages, tools=[tool], tool_choice=ToolChoice(
type="function",
name="get_weather"
))
Parallel Tool Calls¶
Enable parallel function calling (multiple tools in one request):
result = chat(
messages,
tools=[tool1, tool2, tool3],
parallel_tool_calls=True
)
if result.has_tool_calls:
# Model may have called multiple tools
for tool_call in result.tool_calls:
print(f"Called: {tool_call.name}")
Using ToolCallHelper¶
The ToolCallHelper class provides a high-level abstraction
for managing tool calling workflows:
from lexilux import ToolCallHelper
# Create helper with function implementations
helper = ToolCallHelper(functions={
"get_weather": get_weather,
"calculate": calculate,
})
# Make initial request
result = chat("What's 15 * 27?", tools=[calculate_tool])
# Automatically execute and continue
if result.has_tool_calls:
final_result = helper.continue_conversation(
chat=chat,
messages=[{"role": "user", "content": "What's 15 * 27?"}],
tool_result=result,
tools=[calculate_tool]
)
print(final_result.text)
Streaming with Function Calling¶
Function calling works seamlessly with streaming:
# Stream initial request
messages = [{"role": "user", "content": "What's the weather in Tokyo?"}]
chunks = []
tool_calls = []
for chunk in chat.stream(messages, tools=[weather_tool]):
chunks.append(chunk)
if chunk.has_tool_calls:
tool_calls.extend(chunk.tool_calls)
# Execute and stream final response
if tool_calls:
tool_responses = execute_tool_calls(
# Create ChatResult from chunks
result,
functions
)
history = create_conversation_history(messages, result, tool_responses)
# Stream final response
for chunk in chat.stream(history, tools=[weather_tool]):
print(chunk.delta, end="")
Error Handling¶
Handling Unknown Functions¶
The execute_tool_calls() function raises ValueError
for unknown functions:
try:
tool_responses = execute_tool_calls(result, functions)
except ValueError as e:
print(f"Unknown function requested: {e}")
Handling Execution Errors¶
If a function raises an exception during execution, the error message is returned to the model in the tool response:
def failing_tool(location: str) -> str:
raise ValueError("Intentional error")
# Error message will be: "Error executing failing_tool: Intentional error"
tool_responses = execute_tool_calls(result, {"failing_tool": failing_tool})
Best Practices¶
Define Clear Descriptions: Provide detailed descriptions for tools to help the model understand when to use them.
Use JSON Schema Validation: Define proper JSON Schema with types, required fields, and enums for better argument validation.
Handle Errors Gracefully: Always handle exceptions in your function implementations and return meaningful error messages.
Check Tool Calls: Always check
result.has_tool_callsbefore attempting to accessresult.tool_calls.Use Type Hints: Add type hints to your function implementations for better clarity and IDE support.
Test Functions: Test your function implementations independently before integrating with the chat API.
Advanced Topics¶
Strict Schema Mode¶
Enable strict schema validation for tool parameters:
tool = FunctionTool(
name="search",
description="Search database",
parameters={...},
strict=True # Enforce strict schema adherence
)
Tool Response Format¶
Tool responses are formatted as messages with role="tool" and include:
tool_call_id- ID of the tool call being responded tocontent- String result from the function execution
Multi-Turn Conversations¶
For complex workflows requiring multiple tool calls:
history = []
# Turn 1
result1 = chat(messages, tools=tools)
if result1.has_tool_calls:
responses1 = execute_tool_calls(result1, functions)
history = create_conversation_history(messages, result1, responses1)
result1 = chat(history, tools=tools)
# Turn 2 - follow-up question
messages.append({"role": "assistant", "content": result1.text})
messages.append({"role": "user", "content": "What about London?"})
result2 = chat(messages, tools=tools)
# Continue workflow...
API Reference¶
For complete API documentation, see:
FunctionTool- Tool definitionToolChoice- Tool choice configurationToolCall- Tool call in responseToolCallHelper- High-level workflow helperexecute_tool_calls()- Execute tool callscreate_conversation_history()- Build conversation history