Skip to Content

Function calling

Function calling allows the model to make requests to call some predefined functions provided by the app to interact with the environment.

Not all models support function calling. Please check the model card before using the model for function calling.

Register functions to conversations

To enable function calling, function definitions should be registered to the Conversation instance before content generation. Conversation.registerFunction takes a LeapFunction instance as the input, which describes the name, parameters and ability of the function.

val conversation = modelRunner.createConversation("You are a helpful assistant.") conversation.registerFunction( LeapFunction( name = "get_weather", description = "Get the weather forecast of a city", parameters = listOf( LeapFunctionParameter( name = "city", type = LeapFunctionParameterType.String(), description = "The city name", ), ), ), )

Generally speaking, function names and parameter names should be normal identifiers that are recongized by most common programming languages (e.g. Python, Javascript, etc). We recommend to use descriptive names that are composed by only letters, underscores and digits (not as the beginning).

Handle Function Calling Response

Function calling requests by the model will be presented as MessageResponse.FunctionCalls instance, which contains a list of function calls.

data class FunctionCalls(val functionCalls: List<LeapFunctionCall>): MessageResponse

Each LeapFunctionCall instance contains names and arguments of the function call request. The arguments field is a map from String to Any?. The app needs to check whether the required parameters are filled by the models. It is possible (even though very unlikely to happen) that some parameters are missing or the function name is invalid.

data class LeapFunctionCall( val name: String, val arguments: Map<String, Any?>, )

In order to handle the function call response, you will need to add a new branch to match responses from the generateResponse flow:

conversation.generateResponse(userMessage).onEach { response -> when (response) { is MessageResponse.Chunk -> { // process text chunk } is MessageResponse.FunctionCalls { response.functionCalls.forEach { call -> // Process function calls here Log.d(TAG, "Call function: ${call.name}, arguments: ${call.arguments}") } } else -> { // other responses } }

The function calls will also be included in the assistant message generated by the model. So it is possible to delay the function call process until the generation process is done.

conversation.generateResponse(userMessage).onEach { response -> when (response) { is MessageResponse.Complete -> { val assistantMessage = response.fullMessage val functionCalls = assistantMessage.functionCalls functionCalls?.forEach { call -> // process function calls here Log.d(TAG, "Call function: ${call.name}, arguments: ${call.arguments}") } } else -> { // process chunks } } }

Function Definition

Functions for models to call are defined by LeapFunction instances. It has three fields:

data class LeapFunction( val name: String, val description: String, val parameters: List<LeapFunctionParameter>, )

name is the function name. It is recommneded to use only English letters, underscores and digits (not to start with digits) to compose the function names because this format is supported by most models. description tells the model what this function is doing. parameters is the ordered list to declare what arguments (parameters) this function accepts.

The items of parameters are instances of LeapFunctionParameter.

data class LeapFunctionParameter( val name: String, val type: LeapFunctionParameterType, val description: String, val optional: Boolean = false, )
  • name The name of the parameter.
  • type Data type of the parameter.
  • description Tells the model what this parameter is about.
  • optional Whether the function is optional.

LeapFunctionParameterType describes the data types of the parameteres. They will be translated into JSON Schema for model to understand. Following types are supported:

LeapFunctionParameterType.String(enumValues: List<kotlin.String>? = null, description: kotlin.String? = null) LeapFunctionParameterType.Number(enumValues: List<kotlin.Number>? = null, description: kotlin.String? = null) LeapFunctionParameterType.Integer(enumValues: List<Int>? = null, description: kotlin.String? = null) LeapFunctionParameterType.Boolean(description: kotlin.String? = null) LeapFunctionParameterType.Array(itemType: LeapFunctionParameterType, description: kotlin.String? = null) LeapFunctionParameterType.Object( properties: Map<kotlin.String, LeapFunctionParameterType>, required: List<kotlin.String> = listOf(), description: kotlin.String? = null, )
  • String: String literals.
  • Number: Number literals including integers and floating point numbers.
  • Integer: Integer literals.
  • Boolean: Boolean literals.
  • Array: Arrays of a defined type. itemType parameter describes the data type of its items.
  • Object: Objects which has its own properties. properties is the map between the property names to the property data types. required list contains the name of all non-optional properties.

All fields accepts an optional parameter of description, but it will be overrided if it is directly used as LeapFunctionParameter.type. It only plays a role if the type instance is used as Array.itemType or the types in object properties.

For any type that accepts a parameter of enumValues, this parameter provides the instructions to the models on the legit values to fill.

Here is a more comprehensive example on defining a function:

LeapFunction( name = "get_weather", description = "Get the weather forecast of cities", parameters = listOf( LeapFunctionParameter( name = "cities", type = LeapFunctionParameterType.Array( itemType = LeapFunctionParameterType.String() ), description = "City names to query", ), LeapFunctionParameter( name = "temperature_unit", type = LeapFunctionParameterType.String( enumValues = listOf( "Fahrenheit", "Celsius", "Kelvin" ) ), description = "Units for temperature", ), ), )

Function Call Parser

Function call parsers are necessary to parse the function call request outputs from the model into LeapFunctionCall data structure. Different models generate function call requests in different styles, so we need to use the correct parser.

By default, LFMFunctionCallParser is used. It supports Liquid Foundation Model (LFM2).

For Qwen3 models and other models that are using Hermes function calling format , apply HermesFunctionCallParser by injecting a parser instance on the generation options:

val options = GenerationOptions.build { functionCallParser = HermesFunctionCallParser() } conversation.generateResponse(userMessage, options).onEach { // process message response here }
Last updated on