Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ai-logic/firebase-ai-ondevice-interop/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Unreleased

- [feature] Added support for function calling in on-device content generation
requests and responses. (#8758)
- [changed] **Breaking Change**: Updated `GenerateContentRequest` to accept a
`List<Part>` instead of a single `TextPart` and optional `ImagePart`. (#8754)

Expand Down
71 changes: 71 additions & 0 deletions ai-logic/firebase-ai-ondevice-interop/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ package com.google.firebase.ai.ondevice.interop {

public final class Candidate {
ctor public Candidate(String text, com.google.firebase.ai.ondevice.interop.FinishReason finishReason);
ctor public Candidate(String text, com.google.firebase.ai.ondevice.interop.FinishReason finishReason, java.util.List<com.google.firebase.ai.ondevice.interop.FunctionCallPart> functionCalls = emptyList());
method public com.google.firebase.ai.ondevice.interop.FinishReason getFinishReason();
method public java.util.List<com.google.firebase.ai.ondevice.interop.FunctionCallPart> getFunctionCalls();
method public String getText();
property public final com.google.firebase.ai.ondevice.interop.FinishReason finishReason;
property public final java.util.List<com.google.firebase.ai.ondevice.interop.FunctionCallPart> functionCalls;
property public final String text;
}

Expand Down Expand Up @@ -78,15 +81,81 @@ package com.google.firebase.ai.ondevice.interop {
ctor public FirebaseAIOnDeviceUnknownException(String message, Throwable? cause = null);
}

public final class FunctionCallPart implements com.google.firebase.ai.ondevice.interop.Part {
ctor public FunctionCallPart(String name, java.util.Map<java.lang.String,? extends java.lang.Object?> args);
ctor public FunctionCallPart(String name, java.util.Map<java.lang.String,? extends java.lang.Object?> args, String? id = null);
method public java.util.Map<java.lang.String,java.lang.Object?> getArgs();
method public String? getId();
method public String getName();
property public final java.util.Map<java.lang.String,java.lang.Object?> args;
property public final String? id;
property public final String name;
}

public final class FunctionDeclaration {
ctor public FunctionDeclaration(String name, String description);
ctor public FunctionDeclaration(String name, String description, com.google.firebase.ai.ondevice.interop.FunctionSchema? parameters = null);
method public String getDescription();
method public String getName();
method public com.google.firebase.ai.ondevice.interop.FunctionSchema? getParameters();
property public final String description;
property public final String name;
property public final com.google.firebase.ai.ondevice.interop.FunctionSchema? parameters;
}

public final class FunctionResponsePart implements com.google.firebase.ai.ondevice.interop.Part {
ctor public FunctionResponsePart(String name, java.util.Map<java.lang.String,? extends java.lang.Object?> response);
ctor public FunctionResponsePart(String name, java.util.Map<java.lang.String,? extends java.lang.Object?> response, String? id = null);
method public String? getId();
method public String getName();
method public java.util.Map<java.lang.String,java.lang.Object?> getResponse();
property public final String? id;
property public final String name;
property public final java.util.Map<java.lang.String,java.lang.Object?> response;
}

public final class FunctionSchema {
ctor public FunctionSchema(String type);
ctor public FunctionSchema(String type, String? description = null);
ctor public FunctionSchema(String type, String? description = null, java.util.Map<java.lang.String,com.google.firebase.ai.ondevice.interop.FunctionSchema> properties = emptyMap());
ctor public FunctionSchema(String type, String? description = null, java.util.Map<java.lang.String,com.google.firebase.ai.ondevice.interop.FunctionSchema> properties = emptyMap(), java.util.List<java.lang.String> required = emptyList());
ctor public FunctionSchema(String type, String? description = null, java.util.Map<java.lang.String,com.google.firebase.ai.ondevice.interop.FunctionSchema> properties = emptyMap(), java.util.List<java.lang.String> required = emptyList(), java.util.List<java.lang.String>? enum = null);
ctor public FunctionSchema(String type, String? description = null, java.util.Map<java.lang.String,com.google.firebase.ai.ondevice.interop.FunctionSchema> properties = emptyMap(), java.util.List<java.lang.String> required = emptyList(), java.util.List<java.lang.String>? enum = null, Boolean? nullable = null);
ctor public FunctionSchema(String type, String? description = null, java.util.Map<java.lang.String,com.google.firebase.ai.ondevice.interop.FunctionSchema> properties = emptyMap(), java.util.List<java.lang.String> required = emptyList(), java.util.List<java.lang.String>? enum = null, Boolean? nullable = null, com.google.firebase.ai.ondevice.interop.FunctionSchema? items = null);
method public String? getDescription();
method public java.util.List<java.lang.String>? getEnum();
method public com.google.firebase.ai.ondevice.interop.FunctionSchema? getItems();
method public Boolean? getNullable();
method public java.util.Map<java.lang.String,com.google.firebase.ai.ondevice.interop.FunctionSchema> getProperties();
method public java.util.List<java.lang.String> getRequired();
method public String getType();
property public final String? description;
property public final java.util.List<java.lang.String>? enum;
property public final com.google.firebase.ai.ondevice.interop.FunctionSchema? items;
property public final Boolean? nullable;
property public final java.util.Map<java.lang.String,com.google.firebase.ai.ondevice.interop.FunctionSchema> properties;
property public final java.util.List<java.lang.String> required;
property public final String type;
}

public final class GenerateContentRequest {
ctor public GenerateContentRequest(java.util.List<? extends com.google.firebase.ai.ondevice.interop.Part> parts);
ctor public GenerateContentRequest(java.util.List<? extends com.google.firebase.ai.ondevice.interop.Part> parts, Float? temperature = null);
ctor public GenerateContentRequest(java.util.List<? extends com.google.firebase.ai.ondevice.interop.Part> parts, Float? temperature = null, Integer? topK = null);
ctor public GenerateContentRequest(java.util.List<? extends com.google.firebase.ai.ondevice.interop.Part> parts, Float? temperature = null, Integer? topK = null, Integer? seed = null);
ctor public GenerateContentRequest(java.util.List<? extends com.google.firebase.ai.ondevice.interop.Part> parts, Float? temperature = null, Integer? topK = null, Integer? seed = null, Integer? candidateCount = null);
ctor public GenerateContentRequest(java.util.List<? extends com.google.firebase.ai.ondevice.interop.Part> parts, Float? temperature = null, Integer? topK = null, Integer? seed = null, Integer? candidateCount = null, Integer? maxOutputTokens = null);
ctor public GenerateContentRequest(java.util.List<? extends com.google.firebase.ai.ondevice.interop.Part> parts, Float? temperature = null, Integer? topK = null, Integer? seed = null, Integer? candidateCount = null, Integer? maxOutputTokens = null, com.google.firebase.ai.ondevice.interop.TextPart? systemInstruction = null);
ctor public GenerateContentRequest(java.util.List<? extends com.google.firebase.ai.ondevice.interop.Part> parts, Float? temperature = null, Integer? topK = null, Integer? seed = null, Integer? candidateCount = null, Integer? maxOutputTokens = null, com.google.firebase.ai.ondevice.interop.TextPart? systemInstruction = null, Boolean? enableThinking = null);
ctor public GenerateContentRequest(java.util.List<? extends com.google.firebase.ai.ondevice.interop.Part> parts, Float? temperature = null, Integer? topK = null, Integer? seed = null, Integer? candidateCount = null, Integer? maxOutputTokens = null, com.google.firebase.ai.ondevice.interop.TextPart? systemInstruction = null, Boolean? enableThinking = null, java.util.List<com.google.firebase.ai.ondevice.interop.FunctionDeclaration> tools = emptyList());
method public Integer? getCandidateCount();
method public Boolean? getEnableThinking();
method public Integer? getMaxOutputTokens();
method public java.util.List<com.google.firebase.ai.ondevice.interop.Part> getParts();
method public Integer? getSeed();
method public com.google.firebase.ai.ondevice.interop.TextPart? getSystemInstruction();
method public Float? getTemperature();
method public java.util.List<com.google.firebase.ai.ondevice.interop.FunctionDeclaration> getTools();
method public Integer? getTopK();
property public final Integer? candidateCount;
property public final Boolean? enableThinking;
Expand All @@ -95,6 +164,7 @@ package com.google.firebase.ai.ondevice.interop {
property public final Integer? seed;
property public final com.google.firebase.ai.ondevice.interop.TextPart? systemInstruction;
property public final Float? temperature;
property public final java.util.List<com.google.firebase.ai.ondevice.interop.FunctionDeclaration> tools;
property public final Integer? topK;
}

Expand Down Expand Up @@ -133,6 +203,7 @@ package com.google.firebase.ai.ondevice.interop {
method public suspend Object? getBaseModelName(kotlin.coroutines.Continuation<? super java.lang.String>);
method public suspend Object? getTokenLimit(kotlin.coroutines.Continuation<? super java.lang.Integer>);
method public suspend Object? isAvailable(kotlin.coroutines.Continuation<? super java.lang.Boolean>);
method public suspend Object? isFunctionCallingAvailable(kotlin.coroutines.Continuation<? super java.lang.Boolean>);
method public suspend Object? isThinkingModeAvailable(kotlin.coroutines.Continuation<? super java.lang.Boolean>);
method public suspend Object? warmup(kotlin.coroutines.Continuation<? super kotlin.Unit>);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,10 @@ public class FinishReason private constructor(public val name: String) {
}

/** A `Candidate` represents a single response generated by the model for a given request. */
public class Candidate(public val text: String, public val finishReason: FinishReason) {}
public class Candidate
@JvmOverloads
constructor(
public val text: String,
public val finishReason: FinishReason,
public val functionCalls: List<FunctionCallPart> = emptyList()
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.firebase.ai.ondevice.interop

/**
* Defines a function that the model can use as a tool for on-device inference.
*
* @property name The name of the function.
* @property description The description of what the function does.
* @property parameters The schema describing the parameters the function accepts.
*/
public class FunctionDeclaration
@JvmOverloads
constructor(
public val name: String,
public val description: String,
public val parameters: FunctionSchema? = null
)

/**
* Schema defining the structure of function parameters for on-device function calling.
*
* @property type The data type of the schema (for example, OBJECT, STRING, INTEGER, BOOLEAN,
* ARRAY).
* @property description An optional description of what the value represents.
* @property properties The map of property names to schemas when type is OBJECT.
* @property required The list of required property names when type is OBJECT.
* @property enum The list of allowed string values when applicable.
* @property nullable Indicates whether the value can be null.
* @property items The schema for array elements when type is ARRAY.
*/
public class FunctionSchema
@JvmOverloads
constructor(
public val type: String,
public val description: String? = null,
public val properties: Map<String, FunctionSchema> = emptyMap(),
public val required: List<String> = emptyList(),
public val enum: List<String>? = null,
public val nullable: Boolean? = null,
public val items: FunctionSchema? = null
)
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@ package com.google.firebase.ai.ondevice.interop
* response.
* @property systemInstruction Instructions that direct the model to behave a certain way.
* @property enableThinking Whether to enable thinking mode for the model.
* @property tools The list of function declaration tools available to the model.
*/
public class GenerateContentRequest(
public class GenerateContentRequest
@JvmOverloads
constructor(
public val parts: List<Part>,
public val temperature: Float? = null,
public val topK: Int? = null,
Expand All @@ -41,4 +44,5 @@ public class GenerateContentRequest(
public val maxOutputTokens: Int? = null,
public val systemInstruction: TextPart? = null,
public val enableThinking: Boolean? = null,
public val tools: List<FunctionDeclaration> = emptyList(),
) {}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ public interface GenerativeModel {
*/
public suspend fun isThinkingModeAvailable(): Boolean

/**
* Checks whether function calling is available on the model.
*
* @return `true` if function calling is available, `false` otherwise.
*/
public suspend fun isFunctionCallingAvailable(): Boolean

/**
* Generates new content from the input [GenerateContentRequest] given to the model as a prompt.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,50 @@ public class TextPart(public val text: String) : Part

/** Represents image data. */
public class ImagePart(public val bitmap: Bitmap) : Part

/**
* Represents function call name and parameters emitted by the model or sent in conversation
* history.
*/
public class FunctionCallPart
@JvmOverloads
constructor(
public val name: String,
public val args: Map<String, Any?>,
public val id: String? = null
) : Part {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is FunctionCallPart) return false
return name == other.name && args == other.args && id == other.id
}

override fun hashCode(): Int {
var result = name.hashCode()
result = 31 * result + args.hashCode()
result = 31 * result + (id?.hashCode() ?: 0)
return result
}
}

/** Represents function call output to be returned to the model. */
public class FunctionResponsePart
@JvmOverloads
constructor(
public val name: String,
public val response: Map<String, Any?>,
public val id: String? = null
) : Part {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is FunctionResponsePart) return false
return name == other.name && response == other.response && id == other.id
}

override fun hashCode(): Int {
var result = name.hashCode()
result = 31 * result + response.hashCode()
result = 31 * result + (id?.hashCode() ?: 0)
return result
}
}
2 changes: 2 additions & 0 deletions ai-logic/firebase-ai-ondevice/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Unreleased

- [feature] Added support for function calling in on-device content generation
requests and responses. (#8758)
- [feature] Added support for multiple `TextPart` and `ImagePart` instances in
on-device content generation requests. (#8754)

Expand Down
Loading
Loading