2.8 KiB
2.8 KiB
Tool Calling
Why Tools Are Needed
The 3B model will hallucinate external data:
// BAD - Model will make up weather
let response = try await session.respond(to: "Weather in Tokyo?")
Tools let the model call your code to fetch real data.
Tool Protocol
protocol Tool {
var name: String { get }
var description: String { get }
associatedtype Arguments: Generable
func call(arguments: Arguments) async throws -> ToolOutput
}
Weather Tool Example
struct GetWeatherTool: Tool {
let name = "getWeather"
let description = "Get current weather for a city"
@Generable
struct Arguments {
@Guide(description: "City name")
var city: String
}
func call(arguments: Arguments) async throws -> ToolOutput {
let places = try await CLGeocoder().geocodeAddressString(arguments.city)
let weather = try await WeatherService.shared.weather(for: places.first!.location!)
return ToolOutput("Temperature: \(weather.currentWeather.temperature.value)F")
}
}
Using Tools
let session = LanguageModelSession(
tools: [GetWeatherTool()],
instructions: "Help with weather forecasts."
)
let response = try await session.respond(to: "What's the temperature in Cupertino?")
// Model calls GetWeatherTool, uses real data in response
How It Works
- User prompt arrives
- Model decides it needs external data
- Model generates tool call with @Generable arguments
- Framework calls your
call()method - Tool output inserted into transcript
- Model generates final response using real data
Stateful Tools
Use class to track state across calls:
class FindContactTool: Tool {
var pickedContacts = Set<String>()
func call(arguments: Arguments) async throws -> ToolOutput {
contacts.removeAll(where: { pickedContacts.contains($0.name) })
guard let picked = contacts.randomElement() else {
return ToolOutput("No more contacts")
}
pickedContacts.insert(picked.name)
return ToolOutput(picked.name)
}
}
Multiple Tools
let session = LanguageModelSession(
tools: [GetWeatherTool(), FindRestaurantTool(), FindHotelTool()],
instructions: "Plan travel itineraries."
)
// Model autonomously decides which tools to call
ToolOutput Options
// Natural language
return ToolOutput("Temperature is 71F")
// Structured
return ToolOutput(GeneratedContent(properties: ["temperature": 71]))
Tool Naming
- Short, readable:
getWeather,findContact - Use verbs:
get,find,fetch - Concise descriptions (they're in the prompt)
When to Use Tools
Use for: Weather, MapKit, Contacts, Calendar, external APIs Don't use for: Data already in prompt, simple calculations