Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion ui/cron/actions/startJob.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Job } from '@prisma/client';
import { spawn } from 'child_process';
import path from 'path';
import fs from 'fs';
import { TOOLKIT_ROOT, getTrainingFolder, getHFToken } from '../paths';
import { TOOLKIT_ROOT, getTrainingFolder, getHFToken, getOfflineMode } from '../paths';
import { resolvePythonPath } from '../pythonPath';
const isWindows = process.platform === 'win32';

Expand Down Expand Up @@ -81,6 +81,10 @@ const startAndWatchJob = (job: Job) => {
additionalEnv.HF_TOKEN = hfToken;
}

if (await getOfflineMode()) {
additionalEnv.HF_HUB_OFFLINE = '1';
}

// Add the --log argument to the command
const args = [runFilePath, configPath, '--log', logPath];

Expand Down
9 changes: 9 additions & 0 deletions ui/cron/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,12 @@ export const getHFToken = async () => {
}
return token;
};

export const getOfflineMode = async () => {
const row = await prisma.settings.findFirst({
where: {
key: 'OFFLINE_MODE',
},
});
return row?.value === '1';
};
11 changes: 9 additions & 2 deletions ui/src/app/api/settings/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export async function GET() {
if (!settingsObject.DATASETS_FOLDER || settingsObject.DATASETS_FOLDER === '') {
settingsObject.DATASETS_FOLDER = defaultDatasetsFolder;
}
settingsObject.OFFLINE_MODE = settingsObject.OFFLINE_MODE === '1';
return NextResponse.json(settingsObject);
} catch (error) {
return NextResponse.json({ error: 'Failed to fetch settings' }, { status: 500 });
Expand All @@ -29,15 +30,21 @@ export async function GET() {
export async function POST(request: Request) {
try {
const body = await request.json();
const { HF_TOKEN, TRAINING_FOLDER, DATASETS_FOLDER } = body;
const { HF_TOKEN, OFFLINE_MODE, TRAINING_FOLDER, DATASETS_FOLDER } = body;
const offlineModeValue = OFFLINE_MODE ? '1' : '0';

// Upsert both settings
// Persist all settings in the key/value store
await Promise.all([
prisma.settings.upsert({
where: { key: 'HF_TOKEN' },
update: { value: HF_TOKEN },
create: { key: 'HF_TOKEN', value: HF_TOKEN },
}),
prisma.settings.upsert({
where: { key: 'OFFLINE_MODE' },
update: { value: offlineModeValue },
create: { key: 'OFFLINE_MODE', value: offlineModeValue },
}),
prisma.settings.upsert({
where: { key: 'TRAINING_FOLDER' },
update: { value: TRAINING_FOLDER },
Expand Down
17 changes: 17 additions & 0 deletions ui/src/app/settings/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,23 @@ export default function Settings() {
/>
</div>

<div className="flex items-start gap-3">
<input
type="checkbox"
id="OFFLINE_MODE"
name="OFFLINE_MODE"
checked={settings.OFFLINE_MODE}
onChange={e => setSettings(prev => ({ ...prev, OFFLINE_MODE: e.target.checked }))}
className="mt-1 h-4 w-4 rounded border-gray-700 bg-gray-800 text-blue-500 focus:ring-blue-600"
/>
<label htmlFor="OFFLINE_MODE" className="block text-sm font-medium">
Offline mode
<div className="text-gray-500 text-sm">
Prevent spawned jobs from accessing the Hugging Face Hub. Required models must already be cached.
</div>
</label>
</div>

<div>
<label htmlFor="TRAINING_FOLDER" className="block text-sm font-medium mb-2">
Training Folder Path
Expand Down
7 changes: 5 additions & 2 deletions ui/src/hooks/useSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,28 @@ import { apiClient } from '@/utils/api';

export interface Settings {
HF_TOKEN: string;
OFFLINE_MODE: boolean;
TRAINING_FOLDER: string;
DATASETS_FOLDER: string;
}

export default function useSettings() {
const [settings, setSettings] = useState({
const [settings, setSettings] = useState<Settings>({
HF_TOKEN: '',
OFFLINE_MODE: false,
TRAINING_FOLDER: '',
DATASETS_FOLDER: '',
});
const [isSettingsLoaded, setIsLoaded] = useState(false);
useEffect(() => {
apiClient
.get('/api/settings')
.get<Settings>('/api/settings')
.then(res => res.data)
.then(data => {
console.log('Settings:', data);
setSettings({
HF_TOKEN: data.HF_TOKEN || '',
OFFLINE_MODE: data.OFFLINE_MODE,
TRAINING_FOLDER: data.TRAINING_FOLDER || '',
DATASETS_FOLDER: data.DATASETS_FOLDER || '',
});
Expand Down