Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: remove checking URL and add more form inputs #2714

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 98 additions & 28 deletions react/src/components/ImportFromHuggingFaceModal.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
import { baiSignedRequestWithPromise } from '../helper';
import { useSuspendedBackendaiClient } from '../hooks';
import { useSuspenseTanQuery } from '../hooks/reactQueryAlias';
import BAIModal, { BAIModalProps } from './BAIModal';
import Flex from './Flex';
import { FilterOutlined } from '@ant-design/icons';
import { useToggle } from 'ahooks';
import {
App,

Check warning on line 8 in react/src/components/ImportFromHuggingFaceModal.tsx

View workflow job for this annotation

GitHub Actions / coverage

'App' is defined but never used
Button,
Card,
Form,
FormInstance,
Input,
Switch,
theme,
Typography,
} from 'antd';
import Markdown from 'markdown-to-jsx';
import React, { useRef } from 'react';
import _ from 'lodash';
import React, { useEffect, useRef, useState, useTransition } from 'react';
import { useTranslation } from 'react-i18next';

type Service = {
url: string;
inference_engine_version?: string;
replica_number?: number;
service_name?: string;
folder_name?: string;
};

interface ImportFromHuggingFaceModalProps extends BAIModalProps {
Expand All @@ -32,15 +34,62 @@
}) => {
const { t } = useTranslation();
const { token } = theme.useToken();
const baiClient = useSuspendedBackendaiClient();
const formRef = useRef<FormInstance<Service>>(null);
const [isImportOnly, { toggle: toggleIsImportOnly }] = useToggle(false);

const [huggingFaceURL, setHuggingFaceURL] = useState<string | undefined>();
const [isPendingCheck, startCheckTransition] = useTransition();
const hugginFaceModelInfo = useSuspenseTanQuery<{
author?: string;
model_name?: string;
markdown?: string;
isError?: boolean;
url?: string;
}>({
queryKey: ['huggingFaceValidation', huggingFaceURL],
queryFn: () => {
if (_.isEmpty(huggingFaceURL)) return Promise.resolve({});
return baiSignedRequestWithPromise({
method: 'GET',
url: `/services/_/huggingface/models?huggingface_url=${huggingFaceURL}`,
client: baiClient,
})
.then((result: any) => {
return {
...result,
url: huggingFaceURL,
};
})
.catch(() => {
// TODO: handle error more gracefully
return {
isError: true,
url: huggingFaceURL,
};
});
},
});
const isHuggingfaceURLExisted = !_.isEmpty(
hugginFaceModelInfo.data.model_name,
);

// validate when huggingFaceModelInfo is updated
useEffect(() => {
if (hugginFaceModelInfo.data.url) {
formRef.current?.validateFields().catch(() => {});
}
}, [hugginFaceModelInfo.data.url]);

const handleOnClick = () => {
startCheckTransition(() => {
setHuggingFaceURL(formRef.current?.getFieldValue('url'));
});
formRef.current
?.validateFields()
.then((values) => {
// TODO: Implement import from Hugging Face
onRequestClose();
// onRequestClose();
})
.catch(() => {});
};
Expand All @@ -50,13 +99,19 @@
title={t('data.modelStore.ImportFromHuggingFace')}
centered
footer={
<Button type="primary" htmlType="submit" onClick={handleOnClick}>
<Button
type="primary"
htmlType="submit"
onClick={handleOnClick}
loading={isPendingCheck}
>
{isImportOnly
? t('data.modelStore.Import')
: t('data.modelStore.ImportAndStartService')}
</Button>
}
onCancel={onRequestClose}
destroyOnClose
{...baiModalProps}
>
<Form
Expand All @@ -65,28 +120,43 @@
layout="vertical"
requiredMark="optional"
>
<Form.Item name="url" rules={[{ required: true }]}>
<Input placeholder={t('data.modelStore.huggingFaceUrlPlaceholder')} />
</Form.Item>
<Card
size="small"
title={
<Flex direction="row" gap="xs">
<FilterOutlined />
README.md
</Flex>
}
styles={{
body: {
padding: token.paddingLG,
overflow: 'auto',
minHeight: 200,
maxHeight: token.screenXS,
<Form.Item
label="Hugging Face URL"
name="url"
rules={[
{ required: true },
{
pattern: /^https:\/\/huggingface.co\/.*/,
message: t('data.modelStore.StartWithHuggingFaceUrl'),
},
}}
{
validator: async (_, value) => {
if (
!isHuggingfaceURLExisted &&
hugginFaceModelInfo.data?.isError &&
hugginFaceModelInfo.data.url === value
) {
return Promise.reject(
t('data.modelStore.InvalidHuggingFaceUrl'),
);
} else {
return Promise.resolve();
}
},
},
]}
>
<Input />
</Form.Item>
<Form.Item
label={t('data.modelStore.ModelStoreFolderName')}
name="folder_name"
>
<Markdown>{''}</Markdown>
</Card>
<Input />
</Form.Item>
<Form.Item label={t('data.modelStore.ServiceName')} name="service_name">
<Input />
</Form.Item>
<Flex
gap={'xs'}
style={{ marginTop: token.marginLG, marginBottom: token.marginLG }}
Expand Down
9 changes: 8 additions & 1 deletion resources/i18n/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,14 @@
"ReplicaNumber": "Replikatnummer",
"ImportAndStartService": "Dienst importieren und starten",
"huggingFaceUrlPlaceholder": "Geben Sie die URL Hugging Face ein",
"ImportOnly": "Nur importieren"
"ImportOnly": "Nur importieren",
"StartWithHuggingFaceUrl": "Es sollte mit https://huggingface.co beginnen",
"CheckHuggingFaceUrl": "Siehe",
"ModelName": "Name des Modells",
"Author": "Autor",
"InvalidHuggingFaceUrl": "Ungültige Hugging Face URL.",
"ModelStoreFolderName": "Name des Modellspeicherordners",
"ServiceName": "Dienstname"
}
},
"dialog": {
Expand Down
12 changes: 10 additions & 2 deletions resources/i18n/el.json
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,14 @@
"ReplicaNumber": "Αριθμός αντιγράφου",
"ImportAndStartService": "Εισαγωγή και έναρξη υπηρεσίας",
"huggingFaceUrlPlaceholder": "Εισαγάγετε τη διεύθυνση URL Hugging Face.",
"ImportOnly": "Μόνο εισαγωγή"
"ImportOnly": "Μόνο εισαγωγή",
"StartWithHuggingFaceUrl": "Θα πρέπει να ξεκινά με https://huggingface.co",
"CheckHuggingFaceUrl": "Ελέγξτε το",
"ModelName": "Όνομα μοντέλου",
"Author": "Συγγραφέας",
"InvalidHuggingFaceUrl": "Μη έγκυρη διεύθυνση URL Hugging Face.",
"ModelStoreFolderName": "Όνομα φακέλου καταστήματος μοντέλου",
"ServiceName": "Όνομα υπηρεσίας"
}
},
"dialog": {
Expand Down Expand Up @@ -1483,7 +1490,8 @@
"SmallerResourceThenImageRequires": "Το αίτημα πόρων είναι μικρότερο από το ελάχιστο απαιτούμενο από την εικόνα. Δοκιμάστε περισσότερους πόρους.",
"APINotSupported": "Το API δεν υποστηρίζεται. Απαιτείται η τελευταία έκδοση του διαχειριστή Backend.AI.",
"WrongAPIServerAddress": "Λάθος διεύθυνση διακομιστή API.",
"ReachedResourceLimitPleaseContact": "Φτάσατε το όριο των πόρων σας. \nΕπικοινωνήστε με τον διαχειριστή."
"ReachedResourceLimitPleaseContact": "Φτάσατε το όριο των πόρων σας. \nΕπικοινωνήστε με τον διαχειριστή.",
"InvalidUrl": "Δεν είναι έγκυρη διεύθυνση URL"
},
"maxLength": {
"64chars": "(έως 64 χαρακτήρες)",
Expand Down
13 changes: 11 additions & 2 deletions resources/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -911,7 +911,15 @@
"ReplicaNumber": "Replica Number",
"ImportAndStartService": "Import & Start Service",
"huggingFaceUrlPlaceholder": "Input Hugging Face URL",
"ImportOnly": "Import only"
"ImportOnly": "Import only",
"StartWithHuggingFaceUrl": "It should start with https://huggingface.co",
"CheckHuggingFaceUrl": "Check",
"ModelName": "Model name",
"Author": "Author",
"InvalidHuggingFaceUrl": "Invalid Hugging Face URL.",
"ModelStoreFolderName": "Model store folder name",
"ServiceName": "Service name",
"HuggingFaceURL": "Higging Face"
}
},
"dialog": {
Expand Down Expand Up @@ -1610,7 +1618,8 @@
"FolderSharingNotAvailableToUser": "Folder sharing is not available for requested user(s).",
"APINotSupported": "API not supported. Requires latest version of Backend.AI manager.",
"ErrorFetchingExternalContent": "Error fetching external content:",
"ReachedResourceLimitPleaseContact": "Reached your resource limit. Please contact the administrator."
"ReachedResourceLimitPleaseContact": "Reached your resource limit. Please contact the administrator.",
"InvalidUrl": "It is not a valid URL"
},
"maxLength": {
"64chars": "(maximum 64 chars)",
Expand Down
12 changes: 10 additions & 2 deletions resources/i18n/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@
"UserHasNoGroup": "El usuario no tiene grupo. Póngase en contacto con el administrador para solucionarlo.",
"UserNameAlreadyExist": "El nombre de usuario ya existe. No se puede duplicar.",
"VirtualFolderAlreadyExist": "Ya existe una carpeta virtual con el mismo nombre. Elimine su propia carpeta o rechace la invitación.",
"ReachedResourceLimitPleaseContact": "Alcanzó su límite de recursos. \nPor favor contacte al administrador."
"ReachedResourceLimitPleaseContact": "Alcanzó su límite de recursos. \nPor favor contacte al administrador.",
"InvalidUrl": "No es una URL válida"
},
"DownloadSSHKey": "Descargar clave SSH",
"ErrorBoundary": {
Expand Down Expand Up @@ -416,7 +417,14 @@
"ReplicaNumber": "Número de réplica",
"ImportAndStartService": "Servicio de importación e inicio",
"huggingFaceUrlPlaceholder": "Introduzca la URL Hugging Face",
"ImportOnly": "Sólo importar"
"ImportOnly": "Sólo importar",
"StartWithHuggingFaceUrl": "Debería comenzar con https://huggingface.co",
"CheckHuggingFaceUrl": "Consulte",
"ModelName": "Nombre del modelo",
"Author": "Autor",
"InvalidHuggingFaceUrl": "URL Hugging Face no válida.",
"ModelStoreFolderName": "Nombre de la carpeta de la tienda de modelos",
"ServiceName": "Nombre del servicio"
}
},
"dialog": {
Expand Down
12 changes: 10 additions & 2 deletions resources/i18n/fi.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@
"UserHasNoGroup": "Käyttäjällä ei ole ryhmää. Ota yhteyttä ylläpitäjään sen korjaamiseksi.",
"UserNameAlreadyExist": "Käyttäjätunnus on jo olemassa. Sitä ei voi kopioida.",
"VirtualFolderAlreadyExist": "Samanniminen virtuaalikansio on jo olemassa. Poista oma kansiosi tai hylkää kutsu.",
"ReachedResourceLimitPleaseContact": "Resurssiraja saavutettu. \nOta yhteyttä ylläpitäjään."
"ReachedResourceLimitPleaseContact": "Resurssiraja saavutettu. \nOta yhteyttä ylläpitäjään.",
"InvalidUrl": "Se ei ole kelvollinen URL-osoite"
},
"DownloadSSHKey": "Lataa SSH-avain",
"ErrorBoundary": {
Expand Down Expand Up @@ -416,7 +417,14 @@
"ReplicaNumber": "Replikan numero",
"ImportAndStartService": "Tuo ja käynnistä palvelu",
"huggingFaceUrlPlaceholder": "Syötä Hugging Face-URL-osoite",
"ImportOnly": "Vain tuonti"
"ImportOnly": "Vain tuonti",
"StartWithHuggingFaceUrl": "Sen pitäisi alkaa https://huggingface.co",
"CheckHuggingFaceUrl": "Tarkista",
"ModelName": "Mallin nimi",
"Author": "Kirjoittaja",
"InvalidHuggingFaceUrl": "Virheellinen Hugging Face URL-osoite.",
"ModelStoreFolderName": "Mallin tallennuskansion nimi",
"ServiceName": "Palvelun nimi"
}
},
"dialog": {
Expand Down
12 changes: 10 additions & 2 deletions resources/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,14 @@
"ReplicaNumber": "Numéro de réplique",
"ImportAndStartService": "Service d'importation et de démarrage",
"huggingFaceUrlPlaceholder": "Saisissez l'URL Hugging Face",
"ImportOnly": "Importer uniquement"
"ImportOnly": "Importer uniquement",
"StartWithHuggingFaceUrl": "Cela devrait commencer par https://huggingface.co",
"CheckHuggingFaceUrl": "Vérifier",
"ModelName": "Nom du modèle",
"Author": "Auteur",
"InvalidHuggingFaceUrl": "URL Hugging Face non valide.",
"ModelStoreFolderName": "Nom du dossier du magasin de modèles",
"ServiceName": "Nom du service"
}
},
"dialog": {
Expand Down Expand Up @@ -1483,7 +1490,8 @@
"SmallerResourceThenImageRequires": "Votre demande de ressources est inférieure au minimum requis par l'image. Essayez d'autres ressources.",
"APINotSupported": "L'API n'est pas prise en charge. Nécessite la dernière version du gestionnaire Backend.AI.",
"WrongAPIServerAddress": "Mauvaise adresse du serveur API.",
"ReachedResourceLimitPleaseContact": "Vous avez atteint votre limite de ressources. \nVeuillez contacter l'administrateur."
"ReachedResourceLimitPleaseContact": "Vous avez atteint votre limite de ressources. \nVeuillez contacter l'administrateur.",
"InvalidUrl": "Ce n'est pas une URL valide"
},
"maxLength": {
"64chars": "(maximum 64 caractères)",
Expand Down
12 changes: 10 additions & 2 deletions resources/i18n/id.json
Original file line number Diff line number Diff line change
Expand Up @@ -787,7 +787,14 @@
"ReplicaNumber": "Nomor Replika",
"ImportAndStartService": "Impor dan Mulai Layanan",
"huggingFaceUrlPlaceholder": "Masukkan URL Hugging Face",
"ImportOnly": "Impor saja"
"ImportOnly": "Impor saja",
"StartWithHuggingFaceUrl": "Ini harus dimulai dengan https://huggingface.co",
"CheckHuggingFaceUrl": "Periksa",
"ModelName": "Nama model",
"Author": "Penulis",
"InvalidHuggingFaceUrl": "URL Hugging Face tidak valid.",
"ModelStoreFolderName": "Nama folder penyimpanan model",
"ServiceName": "Nama layanan"
}
},
"dialog": {
Expand Down Expand Up @@ -1484,7 +1491,8 @@
"SmallerResourceThenImageRequires": "Permintaan sumber daya Anda lebih kecil dari jumlah minimum yang dibutuhkan oleh gambar. Coba lebih banyak sumber daya.",
"APINotSupported": "API tidak didukung. Memerlukan versi terbaru dari manajer Backend.AI.",
"WrongAPIServerAddress": "Alamat server API salah.",
"ReachedResourceLimitPleaseContact": "Mencapai batas sumber daya Anda. \nSilakan hubungi administrator."
"ReachedResourceLimitPleaseContact": "Mencapai batas sumber daya Anda. \nSilakan hubungi administrator.",
"InvalidUrl": "Ini bukan URL yang valid"
},
"maxLength": {
"64chars": "(maksimum 64 karakter)",
Expand Down
12 changes: 10 additions & 2 deletions resources/i18n/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -787,7 +787,14 @@
"ReplicaNumber": "Numero di replica",
"ImportAndStartService": "Importa e avvia il servizio",
"huggingFaceUrlPlaceholder": "Inserisci l'URL Hugging Face.",
"ImportOnly": "Solo importazione"
"ImportOnly": "Solo importazione",
"StartWithHuggingFaceUrl": "Dovrebbe iniziare con https://huggingface.co",
"CheckHuggingFaceUrl": "Controllo",
"ModelName": "Nome del modello",
"Author": "Autore",
"InvalidHuggingFaceUrl": "URL Hugging Face non valido.",
"ModelStoreFolderName": "Nome della cartella dell'archivio modelli",
"ServiceName": "Nome del servizio"
}
},
"dialog": {
Expand Down Expand Up @@ -1483,7 +1490,8 @@
"SmallerResourceThenImageRequires": "La richiesta di risorse è inferiore al minimo richiesto dall'immagine. Provare con altre risorse.",
"APINotSupported": "API non supportata. Richiede l'ultima versione del gestore Backend.AI.",
"WrongAPIServerAddress": "Indirizzo del server API errato.",
"ReachedResourceLimitPleaseContact": "Raggiunto il limite delle risorse. \nSi prega di contattare l'amministratore."
"ReachedResourceLimitPleaseContact": "Raggiunto il limite delle risorse. \nSi prega di contattare l'amministratore.",
"InvalidUrl": "Non è un URL valido"
},
"maxLength": {
"64chars": "(massimo 64 caratteri)",
Expand Down
Loading
Loading