diff --git a/main.ts b/main.ts
index d7784c9..25aee30 100644
--- a/main.ts
+++ b/main.ts
@@ -10,6 +10,8 @@ import { ReferenceParser } from './src/references/ReferenceParser';
import 'src/css/styles.css';
+import { LLM_DEFAULTS } from 'src/constants';
+
// ----------------------------------------------- Settings ---------------------------------------------------------------
interface LLMAgentSettings {
@@ -22,29 +24,38 @@ interface LLMAgentSettings {
excludedFolders: string[];
refCacheFolder: string;
+ temperatureChat: number;
+ maxTokensChatDefault: string;
+
summarizationModel: string;
voiceCommandModel: string;
logsFolder: string;
voiceInterval: number;
metricsInterval: number;
- voiceDisplayLimit: number; // 3000
- voiceContextLimit: number; // N2 символов для LLM
+ voiceDisplayLimit: number;
+ voiceContextLimit: number;
+ temperatureVoice: number;
+ maxTokensVoiceRegular: string;
+ maxTokensVoiceCommands: string;
promptRegular: string;
promptCommands: string;
promptMetrics: string;
- markerStart: string; // "старт"
- markerStop: string; // "стоп"
+ markerStart: string;
+ markerStop: string;
}
const DEFAULT_SETTINGS: LLMAgentSettings = {
apiBaseUrl: 'http://localhost:5000/api',
systemPrompt: 'Ты полезный ИИ ассистент.',
- defaultModel: 'gemini-2.5-flash-r',
- promptsFolder: 'prompts', // Папка с промптами по умолчанию
+ defaultModel: LLM_DEFAULTS.MODEL,
+ promptsFolder: 'prompts',
enableFileReferences: true,
enablePromptReferences: true,
- excludedFolders: ['.obsidian', 'llm-agent-backend', 'templates', 'ref-cache'], // Папка "templates" по умолчанию исключена
- refCacheFolder: 'ref-cache', // По умолчанию относительно vault
+ excludedFolders: ['.obsidian', 'llm-agent-backend', 'templates', 'ref-cache'],
+ refCacheFolder: 'ref-cache',
+
+ temperatureChat: LLM_DEFAULTS.TEMPERATURE,
+ maxTokensChatDefault: '',
summarizationModel: '',
voiceCommandModel: '',
@@ -53,6 +64,9 @@ const DEFAULT_SETTINGS: LLMAgentSettings = {
metricsInterval: 15,
voiceDisplayLimit: 30000,
voiceContextLimit: 30000,
+ temperatureVoice: LLM_DEFAULTS.TEMPERATURE,
+ maxTokensVoiceRegular: '',
+ maxTokensVoiceCommands: '',
promptRegular: '',
promptCommands: '',
promptMetrics: '',
@@ -116,7 +130,7 @@ export default class LLMAgentPlugin extends Plugin {
} catch (error) {
console.error('Ошибка загрузки доступных моделей:', error);
// Fallback к базовым моделям
- this.availableModels = ['gemini-2.5-flash', 'gpt-4o-mini', 'claude-3-5-sonnet-20241022'];
+ this.availableModels = [LLM_DEFAULTS.MODEL, 'gpt-4o-mini', 'claude-3-5-sonnet-20241022'];
}
}
@@ -297,6 +311,38 @@ class SampleSettingTab extends PluginSettingTab {
});
});
+ // Этот промпт будет отправляться LLM перед каждым диалогом
+ this.addPromptAutocomplete(new Setting(containerEl).setName('Системный промпт'), 'systemPrompt');
+
+ new Setting(containerEl)
+ .setName('Температура чата по умолчанию')
+ .setDesc(`Значение от 0.0 до 2.0 (по умолчанию ${LLM_DEFAULTS.TEMPERATURE}). Влияет на креативность.`)
+ .addText((text) =>
+ text
+ .setPlaceholder(String(LLM_DEFAULTS.TEMPERATURE))
+ .setValue(String(this.plugin.settings.temperatureChat))
+ .onChange(async (value) => {
+ const num = parseFloat(value);
+ this.plugin.settings.temperatureChat = isNaN(num) ? LLM_DEFAULTS.TEMPERATURE : num;
+ await this.plugin.saveSettings();
+ await this.plugin.syncSettings();
+ })
+ );
+
+ new Setting(containerEl)
+ .setName('Макс. токенов чата по умолчанию')
+ .setDesc('Оставьте пустым для отсутствия лимита.')
+ .addText((text) =>
+ text
+ .setPlaceholder('Лимит')
+ .setValue(this.plugin.settings.maxTokensChatDefault)
+ .onChange(async (value) => {
+ this.plugin.settings.maxTokensChatDefault = value;
+ await this.plugin.saveSettings();
+ await this.plugin.syncSettings();
+ })
+ );
+
new Setting(containerEl)
.setName('API Base URL')
.setDesc('Базовый URL для API LLM Agent')
@@ -311,9 +357,6 @@ class SampleSettingTab extends PluginSettingTab {
})
);
- // Этот промпт будет отправляться LLM перед каждым диалогом
- this.addPromptAutocomplete(new Setting(containerEl).setName('Системный промпт'), 'systemPrompt');
-
containerEl.createEl('h2', { text: 'Голосовое управление (Voice Service)' });
new Setting(containerEl)
@@ -329,16 +372,61 @@ class SampleSettingTab extends PluginSettingTab {
});
});
+ // Инструкции для Промпта №1.
+ this.addPromptAutocomplete(
+ new Setting(containerEl).setName('Регулярный промпт'),
+ 'promptRegular'
+ );
+
+ // Инструкции для Промпта №2.
+ this.addPromptAutocomplete(
+ new Setting(containerEl).setName('Промпт команд'),
+ 'promptCommands'
+ );
+
+ this.addPromptAutocomplete(
+ new Setting(containerEl).setName('Промпт качественной аналитики'),
+ 'promptMetrics'
+ );
+
new Setting(containerEl)
- .setName('Папка аудио-логов')
- .setDesc('Папка внутри Obsidian, куда будут сохраняться текстовые расшифровки (в формате .md). Относительно корня хранилища.')
+ .setName('Температура Voice')
+ .setDesc(`Температура для голосовых запросов (по умолчанию ${LLM_DEFAULTS.TEMPERATURE})`)
.addText((text) =>
text
- .setPlaceholder('audio-logs')
- .setValue(this.plugin.settings.logsFolder)
+ .setPlaceholder(String(LLM_DEFAULTS.TEMPERATURE))
+ .setValue(String(this.plugin.settings.temperatureVoice))
.onChange(async (value) => {
- // Убираем лишние слэши для корректности пути
- this.plugin.settings.logsFolder = value.replace(/^\/+|\/+$/g, '').trim();
+ const num = parseFloat(value);
+ this.plugin.settings.temperatureVoice = isNaN(num) ? LLM_DEFAULTS.TEMPERATURE : num;
+ await this.plugin.saveSettings();
+ await this.plugin.syncSettings();
+ })
+ );
+
+ new Setting(containerEl)
+ .setName('Макс. токенов Voice (Регулярный)')
+ .setDesc('Лимит токенов для регулярного анализа. Оставьте пустым для безлимита.')
+ .addText((text) =>
+ text
+ .setPlaceholder('Лимит')
+ .setValue(this.plugin.settings.maxTokensVoiceRegular)
+ .onChange(async (value) => {
+ this.plugin.settings.maxTokensVoiceRegular = value;
+ await this.plugin.saveSettings();
+ await this.plugin.syncSettings();
+ })
+ );
+
+ new Setting(containerEl)
+ .setName('Макс. токенов Voice (Команды)')
+ .setDesc('Лимит токенов для голосовых команд. Оставьте пустым для безлимита.')
+ .addText((text) =>
+ text
+ .setPlaceholder('Лимит')
+ .setValue(this.plugin.settings.maxTokensVoiceCommands)
+ .onChange(async (value) => {
+ this.plugin.settings.maxTokensVoiceCommands = value;
await this.plugin.saveSettings();
await this.plugin.syncSettings();
})
@@ -370,6 +458,21 @@ class SampleSettingTab extends PluginSettingTab {
})
);
+ new Setting(containerEl)
+ .setName('Папка аудио-логов')
+ .setDesc('Папка внутри Obsidian, куда будут сохраняться текстовые расшифровки (в формате .md). Относительно корня хранилища.')
+ .addText((text) =>
+ text
+ .setPlaceholder('audio-logs')
+ .setValue(this.plugin.settings.logsFolder)
+ .onChange(async (value) => {
+ // Убираем лишние слэши для корректности пути
+ this.plugin.settings.logsFolder = value.replace(/^\/+|\/+$/g, '').trim();
+ await this.plugin.saveSettings();
+ await this.plugin.syncSettings();
+ })
+ );
+
new Setting(containerEl)
.setName('Объем контекста (символы)')
.setDesc('Сколько последних символов транскрибации отправлять в модель.')
@@ -411,23 +514,6 @@ class SampleSettingTab extends PluginSettingTab {
})
);
- // Инструкции для Промпта №1.
- this.addPromptAutocomplete(
- new Setting(containerEl).setName('Регулярный промпт'),
- 'promptRegular'
- );
-
- // Инструкции для Промпта №2.
- this.addPromptAutocomplete(
- new Setting(containerEl).setName('Промпт команд'),
- 'promptCommands'
- );
-
- this.addPromptAutocomplete(
- new Setting(containerEl).setName('Промпт качественной аналитики'),
- 'promptMetrics'
- );
-
containerEl.createEl('h2', { text: 'Управление ссылками и файлами' });
new Setting(containerEl)
diff --git a/src/components/ChatPanel.ts b/src/components/ChatPanel.ts
index 5eca47d..415566f 100644
--- a/src/components/ChatPanel.ts
+++ b/src/components/ChatPanel.ts
@@ -16,9 +16,11 @@ import { MarkdownRenderer, setIcon, Notice, TFile, FileSystemAdapter } from 'obs
import { Dialog } from 'src/utils/Dialog';
import { CacheManager } from 'src/references/CacheManager';
+import { LLM_DEFAULTS } from 'src/constants';
+
interface ChatPanelProps {
chatHistory: ChatHistoryItem[];
- onSendMessage: (message: string, selectedModel?: string, attachments?: Attachment[]) => void;
+ onSendMessage: (message: string, selectedModel?: string, attachments?: Attachment[], customMaxTokens?: number, customTemperature?: number) => void;
selectedModel?: string;
plugin: LLMAgentPlugin;
currentGraphCustomSystemPrompt: string | null;
@@ -38,6 +40,11 @@ export class ChatPanel {
currentStreamingNodeId: string | null;
stopButton: HTMLButtonElement;
+ maxTokensInput: HTMLInputElement;
+ maxTokensResetBtn: HTMLButtonElement;
+ tempInput: HTMLInputElement;
+ tempResetBtn: HTMLButtonElement;
+
// Элементы для файловых вложений
attachFileButton: HTMLButtonElement;
fileInput: HTMLInputElement;
@@ -58,7 +65,7 @@ export class ChatPanel {
this.container = container;
this.props = props;
this.chatHistory = props.chatHistory || [];
- this.selectedModel = props.selectedModel || 'gemini-2.5-flash';
+ this.selectedModel = props.selectedModel || LLM_DEFAULTS.MODEL;
// Инициализация системы ссылок
this.initializeReferenceSystem();
@@ -466,6 +473,16 @@ export class ChatPanel {
⚙️
+
+ Temp:
+
+
+
+
+ Tokens:
+
+
+