Skip to content

[python-sdk] add support for multimodal messages #196

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
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 74 additions & 2 deletions python-sdk/ag_ui/core/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
This module contains the types for the Agent User Interaction Protocol Python SDK.
"""

from typing import Annotated, Any, List, Literal, Optional, Union
from typing import Annotated, Any, Iterable, List, Literal, Optional, Required, TypeAlias, Union

from pydantic import BaseModel, ConfigDict, Field
from pydantic.alias_generators import to_camel
Expand Down Expand Up @@ -46,6 +46,77 @@ class BaseMessage(ConfiguredBaseModel):
name: Optional[str] = None


class FileWithBytes(ConfiguredBaseModel):
"""
Define the variant where 'bytes' is present and 'uri' is absent
"""

bytes: str
"""
base64 encoded content of the file
"""
mimeType: str | None = None
"""
Optional mimeType for the file
"""
name: str | None = None
"""
Optional name for the file
"""

class FileWithUri(ConfiguredBaseModel):
"""
Define the variant where 'uri' is present and 'bytes' is absent
"""

mimeType: str | None = None
"""
Optional mimeType for the file
"""
name: str | None = None
"""
Optional name for the file
"""
uri: str
"""
URL for the File content
"""

class FilePart(ConfiguredBaseModel):
"""
Represents a File segment within parts.
"""

file: FileWithBytes | FileWithUri
"""
File content either as url or bytes
"""
type: Literal["file"] = "file"
"""
Part type - file for FileParts
"""
metadata: dict[str, Any] | None = None
"""
Optional metadata associated with the part.
"""

class ImagePart(FilePart):
type: Literal["image"] = "image"

class AudioPart(FilePart):
type: Literal["audio"] = "audio"

class TextPart(ConfiguredBaseModel):
type: Literal["text"] = "text"
text: str

MultipleModalPart: TypeAlias = Union[
TextPart,
AudioPart,
ImagePart,
FilePart,
]

class DeveloperMessage(BaseMessage):
"""
A developer message.
Expand All @@ -68,14 +139,15 @@ class AssistantMessage(BaseMessage):
"""
role: Literal["assistant"] = "assistant" # pyright: ignore[reportIncompatibleVariableOverride]
tool_calls: Optional[List[ToolCall]] = None
content: Optional[str | Iterable[MultipleModalPart]] = None


class UserMessage(BaseMessage):
"""
A user message.
"""
role: Literal["user"] = "user" # pyright: ignore[reportIncompatibleVariableOverride]
content: str
content: Required[str | Iterable[MultipleModalPart]] = None


class ToolMessage(ConfiguredBaseModel):
Expand Down