You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
526 lines
25 KiB
526 lines
25 KiB
import dash
|
|
import time
|
|
import uuid
|
|
from dash import dcc,html
|
|
from dash.dependencies import Input, Output, State, ALL
|
|
from dash.exceptions import PreventUpdate
|
|
import feffery_utils_components as fuc
|
|
import feffery_antd_components as fac
|
|
import feffery_markdown_components as fmc
|
|
from server import app
|
|
from utils.common import validate_data_not_empty,process_string
|
|
from api.modmag import get_model_info_api,get_model_info_extend_api,get_model_engine_api
|
|
|
|
|
|
app.clientside_callback(
|
|
'''(value) => value''',
|
|
Output('model-tree', 'searchKeyword'),
|
|
Input('model-input-search', 'value')
|
|
)
|
|
|
|
@app.callback(
|
|
[Output("side-drawer", "visible"), Output("side-drawer", "children"),Output('side-drawer', 'title')],
|
|
Input(
|
|
{
|
|
"type": "card-button",
|
|
"model_name": ALL,
|
|
"index": ALL,
|
|
},
|
|
"nClicks",
|
|
),
|
|
State('model-infos', 'data'),
|
|
prevent_initial_call=True,
|
|
)
|
|
# def control_side_drawer(_,model_infos):
|
|
|
|
# return [
|
|
# True,
|
|
# "产品 {} 的 {} 被点击了".format(
|
|
# dash.ctx.triggered_id["model_name"], dash.ctx.triggered_id["index"]
|
|
# ),
|
|
# ]
|
|
def control_side_drawer(_,model_infos):
|
|
print("进入回调")
|
|
# print(dash.ctx.triggered_id["model_name"])
|
|
# print("********")
|
|
# print(model_infos)
|
|
# print("********")
|
|
# mode_info = get_model_info_api(dash.ctx.triggered_id["model_name"])
|
|
# print(model_infos)
|
|
# mode_info_extend = get_model_info_extend_api(dash.ctx.triggered_id["model_name"])
|
|
|
|
if dash.ctx.triggered_id["index"] == "button1":
|
|
mode_info = get_model_info_api(dash.ctx.triggered_id["model_name"])
|
|
return [
|
|
True,
|
|
[
|
|
fac.AntdDescriptions(
|
|
[
|
|
fac.AntdDescriptionItem(mode_info["model_name_en"], label='英文名称'),
|
|
fac.AntdDescriptionItem(mode_info["model_name_cn"], label='中文名称'),
|
|
fac.AntdDescriptionItem(mode_info["model_fune_flag"], label='微调支持'),
|
|
fac.AntdDescriptionItem(mode_info["model_release_date"], label='发布日期'),
|
|
fac.AntdDescriptionItem(
|
|
html.A(
|
|
mode_info["model_website_url"],
|
|
href= mode_info["model_website_url"],
|
|
),
|
|
label='模型网址',
|
|
span=2
|
|
),
|
|
fac.AntdDescriptionItem(
|
|
mode_info["model_note"],
|
|
label='模型描述',
|
|
span=2
|
|
),
|
|
fac.AntdDescriptionItem(
|
|
mode_info["model_prmopt"],
|
|
label='prompt示例',
|
|
span=2
|
|
),
|
|
],
|
|
# title='描述列表示例',
|
|
# bordered=True,
|
|
column=2,
|
|
# layout='vertical',
|
|
labelStyle={'fontWeight': 'bold',
|
|
'fontSize': '16px',
|
|
},
|
|
contentStyle={
|
|
'fontSize': '16px',
|
|
},
|
|
)
|
|
],dash.ctx.triggered_id["model_name"]
|
|
]
|
|
elif dash.ctx.triggered_id["index"] == "button2":
|
|
mode_info_extend = get_model_info_extend_api(dash.ctx.triggered_id["model_name"])
|
|
return [
|
|
True,
|
|
fac.AntdTabs(
|
|
items=[
|
|
{
|
|
'key': f'curl',
|
|
'label': f'curl',
|
|
'children': fmc.FefferySyntaxHighlighter(
|
|
codeString= mode_info_extend["curl_code"],
|
|
language='sql',
|
|
codeTheme='night-owl',
|
|
# ),
|
|
codeStyle={
|
|
# 'backgroundColor': 'rgb(240, 242, 245)',
|
|
'maxHeight': '100px', # 确保代码块高度不超过右侧区域的50%
|
|
'overflowY': 'scroll',
|
|
'overflowX': 'scroll',
|
|
'fontSize': '16px'
|
|
# 'paddingLeft': '5px',
|
|
# 'marginTop': '5px'
|
|
}
|
|
),
|
|
},
|
|
{
|
|
'key': f'python',
|
|
'label': f'python',
|
|
'children': fmc.FefferySyntaxHighlighter(
|
|
codeString= mode_info_extend["python_code"],
|
|
language='python',
|
|
codeTheme='night-owl',
|
|
# ),
|
|
codeStyle={
|
|
# 'backgroundColor': 'rgb(240, 242, 245)',
|
|
'maxHeight': '400px', # 确保代码块高度不超过右侧区域的50%
|
|
'overflowY': 'scroll',
|
|
'overflowX': 'scroll',
|
|
'fontSize': '16px'
|
|
# 'paddingLeft': '5px',
|
|
# 'marginTop': '5px'
|
|
}
|
|
),
|
|
},
|
|
{
|
|
'key': f'java',
|
|
'label': f'java',
|
|
'children': fmc.FefferySyntaxHighlighter(
|
|
codeString= mode_info_extend["java_code"],
|
|
language='java',
|
|
codeTheme='night-owl',
|
|
# ),
|
|
codeStyle={
|
|
# 'backgroundColor': 'rgb(240, 242, 245)',
|
|
'maxHeight': '400px', # 确保代码块高度不超过右侧区域的50%
|
|
'overflowY': 'scroll',
|
|
'overflowX': 'scroll',
|
|
'fontSize': '16px'
|
|
# 'paddingLeft': '5px',
|
|
# 'marginTop': '5px'
|
|
}
|
|
),
|
|
}
|
|
],
|
|
style={'fontSize': 40},
|
|
size = 'large'
|
|
),
|
|
dash.ctx.triggered_id["model_name"]
|
|
]
|
|
elif dash.ctx.triggered_id["index"] == "button3":
|
|
mode_engine_info = get_model_engine_api(dash.ctx.triggered_id["model_name"])
|
|
print(mode_engine_info)
|
|
print(type(mode_engine_info))
|
|
model_engines = list(mode_engine_info.keys())
|
|
# 用于存储所有model_format的列表
|
|
model_formats = set()
|
|
model_sizes = set()
|
|
model_quantizations = set()
|
|
# 遍历每个分类
|
|
for item in mode_engine_info.values():
|
|
for model in item:
|
|
model_formats.add(model['model_format'])
|
|
model_sizes.add(model['model_size_in_billions'])
|
|
for quant in model['quantizations']:
|
|
model_quantizations.add(quant)
|
|
|
|
# 将集合转换为列表
|
|
model_formats_list = list(model_formats)
|
|
model_sizes_list = list(model_sizes)
|
|
model_quantizations_list = list(model_quantizations)
|
|
|
|
return [
|
|
True,
|
|
html.Div([
|
|
# fac.AntdDivider('基础信息', innerTextOrientation='left'),
|
|
fac.AntdForm(
|
|
[
|
|
fac.AntdFormItem(
|
|
fac.AntdSelect(
|
|
id='form-item-model-engine',
|
|
size='large',
|
|
placeholder='选择模型引擎',
|
|
options= model_engines,
|
|
# value='选项1',
|
|
style={'width': 620},
|
|
),
|
|
# label='模型引擎',
|
|
labelCol={'flex': 'none'},
|
|
wrapperCol={'flex': 'auto'},
|
|
),
|
|
fac.AntdFormItem(
|
|
fac.AntdSelect(
|
|
id='form-item-model-format',
|
|
size='large',
|
|
placeholder='选择模型格式',
|
|
options= model_formats_list,
|
|
# value='选项1',
|
|
style={'width': 620},
|
|
),
|
|
# label='模型引擎',
|
|
labelCol={'flex': 'none'},
|
|
wrapperCol={'flex': 'auto'},
|
|
),
|
|
fac.AntdFormItem(
|
|
fac.AntdSelect(
|
|
id='form-item-model-size',
|
|
size='large',
|
|
placeholder='选择模型参数',
|
|
options= model_sizes_list,
|
|
# value='选项1',
|
|
style={'width': 620},
|
|
),
|
|
# label='模型引擎',
|
|
labelCol={'flex': 'none'},
|
|
wrapperCol={'flex': 'auto'},
|
|
),
|
|
fac.AntdFormItem(
|
|
fac.AntdSelect(
|
|
id='form-item-model-quant',
|
|
size='large',
|
|
placeholder='选择量化参数',
|
|
options= model_quantizations_list,
|
|
# value='选项1',
|
|
style={'width': 620},
|
|
),
|
|
# label='模型引擎',
|
|
labelCol={'flex': 'none'},
|
|
wrapperCol={'flex': 'auto'},
|
|
),
|
|
fac.AntdFormItem(
|
|
fac.AntdSelect(
|
|
id='form-item-model-gpu',
|
|
size='large',
|
|
placeholder='选择GPU或者CPU',
|
|
options= ['auto',"cpu","gpu"],
|
|
# value='选项1',
|
|
style={'width': 620},
|
|
),
|
|
# label='模型引擎',
|
|
labelCol={'flex': 'none'},
|
|
wrapperCol={'flex': 'auto'},
|
|
),
|
|
fac.AntdFormItem(
|
|
fac.AntdInput(
|
|
id='form-item-model-num',
|
|
size='large',
|
|
placeholder='填写部署模型数量',
|
|
style={
|
|
# "position": "absolute",
|
|
# "bottom": 8,
|
|
# "right": 20,
|
|
"width": "calc(100% - 30px)",
|
|
},
|
|
),
|
|
labelCol={'flex': 'none'},
|
|
wrapperCol={'flex': 'auto'},
|
|
),
|
|
fac.AntdFormItem(
|
|
fac.AntdAccordion(
|
|
items=[
|
|
{
|
|
'title': f'补充信息',
|
|
'key': f'补充信息',
|
|
'children': fac.AntdForm(
|
|
[
|
|
fac.AntdFormItem(
|
|
fac.AntdInput(
|
|
id='form-item-model-id',
|
|
size='large',
|
|
placeholder='参数1',
|
|
style={
|
|
"width": "calc(100% - 30px)",
|
|
"height": 50
|
|
},
|
|
),
|
|
# id='form-item-validate-demo-username-container',
|
|
# label='用户名',
|
|
),
|
|
fac.AntdFormItem(
|
|
fac.AntdInput(
|
|
id='form-item-worker-ip',
|
|
size='large',
|
|
placeholder='参数2',
|
|
style={
|
|
"width": "calc(100% - 30px)",
|
|
"marginTop": "20px",
|
|
"height": 50
|
|
},
|
|
),
|
|
style={
|
|
"marginTop": "5px"}
|
|
),
|
|
fac.AntdFormItem(
|
|
fac.AntdInput(
|
|
id='form-item-gpu-idx',
|
|
size='large',
|
|
placeholder='参数3',
|
|
style={
|
|
"width": "calc(100% - 30px)",
|
|
"marginTop": "20px",
|
|
"height": 50
|
|
},
|
|
),
|
|
style={
|
|
"marginTop": "5px"}
|
|
),
|
|
fac.AntdFormItem(
|
|
fac.AntdSelect(
|
|
id='form-item-download-hub',
|
|
size='large',
|
|
placeholder='参数4',
|
|
options= ['none',"huggingface","modelscope","modelscope"],
|
|
# value='选项1',
|
|
style={'width': 620,
|
|
"marginTop": "20px",
|
|
"height": 50
|
|
},
|
|
),
|
|
style={
|
|
"marginTop": "20px"}
|
|
),
|
|
fac.AntdFormItem(
|
|
fac.AntdInput(
|
|
id='form-item-model-path',
|
|
size='large',
|
|
placeholder='参数5',
|
|
style={
|
|
"width": "calc(100% - 30px)",
|
|
"marginTop": "20px",
|
|
"height": 50
|
|
},
|
|
),
|
|
style={
|
|
"marginTop": "20px"}
|
|
),
|
|
],
|
|
layout='vertical',
|
|
)
|
|
}
|
|
],
|
|
ghost=True,
|
|
style={
|
|
"height": 300}
|
|
),
|
|
),
|
|
fac.AntdFormItem(
|
|
fac.AntdButton(
|
|
'部署',
|
|
id='form-item-model-demo-submit',
|
|
type='primary',
|
|
)
|
|
),
|
|
],
|
|
# style={'width': 300},
|
|
)
|
|
]),
|
|
dash.ctx.triggered_id["model_name"]
|
|
]
|
|
# app.clientside_callback(
|
|
# # 处理控件组编辑抽屉的打开
|
|
# "() => true",
|
|
# Output({"type": "side-drawer"}, "visible"),
|
|
# Input(
|
|
# {
|
|
# "type": "card-button",
|
|
# "model_name": ALL,
|
|
# "index": ALL,
|
|
# },
|
|
# "nClicks",
|
|
# ),
|
|
# prevent_initial_call=True,
|
|
# )
|
|
|
|
#提交后执行外部访问
|
|
@app.callback(
|
|
[
|
|
Output('form-item-validate-demo-username-container', 'validateStatus'),
|
|
Output('form-item-validate-demo-password-container', 'validateStatus'),
|
|
Output('form-item-validate-demo-username-container', 'help'),
|
|
Output('form-item-validate-demo-password-container', 'help'),
|
|
],
|
|
Input('form-item-validate-demo-submit', 'nClicks'),
|
|
[
|
|
State('form-item-validate-demo-username', 'value'),
|
|
State('form-item-validate-demo-password', 'value'),
|
|
],
|
|
prevent_initial_call=True,
|
|
)
|
|
def form_item_model_process(nClicks, username, password):
|
|
if username and password:
|
|
return [
|
|
None if username == 'fac' else 'error',
|
|
('success' if password == '123456' else 'error')
|
|
if username == 'fac'
|
|
else None,
|
|
None if username == 'fac' else '用户不存在!',
|
|
('密码正确!' if password == '123456' else '密码错误!')
|
|
if username == 'fac'
|
|
else None,
|
|
]
|
|
|
|
return [
|
|
None if username else 'error',
|
|
None if password else 'error',
|
|
None if username else '用户名不能为空!',
|
|
None if password else '密码不能为空!',
|
|
]
|
|
|
|
|
|
|
|
@app.callback(
|
|
Output('card-container', 'children'),
|
|
[
|
|
Input('model-tree', 'selectedKeys'),
|
|
Input('model-search', 'nClicks'),
|
|
],
|
|
[
|
|
State('model-name-input', 'value'),
|
|
State('model-ability-select', 'value'),
|
|
State('model-status-select', 'value'),
|
|
State('model-infos', 'data')
|
|
],
|
|
prevent_initial_call=True,
|
|
|
|
)
|
|
# prevent_initial_call=True,
|
|
|
|
def get_model_data_by_tree(selectedKeys, search_click,
|
|
model_name, model_ability, model_status,model_infos):
|
|
|
|
print("进入选择回调new")
|
|
# print(selectedKeys)
|
|
# print(model_infos)
|
|
model_type = selectedKeys[0].split('/')[0]
|
|
model_family = selectedKeys[0].split('/')[1]
|
|
# 筛选出符合条件的项
|
|
data_new = [
|
|
item for item in model_infos
|
|
if item["model_type"] == model_type and item["model_family"] == model_family
|
|
]
|
|
return fac.AntdRow(
|
|
[
|
|
fac.AntdCol(
|
|
fac.AntdCard(
|
|
title=item.get('model_name'),
|
|
children=[
|
|
fac.AntdSpace(
|
|
[
|
|
html.Div(
|
|
fac.AntdCompact([
|
|
fac.AntdTag(content=tag)
|
|
for tag in (
|
|
(item['model_flag'].get('model_lang') if isinstance(item['model_flag'].get('model_lang'), list) else [item['model_flag'].get('model_lang')]) +
|
|
(item['model_flag'].get('model_ability') if isinstance(item['model_flag'].get('model_ability'), list) else [item['model_flag'].get('model_ability')]) +
|
|
([str(item['model_flag'].get('context_length'))] if item['model_flag'].get('context_length') is not None else [])
|
|
)
|
|
if tag is not None
|
|
])
|
|
),
|
|
html.Div(
|
|
process_string(item['model_description']),
|
|
# style={"marginBottom": "5px"}
|
|
),
|
|
html.Div(
|
|
fac.AntdCompact(
|
|
[
|
|
fac.AntdButton('查询信息',
|
|
id={
|
|
"type": "card-button",
|
|
"model_name": item['model_name'],
|
|
"index": "button1",
|
|
},
|
|
style={'backgroundColor': '#f0f0f0', 'border': 'none', 'marginRight': '1px'}
|
|
),
|
|
fac.AntdButton('接口示例',
|
|
id={
|
|
"type": "card-button",
|
|
"model_name": item['model_name'],
|
|
"index": "button2",
|
|
},
|
|
style={'backgroundColor': '#f0f0f0', 'border': 'none', 'marginRight': '1px'}
|
|
),
|
|
fac.AntdButton('部署模型',
|
|
id={
|
|
"type": "card-button",
|
|
"model_name": item['model_name'],
|
|
"index": "button3",
|
|
},
|
|
style={'backgroundColor': '#f0f0f0', 'border': 'none'}
|
|
),
|
|
]
|
|
)
|
|
),
|
|
],
|
|
align='start',
|
|
direction='vertical',
|
|
),
|
|
],
|
|
hoverable=True,
|
|
style={"marginBottom": "5px", "width": "100%", "height": "210px"},
|
|
headStyle={"width": "100%"},
|
|
),
|
|
span=8,
|
|
style={
|
|
"width": "100%",
|
|
# "marginTop": "-1px"
|
|
},
|
|
)
|
|
for item in data_new
|
|
],
|
|
gutter=[25, 25]
|
|
)
|