Skip to content

Commit 590a7a3

Browse files
committed
feat: implement Docker AI model provider with various model credentials and parameters
1 parent 62cbb7a commit 590a7a3

File tree

23 files changed

+1027
-4
lines changed

23 files changed

+1027
-4
lines changed

apps/locales/en_US/LC_MESSAGES/django.po

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8772,4 +8772,13 @@ msgid "Application token usage statistics"
87728772
msgstr ""
87738773

87748774
msgid "Application top question statistics"
8775+
msgstr ""
8776+
8777+
msgid "SAML2 Metadata"
8778+
msgstr ""
8779+
8780+
msgid "SAML2 Log in"
8781+
msgstr ""
8782+
8783+
msgid "SAML2 SSO"
87758784
msgstr ""

apps/locales/zh_CN/LC_MESSAGES/django.po

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8899,3 +8899,12 @@ msgstr "应用令牌使用统计"
88998899

89008900
msgid "Application top question statistics"
89018901
msgstr "应用提问次数统计"
8902+
8903+
msgid "SAML2 Metadata"
8904+
msgstr "SAML2 元数据"
8905+
8906+
msgid "SAML2 Log in"
8907+
msgstr "SAML2 登录"
8908+
8909+
msgid "SAML2 SSO"
8910+
msgstr "SAML2 单点登录"

apps/locales/zh_Hant/LC_MESSAGES/django.po

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8898,4 +8898,13 @@ msgid "Application token usage statistics"
88988898
msgstr "應用令牌使用統計"
88998899

89008900
msgid "Application top question statistics"
8901-
msgstr "應用提問次數統計"
8901+
msgstr "應用提問次數統計"
8902+
8903+
msgid "SAML2 Metadata"
8904+
msgstr "SAML2 元數據"
8905+
8906+
msgid "SAML2 Log in"
8907+
msgstr "SAML2 登入"
8908+
8909+
msgid "SAML2 SSO"
8910+
msgstr "SAML2 單點登入"

apps/models_provider/constants/model_provider_constants.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from models_provider.impl.aws_bedrock_model_provider.aws_bedrock_model_provider import BedrockModelProvider
88
from models_provider.impl.azure_model_provider.azure_model_provider import AzureModelProvider
99
from models_provider.impl.deepseek_model_provider.deepseek_model_provider import DeepSeekModelProvider
10+
from models_provider.impl.docker_ai_model_provider.docker_ai_model_provider import DockerModelProvider
1011
from models_provider.impl.gemini_model_provider.gemini_model_provider import GeminiModelProvider
1112
from models_provider.impl.kimi_model_provider.kimi_model_provider import KimiModelProvider
1213
from models_provider.impl.local_model_provider.local_model_provider import LocalModelProvider
@@ -30,6 +31,7 @@ class ModelProvideConstants(Enum):
3031
model_wenxin_provider = WenxinModelProvider()
3132
model_ollama_provider = OllamaModelProvider()
3233
model_openai_provider = OpenAIModelProvider()
34+
model_docker_ai_provider = DockerModelProvider()
3335
model_kimi_provider = KimiModelProvider()
3436
model_zhipu_provider = ZhiPuModelProvider()
3537
model_xf_provider = XunFeiModelProvider()
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# coding=utf-8
2+
"""
3+
@project: maxkb
4+
@Author:虎
5+
@file: __init__.py.py
6+
@date:2024/3/28 16:25
7+
@desc:
8+
"""

apps/models_provider/impl/docker_ai_model_provider/credential/__init__.py

Whitespace-only changes.
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# coding=utf-8
2+
"""
3+
@project: MaxKB
4+
@Author:虎
5+
@file: embedding.py
6+
@date:2024/7/12 16:45
7+
@desc:
8+
"""
9+
from typing import Dict
10+
11+
from django.utils.translation import gettext as _
12+
13+
from common import forms
14+
from common.exception.app_exception import AppApiException
15+
from common.forms import BaseForm, TooltipLabel
16+
from models_provider.base_model_provider import BaseModelCredential, ValidCode
17+
from common.utils.logger import maxkb_logger
18+
19+
class DockerAIEmbeddingModelParams(BaseForm):
20+
dimensions = forms.SingleSelect(
21+
TooltipLabel(
22+
_('Dimensions'),
23+
_('')
24+
),
25+
required=True,
26+
default_value=1024,
27+
value_field='value',
28+
text_field='label',
29+
option_list=[
30+
{'label': '1536', 'value': '1536'},
31+
{'label': '1024', 'value': '1024'},
32+
{'label': '768', 'value': '768'},
33+
{'label': '512', 'value': '512'},
34+
]
35+
)
36+
37+
38+
class DockerAIEmbeddingCredential(BaseForm, BaseModelCredential):
39+
def is_valid(self, model_type: str, model_name, model_credential: Dict[str, object], model_params, provider,
40+
raise_exception=True):
41+
model_type_list = provider.get_model_type_list()
42+
if not any(list(filter(lambda mt: mt.get('value') == model_type, model_type_list))):
43+
raise AppApiException(ValidCode.valid_error.value,
44+
_('{model_type} Model type is not supported').format(model_type=model_type))
45+
46+
for key in ['api_base', 'api_key']:
47+
if key not in model_credential:
48+
if raise_exception:
49+
raise AppApiException(ValidCode.valid_error.value, _('{key} is required').format(key=key))
50+
else:
51+
return False
52+
try:
53+
model = provider.get_model(model_type, model_name, model_credential)
54+
model.embed_query(_('Hello'))
55+
except Exception as e:
56+
maxkb_logger.error(f'Exception: {e}', exc_info=True)
57+
if isinstance(e, AppApiException):
58+
raise e
59+
if raise_exception:
60+
raise AppApiException(ValidCode.valid_error.value,
61+
_('Verification failed, please check whether the parameters are correct: {error}').format(
62+
error=str(e)))
63+
else:
64+
return False
65+
return True
66+
67+
def encryption_dict(self, model: Dict[str, object]):
68+
return {**model, 'api_key': super().encryption(model.get('api_key', ''))}
69+
70+
def get_model_params_setting_form(self, model_name):
71+
return DockerAIEmbeddingModelParams()
72+
73+
api_base = forms.TextInputField('API URL', required=True)
74+
api_key = forms.PasswordInputField('API Key', required=True)
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# coding=utf-8
2+
import base64
3+
import os
4+
from typing import Dict
5+
6+
from langchain_core.messages import HumanMessage
7+
8+
from common import forms
9+
from common.exception.app_exception import AppApiException
10+
from common.forms import BaseForm, TooltipLabel
11+
from common.utils.logger import maxkb_logger
12+
from models_provider.base_model_provider import BaseModelCredential, ValidCode
13+
from django.utils.translation import gettext_lazy as _, gettext
14+
15+
16+
class DockerAIImageModelParams(BaseForm):
17+
temperature = forms.SliderField(TooltipLabel(_('Temperature'),
18+
_('Higher values make the output more random, while lower values make it more focused and deterministic')),
19+
required=True, default_value=0.7,
20+
_min=0.1,
21+
_max=1.0,
22+
_step=0.01,
23+
precision=2)
24+
25+
max_tokens = forms.SliderField(
26+
TooltipLabel(_('Output the maximum Tokens'),
27+
_('Specify the maximum number of tokens that the model can generate')),
28+
required=True, default_value=800,
29+
_min=1,
30+
_max=100000,
31+
_step=1,
32+
precision=0)
33+
34+
35+
class DockerAIImageModelCredential(BaseForm, BaseModelCredential):
36+
api_base = forms.TextInputField('API URL', required=True)
37+
api_key = forms.PasswordInputField('API Key', required=True)
38+
39+
def is_valid(self, model_type: str, model_name, model_credential: Dict[str, object], model_params, provider,
40+
raise_exception=False):
41+
model_type_list = provider.get_model_type_list()
42+
if not any(list(filter(lambda mt: mt.get('value') == model_type, model_type_list))):
43+
raise AppApiException(ValidCode.valid_error.value,
44+
gettext('{model_type} Model type is not supported').format(model_type=model_type))
45+
46+
for key in ['api_base', 'api_key']:
47+
if key not in model_credential:
48+
if raise_exception:
49+
raise AppApiException(ValidCode.valid_error.value, gettext('{key} is required').format(key=key))
50+
else:
51+
return False
52+
try:
53+
model = provider.get_model(model_type, model_name, model_credential, **model_params)
54+
res = model.stream([HumanMessage(content=[{"type": "text", "text": gettext('Hello')}])])
55+
for chunk in res:
56+
maxkb_logger.info(chunk)
57+
except Exception as e:
58+
maxkb_logger.error(f'Exception: {e}', exc_info=True)
59+
if isinstance(e, AppApiException):
60+
raise e
61+
if raise_exception:
62+
raise AppApiException(ValidCode.valid_error.value,
63+
gettext(
64+
'Verification failed, please check whether the parameters are correct: {error}').format(
65+
error=str(e)))
66+
else:
67+
return False
68+
return True
69+
70+
def encryption_dict(self, model: Dict[str, object]):
71+
return {**model, 'api_key': super().encryption(model.get('api_key', ''))}
72+
73+
def get_model_params_setting_form(self, model_name):
74+
return DockerAIImageModelParams()
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# coding=utf-8
2+
"""
3+
@project: MaxKB
4+
@Author:虎
5+
@file: llm.py
6+
@date:2024/7/11 18:32
7+
@desc:
8+
"""
9+
from typing import Dict
10+
11+
from django.utils.translation import gettext_lazy as _, gettext
12+
from langchain_core.messages import HumanMessage
13+
from openai import BadRequestError
14+
15+
from common import forms
16+
from common.exception.app_exception import AppApiException
17+
from common.forms import BaseForm, TooltipLabel
18+
from models_provider.base_model_provider import BaseModelCredential, ValidCode
19+
from common.utils.logger import maxkb_logger
20+
21+
class DockerAILLMModelParams(BaseForm):
22+
temperature = forms.SliderField(TooltipLabel(_('Temperature'),
23+
_('Higher values make the output more random, while lower values make it more focused and deterministic')),
24+
required=True, default_value=0.7,
25+
_min=0.1,
26+
_max=1.0,
27+
_step=0.01,
28+
precision=2)
29+
30+
max_tokens = forms.SliderField(
31+
TooltipLabel(_('Output the maximum Tokens'),
32+
_('Specify the maximum number of tokens that the model can generate')),
33+
required=True, default_value=800,
34+
_min=1,
35+
_max=100000,
36+
_step=1,
37+
precision=0)
38+
39+
40+
class DockerAILLMModelCredential(BaseForm, BaseModelCredential):
41+
42+
def is_valid(self, model_type: str, model_name, model_credential: Dict[str, object], model_params, provider,
43+
raise_exception=False):
44+
model_type_list = provider.get_model_type_list()
45+
if not any(list(filter(lambda mt: mt.get('value') == model_type, model_type_list))):
46+
raise AppApiException(ValidCode.valid_error.value,
47+
gettext('{model_type} Model type is not supported').format(model_type=model_type))
48+
49+
for key in ['api_base', 'api_key']:
50+
if key not in model_credential:
51+
if raise_exception:
52+
raise AppApiException(ValidCode.valid_error.value, gettext('{key} is required').format(key=key))
53+
else:
54+
return False
55+
try:
56+
57+
model = provider.get_model(model_type, model_name, model_credential, **model_params)
58+
model.invoke([HumanMessage(content=gettext('Hello'))])
59+
except Exception as e:
60+
maxkb_logger.error(f'Exception: {e}', exc_info=True)
61+
if isinstance(e, AppApiException) or isinstance(e, BadRequestError):
62+
raise e
63+
if raise_exception:
64+
raise AppApiException(ValidCode.valid_error.value,
65+
gettext(
66+
'Verification failed, please check whether the parameters are correct: {error}').format(
67+
error=str(e)))
68+
else:
69+
return False
70+
return True
71+
72+
def encryption_dict(self, model: Dict[str, object]):
73+
return {**model, 'api_key': super().encryption(model.get('api_key', ''))}
74+
75+
api_base = forms.TextInputField('API URL', required=True)
76+
api_key = forms.PasswordInputField('API Key', required=True)
77+
78+
def get_model_params_setting_form(self, model_name):
79+
return DockerAILLMModelParams()
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# coding=utf-8
2+
"""
3+
@project: MaxKB
4+
@Author:虎
5+
@file: reranker.py
6+
@date:2024/9/9 17:51
7+
@desc:
8+
"""
9+
from typing import Dict
10+
11+
from django.utils.translation import gettext as _
12+
from langchain_core.documents import Document
13+
14+
from common import forms
15+
from common.exception.app_exception import AppApiException
16+
from common.forms import BaseForm
17+
from models_provider.base_model_provider import BaseModelCredential, ValidCode
18+
from models_provider.impl.docker_ai_model_provider.model.reranker import DockerAIReranker
19+
from common.utils.logger import maxkb_logger
20+
21+
class DockerAIRerankerCredential(BaseForm, BaseModelCredential):
22+
23+
def is_valid(self, model_type: str, model_name, model_credential: Dict[str, object], model_params, provider,
24+
raise_exception=False):
25+
if not model_type == 'RERANKER':
26+
raise AppApiException(ValidCode.valid_error.value,
27+
_('{model_type} Model type is not supported').format(model_type=model_type))
28+
for key in ['api_base']:
29+
if key not in model_credential:
30+
if raise_exception:
31+
raise AppApiException(ValidCode.valid_error.value, _('{key} is required').format(key=key))
32+
else:
33+
return False
34+
try:
35+
model: DockerAIReranker = provider.get_model(model_type, model_name, model_credential)
36+
model.compress_documents([Document(page_content=_('Hello'))], _('Hello'))
37+
except Exception as e:
38+
maxkb_logger.error(f'Exception: {e}', exc_info=True)
39+
if isinstance(e, AppApiException):
40+
raise e
41+
if raise_exception:
42+
raise AppApiException(ValidCode.valid_error.value,
43+
_('Verification failed, please check whether the parameters are correct: {error}').format(
44+
error=str(e)))
45+
else:
46+
return False
47+
return True
48+
49+
def encryption_dict(self, model: Dict[str, object]):
50+
return {**model}
51+
api_base = forms.TextInputField('API URL', required=True)

0 commit comments

Comments
 (0)