Skip to content
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

Adding AnthropicVertexAI API support in the Anthropic LLM lib under oai #309

Merged
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
60 changes: 55 additions & 5 deletions autogen/oai/anthropic.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,27 @@

assistant = autogen.AssistantAgent("assistant", llm_config={"config_list": config_list})
```

Example usage for Anthropic VertexAI:

Install the `anthropic` package by running `pip install anthropic[vertex]`.
- https://docs.anthropic.com/en/docs/quickstart-guide

```python

import autogen
config_list = [
{
"model": "claude-3-5-sonnet-20240620-v1:0",
"gcp_project_id": "dummy_project_id",
"gcp_region": "us-west-2",
"gcp_auth_token": "dummy_auth_token",
"api_type": "anthropic",
}
]

assistant = autogen.AssistantAgent("assistant", llm_config={"config_list": config_list})
```python
"""

from __future__ import annotations
Expand All @@ -58,7 +79,7 @@
import warnings
from typing import Annotated, Any, Dict, List, Optional, Tuple, Union

from anthropic import Anthropic, AnthropicBedrock
from anthropic import Anthropic, AnthropicBedrock, AnthropicVertex
from anthropic import __version__ as anthropic_version
from anthropic.types import Completion, Message, TextBlock, ToolUseBlock
from openai.types.chat import ChatCompletion, ChatCompletionMessageToolCall
Expand Down Expand Up @@ -100,6 +121,9 @@ def __init__(self, **kwargs: Any):
self._aws_secret_key = kwargs.get("aws_secret_key", None)
self._aws_session_token = kwargs.get("aws_session_token", None)
self._aws_region = kwargs.get("aws_region", None)
self._gcp_project_id = kwargs.get("gcp_project_id", None)
self._gcp_region = kwargs.get("gcp_region", None)
self._gcp_auth_token = kwargs.get("gcp_auth_token", None)

if not self._api_key:
self._api_key = os.getenv("ANTHROPIC_API_KEY")
Expand All @@ -113,16 +137,30 @@ def __init__(self, **kwargs: Any):
if not self._aws_region:
self._aws_region = os.getenv("AWS_REGION")

if self._api_key is None and (
self._aws_access_key is None or self._aws_secret_key is None or self._aws_region is None
):
raise ValueError("API key or AWS credentials are required to use the Anthropic API.")
if not self._gcp_region:
self._gcp_region = os.getenv("GCP_REGION")

if self._api_key is None:
if self._aws_region:
if self._aws_access_key is None or self._aws_secret_key is None:
raise ValueError("API key or AWS credentials are required to use the Anthropic API.")
elif self._gcp_region:
if self._gcp_project_id is None or self._gcp_region is None:
raise ValueError("API key or GCP credentials are required to use the Anthropic API.")
else:
raise ValueError("API key or AWS credentials or GCP credentials are required to use the Anthropic API.")

if "response_format" in kwargs and kwargs["response_format"] is not None:
warnings.warn("response_format is not supported for Anthropic, it will be ignored.", UserWarning)

if self._api_key is not None:
self._client = Anthropic(api_key=self._api_key)
elif self._gcp_region is not None:
kw = {}
for i, p in enumerate(inspect.signature(AnthropicVertex).parameters):
if hasattr(self, f"_gcp_{p}"):
kw[p] = getattr(self, f"_gcp_{p}")
self._client = AnthropicVertex(**kw)
else:
self._client = AnthropicBedrock(
aws_access_key=self._aws_access_key,
Expand Down Expand Up @@ -182,6 +220,18 @@ def aws_session_token(self):
def aws_region(self):
return self._aws_region

@property
def gcp_project_id(self):
return self._gcp_project_id

@property
def gcp_region(self):
return self._gcp_region

@property
def gcp_auth_token(self):
return self._gcp_auth_token

def create(self, params: dict[str, Any]) -> ChatCompletion:
if "tools" in params:
converted_functions = self.convert_tools_to_functions(params["tools"])
Expand Down
11 changes: 10 additions & 1 deletion autogen/oai/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,13 @@ def _configure_openai_config_for_bedrock(self, config: dict[str, Any], openai_co
if key in config:
openai_config[key] = config[key]

def _configure_openai_config_for_vertextai(self, config: dict[str, Any], openai_config: dict[str, Any]) -> None:
"""Update openai_config with Google credentials from config."""
required_keys = ["gcp_project_id", "gcp_region", "gcp_auth_token"]
for key in required_keys:
if key in config:
openai_config[key] = config[key]

def _register_default_client(self, config: dict[str, Any], openai_config: dict[str, Any]) -> None:
"""Create a client with the given config to override openai_config,
after removing extra kwargs.
Expand Down Expand Up @@ -615,8 +622,10 @@ def _register_default_client(self, config: dict[str, Any], openai_config: dict[s
client = GeminiClient(response_format=response_format, **openai_config)
self._clients.append(client)
elif api_type is not None and api_type.startswith("anthropic"):
if "api_key" not in config:
if "api_key" not in config and "aws_region" in config:
self._configure_openai_config_for_bedrock(config, openai_config)
elif "api_key" not in config and "gcp_region" in config:
self._configure_openai_config_for_vertextai(config, openai_config)
if anthropic_import_exception:
raise ImportError("Please install `anthropic` to use Anthropic API.")
client = AnthropicClient(response_format=response_format, **openai_config)
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@
"jupyter-executor": jupyter_executor,
"types": types,
"long-context": ["llmlingua<0.3"],
"anthropic": ["anthropic>=0.23.1"],
"anthropic": ["anthropic[vertex]>=0.23.1"],
"cerebras": ["cerebras_cloud_sdk>=1.0.0"],
"mistral": ["mistralai>=1.0.1"],
"groq": ["groq>=0.9.0"],
Expand Down
24 changes: 23 additions & 1 deletion test/oai/test_anthropic.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def test_initialization_missing_api_key():
os.environ.pop("AWS_SECRET_KEY", None)
os.environ.pop("AWS_SESSION_TOKEN", None)
os.environ.pop("AWS_REGION", None)
with pytest.raises(ValueError, match="API key or AWS credentials are required to use the Anthropic API."):
with pytest.raises(ValueError, match="credentials are required to use the Anthropic API."):
AnthropicClient()

AnthropicClient(api_key="dummy_api_key")
Expand All @@ -76,6 +76,15 @@ def anthropic_client_with_aws_credentials():
)


@pytest.fixture()
def anthropic_client_with_vertexai_credentials():
return AnthropicClient(
gcp_project_id="dummy_project_id",
gcp_region="us-west-2",
gcp_auth_token="dummy_auth_token",
)


@pytest.mark.skipif(skip, reason=reason)
def test_intialization(anthropic_client):
assert anthropic_client.api_key == "dummy_api_key", "`api_key` should be correctly set in the config"
Expand All @@ -97,6 +106,19 @@ def test_intialization_with_aws_credentials(anthropic_client_with_aws_credential
), "`aws_region` should be correctly set in the config"


@pytest.mark.skipif(skip, reason=reason)
def test_initialization_with_vertexai_credentials(anthropic_client_with_vertexai_credentials):
assert (
anthropic_client_with_vertexai_credentials.gcp_project_id == "dummy_project_id"
), "`gcp_project_id` should be correctly set in the config"
assert (
anthropic_client_with_vertexai_credentials.gcp_region == "us-west-2"
), "`gcp_region` should be correctly set in the config"
assert (
anthropic_client_with_vertexai_credentials.gcp_auth_token == "dummy_auth_token"
), "`gcp_auth_token` should be correctly set in the config"


# Test cost calculation
@pytest.mark.skipif(skip, reason=reason)
def test_cost_calculation(mock_completion):
Expand Down
58 changes: 58 additions & 0 deletions website/docs/topics/non-openai-models/cloud-anthropic.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,64 @@
"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Alternative Anthropic VertexAI Client (GCP)\n",
"\n",
"To use the Anthropic VertexAI client in AutoGen, you need to configure it for use with Google Cloud Platform (GCP). Ensure you have the necessary project credentials and install the required package.\n",
"\n",
"Configuration\n",
"\n",
"The following configuration example demonstrates how to set up Anthropic VertexAI:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"\n",
"config_list_vertexai = [\n",
" {\n",
" \"model\": \"claude-3-5-sonnet-20240620-v1:0\",\n",
" \"gcp_project_id\": \"your_project_id\",\n",
" \"gcp_region\": \"us-west-2\", # Replace with your GCP region\n",
" \"gcp_auth_token\": None, # Optional: If not passed, Google Default Authentication will be used\n",
" \"api_type\": \"anthropic\",\n",
" }\n",
"]\n",
"\n",
"assistant = autogen.AssistantAgent(\n",
" \"assistant\",\n",
" llm_config={\n",
" \"config_list\": config_list_vertexai,\n",
" },\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Alternative Anthropic VertexAI Client (Google Default Authentication)\n",
"\n",
"If the `gcp_auth_token` is not provided in the configuration, the client will use Google’s default authentication mechanism. This requires the appropriate credentials to be configured in your environment, such as:\n",
"\n",
"- Service account key: You can set the `GOOGLE_APPLICATION_CREDENTIALS` environment variable to point to your service account key file.\n",
"- Cloud Shell or GCP Compute Engine: When running in a GCP-managed environment, default authentication is automatically applied.",
"\n",
"\n",
"Example of setting up the environment variable:\n",
"\n",
"export GOOGLE_APPLICATION_CREDENTIALS=\"/path/to/your/service-account-key.json\"\n",
"\n",
"This allows seamless integration without explicitly specifying the authentication token in your code."
]
},
{
"cell_type": "markdown",
"metadata": {},
Expand Down
Loading