enhance UI
Browse files- README.md +1 -1
- package-lock.json +0 -0
- public/index.html +1 -4
- src/App.tsx +11 -4
- src/components/MarkdownRenderer.tsx +10 -13
- src/components/ModelInfo.tsx +34 -33
- src/components/ModelSelector.tsx +13 -14
- src/components/Tooltip.tsx +22 -0
- src/components/ZeroShotClassification.tsx +11 -8
- src/lib/huggingface.ts +10 -6
README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
---
|
2 |
-
title: Transformers
|
3 |
emoji: 🐠
|
4 |
colorFrom: indigo
|
5 |
colorTo: red
|
|
|
1 |
---
|
2 |
+
title: Transformers.js Playground
|
3 |
emoji: 🐠
|
4 |
colorFrom: indigo
|
5 |
colorTo: red
|
package-lock.json
CHANGED
The diff for this file is too large to render.
See raw diff
|
|
public/index.html
CHANGED
@@ -5,10 +5,7 @@
|
|
5 |
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
6 |
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
7 |
<meta name="theme-color" content="#000000" />
|
8 |
-
<meta
|
9 |
-
name="description"
|
10 |
-
content="Web site created using create-react-app"
|
11 |
-
/>
|
12 |
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
13 |
<!--
|
14 |
manifest.json provides metadata used when your web app is installed on a
|
|
|
5 |
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
6 |
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
7 |
<meta name="theme-color" content="#000000" />
|
8 |
+
<meta name="description" content="" />
|
|
|
|
|
|
|
9 |
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
10 |
<!--
|
11 |
manifest.json provides metadata used when your web app is installed on a
|
src/App.tsx
CHANGED
@@ -11,13 +11,20 @@ import ModelReadme from './components/ModelReadme'
|
|
11 |
import TextGeneration from './components/TextGeneration'
|
12 |
|
13 |
function App() {
|
14 |
-
const {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
|
16 |
useEffect(() => {
|
17 |
setModelInfo(null)
|
18 |
setModels([])
|
19 |
setIsFetching(true)
|
20 |
-
|
21 |
const fetchModels = async () => {
|
22 |
try {
|
23 |
const fetchedModels = await getModelsByPipeline(pipeline)
|
@@ -37,8 +44,8 @@ function App() {
|
|
37 |
<main className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
38 |
<div className="mb-8">
|
39 |
<div className="bg-white rounded-lg border p-6">
|
40 |
-
<div className="flex items-start justify-between
|
41 |
-
<div className="space-y-2
|
42 |
<div className="space-y-2">
|
43 |
<span className="text-lg font-semibold text-gray-900 block">
|
44 |
Choose a Pipeline
|
|
|
11 |
import TextGeneration from './components/TextGeneration'
|
12 |
|
13 |
function App() {
|
14 |
+
const {
|
15 |
+
pipeline,
|
16 |
+
setPipeline,
|
17 |
+
setModels,
|
18 |
+
setModelInfo,
|
19 |
+
modelInfo,
|
20 |
+
setIsFetching
|
21 |
+
} = useModel()
|
22 |
|
23 |
useEffect(() => {
|
24 |
setModelInfo(null)
|
25 |
setModels([])
|
26 |
setIsFetching(true)
|
27 |
+
|
28 |
const fetchModels = async () => {
|
29 |
try {
|
30 |
const fetchedModels = await getModelsByPipeline(pipeline)
|
|
|
44 |
<main className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
45 |
<div className="mb-8">
|
46 |
<div className="bg-white rounded-lg border p-6">
|
47 |
+
<div className="flex items-center lg:items-start justify-between mx-auto flex-col lg:flex-row">
|
48 |
+
<div className="space-y-2 w-10/12 lg:w-7/12">
|
49 |
<div className="space-y-2">
|
50 |
<span className="text-lg font-semibold text-gray-900 block">
|
51 |
Choose a Pipeline
|
src/components/MarkdownRenderer.tsx
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
import ReactMarkdown from 'react-markdown'
|
2 |
import remarkGfm from 'remark-gfm'
|
3 |
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
|
4 |
-
import {
|
5 |
|
6 |
interface MarkdownRendererProps {
|
7 |
content: string
|
@@ -15,13 +15,7 @@ const MarkdownRenderer = ({ content }: MarkdownRendererProps) => {
|
|
15 |
return (
|
16 |
<ReactMarkdown
|
17 |
remarkPlugins={[remarkGfm]}
|
18 |
-
disallowedElements={[
|
19 |
-
'script',
|
20 |
-
'style',
|
21 |
-
'iframe',
|
22 |
-
'object',
|
23 |
-
'embed',
|
24 |
-
]}
|
25 |
unwrapDisallowed={true}
|
26 |
components={{
|
27 |
code: ({ className, children, ...props }: any) => {
|
@@ -29,23 +23,26 @@ const MarkdownRenderer = ({ content }: MarkdownRendererProps) => {
|
|
29 |
const isInline = !match
|
30 |
return !isInline ? (
|
31 |
<SyntaxHighlighter
|
32 |
-
style={
|
33 |
language={match[1]}
|
34 |
PreTag="div"
|
35 |
-
className="rounded-md my-4"
|
36 |
{...props}
|
37 |
>
|
38 |
{String(children).replace(/\n$/, '')}
|
39 |
</SyntaxHighlighter>
|
40 |
) : (
|
41 |
-
<code
|
|
|
|
|
|
|
42 |
{children}
|
43 |
</code>
|
44 |
)
|
45 |
},
|
46 |
a: ({ children, href }) => (
|
47 |
-
<a
|
48 |
-
href={href}
|
49 |
className="text-blue-600 hover:text-blue-800 underline"
|
50 |
target="_blank"
|
51 |
rel="noopener noreferrer"
|
|
|
1 |
import ReactMarkdown from 'react-markdown'
|
2 |
import remarkGfm from 'remark-gfm'
|
3 |
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
|
4 |
+
import { oneLight } from 'react-syntax-highlighter/dist/esm/styles/prism'
|
5 |
|
6 |
interface MarkdownRendererProps {
|
7 |
content: string
|
|
|
15 |
return (
|
16 |
<ReactMarkdown
|
17 |
remarkPlugins={[remarkGfm]}
|
18 |
+
disallowedElements={['script', 'style', 'iframe', 'object', 'embed']}
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
unwrapDisallowed={true}
|
20 |
components={{
|
21 |
code: ({ className, children, ...props }: any) => {
|
|
|
23 |
const isInline = !match
|
24 |
return !isInline ? (
|
25 |
<SyntaxHighlighter
|
26 |
+
style={oneLight}
|
27 |
language={match[1]}
|
28 |
PreTag="div"
|
29 |
+
className="rounded-md my-4 border border-r-2"
|
30 |
{...props}
|
31 |
>
|
32 |
{String(children).replace(/\n$/, '')}
|
33 |
</SyntaxHighlighter>
|
34 |
) : (
|
35 |
+
<code
|
36 |
+
className="bg-gray-100 px-1 py-0.5 rounded text-sm font-mono"
|
37 |
+
{...props}
|
38 |
+
>
|
39 |
{children}
|
40 |
</code>
|
41 |
)
|
42 |
},
|
43 |
a: ({ children, href }) => (
|
44 |
+
<a
|
45 |
+
href={href}
|
46 |
className="text-blue-600 hover:text-blue-800 underline"
|
47 |
target="_blank"
|
48 |
rel="noopener noreferrer"
|
src/components/ModelInfo.tsx
CHANGED
@@ -11,6 +11,7 @@ import {
|
|
11 |
import { getModelSize } from '../lib/huggingface'
|
12 |
import { useModel } from '../contexts/ModelContext'
|
13 |
import ModelLoader from './ModelLoader'
|
|
|
14 |
|
15 |
const ModelInfo = () => {
|
16 |
const formatNumber = (num: number) => {
|
@@ -24,12 +25,7 @@ const ModelInfo = () => {
|
|
24 |
return num.toString()
|
25 |
}
|
26 |
|
27 |
-
const {
|
28 |
-
models,
|
29 |
-
modelInfo,
|
30 |
-
selectedQuantization,
|
31 |
-
isFetching
|
32 |
-
} = useModel()
|
33 |
|
34 |
const ModelInfoSkeleton = () => (
|
35 |
<div className="mt-5 bg-gradient-to-r from-blue-50 to-indigo-50 px-4 py-3 rounded-lg border border-blue-200 space-y-4 h-full min-h-[160px] animate-pulse w-[400px]">
|
@@ -70,7 +66,6 @@ const ModelInfo = () => {
|
|
70 |
return <ModelInfoSkeleton />
|
71 |
}
|
72 |
|
73 |
-
|
74 |
return (
|
75 |
<div className="mt-5 bg-gradient-to-r from-blue-50 to-indigo-50 px-4 py-3 rounded-lg border border-blue-200 space-y-3 h-full min-h-[150px]">
|
76 |
{/* Model Name Row */}
|
@@ -103,7 +98,7 @@ const ModelInfo = () => {
|
|
103 |
</div>
|
104 |
|
105 |
{/* Base Model Link */}
|
106 |
-
{modelInfo.baseId && (
|
107 |
<div className="flex items-center space-x-2 ml-6 text-xs text-gray-600 truncate max-w-100">
|
108 |
<a
|
109 |
href={`https://huggingface.co/${modelInfo.baseId}`}
|
@@ -112,8 +107,8 @@ const ModelInfo = () => {
|
|
112 |
className=" hover:underline"
|
113 |
title={`Base model: ${modelInfo.baseId}`}
|
114 |
>
|
115 |
-
<ExternalLink className="w-3 h-3 inline-block mr-1" />
|
116 |
-
|
117 |
</a>
|
118 |
</div>
|
119 |
)}
|
@@ -121,41 +116,47 @@ const ModelInfo = () => {
|
|
121 |
{/* Stats Row */}
|
122 |
<div className="flex items-center justify-self-end space-x-4 text-xs text-gray-600">
|
123 |
{modelInfo.likes > 0 && (
|
124 |
-
<div className="flex items-center space-x-1">
|
125 |
<Heart className="w-3 h-3 text-red-500" />
|
126 |
<span>{formatNumber(modelInfo.likes)}</span>
|
127 |
</div>
|
128 |
)}
|
129 |
|
130 |
{modelInfo.downloads > 0 && (
|
131 |
-
<div className="flex items-center space-x-1">
|
132 |
<Download className="w-3 h-3 text-green-500" />
|
133 |
<span>{formatNumber(modelInfo.downloads)}</span>
|
134 |
</div>
|
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 |
</div>
|
160 |
|
161 |
<ModelLoader />
|
|
|
11 |
import { getModelSize } from '../lib/huggingface'
|
12 |
import { useModel } from '../contexts/ModelContext'
|
13 |
import ModelLoader from './ModelLoader'
|
14 |
+
import Tooltip from './Tooltip'
|
15 |
|
16 |
const ModelInfo = () => {
|
17 |
const formatNumber = (num: number) => {
|
|
|
25 |
return num.toString()
|
26 |
}
|
27 |
|
28 |
+
const { models, modelInfo, selectedQuantization, isFetching } = useModel()
|
|
|
|
|
|
|
|
|
|
|
29 |
|
30 |
const ModelInfoSkeleton = () => (
|
31 |
<div className="mt-5 bg-gradient-to-r from-blue-50 to-indigo-50 px-4 py-3 rounded-lg border border-blue-200 space-y-4 h-full min-h-[160px] animate-pulse w-[400px]">
|
|
|
66 |
return <ModelInfoSkeleton />
|
67 |
}
|
68 |
|
|
|
69 |
return (
|
70 |
<div className="mt-5 bg-gradient-to-r from-blue-50 to-indigo-50 px-4 py-3 rounded-lg border border-blue-200 space-y-3 h-full min-h-[150px]">
|
71 |
{/* Model Name Row */}
|
|
|
98 |
</div>
|
99 |
|
100 |
{/* Base Model Link */}
|
101 |
+
{modelInfo.baseId && modelInfo.baseId !== modelInfo.id && (
|
102 |
<div className="flex items-center space-x-2 ml-6 text-xs text-gray-600 truncate max-w-100">
|
103 |
<a
|
104 |
href={`https://huggingface.co/${modelInfo.baseId}`}
|
|
|
107 |
className=" hover:underline"
|
108 |
title={`Base model: ${modelInfo.baseId}`}
|
109 |
>
|
110 |
+
<ExternalLink className="w-3 h-3 inline-block mr-1" />(
|
111 |
+
{modelInfo.baseId})
|
112 |
</a>
|
113 |
</div>
|
114 |
)}
|
|
|
116 |
{/* Stats Row */}
|
117 |
<div className="flex items-center justify-self-end space-x-4 text-xs text-gray-600">
|
118 |
{modelInfo.likes > 0 && (
|
119 |
+
<div className="flex items-center space-x-1 cursor-default">
|
120 |
<Heart className="w-3 h-3 text-red-500" />
|
121 |
<span>{formatNumber(modelInfo.likes)}</span>
|
122 |
</div>
|
123 |
)}
|
124 |
|
125 |
{modelInfo.downloads > 0 && (
|
126 |
+
<div className="flex items-center space-x-1 cursor-default">
|
127 |
<Download className="w-3 h-3 text-green-500" />
|
128 |
<span>{formatNumber(modelInfo.downloads)}</span>
|
129 |
</div>
|
130 |
)}
|
131 |
|
132 |
+
<Tooltip content="Model parameters according to Hugging Face API">
|
133 |
+
<div className="flex items-center space-x-1 cursor-default">
|
134 |
+
<Cpu className="w-3 h-3 text-purple-500" />
|
135 |
+
{modelInfo.parameters ? (
|
136 |
+
<span>{formatNumber(modelInfo.parameters)}</span>
|
137 |
+
) : (
|
138 |
+
<span>?</span>
|
139 |
+
)}
|
140 |
+
</div>
|
141 |
+
</Tooltip>
|
142 |
|
143 |
+
<Tooltip
|
144 |
+
content={`Estimated size with ${selectedQuantization} quantization`}
|
145 |
+
>
|
146 |
+
<div className="flex items-center space-x-1 cursor-default">
|
147 |
+
<DatabaseIcon className="w-3 h-3 text-purple-500" />
|
148 |
+
{modelInfo.parameters ? (
|
149 |
+
<span>
|
150 |
+
{`~${getModelSize(
|
151 |
+
modelInfo.parameters,
|
152 |
+
selectedQuantization
|
153 |
+
).toFixed(1)}MB`}
|
154 |
+
</span>
|
155 |
+
) : (
|
156 |
+
<span>?</span>
|
157 |
+
)}
|
158 |
+
</div>
|
159 |
+
</Tooltip>
|
160 |
</div>
|
161 |
|
162 |
<ModelLoader />
|
src/components/ModelSelector.tsx
CHANGED
@@ -108,7 +108,9 @@ function ModelSelector() {
|
|
108 |
supportedQuantizations: modelInfoResponse.supportedQuantizations,
|
109 |
baseId: modelInfoResponse.baseId,
|
110 |
readme: modelInfoResponse.readme,
|
111 |
-
hasChatTemplate: Boolean(
|
|
|
|
|
112 |
}
|
113 |
setModelInfo(modelInfo)
|
114 |
setIsCustomModel(isCustom)
|
@@ -314,7 +316,7 @@ function ModelSelector() {
|
|
314 |
leaveFrom="transform scale-100 opacity-100"
|
315 |
leaveTo="transform scale-95 opacity-0"
|
316 |
>
|
317 |
-
<ListboxOptions className="absolute z-10 w-full mt-1 bg-white border border-gray-300 rounded-md shadow-lg max-h-
|
318 |
{/* Custom Model Input */}
|
319 |
{showCustomInput ? (
|
320 |
<div className="px-3 py-3 border-b border-gray-200 bg-gray-50 sticky top-0 z-10">
|
@@ -362,8 +364,8 @@ function ModelSelector() {
|
|
362 |
</div>
|
363 |
) : (
|
364 |
<>
|
365 |
-
|
366 |
-
|
367 |
<button
|
368 |
onClick={() => setShowCustomInput(true)}
|
369 |
className="w-full flex items-center justify-center space-x-2 px-3 py-2 text-sm text-blue-600 hover:bg-blue-50 rounded transition-colors"
|
@@ -371,10 +373,8 @@ function ModelSelector() {
|
|
371 |
<Plus className="w-4 h-4" />
|
372 |
<span>Load Custom Model</span>
|
373 |
</button>
|
374 |
-
</div>
|
375 |
|
376 |
-
|
377 |
-
<div className="px-3 py-2 border-b border-gray-200 bg-gray-50 sticky top-0 z-10">
|
378 |
<div className="flex items-center space-x-2 text-xs">
|
379 |
<span className="text-gray-600 font-medium">
|
380 |
Sort by:
|
@@ -455,16 +455,15 @@ function ModelSelector() {
|
|
455 |
}
|
456 |
>
|
457 |
{({ selected }) => (
|
458 |
-
<div className="flex items-center justify-between">
|
459 |
-
<div className="flex items-center flex-1
|
460 |
-
<span className="text-sm font-medium truncate">
|
461 |
{model.id}
|
462 |
</span>
|
463 |
-
{selected && (
|
464 |
-
<Check className="w-4 h-4 text-blue-600 ml-2 flex-shrink-0" />
|
465 |
-
)}
|
466 |
</div>
|
467 |
-
|
|
|
|
|
468 |
{/* Stats Display */}
|
469 |
{hasStats && (
|
470 |
<div className="flex items-center space-x-3 text-xs text-gray-500 flex-shrink-0">
|
|
|
108 |
supportedQuantizations: modelInfoResponse.supportedQuantizations,
|
109 |
baseId: modelInfoResponse.baseId,
|
110 |
readme: modelInfoResponse.readme,
|
111 |
+
hasChatTemplate: Boolean(
|
112 |
+
modelInfoResponse.config?.tokenizer_config?.chat_template
|
113 |
+
)
|
114 |
}
|
115 |
setModelInfo(modelInfo)
|
116 |
setIsCustomModel(isCustom)
|
|
|
316 |
leaveFrom="transform scale-100 opacity-100"
|
317 |
leaveTo="transform scale-95 opacity-0"
|
318 |
>
|
319 |
+
<ListboxOptions className="absolute z-10 w-full mt-1 bg-white border border-gray-300 rounded-md shadow-lg max-h-96 overflow-hidden focus:outline-none">
|
320 |
{/* Custom Model Input */}
|
321 |
{showCustomInput ? (
|
322 |
<div className="px-3 py-3 border-b border-gray-200 bg-gray-50 sticky top-0 z-10">
|
|
|
364 |
</div>
|
365 |
) : (
|
366 |
<>
|
367 |
+
<div className="sticky top-0 z-10 bg-gray-50 border-b border-gray-200 p-3 space-y-3">
|
368 |
+
{/* Load Custom Model Button */}
|
369 |
<button
|
370 |
onClick={() => setShowCustomInput(true)}
|
371 |
className="w-full flex items-center justify-center space-x-2 px-3 py-2 text-sm text-blue-600 hover:bg-blue-50 rounded transition-colors"
|
|
|
373 |
<Plus className="w-4 h-4" />
|
374 |
<span>Load Custom Model</span>
|
375 |
</button>
|
|
|
376 |
|
377 |
+
{/* Sort Controls */}
|
|
|
378 |
<div className="flex items-center space-x-2 text-xs">
|
379 |
<span className="text-gray-600 font-medium">
|
380 |
Sort by:
|
|
|
455 |
}
|
456 |
>
|
457 |
{({ selected }) => (
|
458 |
+
<div className="relative flex items-center justify-between">
|
459 |
+
<div className="flex items-center flex-1 w-5/12">
|
460 |
+
<span className="text-sm font-medium truncate w-11/12 ">
|
461 |
{model.id}
|
462 |
</span>
|
|
|
|
|
|
|
463 |
</div>
|
464 |
+
{selected && (
|
465 |
+
<Check className="mr-2 w-4 h-4 text-blue-600 ml-2 flex-shrink-0" />
|
466 |
+
)}
|
467 |
{/* Stats Display */}
|
468 |
{hasStats && (
|
469 |
<div className="flex items-center space-x-3 text-xs text-gray-500 flex-shrink-0">
|
src/components/Tooltip.tsx
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React from 'react'
|
2 |
+
|
3 |
+
interface TooltipProps {
|
4 |
+
children: React.ReactNode
|
5 |
+
content: string | React.ReactNode
|
6 |
+
className?: string
|
7 |
+
}
|
8 |
+
|
9 |
+
const Tooltip: React.FC<TooltipProps> = ({ children, content, className }) => {
|
10 |
+
return (
|
11 |
+
<div className="relative group flex items-center">
|
12 |
+
{children}
|
13 |
+
<div
|
14 |
+
className={`absolute bottom-full mb-2 w-max max-w-xs px-3 py-1.5 text-xs font-medium text-white bg-gray-900 rounded-lg shadow-sm opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-opacity duration-300 z-10 ${className}`}
|
15 |
+
>
|
16 |
+
{content}
|
17 |
+
</div>
|
18 |
+
</div>
|
19 |
+
)
|
20 |
+
}
|
21 |
+
|
22 |
+
export default Tooltip
|
src/components/ZeroShotClassification.tsx
CHANGED
@@ -1,9 +1,5 @@
|
|
1 |
-
import { useState,
|
2 |
-
import {
|
3 |
-
Section,
|
4 |
-
WorkerMessage,
|
5 |
-
ZeroShotWorkerInput,
|
6 |
-
} from '../types'
|
7 |
import { useModel } from '../contexts/ModelContext'
|
8 |
|
9 |
const PLACEHOLDER_REVIEWS: string[] = [
|
@@ -48,7 +44,13 @@ function ZeroShotClassification() {
|
|
48 |
PLACEHOLDER_SECTIONS.map((title) => ({ title, items: [] }))
|
49 |
)
|
50 |
|
51 |
-
const {
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
|
53 |
const classify = useCallback(() => {
|
54 |
if (!modelInfo || !activeWorker) {
|
@@ -157,7 +159,8 @@ function ZeroShotClassification() {
|
|
157 |
disabled={busy}
|
158 |
onClick={classify}
|
159 |
>
|
160 |
-
{hasBeenLoaded
|
|
|
161 |
? 'Categorize'
|
162 |
: 'Processing...'
|
163 |
: 'Load model first'}
|
|
|
1 |
+
import { useState, useEffect, useCallback } from 'react'
|
2 |
+
import { Section, WorkerMessage, ZeroShotWorkerInput } from '../types'
|
|
|
|
|
|
|
|
|
3 |
import { useModel } from '../contexts/ModelContext'
|
4 |
|
5 |
const PLACEHOLDER_REVIEWS: string[] = [
|
|
|
44 |
PLACEHOLDER_SECTIONS.map((title) => ({ title, items: [] }))
|
45 |
)
|
46 |
|
47 |
+
const {
|
48 |
+
activeWorker,
|
49 |
+
status,
|
50 |
+
modelInfo,
|
51 |
+
hasBeenLoaded,
|
52 |
+
selectedQuantization
|
53 |
+
} = useModel()
|
54 |
|
55 |
const classify = useCallback(() => {
|
56 |
if (!modelInfo || !activeWorker) {
|
|
|
159 |
disabled={busy}
|
160 |
onClick={classify}
|
161 |
>
|
162 |
+
{hasBeenLoaded
|
163 |
+
? !busy
|
164 |
? 'Categorize'
|
165 |
: 'Processing...'
|
166 |
: 'Load model first'}
|
src/lib/huggingface.ts
CHANGED
@@ -1,5 +1,9 @@
|
|
1 |
import { supportedPipelines } from '../components/PipelineSelector'
|
2 |
-
import {
|
|
|
|
|
|
|
|
|
3 |
|
4 |
const getModelInfo = async (
|
5 |
modelName: string,
|
@@ -16,7 +20,7 @@ const getModelInfo = async (
|
|
16 |
const response = await fetch(
|
17 |
`https://huggingface.co/api/models/${modelName}`,
|
18 |
{
|
19 |
-
method: 'GET'
|
20 |
// headers: {
|
21 |
// Authorization: `Bearer ${token}`
|
22 |
// }
|
@@ -102,7 +106,7 @@ const getModelInfo = async (
|
|
102 |
const baseModelResponse = await fetch(
|
103 |
`https://huggingface.co/api/models/${baseModel}`,
|
104 |
{
|
105 |
-
method: 'GET'
|
106 |
// headers: {
|
107 |
// Authorization: `Bearer ${token}`
|
108 |
// }
|
@@ -152,7 +156,7 @@ const getModelsByPipeline = async (
|
|
152 |
const response1 = await fetch(
|
153 |
`https://huggingface.co/api/models?filter=${pipelineTag}&filter=onnx&sort=downloads&limit=50`,
|
154 |
{
|
155 |
-
method: 'GET'
|
156 |
// headers: {
|
157 |
// Authorization: `Bearer ${token}`
|
158 |
// }
|
@@ -169,7 +173,7 @@ const getModelsByPipeline = async (
|
|
169 |
const response2 = await fetch(
|
170 |
`https://huggingface.co/api/models?filter=${pipelineTag}&search=onnx&sort=downloads&limit=50`,
|
171 |
{
|
172 |
-
method: 'GET'
|
173 |
// headers: {
|
174 |
// Authorization: `Bearer ${token}`
|
175 |
// }
|
@@ -219,7 +223,7 @@ const getModelsByPipelineCustom = async (
|
|
219 |
const response = await fetch(
|
220 |
`https://huggingface.co/api/models?filter=${pipelineTag}&search=${searchString}&sort=downloads&limit=50`,
|
221 |
{
|
222 |
-
method: 'GET'
|
223 |
// headers: {
|
224 |
// Authorization: `Bearer ${token}`
|
225 |
// }
|
|
|
1 |
import { supportedPipelines } from '../components/PipelineSelector'
|
2 |
+
import {
|
3 |
+
allQuantizationTypes,
|
4 |
+
ModelInfoResponse,
|
5 |
+
QuantizationType
|
6 |
+
} from '../types'
|
7 |
|
8 |
const getModelInfo = async (
|
9 |
modelName: string,
|
|
|
20 |
const response = await fetch(
|
21 |
`https://huggingface.co/api/models/${modelName}`,
|
22 |
{
|
23 |
+
method: 'GET'
|
24 |
// headers: {
|
25 |
// Authorization: `Bearer ${token}`
|
26 |
// }
|
|
|
106 |
const baseModelResponse = await fetch(
|
107 |
`https://huggingface.co/api/models/${baseModel}`,
|
108 |
{
|
109 |
+
method: 'GET'
|
110 |
// headers: {
|
111 |
// Authorization: `Bearer ${token}`
|
112 |
// }
|
|
|
156 |
const response1 = await fetch(
|
157 |
`https://huggingface.co/api/models?filter=${pipelineTag}&filter=onnx&sort=downloads&limit=50`,
|
158 |
{
|
159 |
+
method: 'GET'
|
160 |
// headers: {
|
161 |
// Authorization: `Bearer ${token}`
|
162 |
// }
|
|
|
173 |
const response2 = await fetch(
|
174 |
`https://huggingface.co/api/models?filter=${pipelineTag}&search=onnx&sort=downloads&limit=50`,
|
175 |
{
|
176 |
+
method: 'GET'
|
177 |
// headers: {
|
178 |
// Authorization: `Bearer ${token}`
|
179 |
// }
|
|
|
223 |
const response = await fetch(
|
224 |
`https://huggingface.co/api/models?filter=${pipelineTag}&search=${searchString}&sort=downloads&limit=50`,
|
225 |
{
|
226 |
+
method: 'GET'
|
227 |
// headers: {
|
228 |
// Authorization: `Bearer ${token}`
|
229 |
// }
|