Python: [Breaking] Simplified Content types to a single class with classmethod constructors. (#3252)

* ported Content to a new model

* fixed linting

* fixes

* fixed data format handling

* fix for 3.10 mypy

* fix

* fix int test
This commit is contained in:
Eduard van Valkenburg
2026-01-20 23:09:39 +01:00
committed by GitHub
Unverified
parent 73761aa4a3
commit 83e6229c11
132 changed files with 3949 additions and 4741 deletions
@@ -43,7 +43,7 @@ async def main() -> None:
if isinstance(content, TextReasoningContent):
print(f"\033[32m{content.text}\033[0m", end="", flush=True)
if isinstance(content, UsageContent):
print(f"\n\033[34m[Usage so far: {content.details}]\033[0m\n", end="", flush=True)
print(f"\n\033[34m[Usage so far: {content.usage_details}]\033[0m\n", end="", flush=True)
if chunk.text:
print(chunk.text, end="", flush=True)
@@ -54,7 +54,7 @@ async def main() -> None:
if isinstance(content, TextReasoningContent):
print(f"\033[32m{content.text}\033[0m", end="", flush=True)
if isinstance(content, UsageContent):
print(f"\n\033[34m[Usage so far: {content.details}]\033[0m\n", end="", flush=True)
print(f"\n\033[34m[Usage so far: {content.usage_details}]\033[0m\n", end="", flush=True)
if chunk.text:
print(chunk.text, end="", flush=True)
@@ -61,7 +61,7 @@ async def main() -> None:
case "text_reasoning":
print(f"\033[32m{content.text}\033[0m", end="", flush=True)
case "usage":
print(f"\n\033[34m[Usage so far: {content.details}]\033[0m\n", end="", flush=True)
print(f"\n\033[34m[Usage so far: {content.usage_details}]\033[0m\n", end="", flush=True)
case "hosted_file":
# Catch generated files
files.append(content)
@@ -4,10 +4,7 @@ import asyncio
from agent_framework import (
AgentResponseUpdate,
CitationAnnotation,
HostedCodeInterpreterTool,
HostedFileContent,
TextContent,
)
from agent_framework.azure import AzureAIProjectAgentProvider
from azure.identity.aio import AzureCliCredential
@@ -50,9 +47,9 @@ async def non_streaming_example() -> None:
# AgentResponse has messages property, which contains ChatMessage objects
for message in result.messages:
for content in message.contents:
if isinstance(content, TextContent) and content.annotations:
if content.type == "text" and content.annotations:
for annotation in content.annotations:
if isinstance(annotation, CitationAnnotation) and annotation.file_id:
if annotation.file_id:
annotations_found.append(annotation.file_id)
print(f"Found file annotation: file_id={annotation.file_id}")
@@ -84,15 +81,15 @@ async def streaming_example() -> None:
async for update in agent.run_stream(QUERY):
if isinstance(update, AgentResponseUpdate):
for content in update.contents:
if isinstance(content, TextContent):
if content.type == "text":
if content.text:
text_chunks.append(content.text)
if content.annotations:
for annotation in content.annotations:
if isinstance(annotation, CitationAnnotation) and annotation.file_id:
if annotation.file_id:
annotations_found.append(annotation.file_id)
print(f"Found streaming annotation: file_id={annotation.file_id}")
elif isinstance(content, HostedFileContent):
elif content.type == "hosted_file":
file_ids_found.append(content.file_id)
print(f"Found streaming HostedFileContent: file_id={content.file_id}")
@@ -3,7 +3,7 @@
import asyncio
import os
from agent_framework import CitationAnnotation
from agent_framework import Annotation
from agent_framework.azure import AzureAIAgentsProvider
from azure.ai.agents.aio import AgentsClient
from azure.ai.projects.aio import AIProjectClient
@@ -85,13 +85,11 @@ async def main() -> None:
)
print(f"User: {user_input}")
print("Agent: ", end="", flush=True)
# Stream the response and collect citations
citations: list[CitationAnnotation] = []
citations: list[Annotation] = []
async for chunk in agent.run_stream(user_input):
if chunk.text:
print(chunk.text, end="", flush=True)
# Collect citations from Azure AI Search responses
for content in getattr(chunk, "contents", []):
annotations = getattr(content, "annotations", [])
@@ -104,7 +102,7 @@ async def main() -> None:
if citations:
print("\n\nCitation:")
for i, citation in enumerate(citations, 1):
print(f"[{i}] {citation.url}")
print(f"[{i}] {citation.get('url')}")
print("\n" + "=" * 50 + "\n")
print("Hotel search conversation completed!")
@@ -2,7 +2,7 @@
import asyncio
from agent_framework import CitationAnnotation, HostedWebSearchTool
from agent_framework import Annotation, HostedWebSearchTool
from agent_framework.azure import AzureAIAgentsProvider
from azure.identity.aio import AzureCliCredential
@@ -57,7 +57,7 @@ async def main() -> None:
print("Agent: ", end="", flush=True)
# Stream the response and collect citations
citations: list[CitationAnnotation] = []
citations: list[Annotation] = []
async for chunk in agent.run_stream(user_input):
if chunk.text:
print(chunk.text, end="", flush=True)
@@ -74,9 +74,9 @@ async def main() -> None:
if citations:
print("\n\nCitations:")
for i, citation in enumerate(citations, 1):
print(f"[{i}] {citation.title}: {citation.url}")
if citation.snippet:
print(f" Snippet: {citation.snippet}")
print(f"[{i}] {citation['title']}: {citation.get('url')}")
if "snippet" in citation:
print(f" Snippet: {citation.get('snippet')}")
else:
print("\nNo citations found in the response.")
@@ -2,7 +2,7 @@
import asyncio
from agent_framework import ChatMessage, DataContent, Role, TextContent
from agent_framework import ChatMessage, Content, Role
from agent_framework.ollama import OllamaChatClient
"""
@@ -35,8 +35,8 @@ async def test_image() -> None:
message = ChatMessage(
role=Role.USER,
contents=[
TextContent(text="What's in this image?"),
DataContent(uri=image_uri, media_type="image/png"),
Content.from_text(text="What's in this image?"),
Content.from_uri(uri=image_uri, media_type="image/png"),
],
)
@@ -66,7 +66,7 @@ async def streaming_reasoning_example() -> None:
usage = content
print("\n")
if usage:
print(f"Usage: {usage.details}")
print(f"Usage: {usage.usage_details}")
async def main() -> None:
@@ -82,7 +82,7 @@ with open("path/to/your/image.jpg", "rb") as f:
image_uri = f"data:image/jpeg;base64,{image_base64}"
# Use in DataContent
DataContent(
Content.from_uri(
uri=image_uri,
media_type="image/jpeg"
)
@@ -96,7 +96,7 @@ with open("path/to/your/image.jpg", "rb") as f:
image_bytes = f.read()
# Use in DataContent
DataContent(
Content.from_data(
data=image_bytes,
media_type="image/jpeg"
)
@@ -2,7 +2,7 @@
import asyncio
from agent_framework import ChatMessage, DataContent, Role, TextContent
from agent_framework import ChatMessage, Content, Role
from agent_framework.azure import AzureOpenAIChatClient
from azure.identity import AzureCliCredential
@@ -26,7 +26,10 @@ async def test_image() -> None:
image_uri = create_sample_image()
message = ChatMessage(
role=Role.USER,
contents=[TextContent(text="What's in this image?"), DataContent(uri=image_uri, media_type="image/png")],
contents=[
Content.from_text(text="What's in this image?"),
Content.from_uri(uri=image_uri, media_type="image/png"),
],
)
response = await client.get_response(message)
@@ -3,7 +3,7 @@
import asyncio
from pathlib import Path
from agent_framework import ChatMessage, DataContent, Role, TextContent
from agent_framework import ChatMessage, Content, Role
from agent_framework.azure import AzureOpenAIResponsesClient
from azure.identity import AzureCliCredential
@@ -35,7 +35,10 @@ async def test_image() -> None:
image_uri = create_sample_image()
message = ChatMessage(
role=Role.USER,
contents=[TextContent(text="What's in this image?"), DataContent(uri=image_uri, media_type="image/png")],
contents=[
Content.from_text(text="What's in this image?"),
Content.from_uri(uri=image_uri, media_type="image/png"),
],
)
response = await client.get_response(message)
@@ -50,8 +53,8 @@ async def test_pdf() -> None:
message = ChatMessage(
role=Role.USER,
contents=[
TextContent(text="What information can you extract from this document?"),
DataContent(
Content.from_text(text="What information can you extract from this document?"),
Content.from_data(
data=pdf_bytes,
media_type="application/pdf",
additional_properties={"filename": "sample.pdf"},
@@ -5,7 +5,7 @@ import base64
import struct
from pathlib import Path
from agent_framework import ChatMessage, DataContent, Role, TextContent
from agent_framework import ChatMessage, Content, Role
from agent_framework.openai import OpenAIChatClient
ASSETS_DIR = Path(__file__).resolve().parent.parent / "sample_assets"
@@ -47,7 +47,10 @@ async def test_image() -> None:
image_uri = create_sample_image()
message = ChatMessage(
role=Role.USER,
contents=[TextContent(text="What's in this image?"), DataContent(uri=image_uri, media_type="image/png")],
contents=[
Content.from_text(text="What's in this image?"),
Content.from_uri(uri=image_uri, media_type="image/png"),
],
)
response = await client.get_response(message)
@@ -62,8 +65,8 @@ async def test_audio() -> None:
message = ChatMessage(
role=Role.USER,
contents=[
TextContent(text="What do you hear in this audio?"),
DataContent(uri=audio_uri, media_type="audio/wav"),
Content.from_text(text="What do you hear in this audio?"),
Content.from_uri(uri=audio_uri, media_type="audio/wav"),
],
)
@@ -79,8 +82,8 @@ async def test_pdf() -> None:
message = ChatMessage(
role=Role.USER,
contents=[
TextContent(text="What information can you extract from this document?"),
DataContent(
Content.from_text(text="What information can you extract from this document?"),
Content.from_data(
data=pdf_bytes, media_type="application/pdf", additional_properties={"filename": "employee_report.pdf"}
),
],
@@ -9,7 +9,7 @@ from agent_framework import (
AgentRunUpdateEvent,
ChatClientProtocol,
ChatMessage,
Contents,
Content,
Executor,
Role,
WorkflowBuilder,
@@ -155,7 +155,7 @@ class Worker(Executor):
if review.approved:
print("Worker: Response approved. Emitting to external consumer...")
contents: list[Contents] = []
contents: list[Content] = []
for message in request.agent_messages:
contents.extend(message.contents)