Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
ChengjieLi28 committed Dec 7, 2023
1 parent 347174c commit 93d40dc
Show file tree
Hide file tree
Showing 6 changed files with 280 additions and 21 deletions.
67 changes: 58 additions & 9 deletions xinference/web/ui/src/scenes/launch_model/embeddingCard.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { RocketLaunchOutlined, UndoOutlined } from '@mui/icons-material'
import { Box, Chip, CircularProgress } from '@mui/material'
import DeleteIcon from '@mui/icons-material/Delete'
import { Box, Chip, CircularProgress, Stack } from '@mui/material'
import IconButton from '@mui/material/IconButton'
import React, { useContext, useEffect, useState } from 'react'
import { v1 as uuidv1 } from 'uuid'

Expand All @@ -8,9 +10,15 @@ import { ApiContext } from '../../components/apiContext'
const CARD_HEIGHT = 270
const CARD_WIDTH = 270

const EmbeddingCard = ({ url, modelData }) => {
const EmbeddingCard = ({
url,
modelData,
cardHeight = CARD_HEIGHT,
is_custom = false,
}) => {
const [hover, setHover] = useState(false)
const [selected, setSelected] = useState(false)
const [customDeleted, setCustomDeleted] = useState(false)
const { isCallingApi, setIsCallingApi } = useContext(ApiContext)
const { isUpdatingModel } = useContext(ApiContext)
const { setErrorMsg } = useContext(ApiContext)
Expand Down Expand Up @@ -67,7 +75,7 @@ const EmbeddingCard = ({ url, modelData }) => {
display: 'block',
position: 'relative',
width: `${CARD_WIDTH}px`,
height: `${CARD_HEIGHT}px`,
height: `${cardHeight}px`,
border: '1px solid #ddd',
borderRadius: '20px',
background: 'white',
Expand All @@ -77,7 +85,7 @@ const EmbeddingCard = ({ url, modelData }) => {
display: 'block',
position: 'relative',
width: `${CARD_WIDTH}px`,
height: `${CARD_HEIGHT}px`,
height: `${cardHeight}px`,
border: '1px solid #ddd',
borderRadius: '20px',
background: 'white',
Expand All @@ -89,18 +97,18 @@ const EmbeddingCard = ({ url, modelData }) => {
top: '-1px',
left: '-1px',
width: `${CARD_WIDTH}px`,
height: `${CARD_HEIGHT}px`,
height: `${cardHeight}px`,
border: '1px solid #ddd',
padding: '20px',
borderRadius: '20px',
background: 'white',
},
parameterCard: {
position: 'relative',
top: `-${CARD_HEIGHT + 1}px`,
top: `-${cardHeight + 1}px`,
left: '-1px',
width: `${CARD_WIDTH}px`,
height: `${CARD_HEIGHT}px`,
height: `${cardHeight}px`,
border: '1px solid #ddd',
padding: '20px',
borderRadius: '20px',
Expand Down Expand Up @@ -188,22 +196,51 @@ const EmbeddingCard = ({ url, modelData }) => {
},
}

const handeCustomDelete = (e) => {
e.stopPropagation()
fetch(url + `/v1/model_registrations/embedding/${modelData.model_name}`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
},
})
.then(() => setCustomDeleted(true))
.catch(console.error)
}

// Set two different states based on mouse hover
return (
<Box
style={hover ? styles.containerSelected : styles.container}
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}
onClick={() => {
if (!selected) {
if (!selected && !customDeleted) {
setSelected(true)
}
}}
>
{/* First state: show description page */}
<Box style={styles.descriptionCard}>
<div style={styles.titleContainer}>
<h2 style={styles.h2}>{modelData.model_name}</h2>
{is_custom && (
<Stack
direction="row"
justifyContent="space-evenly"
alignItems="center"
spacing={1}
>
<h2 style={styles.h2}>{modelData.model_name}</h2>
<IconButton
aria-label="delete"
onClick={handeCustomDelete}
disabled={customDeleted}
>
<DeleteIcon />
</IconButton>
</Stack>
)}
{!is_custom && <h2 style={styles.h2}>{modelData.model_name}</h2>}
<div style={styles.langRow}>
{(() => {
if (modelData.language.includes('en')) {
Expand All @@ -222,6 +259,18 @@ const EmbeddingCard = ({ url, modelData }) => {
return <Chip label="ZH" variant="outlined" size="small" />
}
})()}
{(() => {
if (is_custom && customDeleted) {
return (
<Chip
label="Deleted"
variant="outlined"
size="small"
sx={{ marginLeft: '10px' }}
/>
)
}
})()}
</div>
</div>
<div style={styles.iconRow}>
Expand Down
5 changes: 5 additions & 0 deletions xinference/web/ui/src/scenes/launch_model/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import React from 'react'

import ErrorMessageSnackBar from '../../components/errorMessageSnackBar'
import Title from '../../components/Title'
import LaunchCustom from './launchCustom'
import LaunchEmbedding from './launchEmbedding'
import LaunchLLM from './launchLLM'
import LaunchRerank from './launchRerank'
Expand All @@ -25,6 +26,7 @@ const LaunchModel = () => {
<Tab label="Language Models" value="1" />
<Tab label="Embedding Models" value="2" />
<Tab label="Rerank Models" value="3" />
<Tab label="Custom Models" value="4" />
</TabList>
</Box>
<TabPanel value="1" sx={{ padding: 0 }}>
Expand All @@ -36,6 +38,9 @@ const LaunchModel = () => {
<TabPanel value="3" sx={{ padding: 0 }}>
<LaunchRerank />
</TabPanel>
<TabPanel value="4" sx={{ padding: 0 }}>
<LaunchCustom />
</TabPanel>
</TabContext>
</Box>
)
Expand Down
160 changes: 160 additions & 0 deletions xinference/web/ui/src/scenes/launch_model/launchCustom.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import { Box, FormControl, TextField } from '@mui/material'
import React, { useContext, useEffect, useState } from 'react'

import { ApiContext } from '../../components/apiContext'
import EmbeddingCard from './embeddingCard'
import ModelCard from './modelCard'

const LaunchCustom = () => {
let endPoint = useContext(ApiContext).endPoint
const [registrationData, setRegistrationData] = useState([])
const { isCallingApi, setIsCallingApi } = useContext(ApiContext)
const { isUpdatingModel } = useContext(ApiContext)

// States used for filtering
const [searchTerm, setSearchTerm] = useState('')

const handleChange = (event) => {
setSearchTerm(event.target.value)
}

const filter = (registration) => {
if (!registration || typeof searchTerm !== 'string') return false
const modelName = registration.model_name
? registration.model_name.toLowerCase()
: ''
return modelName.includes(searchTerm.toLowerCase())
}

const update = async () => {
if (isCallingApi || isUpdatingModel) return

try {
setIsCallingApi(true)

const embeddingResponse = await fetch(
`${endPoint}/v1/model_registrations/embedding`,
{
method: 'GET',
}
)

const embeddingRegistrations = await embeddingResponse.json()
const customEmbeddingRegistrations = embeddingRegistrations.filter(
(data) => !data.is_builtin
)

const llmResponse = await fetch(
`${endPoint}/v1/model_registrations/LLM`,
{
method: 'GET',
}
)
const llmRegistrations = await llmResponse.json()
const customLLMRegistrations = llmRegistrations.filter(
(data) => !data.is_builtin
)

const newEmbeddingData = await Promise.all(
customEmbeddingRegistrations.map(async (registration) => {
const desc = await fetch(
`${endPoint}/v1/model_registrations/embedding/${registration.model_name}`,
{
method: 'GET',
}
)

return {
...(await desc.json()),
is_builtin: registration.is_builtin,
}
})
)

const newLLMData = await Promise.all(
customLLMRegistrations.map(async (registration) => {
const desc = await fetch(
`${endPoint}/v1/model_registrations/LLM/${registration.model_name}`,
{
method: 'GET',
}
)

return {
...(await desc.json()),
is_builtin: registration.is_builtin,
}
})
)

setRegistrationData(newLLMData.concat(newEmbeddingData))
} catch (error) {
console.error('Error:', error)
} finally {
setIsCallingApi(false)
}
}

useEffect(() => {
update()
}, [])

const style = {
display: 'grid',
gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))',
paddingLeft: '2rem',
gridGap: '2rem 0rem',
}

return (
<Box m="20px">
<div
style={{
display: 'grid',
gridTemplateColumns: '1fr',
margin: '30px 2rem',
}}
>
<FormControl variant="outlined" margin="normal">
<TextField
id="search"
type="search"
label="Search for custom model name"
value={searchTerm}
onChange={handleChange}
size="small"
/>
</FormControl>
</div>
<div style={style}>
{registrationData
.filter((registration) => filter(registration))
.map((filteredRegistration) => {
if (
filteredRegistration.max_tokens &&
filteredRegistration.dimensions
) {
return (
<EmbeddingCard
url={endPoint}
modelData={filteredRegistration}
cardHeight={350}
is_custom={true}
/>
)
} else {
return (
<ModelCard
url={endPoint}
modelData={filteredRegistration}
is_custom={true}
/>
)
}
})}
</div>
</Box>
)
}

export default LaunchCustom
5 changes: 4 additions & 1 deletion xinference/web/ui/src/scenes/launch_model/launchEmbedding.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@ const LaunchEmbedding = () => {
})
)

setRegistrationData(newRegistrationData)
const builtinRegistrations = newRegistrationData.filter(
(v) => v.is_builtin
)
setRegistrationData(builtinRegistrations)
} catch (error) {
console.error('Error:', error)
} finally {
Expand Down
3 changes: 2 additions & 1 deletion xinference/web/ui/src/scenes/launch_model/launchLLM.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,9 @@ const LaunchLLM = () => {
)

const registrations = await response.json()
const builtinRegistrations = registrations.filter((v) => v.is_builtin)

setRegistrationData(registrations)
setRegistrationData(builtinRegistrations)
} catch (error) {
console.error('Error:', error)
} finally {
Expand Down
Loading

0 comments on commit 93d40dc

Please sign in to comment.