diff --git a/.env.example b/.env.example index f3ce08d..48f1c26 100644 --- a/.env.example +++ b/.env.example @@ -12,6 +12,9 @@ LLM_PROVIDER=openai # default # or # LLM_PROVIDER=google # GOOGLE_API_KEY=your-google-api-key +# or +# LLM_PROVIDER=anthropic +# ANTHROPIC_API_KEY=your-anthropic-api-key # uncomment and unset these environment variables to connect to the local dev server # TEMPORAL_ADDRESS=namespace.acct.tmprl.cloud:7233 diff --git a/README.md b/README.md index faf0a98..04821d3 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ The agent can use either OpenAI's GPT-4o, Google Gemini, or a local LLM via Olla - `LLM_PROVIDER=openai` for OpenAI's GPT-4o - `LLM_PROVIDER=google` for Google Gemini +- `LLM_PROVIDER=anthropic` for Anthropic - `LLM_PROVIDER=ollama` for the local LLM via Ollama (not recommended for this use case) ### Option 1: OpenAI Configuration @@ -33,7 +34,14 @@ To use Google Gemini: 1. Obtain a Google API key and set it in the `GOOGLE_API_KEY` environment variable in `.env`. 2. Set `LLM_PROVIDER=google` in your `.env` file. -### Option 3: Local LLM via Ollama (not recommended) +### Option 3: Anthropic + +To use Anthropic: + +1. Obtain an Anthropic API key and set it in the `ANTHROPIC_API_KEY` environment variable in `.env`. +2. Set `LLM_PROVIDER=anthropic` in your `.env` file. + +### Option 4: Local LLM via Ollama (not recommended) To use a local LLM with Ollama: diff --git a/activities/tool_activities.py b/activities/tool_activities.py index 7acda91..375bd76 100644 --- a/activities/tool_activities.py +++ b/activities/tool_activities.py @@ -8,6 +8,7 @@ from temporalio.common import RawValue import os from datetime import datetime import google.generativeai as genai +import anthropic @dataclass @@ -25,6 +26,8 @@ class ToolActivities: return self.prompt_llm_ollama(input) elif llm_provider == "google": return self.prompt_llm_google(input) + elif llm_provider == "anthropic": + return self.prompt_llm_anthropic(input) else: return self.prompt_llm_openai(input) @@ -32,7 +35,7 @@ class ToolActivities: client = OpenAI( api_key=os.environ.get( "OPENAI_API_KEY" - ), # This is the default and can be omitted + ), ) messages = [ @@ -123,6 +126,34 @@ class ToolActivities: return data + def prompt_llm_anthropic(self, input: ToolPromptInput) -> dict: + api_key = os.environ.get("ANTHROPIC_API_KEY") + if not api_key: + raise ValueError("ANTHROPIC_API_KEY is not set in the environment variables.") + + client = anthropic.Anthropic(api_key=api_key) + + response = client.messages.create( + model="claude-3-5-sonnet-20241022", + max_tokens=1024, + system=input.context_instructions, + messages=input.prompt + ) + + response_content = response.content[0].text + print(f"Anthropic response: {response_content}") + + # Use the new sanitize function + response_content = self.sanitize_json_response(response_content) + + try: + data = json.loads(response_content) + except json.JSONDecodeError as e: + print(f"Invalid JSON: {e}") + raise json.JSONDecodeError + + return data + def sanitize_json_response(self, response_content: str) -> str: """ Extracts the JSON block from the response content as a string. diff --git a/poetry.lock b/poetry.lock index 11faa82..d8a9587 100644 --- a/poetry.lock +++ b/poetry.lock @@ -11,6 +11,30 @@ files = [ {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, ] +[[package]] +name = "anthropic" +version = "0.45.0" +description = "The official Python library for the anthropic API" +optional = false +python-versions = ">=3.8" +files = [ + {file = "anthropic-0.45.0-py3-none-any.whl", hash = "sha256:f36aff71d2c232945e64d1970be68a91b05a2ef5e3afa6c1ff195c3303a95ad3"}, + {file = "anthropic-0.45.0.tar.gz", hash = "sha256:4e8541dc355332090bfc51b84549c19b649a13a23dbd6bd68e1d012e08551025"}, +] + +[package.dependencies] +anyio = ">=3.5.0,<5" +distro = ">=1.7.0,<2" +httpx = ">=0.23.0,<1" +jiter = ">=0.4.0,<1" +pydantic = ">=1.9.0,<3" +sniffio = "*" +typing-extensions = ">=4.10,<5" + +[package.extras] +bedrock = ["boto3 (>=1.28.57)", "botocore (>=1.31.57)"] +vertex = ["google-auth (>=2,<3)"] + [[package]] name = "anyio" version = "4.5.2" @@ -1375,4 +1399,4 @@ standard = ["colorama (>=0.4)", "httptools (>=0.6.3)", "python-dotenv (>=0.13)", [metadata] lock-version = "2.0" python-versions = ">=3.9,<4.0" -content-hash = "6607357cf7851b278f44b13b3eccbe4f5309d8c038bba3bdc2114b5989832ba2" +content-hash = "a6b005e6cf77139e266ddf6b3263890f31a7b8813b3b5db95831d5fdb4d20239" diff --git a/pyproject.toml b/pyproject.toml index 908e4ba..1714482 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,6 +29,7 @@ python-dotenv = "^1.0.1" openai = "^1.59.2" stripe = "^11.4.1" google-generativeai = "^0.8.4" +anthropic = "^0.45.0" [tool.poetry.group.dev.dependencies] pytest = "^7.3"