Gemini Live API xử lý các luồng âm thanh hoặc văn bản liên tục, được gọi là phiên. Bạn có thể quản lý vòng đời của phiên, từ lần bắt tay ban đầu cho đến khi kết thúc một cách suôn sẻ.
Giới hạn cho phiên
Đối với Live API, phiên đề cập đến một kết nối liên tục, trong đó đầu vào và đầu ra được truyền trực tuyến liên tục qua một kết nối.
Nếu phiên vượt quá bất kỳ giới hạn nào sau đây, thì kết nối sẽ bị chấm dứt. Tuy nhiên, hãy lưu ý rằng Live API cung cấp một số lựa chọn (xem bên dưới) để xử lý các giới hạn liên quan đến phiên này.
Cửa sổ ngữ cảnh của phiên bị giới hạn ở 128.000 token.
Do giới hạn về cửa sổ ngữ cảnh này, sau đây là độ dài tối đa gần đúng của phiên dựa trên phương thức nhập:
- Các phiên nhập chỉ bằng âm thanh được giới hạn trong
15 phút . - Đầu vào video và âm thanh bị giới hạn ở
2 phút .
- Các phiên nhập chỉ bằng âm thanh được giới hạn trong
Thời lượng kết nối bị giới hạn trong khoảng
10 phút .Bạn sẽ nhận được thông báo sắp kết thúc khoảng
60 giây trước khi kết nối kết thúc.
Sau đây là một số lựa chọn để xử lý các giới hạn liên quan đến phiên:
Nén cửa sổ ngữ cảnh của phiên để máy chủ tự động duy trì kích thước ngữ cảnh trong giới hạn.
Tiếp tục một phiên để tránh mất ngữ cảnh cuộc trò chuyện trong trường hợp mạng bị ngắt kết nối trong thời gian ngắn hoặc sau khi nhận được thông báo sắp rời khỏi.
Bắt đầu một phiên
Hãy truy cập vào hướng dẫn bắt đầu sử dụng Live API để xem một đoạn mã đầy đủ cho biết cách bắt đầu một phiên.
Cập nhật trong phiên
Các mô hình Live API hỗ trợ những chức năng nâng cao sau đây cho bản cập nhật trong phiên:
Hướng dẫn cập nhật hệ thống (chỉ dành cho Vertex AI Gemini API)
Thêm nội dung cập nhật gia tăng
Bạn có thể thêm các bản cập nhật gia tăng trong phiên hoạt động. Sử dụng phương thức này để gửi dữ liệu nhập văn bản, thiết lập bối cảnh phiên hoặc khôi phục bối cảnh phiên.
Đối với những bối cảnh dài hơn, bạn nên cung cấp một bản tóm tắt tin nhắn duy nhất để giải phóng cửa sổ ngữ cảnh cho các lượt tương tác tiếp theo.
Đối với các ngữ cảnh ngắn, bạn có thể gửi các lượt tương tác từng bước để biểu thị chính xác trình tự của các sự kiện, chẳng hạn như đoạn mã bên dưới.
Swift
// Define initial turns (history/context).
let turns: [ModelContent] = [
ModelContent(role: "user", parts: [TextPart("What is the capital of France?")]),
ModelContent(role: "model", parts: [TextPart("Paris")]),
]
// Send history, keeping the conversational turn OPEN (false).
await session.sendContent(turns, turnComplete: false)
// Define the new user query.
let newTurn: [ModelContent] = [
ModelContent(role: "user", parts: [TextPart("What is the capital of Germany?")]),
]
// Send the final query, CLOSING the turn (true) to trigger the model response.
await session.sendContent(newTurn, turnComplete: true)
Kotlin
Not yet supported for Android apps - check back soon!
Java
Not yet supported for Android apps - check back soon!
Web
const turns = [{ text: "Hello from the user!" }];
await session.send(
turns,
false // turnComplete: false
);
console.log("Sent history. Waiting for next input...");
// Define the new user query.
const newTurn [{ text: "And what is the capital of Germany?" }];
// Send the final query, CLOSING the turn (true) to trigger the model response.
await session.send(
newTurn,
true // turnComplete: true
);
console.log("Sent final query. Model response expected now.");
Dart
// Define initial turns (history/context).
final List turns = [
Content(
"user",
[Part.text("What is the capital of France?")],
),
Content(
"model",
[Part.text("Paris")],
),
];
// Send history, keeping the conversational turn OPEN (false).
await session.send(
input: turns,
turnComplete: false,
);
// Define the new user query.
final List newTurn = [
Content(
"user",
[Part.text("What is the capital of Germany?")],
),
];
// Send the final query, CLOSING the turn (true) to trigger the model response.
await session.send(
input: newTurn,
turnComplete: true,
);
Unity
// Define initial turns (history/context).
List turns = new List {
new ModelContent("user", new ModelContent.TextPart("What is the capital of France?") ),
new ModelContent("model", new ModelContent.TextPart("Paris") ),
};
// Send history, keeping the conversational turn OPEN (false).
foreach (ModelContent turn in turns)
{
await session.SendAsync(
content: turn,
turnComplete: false
);
}
// Define the new user query.
ModelContent newTurn = ModelContent.Text("What is the capital of Germany?");
// Send the final query, CLOSING the turn (true) to trigger the model response.
await session.SendAsync(
content: newTurn,
turnComplete: true
);
Cập nhật hướng dẫn hệ thống trong phiên
| Chỉ có khi bạn dùng Vertex AI Gemini API làm trình cung cấp API. |
Bạn có thể cập nhật chỉ dẫn hệ thống trong một phiên hoạt động. Sử dụng tham số này để điều chỉnh câu trả lời của mô hình, ví dụ: thay đổi ngôn ngữ của câu trả lời hoặc sửa đổi giọng điệu.
Để cập nhật hướng dẫn cho hệ thống trong phiên, bạn có thể gửi nội dung văn bản có vai trò system. Hướng dẫn mới cập nhật cho hệ thống sẽ vẫn có hiệu lực trong thời gian còn lại của phiên.
Swift
await session.sendContent(
[ModelContent(
role: "system",
parts: [TextPart("new system instruction")]
)],
turnComplete: false
)
Kotlin
Not yet supported for Android apps - check back soon!
Java
Not yet supported for Android apps - check back soon!
Web
Not yet supported for Web apps - check back soon!
Dart
try {
await _session.send(
input: Content(
'system',
[Part.text('new system instruction')],
),
turnComplete: false,
);
} catch (e) {
print('Failed to update system instructions: $e');
}
Unity
try
{
await session.SendAsync(
content: new ModelContent(
"system",
new ModelContent.TextPart("new system instruction")
),
turnComplete: false
);
}
catch (Exception e)
{
Debug.LogError($"Failed to update system instructions: {e.Message}");
}
Nén cửa sổ ngữ cảnh
|
Nhấp vào nhà cung cấp Gemini API để xem nội dung và mã dành riêng cho nhà cung cấp trên trang này. |
Live API Cửa sổ ngữ cảnh của phiên lưu trữ dữ liệu được truyền trực tiếp theo thời gian thực (25 mã thông báo mỗi giây (TPS) cho âm thanh và 258 TPS cho video) cũng như nội dung khác, bao gồm cả dữ liệu đầu vào là văn bản và dữ liệu đầu ra của mô hình. Tất cả các mô hình Live API đều có giới hạn cửa sổ ngữ cảnh phiên là 128.000 token.
Theo mặc định, do giới hạn cửa sổ ngữ cảnh này, đây là độ dài phiên tối đa gần đúng dựa trên các phương thức nhập:
- Các phiên nhập chỉ bằng âm thanh được giới hạn trong
15 phút . - Đầu vào video và âm thanh bị giới hạn ở
2 phút .
Trong các phiên kéo dài, khi cuộc trò chuyện diễn ra, nhật ký mã thông báo âm thanh và/hoặc video sẽ tích luỹ. Nếu nhật ký này vượt quá giới hạn của mô hình, thì mô hình có thể đưa ra thông tin sai lệch, hoạt động chậm hoặc phiên có thể bị chấm dứt bắt buộc.
Để bật các phiên dài hơn, bạn có thể bật tính năng nén cửa sổ ngữ cảnh bằng cách đặt trường contextWindowCompression làm một phần của LiveGenerationConfig. Khi được bật, máy chủ sẽ sử dụng cơ chế cửa sổ trượt để tự động loại bỏ các lượt gần đây nhất hoặc tóm tắt các lượt đó để duy trì kích thước ngữ cảnh trong giới hạn mặc định hoặc giới hạn được chỉ định. Các chỉ dẫn hệ thống sẽ không bị loại bỏ và luôn nằm ở đầu cửa sổ ngữ cảnh.
Theo quan điểm của người dùng, điều này cho phép thời lượng phiên về lý thuyết là vô hạn vì "bộ nhớ" được quản lý liên tục.
Bạn có thể định cấu hình cơ chế cửa sổ trượt cũng như tuỳ chọn số lượng mã thông báo kích hoạt tính năng nén: (xem các chế độ cài đặt và giá trị có sẵn bên dưới). Sau đây là một số điểm cần cân nhắc chung về việc sử dụng các chế độ cài đặt này:
Việc đặt
targetTokensở mức rất thấp sẽ giải phóng thêm không gian ngữ cảnh cho các luồng liên tục, nhưng mô hình sẽ nhanh chóng "quên" các lượt trò chuyện cũ hơn.Việc đặt
targetTokensgần vớitriggerTokenssẽ giúp duy trì nhiều bộ nhớ hơn nhưng sẽ kích hoạt các quy trình nén thường xuyên hơn nhiều.
| Cài đặt | Mặc định cho cửa sổ trượt nếu không được đặt trong cấu hình | Giá trị nhỏ nhất | Giá trị lớn nhất |
|---|---|---|---|
triggerTokensđộ dài ngữ cảnh trước khi quá trình nén được kích hoạt |
80% giới hạn cửa sổ ngữ cảnh của mô hình | 5.000 | 128.000 |
targetTokenssố lượng mã thông báo mục tiêu cần giữ lại |
50% giá trị triggerTokens
|
0 | 128.000 |
Swift
// Initialize the Gemini Developer API backend service
let liveModel = FirebaseAI.firebaseAI(backend: .googleAI()).liveModel(
modelName: "gemini-2.5-flash-native-audio-preview-12-2025",
// Enable context window compression.
// (Optional) Configure the number of tokens in the context window that triggers the compression.
generationConfig: LiveGenerationConfig(
responseModalities: [.audio],
contextWindowCompression: ContextWindowCompressionConfig(
triggerTokens: 10000,
slidingWindow: SlidingWindow(
targetTokens: 2000,
)
)
)
)
Kotlin
// Initialize the Gemini Developer API backend service
val liveModel = Firebase.ai(backend = GenerativeBackend.googleAI()).liveModel(
modelName = "gemini-2.5-flash-native-audio-preview-12-2025",
// Enable context window compression.
// (Optional) Configure the number of tokens in the context window that triggers the compression.
generationConfig = liveGenerationConfig {
responseModality = ResponseModality.AUDIO,
contextWindowCompression = ContextWindowCompressionConfig(
triggerTokens = 10000,
slidingWindow = SlidingWindow(targetTokens = 2000)
)
}
)
Java
// Initialize the Gemini Developer API backend service
LiveGenerativeModel lm = FirebaseAI.getInstance(GenerativeBackend.googleAI()).liveModel(
"gemini-2.5-flash-native-audio-preview-12-2025",
// Enable context window compression.
// (Optional) Configure the number of tokens in the context window that triggers the compression.
new LiveGenerationConfig.Builder()
.setResponseModality(ResponseModality.AUDIO)
.setContextWindowCompression(
new ContextWindowCompressionConfig(10000, new SlidingWindow(2000))
)
.build()
);
Web
const ai = getAI(firebaseApp, { backend: new GoogleAIBackend() });
const liveModel = getLiveGenerativeModel(ai, {
model: "gemini-2.5-flash-native-audio-preview-12-2025",
// Enable context window compression.
// (Optional) Configure the number of tokens in the context window that triggers the compression.
generationConfig: {
responseModalities: [ResponseModality.AUDIO],
contextWindowCompression: {
triggerTokens: 10000,
slidingWindow: {
targetTokens: 2000,
},
},
},
});
Dart
final _liveModel = FirebaseAI.googleAI().liveGenerativeModel(
model: 'gemini-2.5-flash-native-audio-preview-12-2025',
// Enable context window compression.
// (Optional) Configure the number of tokens in the context window that triggers the compression.
liveGenerationConfig: LiveGenerationConfig(
responseModalities: [ResponseModalities.audio],
contextWindowCompression: ContextWindowCompressionConfig(
triggerTokens: 10000,
slidingWindow: SlidingWindow(targetTokens: 2000),
),
),
);
Unity
var liveModel = FirebaseAI.GetInstance(FirebaseAI.Backend.GoogleAI()).GetLiveModel(
modelName: "gemini-2.5-flash-native-audio-preview-12-2025",
// Enable context window compression.
// (Optional) Configure the number of tokens in the context window that triggers the compression.
liveGenerationConfig: new LiveGenerationConfig(
responseModalities: new[] { ResponseModality.Audio },
contextWindowCompression: new ContextWindowCompressionConfig(
triggerTokens: 10000,
slidingWindow: new SlidingWindow(targetTokens: 2000)
)
)
);
Phát hiện thời điểm một phiên sắp kết thúc
Thời lượng tối đa của một kết nối WebSocket liên tục là khoảng
Ví dụ sau đây minh hoạ cách phát hiện một kết nối sắp bị chấm dứt bằng cách theo dõi thông báo going away:
Swift
for try await response in session.responses {
switch response.payload {
case .goingAwayNotice(let goingAwayNotice):
// Prepare for the session to close soon
if let timeLeft = goingAwayNotice.timeLeft {
print("Server going away in \(timeLeft) seconds")
}
}
}
Kotlin
for (response in session.responses) {
when (val message = response.payload) {
is LiveServerGoAway -> {
// Prepare for the session to close soon
val remaining = message.timeLeft
logger.info("Server going away in $remaining")
}
}
}
Java
session.getResponses().forEach(response -> {
if (response.getPayload() instanceof LiveServerResponse.GoingAwayNotice) {
LiveServerResponse.GoingAwayNotice notice = (LiveServerResponse.GoingAwayNotice) response.getPayload();
// Prepare for the session to close soon
Duration timeLeft = notice.getTimeLeft();
}
});
Web
for await (const message of session.receive()) {
switch (message.type) {
...
case "goingAwayNotice":
console.log("Server going away. Time left:", message.timeLeft);
break;
}
}
Dart
Future _handleLiveServerMessage(LiveServerResponse response) async {
final message = response.message;
if (message is GoingAwayNotice) {
// Prepare for the session to close soon
developer.log('Server going away. Time left: ${message.timeLeft}');
}
}
Unity
foreach (var response in session.Responses) {
if (response.Payload is LiveSessionGoingAway notice) {
// Prepare for the session to close soon
TimeSpan timeLeft = notice.TimeLeft;
Debug.Log($"Server going away notice received. Remaining: {timeLeft}");
}
}
Tiếp tục một phiên
Live API hỗ trợ tiếp tục phiên để tránh mất ngữ cảnh trò chuyện. Mỗi phiên đều có một giá trị nhận dạng và bạn có thể sử dụng giá trị này theo những cách sau:
Duy trì phiên trước khi đạt đến giới hạn thời gian kết nối
Thời lượng tối đa của một kết nối WebSocket liên tục là khoảng
10 phút . Bạn có thể phát hiện thời điểm kết nối sắp kết thúc bằng cách nghe thông báo sắp kết thúc, sau đó kéo dài phiên bằng cách thiết lập một kết nối mới bằng cách sử dụng mã nhận dạng phiên.Tiếp tục phiên ngay sau khi mất kết nối
Nếu một kết nối kết thúc hoặc bị ngắt trước khi hết thời gian kết nối tối đa (ví dụ: chuyển từ Wi-Fi sang 5G), thì máy chủ sẽ giữ trạng thái phiên trong khoảng
10 phút . Trong khoảng thời gian này, bạn có thể tiếp tục phiên bằng cách thiết lập một kết nối mới bằng cách sử dụng mã nhận dạng phiên.Tiếp tục phiên sau một khoảng thời gian dài
Sau khi kết nối kết thúc, máy chủ sẽ giữ trạng thái phiên trong vài giờ. Trong khoảng thời gian này, bạn có thể tiếp tục phiên bằng cách thiết lập một kết nối mới bằng cách sử dụng mã nhận dạng phiên. Xin lưu ý rằng khoảng thời gian này khác nhau đối với 2 nhà cung cấp Gemini API: Gemini Developer API là
2 giờ | Vertex AI Gemini API là24 giờ .
Theo mặc định, tính năng tiếp tục phiên bị tắt. Để bật tính năng tiếp tục phiên, hãy truyền một cấu hình tiếp tục trống khi thiết lập một kết nối mới. Khi được bật, máy chủ sẽ định kỳ gửi các bản cập nhật chứa một mã xử lý tiếp tục phiên. Nếu phiên bị ngắt kết nối, bạn có thể kết nối lại và truyền mã nhận dạng này để tiếp tục phiên mà không bị mất ngữ cảnh.
Các ví dụ sau đây minh hoạ 2 lựa chọn để tiếp tục phiên:
Swift
// Local variable to save the active session handle
var activeSessionHandle: String?
// Initialize the session. Passing an empty config requests the server to send SessionResumptionUpdate
var session = try await liveModel.connect(
sessionResumption: SessionResumptionConfig()
)
// Start receiving responses
for try await message in session.responses {
// Check for new session handles inside your message handling loop
switch message.payload {
case let .sessionResumptionUpdate(updateMessage):
guard let newHandle = updateMessage.newHandle, updateMessage.resumable else {
continue
}
activeSessionHandle = newHandle
print("SessionResumptionUpdate: handle \(newHandle)")
// ... handle other LiveServerMessage types ...
default:
break
}
}
// The following are alternative options to resume a session. Choose only one.
// Option 1: Create and connect a session to resume with the saved handle
if let handle = activeSessionHandle {
session = try await liveModel.connect(
sessionResumption: SessionResumptionConfig(handle: handle)
)
}
// Option 2: Resume the session directly on an existing session object
if let handle = activeSessionHandle {
try await session.resumeSession(
sessionResumption: SessionResumptionConfig(handle: handle)
)
}
Kotlin
// Local variable to save the active session handle
var activeSessionHandle: String? = null
// Initialize the session. Passing an empty config requests the server to send SessionResumptionUpdate
var session = liveModel.connect(
sessionResumption = SessionResumptionConfig()
)
// Start receiving responses
session.receive().collect { message ->
// Process other received response types...
// Check for new session handles inside your message handling loop
if (message is LiveSessionResumptionUpdate) {
if (message.resumable == true && message.newHandle != null) {
activeSessionHandle = message.newHandle
Log.d("TAG", "SessionResumptionUpdate: handle ${message.newHandle}")
}
}
}
// The following are alternative options to resume a session. Choose only one.
// Option 1: Create and connect a session to resume with the saved handle
activeSessionHandle?.let { handle ->
session = liveModel.connect(
sessionResumption = SessionResumptionConfig(handle = handle)
)
}
// Option 2: Resume the session directly on an existing session object
activeSessionHandle?.let { handle ->
session.resumeSession(
sessionResumption = SessionResumptionConfig(handle = handle)
)
}
Java
For Java, session resumption is not yet supported. Check back soon!
Web
// Local variable to save the active session handle
let activeSessionHandle = null;
// Initialize the session. Passing an empty object requests the server to send SessionResumptionUpdate
let session = await liveModel.connect({});
// Start receiving responses
for await (const message of session.receive()) {
// Process other received response types...
// Check for new session handles inside your message handling loop
if (message.type === 'sessionResumptionUpdate') {
if (message.resumable && message.newHandle) {
activeSessionHandle = message.newHandle;
console.log(`SessionResumptionUpdate: handle ${activeSessionHandle}`);
}
}
}
// The following are alternative options to resume a session. Choose only one.
// Option 1: Create and connect a session to resume with the saved handle
if (activeSessionHandle) {
session = await liveModel.connect({
handle: activeSessionHandle
});
}
// Option 2: Resume the session directly on an existing session object
if (activeSessionHandle) {
await session.resumeSession({
handle: activeSessionHandle
});
}
Dart
// Local variable to save the active session handle
String? _activeSessionHandle;
// Initialize the session. Passing an empty config requests the server to send SessionResumptionUpdate
var _session = await _liveModel.connect(
sessionResumption: SessionResumptionConfig(),
);
// Start receiving responses
await for (final message in _session.receive()) {
// Process other received response types...
// Check for new session handles inside your message handling loop
if (message is SessionResumptionUpdate &&
message.resumable != null &&
message.resumable!) {
_activeSessionHandle = message.newHandle;
log('SessionResumptionUpdate: handle ${message.newHandle}');
}
}
// The following are alternative options to resume a session. Choose only one.
// Option 1: Create and connect a session to resume with the saved handle
if (_activeSessionHandle != null) {
_session = await _liveModel.connect(
sessionResumption: SessionResumptionConfig.resume(_activeSessionHandle!),
);
}
// Option 2: Alternatively, resume the session directly on an existing session object
if (_activeSessionHandle != null) {
await _session.resumeSession(
sessionResumption: SessionResumptionConfig.resume(_activeSessionHandle!),
);
}
Unity
// Local variable to save the active session handle
string activeSessionHandle = null;
// Initialize the session. Passing an empty config requests the server to send SessionResumptionUpdate
var session = await liveModel.ConnectAsync(
sessionResumption: new SessionResumptionConfig()
);
// Start receiving responses
await foreach (var response in session.ReceiveAsync())
{
// Process other received response types...
// Check for new session handles inside your message handling loop
if (response.Message is LiveSessionResumptionUpdate updateMessage)
{
if (updateMessage.Resumable == true && !string.IsNullOrEmpty(updateMessage.NewHandle))
{
activeSessionHandle = updateMessage.NewHandle;
Debug.Log($"SessionResumptionUpdate: handle {activeSessionHandle}");
}
}
}
// The following are alternative options to resume a session. Choose only one.
// Option 1: Create and connect a session to resume with the saved handle
if (!string.IsNullOrEmpty(activeSessionHandle)) {
session = await liveModel.ConnectAsync(
sessionResumption: new SessionResumptionConfig(activeSessionHandle)
);
}
// Option 2: Resume the session directly on an existing session object
if (!string.IsNullOrEmpty(activeSessionHandle)) {
await session.ResumeSessionAsync(
sessionResumption: new SessionResumptionConfig(activeSessionHandle)
);
}