mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-02-11 20:14:24 +01:00
📦 feat: Model & Assistants Combobox for Side Panel (#2380)
* WIP: dynamic settings * WIP: update tests and validations * refactor(SidePanel): use hook for Links * WIP: dynamic settings, slider implemented * feat(useDebouncedInput): dynamic typing with generic * refactor(generate): add `custom` optionType to be non-conforming to conversation schema * feat: DynamicDropdown * refactor(DynamicSlider): custom optionType handling and useEffect for conversation updates elsewhere * refactor(Panel): add more test cases * chore(DynamicSlider): note * refactor(useDebouncedInput): import defaultDebouncedDelay from ~/common` * WIP: implement remaining ComponentTypes * chore: add com_sidepanel_parameters * refactor: add langCode handling for dynamic settings * chore(useOriginNavigate): change path to '/c/' * refactor: explicit textarea focus on new convo, share textarea idea via ~/common * refactor: useParameterEffects: reset if convo or preset Ids change, share and maintain statefulness in side panel * wip: combobox * chore: minor styling for Select components * wip: combobox select styling for side panel * feat: complete combobox * refactor: model select for side panel switcher * refactor(Combobox): add portal * chore: comment out dynamic parameters panel for future PR and delete prompt files * refactor(Combobox): add icon field for options, change hover bg-color, add displayValue * fix(useNewConvo): proper textarea focus with setTimeout * refactor(AssistantSwitcher): use Combobox * refactor(ModelSwitcher): add textarea focus on model switch
This commit is contained in:
parent
f64a2cb0b0
commit
8e5f1ad575
33 changed files with 2850 additions and 462 deletions
474
packages/data-provider/src/generate.ts
Normal file
474
packages/data-provider/src/generate.ts
Normal file
|
|
@ -0,0 +1,474 @@
|
|||
import { z, ZodError, ZodIssueCode } from 'zod';
|
||||
import { tConversationSchema, googleSettings as google, openAISettings as openAI } from './schemas';
|
||||
import type { ZodIssue } from 'zod';
|
||||
import type { TConversation, TSetOption } from './schemas';
|
||||
|
||||
export type GoogleSettings = Partial<typeof google>;
|
||||
export type OpenAISettings = Partial<typeof google>;
|
||||
|
||||
export type ComponentType = 'input' | 'textarea' | 'slider' | 'checkbox' | 'switch' | 'dropdown';
|
||||
|
||||
export type OptionType = 'conversation' | 'model' | 'custom';
|
||||
|
||||
export enum ComponentTypes {
|
||||
Input = 'input',
|
||||
Textarea = 'textarea',
|
||||
Slider = 'slider',
|
||||
Checkbox = 'checkbox',
|
||||
Switch = 'switch',
|
||||
Dropdown = 'dropdown',
|
||||
}
|
||||
|
||||
export enum OptionTypes {
|
||||
Conversation = 'conversation',
|
||||
Model = 'model',
|
||||
Custom = 'custom',
|
||||
}
|
||||
export interface SettingDefinition {
|
||||
key: string;
|
||||
description?: string;
|
||||
type: 'number' | 'boolean' | 'string' | 'enum';
|
||||
default?: number | boolean | string;
|
||||
showDefault?: boolean;
|
||||
options?: string[];
|
||||
range?: SettingRange;
|
||||
enumMappings?: Record<string, number | boolean | string>;
|
||||
component: ComponentType;
|
||||
optionType?: OptionType;
|
||||
columnSpan?: number;
|
||||
columns?: number;
|
||||
label?: string;
|
||||
placeholder?: string;
|
||||
labelCode?: boolean;
|
||||
placeholderCode?: boolean;
|
||||
descriptionCode?: boolean;
|
||||
minText?: number;
|
||||
maxText?: number;
|
||||
includeInput?: boolean; // Specific to slider component
|
||||
}
|
||||
|
||||
export type DynamicSettingProps = Partial<SettingDefinition> & {
|
||||
readonly?: boolean;
|
||||
settingKey: string;
|
||||
setOption: TSetOption;
|
||||
defaultValue?: number | boolean | string;
|
||||
};
|
||||
|
||||
const requiredSettingFields = ['key', 'type', 'component'];
|
||||
|
||||
export interface SettingRange {
|
||||
min: number;
|
||||
max: number;
|
||||
step?: number;
|
||||
}
|
||||
|
||||
export type SettingsConfiguration = SettingDefinition[];
|
||||
|
||||
export function generateDynamicSchema(settings: SettingsConfiguration) {
|
||||
const schemaFields: { [key: string]: z.ZodTypeAny } = {};
|
||||
|
||||
for (const setting of settings) {
|
||||
const { key, type, default: defaultValue, range, options, minText, maxText } = setting;
|
||||
|
||||
if (type === 'number') {
|
||||
let schema = z.number();
|
||||
if (range) {
|
||||
schema = schema.min(range.min);
|
||||
schema = schema.max(range.max);
|
||||
}
|
||||
if (typeof defaultValue === 'number') {
|
||||
schemaFields[key] = schema.default(defaultValue);
|
||||
} else {
|
||||
schemaFields[key] = schema;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type === 'boolean') {
|
||||
const schema = z.boolean();
|
||||
if (typeof defaultValue === 'boolean') {
|
||||
schemaFields[key] = schema.default(defaultValue);
|
||||
} else {
|
||||
schemaFields[key] = schema;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type === 'string') {
|
||||
let schema = z.string();
|
||||
if (minText) {
|
||||
schema = schema.min(minText);
|
||||
}
|
||||
if (maxText) {
|
||||
schema = schema.max(maxText);
|
||||
}
|
||||
if (typeof defaultValue === 'string') {
|
||||
schemaFields[key] = schema.default(defaultValue);
|
||||
} else {
|
||||
schemaFields[key] = schema;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type === 'enum') {
|
||||
if (!options || options.length === 0) {
|
||||
console.warn(`Missing or empty 'options' for enum setting '${key}'.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const schema = z.enum(options as [string, ...string[]]);
|
||||
if (typeof defaultValue === 'string') {
|
||||
schemaFields[key] = schema.default(defaultValue);
|
||||
} else {
|
||||
schemaFields[key] = schema;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
console.warn(`Unsupported setting type: ${type}`);
|
||||
}
|
||||
|
||||
return z.object(schemaFields);
|
||||
}
|
||||
|
||||
const ZodTypeToSettingType: Record<string, string | undefined> = {
|
||||
ZodString: 'string',
|
||||
ZodNumber: 'number',
|
||||
ZodBoolean: 'boolean',
|
||||
};
|
||||
|
||||
const minColumns = 1;
|
||||
const maxColumns = 4;
|
||||
const minSliderOptions = 2;
|
||||
const minDropdownOptions = 2;
|
||||
|
||||
/**
|
||||
* Validates the provided setting using the constraints unique to each component type.
|
||||
* @throws {ZodError} Throws a ZodError if any validation fails.
|
||||
*/
|
||||
export function validateSettingDefinitions(settings: SettingsConfiguration): void {
|
||||
const errors: ZodIssue[] = [];
|
||||
// Validate columns
|
||||
const columnsSet = new Set<number>();
|
||||
for (const setting of settings) {
|
||||
if (setting.columns !== undefined) {
|
||||
if (setting.columns < minColumns || setting.columns > maxColumns) {
|
||||
errors.push({
|
||||
code: ZodIssueCode.custom,
|
||||
message: `Invalid columns value for setting ${setting.key}. Must be between ${minColumns} and ${maxColumns}.`,
|
||||
path: ['columns'],
|
||||
});
|
||||
} else {
|
||||
columnsSet.add(setting.columns);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const columns = columnsSet.size === 1 ? columnsSet.values().next().value : 2;
|
||||
|
||||
for (const setting of settings) {
|
||||
for (const field of requiredSettingFields) {
|
||||
if (setting[field as keyof SettingDefinition] === undefined) {
|
||||
errors.push({
|
||||
code: ZodIssueCode.custom,
|
||||
message: `Missing required field ${field} for setting ${setting.key}.`,
|
||||
path: [field],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// check accepted types
|
||||
if (!['number', 'boolean', 'string', 'enum'].includes(setting.type)) {
|
||||
errors.push({
|
||||
code: ZodIssueCode.custom,
|
||||
message: `Invalid type for setting ${setting.key}. Must be one of 'number', 'boolean', 'string', 'enum'.`,
|
||||
path: ['type'],
|
||||
});
|
||||
}
|
||||
|
||||
// Predefined constraints based on components
|
||||
if (setting.component === 'input' || setting.component === 'textarea') {
|
||||
if (setting.type === 'number' && setting.component === 'textarea') {
|
||||
errors.push({
|
||||
code: ZodIssueCode.custom,
|
||||
message: `Textarea component for setting ${setting.key} must have type string.`,
|
||||
path: ['type'],
|
||||
});
|
||||
// continue;
|
||||
}
|
||||
|
||||
if (
|
||||
setting.minText !== undefined &&
|
||||
setting.maxText !== undefined &&
|
||||
setting.minText > setting.maxText
|
||||
) {
|
||||
errors.push({
|
||||
code: ZodIssueCode.custom,
|
||||
message: `For setting ${setting.key}, minText cannot be greater than maxText.`,
|
||||
path: [setting.key, 'minText', 'maxText'],
|
||||
});
|
||||
// continue;
|
||||
}
|
||||
if (!setting.placeholder) {
|
||||
setting.placeholder = '';
|
||||
} // Default placeholder
|
||||
}
|
||||
|
||||
if (setting.component === 'slider') {
|
||||
if (setting.type === 'number' && !setting.range) {
|
||||
errors.push({
|
||||
code: ZodIssueCode.custom,
|
||||
message: `Slider component for setting ${setting.key} must have a range if type is number.`,
|
||||
path: ['range'],
|
||||
});
|
||||
// continue;
|
||||
}
|
||||
if (
|
||||
setting.type === 'enum' &&
|
||||
(!setting.options || setting.options.length < minSliderOptions)
|
||||
) {
|
||||
errors.push({
|
||||
code: ZodIssueCode.custom,
|
||||
message: `Slider component for setting ${setting.key} requires at least ${minSliderOptions} options for enum type.`,
|
||||
path: ['options'],
|
||||
});
|
||||
// continue;
|
||||
}
|
||||
setting.includeInput = setting.type === 'number' ? setting.includeInput ?? true : false; // Default to true if type is number
|
||||
}
|
||||
|
||||
if (setting.component === 'slider' && setting.type === 'number') {
|
||||
if (setting.default === undefined && setting.range) {
|
||||
// Set default to the middle of the range if unspecified
|
||||
setting.default = Math.round((setting.range.min + setting.range.max) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
if (setting.component === 'checkbox' || setting.component === 'switch') {
|
||||
if (setting.options && setting.options.length > 2) {
|
||||
errors.push({
|
||||
code: ZodIssueCode.custom,
|
||||
message: `Checkbox/Switch component for setting ${setting.key} must have 1-2 options.`,
|
||||
path: ['options'],
|
||||
});
|
||||
// continue;
|
||||
}
|
||||
if (!setting.default && setting.type === 'boolean') {
|
||||
setting.default = false; // Default to false if type is boolean
|
||||
}
|
||||
}
|
||||
|
||||
if (setting.component === 'dropdown') {
|
||||
if (!setting.options || setting.options.length < minDropdownOptions) {
|
||||
errors.push({
|
||||
code: ZodIssueCode.custom,
|
||||
message: `Dropdown component for setting ${setting.key} requires at least ${minDropdownOptions} options.`,
|
||||
path: ['options'],
|
||||
});
|
||||
// continue;
|
||||
}
|
||||
if (!setting.default && setting.options && setting.options.length > 0) {
|
||||
setting.default = setting.options[0]; // Default to first option if not specified
|
||||
}
|
||||
}
|
||||
|
||||
// Default columnSpan
|
||||
if (!setting.columnSpan) {
|
||||
setting.columnSpan = Math.floor(columns / 2);
|
||||
}
|
||||
|
||||
// Default label to key
|
||||
if (!setting.label) {
|
||||
setting.label = setting.key;
|
||||
}
|
||||
|
||||
// Validate minText and maxText for input/textarea
|
||||
if (setting.component === 'input' || setting.component === 'textarea') {
|
||||
if (setting.minText !== undefined && setting.minText < 0) {
|
||||
errors.push({
|
||||
code: ZodIssueCode.custom,
|
||||
message: `Invalid minText value for setting ${setting.key}. Must be non-negative.`,
|
||||
path: ['minText'],
|
||||
});
|
||||
}
|
||||
if (setting.maxText !== undefined && setting.maxText < 0) {
|
||||
errors.push({
|
||||
code: ZodIssueCode.custom,
|
||||
message: `Invalid maxText value for setting ${setting.key}. Must be non-negative.`,
|
||||
path: ['maxText'],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Validate optionType and conversation schema
|
||||
if (setting.optionType !== OptionTypes.Custom) {
|
||||
const conversationSchema = tConversationSchema.shape[setting.key as keyof TConversation];
|
||||
if (!conversationSchema) {
|
||||
errors.push({
|
||||
code: ZodIssueCode.custom,
|
||||
message: `Setting ${setting.key} with optionType "${setting.optionType}" must be defined in tConversationSchema.`,
|
||||
path: ['optionType'],
|
||||
});
|
||||
} else {
|
||||
const zodType = conversationSchema._def.typeName;
|
||||
const settingTypeEquivalent = ZodTypeToSettingType[zodType] || null;
|
||||
if (settingTypeEquivalent !== setting.type) {
|
||||
errors.push({
|
||||
code: ZodIssueCode.custom,
|
||||
message: `Setting ${setting.key} with optionType "${setting.optionType}" must match the type defined in tConversationSchema.`,
|
||||
path: ['optionType'],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Default value checks */
|
||||
if (setting.type === 'number' && isNaN(setting.default as number)) {
|
||||
errors.push({
|
||||
code: ZodIssueCode.custom,
|
||||
message: `Invalid default value for setting ${setting.key}. Must be a number.`,
|
||||
path: ['default'],
|
||||
});
|
||||
}
|
||||
|
||||
if (setting.type === 'boolean' && typeof setting.default !== 'boolean') {
|
||||
errors.push({
|
||||
code: ZodIssueCode.custom,
|
||||
message: `Invalid default value for setting ${setting.key}. Must be a boolean.`,
|
||||
path: ['default'],
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
(setting.type === 'string' || setting.type === 'enum') &&
|
||||
typeof setting.default !== 'string'
|
||||
) {
|
||||
errors.push({
|
||||
code: ZodIssueCode.custom,
|
||||
message: `Invalid default value for setting ${setting.key}. Must be a string.`,
|
||||
path: ['default'],
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
setting.type === 'enum' &&
|
||||
setting.options &&
|
||||
!setting.options.includes(setting.default as string)
|
||||
) {
|
||||
errors.push({
|
||||
code: ZodIssueCode.custom,
|
||||
message: `Invalid default value for setting ${
|
||||
setting.key
|
||||
}. Must be one of the options: [${setting.options.join(', ')}].`,
|
||||
path: ['default'],
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
setting.type === 'number' &&
|
||||
setting.range &&
|
||||
typeof setting.default === 'number' &&
|
||||
(setting.default < setting.range.min || setting.default > setting.range.max)
|
||||
) {
|
||||
errors.push({
|
||||
code: ZodIssueCode.custom,
|
||||
message: `Invalid default value for setting ${setting.key}. Must be within the range [${setting.range.min}, ${setting.range.max}].`,
|
||||
path: ['default'],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
throw new ZodError(errors);
|
||||
}
|
||||
}
|
||||
|
||||
export const generateOpenAISchema = (customOpenAI: OpenAISettings) => {
|
||||
const defaults = { ...openAI, ...customOpenAI };
|
||||
return tConversationSchema
|
||||
.pick({
|
||||
model: true,
|
||||
chatGptLabel: true,
|
||||
promptPrefix: true,
|
||||
temperature: true,
|
||||
top_p: true,
|
||||
presence_penalty: true,
|
||||
frequency_penalty: true,
|
||||
resendFiles: true,
|
||||
imageDetail: true,
|
||||
})
|
||||
.transform((obj) => ({
|
||||
...obj,
|
||||
model: obj.model ?? defaults.model.default,
|
||||
chatGptLabel: obj.chatGptLabel ?? null,
|
||||
promptPrefix: obj.promptPrefix ?? null,
|
||||
temperature: obj.temperature ?? defaults.temperature.default,
|
||||
top_p: obj.top_p ?? defaults.top_p.default,
|
||||
presence_penalty: obj.presence_penalty ?? defaults.presence_penalty.default,
|
||||
frequency_penalty: obj.frequency_penalty ?? defaults.frequency_penalty.default,
|
||||
resendFiles:
|
||||
typeof obj.resendFiles === 'boolean' ? obj.resendFiles : defaults.resendFiles.default,
|
||||
imageDetail: obj.imageDetail ?? defaults.imageDetail.default,
|
||||
}))
|
||||
.catch(() => ({
|
||||
model: defaults.model.default,
|
||||
chatGptLabel: null,
|
||||
promptPrefix: null,
|
||||
temperature: defaults.temperature.default,
|
||||
top_p: defaults.top_p.default,
|
||||
presence_penalty: defaults.presence_penalty.default,
|
||||
frequency_penalty: defaults.frequency_penalty.default,
|
||||
resendFiles: defaults.resendFiles.default,
|
||||
imageDetail: defaults.imageDetail.default,
|
||||
}));
|
||||
};
|
||||
|
||||
export const generateGoogleSchema = (customGoogle: GoogleSettings) => {
|
||||
const defaults = { ...google, ...customGoogle };
|
||||
return tConversationSchema
|
||||
.pick({
|
||||
model: true,
|
||||
modelLabel: true,
|
||||
promptPrefix: true,
|
||||
examples: true,
|
||||
temperature: true,
|
||||
maxOutputTokens: true,
|
||||
topP: true,
|
||||
topK: true,
|
||||
})
|
||||
.transform((obj) => {
|
||||
const isGeminiPro = obj?.model?.toLowerCase()?.includes('gemini-pro');
|
||||
|
||||
const maxOutputTokensMax = isGeminiPro
|
||||
? defaults.maxOutputTokens.maxGeminiPro
|
||||
: defaults.maxOutputTokens.max;
|
||||
const maxOutputTokensDefault = isGeminiPro
|
||||
? defaults.maxOutputTokens.defaultGeminiPro
|
||||
: defaults.maxOutputTokens.default;
|
||||
|
||||
let maxOutputTokens = obj.maxOutputTokens ?? maxOutputTokensDefault;
|
||||
maxOutputTokens = Math.min(maxOutputTokens, maxOutputTokensMax);
|
||||
|
||||
return {
|
||||
...obj,
|
||||
model: obj.model ?? defaults.model.default,
|
||||
modelLabel: obj.modelLabel ?? null,
|
||||
promptPrefix: obj.promptPrefix ?? null,
|
||||
examples: obj.examples ?? [{ input: { content: '' }, output: { content: '' } }],
|
||||
temperature: obj.temperature ?? defaults.temperature.default,
|
||||
maxOutputTokens,
|
||||
topP: obj.topP ?? defaults.topP.default,
|
||||
topK: obj.topK ?? defaults.topK.default,
|
||||
};
|
||||
})
|
||||
.catch(() => ({
|
||||
model: defaults.model.default,
|
||||
modelLabel: null,
|
||||
promptPrefix: null,
|
||||
examples: [{ input: { content: '' }, output: { content: '' } }],
|
||||
temperature: defaults.temperature.default,
|
||||
maxOutputTokens: defaults.maxOutputTokens.default,
|
||||
topP: defaults.topP.default,
|
||||
topK: defaults.topK.default,
|
||||
}));
|
||||
};
|
||||
|
|
@ -4,6 +4,7 @@ export * from './config';
|
|||
export * from './file-config';
|
||||
/* schema helpers */
|
||||
export * from './parsers';
|
||||
export * from './generate';
|
||||
/* types (exports schemas from `./types` as they contain needed in other defs) */
|
||||
export * from './types';
|
||||
export * from './types/assistants';
|
||||
|
|
|
|||
|
|
@ -17,6 +17,26 @@ export enum EModelEndpoint {
|
|||
custom = 'custom',
|
||||
}
|
||||
|
||||
export enum ImageDetail {
|
||||
low = 'low',
|
||||
auto = 'auto',
|
||||
high = 'high',
|
||||
}
|
||||
|
||||
export const imageDetailNumeric = {
|
||||
[ImageDetail.low]: 0,
|
||||
[ImageDetail.auto]: 1,
|
||||
[ImageDetail.high]: 2,
|
||||
};
|
||||
|
||||
export const imageDetailValue = {
|
||||
0: ImageDetail.low,
|
||||
1: ImageDetail.auto,
|
||||
2: ImageDetail.high,
|
||||
};
|
||||
|
||||
export const eImageDetailSchema = z.nativeEnum(ImageDetail);
|
||||
|
||||
export const defaultAssistantFormValues = {
|
||||
assistant: '',
|
||||
id: '',
|
||||
|
|
@ -46,38 +66,77 @@ export const ImageVisionTool: FunctionTool = {
|
|||
export const isImageVisionTool = (tool: FunctionTool | FunctionToolCall) =>
|
||||
tool.type === 'function' && tool.function?.name === ImageVisionTool?.function?.name;
|
||||
|
||||
export const endpointSettings = {
|
||||
[EModelEndpoint.google]: {
|
||||
model: {
|
||||
default: 'chat-bison',
|
||||
},
|
||||
maxOutputTokens: {
|
||||
min: 1,
|
||||
max: 2048,
|
||||
step: 1,
|
||||
default: 1024,
|
||||
maxGeminiPro: 8192,
|
||||
defaultGeminiPro: 8192,
|
||||
},
|
||||
temperature: {
|
||||
min: 0,
|
||||
max: 1,
|
||||
step: 0.01,
|
||||
default: 0.2,
|
||||
},
|
||||
topP: {
|
||||
min: 0,
|
||||
max: 1,
|
||||
step: 0.01,
|
||||
default: 0.8,
|
||||
},
|
||||
topK: {
|
||||
min: 1,
|
||||
max: 40,
|
||||
step: 0.01,
|
||||
default: 40,
|
||||
},
|
||||
export const openAISettings = {
|
||||
model: {
|
||||
default: 'gpt-3.5-turbo',
|
||||
},
|
||||
temperature: {
|
||||
min: 0,
|
||||
max: 1,
|
||||
step: 0.01,
|
||||
default: 1,
|
||||
},
|
||||
top_p: {
|
||||
min: 0,
|
||||
max: 1,
|
||||
step: 0.01,
|
||||
default: 1,
|
||||
},
|
||||
presence_penalty: {
|
||||
min: 0,
|
||||
max: 2,
|
||||
step: 0.01,
|
||||
default: 0,
|
||||
},
|
||||
frequency_penalty: {
|
||||
min: 0,
|
||||
max: 2,
|
||||
step: 0.01,
|
||||
default: 0,
|
||||
},
|
||||
resendFiles: {
|
||||
default: true,
|
||||
},
|
||||
imageDetail: {
|
||||
default: ImageDetail.auto,
|
||||
},
|
||||
};
|
||||
|
||||
export const googleSettings = {
|
||||
model: {
|
||||
default: 'chat-bison',
|
||||
},
|
||||
maxOutputTokens: {
|
||||
min: 1,
|
||||
max: 2048,
|
||||
step: 1,
|
||||
default: 1024,
|
||||
maxGeminiPro: 8192,
|
||||
defaultGeminiPro: 8192,
|
||||
},
|
||||
temperature: {
|
||||
min: 0,
|
||||
max: 1,
|
||||
step: 0.01,
|
||||
default: 0.2,
|
||||
},
|
||||
topP: {
|
||||
min: 0,
|
||||
max: 1,
|
||||
step: 0.01,
|
||||
default: 0.8,
|
||||
},
|
||||
topK: {
|
||||
min: 1,
|
||||
max: 40,
|
||||
step: 0.01,
|
||||
default: 40,
|
||||
},
|
||||
};
|
||||
|
||||
export const endpointSettings = {
|
||||
[EModelEndpoint.openAI]: openAISettings,
|
||||
[EModelEndpoint.google]: googleSettings,
|
||||
};
|
||||
|
||||
const google = endpointSettings[EModelEndpoint.google];
|
||||
|
|
@ -86,26 +145,6 @@ export const eModelEndpointSchema = z.nativeEnum(EModelEndpoint);
|
|||
|
||||
export const extendedModelEndpointSchema = z.union([eModelEndpointSchema, z.string()]);
|
||||
|
||||
export enum ImageDetail {
|
||||
low = 'low',
|
||||
auto = 'auto',
|
||||
high = 'high',
|
||||
}
|
||||
|
||||
export const imageDetailNumeric = {
|
||||
[ImageDetail.low]: 0,
|
||||
[ImageDetail.auto]: 1,
|
||||
[ImageDetail.high]: 2,
|
||||
};
|
||||
|
||||
export const imageDetailValue = {
|
||||
0: ImageDetail.low,
|
||||
1: ImageDetail.auto,
|
||||
2: ImageDetail.high,
|
||||
};
|
||||
|
||||
export const eImageDetailSchema = z.nativeEnum(ImageDetail);
|
||||
|
||||
export const tPluginAuthConfigSchema = z.object({
|
||||
authField: z.string(),
|
||||
label: z.string(),
|
||||
|
|
@ -278,12 +317,14 @@ export const tPresetUpdateSchema = tConversationSchema.merge(
|
|||
|
||||
export type TPreset = z.infer<typeof tPresetSchema>;
|
||||
|
||||
export type TSetOption = (
|
||||
param: number | string,
|
||||
) => (newValue: number | string | boolean | Partial<TPreset>) => void;
|
||||
|
||||
export type TConversation = z.infer<typeof tConversationSchema> & {
|
||||
presetOverride?: Partial<TPreset>;
|
||||
};
|
||||
|
||||
// type DefaultSchemaValues = Partial<typeof google>;
|
||||
|
||||
export const openAISchema = tConversationSchema
|
||||
.pick({
|
||||
model: true,
|
||||
|
|
@ -298,26 +339,27 @@ export const openAISchema = tConversationSchema
|
|||
})
|
||||
.transform((obj) => ({
|
||||
...obj,
|
||||
model: obj.model ?? 'gpt-3.5-turbo',
|
||||
model: obj.model ?? openAISettings.model.default,
|
||||
chatGptLabel: obj.chatGptLabel ?? null,
|
||||
promptPrefix: obj.promptPrefix ?? null,
|
||||
temperature: obj.temperature ?? 1,
|
||||
top_p: obj.top_p ?? 1,
|
||||
presence_penalty: obj.presence_penalty ?? 0,
|
||||
frequency_penalty: obj.frequency_penalty ?? 0,
|
||||
resendFiles: typeof obj.resendFiles === 'boolean' ? obj.resendFiles : true,
|
||||
imageDetail: obj.imageDetail ?? ImageDetail.auto,
|
||||
temperature: obj.temperature ?? openAISettings.temperature.default,
|
||||
top_p: obj.top_p ?? openAISettings.top_p.default,
|
||||
presence_penalty: obj.presence_penalty ?? openAISettings.presence_penalty.default,
|
||||
frequency_penalty: obj.frequency_penalty ?? openAISettings.frequency_penalty.default,
|
||||
resendFiles:
|
||||
typeof obj.resendFiles === 'boolean' ? obj.resendFiles : openAISettings.resendFiles.default,
|
||||
imageDetail: obj.imageDetail ?? openAISettings.imageDetail.default,
|
||||
}))
|
||||
.catch(() => ({
|
||||
model: 'gpt-3.5-turbo',
|
||||
model: openAISettings.model.default,
|
||||
chatGptLabel: null,
|
||||
promptPrefix: null,
|
||||
temperature: 1,
|
||||
top_p: 1,
|
||||
presence_penalty: 0,
|
||||
frequency_penalty: 0,
|
||||
resendFiles: true,
|
||||
imageDetail: ImageDetail.auto,
|
||||
temperature: openAISettings.temperature.default,
|
||||
top_p: openAISettings.top_p.default,
|
||||
presence_penalty: openAISettings.presence_penalty.default,
|
||||
frequency_penalty: openAISettings.frequency_penalty.default,
|
||||
resendFiles: openAISettings.resendFiles.default,
|
||||
imageDetail: openAISettings.imageDetail.default,
|
||||
}));
|
||||
|
||||
export const googleSchema = tConversationSchema
|
||||
|
|
@ -674,53 +716,3 @@ export const compactPluginsSchema = tConversationSchema
|
|||
return removeNullishValues(newObj);
|
||||
})
|
||||
.catch(() => ({}));
|
||||
|
||||
// const createGoogleSchema = (customGoogle: DefaultSchemaValues) => {
|
||||
// const defaults = { ...google, ...customGoogle };
|
||||
// return tConversationSchema
|
||||
// .pick({
|
||||
// model: true,
|
||||
// modelLabel: true,
|
||||
// promptPrefix: true,
|
||||
// examples: true,
|
||||
// temperature: true,
|
||||
// maxOutputTokens: true,
|
||||
// topP: true,
|
||||
// topK: true,
|
||||
// })
|
||||
// .transform((obj) => {
|
||||
// const isGeminiPro = obj?.model?.toLowerCase()?.includes('gemini-pro');
|
||||
|
||||
// const maxOutputTokensMax = isGeminiPro
|
||||
// ? defaults.maxOutputTokens.maxGeminiPro
|
||||
// : defaults.maxOutputTokens.max;
|
||||
// const maxOutputTokensDefault = isGeminiPro
|
||||
// ? defaults.maxOutputTokens.defaultGeminiPro
|
||||
// : defaults.maxOutputTokens.default;
|
||||
|
||||
// let maxOutputTokens = obj.maxOutputTokens ?? maxOutputTokensDefault;
|
||||
// maxOutputTokens = Math.min(maxOutputTokens, maxOutputTokensMax);
|
||||
|
||||
// return {
|
||||
// ...obj,
|
||||
// model: obj.model ?? defaults.model.default,
|
||||
// modelLabel: obj.modelLabel ?? null,
|
||||
// promptPrefix: obj.promptPrefix ?? null,
|
||||
// examples: obj.examples ?? [{ input: { content: '' }, output: { content: '' } }],
|
||||
// temperature: obj.temperature ?? defaults.temperature.default,
|
||||
// maxOutputTokens,
|
||||
// topP: obj.topP ?? defaults.topP.default,
|
||||
// topK: obj.topK ?? defaults.topK.default,
|
||||
// };
|
||||
// })
|
||||
// .catch(() => ({
|
||||
// model: defaults.model.default,
|
||||
// modelLabel: null,
|
||||
// promptPrefix: null,
|
||||
// examples: [{ input: { content: '' }, output: { content: '' } }],
|
||||
// temperature: defaults.temperature.default,
|
||||
// maxOutputTokens: defaults.maxOutputTokens.default,
|
||||
// topP: defaults.topP.default,
|
||||
// topK: defaults.topK.default,
|
||||
// }));
|
||||
// };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue