mirror of
https://github.com/lordmathis/llamactl.git
synced 2025-11-06 09:04:27 +00:00
Add MLX backend support with configuration and parsing enhancements
This commit is contained in:
@@ -2,11 +2,10 @@ import React from 'react'
|
|||||||
import { Input } from '@/components/ui/input'
|
import { Input } from '@/components/ui/input'
|
||||||
import { Label } from '@/components/ui/label'
|
import { Label } from '@/components/ui/label'
|
||||||
import { Checkbox } from '@/components/ui/checkbox'
|
import { Checkbox } from '@/components/ui/checkbox'
|
||||||
import type { BackendOptions } from '@/schemas/instanceOptions'
|
|
||||||
import { getBackendFieldType, basicBackendFieldsConfig } from '@/lib/zodFormUtils'
|
import { getBackendFieldType, basicBackendFieldsConfig } from '@/lib/zodFormUtils'
|
||||||
|
|
||||||
interface BackendFormFieldProps {
|
interface BackendFormFieldProps {
|
||||||
fieldKey: keyof BackendOptions
|
fieldKey: string
|
||||||
value: string | number | boolean | string[] | undefined
|
value: string | number | boolean | string[] | undefined
|
||||||
onChange: (key: string, value: string | number | boolean | string[] | undefined) => void
|
onChange: (key: string, value: string | number | boolean | string[] | undefined) => void
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ const InstanceDialog: React.FC<InstanceDialogProps> = ({
|
|||||||
// Get field lists dynamically from the type
|
// Get field lists dynamically from the type
|
||||||
const basicFields = getBasicFields();
|
const basicFields = getBasicFields();
|
||||||
const advancedFields = getAdvancedFields();
|
const advancedFields = getAdvancedFields();
|
||||||
const basicBackendFields = getBasicBackendFields();
|
const basicBackendFields = getBasicBackendFields(formData.backend_type);
|
||||||
const advancedBackendFields = getAdvancedBackendFields();
|
const advancedBackendFields = getAdvancedBackendFields(formData.backend_type);
|
||||||
|
|
||||||
// Reset form when dialog opens/closes or when instance changes
|
// Reset form when dialog opens/closes or when instance changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -66,10 +66,21 @@ const InstanceDialog: React.FC<InstanceDialogProps> = ({
|
|||||||
}, [open, instance]);
|
}, [open, instance]);
|
||||||
|
|
||||||
const handleFieldChange = (key: keyof CreateInstanceOptions, value: any) => {
|
const handleFieldChange = (key: keyof CreateInstanceOptions, value: any) => {
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => {
|
||||||
...prev,
|
// If backend_type is changing, clear backend_options
|
||||||
[key]: value,
|
if (key === 'backend_type' && prev.backend_type !== value) {
|
||||||
}));
|
return {
|
||||||
|
...prev,
|
||||||
|
[key]: value,
|
||||||
|
backend_options: {}, // Clear backend options when backend type changes
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...prev,
|
||||||
|
[key]: value,
|
||||||
|
};
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleBackendFieldChange = (key: string, value: any) => {
|
const handleBackendFieldChange = (key: string, value: any) => {
|
||||||
@@ -78,7 +89,7 @@ const InstanceDialog: React.FC<InstanceDialogProps> = ({
|
|||||||
backend_options: {
|
backend_options: {
|
||||||
...prev.backend_options,
|
...prev.backend_options,
|
||||||
[key]: value,
|
[key]: value,
|
||||||
},
|
} as any,
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -260,7 +271,7 @@ const InstanceDialog: React.FC<InstanceDialogProps> = ({
|
|||||||
<BackendFormField
|
<BackendFormField
|
||||||
key={fieldKey}
|
key={fieldKey}
|
||||||
fieldKey={fieldKey}
|
fieldKey={fieldKey}
|
||||||
value={formData.backend_options?.[fieldKey]}
|
value={(formData.backend_options as any)?.[fieldKey]}
|
||||||
onChange={handleBackendFieldChange}
|
onChange={handleBackendFieldChange}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
@@ -345,7 +356,7 @@ const InstanceDialog: React.FC<InstanceDialogProps> = ({
|
|||||||
<BackendFormField
|
<BackendFormField
|
||||||
key={fieldKey}
|
key={fieldKey}
|
||||||
fieldKey={fieldKey}
|
fieldKey={fieldKey}
|
||||||
value={formData.backend_options?.[fieldKey]}
|
value={(formData.backend_options as any)?.[fieldKey]}
|
||||||
onChange={handleBackendFieldChange}
|
onChange={handleBackendFieldChange}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -2,8 +2,7 @@ import React from 'react'
|
|||||||
import { Input } from '@/components/ui/input'
|
import { Input } from '@/components/ui/input'
|
||||||
import { Label } from '@/components/ui/label'
|
import { Label } from '@/components/ui/label'
|
||||||
import { Checkbox } from '@/components/ui/checkbox'
|
import { Checkbox } from '@/components/ui/checkbox'
|
||||||
import type { CreateInstanceOptions } from '@/types/instance'
|
import { BackendType, type CreateInstanceOptions } from '@/types/instance'
|
||||||
import { BackendType } from '@/types/instance'
|
|
||||||
import { getFieldType, basicFieldsConfig } from '@/lib/zodFormUtils'
|
import { getFieldType, basicFieldsConfig } from '@/lib/zodFormUtils'
|
||||||
|
|
||||||
interface ZodFormFieldProps {
|
interface ZodFormFieldProps {
|
||||||
@@ -39,7 +38,7 @@ const ZodFormField: React.FC<ZodFormFieldProps> = ({ fieldKey, value, onChange }
|
|||||||
className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
||||||
>
|
>
|
||||||
<option value={BackendType.LLAMA_CPP}>Llama Server</option>
|
<option value={BackendType.LLAMA_CPP}>Llama Server</option>
|
||||||
{/* Add more backend types here as they become available */}
|
<option value={BackendType.MLX_LM}>MLX LM</option>
|
||||||
</select>
|
</select>
|
||||||
{config.description && (
|
{config.description && (
|
||||||
<p className="text-sm text-muted-foreground">{config.description}</p>
|
<p className="text-sm text-muted-foreground">{config.description}</p>
|
||||||
|
|||||||
@@ -93,6 +93,14 @@ export const backendsApi = {
|
|||||||
body: JSON.stringify({ command }),
|
body: JSON.stringify({ command }),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
mlx: {
|
||||||
|
// POST /backends/mlx/parse-command
|
||||||
|
parseCommand: (command: string) =>
|
||||||
|
apiCall<CreateInstanceOptions>('/backends/mlx/parse-command', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({ command }),
|
||||||
|
}),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Instance API functions
|
// Instance API functions
|
||||||
|
|||||||
@@ -1,4 +1,15 @@
|
|||||||
import { type CreateInstanceOptions, type BackendOptions, getAllFieldKeys, getAllBackendFieldKeys } from '@/schemas/instanceOptions'
|
import {
|
||||||
|
type CreateInstanceOptions,
|
||||||
|
type LlamaCppBackendOptions,
|
||||||
|
type MlxBackendOptions,
|
||||||
|
LlamaCppBackendOptionsSchema,
|
||||||
|
MlxBackendOptionsSchema,
|
||||||
|
getAllFieldKeys,
|
||||||
|
getAllLlamaCppFieldKeys,
|
||||||
|
getAllMlxFieldKeys,
|
||||||
|
getLlamaCppFieldType,
|
||||||
|
getMlxFieldType
|
||||||
|
} from '@/schemas/instanceOptions'
|
||||||
|
|
||||||
// Instance-level basic fields (not backend-specific)
|
// Instance-level basic fields (not backend-specific)
|
||||||
export const basicFieldsConfig: Record<string, {
|
export const basicFieldsConfig: Record<string, {
|
||||||
@@ -36,8 +47,8 @@ export const basicFieldsConfig: Record<string, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Backend-specific basic fields (these go in backend_options)
|
// LlamaCpp backend-specific basic fields
|
||||||
export const basicBackendFieldsConfig: Record<string, {
|
const basicLlamaCppFieldsConfig: Record<string, {
|
||||||
label: string
|
label: string
|
||||||
description?: string
|
description?: string
|
||||||
placeholder?: string
|
placeholder?: string
|
||||||
@@ -46,7 +57,8 @@ export const basicBackendFieldsConfig: Record<string, {
|
|||||||
model: {
|
model: {
|
||||||
label: 'Model Path',
|
label: 'Model Path',
|
||||||
placeholder: '/path/to/model.gguf',
|
placeholder: '/path/to/model.gguf',
|
||||||
description: 'Path to the model file'
|
description: 'Path to the model file',
|
||||||
|
required: true
|
||||||
},
|
},
|
||||||
hf_repo: {
|
hf_repo: {
|
||||||
label: 'Hugging Face Repository',
|
label: 'Hugging Face Repository',
|
||||||
@@ -65,13 +77,55 @@ export const basicBackendFieldsConfig: Record<string, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isBasicField(key: keyof CreateInstanceOptions): boolean {
|
// MLX backend-specific basic fields
|
||||||
|
const basicMlxFieldsConfig: Record<string, {
|
||||||
|
label: string
|
||||||
|
description?: string
|
||||||
|
placeholder?: string
|
||||||
|
required?: boolean
|
||||||
|
}> = {
|
||||||
|
model: {
|
||||||
|
label: 'Model',
|
||||||
|
placeholder: 'mlx-community/Mistral-7B-Instruct-v0.3-4bit',
|
||||||
|
description: 'The path to the MLX model weights, tokenizer, and config',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
python_path: {
|
||||||
|
label: 'Python Virtual Environment Path',
|
||||||
|
placeholder: '/path/to/venv',
|
||||||
|
description: 'Path to Python virtual environment (optional)'
|
||||||
|
},
|
||||||
|
temp: {
|
||||||
|
label: 'Temperature',
|
||||||
|
placeholder: '0.0',
|
||||||
|
description: 'Default sampling temperature (default: 0.0)'
|
||||||
|
},
|
||||||
|
top_p: {
|
||||||
|
label: 'Top-P',
|
||||||
|
placeholder: '1.0',
|
||||||
|
description: 'Default nucleus sampling top-p (default: 1.0)'
|
||||||
|
},
|
||||||
|
top_k: {
|
||||||
|
label: 'Top-K',
|
||||||
|
placeholder: '0',
|
||||||
|
description: 'Default top-k sampling (default: 0, disables top-k)'
|
||||||
|
},
|
||||||
|
min_p: {
|
||||||
|
label: 'Min-P',
|
||||||
|
placeholder: '0.0',
|
||||||
|
description: 'Default min-p sampling (default: 0.0, disables min-p)'
|
||||||
|
},
|
||||||
|
max_tokens: {
|
||||||
|
label: 'Max Tokens',
|
||||||
|
placeholder: '512',
|
||||||
|
description: 'Default maximum number of tokens to generate (default: 512)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isBasicField(key: keyof CreateInstanceOptions): boolean {
|
||||||
return key in basicFieldsConfig
|
return key in basicFieldsConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isBasicBackendField(key: keyof BackendOptions): boolean {
|
|
||||||
return key in basicBackendFieldsConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getBasicFields(): (keyof CreateInstanceOptions)[] {
|
export function getBasicFields(): (keyof CreateInstanceOptions)[] {
|
||||||
return Object.keys(basicFieldsConfig) as (keyof CreateInstanceOptions)[]
|
return Object.keys(basicFieldsConfig) as (keyof CreateInstanceOptions)[]
|
||||||
@@ -81,13 +135,61 @@ export function getAdvancedFields(): (keyof CreateInstanceOptions)[] {
|
|||||||
return getAllFieldKeys().filter(key => !isBasicField(key))
|
return getAllFieldKeys().filter(key => !isBasicField(key))
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getBasicBackendFields(): (keyof BackendOptions)[] {
|
|
||||||
return Object.keys(basicBackendFieldsConfig) as (keyof BackendOptions)[]
|
export function getBasicBackendFields(backendType?: string): string[] {
|
||||||
|
if (backendType === 'mlx_lm') {
|
||||||
|
return Object.keys(basicMlxFieldsConfig)
|
||||||
|
} else if (backendType === 'llama_cpp') {
|
||||||
|
return Object.keys(basicLlamaCppFieldsConfig)
|
||||||
|
}
|
||||||
|
// Default to LlamaCpp for backward compatibility
|
||||||
|
return Object.keys(basicLlamaCppFieldsConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAdvancedBackendFields(): (keyof BackendOptions)[] {
|
export function getAdvancedBackendFields(backendType?: string): string[] {
|
||||||
return getAllBackendFieldKeys().filter(key => !isBasicBackendField(key))
|
if (backendType === 'mlx_lm') {
|
||||||
|
return getAllMlxFieldKeys().filter(key => !(key in basicMlxFieldsConfig))
|
||||||
|
} else if (backendType === 'llama_cpp') {
|
||||||
|
return getAllLlamaCppFieldKeys().filter(key => !(key in basicLlamaCppFieldsConfig))
|
||||||
|
}
|
||||||
|
// Default to LlamaCpp for backward compatibility
|
||||||
|
return getAllLlamaCppFieldKeys().filter(key => !(key in basicLlamaCppFieldsConfig))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combined backend fields config for use in BackendFormField
|
||||||
|
export const basicBackendFieldsConfig: Record<string, {
|
||||||
|
label: string
|
||||||
|
description?: string
|
||||||
|
placeholder?: string
|
||||||
|
required?: boolean
|
||||||
|
}> = {
|
||||||
|
...basicLlamaCppFieldsConfig,
|
||||||
|
...basicMlxFieldsConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get field type for any backend option (union type)
|
||||||
|
export function getBackendFieldType(key: string): 'text' | 'number' | 'boolean' | 'array' {
|
||||||
|
// Try to get type from LlamaCpp schema first
|
||||||
|
try {
|
||||||
|
if (LlamaCppBackendOptionsSchema.shape && key in LlamaCppBackendOptionsSchema.shape) {
|
||||||
|
return getLlamaCppFieldType(key as keyof LlamaCppBackendOptions)
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Schema might not be available
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try MLX schema
|
||||||
|
try {
|
||||||
|
if (MlxBackendOptionsSchema.shape && key in MlxBackendOptionsSchema.shape) {
|
||||||
|
return getMlxFieldType(key as keyof MlxBackendOptions)
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Schema might not be available
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default fallback
|
||||||
|
return 'text'
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-export the Zod-based functions
|
// Re-export the Zod-based functions
|
||||||
export { getFieldType, getBackendFieldType } from '@/schemas/instanceOptions'
|
export { getFieldType } from '@/schemas/instanceOptions'
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import { BackendType } from '@/types/instance'
|
import { BackendType } from '@/types/instance'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
|
||||||
// Define the backend options schema (previously embedded in CreateInstanceOptionsSchema)
|
// Define the LlamaCpp backend options schema
|
||||||
export const BackendOptionsSchema = z.object({
|
export const LlamaCppBackendOptionsSchema = z.object({
|
||||||
// Common params
|
// Common params
|
||||||
verbose_prompt: z.boolean().optional(),
|
verbose_prompt: z.boolean().optional(),
|
||||||
threads: z.number().optional(),
|
threads: z.number().optional(),
|
||||||
@@ -170,6 +170,40 @@ export const BackendOptionsSchema = z.object({
|
|||||||
fim_qwen_14b_spec: z.boolean().optional(),
|
fim_qwen_14b_spec: z.boolean().optional(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Define the MLX backend options schema
|
||||||
|
export const MlxBackendOptionsSchema = z.object({
|
||||||
|
// Basic connection options
|
||||||
|
model: z.string().optional(),
|
||||||
|
host: z.string().optional(),
|
||||||
|
port: z.number().optional(),
|
||||||
|
python_path: z.string().optional(),
|
||||||
|
|
||||||
|
// Model and adapter options
|
||||||
|
adapter_path: z.string().optional(),
|
||||||
|
draft_model: z.string().optional(),
|
||||||
|
num_draft_tokens: z.number().optional(),
|
||||||
|
trust_remote_code: z.boolean().optional(),
|
||||||
|
|
||||||
|
// Logging and templates
|
||||||
|
log_level: z.enum(['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']).optional(),
|
||||||
|
chat_template: z.string().optional(),
|
||||||
|
use_default_chat_template: z.boolean().optional(),
|
||||||
|
chat_template_args: z.string().optional(), // JSON string
|
||||||
|
|
||||||
|
// Sampling defaults
|
||||||
|
temp: z.number().optional(), // Note: MLX uses "temp" not "temperature"
|
||||||
|
top_p: z.number().optional(),
|
||||||
|
top_k: z.number().optional(),
|
||||||
|
min_p: z.number().optional(),
|
||||||
|
max_tokens: z.number().optional(),
|
||||||
|
})
|
||||||
|
|
||||||
|
// Backend options union
|
||||||
|
export const BackendOptionsSchema = z.union([
|
||||||
|
LlamaCppBackendOptionsSchema,
|
||||||
|
MlxBackendOptionsSchema,
|
||||||
|
])
|
||||||
|
|
||||||
// Define the main create instance options schema
|
// Define the main create instance options schema
|
||||||
export const CreateInstanceOptionsSchema = z.object({
|
export const CreateInstanceOptionsSchema = z.object({
|
||||||
// Restart options
|
// Restart options
|
||||||
@@ -180,11 +214,13 @@ export const CreateInstanceOptionsSchema = z.object({
|
|||||||
on_demand_start: z.boolean().optional(),
|
on_demand_start: z.boolean().optional(),
|
||||||
|
|
||||||
// Backend configuration
|
// Backend configuration
|
||||||
backend_type: z.enum([BackendType.LLAMA_CPP]).optional(),
|
backend_type: z.enum([BackendType.LLAMA_CPP, BackendType.MLX_LM]).optional(),
|
||||||
backend_options: BackendOptionsSchema.optional(),
|
backend_options: BackendOptionsSchema.optional(),
|
||||||
})
|
})
|
||||||
|
|
||||||
// Infer the TypeScript types from the schemas
|
// Infer the TypeScript types from the schemas
|
||||||
|
export type LlamaCppBackendOptions = z.infer<typeof LlamaCppBackendOptionsSchema>
|
||||||
|
export type MlxBackendOptions = z.infer<typeof MlxBackendOptionsSchema>
|
||||||
export type BackendOptions = z.infer<typeof BackendOptionsSchema>
|
export type BackendOptions = z.infer<typeof BackendOptionsSchema>
|
||||||
export type CreateInstanceOptions = z.infer<typeof CreateInstanceOptionsSchema>
|
export type CreateInstanceOptions = z.infer<typeof CreateInstanceOptionsSchema>
|
||||||
|
|
||||||
@@ -193,9 +229,14 @@ export function getAllFieldKeys(): (keyof CreateInstanceOptions)[] {
|
|||||||
return Object.keys(CreateInstanceOptionsSchema.shape) as (keyof CreateInstanceOptions)[]
|
return Object.keys(CreateInstanceOptionsSchema.shape) as (keyof CreateInstanceOptions)[]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper to get all backend option field keys
|
// Helper to get all LlamaCpp backend option field keys
|
||||||
export function getAllBackendFieldKeys(): (keyof BackendOptions)[] {
|
export function getAllLlamaCppFieldKeys(): (keyof LlamaCppBackendOptions)[] {
|
||||||
return Object.keys(BackendOptionsSchema.shape) as (keyof BackendOptions)[]
|
return Object.keys(LlamaCppBackendOptionsSchema.shape) as (keyof LlamaCppBackendOptions)[]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to get all MLX backend option field keys
|
||||||
|
export function getAllMlxFieldKeys(): (keyof MlxBackendOptions)[] {
|
||||||
|
return Object.keys(MlxBackendOptionsSchema.shape) as (keyof MlxBackendOptions)[]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get field type from Zod schema
|
// Get field type from Zod schema
|
||||||
@@ -213,9 +254,9 @@ export function getFieldType(key: keyof CreateInstanceOptions): 'text' | 'number
|
|||||||
return 'text' // ZodString and others default to text
|
return 'text' // ZodString and others default to text
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get field type for backend options
|
// Get field type for LlamaCpp backend options
|
||||||
export function getBackendFieldType(key: keyof BackendOptions): 'text' | 'number' | 'boolean' | 'array' {
|
export function getLlamaCppFieldType(key: keyof LlamaCppBackendOptions): 'text' | 'number' | 'boolean' | 'array' {
|
||||||
const fieldSchema = BackendOptionsSchema.shape[key]
|
const fieldSchema = LlamaCppBackendOptionsSchema.shape[key]
|
||||||
if (!fieldSchema) return 'text'
|
if (!fieldSchema) return 'text'
|
||||||
|
|
||||||
// Handle ZodOptional wrapper
|
// Handle ZodOptional wrapper
|
||||||
@@ -225,4 +266,19 @@ export function getBackendFieldType(key: keyof BackendOptions): 'text' | 'number
|
|||||||
if (innerSchema instanceof z.ZodNumber) return 'number'
|
if (innerSchema instanceof z.ZodNumber) return 'number'
|
||||||
if (innerSchema instanceof z.ZodArray) return 'array'
|
if (innerSchema instanceof z.ZodArray) return 'array'
|
||||||
return 'text' // ZodString and others default to text
|
return 'text' // ZodString and others default to text
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get field type for MLX backend options
|
||||||
|
export function getMlxFieldType(key: keyof MlxBackendOptions): 'text' | 'number' | 'boolean' | 'array' {
|
||||||
|
const fieldSchema = MlxBackendOptionsSchema.shape[key]
|
||||||
|
if (!fieldSchema) return 'text'
|
||||||
|
|
||||||
|
// Handle ZodOptional wrapper
|
||||||
|
const innerSchema = fieldSchema instanceof z.ZodOptional ? fieldSchema.unwrap() : fieldSchema
|
||||||
|
|
||||||
|
if (innerSchema instanceof z.ZodBoolean) return 'boolean'
|
||||||
|
if (innerSchema instanceof z.ZodNumber) return 'number'
|
||||||
|
if (innerSchema instanceof z.ZodArray) return 'array'
|
||||||
|
if (innerSchema instanceof z.ZodEnum) return 'text' // Enum treated as text/select
|
||||||
|
return 'text' // ZodString and others default to text
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,9 @@ import type { CreateInstanceOptions } from '@/schemas/instanceOptions'
|
|||||||
export { type CreateInstanceOptions } from '@/schemas/instanceOptions'
|
export { type CreateInstanceOptions } from '@/schemas/instanceOptions'
|
||||||
|
|
||||||
export const BackendType = {
|
export const BackendType = {
|
||||||
LLAMA_CPP: 'llama_cpp'
|
LLAMA_CPP: 'llama_cpp',
|
||||||
|
MLX_LM: 'mlx_lm',
|
||||||
|
// MLX_VLM: 'mlx_vlm', // Future expansion
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
export type BackendTypeValue = typeof BackendType[keyof typeof BackendType]
|
export type BackendTypeValue = typeof BackendType[keyof typeof BackendType]
|
||||||
|
|||||||
Reference in New Issue
Block a user