import { ListItem as UserListItem } from '@/pages/users/config/types'; import { downloadFile, listFiles, listModels } from '@huggingface/hub'; import { PipelineType } from '@huggingface/tasks'; import { request } from '@umijs/max'; import qs from 'query-string'; import { AccessControlFormData, BackendItem, CatalogItem, CatalogSpec, DraftModelItem, EvaluateResult, EvaluateSpec, FormData, GPUListItem, ListItem, ModelInstanceFormData, ModelInstanceListItem } from '../config/types'; export const MODELS_API = '/models'; export const MODEL_INSTANCE_API = '/model-instances'; export const MODEL_EVALUATIONS = '/model-evaluations'; export const BACKEND_LIST_API = '/inference-backends/list'; export const MY_MODELS_API = '/my-models'; export const DRAFT_MODELS_API = '/draft-models'; export const CATALOG_LIST_API = '/model-sets'; const setProxyUrl = (url: string) => { return `/proxy?url=${encodeURIComponent(url)}`; }; // ===================== Models ===================== export async function queryModelsInstances( params: Global.SearchParams, options?: any ) { return request>( MODEL_INSTANCE_API, { params, method: 'GET', cancelToken: options?.token } ); } export async function queryModelsList( params: Global.SearchParams, options?: Record ) { return request>( `${MODELS_API}?${qs.stringify(params)}`, { method: 'GET', ...options } ); } export async function queryGPUList>( params?: Global.SearchParams & T ) { return request>(`/gpu-devices`, { method: 'GET', params }); } export async function createModel(params: { data: FormData }) { return request(`${MODELS_API}`, { method: 'POST', data: params.data }); } export async function deleteModel(id: number) { return request(`${MODELS_API}/${id}`, { method: 'DELETE' }); } export async function updateModel(params: { id: number; data: FormData }) { return request(`${MODELS_API}/${params.id}`, { method: 'PUT', data: params.data }); } export async function queryModelDetail(id: number) { return request(`${MODELS_API}/${id}`, { method: 'GET' }); } // ===================== Model Instances start ===================== export async function queryModelInstancesList( params: Global.Pagination & { query?: string; id: number }, options?: any ) { return request>( `${MODELS_API}/${params.id}/instances`, { method: 'GET', params, cancelToken: options?.token } ); } export async function createModelInstance(params: { data: ModelInstanceFormData; }) { return request(`${MODEL_INSTANCE_API}`, { method: 'POST', data: params.data }); } export async function deleteModelInstance(id: number) { return request(`${MODEL_INSTANCE_API}/${id}`, { method: 'DELETE' }); } export async function updateModelInstance(params: { id: number; data: FormData; }) { return request(`${MODEL_INSTANCE_API}/${params.id}`, { method: 'PUT', data: params.data }); } export async function queryModelInstanceDetail(id: number) { return request(`${MODEL_INSTANCE_API}/${id}`, { method: 'GET' }); } export async function queryModelInstanceLogs(id: number) { return request(`${MODEL_INSTANCE_API}/${id}/logs`, { method: 'GET' }); } // ===================== Model Instances end ===================== // ===================== call huggingface quicksearch api ===================== const MODEL_SCOPE_LIST_MODEL_API = `https://www.modelscope.cn/api/v1/dolphin/models`; const MODE_SCOPE_MODEL_FIELS_API = `https://modelscope.cn/api/v1/models/`; export async function queryHuggingfaceModelDetail( params: { repo: string }, options?: any ) { const url = `https://huggingface.co/api/models/${params.repo}`; return request(setProxyUrl(url), { method: 'GET', cancelToken: options?.token }); } export async function queryModelScopeModels( params: { PageSize?: number; PageNumber?: number; SortBy?: string; Target?: string; SingleCriterion?: any[]; Name: string; tags?: string[]; tasks?: string[]; }, config?: any ) { const tagsCriterion = params.tags?.map((tag: string) => { return { category: 'tags', predicate: 'contains', values: [tag] }; }); const tasksCriterion = params.tasks?.map((task: string) => { return { category: 'tasks', predicate: 'contains', values: [task] }; }); const Criterion = tagsCriterion?.length || tasksCriterion?.length ? { Criterion: [...(tagsCriterion || []), ...(tasksCriterion || [])] } : {}; const res = await fetch(setProxyUrl(`${MODEL_SCOPE_LIST_MODEL_API}`), { method: 'PUT', signal: config?.signal, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ PageSize: 10, PageNumber: 1, ...params, ...Criterion, Name: `${params.Name}` }) }); if (!res.ok) { throw new Error('Network response was not ok'); } return res.json(); } export async function queryModelScopeModelDetail( params: { name: string }, options?: any ) { return request(setProxyUrl(`${MODE_SCOPE_MODEL_FIELS_API}${params.name}`), { method: 'GET', cancelToken: options?.token }); } export async function queryModelScopeModelFiles( params: { name: string; revision: string }, options?: any ) { const url = `${MODE_SCOPE_MODEL_FIELS_API}${params.name}/repo/files?${qs.stringify( { Revision: params.revision, Recursive: true, Root: '' } )}`; const res = await fetch(setProxyUrl(url), { method: 'GET', signal: options?.signal, body: null }); if (!res.ok) { throw new Error('Network response was not ok'); } return res.json(); } // list models from huggingface export async function queryHuggingfaceModels( params: { limit?: number; search: { query: string; tags?: string[]; sort?: string; task?: PipelineType; }; }, options?: any ) { console.log('params', params); const result = []; for await (const model of listModels({ ...params, ...options, limit: params.limit || 500, additionalFields: ['sha', 'tags'], fetch(_url: string, config: any) { const url = params.search.sort ? `${_url}&sort=${params.search.sort}` : _url; try { return fetch(setProxyUrl(url), { ...config, signal: options.signal }); } catch (error) { // ignore return []; } } })) { result.push(model); } return result; } // list files from huggingface export async function queryHuggingfaceModelFiles( params: { repo: string }, options?: any ) { const result = []; for await (const fileInfo of listFiles({ ...params, recursive: true, fetch(url: string, config: any) { try { return fetch(setProxyUrl(url), { ...config, signal: options?.signal }); } catch (error) { // ignore return []; } } })) { result.push(fileInfo); } return result; } export async function downloadModelFile( params: { repo: string; revision: string; path: string }, options?: any ) { const { repo, revision, path } = params; const res = await ( await downloadFile({ repo, revision: revision, path: path, fetch(url: string, config: any) { return fetch(setProxyUrl(url), { ...config, signal: options?.signal }); } }) )?.text(); return res; } export async function downloadModelScopeModelfile( params: { name: string }, options?: any ) { const url = `${MODE_SCOPE_MODEL_FIELS_API}${params.name}/resolve/master/config.json`; const res = await fetch(setProxyUrl(url), { method: 'GET', signal: options?.signal }); if (!res.ok) { throw new Error('Network response was not ok'); } return res.json(); } // ===================== catalog ===================== export async function queryCatalogList( params: Global.SearchParams, options?: any ) { return request>(`${CATALOG_LIST_API}`, { method: 'GET', params, cancelToken: options?.token }); } export async function queryCatalogItemSpec( params: { id: number; cluster_id: number | null }, options?: any ) { return request>( `${CATALOG_LIST_API}/${params.id}/specs`, { method: 'GET', ...options, params } ); } export async function evaluationsModelSpec( data: { cluster_id: number; model_specs: EvaluateSpec[]; }, options: { token: any } ) { const result = await request<{ results: EvaluateResult[] }>( `${MODEL_EVALUATIONS}`, { method: 'POST', data, cancelToken: options?.token } ); const resultList = result?.results || []; return { results: resultList.map((item) => { return { ...item, cluster_id: data.model_specs?.[0]?.cluster_id || undefined }; }) }; } export async function queryBackendList(params?: { cluster_id: number }) { return request<{ items: BackendItem[]; }>(BACKEND_LIST_API, { method: 'GET', params }); } export async function queryModelAccessUserList(id: number) { return request<{ items: UserListItem[] }>(`${MODELS_API}/${id}/access`, { method: 'GET' }); } export async function updateModelAccessUser(params: { id: number; data: AccessControlFormData; }) { return request(`${MODELS_API}/${params.id}/access`, { method: 'POST', data: params.data }); } export async function queryMyModels(params: Global.SearchParams) { return request>( `${MY_MODELS_API}?${qs.stringify(params)}`, { method: 'GET' } ); } export async function queryMyModelDetail(id: number) { return request(`${MY_MODELS_API}/${id}`, { method: 'GET' }); } export async function queryDraftModelList(params?: Global.SearchParams) { return request<{ items: DraftModelItem[] }>(DRAFT_MODELS_API, { method: 'GET', params }); } export async function queryModelContextLength(params: { model: { source: string; model_scope_model_id?: string; huggingface_repo_id?: string; local_path?: string; }; }) { return request<{ native: number; scaled: number }>( `${MODELS_API}/context-length`, { method: 'POST', data: params } ); }