與伺服器提示詞範本進行多輪互動


本指南適用於任何需要多輪互動的功能,包括:

高階總覽

如果是多輪互動,Firebase AI Logic SDK 會管理對話狀態。使用伺服器提示詞範本時,也適用這項規定。

多輪互動和伺服器提示範本的基本工作流程,與單輪要求的基本工作流程大致相同,但有幾個重要差異:

  1. 使用 Firebase 控制台的引導式 UI 建立範本。

    如要進行多輪互動,您必須在範本內容中加入 {{history}} 標記,告知範本要在何處插入由用戶端 SDK 管理的對話輪次。

  2. 使用 Firebase 控制台的測試功能,在實際要求中測試範本。

    如果是多輪互動,控制台測試體驗只能協助測試初始輪。您可以搭配實際應用程式使用範本,測試後續輪次 (記錄) 的處理方式。

  3. 使用 templateGenerativeModel 從應用程式的程式碼存取範本。

    如要進行多輪互動,您必須使用 startChatsendMessage (就像未使用伺服器提示範本時的多輪互動一樣)。

請注意,函式呼叫還有一些差異,詳情請參閱本頁稍後的相關章節。



多輪對話 (聊天)

如果尚未閱讀,請先參閱建構多輪對話 (即時通訊) 的一般指南,瞭解使用伺服器提示範本時的注意事項。

伺服器提示範本的基本格式

Firebase AI Logic 中,Firebase 控制台提供導覽式 UI,可供您指定範本的 frontmatter 和內容。

伺服器提示詞範本使用以 Dotprompt 為基礎的語法和格式。詳情請參閱範本格式、語法和範例

以下範本範例顯示建構多輪對話 (即時通訊) 時,範本最重要的元件。請注意,範本內容中新增了 {{history}} 標記,這個標記會告知範本要在何處插入由用戶端 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}}

在程式碼中使用範本

按一下 Gemini API 供應商,即可在這個頁面查看供應商專屬內容和程式碼。

以下用戶端程式碼範例說明如何在程式碼中使用範本。請注意,建構多輪互動時,請一併使用 templateGenerativeModelstartChatsendMessage

Swift

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);

Unity


// ...

// 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 控制台提供導覽式 UI,可供您指定範本的 frontmatter 和內容。

伺服器提示詞範本使用以 Dotprompt 為基礎的語法和格式。詳情請參閱範本格式、語法和範例

以下範本範例顯示使用函式呼叫時,範本最重要的元件。注意事項:

  • 在範本的前言中,於 tools 物件中提供函式宣告,列出模型可存取的函式。

    • 為模型可存取的每個函式定義 name(必要)description(選用)

    • 為模型可存取的每個函式定義結構定義。

      以下範本範例假設您要在範本中定義函式結構定義。不過,您可以在用戶端程式碼中提供函式的結構定義。用戶端程式碼中定義的結構定義會覆寫範本中定義的任何結構定義。在本頁稍後部分,您會看到在用戶端程式碼中定義結構定義的範本和用戶端程式碼範例。

  • 在範本內容中,加入 {{history}} 標記,告知範本要在何處插入用戶端 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}}

在程式碼中使用範本

按一下 Gemini API 供應商,即可在這個頁面查看供應商專屬內容和程式碼。

以下用戶端程式碼範例說明如何在程式碼中使用範本。注意事項:

  • 使用多輪互動時,請搭配 templateGenerativeModelstartChatsendMessage

  • 在用戶端程式碼中初始化模型時,請勿列出模型可存取的函式。函式必須列在範本前言的 tools 物件中 (如上所示)。

  • 以下範例用戶端程式碼假設您要在範本中定義函式結構定義。如果您決定在用戶端程式碼中定義結構定義,系統會覆寫範本定義的結構定義。本頁稍後會提供範本和用戶端程式碼範例,說明如何在用戶端程式碼中定義結構定義

  • 檢查模型是否會傳回函式呼叫,做為完成要求的一部分。如果是,應用程式需要執行本機邏輯,然後將結果傳回模型。

範本中定義函式結構定義的用戶端程式碼範例

Swift

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),
      );
    }
  }
}

Unity


// ...

// 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}");
}


函式呼叫 - 在用戶端程式碼中定義結構定義

請務必詳閱上述章節,瞭解函式呼叫如何搭配伺服器提示範本運作 (特別是範本內容中 {{history}} 標記的使用方式)。如果您想在用戶端程式碼 (而非範本) 中定義函式結構定義,本節提供範本和用戶端程式碼範例。

在用戶端程式碼中定義函式結構定義時,請注意下列事項:

  • 如果在用戶端程式碼中定義函式的結構定義 (如下方範例所示),用戶端結構定義會覆寫該函式的所有範本定義結構定義。

  • 如要在用戶端程式碼中定義函式結構定義,請編寫函式宣告,然後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}}

範例用戶端程式碼,其中函式結構定義於用戶端程式碼中
(如需本範例省略的詳細資料,請參閱上方的範例用戶端程式碼)

Swift

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.
...

Unity

// ...

// 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.
  ...
}

// ...



後續步驟