Многоэтапное взаимодействие с шаблонами серверных подсказок


Данное руководство применимо ко всем возможностям, зависящим от многоходовых взаимодействий, включая:

Общий обзор

В многоходовых взаимодействиях состоянием диалога управляют SDK Firebase AI Logic . Это также применимо при использовании шаблонов подсказок сервера.

Основной алгоритм взаимодействия в многоэтапных запросах и шаблоны серверных подсказок принципиально тот же, что и для одноэтапных запросов, с некоторыми важными отличиями:

  1. Создайте шаблон, используя пошаговые инструкции в консоли Firebase .

    Для многоходовых взаимодействий необходимо добавить {% verbatim %}{% endverbatim %} В содержимом шаблона находится тег ` {% verbatim %}{% endverbatim %} , указывающий шаблону, куда следует внедрить диалоги, управляемые клиентским SDK.

  2. Протестируйте шаблон в реальном запросе, используя возможности тестирования в консоли Firebase .

    Для многоходовых взаимодействий тестирование в консоли поможет проверить только первый ход. Чтобы проверить обработку последующих ходов (историю), используйте шаблон в реальном приложении.

  3. Получите доступ к шаблону из кода вашего приложения, используя templateGenerativeModel .

    Для многоходовых взаимодействий необходимо использовать startChat и sendMessage (точно так же, как и для многоходовых взаимодействий, когда не используются шаблоны подсказок сервера).

Обратите внимание, что при вызове функций есть еще несколько отличий, которые описаны в соответствующем разделе далее на этой странице.



Многоэтапная переписка (чат)

If you haven't already, review the general guide for building multi-turn conversations (chat) when not using server prompt templates.

Базовый формат шаблона приглашения сервера

В случае с Firebase AI Logic консоль Firebase предоставляет пошаговый интерфейс для указания метаданных и содержимого шаблона.

В шаблонах командной строки сервера используется синтаксис и формат на основе Dotprompt. Более подробную информацию см. в разделе «Формат, синтаксис и примеры шаблонов» .

В приведенном ниже примере шаблона показаны наиболее важные компоненты шаблона при построении многоэтапной переписки (чата). Обратите внимание на добавление {% verbatim %}{% endverbatim %} В содержимом шаблона находится тег ` {% verbatim %}{% endverbatim %} , указывающий шаблону, куда следует внедрить диалоги, управляемые клиентским SDK.

---
model: 'gemini-3-flash-preview'
---

{{role "system"}}
You help customers with their invoices, including answering questions or providing their invoices to them.
If an invoice is requested, it must be a clearly structured invoice document that uses a tabular or clearly delineated list format for line items.

{{history}}

Используйте свой шаблон в коде

Чтобы просмотреть контент и код, относящиеся к вашему поставщику API Gemini , нажмите на него.

Приведенный ниже пример клиентского кода демонстрирует, как использовать шаблон в вашем коде. Обратите внимание на использование templateGenerativeModel вместе с startChat и sendMessage при создании многоходовых взаимодействий.

Быстрый

For Swift, using server prompt templates with multi-turn interactions is not yet supported. Check back soon!

Kotlin


// ...

// Initialize the Gemini Developer API backend service
// Create a `TemplateGenerativeModel` instance.
val model = Firebase.ai(backend = GenerativeBackend.googleAI())
                        .templateGenerativeModel()

// Start a chat session with a template.
val chatSession = model.startChat(
  // Specify your template ID
  templateId= "my-chat-template-v1-0-0",
  inputs = emptyMap()
)

// Send messages.
// The template's system instructions and model config apply to every turn automatically.
// The SDK automatically manages the state of the conversation.
val response = chatSession.sendMessage(
  content("user") { text("I need a copy of my invoice.") }
)

val text = response.text
println(text)

Java

For Java, using server prompt templates with multi-turn interactions is not yet supported. Check back soon!

Web


// ...

// Initialize the Gemini Developer API backend service.
const ai = getAI(app, { backend: new GoogleAIBackend() });

// Create a `TemplateGenerativeModel` instance.
const model = getTemplateGenerativeModel(ai);

// Start a chat session with a template.
const chatSession = model.startChat({
  // Specify your template ID.
  templateId: 'my-chat-template-v1-0-0',
});

// Send messages.
// The template's system instructions and model config apply to every turn automatically.
// The SDK automatically manages the state of the conversation.
const result = await chatSession.sendMessage("I need a copy of my invoice.");

const text = result.response.text();
console.log(text);

Dart


// ...

// Initialize the Gemini Developer API backend service.
// Create a `TemplateGenerativeModel` instance.
final model = FirebaseAI.googleAI().templateGenerativeModel();

// Start a chat session with a template.
final chatSession = model.startChat(
  // Specify your template ID.
  templateId: 'my-chat-template-v1-0-0',
);

// Send messages.
// The template's system instructions and model config apply to every turn automatically.
// The SDK automatically manages the state of the conversation.
final response = await chatSession.sendMessage(
  Content.text('I need a copy of my invoice.'),
);

final text = response.text;
print(text);

Единство


// ...

// Initialize the Gemini Developer API backend service.
var firebaseAI = FirebaseAI.GetInstance(FirebaseAI.Backend.GoogleAI());

// Create a `TemplateGenerativeModel` instance.
var model = firebaseAI.GetTemplateGenerativeModel();

// Start a chat session with a template.
var chatSession = model.StartChat(
    // Specify your template ID.
    "my-chat-template-v1-0-0"
);

// Send messages.
// The template's system instructions and model config apply to every turn automatically.
// The SDK automatically manages the state of the conversation.
try
{
   var response = await chatSession.SendMessageAsync(ModelContent.Text("I need a copy of my invoice."));
   Debug.Log($"Response Text: {response.Text}");
}
catch (Exception e) {
  Debug.LogError($"An error occurred: {e.Message}");
}



Вызов функции

Если вы еще этого не сделали, ознакомьтесь с общим руководством по вызову функций, когда не используются шаблоны командной строки сервера. Данное руководство по использованию шаблонов командной строки сервера предполагает, что вы понимаете, как в целом работает вызов функций.

Базовый формат шаблона приглашения сервера

В случае с Firebase AI Logic консоль Firebase предоставляет пошаговый интерфейс для указания метаданных и содержимого шаблона.

В шаблонах командной строки сервера используется синтаксис и формат на основе Dotprompt. Более подробную информацию см. в разделе «Формат, синтаксис и примеры шаблонов» .

Приведенный ниже пример шаблона демонстрирует наиболее важные компоненты шаблона при использовании вызова функций. Обратите внимание на следующее:

  • В метаданных шаблона перечислите функции, к которым имеет доступ модель, указав объявления функций в объекте tools .

    • Укажите name (обязательно) и description (необязательно) для каждой функции, к которой имеет доступ модель.

    • Определите схему для каждой функции, к которой имеет доступ модель.

      This example template below assumes that you're defining function schemas in the template. However, you can instead provide the function's schema in the client code. Schema defined in client code will override any schema defined in the template. Later on this page, find an example of a template and client code for defining schema in client code .

  • В содержимое шаблона добавьте {% verbatim %}{% endverbatim %} Тег {% verbatim %}{% endverbatim %} , указывающий шаблону, куда следует внедрить реплики диалога, управляемые клиентским SDK.

Пример шаблона с функциональной схемой, определенной в шаблоне.

---
model: gemini-3-flash-preview
tools:
  - name: fetchWeather
    description: Get the weather conditions for a specific city on a specific date.
    input:
      schema:
        location(object, The name of the city and its state for which to get the weather. Only cities in the USA are supported.):
          city: string, The city of the location.
          state: string, The state of the location.
        date: string, The date for which to get the weather. Date must be in the format YYYY-MM-DD.

---

What was the weather like in Boston, Massachusetts on 10/17 in year 2024?

{{history}}

Используйте свой шаблон в коде

Чтобы просмотреть контент и код, относящиеся к вашему поставщику API Gemini , нажмите на него.

Приведённый ниже пример клиентского кода демонстрирует, как использовать шаблон в вашем коде. Обратите внимание на следующее:

  • При использовании многоходовых взаимодействий используйте templateGenerativeModel вместе с startChat и sendMessage .

  • При инициализации модели в клиентском коде не следует перечислять функции, к которым модель имеет доступ. Вместо этого функции должны быть перечислены в объекте tools метаданных шаблона (см. выше).

  • Приведённый ниже пример клиентского кода предполагает, что вы определяете схемы функций в шаблоне. Если вы решите определить схему в своём клиентском коде, она переопределит схему, определённую в шаблоне. Далее на этой странице вы найдёте пример шаблона и клиентского кода для определения схемы в клиентском коде .

  • Проверьте, возвращает ли модель вызов функции в рамках выполнения запроса. Если да, то вашему приложению необходимо выполнить локальную логику, а затем отправить результат обратно в модель.

Пример клиентского кода со схемой функций, определенной в шаблоне.

Быстрый

For Swift, using server prompt templates with multi-turn interactions is not yet supported. Check back soon!

Kotlin


// ...

// Initialize the Gemini Developer API backend service.
// Create a `TemplateGenerativeModel` instance.
val model = Firebase.ai(backend = GenerativeBackend.googleAI())
    .templateGenerativeModel()

// Start a chat session with a template that has functions listed as tools.
val chatSession = model.startChat(
    // Specify your template ID
    templateId = "my-function-calling-template-v1-0-0",
    inputs = emptyMap()
)

// Send a message that might trigger a function call.
val response = chatSession.sendMessage(
    content("user") { text(userMessage) }
)

// When the model responds with one or more function calls, invoke the function(s).
// Note that this is the same as when *not* using server prompt templates.
val functionCalls = response.functionCalls
val fetchWeatherCall = functionCalls.find { it.name == "fetchWeather" }

// Forward the structured input data from the model to the hypothetical external API.
val functionResponse = fetchWeatherCall?.let {
  // Alternatively, if your `Location` class is marked as @Serializable, you can use
  // val location = Json.decodeFromJsonElement(it.args["location"]!!)
  val location = Location(
      it.args["location"]!!.jsonObject["city"]!!.jsonPrimitive.content,
      it.args["location"]!!.jsonObject["state"]!!.jsonPrimitive.content
  )
  val date = it.args["date"]!!.jsonPrimitive.content
  fetchWeather(location, date)
}

Java

For Java, using server prompt templates with multi-turn interactions is not yet supported. Check back soon!

Web


// ...

// Initialize the Gemini Developer API backend service.
const ai = getAI(app, { backend: new GoogleAIBackend() });

// Create a `TemplateGenerativeModel` instance.
const model = getTemplateGenerativeModel(ai);

// Start a chat session with a template that has functions listed as tools.
const chatSession = model.startChat({
  // Specify your template ID
  templateId: 'my-function-calling-template-v1-0-0',
});

// Send a message that might trigger a function call.
const result = await chatSession.sendMessage(userMessage);

// When the model responds with one or more function calls, invoke the function(s).
// Note that this is the same as when *not* using server prompt templates.
const functionCalls = result.response.functionCalls();
let functionCall;
let functionResult;

if (functionCalls.length > 0) {
  for (const call of functionCalls) {
    if (call.name === "fetchWeather") {
      // Forward the structured input data prepared by the model
      // to the hypothetical external API.
      functionResult = await fetchWeather(call.args);
      functionCall = call;
    }
  }
}

Dart


// ...

// Initialize the Gemini Developer API backend service.
// Create a `TemplateGenerativeModel` instance.
final model = FirebaseAI.googleAI().templateGenerativeModel()

// Start a chat session with a template that has functions listed as tools.
var chatSession = model.startChat(
    // Specify your template ID
    'my-function-calling-template-v1-0-0',
);

// Send a message that might trigger a function call.
var response = await chatSession.sendMessage(
    Content.text(userMessage),
);

// Check if the model wants to call a function.
// Note that this is the same as when *not* using server prompt templates.
final functionCalls = response?.functionCalls.toList();
// When the model responds with one or more function calls, invoke the function(s).
if (functionCalls != null && functionCalls.isNotEmpty) {
  for (final functionCall in functionCalls) {
    if (functionCall.name == 'fetchWeather') {
      Map<String, dynamic> location =
          functionCall.args['location']! as Map<String, dynamic>;
      var date = functionCall.args['date']! as String;
      var city = location['city'] as String;
      var state = location['state'] as String;
      final functionResult =
          await fetchWeather(Location(city, state), date);
      // Send the response to the model so that it can use the result to
      // generate text for the user.
      response = await chatSession.sendMessage(
        Content.functionResponse(functionCall.name, functionResult),
      );
    }
  }
}

Единство


// ...

// Initialize the Gemini Developer API backend service.
var firebaseAI = FirebaseAI.GetInstance(FirebaseAI.Backend.GoogleAI());

// Create a `TemplateGenerativeModel` instance.
var model = firebaseAI.GetTemplateGenerativeModel();

// Start a chat session with a template that has functions listed as tools.
var chatSession = model.StartChat(
    // Specify your template ID
    "my-function-calling-template-v1-0-0"
);

try
{
   // Send a message that might trigger a function call.
   var response = await chatSession.SendMessageAsync(ModelContent.Text(userMessage));
   var functionResponses = new List();

  // When the model responds with one or more function calls, invoke the function(s).
  // Note that this is the same as when *not* using server prompt templates.
  foreach (var functionCall in response.FunctionCalls) {
    if (functionCall.Name == "fetchWeather") {
      // TODO(developer): Handle invalid arguments.
      var location = functionCall.Args["location"] as Dictionary<string, object>;
      var city = location["city"] as string;
      var state = location["state"] as string;
      var date = functionCall.Args["date"] as string;

      functionResponses.Add(ModelContent.FunctionResponse(
        name: functionCall.Name,
        // Forward the structured input data prepared by the model
        // to the hypothetical external API.
        response: FetchWeather(city: city, state: state, date: date)
      ));
    }
    // TODO(developer): Handle other potential function calls, if any.
  }

  // Send the function responses back to the model.
  var functionResponseResult = await chatSession.SendMessageAsync(functionResponses);
}
catch (Exception e) {
  Debug.LogError($"An error occurred: {e.Message}");
}


Вызов функции — определение схемы в клиентском коде.

Обязательно ознакомьтесь с разделами выше, посвященными тому, как работает вызов функций с использованием шаблонов командной строки сервера (в частности, с использованием конструкции {% verbatim %}{% endverbatim %} (тег {% verbatim %}{% endverbatim %} в содержимом шаблона). В этом разделе приведен пример шаблона и клиентского кода, если вы хотите определить схему вашей функции в клиентском коде (а не в шаблоне).

Обратите внимание на следующие моменты, касающиеся определения схемы функции в клиентском коде:

  • Если вы определяете схему функции в клиентском коде (как показано в примере ниже), то схема на стороне клиента переопределит любую схему, определенную в шаблоне для этой функции.

  • Чтобы определить схему функции в клиентском коде, напишите объявление функции, а затем предоставьте его в startChat , а не во время инициализации модели (как это делается, если не используются шаблоны серверных подсказок).

  • Даже если в объявлении функции указано name , шаблон все равно должен содержать список функций, к которым модель должна иметь доступ. name в шаблоне должно совпадать с name в клиентском коде.

Пример шаблона с функциональной схемой, определенной в клиентском коде.

---
model: gemini-3-flash-preview
tools:
  - name: fetchWeather
    description: Get the weather conditions for a specific city on a specific date.
---

What was the weather like in Boston, Massachusetts on 10/17 in year 2024, formatted in CELSIUS?

{{history}}

Пример клиентского кода со схемой функций, определенной в клиентском коде.
(Подробности, опущенные в этом примере, см. в приведенном выше примере клиентского кода )

Быстрый

For Swift, using server prompt templates with multi-turn interactions is not yet supported. Check back soon!

Kotlin

// ...

// Initialize your desired Gemini API backend service.
// Create a `TemplateGenerativeModel` instance.
...

// Define the schema for any functions listed in your template.
val fetchWeatherTool = functionDeclarations(
    functionDeclarations = listOf(
        FunctionDeclaration(
            name = "fetchWeather",
            description = "Returns the weather for a given location at a given time",
            parameters = mapOf(
                "location" to Schema.obj(
                    description = "The name of the city and its state for which to get the weather. Only cities in the USA are supported.",
                    properties = mapOf(
                        "city" to Schema.string(
                            description = "The city of the location."
                        ),
                        "state" to Schema.string(
                            description = "The state of the location."
                        ),
                        "zipCode" to Schema.string(
                            description = "Optional zip code of the location.",
                            nullable = true
                        )
                    ),
                    optionalProperties = listOf("zipCode")
                ),
                "date" to Schema.string(
                    description = "The date for which to get the weather. Date must be in the format: YYYY-MM-DD."
                ),
                "unit" to Schema.enumeration(
                    description = "The temperature unit.",
                    values = listOf("CELSIUS", "FAHRENHEIT"),
                    nullable = true
                )

            ),
            optionalParameters = listOf("unit"),
        )
    )
)

// Start a chat session with a template that has functions listed as tools.
var chatSessionWithSchemaOverride = model.startChat(
    // Specify your template ID.
    templateId = "my-function-calling-template-with-no-function-schema-v1-0-0",
    // In `startChat`, provide the schema for any functions listed in your template.
    // This client-side schema will override any schema defined in the template.
    tools = listOf(fetchWeatherTool)
)

// Send a message that might trigger a function call.
...

// When the model responds with one or more function calls, invoke the function(s).
// Note that this is the same as when *not* using server prompt templates.
...

// Forward the structured input data from the model to the hypothetical external API.
...

Java

For Java, using server prompt templates with multi-turn interactions is not yet supported. Check back soon!

Web

// ...

// Initialize your desired Gemini API backend service.
...

// Create a `TemplateGenerativeModel` instance.
...

// Start a chat session with a template that has functions listed as tools.
const chatSessionWithSchemaOverride = model.startChat({
  // Specify your template ID.
  templateId: 'my-function-calling-template-with-no-function-schema-v1-0-0',
  // In `startChat`, provide the schema for any functions listed in your template.
  // This client-side schema will override any schema defined in the template.
  tools: [
    {
      functionDeclarations: [
        {
          name: "fetchWeather",
          parameters: {
            type: Type.OBJECT,
            properties: {
              location: {
                type: Type.OBJECT,
                description: "The name of the city and its state for which to get the weather. Only cities in the USA are supported.",
                properties: {
                  city: {
                    type: Type.STRING,
                    description: "The city of the location."
                  },
                  state: {
                    type: Type.STRING,
                    description: "The state of the location."
                  },
                  zipCode: {
                    type: Type.INTEGER,
                    description: "Optional zip code of the location.",
                    nullable: true
                  },
                },
                required: ["city", "state"],
              },
              date: {
                type: Type.STRING,
                description: "The date for which to get the weather. Date must be in the format: YYYY-MM-DD.",
              },
              unit: {
                type: Type.STRING,
                description: "The temperature unit.",
                enum: ["CELSIUS", "FAHRENHEIT"],
                nullable: true,
              },
            },
            required: ["location", "date"],
          },
        },
      ],
    }
  ],
});

// Send a message that might trigger a function call.
...

// When the model responds with one or more function calls, invoke the function(s).
// Note that this is the same as when *not* using server prompt templates.
...

Dart

// ...

// Initialize your desired Gemini API backend service.
// Create a `TemplateGenerativeModel` instance.
...

// Start a chat session with a template that has functions listed as tools.
final chatSessionWithSchemaOverride = model?.startChat(
      // Specify your template ID.
      'my-function-calling-template-with-no-function-schema-v1-0-0',
      inputs: {},
      // In `startChat`, provide the schema for any functions listed in your template.
      // This client-side schema will override any schema defined in the template.
      tools: [
        TemplateTool.functionDeclarations(
          [
            TemplateFunctionDeclaration(
              'fetchWeather',
              parameters: {
                'location': JSONSchema.object(
                  description:
                      'The name of the city and its state for which to get '
                      'the weather. Only cities in the USA are supported.',
                  properties: {
                    'city': JSONSchema.string(
                      description: 'The city of the location.',
                    ),
                    'state': JSONSchema.string(
                      description: 'The state of the location.',
                    ),
                    'zipCode': JSONSchema.integer(
                      description: 'Optional zip code of the location.',
                      nullable: true,
                    ),
                  },
                  optionalProperties: ['zipCode'],
                ),
                'date': JSONSchema.string(
                  description: 'The date for which to get the weather. '
                      'Date must be in the format: YYYY-MM-DD.',
                ),
                'unit': JSONSchema.enumString(
                  enumValues: ['CELSIUS', 'FAHRENHEIT'],
                  description: 'The temperature unit.',
                  nullable: true,
                ),
              },
              optionalParameters: ['unit'],
            ),
          ],
        ),
      ],
    );

// Send a message that might trigger a function call.
...

// Check if the model wants to call a function.
// Note that this is the same as when *not* using server prompt templates.
...

Единство

// ...

// Initialize your desired Gemini API backend service.
...

// Create a `TemplateGenerativeModel` instance.
...

// Define the schema for any functions listed in your template.
var fetchWeatherTool = new TemplateTool.FunctionDeclaration(
    name: "fetchWeather",
    parameters: new Dictionary<string, JsonSchema>() {
        { "location", JsonSchema.Object(
            description: "The name of the city and its state for which to get the weather. Only cities in the USA are supported.",
            properties: new Dictionary<string, JsonSchema>() {
                { "city", JsonSchema.String(description: "The city of the location.") },
                { "state", JsonSchema.String(description: "The state of the location.") },
                { "zipCode", JsonSchema.Int(description: "Optional zip code of the location.", nullable: true) }
            },
            optionalProperties: new[] { "zipCode" })
        },
        { "date", JsonSchema.String(description: "The date for which to get the weather. Date must be in the format: YYYY-MM-DD.")},
        { "unit", JsonSchema.Enum(
            values: new[] { "CELSIUS", "FAHRENHEIT" },
            description: "The temperature unit.",
            nullable: true)
        }
    },
    optionalParameters: new[] { "unit" }
);

// Start a chat session with a template that has functions listed as tools.
var chatSessionWithSchemaOverride = model.StartChat(
    // Specify your template ID.
    templateId: "my-function-calling-template-with-no-function-schema-v1-0-0",
    // In `startChat`, provide the schema for any functions listed in your template.
    // This client-side schema will override any schema defined in the template.
    tools: new[] { fetchWeatherTool }
);

try
{
   // Send a message that might trigger a function call.
   ...

  // When the model responds with one or more function calls, invoke the function(s).
  // Note that this is the same as when *not* using server prompt templates.
  ...
}

// ...



Что дальше?