Skip to content

Commit 2f27461

Browse files
authored
Merge pull request #1111 from Mirascope/mira-286
v2: add response.to_tool, stream.to_tool, remove ContextTool
2 parents d22169f + 4b5e439 commit 2f27461

File tree

11 files changed

+49
-93
lines changed

11 files changed

+49
-93
lines changed

python/mirascope/llm/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
RateLimitError,
5757
ServerError,
5858
TimeoutError,
59+
ToolNotFoundError,
5960
)
6061
from .messages import AssistantMessage, Message, SystemMessage, UserMessage
6162
from .models import LLM, model
@@ -120,6 +121,7 @@
120121
"ToolCall",
121122
"ToolCallChunk",
122123
"ToolDef",
124+
"ToolNotFoundError",
123125
"ToolOutput",
124126
"UserContent",
125127
"UserMessage",

python/mirascope/llm/exceptions.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ class NotFoundError(APIError):
4242
"""Raised when requested resource is not found (404)."""
4343

4444

45+
class ToolNotFoundError(APIError):
46+
"""Raised if a tool_call cannot be converted to any corresponding tool."""
47+
48+
4549
class RateLimitError(APIError):
4650
"""Raised when rate limits are exceeded (429)."""
4751

python/mirascope/llm/responses/response.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
from ..content import AssistantContent, Audio, Image, Thinking, ToolCall
1515
from ..messages import Message
16+
from ..tools import Tool
1617
from .finish_reason import FinishReason
1718
from .usage import Usage
1819

@@ -67,11 +68,11 @@ class Response(Generic[T]):
6768
cost: Decimal | None
6869
"""The cost of the request to the LLM, if available."""
6970

70-
tools: Sequence[ToolCall]
71+
tool_calls: Sequence[ToolCall]
7172
"""The tools the LLM wants called on its behalf, if any."""
7273

7374
@property
74-
def tool(self) -> ToolCall | None:
75+
def tool_call(self) -> ToolCall | None:
7576
"""Returns the first tool used in the response, if any."""
7677
raise NotImplementedError()
7778

@@ -95,6 +96,14 @@ def thinking(self) -> Thinking | None:
9596
"""Returns the first thinking in the response content, if any."""
9697
raise NotImplementedError()
9798

99+
def tool(self, tool_call: ToolCall) -> Tool:
100+
"""Converts a ToolCall into a Tool. May raise llm.ToolNotFoundError."""
101+
raise NotImplementedError()
102+
103+
def tools(self, tool_calls: list[ToolCall]) -> list[Tool]:
104+
"""Converts a list of ToolCalls into a list of Tools. May raise llm.ToolNotFoundError."""
105+
raise NotImplementedError()
106+
98107
def format(self) -> T:
99108
"""Format the response according to the response format parser.
100109

python/mirascope/llm/streams/base.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
from decimal import Decimal
44

5+
from ..content import ToolCall
56
from ..responses import FinishReason, Response, Usage
7+
from ..tools import Tool
68

79

810
class BaseStream:
@@ -39,3 +41,11 @@ def to_response(self) -> Response:
3941
4042
"""
4143
raise NotImplementedError()
44+
45+
def tool(self, tool_call: ToolCall) -> Tool:
46+
"""Converts a ToolCall into a Tool. May raise llm.ToolNotFoundError."""
47+
raise NotImplementedError()
48+
49+
def tools(self, tool_calls: list[ToolCall]) -> list[Tool]:
50+
"""Converts a list of ToolCalls into a list of Tools. May raise llm.ToolNotFoundError."""
51+
raise NotImplementedError()

python/mirascope/llm/tools/__init__.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
11
"""The Tools module for LLMs."""
22

3-
from .base_tool import BaseTool
43
from .base_tool_def import BaseToolDef
5-
from .context_tool import ContextTool
64
from .context_tool_def import ContextToolDef
75
from .decorator import ContextToolDecorator, ToolDecorator, tool
86
from .tool import Tool
97
from .tool_def import ToolDef
108

119
__all__ = [
12-
"BaseTool",
1310
"BaseToolDef",
14-
"ContextTool",
1511
"ContextToolDecorator",
1612
"ContextToolDef",
1713
"Tool",

python/mirascope/llm/tools/base_tool.py

Lines changed: 0 additions & 28 deletions
This file was deleted.

python/mirascope/llm/tools/base_tool_def.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""The `BaseToolDef` class for defining tools that LLMs can request be called."""
22

33
from dataclasses import dataclass
4-
from typing import Any, Generic, ParamSpec
4+
from typing import Generic, ParamSpec
55

66
from typing_extensions import TypeVar
77

@@ -28,7 +28,7 @@ class BaseToolDef(Generic[P, R]):
2828
description: str
2929
"""Description of what the tool does, extracted from the function's docstring."""
3030

31-
parameters: dict[str, Any]
31+
parameters: dict[str, Jsonable]
3232
"""JSON Schema describing the parameters accepted by the tool."""
3333

3434
strict: bool

python/mirascope/llm/tools/context_tool.py

Lines changed: 0 additions & 45 deletions
This file was deleted.

python/mirascope/llm/tools/context_tool_def.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,14 @@
44

55
from collections.abc import Callable
66
from dataclasses import dataclass
7-
from typing import TYPE_CHECKING, Concatenate, Generic, ParamSpec, TypeGuard
7+
from typing import Concatenate, Generic, ParamSpec, TypeGuard
88

99
from typing_extensions import TypeVar
1010

1111
from ..context import Context
1212
from ..types import Jsonable
13-
from .base_tool import BaseTool
1413
from .base_tool_def import BaseToolDef
15-
16-
if TYPE_CHECKING:
17-
from .context_tool import ContextTool
14+
from .tool import Tool
1815

1916
P = ParamSpec("P")
2017
R = TypeVar("R", bound=Jsonable)
@@ -45,7 +42,7 @@ def __call__(self, ctx: Context[DepsT], *args: P.args, **kwargs: P.kwargs) -> R:
4542
"""
4643
return self.fn(ctx, *args, **kwargs)
4744

48-
def defines(self, tool: BaseTool) -> TypeGuard[ContextTool[P, R, DepsT]]:
45+
def defines(self, tool: Tool) -> TypeGuard[Tool[P, R, DepsT]]:
4946
"""Check if this ToolDef matches a specific Tool instance.
5047
5148
This method is used to ensure that the ToolDef was created from a specific

python/mirascope/llm/tools/tool.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,38 @@
77
"""
88

99
from dataclasses import dataclass
10-
from typing import ParamSpec, TypeVar
10+
from typing import Generic, ParamSpec
11+
12+
from typing_extensions import TypeVar
1113

1214
from ..content import ToolOutput
1315
from ..types import Jsonable
14-
from .base_tool import BaseTool
16+
from .context_tool_def import ContextToolDef
1517
from .tool_def import ToolDef
1618

1719
P = ParamSpec("P")
1820
R = TypeVar("R", bound=Jsonable)
21+
DepsT = TypeVar("DepsT", default=None)
1922

2023

2124
@dataclass
22-
class Tool(BaseTool[P, R]):
25+
class Tool(Generic[P, R, DepsT]):
2326
"""Tool instance with arguments provided by an LLM.
2427
2528
When an LLM uses a tool during a call, a Tool instance is created with the specific
2629
arguments provided by the LLM.
2730
"""
2831

29-
tool_def: ToolDef[P, R]
32+
name: str
33+
"""The name of the tool being called."""
34+
35+
args: dict[str, Jsonable]
36+
"""The arguments provided by the LLM for this tool call."""
37+
38+
id: str
39+
"""Unique identifier for this tool call."""
40+
41+
tool_def: ToolDef[P, R] | ContextToolDef[P, R, DepsT]
3042
"""The ToolDef that defines the tool being called."""
3143

3244
def call(self) -> ToolOutput[R]:

0 commit comments

Comments
 (0)