import * as React from 'react';
import * as z from 'zod/v4';
import { Button, Chip, Typography } from '@mui/joy';
import { hasServerConf } from '~/common/app.serverconf';
import type { DModelsServiceId } from '~/common/stores/llms/llms.service.types';
import { AlreadySet } from '~/common/components/AlreadySet';
import { ExpanderControlledBox } from '~/common/components/ExpanderControlledBox';
import { ExternalLink } from '~/common/components/ExternalLink';
import { FormInputKey } from '~/common/components/forms/FormInputKey';
import { InlineError } from '~/common/components/InlineError';
import { isLocalUrl } from '~/common/util/urlUtils';
import { Link } from '~/common/components/Link';
import { LocalAIIcon } from '~/common/components/icons/vendors/LocalAIIcon';
import { SetupFormClientSideToggle } from '~/common/components/forms/SetupFormClientSideToggle';
import { SetupFormCorsHint } from '~/common/components/forms/SetupFormCorsHint';
import { SetupFormRefetchButton } from '~/common/components/forms/SetupFormRefetchButton';
import { ApproximateCosts } from '../ApproximateCosts';
import { useLlmUpdateModels } from '../../llm.client.hooks';
import { useServiceSetup } from '../useServiceSetup';
import { LocalAIAdmin } from './LocalAIAdmin';
import { ModelVendorLocalAI } from './localai.vendor';
const localAIHostSchema = z.url().startsWith('http');
export function LocalAIServiceSetup(props: { serviceId: DModelsServiceId }) {
// state
const [checkboxExpanded, setCheckboxExpanded] = React.useState(false);
const [adminOpen, setAdminOpen] = React.useState(false);
// external state
const backendHasHost = hasServerConf('hasLlmLocalAIHost');
const backendHasKey = hasServerConf('hasLlmLocalAIKey');
const { service, serviceAccess, serviceHasLLMs, updateSettings } =
useServiceSetup(props.serviceId, ModelVendorLocalAI);
// derived state
const { clientSideFetch, oaiHost: localAIHost, oaiKey: localAIKey } = serviceAccess;
// host validation
const userHostRequired = !backendHasHost;
const userHostValid = localAIHost.length >= 6 && localAIHostSchema.safeParse(localAIHost).success;
const userHostError = !!localAIHost && !userHostValid;
const shallFetchSucceed = localAIHost ? userHostValid : backendHasHost;
// fetch models - the OpenAI way
const { isFetching, refetch, isError, error } =
useLlmUpdateModels(!serviceHasLLMs && shallFetchSucceed, service);
return <>
Please ensure your LocalAI instance is correctly configured.
{checkboxExpanded && <> Visit the LocalAI website for detailed setup instructions.>}
setCheckboxExpanded(on => !on)}>
Show {checkboxExpanded ? 'less' : 'more'}
Supported features:
✅{' '}Text generation with GPTs
✅{' '}Function calling by GPTs
✅{' '}Model Gallery
✅{' '}Vision API for image chats
✅{' '}JSON output
✅{' '}Image generation (stablediffusion, dreamshaper, sd-3.5-large/medium-ggml)
✖️{' '}Speech transcription
✖️{' '}Text to speech
✖️{' '}Embeddings generation
✖️{' '}Voice cloning
: Learn more}
value={localAIHost} onChange={value => updateSettings({ localAIHost: value })}
/>
updateSettings({ localAIKey: value })}
/>
updateSettings({ csf: on })}
helpText='Fetch models and make requests directly from your LocalAI instance using the browser. Recommended for local setups - requires CORS enabled on the LocalAI server.'
localHostDetected={isLocalUrl(localAIHost)}
/>
setAdminOpen(true)} startDecorator={}>
Install Models
}
/>
Make sure CORS is enabled on the LocalAI server. Start it with CORS=true, and CORS_ALLOW_ORIGINS set to allow this site.
{isError && }
{adminOpen && setAdminOpen(false)} />}
>;
}