feat: 模型库能力默认模型UI + 前台Auto默认模型 + AGNES直连修复 + 意图识别增强
This commit is contained in:
1 parent
2847289921
commit
945eeb8ba0
4 files changed
+121
-23
No files matched your search
@@ -15,23 +15,15 @@ const formatNumber = (n: number) => {
|
||||
};
|
||||
|
||||
const capabilityColors: Record<string, string> = {
|
||||
text: '#5B5FED',
|
||||
vision: '#219B5E',
|
||||
audio: '#E8922C',
|
||||
video: '#D9383A',
|
||||
image: '#D9383A',
|
||||
thinking: '#8B5CF6',
|
||||
tool: '#3B82F6',
|
||||
text: '#5B5FED', thinking: '#8B5CF6', vision: '#219B5E', tool: '#3B82F6',
|
||||
image: '#D9383A', audio: '#E8922C', asr: '#0EA5E9', ocr: '#F59E0B',
|
||||
embedding: '#10B981', rerank: '#EC4899', video: '#EF4444',
|
||||
};
|
||||
|
||||
const capabilityLabels: Record<string, string> = {
|
||||
text: '文本',
|
||||
vision: '视觉',
|
||||
audio: '音频',
|
||||
video: '视频',
|
||||
image: '图像',
|
||||
thinking: '思考',
|
||||
tool: '工具',
|
||||
text: '文本对话', thinking: '推理思考', vision: '视觉理解', tool: '工具调用',
|
||||
image: '图像生成', audio: '语音合成', asr: '语音识别', ocr: 'OCR识别',
|
||||
embedding: '嵌入向量', rerank: '重排序', video: '视频生成',
|
||||
};
|
||||
|
||||
// Test result type
|
||||
@@ -69,6 +61,12 @@ const Models: React.FC = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
// 能力默认模型(Auto 自动模式)
|
||||
const [capabilities, setCapabilities] = useState<any[]>([]);
|
||||
const [capabilityDefaults, setCapabilityDefaults] = useState<Record<string, string>>({});
|
||||
const [capabilityModels, setCapabilityModels] = useState<any[]>([]);
|
||||
const [savingCaps, setSavingCaps] = useState<Set<string>>(new Set());
|
||||
|
||||
// Model test state
|
||||
const [testingModelId, setTestingModelId] = useState<string | null>(null);
|
||||
const [testResult, setTestResult] = useState<TestResult | null>(null);
|
||||
@@ -85,10 +83,11 @@ const Models: React.FC = () => {
|
||||
const loadData = useCallback(async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const [provRes, modelsRes, protoRes] = await Promise.all([
|
||||
const [provRes, modelsRes, protoRes, capRes] = await Promise.all([
|
||||
adminAPI.getProviders(),
|
||||
adminAPI.getAdminModels({ page_size: 100 }),
|
||||
adminAPI.getProtocols(),
|
||||
adminAPI.getCapabilityDefaults(),
|
||||
]);
|
||||
setProviders(Array.isArray(provRes) ? provRes : (provRes.data || []));
|
||||
setProtocols(Array.isArray(protoRes) ? protoRes : (protoRes.data || []));
|
||||
@@ -105,6 +104,11 @@ const Models: React.FC = () => {
|
||||
totalTokens: m.totalTokens ?? m.total_tokens ?? 0,
|
||||
}));
|
||||
setModels(mappedModels);
|
||||
// 能力默认模型
|
||||
const cd = (capRes.data || capRes) as any;
|
||||
setCapabilities(cd.capabilities || []);
|
||||
setCapabilityDefaults(cd.defaults || {});
|
||||
setCapabilityModels(cd.models || []);
|
||||
} catch (err: any) {
|
||||
setError('加载数据失败:' + (err.message || err.detail || JSON.stringify(err)));
|
||||
} finally {
|
||||
@@ -278,6 +282,23 @@ const Models: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 设置/清除某个能力的默认模型(Auto 自动模式使用)
|
||||
const handleSetCapabilityDefault = async (capId: string, modelId: string | null) => {
|
||||
try {
|
||||
setSavingCaps(prev => new Set(prev).add(capId));
|
||||
const res = await adminAPI.setCapabilityDefault(capId, modelId) as any;
|
||||
setCapabilityDefaults((res && res.defaults) || { ...capabilityDefaults, [capId]: modelId || undefined } as Record<string, string>);
|
||||
} catch (err: any) {
|
||||
setError(err.message || '设置失败');
|
||||
} finally {
|
||||
setSavingCaps(prev => {
|
||||
const n = new Set(prev);
|
||||
n.delete(capId);
|
||||
return n;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Toggle capability
|
||||
const toggleCapability = (cap: string) => {
|
||||
if (!editingModel) return;
|
||||
@@ -476,6 +497,54 @@ const Models: React.FC = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* ===== 能力默认模型(Auto 自动模式) ===== */}
|
||||
{capabilities.length > 0 && (
|
||||
<div style={{ background: '#fff', borderRadius: '8px', border: '1px solid #E5E7EB', padding: '20px', marginTop: '16px' }}>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: '4px', flexWrap: 'wrap', gap: '8px' }}>
|
||||
<h3 style={{ margin: 0, fontSize: '16px', fontWeight: 600 }}>能力默认模型</h3>
|
||||
<span style={{ fontSize: '12px', color: '#888' }}>
|
||||
为每项能力指定默认模型,前台「Auto 自动」将按对话意图自动匹配
|
||||
</span>
|
||||
</div>
|
||||
<p style={{ margin: '0 0 16px', fontSize: '13px', color: '#999' }}>
|
||||
选择「Auto 自动」时,系统依据用户输入(如含「画图 / 视频」)自动选用对应能力的默认模型;文本类能力在未单独配置时回退到全局默认模型。
|
||||
</p>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))', gap: '12px' }}>
|
||||
{capabilities.map((cap: any) => {
|
||||
const capModels = capabilityModels.filter(
|
||||
(m: any) => (m.capabilities || []).includes(cap.id) || capabilityDefaults[cap.id] === m.id
|
||||
);
|
||||
const cur = capabilityDefaults[cap.id] || '';
|
||||
const saving = savingCaps.has(cap.id);
|
||||
const dotColor = cap.color || capabilityColors[cap.id] || '#6B7280';
|
||||
return (
|
||||
<div key={cap.id} style={{ border: '1px solid #EEF0F4', borderRadius: '8px', padding: '12px 14px', background: '#FBFCFE' }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '6px' }}>
|
||||
<span style={{ width: '10px', height: '10px', borderRadius: '3px', background: dotColor, flexShrink: 0 }} />
|
||||
<span style={{ fontWeight: 600, fontSize: '14px' }}>{cap.label}</span>
|
||||
<span style={{ fontSize: '11px', color: '#bbb', marginLeft: 'auto' }}>{cap.id}</span>
|
||||
</div>
|
||||
<div style={{ fontSize: '12px', color: '#8a8a8a', marginBottom: '10px', minHeight: '32px' }}>{cap.desc}</div>
|
||||
<select
|
||||
value={cur}
|
||||
disabled={saving}
|
||||
onChange={e => handleSetCapabilityDefault(cap.id, e.target.value || null)}
|
||||
style={{ width: '100%', padding: '7px 10px', border: '1px solid #D1D5DB', borderRadius: '6px', fontSize: '13px', boxSizing: 'border-box', background: '#fff', color: '#333' }}
|
||||
>
|
||||
<option value="">— 未设置(回退全局默认)—</option>
|
||||
{capModels.map((m: any) => (
|
||||
<option key={m.id} value={m.id}>
|
||||
{m.display_name || m.name}{m.provider_name ? `(${m.provider_name})` : ''}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Provider Modal */}
|
||||
{showAddProvider && (
|
||||
<div style={modalOverlay}>
|
||||
|
||||
Reference in new issue
Block a user