Skip to content
Merged
Show file tree
Hide file tree
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: 76 additions & 0 deletions bindings/python/examples/tool_calls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import asyncio
from typing import Annotated

from pydantic import BaseModel

from uzu import (
ChatConfig,
ChatMessage,
ChatReplyConfig,
Engine,
EngineConfig,
SamplingMethod,
SamplingPolicy,
uzu_tool_function,
)


class Coordinate(BaseModel):
"""A geographic coordinate.

Attributes:
latitude: Latitude in decimal degrees.
longitude: Longitude in decimal degrees.
"""

latitude: float
longitude: Annotated[float, "Longitude in decimal degrees."]


@uzu_tool_function(name="get_location", description="Return the current location in coordinates")
def get_current_location() -> Coordinate:
return Coordinate(latitude=51.5074, longitude=-0.1278)


@uzu_tool_function
def get_current_temperature(
latitude: float,
longitude: Annotated[float, "Longitude in decimal degrees."],
) -> float:
"""Return the temperature at the provided coordinates.

Args:
latitude: Latitude in decimal degrees.
longitude: This is overridden by the Annotated description.
"""
_ = latitude, longitude
return 25.0


async def main() -> None:
engine = await Engine.create(EngineConfig.create())
model = await engine.model("mlx-community/Qwen3.5-9B-MLX-8bit")
if model is None:
raise RuntimeError("Model not found")

async for update in (await engine.download(model)).iterator():
print(f"Download progress: {update.progress}")

session = await engine.chat(model, ChatConfig.create())
await session.add_tool(get_current_location)
await session.add_tool(get_current_temperature)

messages = [
ChatMessage.system().with_text("You are a helpful assistant"),
ChatMessage.user().with_text("What temperature is it now at my location?"),
]
config = ChatReplyConfig.create().with_sampling_policy(SamplingPolicy.Custom(method=SamplingMethod.Greedy()))
replies = await session.reply(messages, config)
if replies:
message = replies[-1].message
print(f"Reasoning: {message.reasoning or ''}")
print(f"Text: {message.text or ''}")


if __name__ == "__main__":
asyncio.run(main())
5 changes: 4 additions & 1 deletion bindings/python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ classifiers = [
"Topic :: Scientific/Engineering :: Artificial Intelligence",
]
dynamic = ["version"]
dependencies = [
"docstring-parser>=0.17.0",
"pydantic>=2.13.3",
]
Comment thread
agolokoz marked this conversation as resolved.

[project.urls]
Homepage = "https://trymirai.com"
Expand All @@ -35,7 +39,6 @@ Issues = "https://github.com/trymirai/uzu/issues"

[project.optional-dependencies]
dev = ["pytest>=8.3.4", "ruff>=0.14.0"]
examples = ["pydantic>=2.13.3"]

[tool.maturin]
features = ["bindings-pyo3"]
Expand Down
1 change: 1 addition & 0 deletions bindings/python/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Loading
Loading