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 đến việc chấm dứt một cách suôn sẻ.
Giới hạn cho phiên
Đối với Live API, một phiên đề cập đến một kết nối liên tục, trong đó dữ liệu đầ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, 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 ở mức 128.000 token.
Do giới hạn này về cửa sổ ngữ cảnh, sau đây là thời lượng phiên tối đa gần đúng dựa trên phương thức nhập:
- Phiên chỉ nhập âm thanh bị giới hạn ở mức
15 phút . - Phiên nhập video + âm thanh bị giới hạn ở mức
2 phút .
- Phiên chỉ nhập âm thanh bị giới hạn ở mức
Thời lượng kết nối bị giới hạn ở mức 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.
Dưới đâ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 phiên để tránh mất ngữ cảnh trò chuyện trong thời gian ngắn khi mạng bị ngắt kết nối hoặc sau khi nhận được thông báo sắp kết thúc.
Bắt đầu phiên
Hãy xem hướng dẫn bắt đầu sử dụng Live API để xem đoạn mã đầy đủ cho biết cách bắt đầu phiên.
Cập nhật giữa phiên
Các mô hình Live API hỗ trợ các tính năng nâng cao sau đây cho các bản cập nhật giữa phiên:
Cập nhật hướng dẫn hệ thống (chỉ dành cho Vertex AI Gemini API)
Thêm các bản cập nhật nội dung tăng dần
Bạn có thể thêm các bản cập nhật tăng dần trong phiên đang hoạt động. Hãy dùng tính năng này để gửi dữ liệu đầu vào dạng văn bản, thiết lập ngữ cảnh của phiên hoặc khôi phục ngữ cảnh của phiên.
Đối với ngữ cảnh dài hơn, bạn nên cung cấp bản tóm tắt một tin nhắn để 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 ngữ cảnh ngắn, bạn có thể gửi các lượt tương tác theo từng lượt để biểu thị chính xác trình tự 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 giữa phiên
| Chỉ dùng được khi bạn sử dụng Vertex AI Gemini API làm nhà cung cấp API. |
Bạn có thể cập nhật hướng dẫn hệ thống trong phiên đang hoạt động. Hãy dùng tính năng này để điều chỉnh phản hồi của mô hình, chẳng hạn như thay đổi ngôn ngữ phản hồi hoặc sửa đổi giọng điệu.
Để cập nhật hướng dẫn hệ thống giữa phiên, bạn có thể gửi nội dung văn bản có vai trò system. Hướng dẫn hệ thống đã cập nhật 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 định Gemini API để xem nội dung dành riêng cho nhà cung cấp và mã trên trang này. |
Live API Cửa sổ ngữ cảnh của phiên Live API lưu trữ dữ liệu được truyền trực tuyến theo thời gian thực (25 token 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 dạng 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 về cửa sổ ngữ cảnh của phiên là 128.000 token.
Theo mặc định, do giới hạn này về cửa sổ ngữ cảnh, sau đây là thời lượng phiên tối đa gần đúng dựa trên phương thức nhập:
- Phiên chỉ nhập âm thanh bị giới hạn ở mức
15 phút . - Phiên nhập video + âm thanh bị giới hạn ở mức
2 phút .
Trong các phiên chạy dài, khi cuộc trò chuyện diễn ra, nhật ký token â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ể bị ảo giác, chậm lại 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 trong 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 cũ 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 đã chỉ định. Hướng dẫn hệ thống không bị loại bỏ và sẽ luôn ở đầ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ề mặt 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ỳ ý số lượng token kích hoạt tính năng nén: (xem các chế độ cài đặt và giá trị hiện có bên dưới). Dưới đây là một số điểm cần cân nhắc ở cấp cao về việc sử dụng các chế độ cài đặt này:
Việc đặt
targetTokensrấ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 cũ của cuộc trò chuyện.Việc đặt
targetTokensgần vớitriggerTokenssẽ giữ lại 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.
| Cài đặt | Giá trị 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 kích hoạt tính năng nén |
80% giới hạn cửa sổ ngữ cảnh của mô hình | 5.000 | 128.000 |
targetTokenssố lượng token 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 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 cho biết cách phát hiện việc chấm dứt kết nối sắp xảy ra bằng cách theo dõi thông báo sắp kết thúc:
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 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 mã nhận dạng và bạn có thể sử dụng mã 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 theo dõi thông báo sắp kết thúc, và sau đó kéo dài phiên bằng cách thiết lập kết nối mới bằng mã nhận dạng phiên.Tiếp tục phiên ngay sau khi kết nối bị gián đoạn
Nếu kết nối chấm dứt hoặc bị gián đoạn trước giới hạn thời gian kết nối tối đa (ví dụ: chuyển từ WiFi sang 5G), 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 kết nối mới bằ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 kết nối mới bằ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 hai 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 chuyển cấu hình tiếp tục trống khi thiết lập 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ã nhận dạng 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à chuyển mã nhận dạng này để tiếp tục phiên với ngữ cảnh còn nguyên vẹn.
Các ví dụ sau đây cho thấy 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)
);
}