| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  | import binascii | 
					
						
							|  |  |  | from collections.abc import Generator, Sequence | 
					
						
							|  |  |  | from typing import IO, Optional | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from core.model_runtime.entities.llm_entities import LLMResultChunk | 
					
						
							|  |  |  | from core.model_runtime.entities.message_entities import PromptMessage, PromptMessageTool | 
					
						
							|  |  |  | from core.model_runtime.entities.model_entities import AIModelEntity | 
					
						
							|  |  |  | from core.model_runtime.entities.rerank_entities import RerankResult | 
					
						
							|  |  |  | from core.model_runtime.entities.text_embedding_entities import TextEmbeddingResult | 
					
						
							|  |  |  | from core.model_runtime.utils.encoders import jsonable_encoder | 
					
						
							|  |  |  | from core.plugin.entities.plugin_daemon import ( | 
					
						
							|  |  |  |     PluginBasicBooleanResponse, | 
					
						
							|  |  |  |     PluginDaemonInnerError, | 
					
						
							|  |  |  |     PluginLLMNumTokensResponse, | 
					
						
							|  |  |  |     PluginModelProviderEntity, | 
					
						
							|  |  |  |     PluginModelSchemaEntity, | 
					
						
							|  |  |  |     PluginStringResultResponse, | 
					
						
							|  |  |  |     PluginTextEmbeddingNumTokensResponse, | 
					
						
							|  |  |  |     PluginVoicesResponse, | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2025-04-27 14:22:25 +08:00
										 |  |  | from core.plugin.impl.base import BasePluginClient | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-27 14:22:25 +08:00
										 |  |  | class PluginModelClient(BasePluginClient): | 
					
						
							| 
									
										
										
										
											2025-02-17 17:05:13 +08:00
										 |  |  |     def fetch_model_providers(self, tenant_id: str) -> Sequence[PluginModelProviderEntity]: | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Fetch model providers for the given tenant. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         response = self._request_with_plugin_daemon_response( | 
					
						
							|  |  |  |             "GET", | 
					
						
							|  |  |  |             f"plugin/{tenant_id}/management/models", | 
					
						
							|  |  |  |             list[PluginModelProviderEntity], | 
					
						
							|  |  |  |             params={"page": 1, "page_size": 256}, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         return response | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_model_schema( | 
					
						
							|  |  |  |         self, | 
					
						
							|  |  |  |         tenant_id: str, | 
					
						
							|  |  |  |         user_id: str, | 
					
						
							|  |  |  |         plugin_id: str, | 
					
						
							|  |  |  |         provider: str, | 
					
						
							|  |  |  |         model_type: str, | 
					
						
							|  |  |  |         model: str, | 
					
						
							|  |  |  |         credentials: dict, | 
					
						
							|  |  |  |     ) -> AIModelEntity | None: | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Get model schema | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         response = self._request_with_plugin_daemon_response_stream( | 
					
						
							|  |  |  |             "POST", | 
					
						
							|  |  |  |             f"plugin/{tenant_id}/dispatch/model/schema", | 
					
						
							|  |  |  |             PluginModelSchemaEntity, | 
					
						
							|  |  |  |             data={ | 
					
						
							|  |  |  |                 "user_id": user_id, | 
					
						
							|  |  |  |                 "data": { | 
					
						
							|  |  |  |                     "provider": provider, | 
					
						
							|  |  |  |                     "model_type": model_type, | 
					
						
							|  |  |  |                     "model": model, | 
					
						
							|  |  |  |                     "credentials": credentials, | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             headers={ | 
					
						
							|  |  |  |                 "X-Plugin-ID": plugin_id, | 
					
						
							|  |  |  |                 "Content-Type": "application/json", | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for resp in response: | 
					
						
							|  |  |  |             return resp.model_schema | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def validate_provider_credentials( | 
					
						
							|  |  |  |         self, tenant_id: str, user_id: str, plugin_id: str, provider: str, credentials: dict | 
					
						
							|  |  |  |     ) -> bool: | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         validate the credentials of the provider | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         response = self._request_with_plugin_daemon_response_stream( | 
					
						
							|  |  |  |             "POST", | 
					
						
							|  |  |  |             f"plugin/{tenant_id}/dispatch/model/validate_provider_credentials", | 
					
						
							|  |  |  |             PluginBasicBooleanResponse, | 
					
						
							|  |  |  |             data={ | 
					
						
							|  |  |  |                 "user_id": user_id, | 
					
						
							|  |  |  |                 "data": { | 
					
						
							|  |  |  |                     "provider": provider, | 
					
						
							|  |  |  |                     "credentials": credentials, | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             headers={ | 
					
						
							|  |  |  |                 "X-Plugin-ID": plugin_id, | 
					
						
							|  |  |  |                 "Content-Type": "application/json", | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for resp in response: | 
					
						
							|  |  |  |             if resp.credentials and isinstance(resp.credentials, dict): | 
					
						
							|  |  |  |                 credentials.update(resp.credentials) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return resp.result | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def validate_model_credentials( | 
					
						
							|  |  |  |         self, | 
					
						
							|  |  |  |         tenant_id: str, | 
					
						
							|  |  |  |         user_id: str, | 
					
						
							|  |  |  |         plugin_id: str, | 
					
						
							|  |  |  |         provider: str, | 
					
						
							|  |  |  |         model_type: str, | 
					
						
							|  |  |  |         model: str, | 
					
						
							|  |  |  |         credentials: dict, | 
					
						
							|  |  |  |     ) -> bool: | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         validate the credentials of the provider | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         response = self._request_with_plugin_daemon_response_stream( | 
					
						
							|  |  |  |             "POST", | 
					
						
							|  |  |  |             f"plugin/{tenant_id}/dispatch/model/validate_model_credentials", | 
					
						
							|  |  |  |             PluginBasicBooleanResponse, | 
					
						
							|  |  |  |             data={ | 
					
						
							|  |  |  |                 "user_id": user_id, | 
					
						
							|  |  |  |                 "data": { | 
					
						
							|  |  |  |                     "provider": provider, | 
					
						
							|  |  |  |                     "model_type": model_type, | 
					
						
							|  |  |  |                     "model": model, | 
					
						
							|  |  |  |                     "credentials": credentials, | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             headers={ | 
					
						
							|  |  |  |                 "X-Plugin-ID": plugin_id, | 
					
						
							|  |  |  |                 "Content-Type": "application/json", | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for resp in response: | 
					
						
							|  |  |  |             if resp.credentials and isinstance(resp.credentials, dict): | 
					
						
							|  |  |  |                 credentials.update(resp.credentials) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return resp.result | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def invoke_llm( | 
					
						
							|  |  |  |         self, | 
					
						
							|  |  |  |         tenant_id: str, | 
					
						
							|  |  |  |         user_id: str, | 
					
						
							|  |  |  |         plugin_id: str, | 
					
						
							|  |  |  |         provider: str, | 
					
						
							|  |  |  |         model: str, | 
					
						
							|  |  |  |         credentials: dict, | 
					
						
							|  |  |  |         prompt_messages: list[PromptMessage], | 
					
						
							|  |  |  |         model_parameters: Optional[dict] = None, | 
					
						
							|  |  |  |         tools: Optional[list[PromptMessageTool]] = None, | 
					
						
							|  |  |  |         stop: Optional[list[str]] = None, | 
					
						
							|  |  |  |         stream: bool = True, | 
					
						
							|  |  |  |     ) -> Generator[LLMResultChunk, None, None]: | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Invoke llm | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         response = self._request_with_plugin_daemon_response_stream( | 
					
						
							|  |  |  |             method="POST", | 
					
						
							|  |  |  |             path=f"plugin/{tenant_id}/dispatch/llm/invoke", | 
					
						
							|  |  |  |             type=LLMResultChunk, | 
					
						
							|  |  |  |             data=jsonable_encoder( | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     "user_id": user_id, | 
					
						
							|  |  |  |                     "data": { | 
					
						
							|  |  |  |                         "provider": provider, | 
					
						
							|  |  |  |                         "model_type": "llm", | 
					
						
							|  |  |  |                         "model": model, | 
					
						
							|  |  |  |                         "credentials": credentials, | 
					
						
							|  |  |  |                         "prompt_messages": prompt_messages, | 
					
						
							|  |  |  |                         "model_parameters": model_parameters, | 
					
						
							|  |  |  |                         "tools": tools, | 
					
						
							|  |  |  |                         "stop": stop, | 
					
						
							|  |  |  |                         "stream": stream, | 
					
						
							|  |  |  |                     }, | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             headers={ | 
					
						
							|  |  |  |                 "X-Plugin-ID": plugin_id, | 
					
						
							|  |  |  |                 "Content-Type": "application/json", | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             yield from response | 
					
						
							|  |  |  |         except PluginDaemonInnerError as e: | 
					
						
							|  |  |  |             raise ValueError(e.message + str(e.code)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_llm_num_tokens( | 
					
						
							|  |  |  |         self, | 
					
						
							|  |  |  |         tenant_id: str, | 
					
						
							|  |  |  |         user_id: str, | 
					
						
							|  |  |  |         plugin_id: str, | 
					
						
							|  |  |  |         provider: str, | 
					
						
							|  |  |  |         model_type: str, | 
					
						
							|  |  |  |         model: str, | 
					
						
							|  |  |  |         credentials: dict, | 
					
						
							|  |  |  |         prompt_messages: list[PromptMessage], | 
					
						
							|  |  |  |         tools: Optional[list[PromptMessageTool]] = None, | 
					
						
							|  |  |  |     ) -> int: | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Get number of tokens for llm | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         response = self._request_with_plugin_daemon_response_stream( | 
					
						
							|  |  |  |             method="POST", | 
					
						
							|  |  |  |             path=f"plugin/{tenant_id}/dispatch/llm/num_tokens", | 
					
						
							|  |  |  |             type=PluginLLMNumTokensResponse, | 
					
						
							|  |  |  |             data=jsonable_encoder( | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     "user_id": user_id, | 
					
						
							|  |  |  |                     "data": { | 
					
						
							|  |  |  |                         "provider": provider, | 
					
						
							|  |  |  |                         "model_type": model_type, | 
					
						
							|  |  |  |                         "model": model, | 
					
						
							|  |  |  |                         "credentials": credentials, | 
					
						
							|  |  |  |                         "prompt_messages": prompt_messages, | 
					
						
							|  |  |  |                         "tools": tools, | 
					
						
							|  |  |  |                     }, | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             headers={ | 
					
						
							|  |  |  |                 "X-Plugin-ID": plugin_id, | 
					
						
							|  |  |  |                 "Content-Type": "application/json", | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for resp in response: | 
					
						
							|  |  |  |             return resp.num_tokens | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def invoke_text_embedding( | 
					
						
							|  |  |  |         self, | 
					
						
							|  |  |  |         tenant_id: str, | 
					
						
							|  |  |  |         user_id: str, | 
					
						
							|  |  |  |         plugin_id: str, | 
					
						
							|  |  |  |         provider: str, | 
					
						
							|  |  |  |         model: str, | 
					
						
							|  |  |  |         credentials: dict, | 
					
						
							|  |  |  |         texts: list[str], | 
					
						
							|  |  |  |         input_type: str, | 
					
						
							|  |  |  |     ) -> TextEmbeddingResult: | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Invoke text embedding | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         response = self._request_with_plugin_daemon_response_stream( | 
					
						
							|  |  |  |             method="POST", | 
					
						
							|  |  |  |             path=f"plugin/{tenant_id}/dispatch/text_embedding/invoke", | 
					
						
							|  |  |  |             type=TextEmbeddingResult, | 
					
						
							|  |  |  |             data=jsonable_encoder( | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     "user_id": user_id, | 
					
						
							|  |  |  |                     "data": { | 
					
						
							|  |  |  |                         "provider": provider, | 
					
						
							|  |  |  |                         "model_type": "text-embedding", | 
					
						
							|  |  |  |                         "model": model, | 
					
						
							|  |  |  |                         "credentials": credentials, | 
					
						
							|  |  |  |                         "texts": texts, | 
					
						
							|  |  |  |                         "input_type": input_type, | 
					
						
							|  |  |  |                     }, | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             headers={ | 
					
						
							|  |  |  |                 "X-Plugin-ID": plugin_id, | 
					
						
							|  |  |  |                 "Content-Type": "application/json", | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for resp in response: | 
					
						
							|  |  |  |             return resp | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         raise ValueError("Failed to invoke text embedding") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_text_embedding_num_tokens( | 
					
						
							|  |  |  |         self, | 
					
						
							|  |  |  |         tenant_id: str, | 
					
						
							|  |  |  |         user_id: str, | 
					
						
							|  |  |  |         plugin_id: str, | 
					
						
							|  |  |  |         provider: str, | 
					
						
							|  |  |  |         model: str, | 
					
						
							|  |  |  |         credentials: dict, | 
					
						
							|  |  |  |         texts: list[str], | 
					
						
							|  |  |  |     ) -> list[int]: | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Get number of tokens for text embedding | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         response = self._request_with_plugin_daemon_response_stream( | 
					
						
							|  |  |  |             method="POST", | 
					
						
							|  |  |  |             path=f"plugin/{tenant_id}/dispatch/text_embedding/num_tokens", | 
					
						
							|  |  |  |             type=PluginTextEmbeddingNumTokensResponse, | 
					
						
							|  |  |  |             data=jsonable_encoder( | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     "user_id": user_id, | 
					
						
							|  |  |  |                     "data": { | 
					
						
							|  |  |  |                         "provider": provider, | 
					
						
							|  |  |  |                         "model_type": "text-embedding", | 
					
						
							|  |  |  |                         "model": model, | 
					
						
							|  |  |  |                         "credentials": credentials, | 
					
						
							|  |  |  |                         "texts": texts, | 
					
						
							|  |  |  |                     }, | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             headers={ | 
					
						
							|  |  |  |                 "X-Plugin-ID": plugin_id, | 
					
						
							|  |  |  |                 "Content-Type": "application/json", | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for resp in response: | 
					
						
							|  |  |  |             return resp.num_tokens | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def invoke_rerank( | 
					
						
							|  |  |  |         self, | 
					
						
							|  |  |  |         tenant_id: str, | 
					
						
							|  |  |  |         user_id: str, | 
					
						
							|  |  |  |         plugin_id: str, | 
					
						
							|  |  |  |         provider: str, | 
					
						
							|  |  |  |         model: str, | 
					
						
							|  |  |  |         credentials: dict, | 
					
						
							|  |  |  |         query: str, | 
					
						
							|  |  |  |         docs: list[str], | 
					
						
							|  |  |  |         score_threshold: Optional[float] = None, | 
					
						
							|  |  |  |         top_n: Optional[int] = None, | 
					
						
							|  |  |  |     ) -> RerankResult: | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Invoke rerank | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         response = self._request_with_plugin_daemon_response_stream( | 
					
						
							|  |  |  |             method="POST", | 
					
						
							|  |  |  |             path=f"plugin/{tenant_id}/dispatch/rerank/invoke", | 
					
						
							|  |  |  |             type=RerankResult, | 
					
						
							|  |  |  |             data=jsonable_encoder( | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     "user_id": user_id, | 
					
						
							|  |  |  |                     "data": { | 
					
						
							|  |  |  |                         "provider": provider, | 
					
						
							|  |  |  |                         "model_type": "rerank", | 
					
						
							|  |  |  |                         "model": model, | 
					
						
							|  |  |  |                         "credentials": credentials, | 
					
						
							|  |  |  |                         "query": query, | 
					
						
							|  |  |  |                         "docs": docs, | 
					
						
							|  |  |  |                         "score_threshold": score_threshold, | 
					
						
							|  |  |  |                         "top_n": top_n, | 
					
						
							|  |  |  |                     }, | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             headers={ | 
					
						
							|  |  |  |                 "X-Plugin-ID": plugin_id, | 
					
						
							|  |  |  |                 "Content-Type": "application/json", | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for resp in response: | 
					
						
							|  |  |  |             return resp | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         raise ValueError("Failed to invoke rerank") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def invoke_tts( | 
					
						
							|  |  |  |         self, | 
					
						
							|  |  |  |         tenant_id: str, | 
					
						
							|  |  |  |         user_id: str, | 
					
						
							|  |  |  |         plugin_id: str, | 
					
						
							|  |  |  |         provider: str, | 
					
						
							|  |  |  |         model: str, | 
					
						
							|  |  |  |         credentials: dict, | 
					
						
							|  |  |  |         content_text: str, | 
					
						
							|  |  |  |         voice: str, | 
					
						
							|  |  |  |     ) -> Generator[bytes, None, None]: | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Invoke tts | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         response = self._request_with_plugin_daemon_response_stream( | 
					
						
							|  |  |  |             method="POST", | 
					
						
							|  |  |  |             path=f"plugin/{tenant_id}/dispatch/tts/invoke", | 
					
						
							|  |  |  |             type=PluginStringResultResponse, | 
					
						
							|  |  |  |             data=jsonable_encoder( | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     "user_id": user_id, | 
					
						
							|  |  |  |                     "data": { | 
					
						
							|  |  |  |                         "provider": provider, | 
					
						
							|  |  |  |                         "model_type": "tts", | 
					
						
							|  |  |  |                         "model": model, | 
					
						
							|  |  |  |                         "credentials": credentials, | 
					
						
							|  |  |  |                         "tenant_id": tenant_id, | 
					
						
							|  |  |  |                         "content_text": content_text, | 
					
						
							|  |  |  |                         "voice": voice, | 
					
						
							|  |  |  |                     }, | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             headers={ | 
					
						
							|  |  |  |                 "X-Plugin-ID": plugin_id, | 
					
						
							|  |  |  |                 "Content-Type": "application/json", | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             for result in response: | 
					
						
							|  |  |  |                 hex_str = result.result | 
					
						
							|  |  |  |                 yield binascii.unhexlify(hex_str) | 
					
						
							|  |  |  |         except PluginDaemonInnerError as e: | 
					
						
							|  |  |  |             raise ValueError(e.message + str(e.code)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_tts_model_voices( | 
					
						
							|  |  |  |         self, | 
					
						
							|  |  |  |         tenant_id: str, | 
					
						
							|  |  |  |         user_id: str, | 
					
						
							|  |  |  |         plugin_id: str, | 
					
						
							|  |  |  |         provider: str, | 
					
						
							|  |  |  |         model: str, | 
					
						
							|  |  |  |         credentials: dict, | 
					
						
							|  |  |  |         language: Optional[str] = None, | 
					
						
							|  |  |  |     ) -> list[dict]: | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Get tts model voices | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         response = self._request_with_plugin_daemon_response_stream( | 
					
						
							|  |  |  |             method="POST", | 
					
						
							|  |  |  |             path=f"plugin/{tenant_id}/dispatch/tts/model/voices", | 
					
						
							|  |  |  |             type=PluginVoicesResponse, | 
					
						
							|  |  |  |             data=jsonable_encoder( | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     "user_id": user_id, | 
					
						
							|  |  |  |                     "data": { | 
					
						
							|  |  |  |                         "provider": provider, | 
					
						
							|  |  |  |                         "model_type": "tts", | 
					
						
							|  |  |  |                         "model": model, | 
					
						
							|  |  |  |                         "credentials": credentials, | 
					
						
							|  |  |  |                         "language": language, | 
					
						
							|  |  |  |                     }, | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             headers={ | 
					
						
							|  |  |  |                 "X-Plugin-ID": plugin_id, | 
					
						
							|  |  |  |                 "Content-Type": "application/json", | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for resp in response: | 
					
						
							|  |  |  |             voices = [] | 
					
						
							|  |  |  |             for voice in resp.voices: | 
					
						
							|  |  |  |                 voices.append({"name": voice.name, "value": voice.value}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return voices | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def invoke_speech_to_text( | 
					
						
							|  |  |  |         self, | 
					
						
							|  |  |  |         tenant_id: str, | 
					
						
							|  |  |  |         user_id: str, | 
					
						
							|  |  |  |         plugin_id: str, | 
					
						
							|  |  |  |         provider: str, | 
					
						
							|  |  |  |         model: str, | 
					
						
							|  |  |  |         credentials: dict, | 
					
						
							|  |  |  |         file: IO[bytes], | 
					
						
							|  |  |  |     ) -> str: | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Invoke speech to text | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         response = self._request_with_plugin_daemon_response_stream( | 
					
						
							|  |  |  |             method="POST", | 
					
						
							|  |  |  |             path=f"plugin/{tenant_id}/dispatch/speech2text/invoke", | 
					
						
							|  |  |  |             type=PluginStringResultResponse, | 
					
						
							|  |  |  |             data=jsonable_encoder( | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     "user_id": user_id, | 
					
						
							|  |  |  |                     "data": { | 
					
						
							|  |  |  |                         "provider": provider, | 
					
						
							|  |  |  |                         "model_type": "speech2text", | 
					
						
							|  |  |  |                         "model": model, | 
					
						
							|  |  |  |                         "credentials": credentials, | 
					
						
							|  |  |  |                         "file": binascii.hexlify(file.read()).decode(), | 
					
						
							|  |  |  |                     }, | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             headers={ | 
					
						
							|  |  |  |                 "X-Plugin-ID": plugin_id, | 
					
						
							|  |  |  |                 "Content-Type": "application/json", | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for resp in response: | 
					
						
							|  |  |  |             return resp.result | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         raise ValueError("Failed to invoke speech to text") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def invoke_moderation( | 
					
						
							|  |  |  |         self, | 
					
						
							|  |  |  |         tenant_id: str, | 
					
						
							|  |  |  |         user_id: str, | 
					
						
							|  |  |  |         plugin_id: str, | 
					
						
							|  |  |  |         provider: str, | 
					
						
							|  |  |  |         model: str, | 
					
						
							|  |  |  |         credentials: dict, | 
					
						
							|  |  |  |         text: str, | 
					
						
							|  |  |  |     ) -> bool: | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Invoke moderation | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         response = self._request_with_plugin_daemon_response_stream( | 
					
						
							|  |  |  |             method="POST", | 
					
						
							|  |  |  |             path=f"plugin/{tenant_id}/dispatch/moderation/invoke", | 
					
						
							|  |  |  |             type=PluginBasicBooleanResponse, | 
					
						
							|  |  |  |             data=jsonable_encoder( | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     "user_id": user_id, | 
					
						
							|  |  |  |                     "data": { | 
					
						
							|  |  |  |                         "provider": provider, | 
					
						
							|  |  |  |                         "model_type": "moderation", | 
					
						
							|  |  |  |                         "model": model, | 
					
						
							|  |  |  |                         "credentials": credentials, | 
					
						
							|  |  |  |                         "text": text, | 
					
						
							|  |  |  |                     }, | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             headers={ | 
					
						
							|  |  |  |                 "X-Plugin-ID": plugin_id, | 
					
						
							|  |  |  |                 "Content-Type": "application/json", | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for resp in response: | 
					
						
							|  |  |  |             return resp.result | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         raise ValueError("Failed to invoke moderation") |