Update UI to use new theme tokens
Browse files- src/components/ModelInfo.tsx +23 -23
- src/components/pipelines/FeatureExtraction.tsx +3 -3
- src/components/pipelines/FeatureExtractionConfig.tsx +9 -9
- src/components/pipelines/ImageClassification.tsx +3 -3
- src/components/pipelines/ImageClassificationConfig.tsx +8 -8
- src/components/pipelines/TextClassification.tsx +1 -1
- src/components/pipelines/TextGeneration.tsx +3 -3
- src/components/pipelines/TextGenerationConfig.tsx +53 -66
- src/components/pipelines/ZeroShotClassification.tsx +1 -1
- src/components/pipelines/ZeroShotClassificationConfig.tsx +23 -23
src/components/ModelInfo.tsx
CHANGED
@@ -28,37 +28,37 @@ const ModelInfo = () => {
|
|
28 |
const { models, modelInfo, selectedQuantization, isFetching } = useModel()
|
29 |
|
30 |
const ModelInfoSkeleton = () => (
|
31 |
-
<div className="bg-
|
32 |
<div className="flex items-center space-x-2">
|
33 |
-
<Bot className="w-4 h-4 text-
|
34 |
-
<div className="h-4 bg-
|
35 |
-
<div className="w-4 h-4 bg-
|
36 |
</div>
|
37 |
|
38 |
<div className="flex items-center space-x-2 ml-6">
|
39 |
-
<div className="h-3 bg-
|
40 |
</div>
|
41 |
|
42 |
<div className="grid grid-cols-2 gap-2 text-xs">
|
43 |
<div className="flex items-center space-x-1">
|
44 |
-
<Heart className="w-3 h-3 text-
|
45 |
-
<div className="h-3 bg-
|
46 |
</div>
|
47 |
<div className="flex items-center space-x-1">
|
48 |
-
<Download className="w-3 h-3 text-
|
49 |
-
<div className="h-3 bg-
|
50 |
</div>
|
51 |
<div className="flex items-center space-x-1">
|
52 |
-
<Cpu className="w-3 h-3 text-
|
53 |
-
<div className="h-3 bg-
|
54 |
</div>
|
55 |
<div className="flex items-center space-x-1">
|
56 |
-
<DatabaseIcon className="w-3 h-3 text-
|
57 |
-
<div className="h-3 bg-
|
58 |
</div>
|
59 |
</div>
|
60 |
-
<hr className="border-
|
61 |
-
<div className="h-8 bg-
|
62 |
</div>
|
63 |
)
|
64 |
|
@@ -67,7 +67,7 @@ const ModelInfo = () => {
|
|
67 |
}
|
68 |
|
69 |
return (
|
70 |
-
<div className="relative bg-
|
71 |
{/* Model Name Row */}
|
72 |
<div className="flex justify-center items-center space-x-2">
|
73 |
{/* Compatibility Status */}
|
@@ -76,7 +76,7 @@ const ModelInfo = () => {
|
|
76 |
{modelInfo.isCompatible ? (
|
77 |
<CheckCircle className="w-4 h-4 text-green-500" />
|
78 |
) : (
|
79 |
-
<XCircle className="w-4 h-4 text-
|
80 |
)}
|
81 |
</div>
|
82 |
)}
|
@@ -85,7 +85,7 @@ const ModelInfo = () => {
|
|
85 |
href={`https://huggingface.co/${modelInfo.name}`}
|
86 |
target="_blank"
|
87 |
rel="noopener noreferrer"
|
88 |
-
className="text-sm font-medium text-
|
89 |
title={modelInfo.name}
|
90 |
>
|
91 |
<ExternalLink className="w-3 h-3 inline-block mr-1" />
|
@@ -97,7 +97,7 @@ const ModelInfo = () => {
|
|
97 |
href={`https://huggingface.co/${modelInfo.baseId}`}
|
98 |
target="_blank"
|
99 |
rel="noopener noreferrer"
|
100 |
-
className="text-xs text-
|
101 |
title={`Base model: ${modelInfo.baseId}`}
|
102 |
>
|
103 |
<ExternalLink className="w-3 h-3 inline-block mr-1" />(
|
@@ -108,10 +108,10 @@ const ModelInfo = () => {
|
|
108 |
</div>
|
109 |
|
110 |
{/* Stats Grid */}
|
111 |
-
<div className="grid grid-cols-2 gap-2 text-xs text-
|
112 |
{modelInfo.likes > 0 && (
|
113 |
<div className="flex items-center space-x-1">
|
114 |
-
<Heart className="w-3 h-3 text-
|
115 |
<span>{formatNumber(modelInfo.likes)}</span>
|
116 |
</div>
|
117 |
)}
|
@@ -157,8 +157,8 @@ const ModelInfo = () => {
|
|
157 |
|
158 |
{/* Incompatibility Message */}
|
159 |
{modelInfo.isCompatible === false && modelInfo.incompatibilityReason && (
|
160 |
-
<div className="bg-
|
161 |
-
<p className="text-xs text-
|
162 |
{modelInfo.incompatibilityReason}
|
163 |
</p>
|
164 |
</div>
|
|
|
28 |
const { models, modelInfo, selectedQuantization, isFetching } = useModel()
|
29 |
|
30 |
const ModelInfoSkeleton = () => (
|
31 |
+
<div className="bg-gradient-to-r from-secondary to-accent px-3 py-3 rounded-lg border border-border space-y-3 animate-pulse w-4/5">
|
32 |
<div className="flex items-center space-x-2">
|
33 |
+
<Bot className="w-4 h-4 text-primary/60" />
|
34 |
+
<div className="h-4 bg-muted rounded-sm flex-1"></div>
|
35 |
+
<div className="w-4 h-4 bg-muted rounded-full"></div>
|
36 |
</div>
|
37 |
|
38 |
<div className="flex items-center space-x-2 ml-6">
|
39 |
+
<div className="h-3 bg-muted/80 rounded-sm w-32"></div>
|
40 |
</div>
|
41 |
|
42 |
<div className="grid grid-cols-2 gap-2 text-xs">
|
43 |
<div className="flex items-center space-x-1">
|
44 |
+
<Heart className="w-3 h-3 text-destructive/60" />
|
45 |
+
<div className="h-3 bg-muted/80 rounded-sm w-8"></div>
|
46 |
</div>
|
47 |
<div className="flex items-center space-x-1">
|
48 |
+
<Download className="w-3 h-3 text-chart-2/60" />
|
49 |
+
<div className="h-3 bg-muted/80 rounded-sm w-8"></div>
|
50 |
</div>
|
51 |
<div className="flex items-center space-x-1">
|
52 |
+
<Cpu className="w-3 h-3 text-chart-4/60" />
|
53 |
+
<div className="h-3 bg-muted/80 rounded-sm w-8"></div>
|
54 |
</div>
|
55 |
<div className="flex items-center space-x-1">
|
56 |
+
<DatabaseIcon className="w-3 h-3 text-chart-4/60" />
|
57 |
+
<div className="h-3 bg-muted/80 rounded-sm w-12"></div>
|
58 |
</div>
|
59 |
</div>
|
60 |
+
<hr className="border-border" />
|
61 |
+
<div className="h-8 bg-muted/80 rounded-sm w-full"></div>
|
62 |
</div>
|
63 |
)
|
64 |
|
|
|
67 |
}
|
68 |
|
69 |
return (
|
70 |
+
<div className="relative bg-gradient-to-r from-secondary to-accent px-3 py-3 rounded-lg border border-border space-y-3 h-full w-4/5">
|
71 |
{/* Model Name Row */}
|
72 |
<div className="flex justify-center items-center space-x-2">
|
73 |
{/* Compatibility Status */}
|
|
|
76 |
{modelInfo.isCompatible ? (
|
77 |
<CheckCircle className="w-4 h-4 text-green-500" />
|
78 |
) : (
|
79 |
+
<XCircle className="w-4 h-4 text-destructive" />
|
80 |
)}
|
81 |
</div>
|
82 |
)}
|
|
|
85 |
href={`https://huggingface.co/${modelInfo.name}`}
|
86 |
target="_blank"
|
87 |
rel="noopener noreferrer"
|
88 |
+
className="text-sm font-medium text-foreground/80 hover:underline block truncate"
|
89 |
title={modelInfo.name}
|
90 |
>
|
91 |
<ExternalLink className="w-3 h-3 inline-block mr-1" />
|
|
|
97 |
href={`https://huggingface.co/${modelInfo.baseId}`}
|
98 |
target="_blank"
|
99 |
rel="noopener noreferrer"
|
100 |
+
className="text-xs text-muted-foreground hover:underline block truncate mt-1"
|
101 |
title={`Base model: ${modelInfo.baseId}`}
|
102 |
>
|
103 |
<ExternalLink className="w-3 h-3 inline-block mr-1" />(
|
|
|
108 |
</div>
|
109 |
|
110 |
{/* Stats Grid */}
|
111 |
+
<div className="grid grid-cols-2 gap-2 text-xs text-muted-foreground">
|
112 |
{modelInfo.likes > 0 && (
|
113 |
<div className="flex items-center space-x-1">
|
114 |
+
<Heart className="w-3 h-3 text-destructive" />
|
115 |
<span>{formatNumber(modelInfo.likes)}</span>
|
116 |
</div>
|
117 |
)}
|
|
|
157 |
|
158 |
{/* Incompatibility Message */}
|
159 |
{modelInfo.isCompatible === false && modelInfo.incompatibilityReason && (
|
160 |
+
<div className="bg-destructive/10 border border-destructive/20 rounded-md px-2 py-2">
|
161 |
+
<p className="text-xs text-destructive whitespace-break-spaces">
|
162 |
{modelInfo.incompatibilityReason}
|
163 |
</p>
|
164 |
</div>
|
src/components/pipelines/FeatureExtraction.tsx
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
import { useState, useRef, useEffect, useCallback } from 'react'
|
2 |
-
import { Plus,
|
3 |
import {
|
4 |
EmbeddingExample,
|
5 |
FeatureExtractionWorkerInput,
|
@@ -241,7 +241,7 @@ function FeatureExtraction() {
|
|
241 |
const busy = status !== 'ready' || isExtracting
|
242 |
|
243 |
return (
|
244 |
-
<div className="flex flex-col
|
245 |
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between mb-4 gap-2">
|
246 |
<h1 className="text-xl sm:text-2xl font-bold">
|
247 |
Feature Extraction (Embeddings)
|
@@ -273,7 +273,7 @@ function FeatureExtraction() {
|
|
273 |
className="p-2 bg-red-100 hover:bg-red-200 rounded-lg transition-colors"
|
274 |
title="Clear All Examples"
|
275 |
>
|
276 |
-
<
|
277 |
</button>
|
278 |
</div>
|
279 |
</div>
|
|
|
1 |
import { useState, useRef, useEffect, useCallback } from 'react'
|
2 |
+
import { Plus, Eraser, Loader2, X, Eye, EyeOff } from 'lucide-react'
|
3 |
import {
|
4 |
EmbeddingExample,
|
5 |
FeatureExtractionWorkerInput,
|
|
|
241 |
const busy = status !== 'ready' || isExtracting
|
242 |
|
243 |
return (
|
244 |
+
<div className="flex flex-col max-h-[calc(100dvh-148px)] w-full p-4">
|
245 |
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between mb-4 gap-2">
|
246 |
<h1 className="text-xl sm:text-2xl font-bold">
|
247 |
Feature Extraction (Embeddings)
|
|
|
273 |
className="p-2 bg-red-100 hover:bg-red-200 rounded-lg transition-colors"
|
274 |
title="Clear All Examples"
|
275 |
>
|
276 |
+
<Eraser className="w-4 h-4" />
|
277 |
</button>
|
278 |
</div>
|
279 |
</div>
|
src/components/pipelines/FeatureExtractionConfig.tsx
CHANGED
@@ -6,13 +6,13 @@ const FeatureExtractionConfig = () => {
|
|
6 |
|
7 |
return (
|
8 |
<div className="space-y-4">
|
9 |
-
<h3 className="text-lg font-semibold text-
|
10 |
Feature Extraction Settings
|
11 |
</h3>
|
12 |
|
13 |
<div className="space-y-3">
|
14 |
<div>
|
15 |
-
<label className="block text-sm font-medium text-
|
16 |
Pooling Strategy
|
17 |
</label>
|
18 |
<select
|
@@ -23,13 +23,13 @@ const FeatureExtractionConfig = () => {
|
|
23 |
pooling: e.target.value as 'mean' | 'cls' | 'max'
|
24 |
}))
|
25 |
}
|
26 |
-
className="w-full px-3 py-2 border border-
|
27 |
>
|
28 |
<option value="mean">Mean Pooling</option>
|
29 |
<option value="cls">CLS Token</option>
|
30 |
<option value="max">Max Pooling</option>
|
31 |
</select>
|
32 |
-
<p className="text-xs text-
|
33 |
How to aggregate token embeddings into sentence embeddings
|
34 |
</p>
|
35 |
</div>
|
@@ -45,20 +45,20 @@ const FeatureExtractionConfig = () => {
|
|
45 |
normalize: e.target.checked
|
46 |
}))
|
47 |
}
|
48 |
-
className="rounded border-
|
49 |
/>
|
50 |
-
<span className="text-sm font-medium text-
|
51 |
Normalize Embeddings
|
52 |
</span>
|
53 |
</label>
|
54 |
-
<p className="text-xs text-
|
55 |
L2 normalize embeddings for better similarity calculations
|
56 |
</p>
|
57 |
</div>
|
58 |
</div>
|
59 |
|
60 |
-
<div className="pt-2 border-t border-
|
61 |
-
<div className="text-xs text-
|
62 |
<p className="mb-1">
|
63 |
<strong>Mean Pooling:</strong> Average all token embeddings
|
64 |
</p>
|
|
|
6 |
|
7 |
return (
|
8 |
<div className="space-y-4">
|
9 |
+
<h3 className="text-lg font-semibold text-foreground">
|
10 |
Feature Extraction Settings
|
11 |
</h3>
|
12 |
|
13 |
<div className="space-y-3">
|
14 |
<div>
|
15 |
+
<label className="block text-sm font-medium text-foreground/80 mb-1">
|
16 |
Pooling Strategy
|
17 |
</label>
|
18 |
<select
|
|
|
23 |
pooling: e.target.value as 'mean' | 'cls' | 'max'
|
24 |
}))
|
25 |
}
|
26 |
+
className="w-full px-3 py-2 border border-input rounded-md shadow-xs focus:outline-hidden focus:ring-2 focus:ring-ring focus:border-ring text-sm"
|
27 |
>
|
28 |
<option value="mean">Mean Pooling</option>
|
29 |
<option value="cls">CLS Token</option>
|
30 |
<option value="max">Max Pooling</option>
|
31 |
</select>
|
32 |
+
<p className="text-xs text-muted-foreground mt-1">
|
33 |
How to aggregate token embeddings into sentence embeddings
|
34 |
</p>
|
35 |
</div>
|
|
|
45 |
normalize: e.target.checked
|
46 |
}))
|
47 |
}
|
48 |
+
className="rounded border-input text-primary shadow-xs focus:border-ring focus:ring-3 focus:ring-ring/20"
|
49 |
/>
|
50 |
+
<span className="text-sm font-medium text-foreground/80">
|
51 |
Normalize Embeddings
|
52 |
</span>
|
53 |
</label>
|
54 |
+
<p className="text-xs text-muted-foreground mt-1 ml-6">
|
55 |
L2 normalize embeddings for better similarity calculations
|
56 |
</p>
|
57 |
</div>
|
58 |
</div>
|
59 |
|
60 |
+
<div className="pt-2 border-t border-border">
|
61 |
+
<div className="text-xs text-muted-foreground">
|
62 |
<p className="mb-1">
|
63 |
<strong>Mean Pooling:</strong> Average all token embeddings
|
64 |
</p>
|
src/components/pipelines/ImageClassification.tsx
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
import { useState, useRef, useCallback, useEffect } from 'react'
|
2 |
import {
|
3 |
Upload,
|
4 |
-
|
5 |
Loader2,
|
6 |
X,
|
7 |
Eye,
|
@@ -185,7 +185,7 @@ function ImageClassification() {
|
|
185 |
const busy = status !== 'ready' || isClassifying
|
186 |
|
187 |
return (
|
188 |
-
<div className="flex flex-col h-full max-h-[
|
189 |
<div className="flex items-center justify-between mb-4">
|
190 |
<h1 className="text-2xl font-bold">Image Classification</h1>
|
191 |
<div className="flex gap-2">
|
@@ -213,7 +213,7 @@ function ImageClassification() {
|
|
213 |
className="p-2 bg-red-100 hover:bg-red-200 rounded-lg transition-colors"
|
214 |
title="Clear All Images"
|
215 |
>
|
216 |
-
<
|
217 |
</button>
|
218 |
</div>
|
219 |
</div>
|
|
|
1 |
import { useState, useRef, useCallback, useEffect } from 'react'
|
2 |
import {
|
3 |
Upload,
|
4 |
+
Eraser,
|
5 |
Loader2,
|
6 |
X,
|
7 |
Eye,
|
|
|
185 |
const busy = status !== 'ready' || isClassifying
|
186 |
|
187 |
return (
|
188 |
+
<div className="flex flex-col h-full max-h-[calc(100dvh-148px)] w-full p-4">
|
189 |
<div className="flex items-center justify-between mb-4">
|
190 |
<h1 className="text-2xl font-bold">Image Classification</h1>
|
191 |
<div className="flex gap-2">
|
|
|
213 |
className="p-2 bg-red-100 hover:bg-red-200 rounded-lg transition-colors"
|
214 |
title="Clear All Images"
|
215 |
>
|
216 |
+
<Eraser className="w-4 h-4" />
|
217 |
</button>
|
218 |
</div>
|
219 |
</div>
|
src/components/pipelines/ImageClassificationConfig.tsx
CHANGED
@@ -6,13 +6,13 @@ const ImageClassificationConfig = () => {
|
|
6 |
|
7 |
return (
|
8 |
<div className="space-y-4">
|
9 |
-
<h3 className="text-lg font-semibold text-
|
10 |
Image Classification Settings
|
11 |
</h3>
|
12 |
|
13 |
<div className="space-y-3">
|
14 |
<div>
|
15 |
-
<label className="block text-sm font-medium text-
|
16 |
Top K Predictions: {topK}
|
17 |
</label>
|
18 |
<input
|
@@ -22,21 +22,21 @@ const ImageClassificationConfig = () => {
|
|
22 |
step="1"
|
23 |
value={topK}
|
24 |
onChange={(e) => setTopK(parseInt(e.target.value))}
|
25 |
-
className="w-full h-2 bg-
|
26 |
/>
|
27 |
-
<div className="flex justify-between text-xs text-
|
28 |
<span>1</span>
|
29 |
<span>5</span>
|
30 |
<span>10</span>
|
31 |
</div>
|
32 |
-
<p className="text-xs text-
|
33 |
Number of top predictions to return for each image
|
34 |
</p>
|
35 |
</div>
|
36 |
|
37 |
-
<div className="p-3 bg-
|
38 |
-
<h4 className="text-sm font-medium text-
|
39 |
-
<div className="text-xs text-
|
40 |
<p>• Use Top K = 3-5 for most cases</p>
|
41 |
<p>• Smaller images process faster</p>
|
42 |
<p>• Try quantized models for speed</p>
|
|
|
6 |
|
7 |
return (
|
8 |
<div className="space-y-4">
|
9 |
+
<h3 className="text-lg font-semibold text-foreground">
|
10 |
Image Classification Settings
|
11 |
</h3>
|
12 |
|
13 |
<div className="space-y-3">
|
14 |
<div>
|
15 |
+
<label className="block text-sm font-medium text-foreground/80 mb-1">
|
16 |
Top K Predictions: {topK}
|
17 |
</label>
|
18 |
<input
|
|
|
22 |
step="1"
|
23 |
value={topK}
|
24 |
onChange={(e) => setTopK(parseInt(e.target.value))}
|
25 |
+
className="w-full h-2 bg-muted rounded-lg appearance-none cursor-pointer"
|
26 |
/>
|
27 |
+
<div className="flex justify-between text-xs text-muted-foreground/60 mt-1">
|
28 |
<span>1</span>
|
29 |
<span>5</span>
|
30 |
<span>10</span>
|
31 |
</div>
|
32 |
+
<p className="text-xs text-muted-foreground mt-1">
|
33 |
Number of top predictions to return for each image
|
34 |
</p>
|
35 |
</div>
|
36 |
|
37 |
+
<div className="p-3 bg-chart-4/10 border border-chart-4/20 rounded-lg">
|
38 |
+
<h4 className="text-sm font-medium text-chart-4 mb-2">💡 Tips</h4>
|
39 |
+
<div className="text-xs text-chart-4/80 space-y-1">
|
40 |
<p>• Use Top K = 3-5 for most cases</p>
|
41 |
<p>• Smaller images process faster</p>
|
42 |
<p>• Try quantized models for speed</p>
|
src/components/pipelines/TextClassification.tsx
CHANGED
@@ -80,7 +80,7 @@ function TextClassification() {
|
|
80 |
}
|
81 |
|
82 |
return (
|
83 |
-
<div className="flex flex-col h-full max-h-[
|
84 |
<h1 className="text-2xl font-bold mb-4 shrink-0">Text Classification</h1>
|
85 |
|
86 |
<div className="flex flex-col lg:flex-row gap-4 flex-1 min-h-0">
|
|
|
80 |
}
|
81 |
|
82 |
return (
|
83 |
+
<div className="flex flex-col h-full max-h-[calc(100dvh-148px)] w-full p-4">
|
84 |
<h1 className="text-2xl font-bold mb-4 shrink-0">Text Classification</h1>
|
85 |
|
86 |
<div className="flex flex-col lg:flex-row gap-4 flex-1 min-h-0">
|
src/components/pipelines/TextGeneration.tsx
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
import { useState, useRef, useEffect, useCallback } from 'react'
|
2 |
-
import { Send,
|
3 |
import {
|
4 |
ChatMessage,
|
5 |
TextGenerationWorkerInput,
|
@@ -153,7 +153,7 @@ function TextGeneration() {
|
|
153 |
const hasChatTemplate = modelInfo?.hasChatTemplate
|
154 |
|
155 |
return (
|
156 |
-
<div className="flex flex-col min-h-[
|
157 |
<div className="flex items-center justify-between mb-4">
|
158 |
<h1 className="text-2xl font-bold">
|
159 |
Text Generation {hasChatTemplate ? '(Chat)' : ''}
|
@@ -164,7 +164,7 @@ function TextGeneration() {
|
|
164 |
className="p-2 bg-red-100 hover:bg-red-200 rounded-lg transition-colors"
|
165 |
title={hasChatTemplate ? 'Clear Chat' : 'Clear Text'}
|
166 |
>
|
167 |
-
<
|
168 |
</button>
|
169 |
{isGenerating && (
|
170 |
<button
|
|
|
1 |
import { useState, useRef, useEffect, useCallback } from 'react'
|
2 |
+
import { Send, Eraser, Loader2, X } from 'lucide-react'
|
3 |
import {
|
4 |
ChatMessage,
|
5 |
TextGenerationWorkerInput,
|
|
|
153 |
const hasChatTemplate = modelInfo?.hasChatTemplate
|
154 |
|
155 |
return (
|
156 |
+
<div className="flex flex-col min-h-[30dvh] max-h-[calc(100dvh-148px)] w-full p-4">
|
157 |
<div className="flex items-center justify-between mb-4">
|
158 |
<h1 className="text-2xl font-bold">
|
159 |
Text Generation {hasChatTemplate ? '(Chat)' : ''}
|
|
|
164 |
className="p-2 bg-red-100 hover:bg-red-200 rounded-lg transition-colors"
|
165 |
title={hasChatTemplate ? 'Clear Chat' : 'Clear Text'}
|
166 |
>
|
167 |
+
<Eraser className="w-4 h-4" />
|
168 |
</button>
|
169 |
{isGenerating && (
|
170 |
<button
|
src/components/pipelines/TextGenerationConfig.tsx
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
-
import { Switch } from '
|
|
|
2 |
import {
|
3 |
useTextGeneration,
|
4 |
GenerationConfigState
|
@@ -19,89 +20,80 @@ function TextGenerationConfig() {
|
|
19 |
|
20 |
return (
|
21 |
<div className="space-y-4">
|
22 |
-
<h3 className="text-lg font-semibold text-
|
23 |
Text Generation Settings
|
24 |
</h3>
|
25 |
|
26 |
<div className="space-y-3">
|
27 |
<div>
|
28 |
-
<label className="block text-sm font-medium text-
|
29 |
Temperature: {config.temperature}
|
30 |
</label>
|
31 |
-
<
|
32 |
-
|
33 |
-
min=
|
34 |
-
max=
|
35 |
-
step=
|
36 |
-
|
37 |
-
|
38 |
-
handleConfigChange('temperature', parseFloat(e.target.value))
|
39 |
}
|
40 |
-
className="w-full
|
41 |
/>
|
42 |
-
|
|
|
43 |
Controls randomness in generation (lower = more focused, higher =
|
44 |
more creative)
|
45 |
</p>
|
46 |
</div>
|
47 |
|
48 |
<div>
|
49 |
-
<label className="block text-sm font-medium text-
|
50 |
Max Tokens: {config.maxTokens}
|
51 |
</label>
|
52 |
-
<
|
53 |
-
|
54 |
-
min=
|
55 |
-
max=
|
56 |
-
step=
|
57 |
-
|
58 |
-
|
59 |
-
handleConfigChange('maxTokens', parseInt(e.target.value))
|
60 |
-
}
|
61 |
-
className="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"
|
62 |
/>
|
63 |
-
<p className="text-xs text-
|
64 |
Maximum number of tokens to generate in the response
|
65 |
</p>
|
66 |
</div>
|
67 |
|
68 |
<div>
|
69 |
-
<label className="block text-sm font-medium text-
|
70 |
Top-p: {config.topP}
|
71 |
</label>
|
72 |
-
<
|
73 |
-
|
74 |
-
min=
|
75 |
-
max=
|
76 |
-
step=
|
77 |
-
|
78 |
-
|
79 |
-
handleConfigChange('topP', parseFloat(e.target.value))
|
80 |
-
}
|
81 |
-
className="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"
|
82 |
/>
|
83 |
-
<p className="text-xs text-
|
84 |
Nucleus sampling - considers tokens with cumulative probability up
|
85 |
to this value
|
86 |
</p>
|
87 |
</div>
|
88 |
|
89 |
<div>
|
90 |
-
<label className="block text-sm font-medium text-
|
91 |
Top-k: {config.topK}
|
92 |
</label>
|
93 |
-
<
|
94 |
-
|
95 |
-
min=
|
96 |
-
max=
|
97 |
-
step=
|
98 |
-
|
99 |
-
|
100 |
-
handleConfigChange('topK', parseInt(e.target.value))
|
101 |
-
}
|
102 |
-
className="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"
|
103 |
/>
|
104 |
-
<p className="text-xs text-
|
105 |
Only consider the top K most likely tokens at each step
|
106 |
</p>
|
107 |
</div>
|
@@ -109,37 +101,32 @@ function TextGenerationConfig() {
|
|
109 |
<div className="flex items-center">
|
110 |
<Switch
|
111 |
checked={config.doSample}
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
className={`${config.doSample ? 'translate-x-6' : 'translate-x-1'}
|
118 |
-
inline-block h-4 w-4 transform rounded-full bg-white transition`}
|
119 |
-
/>
|
120 |
-
</Switch>
|
121 |
-
<label className="ml-3 text-sm font-medium text-gray-700">
|
122 |
Do Sample
|
123 |
</label>
|
124 |
</div>
|
125 |
-
<p className="text-xs text-
|
126 |
Enable sampling-based generation (disable for deterministic output)
|
127 |
</p>
|
128 |
|
129 |
{/* System Message for Chat */}
|
130 |
{modelInfo?.hasChatTemplate && (
|
131 |
-
<div className="pt-2 border-t border-
|
132 |
-
<h4 className="text-sm font-semibold text-
|
133 |
System Message
|
134 |
</h4>
|
135 |
<textarea
|
136 |
value={messages.find((m) => m.role === 'system')?.content || ''}
|
137 |
onChange={(e) => updateSystemMessage(e.target.value)}
|
138 |
-
className="w-full p-2 border border-
|
139 |
rows={4}
|
140 |
placeholder="e.g., You are a helpful assistant."
|
141 |
/>
|
142 |
-
<p className="text-xs text-
|
143 |
Initial instructions that guide the model's behavior throughout
|
144 |
the conversation
|
145 |
</p>
|
@@ -147,8 +134,8 @@ function TextGenerationConfig() {
|
|
147 |
)}
|
148 |
</div>
|
149 |
|
150 |
-
<div className="pt-2 border-t border-
|
151 |
-
<div className="text-xs text-
|
152 |
<p className="mb-1">
|
153 |
<strong>Temperature:</strong> Higher values make output more random,
|
154 |
lower values more focused
|
|
|
1 |
+
import { Switch } from '@/components/ui/switch'
|
2 |
+
import { Slider } from '@/components/ui/slider'
|
3 |
import {
|
4 |
useTextGeneration,
|
5 |
GenerationConfigState
|
|
|
20 |
|
21 |
return (
|
22 |
<div className="space-y-4">
|
23 |
+
<h3 className="text-lg font-semibold text-foreground">
|
24 |
Text Generation Settings
|
25 |
</h3>
|
26 |
|
27 |
<div className="space-y-3">
|
28 |
<div>
|
29 |
+
<label className="block text-sm font-medium text-foreground/80 mb-1">
|
30 |
Temperature: {config.temperature}
|
31 |
</label>
|
32 |
+
<Slider
|
33 |
+
defaultValue={[config.temperature]}
|
34 |
+
min={0.1}
|
35 |
+
max={2}
|
36 |
+
step={0.1}
|
37 |
+
onValueChange={(value) =>
|
38 |
+
handleConfigChange('temperature', value[0])
|
|
|
39 |
}
|
40 |
+
className="w-full rounded-lg"
|
41 |
/>
|
42 |
+
|
43 |
+
<p className="text-xs text-muted-foreground mt-1">
|
44 |
Controls randomness in generation (lower = more focused, higher =
|
45 |
more creative)
|
46 |
</p>
|
47 |
</div>
|
48 |
|
49 |
<div>
|
50 |
+
<label className="block text-sm font-medium text-foreground/80 mb-1">
|
51 |
Max Tokens: {config.maxTokens}
|
52 |
</label>
|
53 |
+
<Slider
|
54 |
+
defaultValue={[config.maxTokens]}
|
55 |
+
min={10}
|
56 |
+
max={500}
|
57 |
+
step={10}
|
58 |
+
onValueChange={(value) => handleConfigChange('maxTokens', value[0])}
|
59 |
+
className="w-full rounded-lg"
|
|
|
|
|
|
|
60 |
/>
|
61 |
+
<p className="text-xs text-muted-foreground mt-1">
|
62 |
Maximum number of tokens to generate in the response
|
63 |
</p>
|
64 |
</div>
|
65 |
|
66 |
<div>
|
67 |
+
<label className="block text-sm font-medium text-foreground/80 mb-1">
|
68 |
Top-p: {config.topP}
|
69 |
</label>
|
70 |
+
<Slider
|
71 |
+
defaultValue={[config.maxTokens]}
|
72 |
+
min={0.1}
|
73 |
+
max={1}
|
74 |
+
step={0.1}
|
75 |
+
onValueChange={(value) => handleConfigChange('topP', value[0])}
|
76 |
+
className="w-full rounded-lg"
|
|
|
|
|
|
|
77 |
/>
|
78 |
+
<p className="text-xs text-muted-foreground mt-1">
|
79 |
Nucleus sampling - considers tokens with cumulative probability up
|
80 |
to this value
|
81 |
</p>
|
82 |
</div>
|
83 |
|
84 |
<div>
|
85 |
+
<label className="block text-sm font-medium text-foreground/80 mb-1">
|
86 |
Top-k: {config.topK}
|
87 |
</label>
|
88 |
+
<Slider
|
89 |
+
defaultValue={[config.topK]}
|
90 |
+
min={1}
|
91 |
+
max={100}
|
92 |
+
step={1}
|
93 |
+
onValueChange={(value) => handleConfigChange('topK', value[0])}
|
94 |
+
className="w-full rounded-lg"
|
|
|
|
|
|
|
95 |
/>
|
96 |
+
<p className="text-xs text-muted-foreground mt-1">
|
97 |
Only consider the top K most likely tokens at each step
|
98 |
</p>
|
99 |
</div>
|
|
|
101 |
<div className="flex items-center">
|
102 |
<Switch
|
103 |
checked={config.doSample}
|
104 |
+
onCheckedChange={(checked) =>
|
105 |
+
handleConfigChange('doSample', checked)
|
106 |
+
}
|
107 |
+
/>
|
108 |
+
<label className="ml-3 text-sm font-medium text-foreground/80">
|
|
|
|
|
|
|
|
|
|
|
109 |
Do Sample
|
110 |
</label>
|
111 |
</div>
|
112 |
+
<p className="text-xs text-muted-foreground mt-1">
|
113 |
Enable sampling-based generation (disable for deterministic output)
|
114 |
</p>
|
115 |
|
116 |
{/* System Message for Chat */}
|
117 |
{modelInfo?.hasChatTemplate && (
|
118 |
+
<div className="pt-2 border-t border-border">
|
119 |
+
<h4 className="text-sm font-semibold text-foreground mb-2">
|
120 |
System Message
|
121 |
</h4>
|
122 |
<textarea
|
123 |
value={messages.find((m) => m.role === 'system')?.content || ''}
|
124 |
onChange={(e) => updateSystemMessage(e.target.value)}
|
125 |
+
className="w-full p-2 border border-input rounded-md text-sm focus:outline-hidden focus:ring-1 focus:ring-ring focus:border-ring"
|
126 |
rows={4}
|
127 |
placeholder="e.g., You are a helpful assistant."
|
128 |
/>
|
129 |
+
<p className="text-xs text-muted-foreground mt-1">
|
130 |
Initial instructions that guide the model's behavior throughout
|
131 |
the conversation
|
132 |
</p>
|
|
|
134 |
)}
|
135 |
</div>
|
136 |
|
137 |
+
<div className="pt-2 border-t border-border">
|
138 |
+
<div className="text-xs text-muted-foreground">
|
139 |
<p className="mb-1">
|
140 |
<strong>Temperature:</strong> Higher values make output more random,
|
141 |
lower values more focused
|
src/components/pipelines/ZeroShotClassification.tsx
CHANGED
@@ -81,7 +81,7 @@ function ZeroShotClassification() {
|
|
81 |
const busy: boolean = status !== 'ready'
|
82 |
|
83 |
return (
|
84 |
-
<div className="flex flex-col h-full max-h-[
|
85 |
<div className="flex items-center justify-between mb-4">
|
86 |
<h1 className="text-2xl font-bold">Zero-Shot Classification</h1>
|
87 |
</div>
|
|
|
81 |
const busy: boolean = status !== 'ready'
|
82 |
|
83 |
return (
|
84 |
+
<div className="flex flex-col h-full max-h-[calc(100dvh-148px)] 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>
|
src/components/pipelines/ZeroShotClassificationConfig.tsx
CHANGED
@@ -1,6 +1,7 @@
|
|
1 |
import React from 'react'
|
2 |
-
import { Plus, Minus,
|
3 |
import { useZeroShotClassification } from '../../contexts/ZeroShotClassificationContext'
|
|
|
4 |
|
5 |
const ZeroShotClassificationConfig = () => {
|
6 |
const {
|
@@ -15,37 +16,36 @@ const ZeroShotClassificationConfig = () => {
|
|
15 |
|
16 |
return (
|
17 |
<div className="space-y-4">
|
18 |
-
<h3 className="text-lg font-semibold text-
|
19 |
Zero-Shot Classification Settings
|
20 |
</h3>
|
21 |
|
22 |
<div className="space-y-3">
|
23 |
<div>
|
24 |
-
<label className="block text-sm font-medium text-
|
25 |
Classification Threshold: {config.threshold}
|
26 |
</label>
|
27 |
-
<
|
28 |
-
|
29 |
-
min=
|
30 |
-
max=
|
31 |
-
step=
|
32 |
-
|
33 |
-
onChange={(e) =>
|
34 |
setConfig((prev) => ({
|
35 |
...prev,
|
36 |
-
threshold:
|
37 |
}))
|
38 |
}
|
39 |
-
className="w-full
|
40 |
/>
|
41 |
-
<p className="text-xs text-
|
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-
|
48 |
-
<h4 className="text-sm font-semibold text-
|
49 |
Categories
|
50 |
</h4>
|
51 |
|
@@ -57,9 +57,9 @@ const ZeroShotClassificationConfig = () => {
|
|
57 |
value={section.title}
|
58 |
onChange={(e) => updateSectionTitle(index, e.target.value)}
|
59 |
disabled={section.title === 'Other'}
|
60 |
-
className="flex-1 px-2 py-1 text-xs border border-
|
61 |
/>
|
62 |
-
<span className="text-xs text-
|
63 |
({section.items.length})
|
64 |
</span>
|
65 |
</div>
|
@@ -69,7 +69,7 @@ const ZeroShotClassificationConfig = () => {
|
|
69 |
<div className="flex gap-2 mt-3">
|
70 |
<button
|
71 |
onClick={addCategory}
|
72 |
-
className="flex items-center gap-1 px-3 py-1 text-xs bg-
|
73 |
title="Add Category"
|
74 |
>
|
75 |
<Plus className="w-3 h-3" />
|
@@ -78,7 +78,7 @@ const ZeroShotClassificationConfig = () => {
|
|
78 |
<button
|
79 |
onClick={removeCategory}
|
80 |
disabled={sections.length <= 1}
|
81 |
-
className="flex items-center gap-1 px-3 py-1 text-xs bg-
|
82 |
title="Remove Category"
|
83 |
>
|
84 |
<Minus className="w-3 h-3" />
|
@@ -86,18 +86,18 @@ const ZeroShotClassificationConfig = () => {
|
|
86 |
</button>
|
87 |
<button
|
88 |
onClick={clearResults}
|
89 |
-
className="flex items-center gap-1 px-3 py-1 text-xs bg-
|
90 |
title="Clear Results"
|
91 |
>
|
92 |
-
<
|
93 |
Clear
|
94 |
</button>
|
95 |
</div>
|
96 |
</div>
|
97 |
</div>
|
98 |
|
99 |
-
<div className="pt-2 border-t border-
|
100 |
-
<div className="text-xs text-
|
101 |
<p className="mb-1">
|
102 |
<strong>Threshold:</strong> Items with confidence scores below this
|
103 |
threshold will be classified as "Other"
|
|
|
1 |
import React from 'react'
|
2 |
+
import { Plus, Minus, Eraser } from 'lucide-react'
|
3 |
import { useZeroShotClassification } from '../../contexts/ZeroShotClassificationContext'
|
4 |
+
import { Slider } from '@/components/ui/slider'
|
5 |
|
6 |
const ZeroShotClassificationConfig = () => {
|
7 |
const {
|
|
|
16 |
|
17 |
return (
|
18 |
<div className="space-y-4">
|
19 |
+
<h3 className="text-lg font-semibold text-foreground">
|
20 |
Zero-Shot Classification Settings
|
21 |
</h3>
|
22 |
|
23 |
<div className="space-y-3">
|
24 |
<div>
|
25 |
+
<label className="block text-sm font-medium text-foreground/80 mb-1">
|
26 |
Classification Threshold: {config.threshold}
|
27 |
</label>
|
28 |
+
<Slider
|
29 |
+
defaultValue={[config.threshold]}
|
30 |
+
min={0.1}
|
31 |
+
max={0.95}
|
32 |
+
step={0.01}
|
33 |
+
onValueChange={(value) =>
|
|
|
34 |
setConfig((prev) => ({
|
35 |
...prev,
|
36 |
+
threshold: value[0]
|
37 |
}))
|
38 |
}
|
39 |
+
className="w-full rounded-lg"
|
40 |
/>
|
41 |
+
<p className="text-xs text-muted-foreground 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-border">
|
48 |
+
<h4 className="text-sm font-semibold text-foreground mb-3">
|
49 |
Categories
|
50 |
</h4>
|
51 |
|
|
|
57 |
value={section.title}
|
58 |
onChange={(e) => updateSectionTitle(index, e.target.value)}
|
59 |
disabled={section.title === 'Other'}
|
60 |
+
className="flex-1 px-2 py-1 text-xs border border-input rounded-sm focus:outline-hidden focus:ring-1 focus:ring-ring focus:border-ring disabled:bg-muted disabled:cursor-not-allowed"
|
61 |
/>
|
62 |
+
<span className="text-xs text-muted-foreground min-w-8">
|
63 |
({section.items.length})
|
64 |
</span>
|
65 |
</div>
|
|
|
69 |
<div className="flex gap-2 mt-3">
|
70 |
<button
|
71 |
onClick={addCategory}
|
72 |
+
className="cursor-pointer flex items-center gap-1 px-3 py-1 text-xs bg-chart-2 hover:bg-chart-2/80 text-white rounded-sm transition-colors"
|
73 |
title="Add Category"
|
74 |
>
|
75 |
<Plus className="w-3 h-3" />
|
|
|
78 |
<button
|
79 |
onClick={removeCategory}
|
80 |
disabled={sections.length <= 1}
|
81 |
+
className="cursor-pointer flex items-center gap-1 px-3 py-1 text-xs bg-destructive hover:bg-destructive/80 disabled:bg-muted disabled:cursor-not-allowed text-white rounded-sm transition-colors"
|
82 |
title="Remove Category"
|
83 |
>
|
84 |
<Minus className="w-3 h-3" />
|
|
|
86 |
</button>
|
87 |
<button
|
88 |
onClick={clearResults}
|
89 |
+
className="cursor-pointer flex items-center gap-1 px-3 py-1 text-xs bg-chart-5 hover:bg-chart-5 text-white rounded-sm transition-colors"
|
90 |
title="Clear Results"
|
91 |
>
|
92 |
+
<Eraser className="w-3 h-3" />
|
93 |
Clear
|
94 |
</button>
|
95 |
</div>
|
96 |
</div>
|
97 |
</div>
|
98 |
|
99 |
+
<div className="pt-2 border-t border-border">
|
100 |
+
<div className="text-xs text-muted-foreground">
|
101 |
<p className="mb-1">
|
102 |
<strong>Threshold:</strong> Items with confidence scores below this
|
103 |
threshold will be classified as "Other"
|