Skip to content

Structured streaming doesn't work with claude (Stream Whale example) #1665

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
2 tasks done
sgondala opened this issue May 8, 2025 · 1 comment · May be fixed by #1669
Open
2 tasks done

Structured streaming doesn't work with claude (Stream Whale example) #1665

sgondala opened this issue May 8, 2025 · 1 comment · May be fixed by #1669
Assignees

Comments

@sgondala
Copy link

sgondala commented May 8, 2025

Initial Checks

Description

Structured streaming doesn't doesn’t work with Claude.

I tried using stream whales example as-is. While using openai:gpt-4, we see the expected streaming behavior with the table populating progressively. However, when switching to anthropic:claude-3-7-sonnet-latest, the output appears all at once rather than streaming incrementally.

Example Code

import os
from typing import Annotated

import logfire
from dotenv import load_dotenv
from pydantic import Field, ValidationError
from pydantic_ai import Agent
from rich.console import Console
from rich.live import Live
from rich.table import Table
from typing_extensions import NotRequired, TypedDict

load_dotenv()

# 'if-token-present' means nothing will be sent (and the example will work) if you don't have logfire configured
logfire.configure(send_to_logfire="if-token-present")


class Whale(TypedDict):
    name: str
    length: Annotated[float, Field(description="Average length of an adult whale in meters.")]
    weight: NotRequired[
        Annotated[
            float,
            Field(description="Average weight of an adult whale in kilograms.", ge=50),
        ]
    ]
    ocean: NotRequired[str]
    description: NotRequired[Annotated[str, Field(description="Short Description")]]


agent = Agent("anthropic:claude-3-7-sonnet-latest", output_type=list[Whale], instrument=True)


async def main():
    console = Console()
    with Live("\n" * 36, console=console) as live:
        console.print("Requesting data...", style="cyan")
        async with agent.run_stream("Generate me details of 5 species of Whale.") as result:
            console.print("Response:", style="green")

            async for message, last in result.stream_structured(debounce_by=0.01):
                try:
                    whales = await result.validate_structured_output(message, allow_partial=not last)
                except ValidationError as exc:
                    if all(e["type"] == "missing" and e["loc"] == ("response",) for e in exc.errors()):
                        continue
                    else:
                        raise

                table = Table(
                    title="Species of Whale",
                    caption="Streaming Structured responses from GPT-4",
                    width=120,
                )
                table.add_column("ID", justify="right")
                table.add_column("Name")
                table.add_column("Avg. Length (m)", justify="right")
                table.add_column("Avg. Weight (kg)", justify="right")
                table.add_column("Ocean")
                table.add_column("Description", justify="right")

                for wid, whale in enumerate(whales, start=1):
                    table.add_row(
                        str(wid),
                        whale["name"],
                        f'{whale["length"]:0.0f}',
                        f"{w:0.0f}" if (w := whale.get("weight")) else "…",
                        whale.get("ocean") or "…",
                        whale.get("description") or "…",
                    )
                live.update(table)


if __name__ == "__main__":
    import asyncio

    asyncio.run(main())

Python, Pydantic AI & LLM client version

python = 3.10 
pydantic ai = 0.1.10
llm = anthropic:claude-3-7-sonnet-latest
@DouweM
Copy link
Contributor

DouweM commented May 8, 2025

@sgondala Thanks for the report, I've implemented a fix in #1669.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants