Add language assistant settings and related features: Introduce new routes and controller methods for managing language assistant settings, including retrieval and saving of LLM configurations. Update navigation structure to include language assistant options. Enhance vocab course model to support additional learning attributes such as learning goals and core patterns. Update SQL scripts to reflect new database schema changes for vocab courses. Improve localization for language assistant settings in German and English.
This commit is contained in:
@@ -10,7 +10,6 @@ import InterestTranslation from '../models/type/interest_translation.js';
|
||||
import { Op } from 'sequelize';
|
||||
import UserParamVisibilityType from '../models/type/user_param_visibility.js';
|
||||
import UserParamVisibility from '../models/community/user_param_visibility.js';
|
||||
import { generateIv } from '../utils/encryption.js';
|
||||
|
||||
class SettingsService extends BaseService{
|
||||
async getUserParams(userId, paramDescriptions) {
|
||||
@@ -381,6 +380,129 @@ class SettingsService extends BaseService{
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* LLM-/Sprachassistent: Werte in community.user_param, Typen in type.user_param,
|
||||
* Gruppe type.settings.name = languageAssistant. API-Key separat (llm_api_key), Metadaten als JSON in llm_settings.
|
||||
* Kein Klartext-Key an den Client.
|
||||
*/
|
||||
async getLlmSettings(hashedUserId) {
|
||||
const user = await this.getUserByHashedId(hashedUserId);
|
||||
const settingsType = await UserParamType.findOne({ where: { description: 'llm_settings' } });
|
||||
const apiKeyType = await UserParamType.findOne({ where: { description: 'llm_api_key' } });
|
||||
if (!settingsType || !apiKeyType) {
|
||||
return {
|
||||
enabled: true,
|
||||
baseUrl: '',
|
||||
model: 'gpt-4o-mini',
|
||||
hasKey: false,
|
||||
keyLast4: null
|
||||
};
|
||||
}
|
||||
|
||||
const settingsRow = await UserParam.findOne({
|
||||
where: { userId: user.id, paramTypeId: settingsType.id }
|
||||
});
|
||||
const keyRow = await UserParam.findOne({
|
||||
where: { userId: user.id, paramTypeId: apiKeyType.id }
|
||||
});
|
||||
|
||||
let parsed = {};
|
||||
if (settingsRow?.value) {
|
||||
try {
|
||||
parsed = JSON.parse(settingsRow.value);
|
||||
} catch {
|
||||
parsed = {};
|
||||
}
|
||||
}
|
||||
|
||||
const hasKey = Boolean(keyRow && keyRow.value && String(keyRow.value).trim());
|
||||
|
||||
return {
|
||||
enabled: parsed.enabled !== false,
|
||||
baseUrl: parsed.baseUrl || '',
|
||||
model: parsed.model || 'gpt-4o-mini',
|
||||
hasKey,
|
||||
keyLast4: parsed.keyLast4 || null
|
||||
};
|
||||
}
|
||||
|
||||
async saveLlmSettings(hashedUserId, payload) {
|
||||
const user = await this.getUserByHashedId(hashedUserId);
|
||||
const settingsType = await UserParamType.findOne({ where: { description: 'llm_settings' } });
|
||||
const apiKeyType = await UserParamType.findOne({ where: { description: 'llm_api_key' } });
|
||||
if (!settingsType || !apiKeyType) {
|
||||
throw new Error(
|
||||
'LLM-Einstellungstypen fehlen (languageAssistant / llm_settings / llm_api_key). initializeSettings & initializeTypes ausführen.'
|
||||
);
|
||||
}
|
||||
|
||||
const settingsRow = await UserParam.findOne({
|
||||
where: { userId: user.id, paramTypeId: settingsType.id }
|
||||
});
|
||||
let parsed = {};
|
||||
if (settingsRow?.value) {
|
||||
try {
|
||||
parsed = JSON.parse(settingsRow.value);
|
||||
} catch {
|
||||
parsed = {};
|
||||
}
|
||||
}
|
||||
|
||||
const { apiKey, clearKey, baseUrl, model, enabled } = payload;
|
||||
|
||||
if (clearKey) {
|
||||
const keyRow = await UserParam.findOne({
|
||||
where: { userId: user.id, paramTypeId: apiKeyType.id }
|
||||
});
|
||||
if (keyRow) {
|
||||
await keyRow.destroy();
|
||||
}
|
||||
delete parsed.keyLast4;
|
||||
} else if (apiKey !== undefined && String(apiKey).trim() !== '') {
|
||||
const plain = String(apiKey).trim();
|
||||
parsed.keyLast4 = plain.length >= 4 ? plain.slice(-4) : plain;
|
||||
const [keyRow, keyCreated] = await UserParam.findOrCreate({
|
||||
where: { userId: user.id, paramTypeId: apiKeyType.id },
|
||||
defaults: {
|
||||
userId: user.id,
|
||||
paramTypeId: apiKeyType.id,
|
||||
value: plain
|
||||
}
|
||||
});
|
||||
if (!keyCreated) {
|
||||
await keyRow.update({ value: plain });
|
||||
}
|
||||
}
|
||||
|
||||
if (baseUrl !== undefined) {
|
||||
parsed.baseUrl = String(baseUrl).trim();
|
||||
}
|
||||
if (model !== undefined) {
|
||||
parsed.model = String(model).trim() || 'gpt-4o-mini';
|
||||
}
|
||||
if (enabled !== undefined) {
|
||||
parsed.enabled = Boolean(enabled);
|
||||
}
|
||||
if (!parsed.model) {
|
||||
parsed.model = 'gpt-4o-mini';
|
||||
}
|
||||
|
||||
const jsonStr = JSON.stringify(parsed);
|
||||
const [metaRow, metaCreated] = await UserParam.findOrCreate({
|
||||
where: { userId: user.id, paramTypeId: settingsType.id },
|
||||
defaults: {
|
||||
userId: user.id,
|
||||
paramTypeId: settingsType.id,
|
||||
value: jsonStr
|
||||
}
|
||||
});
|
||||
if (!metaCreated) {
|
||||
await metaRow.update({ value: jsonStr });
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
}
|
||||
|
||||
export default new SettingsService();
|
||||
|
||||
Reference in New Issue
Block a user