diff --git a/src/GeneralSettings.jsx b/src/GeneralSettings.jsx index be962dc..e1d7a33 100644 --- a/src/GeneralSettings.jsx +++ b/src/GeneralSettings.jsx @@ -11,6 +11,7 @@ import desktopApi from './desktop/desktopApi'; const EMBED_MODEL_KEY = 'embedModel'; const RERANK_MODEL_KEY = 'rerankModel'; +const ENRICHMENT_MODEL_KEY = 'enrichmentModel'; const MODEL_KEY = 'chatModel'; const VISION_MODEL_KEY = 'visionModel'; const TRANSCRIPTION_MODEL_KEY = 'transcriptionModel'; @@ -18,6 +19,7 @@ const DEFAULT_AUDIO_INPUT_DEVICE_ID = ''; const DEFAULT_AUDIO_INPUT_LANGUAGE = ''; const DEFAULT_BACKEND_API_URL = 'http://127.0.0.1:8000'; const DEFAULT_EMBED_MODEL = 'nomic-embed-text:latest'; +const DEFAULT_ENRICHMENT_MODEL = 'qwen3:4b'; const DEFAULT_TRANSCRIPTION_MODEL = 'base'; const DEFAULT_UPDATE_STATUS = { state: 'idle', @@ -79,6 +81,7 @@ export default function GeneralSettings({ const [backendApiUrl, setBackendApiUrl] = useState(''); const [embedModel, setEmbedModel] = useState(DEFAULT_EMBED_MODEL); const [rerankModel, setRerankModel] = useState(DEFAULT_EMBED_MODEL); + const [enrichmentModel, setEnrichmentModel] = useState(DEFAULT_ENRICHMENT_MODEL); const [chatModels, setChatModels] = useState([]); const [embeddingModels, setEmbeddingModels] = useState([]); const [visionModels, setVisionModels] = useState([]); @@ -120,6 +123,7 @@ export default function GeneralSettings({ setBackendApiUrl(resolveBackendApiUrl(settings)); setEmbedModel(settings.embedModel || DEFAULT_EMBED_MODEL); setRerankModel(settings.rerankModel || settings.embedModel || DEFAULT_EMBED_MODEL); + setEnrichmentModel(settings.enrichmentModel || DEFAULT_ENRICHMENT_MODEL); setSelectedModel(settings.chatModel || ''); setVisionModel(settings.visionModel || settings.chatModel || ''); setTranscriptionModel(settings.transcriptionModel || DEFAULT_TRANSCRIPTION_MODEL); @@ -271,6 +275,15 @@ export default function GeneralSettings({ desktopApi.setSetting(RERANK_MODEL_KEY, nextModel); }, [rerankingModels, rerankModel, embedModel, panel, settingsHydrated]); + useEffect(() => { + if (panel !== 'AI Models' || !settingsHydrated || enrichmentModel) { + return; + } + const nextModel = chatModels[0] || DEFAULT_ENRICHMENT_MODEL; + setEnrichmentModel(nextModel); + desktopApi.setSetting(ENRICHMENT_MODEL_KEY, nextModel); + }, [chatModels, enrichmentModel, panel, settingsHydrated]); + useEffect(() => { if (panel !== 'AI Models') { return; @@ -388,6 +401,12 @@ export default function GeneralSettings({ desktopApi.setSetting(RERANK_MODEL_KEY, nextModel); }; + const handleEnrichmentModelChange = (event) => { + const nextModel = event.target.value; + setEnrichmentModel(nextModel); + desktopApi.setSetting(ENRICHMENT_MODEL_KEY, nextModel); + }; + const handleTranscriptionModelChange = (event) => { const nextModel = event.target.value; setTranscriptionModel(nextModel); @@ -575,6 +594,7 @@ export default function GeneralSettings({ const visionModelOptions = buildSelectOptions(visionModels, visionModel, 'saved model unavailable', showMissingModelLabel); const embeddingModelOptions = buildSelectOptions(embeddingModels, embedModel, 'saved model unavailable', showMissingModelLabel); const rerankingModelOptions = buildSelectOptions(rerankingModels, rerankModel, 'saved model unavailable', showMissingModelLabel); + const enrichmentModelOptions = buildSelectOptions(chatModels, enrichmentModel, 'saved model unavailable', showMissingModelLabel); const transcriptionModelOptions = buildSelectOptions(whisperModels, transcriptionModel, 'saved model unavailable', showMissingModelLabel); if (panel === 'AI Models') { @@ -640,6 +660,22 @@ export default function GeneralSettings({ Heimgeist currently uses an embedding-based reranker for web search, so this should generally be an embedding-capable Ollama model.
++ Heimgeist uses this local model for summaries, keywords, entities, and optional Deep enrichment Q&A. +
+