fix: filter non-normal gguf files

This commit is contained in:
jialin
2025-08-14 11:03:55 +08:00
parent ccfdb99348
commit d6dce4021d
12 changed files with 107 additions and 51 deletions
+19 -1
View File
@@ -2,9 +2,27 @@ import langConfigMap from '@/locales/lang-config-map';
import { GlobalOutlined } from '@ant-design/icons';
import { getAllLocales, setLocale } from '@umijs/max';
import { Dropdown } from 'antd';
import { createStyles } from 'antd-style';
import { get } from 'lodash';
const useStyles = createStyles(({ token, css }) => ({
button: css`
color: ${token.colorText};
padding: 0 12px;
cursor: pointer;
.anticon {
color: ${token.colorText};
}
&:hover {
.anticon {
color: ${token.colorTextTertiary};
}
}
`
}));
const LangSelect = () => {
const { styles } = useStyles();
const allLocals = getAllLocales();
const items = allLocals.map((key) => {
return {
@@ -25,7 +43,7 @@ const LangSelect = () => {
return (
<Dropdown menu={{ items }}>
<span style={{ padding: '0 12px', cursor: 'pointer' }}>
<span className={styles.button}>
<GlobalOutlined />
</span>
</Dropdown>
@@ -15,9 +15,13 @@ const useStyles = createStyles(({ token, css }) => ({
padding: 0 8px;
&:hover {
color: ${token.colorTextTertiary};
.anticon {
color: ${token.colorTextTertiary};
}
}
.anticon {
font-size: 16px;
color: ${token.colorText};
}
.icon-auto {
font-size: 20px;
-1
View File
@@ -570,7 +570,6 @@ body {
.ant-message-notice-content {
border-radius: var(--border-radius-base) !important;
line-height: 2;
max-width: 300px;
text-align: left;
word-break: break-word;
+3 -1
View File
@@ -255,5 +255,7 @@ export default {
'common.login.auth': 'Authenticating...',
'common.login.auth.failed': 'Authentication failed',
'common.login.password': 'Log in with Password',
'common.external.login': 'Log in with {type}'
'common.external.login': 'Log in with {type}',
'common.sso.noConfig':
'Single sign-on is not enabled on this system. Please contact your administrator.'
};
+4 -1
View File
@@ -255,7 +255,9 @@ export default {
'common.login.auth': 'Authenticating...',
'common.login.auth.failed': 'Authentication failed',
'common.login.password': 'Log in with Password',
'common.external.login': 'Log in with {type}'
'common.external.login': 'Log in with {type}',
'common.sso.noConfig':
'Single sign-on is not enabled on this system. Please contact your administrator.'
};
// ========== To-Do: Translate Keys (Remove After Translation) ==========
@@ -278,4 +280,5 @@ export default {
// 17. 'common.login.auth.failed': 'Authentication failed',
// 18. 'common.external.login': 'Log in with {type}'
// 19. 'common.login.password': 'Log in with Password',
// 20. 'common.sso.noConfig': 'Single sign-on is not enabled on this system. Please contact your administrator.'
// ========== End of To-Do List ==========
+4 -1
View File
@@ -254,10 +254,13 @@ export default {
'common.login.auth': 'Аутентификация...',
'common.login.auth.failed': 'Ошибка аутентификации',
'common.login.password': 'Log in with Password',
'common.external.login': 'Log in with {type}'
'common.external.login': 'Log in with {type}',
'common.sso.noConfig':
'Single sign-on is not enabled on this system. Please contact your administrator.'
};
// ========== To-Do: Translate Keys (Remove After Translation) ==========
// 1. 'common.external.login': 'Log in with {type}'
// 2. 'common.login.password': 'Log in with Password'
// 3. 'common.sso.noConfig': 'Single sign-on is not enabled on this system. Please contact your administrator.'
// ========== End of To-Do List ==========
+2 -1
View File
@@ -248,5 +248,6 @@ export default {
'common.login.auth': '认证中...',
'common.login.auth.failed': '认证失败',
'common.login.password': '使用密码登录',
'common.external.login': '使用 {type} 登录'
'common.external.login': '使用 {type} 登录',
'common.sso.noConfig': '该系统未启用单点登录,请联系管理员。'
};
@@ -161,6 +161,11 @@ const HFModelFile: React.FC<HFModelFileProps> = forwardRef((props, ref) => {
return filterRegGGUF.test(file.path) || _.includes(file.path, '.gguf');
};
const isNormalGGUFModelFile = (filename: string) => {
const file = filename?.toLowerCase() ?? '';
return file.indexOf('mmproj') === -1 && file.indexOf('imatrix') === -1;
};
// hugging face files
const getHuggingfaceFiles = async () => {
try {
@@ -175,7 +180,7 @@ const HFModelFile: React.FC<HFModelFileProps> = forwardRef((props, ref) => {
});
const list = _.filter(fileList, (file: any) => {
return hfFileFilter(file) && file.path.indexOf('mmproj') === -1;
return hfFileFilter(file) && isNormalGGUFModelFile(file.path);
});
return list;
@@ -188,7 +193,7 @@ const HFModelFile: React.FC<HFModelFileProps> = forwardRef((props, ref) => {
return (
filterRegGGUF.test(file.Path) &&
file.Type === 'blob' &&
file.Path.indexOf('mmproj') === -1
isNormalGGUFModelFile(file.Path)
);
};
+11 -28
View File
@@ -1,7 +1,5 @@
import LogoIcon from '@/assets/images/gpustack-logo.png';
import { userAtom } from '@/atoms/user';
import LangSelect from '@/components/lang-select';
import ThemeDropActions from '@/components/theme-toggle/theme-drop-actions';
import { useIntl, useModel } from '@umijs/max';
import { Button, Divider, Form, Spin, message } from 'antd';
import { createStyles } from 'antd-style';
@@ -52,22 +50,6 @@ const DividerWrapper = styled(Divider)`
`;
const useStyles = createStyles(({ token, css }) => ({
header: css`
display: flex;
align-items: center;
gap: 8px;
position: fixed;
right: 0;
top: 0;
height: 60px;
padding: 20px;
.anticon-global {
color: ${token.colorText};
}
.anticon:hover {
color: ${token.colorTextTertiary};
}
`,
errorMessage: css`
display: flex;
flex-direction: column;
@@ -99,6 +81,7 @@ const LoginForm = () => {
const intl = useIntl();
const [form] = Form.useForm();
const [isPassword, setIsPassword] = useState(false);
const [loading, setLoading] = useState(false);
const renderWelCome = () => {
return (
@@ -161,6 +144,7 @@ const LoginForm = () => {
gotoDefaultPage(userInfo);
}
},
onError: (error) => {
// gpustack handle in the interceptor
}
@@ -173,6 +157,9 @@ const LoginForm = () => {
setUserInfo(userInfo);
gotoDefaultPage({});
},
onLoading: (loading) => {
setLoading(loading);
},
onError: handleOnError
});
@@ -186,6 +173,8 @@ const LoginForm = () => {
} else if (SSOAuth.options.saml) {
SSOAuth.loginWithSAML();
}
setLoading(true);
setAuthError(null);
};
const hasThirdPartyLogin = useMemo(() => {
@@ -228,22 +217,16 @@ const LoginForm = () => {
};
const isThirdPartyAuthHandling = useMemo(() => {
return SSOAuth.isSSOLogin && !authError;
}, [SSOAuth.isSSOLogin, authError]);
return loading && !authError;
}, [loading, authError]);
return (
<div>
{contextHolder}
<div className={styles.header}>
<ThemeDropActions></ThemeDropActions>
<LangSelect />
</div>
<div>
{isThirdPartyAuthHandling ? (
<Spin>
<span style={{ color: 'var(--ant-color-text)' }}>
{intl.formatMessage({ id: 'common.login.auth' })}
</span>
<Spin tip={intl.formatMessage({ id: 'common.login.auth' })}>
<div style={{ width: 300 }}></div>
</Spin>
) : (
<>
+2 -5
View File
@@ -2,8 +2,8 @@ import { initialPasswordAtom, userAtom } from '@/atoms/user';
import SealInput from '@/components/seal-form/seal-input';
import { PasswordReg } from '@/config';
import { CRYPT_TEXT } from '@/utils/localstore/index';
import { GlobalOutlined, LockOutlined } from '@ant-design/icons';
import { SelectLang, useIntl } from '@umijs/max';
import { LockOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Button, Form, message } from 'antd';
import CryptoJS from 'crypto-js';
import { useAtom } from 'jotai';
@@ -47,9 +47,6 @@ const PasswordForm: React.FC = () => {
return (
<div>
<div style={{ position: 'fixed', right: 0, top: 0, padding: '0 20px' }}>
<SelectLang icon={<GlobalOutlined />} reload={false} />
</div>
<Form
form={form}
style={{ width: '360px', margin: '0 auto' }}
+10 -2
View File
@@ -1,5 +1,5 @@
// hooks/useSSOAuth.ts
import { history } from '@umijs/max';
import { history, useIntl } from '@umijs/max';
import { useEffect, useState } from 'react';
type LoginOption = {
@@ -22,17 +22,21 @@ async function fetchAuthConfig(url: string) {
export function useSSOAuth({
fetchUserInfo,
onSuccess,
onLoading,
onError
}: {
fetchUserInfo: () => Promise<any>;
onSuccess?: (userInfo: any) => void;
onError?: (err: Error) => void;
onLoading?: (loading: boolean) => void;
}) {
const [loginOption, setLoginOption] = useState<LoginOption>({
saml: false,
oidc: false
});
const intl = useIntl();
const { location } = history;
const params = new URLSearchParams(location.search);
const sso = params.get('sso');
@@ -53,17 +57,21 @@ export function useSSOAuth({
saml: !!authConfig.is_saml
});
if (sso) {
onLoading?.(true);
if (authConfig.is_oidc) {
oidcLogin();
} else if (authConfig.is_saml) {
samlLogin();
} else {
onError?.(new Error('No SSO configuration found'));
onError?.(
new Error(intl.formatMessage({ id: 'common.sso.noConfig' }))
);
}
}
} catch (error: any) {
setLoginOption({ oidc: false, saml: false });
onError?.(error);
onLoading?.(false);
}
};
+41 -8
View File
@@ -2,9 +2,12 @@ import Bg2 from '@/assets/images/bg-2.png';
import { userAtom } from '@/atoms/user';
import DarkMask from '@/components/dark-mask';
import Footer from '@/components/footer';
import LangSelect from '@/components/lang-select';
import ThemeDropActions from '@/components/theme-toggle/theme-drop-actions';
import useUserSettings from '@/hooks/use-user-settings';
import { useModel } from '@umijs/max';
import { ConfigProvider, theme } from 'antd';
import { createStyles } from 'antd-style';
import { useAtom } from 'jotai';
import { useEffect } from 'react';
import styled from 'styled-components';
@@ -12,6 +15,29 @@ import LoginForm from './components/login-form';
import PasswordForm from './components/password-form';
import { checkDefaultPage } from './utils';
const useStyles = createStyles(({ token, css }) => ({
header: css`
display: flex;
align-items: center;
gap: 8px;
position: fixed;
right: 0;
top: 0;
height: 60px;
padding: 20px;
.anticon-global {
color: ${token.colorText};
}
.anticon:hover {
color: ${token.colorTextTertiary};
}
`,
formContainer: css`
height: calc(100vh - 64px);
width: 100%;
`
}));
const Wrapper = styled.div<{ $isDarkTheme: boolean }>`
position: fixed;
top: 0;
@@ -30,7 +56,6 @@ const Wrapper = styled.div<{ $isDarkTheme: boolean }>`
`;
const Box = styled.div`
padding-top: 10%;
display: flex;
flex-direction: column;
justify-content: space-between;
@@ -40,6 +65,7 @@ const Box = styled.div`
const FormWrapper = styled.div`
position: relative;
margin: 0 auto;
z-index: 999;
border-radius: var(--border-radius-modal);
width: max-content;
height: max-content;
@@ -48,6 +74,8 @@ const FormWrapper = styled.div`
padding: 40px;
background-color: var(--color-modal-content-bg);
box-shadow: var(--color-modal-box-shadow);
margin-top: 50vh;
transform: translateY(-50%);
.field-wrapper {
background-color: transparent !important;
}
@@ -58,6 +86,7 @@ const FormWrapper = styled.div`
`;
const Login = () => {
const { styles } = useStyles();
const { themeData, userSettings, isDarkTheme } = useUserSettings();
const [userInfo, setUserInfo] = useAtom(userAtom);
const { initialState, setInitialState } = useModel('@@initialState') || {};
@@ -95,10 +124,14 @@ const Login = () => {
...themeData
}}
>
<div>
<DarkMask></DarkMask>
<Wrapper $isDarkTheme={isDarkTheme}></Wrapper>
<Box>
<div className={styles.header}>
<ThemeDropActions></ThemeDropActions>
<LangSelect />
</div>
<DarkMask></DarkMask>
<Wrapper $isDarkTheme={isDarkTheme}></Wrapper>
<Box>
<div className={styles.formContainer}>
<FormWrapper>
{userInfo?.require_password_change ? (
<PasswordForm />
@@ -106,9 +139,9 @@ const Login = () => {
<LoginForm />
)}
</FormWrapper>
<Footer />
</Box>
</div>
</div>
<Footer />
</Box>
</ConfigProvider>
);
};