Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

LiteLlm with SSE streaming records the answer twice in gen_ai.output.messages

Đang mở Phù hợp với người mới
#7,630 11 bình luận 0 reaction 1 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 4 ngày

@surajksharma07 đang làm issue này rồi.

Từ ngày 22/10/2026.

  • #7694 của @ishan-1010 — đang mở

Đánh giá

Độ khó
2/5
Thời gian dự kiến
1-3 giờ
Mức phù hợp với người mới
78/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
python
Lĩnh vực
backend, observability

Hướng nghiên cứu

Bắt đầu với src/google/adk/telemetry/_instrumentation.py, đặc biệt là record_llm_response, và so sánh cách đoạn mã xử lý các phản hồi một phần được truyền theo luồng với phản hồi đã tổng hợp. Sau đó đọc mã truyền luồng LiteLlm trong src/google/adk/models/lite_llm.py ở gần các dòng được liên kết. Tái hiện bằng ví dụ StreamingMode.SSE được cung cấp và xác minh đầu ra được ghi nhận có một thông điệp trả lời đầy đủ, khớp với StreamingMode.NONE.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

models

🔴 Required Information

Describe the Bug:
with StreamingMode.SSE and a LiteLlm model the generate_content span ends up with every streamed chunk in gen_ai.output.messages and then the full answer again at the end. so the answer shows up twice and all the chunks have an empty finish_reason. without streaming its one message like expected. only visible with message content capture on (OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT)

looks like the text chunks get yielded as partial responses with no finish reason (lite_llm.py#L4475-L4485) and only the final aggregated response gets one (#L4556-L4558). record_llm_response keeps recording until it sees a finish reason (_instrumentation.py#L568-L595) so every chunk plus the aggregate goes in. since its in the LiteLlm wrapper i'd expect real providers to do the same but i only tested with litellm's mock_response

Steps to Reproduce:

  1. pip install google-adk litellm
  2. run this (no api key needed, it uses litellm's mock_response)
import asyncio
import json
import os

os.environ["OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT"] = "SPAN_ONLY"

from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
from opentelemetry.sdk.trace.export.in_memory_span_exporter import InMemorySpanExporter

spans = InMemorySpanExporter()
provider = TracerProvider()
provider.add_span_processor(SimpleSpanProcessor(spans))
trace.set_tracer_provider(provider)

from google.adk.agents import Agent
from google.adk.agents.run_config import RunConfig, StreamingMode
from google.adk.models.lite_llm import LiteLlm
from google.adk.runners import InMemoryRunner
from google.genai import types


async def run(mode):
  spans.clear()
  model = LiteLlm(model="openai/gpt-4o", mock_response="Oslo is 4C and cloudy today.", api_key="unused")
  runner = InMemoryRunner(agent=Agent(name="a", model=model), app_name="p")
  session = await runner.session_service.create_session(app_name="p", user_id="u")
  msg = types.Content(role="user", parts=[types.Part(text="weather?")])
  async for _ in runner.run_async(user_id="u", session_id=session.id, new_message=msg,
                                  run_config=RunConfig(streaming_mode=mode)):
    pass
  await runner.close()
  span = next(s for s in spans.get_finished_spans() if s.name.startswith("generate_content"))
  messages = json.loads(span.attributes["gen_ai.output.messages"])
  print(f"{mode.name}: {len(messages)} output message(s)")
  for m in messages:
    print("  ", repr(m.get("finish_reason")), "".join(p.get("content", "") for p in m["parts"]))


asyncio.run(run(StreamingMode.NONE))
asyncio.run(run(StreamingMode.SSE))

Expected Behavior:
one output message with the full answer, same as without streaming

Observed Behavior:

NONE: 1 output message(s)
   'stop' Oslo is 4C and cloudy today.
SSE: 11 output message(s)
   '' Osl
   '' o i
   '' s 4
   '' C a
   '' nd
   '' clo
   '' udy
   ''  to
   '' day
   '' .
   'stop' Oslo is 4C and cloudy today.

Environment Details:

  • ADK Library Version (pip show google-adk): 2.12.0 (main at 77a74f0)
  • Desktop OS: macOS
  • Python Version (python -V): 3.12.15

Model Information:

  • Are you using LiteLLM: Yes
  • Which model is being used: openai/gpt-4o via litellm mock_response

🟡 Optional Information

Regression:
havent checked older versions

maybe skip the partial chunks when recording output messages and keep just the aggregate? happy to send a PR if that sounds right

Ngôn ngữ chính
Python
Star
22k
Fork
4.2k
Merge trung bình
3 ngày 11 giờ
Pull request đã merge (30 ngày)
7

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của google/adk-python

Tất cả issue của google/adk-python

Issue tương tự

Thêm issue về Python

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.