Skip to content

Commit b6cc92a

Browse files
committed
feat: add Gemini 3.1 Flash Live support for run_live()
Changes: 1. send_realtime(): use audio= instead of deprecated media= (all models) 2. send_content(): use send_tool_response() for function responses (all models) 3. send_content(): route text via send_realtime_input for 3.1 models 4. connect(): inject history_config for 3.1 models Changes 1-2 are backward-compatible API upgrades (removing deprecated usage). Changes 3-4 are conditional on model version containing '3.1'. Tested in production with real phone calls on gemini-3.1-flash-live-preview. Note: 3.1 models do not support enable_affective_dialog, context_window_compression, or proactivity config fields. These are documented in issue #5075 as model limitations. Fixes #5018
1 parent f973673 commit b6cc92a

File tree

2 files changed

+24
-5
lines changed

2 files changed

+24
-5
lines changed

src/google/adk/models/gemini_llm_connection.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,21 @@ async def send_content(self, content: types.Content):
105105
# All parts have to be function responses.
106106
function_responses = [part.function_response for part in content.parts]
107107
logger.debug('Sending LLM function response: %s', function_responses)
108-
await self._gemini_session.send(
109-
input=types.LiveClientToolResponse(
110-
function_responses=function_responses
111-
),
108+
await self._gemini_session.send_tool_response(
109+
function_responses=function_responses
112110
)
113111
else:
112+
# 3.1 models reject LiveClientContent for mid-conversation text
113+
if self._model_version and '3.1' in self._model_version:
114+
text_parts = [p.text for p in content.parts if p.text]
115+
if text_parts:
116+
combined = ' '.join(text_parts)
117+
logger.debug(
118+
'Sending text via realtime input for 3.1 model: %s',
119+
combined[:100],
120+
)
121+
await self._gemini_session.send_realtime_input(text=combined)
122+
return
114123
logger.debug('Sending LLM new content %s', content)
115124
await self._gemini_session.send(
116125
input=types.LiveClientContent(
@@ -128,7 +137,7 @@ async def send_realtime(self, input: RealtimeInput):
128137
if isinstance(input, types.Blob):
129138
# The blob is binary and is very large. So let's not log it.
130139
logger.debug('Sending LLM Blob.')
131-
await self._gemini_session.send_realtime_input(media=input)
140+
await self._gemini_session.send_realtime_input(audio=input)
132141

133142
elif isinstance(input, types.ActivityStart):
134143
logger.debug('Sending LLM activity start signal.')

src/google/adk/models/google_llm.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,16 @@ async def connect(self, llm_request: LlmRequest) -> BaseLlmConnection:
401401
' backend. Please use Vertex AI backend.'
402402
)
403403
llm_request.live_connect_config.tools = llm_request.config.tools
404+
405+
# 3.1 models require history_config for session history to work
406+
model_name = llm_request.model or ''
407+
if '3.1' in model_name and not getattr(
408+
llm_request.live_connect_config, 'history_config', None
409+
):
410+
llm_request.live_connect_config.history_config = types.HistoryConfig(
411+
initial_history_in_client_content=True
412+
)
413+
404414
logger.debug('Connecting to live with llm_request:%s', llm_request)
405415
logger.debug('Live connect config: %s', llm_request.live_connect_config)
406416
async with self._live_api_client.aio.live.connect(

0 commit comments

Comments
 (0)