File size: 7,578 Bytes
4d810fa 117cfaa 96812c9 4d810fa 96812c9 117cfaa 96812c9 4d810fa 6ebf2fd 4d810fa 6ebf2fd 046ca57 6ebf2fd 322c234 4d810fa 322c234 4d810fa 322c234 4d810fa dc79f22 4d810fa 6ebf2fd 79eafc9 97cab0c 4d810fa 97cab0c 4d810fa 6ebf2fd 117cfaa 6ebf2fd 97cab0c 4d810fa 6ebf2fd 4d810fa 79eafc9 6ebf2fd 4d810fa 97cab0c 4d810fa 6ebf2fd 97cab0c 79eafc9 6ebf2fd 96812c9 59a1fe9 322c234 59a1fe9 0250375 322c234 25e8265 322c234 117cfaa 322c234 4d810fa 322c234 0250375 322c234 0250375 322c234 117cfaa 322c234 0250375 4d810fa 322c234 4d810fa 322c234 25e8265 25647ae 79eafc9 25647ae 322c234 4d810fa 25e8265 322c234 59a1fe9 322c234 59a1fe9 117cfaa 59a1fe9 4d810fa 59a1fe9 322c234 4d810fa 322c234 ad5cef3 97cab0c ad5cef3 322c234 59a1fe9 4d810fa 322c234 59a1fe9 1150456 6ebf2fd 1150456 6ebf2fd 1150456 6ebf2fd 1150456 6ebf2fd 4d810fa 1150456 4d810fa 1150456 4d810fa |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 |
import { supportedPipelines } from '../components/PipelineSelector'
import {
allQuantizationTypes,
ModelInfoResponse,
QuantizationType
} from '../types'
const getModelInfo = async (
modelName: string,
pipeline: string
): Promise<ModelInfoResponse> => {
const response = await fetch(
`https://huggingface.co/api/models/${modelName}`,
{
method: 'GET'
}
)
if (!response.ok) {
throw new Error(`Failed to fetch model info: ${response.statusText}`)
}
const modelData: ModelInfoResponse = await response.json()
const requiredFiles = [
'config.json'
// 'tokenizer.json',
// 'tokenizer_config.json'
]
const siblingFiles = modelData.siblings?.map((s) => s.rfilename) || []
const missingFiles = requiredFiles.filter(
(file) => !siblingFiles.includes(file)
)
const hasOnnxFolder = siblingFiles.some(
(file) => file.endsWith('.onnx') && file.startsWith('onnx/')
)
const isCompatible =
missingFiles.length === 0 &&
hasOnnxFolder &&
modelData.tags.includes(pipeline)
let incompatibilityReason = ''
if (!modelData.tags.includes(pipeline)) {
const expectedPipelines = modelData.tags
.filter((tag) => supportedPipelines.includes(tag))
.join(', ')
incompatibilityReason = expectedPipelines
? `- Model can be used with ${expectedPipelines} pipelines only\n`
: `- Pipeline ${pipeline} not supported by the model\n`
}
if (missingFiles.length > 0) {
incompatibilityReason += `- Missing required files: ${missingFiles.join(
', '
)}\n`
} else if (!hasOnnxFolder) {
incompatibilityReason += '- Folder onnx/ is missing\n'
}
const supportedQuantizations = hasOnnxFolder
? siblingFiles
.filter((file) => file.endsWith('.onnx') && file.includes('_'))
.map((file) => file.split('/')[1].split('_')[1].split('.')[0])
.filter((q) => q !== 'quantized')
.filter((q) => allQuantizationTypes.includes(q as QuantizationType))
: []
const uniqueSupportedQuantizations = Array.from(
new Set(supportedQuantizations)
)
uniqueSupportedQuantizations.sort((a, b) => {
const getNumericValue = (str: string) => {
const match = str.match(/(\d+)/)
return match ? parseInt(match[1]) : Infinity
}
return getNumericValue(a) - getNumericValue(b)
})
if (
uniqueSupportedQuantizations.length === 0 &&
siblingFiles.some((file) => file.endsWith('_quantized.onnx'))
) {
uniqueSupportedQuantizations.push('q8')
}
const voices: string[] = []
siblingFiles
.filter((file) => file.startsWith('voices/') && !file.endsWith('af.bin'))
.forEach((file) => {
voices.push(file.split('/')[1].split('.')[0])
})
// Fetch README content
const fetchReadme = async (modelId: string): Promise<string> => {
try {
const readmeResponse = await fetch(
`https://huggingface.co/${modelId}/raw/main/README.md`
)
if (readmeResponse.ok) {
return await readmeResponse.text()
}
} catch (error) {
console.warn(`Failed to fetch README for ${modelId}:`, error)
}
return ''
}
const baseModel = modelData.cardData?.base_model ?? modelData.modelId
if (baseModel && !modelData.safetensors) {
const baseModelResponse = await fetch(
`https://huggingface.co/api/models/${baseModel}`,
{
method: 'GET'
}
)
if (baseModelResponse.ok) {
const baseModelData: ModelInfoResponse = await baseModelResponse.json()
const readme = await fetchReadme(baseModel)
return {
...baseModelData,
id: modelData.id,
baseId: baseModel,
isCompatible,
incompatibilityReason,
supportedQuantizations:
uniqueSupportedQuantizations as QuantizationType[],
readme,
voices
}
}
}
const readme = await fetchReadme(modelData.id)
return {
...modelData,
isCompatible,
incompatibilityReason,
supportedQuantizations: uniqueSupportedQuantizations as QuantizationType[],
readme,
voices
}
}
const getModelsByPipeline = async (
pipelineTag: string
): Promise<ModelInfoResponse[]> => {
// Second search with search=onnx
const response1 = await fetch(
`https://huggingface.co/api/models?filter=${pipelineTag}&search=onnx-community&sort=createdAt&limit=15`,
{
method: 'GET'
}
)
if (!response1.ok) {
throw new Error(
`Failed to fetch models for pipeline: ${response1.statusText}`
)
}
const models1 = await response1.json()
// First search with filter=onnx
const response2 = await fetch(
`https://huggingface.co/api/models?filter=${pipelineTag}${pipelineTag === 'feature-extraction' ? '&library=sentence-transformers' : '&filter=onnx'}&sort=downloads&limit=50`,
{
method: 'GET'
}
)
if (!response1.ok) {
throw new Error(
`Failed to fetch models for pipeline: ${response2.statusText}`
)
}
const models2 = await response2.json()
// Combine and deduplicate models based on id
const combinedModels = [...models1, ...models2].filter(
(m: ModelInfoResponse) => m.createdAt > '2022/02/03'
)
const uniqueModels = combinedModels.filter(
(model, index, self) => index === self.findIndex((m) => m.id === model.id)
)
if (pipelineTag === 'text-classification') {
return uniqueModels
.filter(
(model: ModelInfoResponse) =>
!model.tags.includes('reranker') &&
!model.id.includes('reranker') &&
!model.id.includes('ms-marco') &&
!model.id.includes('MiniLM')
)
.slice(0, 30)
} else if (pipelineTag === 'text-to-speech') {
return uniqueModels
.filter(
(model: ModelInfoResponse) =>
// !model.tags.includes('style_text_to_speech_2') &&
!model.id.includes('qwen2')
)
.slice(0, 30)
}
return uniqueModels.slice(0, 30)
}
const getModelsByPipelineCustom = async (
searchString: string,
pipelineTag: string
): Promise<ModelInfoResponse[]> => {
const response = await fetch(
`https://huggingface.co/api/models?filter=${pipelineTag}&search=${searchString}&sort=downloads&limit=50`,
{
method: 'GET'
}
)
if (!response.ok) {
throw new Error(
`Failed to fetch models for pipeline: ${response.statusText}`
)
}
const models = await response.json()
const uniqueModels = models.filter(
(m: ModelInfoResponse) => m.createdAt > '2022/02/03'
)
if (pipelineTag === 'text-classification') {
return uniqueModels
.filter(
(model: ModelInfoResponse) =>
!model.tags.includes('reranker') &&
!model.id.includes('reranker') &&
!model.id.includes('ms-marco') &&
!model.id.includes('MiniLM')
)
.slice(0, 20)
}
return uniqueModels.slice(0, 20)
}
function getModelSize(
parameters: number,
quantization: QuantizationType
): number {
let bytesPerParameter: number
switch (quantization) {
case 'fp32':
// 32-bit floating point uses 4 bytes
bytesPerParameter = 4
break
case 'fp16':
bytesPerParameter = 2
break
case 'int8':
case 'bnb8':
case 'uint8':
case 'q8':
bytesPerParameter = 1
break
case 'bnb4':
case 'q4':
case 'q4f16':
bytesPerParameter = 0.5
break
}
const sizeInBytes = parameters * bytesPerParameter
const sizeInMB = sizeInBytes / (1024 * 1024)
return sizeInMB
}
export {
getModelInfo,
getModelSize,
getModelsByPipeline,
getModelsByPipelineCustom
}
|