mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-09-22 08:12:00 +02:00

* feat: update useTextToSpeech and useSpeechToText hooks to support external audio endpoints This commit updates the useTextToSpeech and useSpeechToText hooks in the Input directory to support external audio endpoints. It introduces the useGetExternalTextToSpeech and useGetExternalSpeechToText hooks, which determine whether the audio endpoints should be set to 'browser' or 'external' based on the value of the endpointTTS and endpointSTT Recoil states. The useTextToSpeech and useSpeechToText hooks now use these new hooks to determine whether to use external audio endpoints * feat: add userSelect style to ConversationModeSwitch label * fix: remove unused updateTokenWebsocket function and import The updateTokenWebsocket function and its import are no longer used in the OpenAIClient module. This commit removes the function and import to clean up the codebase * feat: support external audio endpoints in useTextToSpeech and useSpeechToText hooks This commit updates the useTextToSpeech and useSpeechToText hooks in the Input directory to support external audio endpoints. It introduces the useGetExternalTextToSpeech and useGetExternalSpeechToText hooks, which determine whether the audio endpoints should be set to 'browser' or 'external' based on the value of the endpointTTS and endpointSTT Recoil states. The useTextToSpeech and useSpeechToText hooks now use these new hooks to determine whether to use external audio endpoints * feat: update AutomaticPlayback component to AutomaticPlaybackSwitch; tests: added AutomaticPlaybackSwitch.spec > > This commit renames the AutomaticPlayback component to AutomaticPlaybackSwitch in the Speech directory. The new name better reflects the purpose of the component and aligns with the naming convention used in the codebase. * feat: update useSpeechToText hook to include interimTranscript This commit updates the useSpeechToText hook in the client/src/components/Chat/Input/AudioRecorder.tsx file to include the interimTranscript state. This allows for real-time display of the speech-to-text transcription while the user is still speaking. The interimTranscript is now used to update the text area value during recording. * feat: Add customConfigSpeech API endpoint for retrieving custom speech configuration This commit adds a new API endpoint in the file under the directory. This endpoint is responsible for retrieving the custom speech configuration using the function from the module * feat: update store var and ; fix: getCustomConfigSpeech * fix: client tests, removed unused import * feat: Update useCustomConfigSpeechQuery to return an array of custom speech configurations This commit modifies the useCustomConfigSpeechQuery function in the client/src/data-provider/queries.ts file to return an array of custom speech configurations instead of a single object. This change allows for better handling and manipulation of the data in the application * feat: Update useCustomConfigSpeechQuery to return an array of custom speech configurations * refactor: Update variable name in speechTab schema * refactor: removed unused and nested code * fix: using recoilState * refactor: Update Speech component to use useCallback for setting settings * fix: test * fix: tests * feature: ensure that the settings don't change after modifying then through the UI * remove comment * fix: Handle error gracefully in getCustomConfigSpeech and getVoices endpoints * fix: Handle error * fix: backend tests * fix: invalid custom config logging * chore: add back custom config info logging * chore: revert loadCustomConfig spec --------- Co-authored-by: Danny Avila <danny@librechat.ai>
120 lines
3.7 KiB
JavaScript
120 lines
3.7 KiB
JavaScript
const path = require('path');
|
|
const { CacheKeys, configSchema, EImageOutputType } = require('librechat-data-provider');
|
|
const getLogStores = require('~/cache/getLogStores');
|
|
const loadYaml = require('~/utils/loadYaml');
|
|
const { logger } = require('~/config');
|
|
const axios = require('axios');
|
|
const yaml = require('js-yaml');
|
|
|
|
const projectRoot = path.resolve(__dirname, '..', '..', '..', '..');
|
|
const defaultConfigPath = path.resolve(projectRoot, 'librechat.yaml');
|
|
|
|
let i = 0;
|
|
|
|
/**
|
|
* Load custom configuration files and caches the object if the `cache` field at root is true.
|
|
* Validation via parsing the config file with the config schema.
|
|
* @function loadCustomConfig
|
|
* @returns {Promise<TCustomConfig | null>} A promise that resolves to null or the custom config object.
|
|
* */
|
|
async function loadCustomConfig() {
|
|
// Use CONFIG_PATH if set, otherwise fallback to defaultConfigPath
|
|
const configPath = process.env.CONFIG_PATH || defaultConfigPath;
|
|
|
|
let customConfig;
|
|
|
|
if (/^https?:\/\//.test(configPath)) {
|
|
try {
|
|
const response = await axios.get(configPath);
|
|
customConfig = response.data;
|
|
} catch (error) {
|
|
i === 0 && logger.error(`Failed to fetch the remote config file from ${configPath}`, error);
|
|
i === 0 && i++;
|
|
return null;
|
|
}
|
|
} else {
|
|
customConfig = loadYaml(configPath);
|
|
if (!customConfig) {
|
|
i === 0 &&
|
|
logger.info(
|
|
'Custom config file missing or YAML format invalid.\n\nCheck out the latest config file guide for configurable options and features.\nhttps://www.librechat.ai/docs/configuration/librechat_yaml\n\n',
|
|
);
|
|
i === 0 && i++;
|
|
return null;
|
|
}
|
|
|
|
if (customConfig.reason || customConfig.stack) {
|
|
i === 0 && logger.error('Config file YAML format is invalid:', customConfig);
|
|
i === 0 && i++;
|
|
return null;
|
|
}
|
|
}
|
|
|
|
if (typeof customConfig === 'string') {
|
|
try {
|
|
customConfig = yaml.load(customConfig);
|
|
} catch (parseError) {
|
|
i === 0 && logger.info(`Failed to parse the YAML config from ${configPath}`, parseError);
|
|
i === 0 && i++;
|
|
return null;
|
|
}
|
|
}
|
|
|
|
const result = configSchema.strict().safeParse(customConfig);
|
|
if (result?.error?.errors?.some((err) => err?.path && err.path?.includes('imageOutputType'))) {
|
|
throw new Error(
|
|
`
|
|
Please specify a correct \`imageOutputType\` value (case-sensitive).
|
|
|
|
The available options are:
|
|
- ${EImageOutputType.JPEG}
|
|
- ${EImageOutputType.PNG}
|
|
- ${EImageOutputType.WEBP}
|
|
|
|
Refer to the latest config file guide for more information:
|
|
https://www.librechat.ai/docs/configuration/librechat_yaml`,
|
|
);
|
|
}
|
|
if (!result.success) {
|
|
let errorMessage = `Invalid custom config file at ${configPath}:
|
|
${JSON.stringify(result.error, null, 2)}`;
|
|
|
|
if (i === 0) {
|
|
logger.error(errorMessage);
|
|
const speechError = result.error.errors.find(
|
|
(err) =>
|
|
err.code === 'unrecognized_keys' &&
|
|
(err.message?.includes('stt') || err.message?.includes('tts')),
|
|
);
|
|
|
|
if (speechError) {
|
|
logger.warn(`
|
|
The Speech-to-text and Text-to-speech configuration format has recently changed.
|
|
If you're getting this error, please refer to the latest documentation:
|
|
|
|
https://www.librechat.ai/docs/configuration/stt_tts`);
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
return null;
|
|
} else {
|
|
logger.info('Custom config file loaded:');
|
|
logger.info(JSON.stringify(customConfig, null, 2));
|
|
logger.debug('Custom config:', customConfig);
|
|
}
|
|
|
|
if (customConfig.cache) {
|
|
const cache = getLogStores(CacheKeys.CONFIG_STORE);
|
|
await cache.set(CacheKeys.CUSTOM_CONFIG, customConfig);
|
|
}
|
|
|
|
if (result.data.modelSpecs) {
|
|
customConfig.modelSpecs = result.data.modelSpecs;
|
|
}
|
|
|
|
return customConfig;
|
|
}
|
|
|
|
module.exports = loadCustomConfig;
|