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='设置运行模型名称', style={ "width": "calc(100% - 30px)", }, ), # id='form-item-validate-demo-username-container', # label='用户名', ), fac.AntdFormItem( fac.AntdInput( id='form-item-worker-ip', size='large', placeholder='设置运行模型的worker地址', style={ "width": "calc(100% - 30px)", "marginTop": "5px" }, ), style={ "marginTop": "5px"} ), fac.AntdFormItem( fac.AntdInput( id='form-item-gpu-idx', size='large', placeholder='设置运行模型的gpu索引', style={ "width": "calc(100% - 30px)", "marginTop": "5px" }, ), style={ "marginTop": "5px"} ), fac.AntdFormItem( fac.AntdSelect( id='form-item-download-hub', size='large', placeholder='选择下载地址', options= ['none',"huggingface","modelscope","modelscope"], # value='选项1', style={'width': 620, "marginTop": "5px" }, ), style={ "marginTop": "5px"} ), fac.AntdFormItem( fac.AntdInput( id='form-item-model-path', size='large', placeholder='指定模型路径启动', style={ "width": "calc(100% - 30px)", "marginTop": "5px" }, ), style={ "marginTop": "5px"} ), ], 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] )