From b73b7fd777c19d222b2a8031579541bfefd2c3d9 Mon Sep 17 00:00:00 2001 From: Nathan McCandlish <39928272+nsmccandlish@users.noreply.github.com> Date: Tue, 22 Oct 2024 10:08:13 -0700 Subject: [PATCH] Revert "upgrade sdk to supported version for computer use demo(#36)" This reverts commit 88c1b7115242cba07707043503fcca458176d090. --- computer-use-demo/computer_use_demo/loop.py | 47 +++++++++++++------ .../computer_use_demo/requirements.txt | 2 +- .../computer_use_demo/tools/base.py | 35 ++++++++++++-- .../computer_use_demo/tools/bash.py | 13 +---- .../computer_use_demo/tools/collection.py | 6 +-- .../computer_use_demo/tools/computer.py | 17 ++----- .../computer_use_demo/tools/edit.py | 12 +---- 7 files changed, 72 insertions(+), 60 deletions(-) diff --git a/computer-use-demo/computer_use_demo/loop.py b/computer-use-demo/computer_use_demo/loop.py index a2d9f212..317a70ca 100644 --- a/computer-use-demo/computer_use_demo/loop.py +++ b/computer-use-demo/computer_use_demo/loop.py @@ -10,6 +10,8 @@ from anthropic import Anthropic, AnthropicBedrock, AnthropicVertex, APIResponse from anthropic.types import ( + MessageParam, + ToolParam, ToolResultBlockParam, ) from anthropic.types.beta import ( @@ -19,6 +21,7 @@ BetaMessage, BetaMessageParam, BetaTextBlockParam, + BetaToolParam, BetaToolResultBlockParam, ) @@ -92,25 +95,39 @@ async def sampling_loop( if only_n_most_recent_images: _maybe_filter_to_n_most_recent_images(messages, only_n_most_recent_images) - if provider == APIProvider.ANTHROPIC: - client = Anthropic(api_key=api_key) - elif provider == APIProvider.VERTEX: - client = AnthropicVertex() - elif provider == APIProvider.BEDROCK: - client = AnthropicBedrock() - # Call the API # we use raw_response to provide debug information to streamlit. Your # implementation may be able call the SDK directly with: # `response = client.messages.create(...)` instead. - raw_response = client.beta.messages.with_raw_response.create( - max_tokens=max_tokens, - messages=messages, - model=model, - system=system, - tools=tool_collection.to_params(), - betas=["computer-use-2024-10-22"], - ) + if provider == APIProvider.ANTHROPIC: + raw_response = Anthropic( + api_key=api_key + ).beta.messages.with_raw_response.create( + max_tokens=max_tokens, + messages=messages, + model=model, + system=system, + tools=cast(list[BetaToolParam], tool_collection.to_params()), + extra_headers={"anthropic-beta": BETA_FLAG}, + ) + elif provider == APIProvider.VERTEX: + raw_response = AnthropicVertex().messages.with_raw_response.create( + max_tokens=max_tokens, + messages=cast(list[MessageParam], messages), + model=model, + system=system, + tools=cast(list[ToolParam], tool_collection.to_params()), + extra_headers={"anthropic-beta": BETA_FLAG}, + ) + elif provider == APIProvider.BEDROCK: + raw_response = AnthropicBedrock().messages.with_raw_response.create( + max_tokens=max_tokens, + messages=cast(list[MessageParam], messages), + model=model, + system=system, + tools=cast(list[ToolParam], tool_collection.to_params()), + extra_body={"anthropic_beta": [BETA_FLAG]}, + ) api_response_callback(cast(APIResponse[BetaMessage], raw_response)) diff --git a/computer-use-demo/computer_use_demo/requirements.txt b/computer-use-demo/computer_use_demo/requirements.txt index d3e16af7..8b3760d1 100644 --- a/computer-use-demo/computer_use_demo/requirements.txt +++ b/computer-use-demo/computer_use_demo/requirements.txt @@ -1,5 +1,5 @@ streamlit>=1.38.0 -anthropic[bedrock,vertex]>=0.37.0 +anthropic[bedrock,vertex]>=0.36.2 jsonschema==4.22.0 boto3>=1.28.57 google-auth<3,>=2 diff --git a/computer-use-demo/computer_use_demo/tools/base.py b/computer-use-demo/computer_use_demo/tools/base.py index d6f13712..37eafbf0 100644 --- a/computer-use-demo/computer_use_demo/tools/base.py +++ b/computer-use-demo/computer_use_demo/tools/base.py @@ -1,23 +1,48 @@ from abc import ABCMeta, abstractmethod from dataclasses import dataclass, fields, replace -from typing import Any +from typing import Any, ClassVar, Literal, Optional, Required, TypedDict -from anthropic.types.beta import BetaToolUnionParam +APIToolType = Literal["computer_20241022", "text_editor_20241022", "bash_20241022"] +APIToolName = Literal["computer", "str_replace_editor", "bash"] + + +class AnthropicAPIToolParam(TypedDict): + """API shape for Anthropic-defined tools.""" + + name: Required[APIToolName] + type: Required[APIToolType] + + +class ComputerToolOptions(TypedDict): + display_height_px: Required[int] + display_width_px: Required[int] + display_number: Optional[int] class BaseAnthropicTool(metaclass=ABCMeta): """Abstract base class for Anthropic-defined tools.""" + name: ClassVar[APIToolName] + api_type: ClassVar[APIToolType] + + @property + def options(self) -> ComputerToolOptions | None: + return None + @abstractmethod def __call__(self, **kwargs) -> Any: """Executes the tool with the given arguments.""" ... - @abstractmethod def to_params( self, - ) -> BetaToolUnionParam: - raise NotImplementedError + ) -> dict: # -> AnthropicToolParam & Optional[ComputerToolOptions] + """Creates the shape necessary to this tool to the Anthropic API.""" + return { + "name": self.name, + "type": self.api_type, + **(self.options or {}), + } @dataclass(kw_only=True, frozen=True) diff --git a/computer-use-demo/computer_use_demo/tools/bash.py b/computer-use-demo/computer_use_demo/tools/bash.py index db13db00..e5d3df50 100644 --- a/computer-use-demo/computer_use_demo/tools/bash.py +++ b/computer-use-demo/computer_use_demo/tools/bash.py @@ -1,8 +1,5 @@ import asyncio import os -from typing import ClassVar, Literal - -from anthropic.types.beta import BetaToolBash20241022Param from .base import BaseAnthropicTool, CLIResult, ToolError, ToolResult @@ -110,8 +107,8 @@ class BashTool(BaseAnthropicTool): """ _session: _BashSession | None - name: ClassVar[Literal["bash"]] = "bash" - api_type: ClassVar[Literal["bash_20241022"]] = "bash_20241022" + name = "bash" + api_type = "bash_20241022" def __init__(self): self._session = None @@ -136,9 +133,3 @@ async def __call__( return await self._session.run(command) raise ToolError("no command provided.") - - def to_params(self) -> BetaToolBash20241022Param: - return { - "type": self.api_type, - "name": self.name, - } diff --git a/computer-use-demo/computer_use_demo/tools/collection.py b/computer-use-demo/computer_use_demo/tools/collection.py index c4e8c95c..12e52123 100644 --- a/computer-use-demo/computer_use_demo/tools/collection.py +++ b/computer-use-demo/computer_use_demo/tools/collection.py @@ -2,8 +2,6 @@ from typing import Any -from anthropic.types.beta import BetaToolUnionParam - from .base import ( BaseAnthropicTool, ToolError, @@ -17,11 +15,11 @@ class ToolCollection: def __init__(self, *tools: BaseAnthropicTool): self.tools = tools - self.tool_map = {tool.to_params()["name"]: tool for tool in tools} + self.tool_map = {tool.name: tool for tool in tools} def to_params( self, - ) -> list[BetaToolUnionParam]: + ) -> list[dict]: # -> List[AnthropicToolParam & Optional[ComputerToolOptions]] return [tool.to_params() for tool in self.tools] async def run(self, *, name: str, tool_input: dict[str, Any]) -> ToolResult: diff --git a/computer-use-demo/computer_use_demo/tools/computer.py b/computer-use-demo/computer_use_demo/tools/computer.py index 0b5c77db..7e48c981 100644 --- a/computer-use-demo/computer_use_demo/tools/computer.py +++ b/computer-use-demo/computer_use_demo/tools/computer.py @@ -8,9 +8,7 @@ from typing import Literal, TypedDict from uuid import uuid4 -from anthropic.types.beta import BetaToolComputerUse20241022Param - -from .base import BaseAnthropicTool, ToolError, ToolResult +from .base import BaseAnthropicTool, ComputerToolOptions, ToolError, ToolResult from .run import run OUTPUT_DIR = "/tmp/outputs" @@ -51,12 +49,6 @@ class ScalingSource(StrEnum): API = "api" -class ComputerToolOptions(TypedDict): - display_height_px: int - display_width_px: int - display_number: int | None - - def chunks(s: str, chunk_size: int) -> list[str]: return [s[i : i + chunk_size] for i in range(0, len(s), chunk_size)] @@ -67,8 +59,8 @@ class ComputerTool(BaseAnthropicTool): The tool parameters are defined by Anthropic and are not editable. """ - name: Literal["computer"] = "computer" - api_type: Literal["computer_20241022"] = "computer_20241022" + name = "computer" + api_type = "computer_20241022" width: int height: int display_num: int | None @@ -87,9 +79,6 @@ def options(self) -> ComputerToolOptions: "display_number": self.display_num, } - def to_params(self) -> BetaToolComputerUse20241022Param: - return {"name": self.name, "type": self.api_type, **self.options} - def __init__(self): super().__init__() diff --git a/computer-use-demo/computer_use_demo/tools/edit.py b/computer-use-demo/computer_use_demo/tools/edit.py index 3cca1f36..d0609f9b 100644 --- a/computer-use-demo/computer_use_demo/tools/edit.py +++ b/computer-use-demo/computer_use_demo/tools/edit.py @@ -2,8 +2,6 @@ from pathlib import Path from typing import Literal, get_args -from anthropic.types.beta import BetaToolTextEditor20241022Param - from .base import BaseAnthropicTool, CLIResult, ToolError, ToolResult from .run import maybe_truncate, run @@ -23,8 +21,8 @@ class EditTool(BaseAnthropicTool): The tool parameters are defined by Anthropic and are not editable. """ - api_type: Literal["text_editor_20241022"] = "text_editor_20241022" - name: Literal["str_replace_editor"] = "str_replace_editor" + api_type = "text_editor_20241022" + name = "str_replace_editor" _file_history: dict[Path, list[str]] @@ -32,12 +30,6 @@ def __init__(self): self._file_history = defaultdict(list) super().__init__() - def to_params(self) -> BetaToolTextEditor20241022Param: - return { - "name": self.name, - "type": self.api_type, - } - async def __call__( self, *,