From 240a94182e285c0d82b0fd29bff0d8a4ae158e39 Mon Sep 17 00:00:00 2001 From: Yeuoly <45712896+Yeuoly@users.noreply.github.com> Date: Fri, 22 Mar 2024 15:15:48 +0800 Subject: [PATCH] Feat/add triton inference server (#2928) --- .../model_providers/_position.yaml | 3 +- .../triton_inference_server/__init__.py | 0 .../_assets/icon_l_en.png | Bin 0 -> 79751 bytes .../_assets/icon_s_en.svg | 3 + .../triton_inference_server/llm/__init__.py | 0 .../triton_inference_server/llm/llm.py | 267 ++++++++++++++++++ .../triton_inference_server.py | 9 + .../triton_inference_server.yaml | 84 ++++++ 8 files changed, 365 insertions(+), 1 deletion(-) create mode 100644 api/core/model_runtime/model_providers/triton_inference_server/__init__.py create mode 100644 api/core/model_runtime/model_providers/triton_inference_server/_assets/icon_l_en.png create mode 100644 api/core/model_runtime/model_providers/triton_inference_server/_assets/icon_s_en.svg create mode 100644 api/core/model_runtime/model_providers/triton_inference_server/llm/__init__.py create mode 100644 api/core/model_runtime/model_providers/triton_inference_server/llm/llm.py create mode 100644 api/core/model_runtime/model_providers/triton_inference_server/triton_inference_server.py create mode 100644 api/core/model_runtime/model_providers/triton_inference_server/triton_inference_server.yaml diff --git a/api/core/model_runtime/model_providers/_position.yaml b/api/core/model_runtime/model_providers/_position.yaml index 049ad67a77..7b4416f44e 100644 --- a/api/core/model_runtime/model_providers/_position.yaml +++ b/api/core/model_runtime/model_providers/_position.yaml @@ -11,6 +11,8 @@ - groq - replicate - huggingface_hub +- xinference +- triton_inference_server - zhipuai - baichuan - spark @@ -20,7 +22,6 @@ - moonshot - jina - chatglm -- xinference - yi - openllm - localai diff --git a/api/core/model_runtime/model_providers/triton_inference_server/__init__.py b/api/core/model_runtime/model_providers/triton_inference_server/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/api/core/model_runtime/model_providers/triton_inference_server/_assets/icon_l_en.png b/api/core/model_runtime/model_providers/triton_inference_server/_assets/icon_l_en.png new file mode 100644 index 0000000000000000000000000000000000000000..dd32d45803ee423f506fb3dc021e118ceccc0cfe GIT binary patch literal 79751 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 + + diff --git a/api/core/model_runtime/model_providers/triton_inference_server/llm/__init__.py b/api/core/model_runtime/model_providers/triton_inference_server/llm/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/api/core/model_runtime/model_providers/triton_inference_server/llm/llm.py b/api/core/model_runtime/model_providers/triton_inference_server/llm/llm.py new file mode 100644 index 0000000000..95272a41c2 --- /dev/null +++ b/api/core/model_runtime/model_providers/triton_inference_server/llm/llm.py @@ -0,0 +1,267 @@ +from collections.abc import Generator + +from httpx import Response, post +from yarl import URL + +from core.model_runtime.entities.common_entities import I18nObject +from core.model_runtime.entities.llm_entities import LLMMode, LLMResult, LLMResultChunk, LLMResultChunkDelta, LLMUsage +from core.model_runtime.entities.message_entities import ( + AssistantPromptMessage, + PromptMessage, + PromptMessageTool, + SystemPromptMessage, + UserPromptMessage, +) +from core.model_runtime.entities.model_entities import ( + AIModelEntity, + FetchFrom, + ModelPropertyKey, + ModelType, + ParameterRule, + ParameterType, +) +from core.model_runtime.errors.invoke import ( + InvokeAuthorizationError, + InvokeBadRequestError, + InvokeConnectionError, + InvokeError, + InvokeRateLimitError, + InvokeServerUnavailableError, +) +from core.model_runtime.errors.validate import CredentialsValidateFailedError +from core.model_runtime.model_providers.__base.large_language_model import LargeLanguageModel + + +class TritonInferenceAILargeLanguageModel(LargeLanguageModel): + def _invoke(self, model: str, credentials: dict, prompt_messages: list[PromptMessage], + model_parameters: dict, tools: list[PromptMessageTool] | None = None, + stop: list[str] | None = None, stream: bool = True, user: str | None = None) \ + -> LLMResult | Generator: + """ + invoke LLM + + see `core.model_runtime.model_providers.__base.large_language_model.LargeLanguageModel._invoke` + """ + return self._generate( + model=model, credentials=credentials, prompt_messages=prompt_messages, model_parameters=model_parameters, + tools=tools, stop=stop, stream=stream, user=user, + ) + + def validate_credentials(self, model: str, credentials: dict) -> None: + """ + validate credentials + """ + if 'server_url' not in credentials: + raise CredentialsValidateFailedError('server_url is required in credentials') + + try: + self._invoke(model=model, credentials=credentials, prompt_messages=[ + UserPromptMessage(content='ping') + ], model_parameters={}, stream=False) + except InvokeError as ex: + raise CredentialsValidateFailedError(f'An error occurred during connection: {str(ex)}') + + def get_num_tokens(self, model: str, credentials: dict, prompt_messages: list[PromptMessage], + tools: list[PromptMessageTool] | None = None) -> int: + """ + get number of tokens + + cause TritonInference LLM is a customized model, we could net detect which tokenizer to use + so we just take the GPT2 tokenizer as default + """ + return self._get_num_tokens_by_gpt2(self._convert_prompt_message_to_text(prompt_messages)) + + def _convert_prompt_message_to_text(self, message: list[PromptMessage]) -> str: + """ + convert prompt message to text + """ + text = '' + for item in message: + if isinstance(item, UserPromptMessage): + text += f'User: {item.content}' + elif isinstance(item, SystemPromptMessage): + text += f'System: {item.content}' + elif isinstance(item, AssistantPromptMessage): + text += f'Assistant: {item.content}' + else: + raise NotImplementedError(f'PromptMessage type {type(item)} is not supported') + return text + + def get_customizable_model_schema(self, model: str, credentials: dict) -> AIModelEntity | None: + """ + used to define customizable model schema + """ + rules = [ + ParameterRule( + name='temperature', + type=ParameterType.FLOAT, + use_template='temperature', + label=I18nObject( + zh_Hans='温度', + en_US='Temperature' + ), + ), + ParameterRule( + name='top_p', + type=ParameterType.FLOAT, + use_template='top_p', + label=I18nObject( + zh_Hans='Top P', + en_US='Top P' + ) + ), + ParameterRule( + name='max_tokens', + type=ParameterType.INT, + use_template='max_tokens', + min=1, + max=int(credentials.get('context_length', 2048)), + default=min(512, int(credentials.get('context_length', 2048))), + label=I18nObject( + zh_Hans='最大生成长度', + en_US='Max Tokens' + ) + ) + ] + + completion_type = None + + if 'completion_type' in credentials: + if credentials['completion_type'] == 'chat': + completion_type = LLMMode.CHAT.value + elif credentials['completion_type'] == 'completion': + completion_type = LLMMode.COMPLETION.value + else: + raise ValueError(f'completion_type {credentials["completion_type"]} is not supported') + + entity = AIModelEntity( + model=model, + label=I18nObject( + en_US=model + ), + parameter_rules=rules, + fetch_from=FetchFrom.CUSTOMIZABLE_MODEL, + model_type=ModelType.LLM, + model_properties={ + ModelPropertyKey.MODE: completion_type, + ModelPropertyKey.CONTEXT_SIZE: int(credentials.get('context_length', 2048)), + }, + ) + + return entity + + def _generate(self, model: str, credentials: dict, prompt_messages: list[PromptMessage], + model_parameters: dict, + tools: list[PromptMessageTool] | None = None, + stop: list[str] | None = None, stream: bool = True, user: str | None = None) \ + -> LLMResult | Generator: + """ + generate text from LLM + """ + if 'server_url' not in credentials: + raise CredentialsValidateFailedError('server_url is required in credentials') + + if 'stream' in credentials and not bool(credentials['stream']) and stream: + raise ValueError(f'stream is not supported by model {model}') + + try: + parameters = {} + if 'temperature' in model_parameters: + parameters['temperature'] = model_parameters['temperature'] + if 'top_p' in model_parameters: + parameters['top_p'] = model_parameters['top_p'] + if 'top_k' in model_parameters: + parameters['top_k'] = model_parameters['top_k'] + if 'presence_penalty' in model_parameters: + parameters['presence_penalty'] = model_parameters['presence_penalty'] + if 'frequency_penalty' in model_parameters: + parameters['frequency_penalty'] = model_parameters['frequency_penalty'] + + response = post(str(URL(credentials['server_url']) / 'v2' / 'models' / model / 'generate'), json={ + 'text_input': self._convert_prompt_message_to_text(prompt_messages), + 'max_tokens': model_parameters.get('max_tokens', 512), + 'parameters': { + 'stream': False, + **parameters + }, + }, timeout=(10, 120)) + response.raise_for_status() + if response.status_code != 200: + raise InvokeBadRequestError(f'Invoke failed with status code {response.status_code}, {response.text}') + + if stream: + return self._handle_chat_stream_response(model=model, credentials=credentials, prompt_messages=prompt_messages, + tools=tools, resp=response) + return self._handle_chat_generate_response(model=model, credentials=credentials, prompt_messages=prompt_messages, + tools=tools, resp=response) + except Exception as ex: + raise InvokeConnectionError(f'An error occurred during connection: {str(ex)}') + + def _handle_chat_generate_response(self, model: str, credentials: dict, prompt_messages: list[PromptMessage], + tools: list[PromptMessageTool], + resp: Response) -> LLMResult: + """ + handle normal chat generate response + """ + text = resp.json()['text_output'] + + usage = LLMUsage.empty_usage() + usage.prompt_tokens = self.get_num_tokens(model, credentials, prompt_messages) + usage.completion_tokens = self._get_num_tokens_by_gpt2(text) + + return LLMResult( + model=model, + prompt_messages=prompt_messages, + message=AssistantPromptMessage( + content=text + ), + usage=usage + ) + + def _handle_chat_stream_response(self, model: str, credentials: dict, prompt_messages: list[PromptMessage], + tools: list[PromptMessageTool], + resp: Response) -> Generator: + """ + handle normal chat generate response + """ + text = resp.json()['text_output'] + + usage = LLMUsage.empty_usage() + usage.prompt_tokens = self.get_num_tokens(model, credentials, prompt_messages) + usage.completion_tokens = self._get_num_tokens_by_gpt2(text) + + yield LLMResultChunk( + model=model, + prompt_messages=prompt_messages, + delta=LLMResultChunkDelta( + index=0, + message=AssistantPromptMessage( + content=text + ), + usage=usage + ) + ) + + @property + def _invoke_error_mapping(self) -> dict[type[InvokeError], list[type[Exception]]]: + """ + Map model invoke error to unified error + The key is the error type thrown to the caller + The value is the error type thrown by the model, + which needs to be converted into a unified error type for the caller. + + :return: Invoke error mapping + """ + return { + InvokeConnectionError: [ + ], + InvokeServerUnavailableError: [ + ], + InvokeRateLimitError: [ + ], + InvokeAuthorizationError: [ + ], + InvokeBadRequestError: [ + ValueError + ] + } \ No newline at end of file diff --git a/api/core/model_runtime/model_providers/triton_inference_server/triton_inference_server.py b/api/core/model_runtime/model_providers/triton_inference_server/triton_inference_server.py new file mode 100644 index 0000000000..06846825ab --- /dev/null +++ b/api/core/model_runtime/model_providers/triton_inference_server/triton_inference_server.py @@ -0,0 +1,9 @@ +import logging + +from core.model_runtime.model_providers.__base.model_provider import ModelProvider + +logger = logging.getLogger(__name__) + +class XinferenceAIProvider(ModelProvider): + def validate_provider_credentials(self, credentials: dict) -> None: + pass diff --git a/api/core/model_runtime/model_providers/triton_inference_server/triton_inference_server.yaml b/api/core/model_runtime/model_providers/triton_inference_server/triton_inference_server.yaml new file mode 100644 index 0000000000..50a804743d --- /dev/null +++ b/api/core/model_runtime/model_providers/triton_inference_server/triton_inference_server.yaml @@ -0,0 +1,84 @@ +provider: triton_inference_server +label: + en_US: Triton Inference Server +icon_small: + en_US: icon_s_en.svg +icon_large: + en_US: icon_l_en.png +background: "#EFFDFD" +help: + title: + en_US: How to deploy Triton Inference Server + zh_Hans: 如何部署 Triton Inference Server + url: + en_US: https://github.com/triton-inference-server/server +supported_model_types: + - llm +configurate_methods: + - customizable-model +model_credential_schema: + model: + label: + en_US: Model Name + zh_Hans: 模型名称 + placeholder: + en_US: Enter your model name + zh_Hans: 输入模型名称 + credential_form_schemas: + - variable: server_url + label: + zh_Hans: 服务器URL + en_US: Server url + type: secret-input + required: true + placeholder: + zh_Hans: 在此输入 Triton Inference Server 的服务器地址,如 http://192.168.1.100:8000 + en_US: Enter the url of your Triton Inference Server, e.g. http://192.168.1.100:8000 + - variable: context_size + label: + zh_Hans: 上下文大小 + en_US: Context size + type: text-input + required: true + placeholder: + zh_Hans: 在此输入您的上下文大小 + en_US: Enter the context size + default: 2048 + - variable: completion_type + label: + zh_Hans: 补全类型 + en_US: Model type + type: select + required: true + default: chat + placeholder: + zh_Hans: 在此输入您的补全类型 + en_US: Enter the completion type + options: + - label: + zh_Hans: 补全模型 + en_US: Completion model + value: completion + - label: + zh_Hans: 对话模型 + en_US: Chat model + value: chat + - variable: stream + label: + zh_Hans: 流式输出 + en_US: Stream output + type: select + required: true + default: true + placeholder: + zh_Hans: 是否支持流式输出 + en_US: Whether to support stream output + options: + - label: + zh_Hans: 是 + en_US: Yes + value: true + - label: + zh_Hans: 否 + en_US: No + value: false