-
Notifications
You must be signed in to change notification settings - Fork 2.6k
feat: support Tencent Cloud #2242
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| # coding=utf-8 | ||
| """ | ||
| @project: maxkb | ||
| @Author:虎 | ||
| @file: __init__.py.py | ||
| @date:2024/3/28 16:25 | ||
| @desc: | ||
| """ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| # coding=utf-8 | ||
| """ | ||
| @project: MaxKB | ||
| @Author:虎 | ||
| @file: llm.py | ||
| @date:2024/7/11 18:32 | ||
| @desc: | ||
| """ | ||
| from typing import Dict | ||
|
|
||
| from django.utils.translation import gettext_lazy as _, gettext | ||
| from langchain_core.messages import HumanMessage | ||
|
|
||
| from common import forms | ||
| from common.exception.app_exception import AppApiException | ||
| from common.forms import BaseForm, TooltipLabel | ||
| from setting.models_provider.base_model_provider import BaseModelCredential, ValidCode | ||
|
|
||
|
|
||
| class TencentCloudLLMModelParams(BaseForm): | ||
| temperature = forms.SliderField(TooltipLabel(_('Temperature'), | ||
| _('Higher values make the output more random, while lower values make it more focused and deterministic')), | ||
| required=True, default_value=0.7, | ||
| _min=0.1, | ||
| _max=1.0, | ||
| _step=0.01, | ||
| precision=2) | ||
|
|
||
| max_tokens = forms.SliderField( | ||
| TooltipLabel(_('Output the maximum Tokens'), | ||
| _('Specify the maximum number of tokens that the model can generate')), | ||
| required=True, default_value=800, | ||
| _min=1, | ||
| _max=100000, | ||
| _step=1, | ||
| precision=0) | ||
|
|
||
|
|
||
| class TencentCloudLLMModelCredential(BaseForm, BaseModelCredential): | ||
|
|
||
| def is_valid(self, model_type: str, model_name, model_credential: Dict[str, object], model_params, provider, | ||
| raise_exception=False): | ||
| model_type_list = provider.get_model_type_list() | ||
| if not any(list(filter(lambda mt: mt.get('value') == model_type, model_type_list))): | ||
| raise AppApiException(ValidCode.valid_error.value, | ||
| gettext('{model_type} Model type is not supported').format(model_type=model_type)) | ||
|
|
||
| for key in ['api_base', 'api_key']: | ||
| if key not in model_credential: | ||
| if raise_exception: | ||
| raise AppApiException(ValidCode.valid_error.value, gettext('{key} is required').format(key=key)) | ||
| else: | ||
| return False | ||
| try: | ||
|
|
||
| model = provider.get_model(model_type, model_name, model_credential, **model_params) | ||
| model.invoke([HumanMessage(content=gettext('Hello'))]) | ||
| except Exception as e: | ||
| if isinstance(e, AppApiException): | ||
| raise e | ||
| if raise_exception: | ||
| raise AppApiException(ValidCode.valid_error.value, | ||
| gettext( | ||
| 'Verification failed, please check whether the parameters are correct: {error}').format( | ||
| error=str(e))) | ||
| else: | ||
| return False | ||
| return True | ||
|
|
||
| def encryption_dict(self, model: Dict[str, object]): | ||
| return {**model, 'api_key': super().encryption(model.get('api_key', ''))} | ||
|
|
||
| api_base = forms.TextInputField('API URL', required=True) | ||
| api_key = forms.PasswordInputField('API Key', required=True) | ||
|
|
||
| def get_model_params_setting_form(self, model_name): | ||
| return TencentCloudLLMModelParams() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| # coding=utf-8 | ||
| """ | ||
| @project: maxkb | ||
| @Author:虎 | ||
| @file: llm.py | ||
| @date:2024/4/18 15:28 | ||
| @desc: | ||
| """ | ||
| from typing import List, Dict | ||
|
|
||
| from langchain_core.messages import BaseMessage, get_buffer_string | ||
|
|
||
| from common.config.tokenizer_manage_config import TokenizerManage | ||
| from setting.models_provider.base_model_provider import MaxKBBaseModel | ||
| from setting.models_provider.impl.base_chat_open_ai import BaseChatOpenAI | ||
|
|
||
|
|
||
| def custom_get_token_ids(text: str): | ||
| tokenizer = TokenizerManage.get_tokenizer() | ||
| return tokenizer.encode(text) | ||
|
|
||
|
|
||
| class TencentCloudChatModel(MaxKBBaseModel, BaseChatOpenAI): | ||
|
|
||
| @staticmethod | ||
| def is_cache_model(): | ||
| return False | ||
|
|
||
| @staticmethod | ||
| def new_instance(model_type, model_name, model_credential: Dict[str, object], **model_kwargs): | ||
| optional_params = MaxKBBaseModel.filter_optional_params(model_kwargs) | ||
| azure_chat_open_ai = TencentCloudChatModel( | ||
| model=model_name, | ||
| openai_api_base=model_credential.get('api_base'), | ||
| openai_api_key=model_credential.get('api_key'), | ||
| **optional_params, | ||
| custom_get_token_ids=custom_get_token_ids | ||
| ) | ||
| return azure_chat_open_ai | ||
|
|
||
| def get_num_tokens_from_messages(self, messages: List[BaseMessage]) -> int: | ||
| try: | ||
| return super().get_num_tokens_from_messages(messages) | ||
| except Exception as e: | ||
| tokenizer = TokenizerManage.get_tokenizer() | ||
| return sum([len(tokenizer.encode(get_buffer_string([m]))) for m in messages]) | ||
|
|
||
| def get_num_tokens(self, text: str) -> int: | ||
| try: | ||
| return super().get_num_tokens(text) | ||
| except Exception as e: | ||
| tokenizer = TokenizerManage.get_tokenizer() | ||
| return len(tokenizer.encode(text)) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here are the potential improvements and corrections to your Python code:
messages = [BaseMessage(content="Hello")] # Example message instance
try:
num_tokens = maxkb.model.TencentCloudChatModel.get_num_tokens_from_messages(messages)
print(f"Number of tokens: {num_tokens}")
except ValueError as ve:
print("Tokenization error:", ve)
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| # coding=utf-8 | ||
| """ | ||
| @project: maxkb | ||
| @Author:虎 | ||
| @file: openai_model_provider.py | ||
| @date:2024/3/28 16:26 | ||
| @desc: | ||
| """ | ||
| import os | ||
|
|
||
| from common.util.file_util import get_file_content | ||
| from setting.models_provider.base_model_provider import IModelProvider, ModelProvideInfo, ModelInfo, \ | ||
| ModelTypeConst, ModelInfoManage | ||
| from setting.models_provider.impl.openai_model_provider.credential.embedding import OpenAIEmbeddingCredential | ||
| from setting.models_provider.impl.openai_model_provider.credential.image import OpenAIImageModelCredential | ||
| from setting.models_provider.impl.openai_model_provider.credential.llm import OpenAILLMModelCredential | ||
| from setting.models_provider.impl.openai_model_provider.credential.stt import OpenAISTTModelCredential | ||
| from setting.models_provider.impl.openai_model_provider.credential.tti import OpenAITextToImageModelCredential | ||
| from setting.models_provider.impl.openai_model_provider.credential.tts import OpenAITTSModelCredential | ||
| from setting.models_provider.impl.openai_model_provider.model.embedding import OpenAIEmbeddingModel | ||
| from setting.models_provider.impl.openai_model_provider.model.image import OpenAIImage | ||
| from setting.models_provider.impl.openai_model_provider.model.llm import OpenAIChatModel | ||
| from setting.models_provider.impl.openai_model_provider.model.stt import OpenAISpeechToText | ||
| from setting.models_provider.impl.openai_model_provider.model.tti import OpenAITextToImage | ||
| from setting.models_provider.impl.openai_model_provider.model.tts import OpenAITextToSpeech | ||
| from setting.models_provider.impl.tencent_cloud_model_provider.credential.llm import TencentCloudLLMModelCredential | ||
| from setting.models_provider.impl.tencent_cloud_model_provider.model.llm import TencentCloudChatModel | ||
| from smartdoc.conf import PROJECT_DIR | ||
| from django.utils.translation import gettext_lazy as _ | ||
|
|
||
| openai_llm_model_credential = TencentCloudLLMModelCredential() | ||
| model_info_list = [ | ||
| ModelInfo('deepseek-v3', '', ModelTypeConst.LLM, | ||
| openai_llm_model_credential, TencentCloudChatModel | ||
| ), | ||
| ModelInfo('deepseek-r1', '', ModelTypeConst.IMAGE, | ||
| openai_llm_model_credential, TencentCloudChatModel | ||
| ), | ||
| ] | ||
|
|
||
| model_info_manage = ( | ||
| ModelInfoManage.builder() | ||
| .append_model_info_list(model_info_list) | ||
| .append_default_model_info( | ||
| ModelInfo('deepseek-v3', _('The latest gpt-3.5-turbo, updated with OpenAI adjustments'), ModelTypeConst.LLM, | ||
| openai_llm_model_credential, TencentCloudChatModel | ||
| )) | ||
| .build() | ||
| ) | ||
|
|
||
|
|
||
| class TencentCloudModelProvider(IModelProvider): | ||
|
|
||
| def get_model_info_manage(self): | ||
| return model_info_manage | ||
|
|
||
| def get_model_provide_info(self): | ||
| return ModelProvideInfo(provider='model_tencent_cloud_provider', name=_('Tencent Cloud'), icon=get_file_content( | ||
| os.path.join(PROJECT_DIR, "apps", "setting", 'models_provider', 'impl', 'tencent_cloud_model_provider', | ||
| 'icon', | ||
| 'tencent_cloud_icon_svg'))) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is one potential issue: The |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code appears to be properly structured, including importing necessary modules and defining classes with specific functionalities. However, here are a few improvements and points to consider:
Improvements:
Whitespace Consistency: The code uses inconsistent indentation levels (4 spaces vs. tabs). It's recommended to stick with one style consistently.
Comments and Formatting: Ensure comments explain complex logic or decisions clearly. Also, format functions and variables using PEP8 conventions for better readability.
Docstring Style: Use Google-style docstrings instead of Django-style doc strings for consistency.
Error Handling: Consider adding more detailed logging around exceptions to help with debugging.
Security Practices: Always ensure sensitive information like API keys is handled securely, especially when they're being used to interact with external services.
Type Hints: Although Python 3 supports type hints well, it might be helpful to include them in all class methods where applicable.
Testing: Add unit tests to cover different scenarios, such as valid and invalid credentials, model invocation failures, etc.
Here are some example adjustments:
These changes improve code maintainability, readability, and security practices while adhering to best coding standards.