Spaces:
Running
Running
File size: 6,471 Bytes
44072a9 abd8f45 98847a8 b087e88 503a577 44072a9 98847a8 ed37070 503a577 ed37070 503a577 ed37070 98847a8 ed37070 98847a8 44072a9 98847a8 abd8f45 9eea4a2 abd8f45 9eea4a2 abd8f45 9eea4a2 abd8f45 98847a8 ed37070 abd8f45 ed37070 abd8f45 ed37070 abd8f45 ed37070 abd8f45 ed37070 98847a8 503a577 98847a8 44072a9 ed37070 98847a8 ed37070 98847a8 44072a9 98847a8 ed37070 98847a8 503a577 98847a8 |
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 |
import React, { useState, useEffect, useRef } from 'react'
import { useLocation, useNavigate } from 'react-router-dom'
import API from '../API'
import LoadingSpinner from './LoadingSpinner'
import ImageGallery from './ImageGallery'
import AudioGallery from './AudioGallery'
import VideoGallery from './VideoGallery'
import ModelInfoIcon from './ModelInfoIcon'
import Descriptions from '../Descriptions'
interface ExamplesProps {
fileType: 'image' | 'audio' | 'video'
}
// Move ExamplesData type export to allow import in Galleries.tsx
export type ExamplesData = {
image_url: string
audio_url?: string
video_url?: string
name: string
metadata: {
[key: string]: string | boolean
}
}
const Examples = ({ fileType }: ExamplesProps) => {
const [examples, setExamples] = useState<{
[model: string]: { [attack: string]: ExamplesData[] }
}>({})
const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
const [selectedModel, setSelectedModel] = useState<string | null>(null)
const [selectedAttack, setSelectedAttack] = useState<string | null>(null)
const [descriptionsLoaded, setDescriptionsLoaded] = useState(false)
const descriptions = useRef(Descriptions.getInstance())
useEffect(() => {
descriptions.current.load().then(() => setDescriptionsLoaded(true))
}, [])
const location = useLocation()
// Parse query params for model and attack
useEffect(() => {
const params = new URLSearchParams(location.search)
const modelParam = params.get('model')
const attackParam = params.get('attack')
const strengthParam = params.get('strength')
if (modelParam) setSelectedModel(modelParam)
// Find the most appropriate selectedAttack
if (attackParam || strengthParam) {
setSelectedAttack((prev) => {
if (!selectedModel || !examples[selectedModel]) return prev
const attacks = Object.keys(examples[selectedModel])
// If both attack and strength are present, look for attack containing attackParam and ending with strengthParam
if (attackParam && strengthParam) {
const found = attacks.find((a) => a.includes(attackParam) && a.endsWith(strengthParam))
if (found) return found
}
// If only attack is present, look for attack containing attackParam
if (attackParam) {
const found = attacks.find((a) => a.includes(attackParam))
if (found) return found
}
// If only strength is present, look for attack ending with strengthParam
if (strengthParam) {
const found = attacks.find((a) => a.endsWith(strengthParam))
if (found) return found
}
return prev
})
}
}, [location.search, selectedModel, examples])
useEffect(() => {
setLoading(true)
setError(null)
API.fetchExamplesByType(fileType)
.then((data) => {
setExamples(data)
const models = Object.keys(data)
if (models.length > 0) {
// If query param exists and is valid, use it, else default to first
setSelectedModel((prev) => (prev && data[prev] ? prev : models[0]))
const attacks = Object.keys(data[models[0]])
if (attacks.length > 0) {
setSelectedAttack((prev) => (prev && data[models[0]][prev] ? prev : attacks[0]))
} else {
setSelectedAttack(null)
}
} else {
setSelectedModel(null)
setSelectedAttack(null)
}
setLoading(false)
})
.catch((err) => {
setError(err.message)
setLoading(false)
})
}, [fileType])
if (loading) {
return <LoadingSpinner />
}
return (
<div className="examples-container">
<div className="selectors-container flex flex-col gap-4">
<fieldset className="fieldset w-full p-4 rounded border border-gray-700 bg-base-200">
<legend className="fieldset-legend font-semibold">Model</legend>
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-1 max-h-48 overflow-y-auto pr-2">
{Object.keys(examples).map((model) => {
const fullName = descriptions.current.getModelFullName(model) || model
return (
<div key={model} className="flex items-center gap-2 text-sm relative group">
<label className="flex items-center gap-2 flex-grow">
<input
type="radio"
className="radio radio-sm"
checked={selectedModel === model}
onChange={() => setSelectedModel(model)}
name="model-selection"
/>
<div className="flex items-center">
<span className="truncate" title={fullName}>
{model}
</span>
<ModelInfoIcon modelName={model} />
</div>
</label>
</div>
)
})}
</div>
</fieldset>
{selectedModel && (
<fieldset className="fieldset">
<legend className="fieldset-legend">Attack</legend>
<select
className="select select-bordered"
value={selectedAttack || ''}
onChange={(e) => setSelectedAttack(e.target.value || null)}
>
{Object.keys(examples[selectedModel]).map((attack) => (
<option key={attack} value={attack}>
{attack}
</option>
))}
</select>
</fieldset>
)}
</div>
{error && <p className="error">Error: {error}</p>}
{selectedModel && selectedAttack && fileType === 'image' && (
<ImageGallery
selectedModel={selectedModel}
selectedAttack={selectedAttack}
examples={examples}
/>
)}
{selectedModel && selectedAttack && fileType === 'audio' && (
<AudioGallery
selectedModel={selectedModel}
selectedAttack={selectedAttack}
examples={examples}
/>
)}
{selectedModel && selectedAttack && fileType === 'video' && (
<VideoGallery
selectedModel={selectedModel}
selectedAttack={selectedAttack}
examples={examples}
/>
)}
</div>
)
}
export default Examples
|