google / google/adk-python

Live multi-agent runs turn audio transcription back on after the caller disabled it

Đang mở
#6,827 0 bình luận 0 reaction 1 người được giao Được @wuliang229 nhận Xem trên GitHub
live
Ngôn ngữ chính
Python
Star
21.5k
Fork
4k
Merge trung bình
1 ngày 14 giờ
Pull request đã merge (30 ngày)
37

Mô tả

`_new_invocation_context_for_live()` (`runners.py:2371`) forces `input_audio_transcription` / `output_audio_transcription` on for live multi-agent runs, overwriting an explicit `None`. It writes into the `RunConfig` it was given, so the caller's object is modified too.

`None` is the only way to say "off": both fields are `Field(default_factory=types.AudioTranscriptionConfig)`, so the default is already truthy. `if not run_config.input_audio_transcription:` can't tell "off" from "unset". The block is a no-op for a default `RunConfig` — it only fires when someone deliberately turned transcription off.

**Expected:** `None` stays `None` for the run, and the caller's `RunConfig` is not mutated. (`0b39e728` already copies before filling the AUDIO default at `runners.py:1899` for that reason.)

**Observed:**

```
response_modalities=[]
caller's cfg.input_audio_transcription = AudioTranscriptionConfig()
run's ic.run_config.input_audio_transcription = AudioTranscriptionConfig()
response_modalities=None
caller's cfg.input_audio_transcription = AudioTranscriptionConfig()
run's ic.run_config.input_audio_transcription = AudioTranscriptionConfig()
```

Going through `run_live()` instead, the caller is shielded when `response_modalities` is unset because `runners.py:1899` copies first. The config the run actually uses has transcription on either way, and a reused `RunConfig` carries it forward.

```python
from google.adk.agents.live_request_queue import LiveRequestQueue
from google.adk.agents.llm_agent import LlmAgent
from google.adk.agents.run_config import RunConfig
from google.adk.runners import InMemoryRunner
from google.adk.sessions.session import Session
from google.genai import types

MODEL = "gemini-2.0-flash-live-001"

root = LlmAgent(name="root", model=MODEL,
sub_agents=[LlmAgent(name="child", model=MODEL)])
runner = InMemoryRunner(agent=root, app_name="app")
session = Session(id="s", app_name="app", user_id="u")

for modalities in ([types.Modality.AUDIO], None):
cfg = RunConfig(response_modalities=modalities,
input_audio_transcription=None,
output_audio_transcription=None)
ic = runner._new_invocation_context_for_live(
session, live_request_queue=LiveRequestQueue(), run_config=cfg)
print(f"response_modalities={modalities}")
print(f" caller's cfg.input_audio_transcription = "
f"{cfg.input_audio_transcription!r}")
print(f" run's ic.run_config.input_audio_transcription = "
f"{ic.run_config.input_audio_transcription!r}")
```

`39f78dc2` added the force-on when both fields still defaulted to `None`. `ab69ef8d` later switched them to `default_factory`, which is why the block can only fire on an explicit opt-out. `0b39e728` fixed the same class of write for `response_modalities`; this site was not included.

Fix: don't write when the field is in `model_fields_set`, and `model_copy` before any update so the caller is left alone. Deleting the block also works — the defaults already provide what it's trying to force. If transfer actually requires transcription, raise or warn instead of silently flipping it.

ADK `v2.7.1` / `v1.39.0` / `main` (`4599a526`). macOS, Python 3.13.1. Model never reached — this happens while building the invocation context.

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.