mirror of
https://github.com/mindverse/Second-Me.git
synced 2026-08-20 06:03:17 +00:00
Added model selection function, updated model list acquisition logic, and enhanced model information display
This commit is contained in:
parent
cb5d0cb4da
commit
5cc5cf39e6
2 changed files with 158 additions and 8 deletions
|
|
@ -2,7 +2,7 @@ import { Status, statusRankMap, useTrainingStore } from '@/store/useTrainingStor
|
|||
import { startService, stopService } from '@/service/train';
|
||||
import { StatusBar } from '../StatusBar';
|
||||
import { useRef, useEffect, useState, useMemo } from 'react';
|
||||
import { message } from 'antd';
|
||||
import { message, Select, Tooltip, Spin } from 'antd';
|
||||
import {
|
||||
CloudUploadOutlined,
|
||||
CheckCircleOutlined,
|
||||
|
|
@ -15,6 +15,7 @@ import RegisterUploadModal from '../upload/RegisterUploadModal';
|
|||
import { useLoadInfoStore } from '@/store/useLoadInfoStore';
|
||||
import TrainingTipModal from '../upload/TraingTipModal';
|
||||
import { getMemoryList } from '@/service/memory';
|
||||
import { getModelList, ModelInfo } from '@/service/model';
|
||||
|
||||
const StatusDot = ({ active }: { active: boolean }) => (
|
||||
<div
|
||||
|
|
@ -22,6 +23,41 @@ const StatusDot = ({ active }: { active: boolean }) => (
|
|||
/>
|
||||
);
|
||||
|
||||
// Helper component for option tooltips
|
||||
const OptionTooltip = ({ model }: { model: ModelInfo }) => {
|
||||
const fileName = model.model_path.split('/')[1];
|
||||
const timeStamp = fileName?.replace('.gguf', '') || 'Unknown version';
|
||||
const modelName = model.model_path.split('/')[0];
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
title={
|
||||
<div className="text-xs">
|
||||
<div className="font-bold mb-1">{modelName}</div>
|
||||
<div className="font-bold mt-2 mb-1">Training Parameters:</div>
|
||||
<ul>
|
||||
{Object.entries(model.training_params).length > 0 ? (
|
||||
Object.entries(model.training_params).map(([key, value]) => (
|
||||
<li key={key}>
|
||||
{key}: {typeof value === 'object' ? JSON.stringify(value) : String(value)}
|
||||
</li>
|
||||
))
|
||||
) : (
|
||||
<li>No training parameters available</li>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
placement="left"
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
<span className="font-medium">{timeStamp}</span>
|
||||
<span className="text-xs text-gray-500">{modelName}</span>
|
||||
</div>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
export function ModelStatus() {
|
||||
const status = useTrainingStore((state) => state.status);
|
||||
const setStatus = useTrainingStore((state) => state.setStatus);
|
||||
|
|
@ -43,6 +79,11 @@ export function ModelStatus() {
|
|||
const [showRegisterModal, setShowRegisterModal] = useState(false);
|
||||
const [showtrainingModal, setShowtrainingModal] = useState(false);
|
||||
|
||||
// Model selection states
|
||||
const [modelList, setModelList] = useState<ModelInfo[]>([]);
|
||||
const [selectedModel, setSelectedModel] = useState<string>('');
|
||||
const [loadingModels, setLoadingModels] = useState<boolean>(false);
|
||||
|
||||
const handleRegistryClick = () => {
|
||||
if (!serviceStarted) {
|
||||
messageApi.info({
|
||||
|
|
@ -54,6 +95,16 @@ export function ModelStatus() {
|
|||
}
|
||||
};
|
||||
|
||||
const handleModelChange = (value: string) => {
|
||||
setSelectedModel(value);
|
||||
// Update configuration in localStorage
|
||||
const config = JSON.parse(localStorage.getItem('trainingParams') || '{}');
|
||||
|
||||
// Store the complete model path
|
||||
config.model_name = value;
|
||||
localStorage.setItem('trainingParams', JSON.stringify(config));
|
||||
};
|
||||
|
||||
const fetchMemories = async () => {
|
||||
try {
|
||||
const memoryRes = await getMemoryList();
|
||||
|
|
@ -70,9 +121,51 @@ export function ModelStatus() {
|
|||
}
|
||||
};
|
||||
|
||||
const fetchModels = async () => {
|
||||
setLoadingModels(true);
|
||||
|
||||
try {
|
||||
const res = await getModelList();
|
||||
|
||||
if (res.data.code === 0) {
|
||||
setModelList(res.data.data);
|
||||
// Read saved configuration, initialize selected model
|
||||
const config = JSON.parse(localStorage.getItem('trainingParams') || '{}');
|
||||
|
||||
if (config.model_name) {
|
||||
// Check if the model exists in the list
|
||||
const modelExists = res.data.data.some(
|
||||
(model: ModelInfo) => model.model_path === config.model_name
|
||||
);
|
||||
|
||||
if (modelExists) {
|
||||
setSelectedModel(config.model_name);
|
||||
} else if (res.data.data.length > 0) {
|
||||
// Default to the first model in the list
|
||||
setSelectedModel(res.data.data[0].model_path);
|
||||
}
|
||||
} else if (res.data.data.length > 0) {
|
||||
// Default to the first model in the list
|
||||
setSelectedModel(res.data.data[0].model_path);
|
||||
}
|
||||
} else {
|
||||
messageApi.error({ content: res.data.message!, duration: 1 });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching model list:', error);
|
||||
messageApi.error({
|
||||
content: error.response?.data?.message || error.message,
|
||||
duration: 1
|
||||
});
|
||||
} finally {
|
||||
setLoadingModels(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchMemories();
|
||||
fetchServiceStatus();
|
||||
fetchModels();
|
||||
|
||||
return () => {
|
||||
clearPolling();
|
||||
|
|
@ -130,19 +223,18 @@ export function ModelStatus() {
|
|||
console.error('Error checking service status:', error);
|
||||
});
|
||||
}, 3000);
|
||||
};
|
||||
|
||||
const handleStartService = () => {
|
||||
}; const handleStartService = () => {
|
||||
// Use selected model or get from local storage
|
||||
const config = JSON.parse(localStorage.getItem('trainingParams') || '{}');
|
||||
const modelPath = selectedModel || config.model_name;
|
||||
|
||||
if (!config.model_name) {
|
||||
message.error('Please train a base model first');
|
||||
|
||||
if (!modelPath) {
|
||||
message.error('Please select a model to start');
|
||||
return;
|
||||
}
|
||||
|
||||
setServiceStarting(true);
|
||||
startService({ model_name: config.model_name })
|
||||
startService({ model_name: modelPath })
|
||||
.then((res) => {
|
||||
if (res.data.code === 0) {
|
||||
messageApi.success({ content: 'Service starting...', duration: 1 });
|
||||
|
|
@ -204,6 +296,47 @@ export function ModelStatus() {
|
|||
<StatusBar status={status} />
|
||||
|
||||
<div className="flex items-center gap-6">
|
||||
{/* Model Selection - only show when service is not started */}
|
||||
{!serviceStarted && (
|
||||
<div className="relative mr-3">
|
||||
<Spin spinning={loadingModels} size="small">
|
||||
<Select
|
||||
className="w-56"
|
||||
disabled={serviceStarted || isServiceStarting}
|
||||
loading={loadingModels}
|
||||
onChange={handleModelChange}
|
||||
optionLabelProp="label"
|
||||
placeholder="Select Model"
|
||||
value={selectedModel}
|
||||
options={modelList.map((model) => {
|
||||
const fileName = model.model_path.split('/')[1];
|
||||
const timeStamp = fileName?.replace('.gguf', '') || 'Unknown version';
|
||||
const modelName = model.model_path.split('/')[0];
|
||||
return {
|
||||
label: timeStamp,
|
||||
value: model.model_path,
|
||||
model: model
|
||||
};
|
||||
})}
|
||||
optionRender={(option) => {
|
||||
const model = option.data.model as ModelInfo;
|
||||
return <OptionTooltip model={model} />;
|
||||
}}
|
||||
onDropdownVisibleChange={(open) => {
|
||||
if (open) {
|
||||
// Hide any currently visible tooltips when dropdown opens
|
||||
const tooltipElements = document.querySelectorAll('.ant-tooltip');
|
||||
tooltipElements.forEach(el => {
|
||||
if (window.getComputedStyle(el).display !== 'none') {
|
||||
(el as HTMLElement).style.display = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Spin>
|
||||
</div>
|
||||
)}
|
||||
{/* Control Buttons */}
|
||||
<div className="flex items-center gap-3">
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -44,6 +44,16 @@ export interface BioVersion {
|
|||
version: number;
|
||||
}
|
||||
|
||||
export interface ModelInfo {
|
||||
model_path: string;
|
||||
full_path: string;
|
||||
file_size: number;
|
||||
created_time: number;
|
||||
training_params: {
|
||||
[key: string]: any;
|
||||
};
|
||||
}
|
||||
|
||||
export const getGlobalBioVersion = () => {
|
||||
return Request<CommonResponse<BioVersion[]>>({
|
||||
method: 'get',
|
||||
|
|
@ -64,3 +74,10 @@ export const getStatusBio = () => {
|
|||
url: '/api/kernel/l1/status_bio/get'
|
||||
});
|
||||
};
|
||||
|
||||
export const getModelList = () => {
|
||||
return Request<CommonResponse<ModelInfo[]>>({
|
||||
method: 'get',
|
||||
url: '/api/kernel2/list_gguf_models'
|
||||
});
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue