diff --git a/src/app/api/auth/hf/callback/route.ts b/src/app/api/auth/hf/callback/route.ts deleted file mode 100644 index 2e353f3149ff687b697cb541e787a42442de501a..0000000000000000000000000000000000000000 --- a/src/app/api/auth/hf/callback/route.ts +++ /dev/null @@ -1,112 +0,0 @@ -import { NextRequest, NextResponse } from 'next/server'; -import { cookies } from 'next/headers'; - -const TOKEN_ENDPOINT = 'https://huggingface.co/oauth/token'; -const USERINFO_ENDPOINT = 'https://huggingface.co/oauth/userinfo'; -const STATE_COOKIE = 'hf_oauth_state'; - -function htmlResponse(script: string) { - return new NextResponse( - `
`, - { - headers: { 'Content-Type': 'text/html; charset=utf-8' }, - }, - ); -} - -export async function GET(request: NextRequest) { - const clientId = process.env.HF_OAUTH_CLIENT_ID || process.env.NEXT_PUBLIC_HF_OAUTH_CLIENT_ID; - const clientSecret = process.env.HF_OAUTH_CLIENT_SECRET; - - if (!clientId || !clientSecret) { - return NextResponse.json({ error: 'OAuth application is not configured' }, { status: 500 }); - } - - const { searchParams } = new URL(request.url); - const code = searchParams.get('code'); - const incomingState = searchParams.get('state'); - - const cookieStore = cookies(); - const storedState = cookieStore.get(STATE_COOKIE)?.value; - - cookieStore.delete(STATE_COOKIE); - - const origin = request.nextUrl.origin; - - if (!code || !incomingState || !storedState || incomingState !== storedState) { - const script = ` - window.opener && window.opener.postMessage({ - type: 'HF_OAUTH_ERROR', - payload: { message: 'Invalid or expired OAuth state.' } - }, '${origin}'); - window.close(); - `; - return htmlResponse(script.trim()); - } - - const redirectUri = process.env.HF_OAUTH_REDIRECT_URI || process.env.NEXT_PUBLIC_HF_OAUTH_REDIRECT_URI || `${origin}/api/auth/hf/callback`; - - try { - const tokenResponse = await fetch(TOKEN_ENDPOINT, { - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - body: new URLSearchParams({ - grant_type: 'authorization_code', - code, - redirect_uri: redirectUri, - client_id: clientId, - client_secret: clientSecret, - }), - }); - - if (!tokenResponse.ok) { - const errorPayload = await tokenResponse.json().catch(() => ({})); - throw new Error(errorPayload?.error_description || 'Failed to exchange code for token'); - } - - const tokenData = await tokenResponse.json(); - const accessToken = tokenData?.access_token; - if (!accessToken) { - throw new Error('Access token missing in response'); - } - - const userResponse = await fetch(USERINFO_ENDPOINT, { - headers: { - Authorization: `Bearer ${accessToken}`, - }, - }); - - if (!userResponse.ok) { - throw new Error('Failed to fetch user info'); - } - - const profile = await userResponse.json(); - const namespace = profile?.preferred_username || profile?.name || 'user'; - - const script = ` - window.opener && window.opener.postMessage({ - type: 'HF_OAUTH_SUCCESS', - payload: { - token: ${JSON.stringify(accessToken)}, - namespace: ${JSON.stringify(namespace)}, - } - }, '${origin}'); - window.close(); - `; - - return htmlResponse(script.trim()); - } catch (error: any) { - const message = error?.message || 'OAuth flow failed'; - const script = ` - window.opener && window.opener.postMessage({ - type: 'HF_OAUTH_ERROR', - payload: { message: ${JSON.stringify(message)} } - }, '${origin}'); - window.close(); - `; - - return htmlResponse(script.trim()); - } -} diff --git a/src/app/api/auth/hf/login/route.ts b/src/app/api/auth/hf/login/route.ts deleted file mode 100644 index 22c252217d8b94f9db7a495892a79193df05786a..0000000000000000000000000000000000000000 --- a/src/app/api/auth/hf/login/route.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { randomUUID } from 'crypto'; -import { NextRequest, NextResponse } from 'next/server'; - -const HF_AUTHORIZE_URL = 'https://huggingface.co/oauth/authorize'; -const STATE_COOKIE = 'hf_oauth_state'; - -export async function GET(request: NextRequest) { - const clientId = process.env.HF_OAUTH_CLIENT_ID || process.env.NEXT_PUBLIC_HF_OAUTH_CLIENT_ID; - if (!clientId) { - return NextResponse.json({ error: 'OAuth client ID not configured' }, { status: 500 }); - } - - const state = randomUUID(); - const origin = request.nextUrl.origin; - const redirectUri = process.env.HF_OAUTH_REDIRECT_URI || process.env.NEXT_PUBLIC_HF_OAUTH_REDIRECT_URI || `${origin}/api/auth/hf/callback`; - - const authorizeUrl = new URL(HF_AUTHORIZE_URL); - authorizeUrl.searchParams.set('response_type', 'code'); - authorizeUrl.searchParams.set('client_id', clientId); - authorizeUrl.searchParams.set('redirect_uri', redirectUri); - authorizeUrl.searchParams.set('scope', 'openid profile read-repos'); - authorizeUrl.searchParams.set('state', state); - - const response = NextResponse.redirect(authorizeUrl.toString(), { status: 302 }); - response.cookies.set({ - name: STATE_COOKIE, - value: state, - httpOnly: true, - sameSite: 'lax', - secure: process.env.NODE_ENV === 'production', - maxAge: 60 * 5, - path: '/', - }); - - return response; -} diff --git a/src/app/api/auth/hf/validate/route.ts b/src/app/api/auth/hf/validate/route.ts deleted file mode 100644 index 32dc41fb4d3a7e82d8434ce577aa9e563c349203..0000000000000000000000000000000000000000 --- a/src/app/api/auth/hf/validate/route.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { NextRequest, NextResponse } from 'next/server'; -import { whoAmI } from '@huggingface/hub'; - -export async function POST(request: NextRequest) { - try { - const body = await request.json().catch(() => ({})); - const token = (body?.token || '').trim(); - - if (!token) { - return NextResponse.json({ error: 'Token is required' }, { status: 400 }); - } - - const info = await whoAmI({ accessToken: token }); - return NextResponse.json({ - name: info?.name || info?.username || 'user', - email: info?.email || null, - orgs: info?.orgs || [], - }); - } catch (error: any) { - return NextResponse.json({ error: error?.message || 'Invalid token' }, { status: 401 }); - } -} diff --git a/src/app/api/auth/route.ts b/src/app/api/auth/route.ts deleted file mode 100644 index 1dc229739fbbeaabf307e3be544dd7e2bc8ab66f..0000000000000000000000000000000000000000 --- a/src/app/api/auth/route.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { NextResponse } from 'next/server'; - -export async function GET() { - // if this gets hit, auth has already been verified - return NextResponse.json({ isAuthenticated: true }); -} diff --git a/src/app/api/caption/get/route.ts b/src/app/api/caption/get/route.ts deleted file mode 100644 index 4f8d2818318805f97a80370e1a9cfc584cd9dc26..0000000000000000000000000000000000000000 --- a/src/app/api/caption/get/route.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* eslint-disable */ -import { NextRequest, NextResponse } from 'next/server'; -import fs from 'fs'; -import path from 'path'; -import { getDatasetsRoot } from '@/server/settings'; - -export async function POST(request: NextRequest) { - - const body = await request.json(); - const { imgPath } = body; - console.log('Received POST request for caption:', imgPath); - try { - // Decode the path - const filepath = imgPath; - console.log('Decoded image path:', filepath); - - // caption name is the filepath without extension but with .txt - const captionPath = filepath.replace(/\.[^/.]+$/, '') + '.txt'; - - // Get allowed directories - const allowedDir = await getDatasetsRoot(); - - // Security check: Ensure path is in allowed directory - const isAllowed = filepath.startsWith(allowedDir) && !filepath.includes('..'); - - if (!isAllowed) { - console.warn(`Access denied: ${filepath} not in ${allowedDir}`); - return new NextResponse('Access denied', { status: 403 }); - } - - // Check if file exists - if (!fs.existsSync(captionPath)) { - // send back blank string if caption file does not exist - return new NextResponse(''); - } - - // Read caption file - const caption = fs.readFileSync(captionPath, 'utf-8'); - - // Return caption - return new NextResponse(caption); - } catch (error) { - console.error('Error getting caption:', error); - return new NextResponse('Error getting caption', { status: 500 }); - } -} diff --git a/src/app/api/datasets/create/route.tsx b/src/app/api/datasets/create/route.tsx deleted file mode 100644 index e005d058f3423db41f4830b69a1d51c7872d1351..0000000000000000000000000000000000000000 --- a/src/app/api/datasets/create/route.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { NextResponse } from 'next/server'; -import fs from 'fs'; -import path from 'path'; -import { getDatasetsRoot } from '@/server/settings'; - -export async function POST(request: Request) { - try { - const body = await request.json(); - let { name } = body; - // clean name by making lower case, removing special characters, and replacing spaces with underscores - name = name.toLowerCase().replace(/[^a-z0-9]+/g, '_'); - - let datasetsPath = await getDatasetsRoot(); - let datasetPath = path.join(datasetsPath, name); - - // if folder doesnt exist, create it - if (!fs.existsSync(datasetPath)) { - fs.mkdirSync(datasetPath); - } - - return NextResponse.json({ success: true, name: name, path: datasetPath }); - } catch (error) { - return NextResponse.json({ error: 'Failed to create dataset' }, { status: 500 }); - } -} diff --git a/src/app/api/datasets/delete/route.tsx b/src/app/api/datasets/delete/route.tsx deleted file mode 100644 index 9a1d970ee415c9d040596854ce74ad5401859259..0000000000000000000000000000000000000000 --- a/src/app/api/datasets/delete/route.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { NextResponse } from 'next/server'; -import fs from 'fs'; -import path from 'path'; -import { getDatasetsRoot } from '@/server/settings'; - -export async function POST(request: Request) { - try { - const body = await request.json(); - const { name } = body; - let datasetsPath = await getDatasetsRoot(); - let datasetPath = path.join(datasetsPath, name); - - // if folder doesnt exist, ignore - if (!fs.existsSync(datasetPath)) { - return NextResponse.json({ success: true }); - } - - // delete it and return success - fs.rmdirSync(datasetPath, { recursive: true }); - return NextResponse.json({ success: true }); - } catch (error) { - return NextResponse.json({ error: 'Failed to create dataset' }, { status: 500 }); - } -} diff --git a/src/app/api/datasets/list/route.ts b/src/app/api/datasets/list/route.ts deleted file mode 100644 index dc829c65f3cab2829221f85341967fc1b52a921c..0000000000000000000000000000000000000000 --- a/src/app/api/datasets/list/route.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { NextResponse } from 'next/server'; -import fs from 'fs'; -import { getDatasetsRoot } from '@/server/settings'; - -export async function GET() { - try { - let datasetsPath = await getDatasetsRoot(); - - // if folder doesnt exist, create it - if (!fs.existsSync(datasetsPath)) { - fs.mkdirSync(datasetsPath); - } - - // find all the folders in the datasets folder - let folders = fs - .readdirSync(datasetsPath, { withFileTypes: true }) - .filter(dirent => dirent.isDirectory()) - .filter(dirent => !dirent.name.startsWith('.')) - .map(dirent => dirent.name); - - return NextResponse.json(folders); - } catch (error) { - return NextResponse.json({ error: 'Failed to fetch datasets' }, { status: 500 }); - } -} diff --git a/src/app/api/datasets/listImages/route.ts b/src/app/api/datasets/listImages/route.ts deleted file mode 100644 index 06dca84ae780c7fddb200fc6de422b7a42e309ea..0000000000000000000000000000000000000000 --- a/src/app/api/datasets/listImages/route.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { NextResponse } from 'next/server'; -import fs from 'fs'; -import path from 'path'; -import { getDatasetsRoot } from '@/server/settings'; - -export async function POST(request: Request) { - const datasetsPath = await getDatasetsRoot(); - const body = await request.json(); - const { datasetName } = body; - const datasetFolder = path.join(datasetsPath, datasetName); - - try { - // Check if folder exists - if (!fs.existsSync(datasetFolder)) { - return NextResponse.json({ error: `Folder '${datasetName}' not found` }, { status: 404 }); - } - - // Find all images recursively - const imageFiles = findImagesRecursively(datasetFolder); - - // Format response - const result = imageFiles.map(imgPath => ({ - img_path: imgPath, - })); - - return NextResponse.json({ images: result }); - } catch (error) { - console.error('Error finding images:', error); - return NextResponse.json({ error: 'Failed to process request' }, { status: 500 }); - } -} - -/** - * Recursively finds all image files in a directory and its subdirectories - * @param dir Directory to search - * @returns Array of absolute paths to image files - */ -function findImagesRecursively(dir: string): string[] { - const imageExtensions = ['.png', '.jpg', '.jpeg', '.webp', '.mp4', '.avi', '.mov', '.mkv', '.wmv', '.m4v', '.flv']; - let results: string[] = []; - - const items = fs.readdirSync(dir); - - for (const item of items) { - const itemPath = path.join(dir, item); - const stat = fs.statSync(itemPath); - - if (stat.isDirectory() && item !== '_controls' && !item.startsWith('.')) { - // If it's a directory, recursively search it - results = results.concat(findImagesRecursively(itemPath)); - } else { - // If it's a file, check if it's an image - const ext = path.extname(itemPath).toLowerCase(); - if (imageExtensions.includes(ext)) { - results.push(itemPath); - } - } - } - - return results; -} diff --git a/src/app/api/datasets/upload/route.ts b/src/app/api/datasets/upload/route.ts deleted file mode 100644 index 51aff81fd3bf4b091f10a1df9f2da887910f4753..0000000000000000000000000000000000000000 --- a/src/app/api/datasets/upload/route.ts +++ /dev/null @@ -1,57 +0,0 @@ -// src/app/api/datasets/upload/route.ts -import { NextRequest, NextResponse } from 'next/server'; -import { writeFile, mkdir } from 'fs/promises'; -import { join } from 'path'; -import { getDatasetsRoot } from '@/server/settings'; - -export async function POST(request: NextRequest) { - try { - const datasetsPath = await getDatasetsRoot(); - if (!datasetsPath) { - return NextResponse.json({ error: 'Datasets path not found' }, { status: 500 }); - } - const formData = await request.formData(); - const files = formData.getAll('files'); - const datasetName = formData.get('datasetName') as string; - - if (!files || files.length === 0) { - return NextResponse.json({ error: 'No files provided' }, { status: 400 }); - } - - // Create upload directory if it doesn't exist - const uploadDir = join(datasetsPath, datasetName); - await mkdir(uploadDir, { recursive: true }); - - const savedFiles: string[] = []; - - // Process files sequentially to avoid overwhelming the system - for (let i = 0; i < files.length; i++) { - const file = files[i] as any; - const bytes = await file.arrayBuffer(); - const buffer = Buffer.from(bytes); - - // Clean filename and ensure it's unique - const fileName = file.name.replace(/[^a-zA-Z0-9.-]/g, '_'); - const filePath = join(uploadDir, fileName); - - await writeFile(filePath, buffer); - savedFiles.push(fileName); - } - - return NextResponse.json({ - message: 'Files uploaded successfully', - files: savedFiles, - }); - } catch (error) { - console.error('Upload error:', error); - return NextResponse.json({ error: 'Error uploading files' }, { status: 500 }); - } -} - -// Increase payload size limit (default is 4mb) -export const config = { - api: { - bodyParser: false, - responseLimit: '50mb', - }, -}; diff --git a/src/app/api/files/[...filePath]/route.ts b/src/app/api/files/[...filePath]/route.ts deleted file mode 100644 index 46eb5c4ab08b9c02ba4ff8d0fe7f6dc2cd15442a..0000000000000000000000000000000000000000 --- a/src/app/api/files/[...filePath]/route.ts +++ /dev/null @@ -1,116 +0,0 @@ -/* eslint-disable */ -import { NextRequest, NextResponse } from 'next/server'; -import fs from 'fs'; -import path from 'path'; -import { getDatasetsRoot, getTrainingFolder } from '@/server/settings'; - -export async function GET(request: NextRequest, { params }: { params: { filePath: string } }) { - const { filePath } = await params; - try { - // Decode the path - const decodedFilePath = decodeURIComponent(filePath); - - // Get allowed directories - const datasetRoot = await getDatasetsRoot(); - const trainingRoot = await getTrainingFolder(); - const allowedDirs = [datasetRoot, trainingRoot]; - - // Security check: Ensure path is in allowed directory - const isAllowed = - allowedDirs.some(allowedDir => decodedFilePath.startsWith(allowedDir)) && !decodedFilePath.includes('..'); - - if (!isAllowed) { - console.warn(`Access denied: ${decodedFilePath} not in ${allowedDirs.join(', ')}`); - return new NextResponse('Access denied', { status: 403 }); - } - - // Check if file exists - if (!fs.existsSync(decodedFilePath)) { - console.warn(`File not found: ${decodedFilePath}`); - return new NextResponse('File not found', { status: 404 }); - } - - // Get file info - const stat = fs.statSync(decodedFilePath); - if (!stat.isFile()) { - return new NextResponse('Not a file', { status: 400 }); - } - - // Get filename for Content-Disposition - const filename = path.basename(decodedFilePath); - - // Determine content type - const ext = path.extname(decodedFilePath).toLowerCase(); - const contentTypeMap: { [key: string]: string } = { - '.jpg': 'image/jpeg', - '.jpeg': 'image/jpeg', - '.png': 'image/png', - '.gif': 'image/gif', - '.webp': 'image/webp', - '.svg': 'image/svg+xml', - '.bmp': 'image/bmp', - '.safetensors': 'application/octet-stream', - '.zip': 'application/zip', - // Videos - '.mp4': 'video/mp4', - '.avi': 'video/x-msvideo', - '.mov': 'video/quicktime', - '.mkv': 'video/x-matroska', - '.wmv': 'video/x-ms-wmv', - '.m4v': 'video/x-m4v', - '.flv': 'video/x-flv' - }; - - const contentType = contentTypeMap[ext] || 'application/octet-stream'; - - // Get range header for partial content support - const range = request.headers.get('range'); - - // Common headers for better download handling - const commonHeaders = { - 'Content-Type': contentType, - 'Accept-Ranges': 'bytes', - 'Cache-Control': 'public, max-age=86400', - 'Content-Disposition': `attachment; filename="${encodeURIComponent(filename)}"`, - 'X-Content-Type-Options': 'nosniff', - }; - - if (range) { - // Parse range header - const parts = range.replace(/bytes=/, '').split('-'); - const start = parseInt(parts[0], 10); - const end = parts[1] ? parseInt(parts[1], 10) : Math.min(start + 10 * 1024 * 1024, stat.size - 1); // 10MB chunks - const chunkSize = end - start + 1; - - const fileStream = fs.createReadStream(decodedFilePath, { - start, - end, - highWaterMark: 64 * 1024, // 64KB buffer - }); - - return new NextResponse(fileStream as any, { - status: 206, - headers: { - ...commonHeaders, - 'Content-Range': `bytes ${start}-${end}/${stat.size}`, - 'Content-Length': String(chunkSize), - }, - }); - } else { - // For full file download, read directly without streaming wrapper - const fileStream = fs.createReadStream(decodedFilePath, { - highWaterMark: 64 * 1024, // 64KB buffer - }); - - return new NextResponse(fileStream as any, { - headers: { - ...commonHeaders, - 'Content-Length': String(stat.size), - }, - }); - } - } catch (error) { - console.error('Error serving file:', error); - return new NextResponse('Internal Server Error', { status: 500 }); - } -} diff --git a/src/app/api/gpu/route.ts b/src/app/api/gpu/route.ts deleted file mode 100644 index 8b11dbb0e6d8e8de0f191bb1e78bb8687376881a..0000000000000000000000000000000000000000 --- a/src/app/api/gpu/route.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { NextResponse } from 'next/server'; -import { exec } from 'child_process'; -import { promisify } from 'util'; -import os from 'os'; - -const execAsync = promisify(exec); - -export async function GET() { - try { - // Get platform - const platform = os.platform(); - const isWindows = platform === 'win32'; - - // Check if nvidia-smi is available - const hasNvidiaSmi = await checkNvidiaSmi(isWindows); - - if (!hasNvidiaSmi) { - return NextResponse.json({ - hasNvidiaSmi: false, - gpus: [], - error: 'nvidia-smi not found or not accessible', - }); - } - - // Get GPU stats - const gpuStats = await getGpuStats(isWindows); - - return NextResponse.json({ - hasNvidiaSmi: true, - gpus: gpuStats, - }); - } catch (error) { - console.error('Error fetching NVIDIA GPU stats:', error); - return NextResponse.json( - { - hasNvidiaSmi: false, - gpus: [], - error: `Failed to fetch GPU stats: ${error instanceof Error ? error.message : String(error)}`, - }, - { status: 500 }, - ); - } -} - -async function checkNvidiaSmi(isWindows: boolean): Promise- {isAuthenticated - ? 'You are signed in with Hugging Face and can manage jobs, datasets, and submissions.' - : 'Authenticate with Hugging Face or add a personal access token to create jobs, upload datasets, and launch training.'} -
-You need to sign in with Hugging Face or provide a valid token to view this dataset.
-{subtitle}
-Sign in with Hugging Face or add an access token to manage datasets.
-Sign in with Hugging Face or add an access token to view job details.
-Loading...
} - {status === 'error' && job == null &&Error fetching job
} - {job && ( - <> - {pages.map(page => { - const Component = page.component; - return page.value === pageKey ?You need to sign in with Hugging Face or provide a valid access token before creating or editing jobs.
-Sign in with Hugging Face or add a personal access token to view and manage training jobs.
-{authDescription}
-{authError}
- )} -
-
- Drop files to upload
-- Destination: {datasetName || 'unknown'} -
-Images, videos, or .txt supported
- > - ) : ( - <> -Uploading… {uploadProgress}%
-{gpuData.error}
} -Temperature
-{gpu.temperature}°C
-Fan Speed
-{gpu.fan.speed}%
-GPU Load
- {gpu.utilization.gpu}% -Memory
- - {((gpu.memory.used / gpu.memory.total) * 100).toFixed(1)}% - -- {formatMemory(gpu.memory.used)} / {formatMemory(gpu.memory.total)} -
-Clock Speed
-{gpu.clocks.graphics} MHz
-Power Draw
-- {gpu.power.draw?.toFixed(1)}W - / {gpu.power.limit?.toFixed(1) || ' ? '}W -
-- First, let's validate your Hugging Face token and get your username for dataset uploads. -
- - {validationResult && ( -- ✓ Token valid! Logged in as: {validationResult.name} -
-- Choose whether to upload a new dataset or use an existing one from HF Hub. -
- -- Enter the full dataset ID (namespace/name) from HuggingFace Hub -
- > - )} - - {uploadResult && ( -- ✓ Dataset {uploadResult.existing ? 'validated' : 'uploaded'} successfully! -
-- {uploadResult.existing ? 'Using dataset:' : 'View at:'} {uploadResult.repoId} -
-- Configure and submit your training job to HF Jobs. -
- -- ✓ Job submitted successfully! -
-
- Job ID: {jobResult.jobId}
-
- Your training job has been submitted to Hugging Face Jobs and is now running in the cloud. -
-
- Job ID: {jobResult?.jobId}
-
- Monitor Job: - View on HF Jobs → - -
- )} -- Dataset: {uploadResult?.repoId} -
-- Hardware: {hardware} -
-Next steps:
-hf jobs logs {jobResult?.jobId}{namespace}/{jobConfig.config.name}-lora{error}
-Job Name
-{job.name}
-- {isHFJob ? 'Hardware' : 'Assigned GPUs'} -
-- {isHFJob ? (jobConfig?.hardware || job.gpu_ids) : `GPUs: ${job.gpu_ids}`} -
-Speed
-{job.speed_string == '' ? '?' : job.speed_string}
-- This job is running on HF Jobs. View logs and monitor progress on the HuggingFace platform. -
- -- This HF Job is ready for submission. Edit the job clicking on the pen on the top right. -
-{line};
- })}
- {subtitle}
-
- Ostris
- AI-Toolkit
- Welcome, {namespace || 'user'}
- )} -Empty
- -| - {column.title} - | - ))} -
|---|
| - {column.render ? column.render(row) : row[column.key]} - | - ))} -
{'[trigger]'} placeholder in your captions. This will be automatically replaced with your trigger
- word.
- {'[trigger]'} placeholder in your test prompts as well.
- >
- ),
- },
- 'config.process[0].model.name_or_path': {
- title: 'Name or Path',
- description: (
- <>
- The name of a diffusers repo on Huggingface or the local path to the base model you want to train from. The
- folder needs to be in diffusers format for most models. For some models, such as SDXL and SD1, you can put the
- path to an all in one safetensors checkpoint here.
- >
- ),
- },
- 'datasets.control_path': {
- title: 'Control Dataset',
- description: (
- <>
- The control dataset needs to have files that match the filenames of your training dataset. They should be
- matching file pairs. These images are fed as control/input images during training.
- >
- ),
- },
- 'datasets.num_frames': {
- title: 'Number of Frames',
- description: (
- <>
- This sets the number of frames to shrink videos to for a video dataset. If this dataset is images, set this to 1
- for one frame. If your dataset is only videos, frames will be extracted evenly spaced from the videos in the
- dataset.
-