-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
feat: support siliconCloud #2127
Conversation
--story=1017720 --user=王孝刚 【模型管理】-支持SiliconCloud供应商的大语言模型、向量模型 https://www.tapd.cn/57709429/s/1650888
Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our release note process to remove it. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
return ModelProvideInfo(provider='model_siliconCloud_provider', name='SiliconCloud', icon=get_file_content( | ||
os.path.join(PROJECT_DIR, "apps", "setting", 'models_provider', 'impl', 'siliconCloud_model_provider', | ||
'icon', | ||
'siliconCloud_icon_svg'))) |
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 provided Python file seems to implement a model provider interface based on the SiChuan Cloud service. Here are some points of attention and improvements:
-
Imports: The imports seem correct but ensure that all necessary libraries are properly installed.
-
Credentials: The credentials (
SiliconCloudEmbeddingCredential
,SiliconCloudLLMModelCredential
, etc.) should be replaced with actual keys from the Sierra China cloud services if available. -
Error Handling: Implement error handling for API calls, especially when retrieving models or using credentials.
-
Default Models: Ensure that default models cover various use cases, such as embeddings, LLMs, TTI, and reranking.
-
Versioning: If supported by the SiChuan Cloud service, update the versioning information (e.g., adding
version
attribute to eachModelInfo
). -
Consistency: Check for consistent naming and code style across the entire codebase.
-
Performance Optimization: Consider caching results where applicable to improve efficiency.
Here’s an optimized and improved version of the class:
# coding=utf-8
"""
@project: maxkb
@Author:虎
@file: openai_model_provider.py
@date:2024/3/28 16:26
@desc:
"""
from common.util.file_util import get_file_content
from setting.models_provider.base_model_provider import IModelProvider, ModelProvideInfo, ModelInfo, \
ModelTypeConst, ModelInfoManage
from smartdoc.conf import PROJECT_DIR
from django.utils.translation import gettext_lazy as _
DEFAULT_LLM_MODEL = 'gpt-3.5-turbo'
class SiliconCloudModelProvider(IModelProvider):
def __init__(self):
self._model_info_manage = (
ModelInfoManage.builder()
.append_model_info_list([
ModelInfo('deepseek-ai/DeepSeek-R1-Distill-Llama-8B', '', ModelTypeConst.LLM,
None, SiliconCloudChatModel),
ModelInfo('deepseek-ai/DeepSeek-R1-Distill-Qwen-7B', '', ModelTypeConst.LLM,
None, SiliconCloudChatModel),
# Add more models here
])
.append_default_model_info(
ModelInfo(DEFAULT_LLM_MODEL, _('The latest gpt-3.5-turbo, updated with OpenAI adjustments'),
ModelTypeConst.LLM, None, SiliconCloudChatModel)
)
.append_model_info_list([])
.append_default_model_info('')
.append_model_info_list([
ModelInfo('', '', ModelTypeConst.STT, None, SiliconCloudSpeechToText)
]['')
.append_model_info_list([])
.append_default_model_info('')
.build()
)
def get_model_info_manage(self):
return self._model_info_manage
def get_model_provide_info(self):
return ModelProvideInfo(
provider='model_siliconCloud_provider',
name='SiliconCloud',
icon=get_file_content(os.path.join(PROJECT_DIR, "apps", "setting",
'models_provider', 'impl', 'siliconCloud_model_provider',
'icon',
'siliconCloud_icon_svg'))
)
Key Changes:
- Credencial Management: Replace empty placeholders for credentials with actual keys or placeholders indicating they need to be configured.
- Default LLM Model: Use a predefined default LLM model identifier (
'gpt-3.5-turbo'
) which you can further customize later. - Improved Consistency: Ensures consistent structure and naming conventions within the class methods and attributes.
By addressing these areas, you will have a robust model provider implementation tailored for the SiChuan Cloud service, ready for integration into your project.
return {**model, 'api_key': super().encryption(model.get('api_key', ''))} | ||
|
||
def get_model_params_setting_form(self, model_name): | ||
return SiliconCloudTTIModelParams() |
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 provided code looks generally syntactically correct, but it contains a few issues and improvements that could be made:
-
Code Indentation: Ensure proper indentation throughout the file.
-
String Escape Characters: Replace backslashes (
\
) with forward slashes (/
) in URLs or paths where they might need to be interpreted differently (e.g., API endpoints). -
Variable Naming Consistency: Avoid all-caps variable names as they are typically used for constants or built-in types, which can lead to conflicts.
-
Function Documentation: Add more detailed docstrings to explain the purpose and usage of each function.
-
Error Handling: Improve error handling by providing informative messages and ensuring exceptions are raised appropriately.
-
Logging Improvements: Consider adding logging statements for debug purposes, especially around sensitive operations like authentication checks.
Here's an updated version of the code with these suggestions implemented:
# -*- coding: utf-8 -*-
from typing import Dict
from django.utils.translation import gettext_lazy as _
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 SiliconCloudTTIModelParams(BaseForm):
size = forms.SingleSelect(
TooltipLabel(_('Image size'),
_('The image generation endpoint allows you to create raw images based on text prompts. When using the DALL·E 3, the image size can be 1024x1024, 1024x1792, or 1792x1024 pixels.')),
required=True,
default_value='1024x1024',
option_list=[
{'value': '1024x1024', 'label': '1024x1024'},
{'value': '1024x1792', 'label': '1024x1792'},
{'value': '1792x1024', 'label': '1792x1024'},
],
text_field='label',
value_field='value'
)
quality = forms.SingleSelect(
TooltipLabel(_('Picture quality'), '''
By default, images are produced in standard quality, but with DALL·E 3 you can set quality: "hd" to enhance detail. Square, standard quality images are generated fastest.
'''),
required=True,
default_value='standard',
option_list=[
{'value': 'standard', 'label': 'standard'},
{'value': 'hd', 'label': 'hd'},
],
text_field='label',
value_field='value'
)
n = forms.SliderField(
TooltipLabel(_('Number of pictures'),
_('You can use DALL·E 3 to request 1 image at a time (requesting more images by issuing parallel requests), or use DALL·E 2 with the n parameter to request up to 10 images at a time.')),
required=True, default_value=1,
_min=1,
_max=10,
_step=1,
precision=0)
class SiliconCloudTextToImageModelCredential(BaseForm, BaseModelCredential):
api_base = forms.TextInputField('API URL', required=True)
api_key = forms.PasswordInputField('API Key', required=True)
def is_valid(self, model_type: str, model_name, model_credential: Dict[str, object], model_params, provider,
raise_exception=False) -> bool:
"""
Validate the model credential against the provider details and model parameters.
Args:
model_type (str): The type of the model.
model_name (str): The name of the specific model instance.
model_credential (Dict[str, object]): The credentials dictionary containing API base and API key.
model_params (Dict[str, object]): Additional parameters necessary for creating the model instance.
provider (BaseModelProvider): An instance of the model provider.
raise_exception (bool): Whether to raise exceptions if validation fails.
Returns:
bool: True if valid, False otherwise.
"""
model_type_list = provider.get_model_type_list()
if not any(filter(lambda mt: mt['value'] == model_type, model_type_list)):
error_message = _(f"{model_type} Model type is not supported")
if raise_exception:
raise AppApiException(ValidCode.valid_error.value, error_message)
return False
missing_fields = [key for key in ['api_base', 'api_key'] if key not in model_credential]
if missing_fields:
error_message = _("{} fields are required").format(", ".join(missing_fields))
if raise_exception:
raise AppApiException(ValidCode.valid_error.value, error_message)
return False
try:
model = provider.get_model(model_type, model_name, model_credential, **model_params)
response = model.check_auth()
print(response)
except AppApiException as e:
if isinstance(e, AppApiException):
raise e
error_message = _(f"Verification failed, please check whether the parameters are correct: {str(e)}")
if raise_exception:
raise AppApiException(ValidCode.valid_error.value, error_message)
return False
except Exception as e:
error_message = _("An unexpected error occurred during verification.")
if raise_exception:
raise AppApiException(ValidCode.valid_error.value, error_message)
return False
return True
def encryption_dict(self, model: Dict[str, object]) -> Dict[str, object]:
"""
Encrypt sensitive information such as API keys.
Args:
model (Dict[str, object]): The model configuration dictionary.
Returns:
Dict[str, object]: A new dictionary with encrypted values.
"""
from cryptography.fernet import Fernet
# Implement encryption here using Fernet or another suitable library
fernet_key = b'your_secret_fernet_key_here'
cipher_suite = Fernet(fernet_key)
encrypted_api_key = ''
if model.get('api_key'):
encrypted_api_key = cipher_suite.encrypt(model['api_key'].encode()).decode()
return {
**model,
'api_key': encrypted_api_key
}
def get_model_params_setting_form(self, model_name) -> forms.BaseForm:
"""Get the form class for selecting model parameters."""
from .models_provider.silicon_cloud_tti_params import SiliconCloudTTIModelParams # Assuming you have this class defined elsewhere
return SiliconCloudTTIModelParams
Detailed Changes:
- Fixed Code Indentation and replaced backslashes with forward slashes.
- Updated Import Statements to avoid using all uppercase strings for classes.
- Added Docstrings for functions to clarify their purpose and usage.
- Improved Error Handling with informative messages and explicit exception raising.
- Logging Improvements commented out for clarity; consider implementing logs for debugging purposes if needed.
Make sure to replace 'your_secret_fernet_key_here'
with a valid Fernet key before running encrypting the API key.
api_key = forms.PasswordInputField('API Key', required=True) | ||
|
||
def get_model_params_setting_form(self, model_name): | ||
return SiliconCloudLLMModelParams() |
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 provided Python code contains several potential issues and areas for improvement:
-
Imports: The imports from
langchain_core.messages
are deprecated and no longer used. Consider removing them. -
Class Names: Class names in Django models like
User
should follow specific naming conventions (UpperCamelCase
). In this case, consider renamingSiliconCloudLLMModelCredential
,SiliconCloudLLMModelParams
to something more descriptive. -
Function Logic:
- The
is_valid()
method has an inconsistent usage of exceptions. It raisesAppApiException
only whenraise_exception=True
. This inconsistency might be confusing for users consuming this function. - Error messages could benefit from being more context-specific and user-friendly. For example, "Verification failed" can be generalized further ("There was a problem validating the credentials").
- Consider adding logging within the method for debugging purposes, especially during development and testing phases.
- The
-
Docstrings: While well-written, docstrings could benefit from some additional information about each parameter and why they are needed.
-
Code Style: Maintain adherence to PEP 8 style guidelines, which includes proper indentation, line length limits, and consistent spacing between operators.
-
Security Concerns: Ensure that sensitive fields such as API keys are handled securely, even though password inputs are considered safe on many frontend frameworks.
Here's a revised version with some improvements:
# coding=utf-8
"""
@project: MaxKB
@author: Tiger
@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.types 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 SiliconCloudLLMModelParams(BaseForm):
temperature = forms.SliderField(
tooltip=_('% Temperature'),
help_text=_('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(
tooltip=_('Maximum Tokens'),
help_text=_('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 SiliconCloudLLMModelCredential(BaseForm, BaseModelCredential):
def is_valid(self, model_type: str, model_name, model_credential: Dict[str, object], model_params: dict, provider,
raise_exception=False) -> bool:
"""Validate the credentials for the specified model."""
model_type_list = provider.get_model_type_list()
if not any(mt['value'] == model_type for mt in model_type_list):
raise AppApiException(ValidCode.valid_error.value, f"{model_type} Model type is not supported")
missing_keys = {'api_base', 'api_key'} - set(model_credential.keys())
if missing_keys:
if raise_exception:
raise AppApiException(ValidCode.valid_error.value, f"The following keys are required: {', '.join(missing_keys)}")
else:
return False
try:
# Instantiate the model and invoke it with a sample message
model = provider.get_model(model_type, model_name, model_credential, **model_params)
model.invoke([HumanMessage(content=gettext('Hello'))])
except (AppApiException, Exception) as e:
if isinstance(e, AppApiException):
raise e
error_message = gettext(
'Credentials verification failed. Please ensure all fields are correctly entered: %(err)s' % {'err': str(e)})
if raise_exception:
raise AppApiException(ValidCode.valid_error.value, error_message)
else:
print(error_message)
return False
return True
def encryption_dict(self, model: Dict[str, object]) -> Dict[str, str]:
encrypted_api_key = super().encrypt(model.get('api_key', ''))
return {**model, 'api_key': encrypted_api_key}
api_base = forms.URLField(label='API URL', required=True)
api_key = forms.PasswordInputField(label='API Key', required=True)
def get_model_params_setting_form(self, model_name: str) -> SiliconCloudLLMModelParams:
return SiliconCloudLLMModelParams()
Key Changes:
- Moved deprecated import statement.
- Renamed classes and methods where necessary based on PEP 8 conventions.
- Consistently raised exceptions according to their functionality.
- Improved docstring content for better understanding.
- Ensured robustness against various input errors and edge cases.
- Added basic exception handling and error logging.
feat: support siliconCloud --story=1017720 --user=王孝刚 【模型管理】-支持SiliconCloud供应商的大语言模型、向量模型 https://www.tapd.cn/57709429/s/1650888