diff --git a/connectors-endpoints/anthropic-claude2.json b/connectors-endpoints/anthropic-claude2.json deleted file mode 100644 index f98f8d64..00000000 --- a/connectors-endpoints/anthropic-claude2.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "Anthropic-Claude2", - "connector_type": "anthropic-connector", - "uri": "", - "token": "", - "max_calls_per_second": 1, - "max_concurrency": 1, - "model": "claude-2", - "params": { - "timeout": 300, - "max_attempts": 3, - "temperature": 0.5, - "max_tokens_to_sample": 300 - } -} \ No newline at end of file diff --git a/connectors-endpoints/anthropic-claude4.5.json b/connectors-endpoints/anthropic-claude4.5.json new file mode 100644 index 00000000..bd7cf9c6 --- /dev/null +++ b/connectors-endpoints/anthropic-claude4.5.json @@ -0,0 +1,15 @@ +{ + "name": "Anthropic-Claude4.5", + "connector_type": "anthropic-connector", + "uri": "", + "token": "", + "max_calls_per_second": 1, + "max_concurrency": 1, + "model": "claude-sonnet-4-5-20250929", + "params": { + "timeout": 300, + "max_attempts": 3, + "temperature": 0.0, + "max_tokens": 64000 + } + } \ No newline at end of file diff --git a/connectors/anthropic-connector.py b/connectors/anthropic-connector.py index 2f7b0a9a..d6b31c5a 100644 --- a/connectors/anthropic-connector.py +++ b/connectors/anthropic-connector.py @@ -1,8 +1,7 @@ import os import anthropic -from anthropic import AI_PROMPT, HUMAN_PROMPT -from anthropic.types import Completion +from anthropic.types import Message from moonshot.src.connectors.connector import Connector, perform_retry from moonshot.src.connectors.connector_response import ConnectorResponse from moonshot.src.connectors_endpoints.connector_endpoint_arguments import ( @@ -38,16 +37,31 @@ async def get_response(self, prompt: str) -> ConnectorResponse: ConnectorResponse: An object containing the text response generated by the Anthropic model. """ connector_prompt = f"{self.pre_prompt}{prompt}{self.post_prompt}" + + # Build messages list + messages = [{"role": "user", "content": connector_prompt}] + # Merge self.optional_params with additional parameters new_params = { **self.optional_params, "model": self.model, - "prompt": f"{HUMAN_PROMPT}{connector_prompt}{AI_PROMPT}", + "messages": messages, } - response = await self._client.completions.create(**new_params) + + # Add system prompt if available + if self.system_prompt: + new_params["system"] = self.system_prompt + + # Validate that max_tokens is provided and is greater than 0 + # This assertion is to make the requirements from anthropic API clear to the user + # The anthropic API will raise an error if max_tokens is not provided or is less than 0 + if "max_tokens" not in new_params or new_params.get("max_tokens", 0) <= 0: + raise ValueError("max_tokens is required and must be greater than 0") + + response: Message = await self._client.messages.create(**new_params) return ConnectorResponse(response=await self._process_response(response)) - async def _process_response(self, response: Completion) -> str: + async def _process_response(self, response: Message) -> str: """ Process an HTTP response and extract relevant information as a string. @@ -56,9 +70,23 @@ async def _process_response(self, response: Completion) -> str: from the response body, headers, or other attributes. Args: - response (Completion): An HTTP response object containing the response data. + response (Message): An Anthropic Message response object containing the response data. Returns: str: A string representing the relevant information extracted from the response. """ - return response.completion[1:] + # Extract text from all text content blocks in the response + # Anthropic can return multiple content blocks (text, tool_use, etc.) + # We filter for text blocks and join them together + if not response.content: + return "" + + text_blocks = [] + for block in response.content: + # Check if this is a text block and extract its text + if hasattr(block, "type") and block.type == "text" and hasattr(block, "text"): + text_blocks.append(block.text) + + # We have decided to join text blocks with double newlines to separate paragraphs, + # whichever join we decide would have affected the result anyway + return "\n\n".join(text_blocks) if text_blocks else ""