Move pipeline components to dedicated folder
Browse files- src/App.tsx +4 -4
- src/components/Sidebar.tsx +3 -3
- src/components/{FeatureExtraction.tsx → pipelines/FeatureExtraction.tsx} +3 -3
- src/components/{FeatureExtractionConfig.tsx → pipelines/FeatureExtractionConfig.tsx} +17 -11
- src/components/{TextClassification.tsx → pipelines/TextClassification.tsx} +2 -2
- src/components/{TextGeneration.tsx → pipelines/TextGeneration.tsx} +7 -3
- src/components/{TextGenerationConfig.tsx → pipelines/TextGenerationConfig.tsx} +2 -2
- src/components/{ZeroShotClassification.tsx → pipelines/ZeroShotClassification.tsx} +7 -7
- src/components/{ZeroShotClassificationConfig.tsx → pipelines/ZeroShotClassificationConfig.tsx} +20 -12
- src/lib/huggingface.ts +6 -1
src/App.tsx
CHANGED
@@ -1,12 +1,12 @@
|
|
1 |
import { useEffect, useState } from 'react'
|
2 |
import { Settings } from 'lucide-react'
|
3 |
-
import ZeroShotClassification from './components/ZeroShotClassification'
|
4 |
-
import TextClassification from './components/TextClassification'
|
5 |
import Header from './Header'
|
6 |
import { useModel } from './contexts/ModelContext'
|
7 |
import { getModelsByPipeline } from './lib/huggingface'
|
8 |
-
import TextGeneration from './components/TextGeneration'
|
9 |
-
import FeatureExtraction from './components/FeatureExtraction'
|
10 |
import Sidebar from './components/Sidebar'
|
11 |
import ModelReadme from './components/ModelReadme'
|
12 |
import { PipelineLayout } from './components/PipelineLayout'
|
|
|
1 |
import { useEffect, useState } from 'react'
|
2 |
import { Settings } from 'lucide-react'
|
3 |
+
import ZeroShotClassification from './components/pipelines/ZeroShotClassification'
|
4 |
+
import TextClassification from './components/pipelines/TextClassification'
|
5 |
import Header from './Header'
|
6 |
import { useModel } from './contexts/ModelContext'
|
7 |
import { getModelsByPipeline } from './lib/huggingface'
|
8 |
+
import TextGeneration from './components/pipelines/TextGeneration'
|
9 |
+
import FeatureExtraction from './components/pipelines/FeatureExtraction'
|
10 |
import Sidebar from './components/Sidebar'
|
11 |
import ModelReadme from './components/ModelReadme'
|
12 |
import { PipelineLayout } from './components/PipelineLayout'
|
src/components/Sidebar.tsx
CHANGED
@@ -3,9 +3,9 @@ import PipelineSelector from './PipelineSelector'
|
|
3 |
import ModelSelector from './ModelSelector'
|
4 |
import ModelInfo from './ModelInfo'
|
5 |
import { useModel } from '../contexts/ModelContext'
|
6 |
-
import TextGenerationConfig from './TextGenerationConfig'
|
7 |
-
import FeatureExtractionConfig from './FeatureExtractionConfig'
|
8 |
-
import ZeroShotClassificationConfig from './ZeroShotClassificationConfig'
|
9 |
|
10 |
interface SidebarProps {
|
11 |
isOpen: boolean
|
|
|
3 |
import ModelSelector from './ModelSelector'
|
4 |
import ModelInfo from './ModelInfo'
|
5 |
import { useModel } from '../contexts/ModelContext'
|
6 |
+
import TextGenerationConfig from './pipelines/TextGenerationConfig'
|
7 |
+
import FeatureExtractionConfig from './pipelines/FeatureExtractionConfig'
|
8 |
+
import ZeroShotClassificationConfig from './pipelines/ZeroShotClassificationConfig'
|
9 |
|
10 |
interface SidebarProps {
|
11 |
isOpen: boolean
|
src/components/{FeatureExtraction.tsx → pipelines/FeatureExtraction.tsx}
RENAMED
@@ -4,9 +4,9 @@ import {
|
|
4 |
EmbeddingExample,
|
5 |
FeatureExtractionWorkerInput,
|
6 |
WorkerMessage
|
7 |
-
} from '
|
8 |
-
import { useModel } from '
|
9 |
-
import { useFeatureExtraction } from '
|
10 |
|
11 |
interface Point2D {
|
12 |
x: number
|
|
|
4 |
EmbeddingExample,
|
5 |
FeatureExtractionWorkerInput,
|
6 |
WorkerMessage
|
7 |
+
} from '../../types'
|
8 |
+
import { useModel } from '../../contexts/ModelContext'
|
9 |
+
import { useFeatureExtraction } from '../../contexts/FeatureExtractionContext'
|
10 |
|
11 |
interface Point2D {
|
12 |
x: number
|
src/components/{FeatureExtractionConfig.tsx → pipelines/FeatureExtractionConfig.tsx}
RENAMED
@@ -1,5 +1,5 @@
|
|
1 |
import React from 'react'
|
2 |
-
import { useFeatureExtraction } from '
|
3 |
|
4 |
const FeatureExtractionConfig = () => {
|
5 |
const { config, setConfig } = useFeatureExtraction()
|
@@ -17,10 +17,12 @@ const FeatureExtractionConfig = () => {
|
|
17 |
</label>
|
18 |
<select
|
19 |
value={config.pooling}
|
20 |
-
onChange={(e) =>
|
21 |
-
|
22 |
-
|
23 |
-
|
|
|
|
|
24 |
className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm"
|
25 |
>
|
26 |
<option value="mean">Mean Pooling</option>
|
@@ -37,10 +39,12 @@ const FeatureExtractionConfig = () => {
|
|
37 |
<input
|
38 |
type="checkbox"
|
39 |
checked={config.normalize}
|
40 |
-
onChange={(e) =>
|
41 |
-
|
42 |
-
|
43 |
-
|
|
|
|
|
44 |
className="rounded border-gray-300 text-blue-600 shadow-sm focus:border-blue-300 focus:ring focus:ring-blue-200 focus:ring-opacity-50"
|
45 |
/>
|
46 |
<span className="text-sm font-medium text-gray-700">
|
@@ -59,10 +63,12 @@ const FeatureExtractionConfig = () => {
|
|
59 |
<strong>Mean Pooling:</strong> Average all token embeddings
|
60 |
</p>
|
61 |
<p className="mb-1">
|
62 |
-
<strong>CLS Token:</strong> Use the [CLS] token embedding (if
|
|
|
63 |
</p>
|
64 |
<p>
|
65 |
-
<strong>Max Pooling:</strong> Take element-wise maximum across
|
|
|
66 |
</p>
|
67 |
</div>
|
68 |
</div>
|
|
|
1 |
import React from 'react'
|
2 |
+
import { useFeatureExtraction } from '../../contexts/FeatureExtractionContext'
|
3 |
|
4 |
const FeatureExtractionConfig = () => {
|
5 |
const { config, setConfig } = useFeatureExtraction()
|
|
|
17 |
</label>
|
18 |
<select
|
19 |
value={config.pooling}
|
20 |
+
onChange={(e) =>
|
21 |
+
setConfig((prev) => ({
|
22 |
+
...prev,
|
23 |
+
pooling: e.target.value as 'mean' | 'cls' | 'max'
|
24 |
+
}))
|
25 |
+
}
|
26 |
className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm"
|
27 |
>
|
28 |
<option value="mean">Mean Pooling</option>
|
|
|
39 |
<input
|
40 |
type="checkbox"
|
41 |
checked={config.normalize}
|
42 |
+
onChange={(e) =>
|
43 |
+
setConfig((prev) => ({
|
44 |
+
...prev,
|
45 |
+
normalize: e.target.checked
|
46 |
+
}))
|
47 |
+
}
|
48 |
className="rounded border-gray-300 text-blue-600 shadow-sm focus:border-blue-300 focus:ring focus:ring-blue-200 focus:ring-opacity-50"
|
49 |
/>
|
50 |
<span className="text-sm font-medium text-gray-700">
|
|
|
63 |
<strong>Mean Pooling:</strong> Average all token embeddings
|
64 |
</p>
|
65 |
<p className="mb-1">
|
66 |
+
<strong>CLS Token:</strong> Use the [CLS] token embedding (if
|
67 |
+
available)
|
68 |
</p>
|
69 |
<p>
|
70 |
+
<strong>Max Pooling:</strong> Take element-wise maximum across
|
71 |
+
tokens
|
72 |
</p>
|
73 |
</div>
|
74 |
</div>
|
src/components/{TextClassification.tsx → pipelines/TextClassification.tsx}
RENAMED
@@ -1,6 +1,6 @@
|
|
1 |
import { useState, useCallback, useEffect } from 'react'
|
2 |
-
import { TextClassificationWorkerInput, WorkerMessage } from '
|
3 |
-
import { useModel } from '
|
4 |
|
5 |
const PLACEHOLDER_TEXTS: string[] = [
|
6 |
'I absolutely love this product! It exceeded all my expectations.',
|
|
|
1 |
import { useState, useCallback, useEffect } from 'react'
|
2 |
+
import { TextClassificationWorkerInput, WorkerMessage } from '../../types'
|
3 |
+
import { useModel } from '../../contexts/ModelContext'
|
4 |
|
5 |
const PLACEHOLDER_TEXTS: string[] = [
|
6 |
'I absolutely love this product! It exceeded all my expectations.',
|
src/components/{TextGeneration.tsx → pipelines/TextGeneration.tsx}
RENAMED
@@ -1,8 +1,12 @@
|
|
1 |
import { useState, useRef, useEffect, useCallback } from 'react'
|
2 |
import { Send, Trash2, Loader2, X } from 'lucide-react'
|
3 |
-
import {
|
4 |
-
|
5 |
-
|
|
|
|
|
|
|
|
|
6 |
|
7 |
function TextGeneration() {
|
8 |
const { config, messages, setMessages } = useTextGeneration()
|
|
|
1 |
import { useState, useRef, useEffect, useCallback } from 'react'
|
2 |
import { Send, Trash2, Loader2, X } from 'lucide-react'
|
3 |
+
import {
|
4 |
+
ChatMessage,
|
5 |
+
TextGenerationWorkerInput,
|
6 |
+
WorkerMessage
|
7 |
+
} from '../../types'
|
8 |
+
import { useModel } from '../../contexts/ModelContext'
|
9 |
+
import { useTextGeneration } from '../../contexts/TextGenerationContext'
|
10 |
|
11 |
function TextGeneration() {
|
12 |
const { config, messages, setMessages } = useTextGeneration()
|
src/components/{TextGenerationConfig.tsx → pipelines/TextGenerationConfig.tsx}
RENAMED
@@ -2,8 +2,8 @@ import { Switch } from '@headlessui/react'
|
|
2 |
import {
|
3 |
useTextGeneration,
|
4 |
GenerationConfigState
|
5 |
-
} from '
|
6 |
-
import { useModel } from '
|
7 |
|
8 |
function TextGenerationConfig() {
|
9 |
const { config, setConfig, messages, updateSystemMessage } =
|
|
|
2 |
import {
|
3 |
useTextGeneration,
|
4 |
GenerationConfigState
|
5 |
+
} from '../../contexts/TextGenerationContext'
|
6 |
+
import { useModel } from '../../contexts/ModelContext'
|
7 |
|
8 |
function TextGenerationConfig() {
|
9 |
const { config, setConfig, messages, updateSystemMessage } =
|
src/components/{ZeroShotClassification.tsx → pipelines/ZeroShotClassification.tsx}
RENAMED
@@ -1,7 +1,7 @@
|
|
1 |
import { useEffect, useCallback } from 'react'
|
2 |
-
import { WorkerMessage, ZeroShotWorkerInput } from '
|
3 |
-
import { useModel } from '
|
4 |
-
import { useZeroShotClassification } from '
|
5 |
import { Send, Loader2 } from 'lucide-react'
|
6 |
|
7 |
function ZeroShotClassification() {
|
@@ -81,7 +81,7 @@ function ZeroShotClassification() {
|
|
81 |
const busy: boolean = status !== 'ready'
|
82 |
|
83 |
return (
|
84 |
-
<div className="flex flex-col h-
|
85 |
<div className="flex items-center justify-between mb-4">
|
86 |
<h1 className="text-2xl font-bold">Zero-Shot Classification</h1>
|
87 |
</div>
|
@@ -96,7 +96,7 @@ function ZeroShotClassification() {
|
|
96 |
onChange={(e) => setText(e.target.value)}
|
97 |
placeholder="Enter text items to classify, one per line..."
|
98 |
className="w-full p-3 border border-gray-300 rounded-lg resize-none focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-100 disabled:cursor-not-allowed"
|
99 |
-
rows={
|
100 |
disabled={!hasBeenLoaded || busy}
|
101 |
/>
|
102 |
</div>
|
@@ -126,11 +126,11 @@ function ZeroShotClassification() {
|
|
126 |
|
127 |
{/* Results Grid */}
|
128 |
<div className="flex-1 overflow-hidden">
|
129 |
-
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-
|
130 |
{sections.map((section, index) => (
|
131 |
<div
|
132 |
key={index}
|
133 |
-
className="flex flex-col bg-white border border-gray-200 rounded-lg
|
134 |
>
|
135 |
<div className="px-3 py-2 bg-gray-50 border-b border-gray-200">
|
136 |
<h3
|
|
|
1 |
import { useEffect, useCallback } from 'react'
|
2 |
+
import { WorkerMessage, ZeroShotWorkerInput } from '../../types'
|
3 |
+
import { useModel } from '../../contexts/ModelContext'
|
4 |
+
import { useZeroShotClassification } from '../../contexts/ZeroShotClassificationContext'
|
5 |
import { Send, Loader2 } from 'lucide-react'
|
6 |
|
7 |
function ZeroShotClassification() {
|
|
|
81 |
const busy: boolean = status !== 'ready'
|
82 |
|
83 |
return (
|
84 |
+
<div className="flex flex-col h-full max-h-[100vh] w-full p-4">
|
85 |
<div className="flex items-center justify-between mb-4">
|
86 |
<h1 className="text-2xl font-bold">Zero-Shot Classification</h1>
|
87 |
</div>
|
|
|
96 |
onChange={(e) => setText(e.target.value)}
|
97 |
placeholder="Enter text items to classify, one per line..."
|
98 |
className="w-full p-3 border border-gray-300 rounded-lg resize-none focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-100 disabled:cursor-not-allowed"
|
99 |
+
rows={12}
|
100 |
disabled={!hasBeenLoaded || busy}
|
101 |
/>
|
102 |
</div>
|
|
|
126 |
|
127 |
{/* Results Grid */}
|
128 |
<div className="flex-1 overflow-hidden">
|
129 |
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4 gap-4 h-full">
|
130 |
{sections.map((section, index) => (
|
131 |
<div
|
132 |
key={index}
|
133 |
+
className="flex flex-col bg-white border border-gray-200 rounded-lg max-h-96"
|
134 |
>
|
135 |
<div className="px-3 py-2 bg-gray-50 border-b border-gray-200">
|
136 |
<h3
|
src/components/{ZeroShotClassificationConfig.tsx → pipelines/ZeroShotClassificationConfig.tsx}
RENAMED
@@ -1,6 +1,6 @@
|
|
1 |
import React from 'react'
|
2 |
import { Plus, Minus, Trash2 } from 'lucide-react'
|
3 |
-
import { useZeroShotClassification } from '
|
4 |
|
5 |
const ZeroShotClassificationConfig = () => {
|
6 |
const {
|
@@ -27,22 +27,27 @@ const ZeroShotClassificationConfig = () => {
|
|
27 |
<input
|
28 |
type="range"
|
29 |
min="0.1"
|
30 |
-
max="0.
|
31 |
-
step="0.
|
32 |
value={config.threshold}
|
33 |
-
onChange={(e) =>
|
34 |
-
|
35 |
-
|
36 |
-
|
|
|
|
|
37 |
className="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"
|
38 |
/>
|
39 |
<p className="text-xs text-gray-500 mt-1">
|
40 |
-
Minimum confidence score required for classification (lower values
|
|
|
41 |
</p>
|
42 |
</div>
|
43 |
|
44 |
<div className="pt-2 border-t border-gray-200">
|
45 |
-
<h4 className="text-sm font-semibold text-gray-800 mb-3">
|
|
|
|
|
46 |
|
47 |
<div className="space-y-2 max-h-40 overflow-y-auto">
|
48 |
{sections.map((section, index) => (
|
@@ -94,13 +99,16 @@ const ZeroShotClassificationConfig = () => {
|
|
94 |
<div className="pt-2 border-t border-gray-200">
|
95 |
<div className="text-xs text-gray-500">
|
96 |
<p className="mb-1">
|
97 |
-
<strong>Threshold:</strong> Items with confidence scores below this
|
|
|
98 |
</p>
|
99 |
<p className="mb-1">
|
100 |
-
<strong>Categories:</strong> Edit category names to customize
|
|
|
101 |
</p>
|
102 |
<p>
|
103 |
-
<strong>Other:</strong> Fallback category for items that don't meet
|
|
|
104 |
</p>
|
105 |
</div>
|
106 |
</div>
|
|
|
1 |
import React from 'react'
|
2 |
import { Plus, Minus, Trash2 } from 'lucide-react'
|
3 |
+
import { useZeroShotClassification } from '../../contexts/ZeroShotClassificationContext'
|
4 |
|
5 |
const ZeroShotClassificationConfig = () => {
|
6 |
const {
|
|
|
27 |
<input
|
28 |
type="range"
|
29 |
min="0.1"
|
30 |
+
max="0.95"
|
31 |
+
step="0.01"
|
32 |
value={config.threshold}
|
33 |
+
onChange={(e) =>
|
34 |
+
setConfig((prev) => ({
|
35 |
+
...prev,
|
36 |
+
threshold: parseFloat(e.target.value)
|
37 |
+
}))
|
38 |
+
}
|
39 |
className="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"
|
40 |
/>
|
41 |
<p className="text-xs text-gray-500 mt-1">
|
42 |
+
Minimum confidence score required for classification (lower values
|
43 |
+
classify more items)
|
44 |
</p>
|
45 |
</div>
|
46 |
|
47 |
<div className="pt-2 border-t border-gray-200">
|
48 |
+
<h4 className="text-sm font-semibold text-gray-800 mb-3">
|
49 |
+
Categories
|
50 |
+
</h4>
|
51 |
|
52 |
<div className="space-y-2 max-h-40 overflow-y-auto">
|
53 |
{sections.map((section, index) => (
|
|
|
99 |
<div className="pt-2 border-t border-gray-200">
|
100 |
<div className="text-xs text-gray-500">
|
101 |
<p className="mb-1">
|
102 |
+
<strong>Threshold:</strong> Items with confidence scores below this
|
103 |
+
threshold will be classified as "Other"
|
104 |
</p>
|
105 |
<p className="mb-1">
|
106 |
+
<strong>Categories:</strong> Edit category names to customize
|
107 |
+
classification labels
|
108 |
</p>
|
109 |
<p>
|
110 |
+
<strong>Other:</strong> Fallback category for items that don't meet
|
111 |
+
the threshold for any specific category
|
112 |
</p>
|
113 |
</div>
|
114 |
</div>
|
src/lib/huggingface.ts
CHANGED
@@ -153,8 +153,13 @@ const getModelsByPipeline = async (
|
|
153 |
// }
|
154 |
|
155 |
// First search with filter=onnx
|
|
|
|
|
|
|
|
|
|
|
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: {
|
|
|
153 |
// }
|
154 |
|
155 |
// First search with filter=onnx
|
156 |
+
console.log(
|
157 |
+
pipelineTag === 'feature-extraction'
|
158 |
+
? '&search=sentence-transformers'
|
159 |
+
: '&filter=onnx'
|
160 |
+
)
|
161 |
const response1 = await fetch(
|
162 |
+
`https://huggingface.co/api/models?filter=${pipelineTag}${pipelineTag === 'feature-extraction' ? '&library=sentence-transformers' : '&filter=onnx'}&sort=downloads&limit=50`,
|
163 |
{
|
164 |
method: 'GET'
|
165 |
// headers: {
|