nico-martin's picture
nico-martin HF Staff
added pythonic tool calls
ec2237a
import {
Button,
InputCheckbox,
InputCheckboxList,
InputSelect,
InputSlider,
InputTextarea,
} from "@theme";
import { formatBytes } from "@utils/format.ts";
import { MODELS } from "@utils/models.ts";
import { TOOLS } from "@utils/tools.ts";
import { useEffect, useRef } from "react";
import { Controller, useForm } from "react-hook-form";
import type { ChatSettings } from "./types.ts";
export default function ChatSettingsModalForm({
defaultValues,
onSubmit,
downloadedModels,
visible,
}: {
defaultValues: ChatSettings;
onSubmit: (data: ChatSettings) => void;
downloadedModels: Array<string>;
visible: boolean;
}) {
const selectModelRef = useRef<HTMLSelectElement>(null);
const {
control,
handleSubmit,
formState: { errors },
} = useForm<ChatSettings>({
defaultValues,
});
const modelOptions = Object.values(
Object.entries(MODELS).reduce(
(groups, [key, model]) => {
const groupName = model.group;
if (!groups[groupName]) {
groups[groupName] = {
label: groupName.charAt(0).toUpperCase() + groupName.slice(1),
options: [],
};
}
groups[groupName].options.push({
value: key,
label: `${model.title} - ${formatBytes(model.size)}${downloadedModels.includes(key) ? " *" : ""}`,
title: model.title,
});
return groups;
},
{} as Record<
string,
{
label: string;
options: Array<{ value: string; label: string; title: string }>;
}
>
)
)
.sort((a, b) => a.label.localeCompare(b.label))
.map((group) => ({
...group,
options: group.options
.sort((a, b) => a.title.localeCompare(b.title))
.map(({ value, label }) => ({ value, label })),
}));
const toolOptions = TOOLS.map((tool) => ({
name: tool.name,
label: tool.name,
description: tool.description,
}));
useEffect(() => {
if (visible && selectModelRef.current) {
// Use setTimeout to ensure the element is rendered and ready for focus
setTimeout(() => {
selectModelRef.current?.focus();
}, 200);
}
}, [visible]);
return (
<form onSubmit={handleSubmit(onSubmit)} className="flex flex-col gap-6">
<Controller
name="modelKey"
control={control}
rules={{ required: "Model is required" }}
render={({ field }) => (
<InputSelect
id="model-select"
label="Model"
error={errors.modelKey?.message as string}
value={field.value}
onChange={field.onChange}
options={modelOptions}
required
tooltip="(*) are already downloaded"
ref={selectModelRef}
/>
)}
/>
<Controller
name="systemPrompt"
control={control}
rules={{ required: "System prompt is required" }}
render={({ field }) => (
<InputTextarea
id="system-prompt"
label="System Prompt"
placeholder="You are a helpful AI Assistant"
error={errors.systemPrompt?.message as string}
value={field.value}
onChange={field.onChange}
rows={6}
required
/>
)}
/>
<Controller
name="tools"
control={control}
render={({ field }) => (
<InputCheckboxList
id="tools"
label="Tools (only if supported by the model)"
options={toolOptions}
value={field.value}
onChange={field.onChange}
error={errors.tools?.message as string}
/>
)}
/>
<Controller
name="temperature"
control={control}
rules={{
required: "Temperature is required",
min: { value: 0, message: "Temperature must be at least 0" },
max: { value: 2, message: "Temperature must be at most 2" },
}}
render={({ field }) => (
<InputSlider
id="temperature"
label="Temperature"
value={field.value}
onChange={field.onChange}
min={0}
max={2}
step={0.1}
error={errors.temperature?.message as string}
tooltip="Controls randomness in responses. Lower values are more focused, higher values are more creative."
/>
)}
/>
<Controller
name="enableThinking"
control={control}
render={({ field }) => (
<InputCheckbox
id="enable-thinking"
label="Enable Thinking"
description="Allow the model to show its reasoning process (only if supported by the model)"
checked={field.value}
onChange={field.onChange}
error={errors.enableThinking?.message as string}
/>
)}
/>
<Button type="submit">Start Conversation</Button>
</form>
);
}