205 lines
6.7 KiB
Python
205 lines
6.7 KiB
Python
|
|
"""
|
||
|
|
Anthropic Skills API configuration and transformations
|
||
|
|
"""
|
||
|
|
|
||
|
|
from typing import Any, Dict, Optional, Tuple
|
||
|
|
|
||
|
|
import httpx
|
||
|
|
|
||
|
|
from litellm._logging import verbose_logger
|
||
|
|
from litellm.llms.base_llm.skills.transformation import (
|
||
|
|
BaseSkillsAPIConfig,
|
||
|
|
LiteLLMLoggingObj,
|
||
|
|
)
|
||
|
|
from litellm.types.llms.anthropic_skills import (
|
||
|
|
CreateSkillRequest,
|
||
|
|
DeleteSkillResponse,
|
||
|
|
ListSkillsParams,
|
||
|
|
ListSkillsResponse,
|
||
|
|
Skill,
|
||
|
|
)
|
||
|
|
from litellm.types.router import GenericLiteLLMParams
|
||
|
|
from litellm.types.utils import LlmProviders
|
||
|
|
|
||
|
|
|
||
|
|
class AnthropicSkillsConfig(BaseSkillsAPIConfig):
|
||
|
|
"""Anthropic-specific Skills API configuration"""
|
||
|
|
|
||
|
|
@property
|
||
|
|
def custom_llm_provider(self) -> LlmProviders:
|
||
|
|
return LlmProviders.ANTHROPIC
|
||
|
|
|
||
|
|
def validate_environment(
|
||
|
|
self, headers: dict, litellm_params: Optional[GenericLiteLLMParams]
|
||
|
|
) -> dict:
|
||
|
|
"""Add Anthropic-specific headers"""
|
||
|
|
from litellm.llms.anthropic.common_utils import AnthropicModelInfo
|
||
|
|
|
||
|
|
# Get API key
|
||
|
|
api_key = None
|
||
|
|
if litellm_params:
|
||
|
|
api_key = litellm_params.api_key
|
||
|
|
api_key = AnthropicModelInfo.get_api_key(api_key)
|
||
|
|
|
||
|
|
if not api_key:
|
||
|
|
raise ValueError("ANTHROPIC_API_KEY is required for Skills API")
|
||
|
|
|
||
|
|
# Add required headers
|
||
|
|
headers["x-api-key"] = api_key
|
||
|
|
headers["anthropic-version"] = "2023-06-01"
|
||
|
|
|
||
|
|
# Add beta header for skills API
|
||
|
|
from litellm.constants import ANTHROPIC_SKILLS_API_BETA_VERSION
|
||
|
|
|
||
|
|
if "anthropic-beta" not in headers:
|
||
|
|
headers["anthropic-beta"] = ANTHROPIC_SKILLS_API_BETA_VERSION
|
||
|
|
elif isinstance(headers["anthropic-beta"], list):
|
||
|
|
if ANTHROPIC_SKILLS_API_BETA_VERSION not in headers["anthropic-beta"]:
|
||
|
|
headers["anthropic-beta"].append(ANTHROPIC_SKILLS_API_BETA_VERSION)
|
||
|
|
elif isinstance(headers["anthropic-beta"], str):
|
||
|
|
if ANTHROPIC_SKILLS_API_BETA_VERSION not in headers["anthropic-beta"]:
|
||
|
|
headers["anthropic-beta"] = [
|
||
|
|
headers["anthropic-beta"],
|
||
|
|
ANTHROPIC_SKILLS_API_BETA_VERSION,
|
||
|
|
]
|
||
|
|
|
||
|
|
headers["content-type"] = "application/json"
|
||
|
|
|
||
|
|
return headers
|
||
|
|
|
||
|
|
def get_complete_url(
|
||
|
|
self,
|
||
|
|
api_base: Optional[str],
|
||
|
|
endpoint: str,
|
||
|
|
skill_id: Optional[str] = None,
|
||
|
|
) -> str:
|
||
|
|
"""Get complete URL for Anthropic Skills API"""
|
||
|
|
from litellm.llms.anthropic.common_utils import AnthropicModelInfo
|
||
|
|
|
||
|
|
if api_base is None:
|
||
|
|
api_base = AnthropicModelInfo.get_api_base()
|
||
|
|
|
||
|
|
if skill_id:
|
||
|
|
return f"{api_base}/v1/skills/{skill_id}"
|
||
|
|
return f"{api_base}/v1/{endpoint}"
|
||
|
|
|
||
|
|
def transform_create_skill_request(
|
||
|
|
self,
|
||
|
|
create_request: CreateSkillRequest,
|
||
|
|
litellm_params: GenericLiteLLMParams,
|
||
|
|
headers: dict,
|
||
|
|
) -> Dict:
|
||
|
|
"""Transform create skill request for Anthropic"""
|
||
|
|
verbose_logger.debug("Transforming create skill request: %s", create_request)
|
||
|
|
|
||
|
|
# Anthropic expects the request body directly
|
||
|
|
request_body = {k: v for k, v in create_request.items() if v is not None}
|
||
|
|
|
||
|
|
return request_body
|
||
|
|
|
||
|
|
def transform_create_skill_response(
|
||
|
|
self,
|
||
|
|
raw_response: httpx.Response,
|
||
|
|
logging_obj: LiteLLMLoggingObj,
|
||
|
|
) -> Skill:
|
||
|
|
"""Transform Anthropic response to Skill object"""
|
||
|
|
response_json = raw_response.json()
|
||
|
|
verbose_logger.debug("Transforming create skill response: %s", response_json)
|
||
|
|
|
||
|
|
return Skill(**response_json)
|
||
|
|
|
||
|
|
def transform_list_skills_request(
|
||
|
|
self,
|
||
|
|
list_params: ListSkillsParams,
|
||
|
|
litellm_params: GenericLiteLLMParams,
|
||
|
|
headers: dict,
|
||
|
|
) -> Tuple[str, Dict]:
|
||
|
|
"""Transform list skills request for Anthropic"""
|
||
|
|
from litellm.llms.anthropic.common_utils import AnthropicModelInfo
|
||
|
|
|
||
|
|
api_base = AnthropicModelInfo.get_api_base(
|
||
|
|
litellm_params.api_base if litellm_params else None
|
||
|
|
)
|
||
|
|
url = self.get_complete_url(api_base=api_base, endpoint="skills")
|
||
|
|
|
||
|
|
# Build query parameters
|
||
|
|
query_params: Dict[str, Any] = {}
|
||
|
|
if "limit" in list_params and list_params["limit"]:
|
||
|
|
query_params["limit"] = list_params["limit"]
|
||
|
|
if "page" in list_params and list_params["page"]:
|
||
|
|
query_params["page"] = list_params["page"]
|
||
|
|
if "source" in list_params and list_params["source"]:
|
||
|
|
query_params["source"] = list_params["source"]
|
||
|
|
|
||
|
|
verbose_logger.debug(
|
||
|
|
"List skills request made to Anthropic Skills endpoint with params: %s",
|
||
|
|
query_params,
|
||
|
|
)
|
||
|
|
|
||
|
|
return url, query_params
|
||
|
|
|
||
|
|
def transform_list_skills_response(
|
||
|
|
self,
|
||
|
|
raw_response: httpx.Response,
|
||
|
|
logging_obj: LiteLLMLoggingObj,
|
||
|
|
) -> ListSkillsResponse:
|
||
|
|
"""Transform Anthropic response to ListSkillsResponse"""
|
||
|
|
response_json = raw_response.json()
|
||
|
|
verbose_logger.debug("Transforming list skills response: %s", response_json)
|
||
|
|
|
||
|
|
return ListSkillsResponse(**response_json)
|
||
|
|
|
||
|
|
def transform_get_skill_request(
|
||
|
|
self,
|
||
|
|
skill_id: str,
|
||
|
|
api_base: str,
|
||
|
|
litellm_params: GenericLiteLLMParams,
|
||
|
|
headers: dict,
|
||
|
|
) -> Tuple[str, Dict]:
|
||
|
|
"""Transform get skill request for Anthropic"""
|
||
|
|
url = self.get_complete_url(
|
||
|
|
api_base=api_base, endpoint="skills", skill_id=skill_id
|
||
|
|
)
|
||
|
|
|
||
|
|
verbose_logger.debug("Get skill request - URL: %s", url)
|
||
|
|
|
||
|
|
return url, headers
|
||
|
|
|
||
|
|
def transform_get_skill_response(
|
||
|
|
self,
|
||
|
|
raw_response: httpx.Response,
|
||
|
|
logging_obj: LiteLLMLoggingObj,
|
||
|
|
) -> Skill:
|
||
|
|
"""Transform Anthropic response to Skill object"""
|
||
|
|
response_json = raw_response.json()
|
||
|
|
verbose_logger.debug("Transforming get skill response: %s", response_json)
|
||
|
|
|
||
|
|
return Skill(**response_json)
|
||
|
|
|
||
|
|
def transform_delete_skill_request(
|
||
|
|
self,
|
||
|
|
skill_id: str,
|
||
|
|
api_base: str,
|
||
|
|
litellm_params: GenericLiteLLMParams,
|
||
|
|
headers: dict,
|
||
|
|
) -> Tuple[str, Dict]:
|
||
|
|
"""Transform delete skill request for Anthropic"""
|
||
|
|
url = self.get_complete_url(
|
||
|
|
api_base=api_base, endpoint="skills", skill_id=skill_id
|
||
|
|
)
|
||
|
|
|
||
|
|
verbose_logger.debug("Delete skill request - URL: %s", url)
|
||
|
|
|
||
|
|
return url, headers
|
||
|
|
|
||
|
|
def transform_delete_skill_response(
|
||
|
|
self,
|
||
|
|
raw_response: httpx.Response,
|
||
|
|
logging_obj: LiteLLMLoggingObj,
|
||
|
|
) -> DeleteSkillResponse:
|
||
|
|
"""Transform Anthropic response to DeleteSkillResponse"""
|
||
|
|
response_json = raw_response.json()
|
||
|
|
verbose_logger.debug("Transforming delete skill response: %s", response_json)
|
||
|
|
|
||
|
|
return DeleteSkillResponse(**response_json)
|