Spaces:
Paused
Paused
| """ | |
| Translate from OpenAI's `/v1/chat/completions` to Groq's `/v1/chat/completions` | |
| """ | |
| from typing import List, Optional, Tuple, Union | |
| from pydantic import BaseModel | |
| from litellm.secret_managers.main import get_secret_str | |
| from litellm.types.llms.openai import ( | |
| AllMessageValues, | |
| ChatCompletionAssistantMessage, | |
| ChatCompletionToolParam, | |
| ChatCompletionToolParamFunctionChunk, | |
| ) | |
| from ...openai_like.chat.transformation import OpenAILikeChatConfig | |
| class GroqChatConfig(OpenAILikeChatConfig): | |
| frequency_penalty: Optional[int] = None | |
| function_call: Optional[Union[str, dict]] = None | |
| functions: Optional[list] = None | |
| logit_bias: Optional[dict] = None | |
| max_tokens: Optional[int] = None | |
| n: Optional[int] = None | |
| presence_penalty: Optional[int] = None | |
| stop: Optional[Union[str, list]] = None | |
| temperature: Optional[int] = None | |
| top_p: Optional[int] = None | |
| response_format: Optional[dict] = None | |
| tools: Optional[list] = None | |
| tool_choice: Optional[Union[str, dict]] = None | |
| def __init__( | |
| self, | |
| frequency_penalty: Optional[int] = None, | |
| function_call: Optional[Union[str, dict]] = None, | |
| functions: Optional[list] = None, | |
| logit_bias: Optional[dict] = None, | |
| max_tokens: Optional[int] = None, | |
| n: Optional[int] = None, | |
| presence_penalty: Optional[int] = None, | |
| stop: Optional[Union[str, list]] = None, | |
| temperature: Optional[int] = None, | |
| top_p: Optional[int] = None, | |
| response_format: Optional[dict] = None, | |
| tools: Optional[list] = None, | |
| tool_choice: Optional[Union[str, dict]] = None, | |
| ) -> None: | |
| locals_ = locals().copy() | |
| for key, value in locals_.items(): | |
| if key != "self" and value is not None: | |
| setattr(self.__class__, key, value) | |
| def get_config(cls): | |
| return super().get_config() | |
| def get_supported_openai_params(self, model: str) -> list: | |
| base_params = super().get_supported_openai_params(model) | |
| try: | |
| base_params.remove("max_retries") | |
| except ValueError: | |
| pass | |
| return base_params | |
| def _transform_messages(self, messages: List[AllMessageValues], model: str) -> List: | |
| for idx, message in enumerate(messages): | |
| """ | |
| 1. Don't pass 'null' function_call assistant message to groq - https://github.com/BerriAI/litellm/issues/5839 | |
| """ | |
| if isinstance(message, BaseModel): | |
| _message = message.model_dump() | |
| else: | |
| _message = message | |
| assistant_message = _message.get("role") == "assistant" | |
| if assistant_message: | |
| new_message = ChatCompletionAssistantMessage(role="assistant") | |
| for k, v in _message.items(): | |
| if v is not None: | |
| new_message[k] = v # type: ignore | |
| messages[idx] = new_message | |
| return messages | |
| def _get_openai_compatible_provider_info( | |
| self, api_base: Optional[str], api_key: Optional[str] | |
| ) -> Tuple[Optional[str], Optional[str]]: | |
| # groq is openai compatible, we just need to set this to custom_openai and have the api_base be https://api.groq.com/openai/v1 | |
| api_base = ( | |
| api_base | |
| or get_secret_str("GROQ_API_BASE") | |
| or "https://api.groq.com/openai/v1" | |
| ) # type: ignore | |
| dynamic_api_key = api_key or get_secret_str("GROQ_API_KEY") | |
| return api_base, dynamic_api_key | |
| def _should_fake_stream(self, optional_params: dict) -> bool: | |
| """ | |
| Groq doesn't support 'response_format' while streaming | |
| """ | |
| if optional_params.get("response_format") is not None: | |
| return True | |
| return False | |
| def _create_json_tool_call_for_response_format( | |
| self, | |
| json_schema: dict, | |
| ): | |
| """ | |
| Handles creating a tool call for getting responses in JSON format. | |
| Args: | |
| json_schema (Optional[dict]): The JSON schema the response should be in | |
| Returns: | |
| AnthropicMessagesTool: The tool call to send to Anthropic API to get responses in JSON format | |
| """ | |
| return ChatCompletionToolParam( | |
| type="function", | |
| function=ChatCompletionToolParamFunctionChunk( | |
| name="json_tool_call", | |
| parameters=json_schema, | |
| ), | |
| ) | |
| def map_openai_params( | |
| self, | |
| non_default_params: dict, | |
| optional_params: dict, | |
| model: str, | |
| drop_params: bool = False, | |
| replace_max_completion_tokens_with_max_tokens: bool = False, # groq supports max_completion_tokens | |
| ) -> dict: | |
| _response_format = non_default_params.get("response_format") | |
| if self._should_fake_stream(non_default_params): | |
| optional_params["fake_stream"] = True | |
| if _response_format is not None and isinstance(_response_format, dict): | |
| json_schema: Optional[dict] = None | |
| if "response_schema" in _response_format: | |
| json_schema = _response_format["response_schema"] | |
| elif "json_schema" in _response_format: | |
| json_schema = _response_format["json_schema"]["schema"] | |
| """ | |
| When using tools in this way: - https://docs.anthropic.com/en/docs/build-with-claude/tool-use#json-mode | |
| - You usually want to provide a single tool | |
| - You should set tool_choice (see Forcing tool use) to instruct the model to explicitly use that tool | |
| - Remember that the model will pass the input to the tool, so the name of the tool and description should be from the model’s perspective. | |
| """ | |
| if json_schema is not None: | |
| _tool_choice = { | |
| "type": "function", | |
| "function": {"name": "json_tool_call"}, | |
| } | |
| _tool = self._create_json_tool_call_for_response_format( | |
| json_schema=json_schema, | |
| ) | |
| optional_params["tools"] = [_tool] | |
| optional_params["tool_choice"] = _tool_choice | |
| optional_params["json_mode"] = True | |
| non_default_params.pop( | |
| "response_format", None | |
| ) # only remove if it's a json_schema - handled via using groq's tool calling params. | |
| optional_params = super().map_openai_params( | |
| non_default_params, optional_params, model, drop_params | |
| ) | |
| return optional_params | |