multimodalart HF Staff commited on
Commit
5d9965c
·
verified ·
1 Parent(s): a3de4b2

adjust for event

Browse files
ui/src/app/api/hf-jobs/route.ts CHANGED
@@ -7,7 +7,7 @@ import { tmpdir } from 'os';
7
  export async function POST(request: NextRequest) {
8
  try {
9
  const body = await request.json();
10
- const { action, token, hardware, namespace, jobConfig, datasetRepo } = body;
11
 
12
  switch (action) {
13
  case 'checkStatus':
@@ -59,7 +59,12 @@ export async function POST(request: NextRequest) {
59
  await writeFile(scriptPath, uvScript);
60
 
61
  // Submit HF job using uv run
62
- const jobId = await submitHFJobUV(token, hardware, scriptPath);
 
 
 
 
 
63
 
64
  return NextResponse.json({
65
  success: true,
@@ -597,7 +602,7 @@ def generate_model_card_readme(repo_id: str, config: dict, model_name: str, cura
597
  tags.append("sd3")
598
 
599
  # Add LoRA-specific tags
600
- tags.extend(["lora", "diffusers", "template:sd-lora", "ai-toolkit", "ai-toolkit-jobs"])
601
 
602
  # Generate widgets and gallery section from sample images
603
  curated_samples = curated_samples or []
@@ -778,7 +783,7 @@ if __name__ == "__main__":
778
  `;
779
  }
780
 
781
- async function submitHFJobUV(token: string, hardware: string, scriptPath: string): Promise<string> {
782
  return new Promise((resolve, reject) => {
783
  // Ensure token is available
784
  if (!token) {
@@ -787,17 +792,25 @@ async function submitHFJobUV(token: string, hardware: string, scriptPath: string
787
  }
788
 
789
  console.log('Setting up environment with HF_TOKEN for job submission');
790
- console.log(`Command: hf jobs uv run --flavor ${hardware} --timeout 5h --secrets HF_TOKEN --detach ${scriptPath}`);
791
-
 
792
  // Use hf jobs uv run command with timeout and detach to get job ID
793
- const childProcess = spawn('hf', [
794
  'jobs', 'uv', 'run',
795
  '--flavor', hardware,
796
  '--timeout', '5h',
797
  '--secrets', 'HF_TOKEN',
798
- '--detach',
799
- scriptPath
800
- ], {
 
 
 
 
 
 
 
801
  env: {
802
  ...process.env,
803
  HF_TOKEN: token
 
7
  export async function POST(request: NextRequest) {
8
  try {
9
  const body = await request.json();
10
+ const { action, token, hardware, namespace, jobConfig, datasetRepo, participateHackathon } = body;
11
 
12
  switch (action) {
13
  case 'checkStatus':
 
59
  await writeFile(scriptPath, uvScript);
60
 
61
  // Submit HF job using uv run
62
+ const jobId = await submitHFJobUV(
63
+ token,
64
+ hardware,
65
+ scriptPath,
66
+ participateHackathon ? 'lora-training-frenzi' : undefined
67
+ );
68
 
69
  return NextResponse.json({
70
  success: true,
 
602
  tags.append("sd3")
603
 
604
  # Add LoRA-specific tags
605
+ tags.extend(["lora", "diffusers", "template:sd-lora", "ai-toolkit"])
606
 
607
  # Generate widgets and gallery section from sample images
608
  curated_samples = curated_samples or []
 
783
  `;
784
  }
785
 
786
+ async function submitHFJobUV(token: string, hardware: string, scriptPath: string, namespaceOverride?: string): Promise<string> {
787
  return new Promise((resolve, reject) => {
788
  // Ensure token is available
789
  if (!token) {
 
792
  }
793
 
794
  console.log('Setting up environment with HF_TOKEN for job submission');
795
+ const namespaceArgs = namespaceOverride ? ` --namespace ${namespaceOverride}` : '';
796
+ console.log(`Command: hf jobs uv run --flavor ${hardware} --timeout 5h --secrets HF_TOKEN --detach${namespaceArgs} ${scriptPath}`);
797
+
798
  // Use hf jobs uv run command with timeout and detach to get job ID
799
+ const args = [
800
  'jobs', 'uv', 'run',
801
  '--flavor', hardware,
802
  '--timeout', '5h',
803
  '--secrets', 'HF_TOKEN',
804
+ '--detach'
805
+ ];
806
+
807
+ if (namespaceOverride) {
808
+ args.push('--namespace', namespaceOverride);
809
+ }
810
+
811
+ args.push(scriptPath);
812
+
813
+ const childProcess = spawn('hf', args, {
814
  env: {
815
  ...process.env,
816
  HF_TOKEN: token
ui/src/app/dashboard/page.tsx CHANGED
@@ -19,6 +19,13 @@ export default function Dashboard() {
19
  <div className="flex-1" />
20
  </TopBar>
21
  <MainContent>
 
 
 
 
 
 
 
22
  <div className="border border-gray-800 rounded-xl bg-gray-900 p-6 flex flex-col gap-4">
23
  <div>
24
  <h2 className="text-xl font-semibold text-gray-100">
 
19
  <div className="flex-1" />
20
  </TopBar>
21
  <MainContent>
22
+ <div className="mb-6">
23
+ <img
24
+ src="https://d112y698adiu2z.cloudfront.net/photos/production/challenge_photos/003/754/358/datas/full_width.png"
25
+ alt="FLUX.1 Kontext Dev Hackathon banner"
26
+ className="w-full rounded-lg border border-gray-800"
27
+ />
28
+ </div>
29
  <div className="border border-gray-800 rounded-xl bg-gray-900 p-6 flex flex-col gap-4">
30
  <div>
31
  <h2 className="text-xl font-semibold text-gray-100">
ui/src/app/jobs/new/SimpleJob.tsx CHANGED
@@ -125,6 +125,16 @@ export default function SimpleJob({
125
  return newQuantizationOptions;
126
  }, [modelArch]);
127
 
 
 
 
 
 
 
 
 
 
 
128
  return (
129
  <>
130
  <form onSubmit={handleSubmit} className="space-y-8">
@@ -956,6 +966,7 @@ export default function SimpleJob({
956
  <div className="mt-8">
957
  <HFJobsWorkflow
958
  jobConfig={jobConfig}
 
959
  onComplete={(jobId, localJobId) => {
960
  console.log('HF Job submitted:', jobId, 'Local job ID:', localJobId);
961
  if (onHFJobComplete) {
 
125
  return newQuantizationOptions;
126
  }, [modelArch]);
127
 
128
+ const isFluxKontextDev = useMemo(() => {
129
+ try {
130
+ const process = jobConfig?.config?.process?.[0];
131
+ const model = process?.model ?? {};
132
+ return model?.arch === 'flux_kontext' && model?.name_or_path === 'black-forest-labs/FLUX.1-Kontext-dev';
133
+ } catch (error) {
134
+ return false;
135
+ }
136
+ }, [jobConfig]);
137
+
138
  return (
139
  <>
140
  <form onSubmit={handleSubmit} className="space-y-8">
 
966
  <div className="mt-8">
967
  <HFJobsWorkflow
968
  jobConfig={jobConfig}
969
+ hackathonEligible={isFluxKontextDev}
970
  onComplete={(jobId, localJobId) => {
971
  console.log('HF Job submitted:', jobId, 'Local job ID:', localJobId);
972
  if (onHFJobComplete) {
ui/src/components/HFJobsWorkflow.tsx CHANGED
@@ -1,6 +1,6 @@
1
  'use client';
2
 
3
- import { useState } from 'react';
4
  import { Button } from '@headlessui/react';
5
  import { SelectInput, TextInput, Checkbox } from '@/components/formInputs';
6
  import Card from '@/components/Card';
@@ -130,11 +130,12 @@ import { useAuth } from '@/contexts/AuthContext';
130
  interface HFJobsWorkflowProps {
131
  jobConfig: JobConfig;
132
  onComplete: (jobId: string, localJobId?: string) => void;
 
133
  }
134
 
135
  type Step = 'validate' | 'upload' | 'submit' | 'complete';
136
 
137
- export default function HFJobsWorkflow({ jobConfig, onComplete }: HFJobsWorkflowProps) {
138
  const { settings } = useSettings();
139
  const { token: authToken } = useAuth();
140
  const [defaultNamespace, setDefaultNamespace] = useState('');
@@ -149,6 +150,13 @@ export default function HFJobsWorkflow({ jobConfig, onComplete }: HFJobsWorkflow
149
  const [hardware, setHardware] = useState(settings.HF_JOBS_DEFAULT_HARDWARE || 'a100-large');
150
  const [namespace, setNamespace] = useState(settings.HF_JOBS_NAMESPACE || '');
151
  const [autoUpload, setAutoUpload] = useState(true);
 
 
 
 
 
 
 
152
 
153
  // Progress state
154
  const [validationResult, setValidationResult] = useState<any>(null);
@@ -301,6 +309,7 @@ export default function HFJobsWorkflow({ jobConfig, onComplete }: HFJobsWorkflow
301
  namespace: resolvedNamespace,
302
  jobConfig,
303
  datasetRepo,
 
304
  });
305
 
306
  if (response.data.success) {
@@ -385,6 +394,26 @@ export default function HFJobsWorkflow({ jobConfig, onComplete }: HFJobsWorkflow
385
  return (
386
  <Card title="Validate HF Token">
387
  <div className="space-y-4">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
388
  <p className="text-sm text-gray-400">
389
  First, let's validate your Hugging Face token and get your username for dataset uploads.
390
  </p>
 
1
  'use client';
2
 
3
+ import { useEffect, useState } from 'react';
4
  import { Button } from '@headlessui/react';
5
  import { SelectInput, TextInput, Checkbox } from '@/components/formInputs';
6
  import Card from '@/components/Card';
 
130
  interface HFJobsWorkflowProps {
131
  jobConfig: JobConfig;
132
  onComplete: (jobId: string, localJobId?: string) => void;
133
+ hackathonEligible?: boolean;
134
  }
135
 
136
  type Step = 'validate' | 'upload' | 'submit' | 'complete';
137
 
138
+ export default function HFJobsWorkflow({ jobConfig, onComplete, hackathonEligible = false }: HFJobsWorkflowProps) {
139
  const { settings } = useSettings();
140
  const { token: authToken } = useAuth();
141
  const [defaultNamespace, setDefaultNamespace] = useState('');
 
150
  const [hardware, setHardware] = useState(settings.HF_JOBS_DEFAULT_HARDWARE || 'a100-large');
151
  const [namespace, setNamespace] = useState(settings.HF_JOBS_NAMESPACE || '');
152
  const [autoUpload, setAutoUpload] = useState(true);
153
+ const [participateHackathon, setParticipateHackathon] = useState(false);
154
+
155
+ useEffect(() => {
156
+ if (!hackathonEligible && participateHackathon) {
157
+ setParticipateHackathon(false);
158
+ }
159
+ }, [hackathonEligible, participateHackathon]);
160
 
161
  // Progress state
162
  const [validationResult, setValidationResult] = useState<any>(null);
 
309
  namespace: resolvedNamespace,
310
  jobConfig,
311
  datasetRepo,
312
+ participateHackathon: hackathonEligible && participateHackathon,
313
  });
314
 
315
  if (response.data.success) {
 
394
  return (
395
  <Card title="Validate HF Token">
396
  <div className="space-y-4">
397
+ {hackathonEligible && (
398
+ <Checkbox
399
+ label={
400
+ <span>
401
+ Participating in the free FLUX.1 Kontext Dev Hackathon? If so, please join this
402
+ <a
403
+ href="https://huggingface.co/organizations/lora-training-frenzi/share/kEyyVNQXBPWqmARdwHFVdIiFqqONHZPOtz"
404
+ target="_blank"
405
+ rel="noopener noreferrer"
406
+ className="text-blue-400 underline mx-1"
407
+ >
408
+ organization
409
+ </a>
410
+ before starting your job.
411
+ </span>
412
+ }
413
+ checked={participateHackathon}
414
+ onChange={value => setParticipateHackathon(value)}
415
+ />
416
+ )}
417
  <p className="text-sm text-gray-400">
418
  First, let's validate your Hugging Face token and get your username for dataset uploads.
419
  </p>