mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-09 03:18:44 +00:00
Add support for openai skills
This commit is contained in:
parent
44bb1dafdb
commit
de8dbc3a24
5 changed files with 270 additions and 0 deletions
|
|
@ -1403,6 +1403,7 @@ if TYPE_CHECKING:
|
|||
from .llms.gemini.interactions.transformation import GoogleAIStudioInteractionsConfig as GoogleAIStudioInteractionsConfig
|
||||
from .llms.openai.chat.o_series_transformation import OpenAIOSeriesConfig as OpenAIOSeriesConfig, OpenAIOSeriesConfig as OpenAIO1Config
|
||||
from .llms.anthropic.skills.transformation import AnthropicSkillsConfig as AnthropicSkillsConfig
|
||||
from .llms.openai.skills.transformation import OpenAISkillsConfig as OpenAISkillsConfig
|
||||
from .llms.base_llm.skills.transformation import BaseSkillsAPIConfig as BaseSkillsAPIConfig
|
||||
from .llms.gradient_ai.chat.transformation import GradientAIConfig as GradientAIConfig
|
||||
from .llms.openai.chat.gpt_transformation import OpenAIGPTConfig as OpenAIGPTConfig
|
||||
|
|
|
|||
|
|
@ -230,6 +230,7 @@ LLM_CONFIG_NAMES = (
|
|||
"GoogleAIStudioInteractionsConfig",
|
||||
"OpenAIOSeriesConfig",
|
||||
"AnthropicSkillsConfig",
|
||||
"OpenAISkillsConfig",
|
||||
"BaseSkillsAPIConfig",
|
||||
"GradientAIConfig",
|
||||
# Alias for backwards compatibility
|
||||
|
|
@ -918,6 +919,10 @@ _LLM_CONFIGS_IMPORT_MAP = {
|
|||
".llms.anthropic.skills.transformation",
|
||||
"AnthropicSkillsConfig",
|
||||
),
|
||||
"OpenAISkillsConfig": (
|
||||
".llms.openai.skills.transformation",
|
||||
"OpenAISkillsConfig",
|
||||
),
|
||||
"BaseSkillsAPIConfig": (
|
||||
".llms.base_llm.skills.transformation",
|
||||
"BaseSkillsAPIConfig",
|
||||
|
|
|
|||
7
litellm/llms/openai/skills/__init__.py
Normal file
7
litellm/llms/openai/skills/__init__.py
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
"""
|
||||
OpenAI Skills API support
|
||||
"""
|
||||
|
||||
from .transformation import OpenAISkillsConfig
|
||||
|
||||
__all__ = ["OpenAISkillsConfig"]
|
||||
255
litellm/llms/openai/skills/transformation.py
Normal file
255
litellm/llms/openai/skills/transformation.py
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
"""
|
||||
OpenAI 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 OpenAISkillsConfig(BaseSkillsAPIConfig):
|
||||
"""OpenAI-specific Skills API configuration"""
|
||||
|
||||
@property
|
||||
def custom_llm_provider(self) -> LlmProviders:
|
||||
return LlmProviders.OPENAI
|
||||
|
||||
def validate_environment(
|
||||
self, headers: dict, litellm_params: Optional[GenericLiteLLMParams]
|
||||
) -> dict:
|
||||
"""Add OpenAI-specific headers"""
|
||||
from litellm.llms.openai.chat.gpt_transformation import OpenAIGPTConfig
|
||||
|
||||
# Get API key
|
||||
api_key = None
|
||||
if litellm_params:
|
||||
api_key = litellm_params.api_key
|
||||
api_key = OpenAIGPTConfig.get_api_key(api_key)
|
||||
|
||||
if not api_key:
|
||||
raise ValueError("OPENAI_API_KEY is required for Skills API")
|
||||
|
||||
# Add required headers
|
||||
headers["Authorization"] = f"Bearer {api_key}"
|
||||
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 OpenAI Skills API"""
|
||||
from litellm.llms.openai.chat.gpt_transformation import OpenAIGPTConfig
|
||||
|
||||
if api_base is None:
|
||||
api_base = OpenAIGPTConfig.get_api_base()
|
||||
|
||||
# Default to OpenAI's API base if not provided
|
||||
if api_base is None:
|
||||
api_base = "https://api.openai.com"
|
||||
|
||||
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 OpenAI"""
|
||||
verbose_logger.debug(
|
||||
"Transforming create skill request: %s", create_request
|
||||
)
|
||||
|
||||
# OpenAI expects the request body with files as an array or single zip
|
||||
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 OpenAI response to Skill object"""
|
||||
response_json = raw_response.json()
|
||||
verbose_logger.debug(
|
||||
"Transforming create skill response: %s", response_json
|
||||
)
|
||||
|
||||
# Map OpenAI response fields to our Skill model
|
||||
# OpenAI returns: id, created_at, default_version, description, latest_version, name, object
|
||||
skill_data = {
|
||||
"id": response_json.get("id"),
|
||||
"created_at": str(response_json.get("created_at", "")),
|
||||
"display_title": response_json.get("name"), # Map name to display_title
|
||||
"latest_version": response_json.get("latest_version"),
|
||||
"source": "custom", # OpenAI skills are custom
|
||||
"type": "skill",
|
||||
"updated_at": str(response_json.get("created_at", "")), # Use created_at as updated_at if not provided
|
||||
}
|
||||
|
||||
return Skill(**skill_data)
|
||||
|
||||
def transform_list_skills_request(
|
||||
self,
|
||||
list_params: ListSkillsParams,
|
||||
litellm_params: GenericLiteLLMParams,
|
||||
headers: dict,
|
||||
) -> Tuple[str, Dict]:
|
||||
"""Transform list skills request for OpenAI"""
|
||||
from litellm.llms.openai.chat.gpt_transformation import OpenAIGPTConfig
|
||||
|
||||
api_base = OpenAIGPTConfig.get_api_base(
|
||||
litellm_params.api_base if litellm_params else None
|
||||
)
|
||||
|
||||
if api_base is None:
|
||||
api_base = "https://api.openai.com"
|
||||
|
||||
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 OpenAI 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 OpenAI response to ListSkillsResponse"""
|
||||
response_json = raw_response.json()
|
||||
verbose_logger.debug(
|
||||
"Transforming list skills response: %s", response_json
|
||||
)
|
||||
|
||||
# OpenAI returns a list format, we need to map it to our response format
|
||||
# Assuming OpenAI returns similar structure with data array
|
||||
skills_data = []
|
||||
for skill_json in response_json.get("data", []):
|
||||
skill_data = {
|
||||
"id": skill_json.get("id"),
|
||||
"created_at": str(skill_json.get("created_at", "")),
|
||||
"display_title": skill_json.get("name"),
|
||||
"latest_version": skill_json.get("latest_version"),
|
||||
"source": "custom",
|
||||
"type": "skill",
|
||||
"updated_at": str(skill_json.get("created_at", "")),
|
||||
}
|
||||
skills_data.append(Skill(**skill_data))
|
||||
|
||||
return ListSkillsResponse(
|
||||
data=skills_data,
|
||||
next_page=response_json.get("next_page"),
|
||||
has_more=response_json.get("has_more", False),
|
||||
)
|
||||
|
||||
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 OpenAI"""
|
||||
if api_base is None:
|
||||
api_base = "https://api.openai.com"
|
||||
|
||||
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 OpenAI response to Skill object"""
|
||||
response_json = raw_response.json()
|
||||
verbose_logger.debug(
|
||||
"Transforming get skill response: %s", response_json
|
||||
)
|
||||
|
||||
skill_data = {
|
||||
"id": response_json.get("id"),
|
||||
"created_at": str(response_json.get("created_at", "")),
|
||||
"display_title": response_json.get("name"),
|
||||
"latest_version": response_json.get("latest_version"),
|
||||
"source": "custom",
|
||||
"type": "skill",
|
||||
"updated_at": str(response_json.get("created_at", "")),
|
||||
}
|
||||
|
||||
return Skill(**skill_data)
|
||||
|
||||
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 OpenAI"""
|
||||
if api_base is None:
|
||||
api_base = "https://api.openai.com"
|
||||
|
||||
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 OpenAI response to DeleteSkillResponse"""
|
||||
response_json = raw_response.json()
|
||||
verbose_logger.debug(
|
||||
"Transforming delete skill response: %s", response_json
|
||||
)
|
||||
|
||||
# OpenAI likely returns similar structure
|
||||
return DeleteSkillResponse(
|
||||
id=response_json.get("id"),
|
||||
type="skill_deleted",
|
||||
)
|
||||
|
|
@ -8279,6 +8279,8 @@ class ProviderConfigManager:
|
|||
"""
|
||||
if litellm.LlmProviders.ANTHROPIC == provider:
|
||||
return litellm.AnthropicSkillsConfig()
|
||||
elif litellm.LlmProviders.OPENAI == provider:
|
||||
return litellm.OpenAISkillsConfig()
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue