서버 프롬프트 템플릿과의 다중 턴 상호작용


이 가이드는 다음과 같은 다중 턴 상호작용에 의존하는 모든 기능에 적용됩니다.

높은 수준의 개요

멀티턴 상호작용의 경우 Firebase AI Logic SDK가 대화 상태를 관리합니다. 서버 프롬프트 템플릿을 사용하는 경우에도 마찬가지입니다.

다중 턴 상호작용 및 서버 프롬프트 템플릿의 기본 워크플로는 단일 턴 요청과 기본적으로 동일하지만 몇 가지 중요한 차이점이 있습니다.

  1. Firebase 콘솔의 안내 UI를 사용하여 템플릿을 만듭니다.

    멀티턴 상호작용의 경우 템플릿의 콘텐츠에 {{history}} 태그를 추가해야 합니다. 이 태그는 클라이언트 SDK에서 관리하는 대화 턴을 삽입할 위치를 템플릿에 알려줍니다.

  2. Firebase 콘솔의 테스트 환경을 사용하여 실제 요청에서 템플릿을 테스트합니다.

    멀티턴 상호작용의 경우 콘솔 테스트 환경은 초기 턴만 테스트하는 데 도움이 됩니다. 실제 앱으로 템플릿을 사용하여 후속 턴 (기록)이 처리되는 방식을 테스트할 수 있습니다.

  3. templateGenerativeModel를 사용하여 앱의 코드에서 템플릿에 액세스합니다.

    멀티턴 상호작용의 경우 서버 프롬프트 템플릿을 사용하지 않는 경우 멀티턴 상호작용에서와 마찬가지로 startChatsendMessage를 사용해야 합니다.

함수 호출의 경우 몇 가지 차이점이 더 있으며, 이는 이 페이지의 뒷부분에 있는 해당 섹션에 설명되어 있습니다.



멀티턴 대화 (채팅)

아직 검토하지 않았다면 서버 프롬프트 템플릿을 사용하지 않는 경우 다중 턴 대화 (채팅) 빌드에 관한 일반 가이드를 검토하세요.

서버 프롬프트 템플릿의 기본 형식

Firebase AI Logic의 경우 Firebase 콘솔은 템플릿의 프런트매터와 콘텐츠를 지정할 수 있는 안내 UI를 제공합니다.

서버 프롬프트 템플릿은 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 제공업체를 클릭하여 이 페이지에서 제공업체별 콘텐츠와 코드를 확인합니다.

아래의 클라이언트 코드 예시에서는 코드에서 템플릿을 사용하는 방법을 보여줍니다. 멀티턴 상호작용을 빌드할 때 startChatsendMessage와 함께 templateGenerativeModel를 사용한다는 점에 유의하세요.

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를 제공합니다.

서버 프롬프트 템플릿은 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.
  ...
}

// ...



다음 단계