mirror of
https://github.com/bal-spec/sillytavern-character-memory.git
synced 2026-05-02 05:31:44 +00:00
- Add "Merge extraction chunks" checkbox (default: off) so long chats produce multiple smaller blocks instead of one massive one - Add "dates and times" to extraction prompt's WHAT TO EXTRACT list as a gentle nudge for temporal context Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
314 lines
22 KiB
HTML
314 lines
22 KiB
HTML
<div class="charMemory_settings">
|
|
<div class="inline-drawer">
|
|
<div class="inline-drawer-toggle inline-drawer-header">
|
|
<b>Character Memory</b>
|
|
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
|
</div>
|
|
<div class="inline-drawer-content">
|
|
|
|
<!-- Stats bar — always visible -->
|
|
<div class="charMemory_statsBar">
|
|
<div class="charMemory_statItem" title="The Data Bank file where memories are stored for this character">
|
|
<i class="fa-solid fa-file-lines fa-sm"></i>
|
|
<span id="charMemory_statFile">No character</span>
|
|
</div>
|
|
<div class="charMemory_statItem" title="Total number of individual memory bullets stored">
|
|
<i class="fa-solid fa-brain fa-sm"></i>
|
|
<span id="charMemory_statCount">0 memories</span>
|
|
</div>
|
|
<div class="charMemory_statItem" title="New messages since last extraction / auto-extraction threshold">
|
|
<i class="fa-solid fa-arrows-rotate fa-sm"></i>
|
|
<span id="charMemory_statProgress">0/10 msgs</span>
|
|
</div>
|
|
<div class="charMemory_statItem" title="Time remaining before the next auto-extraction is allowed">
|
|
<i class="fa-solid fa-clock fa-sm"></i>
|
|
<span id="charMemory_statCooldown">Ready</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Top-level tabs -->
|
|
<div class="charMemory_tabs">
|
|
<button class="charMemory_tab active" data-tab="main">Main</button>
|
|
<button class="charMemory_tab" data-tab="consolidate">Consolidate</button>
|
|
<button class="charMemory_tab" data-tab="batch">Batch Extraction</button>
|
|
<button class="charMemory_tab" data-tab="settings">Settings</button>
|
|
<button class="charMemory_tab" data-tab="log">Log</button>
|
|
</div>
|
|
|
|
<!-- Main tab (default) -->
|
|
<div class="charMemory_tabContent" id="charMemory_tabMain">
|
|
<div class="charMemory_sectionHeader">
|
|
<small><b>Memory Extraction</b></small>
|
|
<label class="checkbox_label" for="charMemory_enabled" title="When enabled, memories are extracted automatically after a set number of new messages">
|
|
<input type="checkbox" id="charMemory_enabled" />
|
|
<small>Automatic</small>
|
|
</label>
|
|
</div>
|
|
<div class="charMemory_buttonRow">
|
|
<input type="button" id="charMemory_extractNow" class="menu_button" value="Extract Now" title="Extract memories from unprocessed messages. If all messages have been processed, use 'Reset Extraction State' first to re-read from the beginning." />
|
|
<input type="button" id="charMemory_manageMemories" class="menu_button" value="View / Edit" title="Browse, edit, and delete individual stored memories" />
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Consolidate tab -->
|
|
<div class="charMemory_tabContent" id="charMemory_tabConsolidate" style="display:none;">
|
|
<div class="charMemory_promptSection">
|
|
<label for="charMemory_consolidationStrategy">
|
|
<small>Consolidation strategy</small>
|
|
</label>
|
|
<select id="charMemory_consolidationStrategy" class="text_pole">
|
|
<option value="conservative">Conservative — only merge near-exact duplicates</option>
|
|
<option value="balanced">Balanced — merge duplicates & related facts (default)</option>
|
|
<option value="aggressive">Aggressive — compress heavily, summarize themes</option>
|
|
</select>
|
|
<small id="charMemory_consolidationPreview" class="charMemory_helperText" style="font-style:italic;"></small>
|
|
<details class="charMemory_promptDisclosure" id="charMemory_promptDisclosure">
|
|
<summary><small>Show prompt</small></summary>
|
|
<textarea id="charMemory_consolidationPrompt" class="text_pole textarea_compact" rows="6" placeholder="Edit the consolidation prompt for this strategy..."></textarea>
|
|
<div class="charMemory_buttonRow">
|
|
<input type="button" id="charMemory_restorePresetDefault" class="menu_button" value="Restore Default" title="Reset this preset's prompt to its built-in default" style="display:none;" />
|
|
</div>
|
|
</details>
|
|
</div>
|
|
<div class="charMemory_buttonRow">
|
|
<input type="button" id="charMemory_consolidate" class="menu_button" value="Consolidate" title="Use the LLM to merge duplicate and related memories into fewer, cleaner entries" />
|
|
<input type="button" id="charMemory_undoConsolidate" class="menu_button" value="Undo Consolidation" title="Restore memories from before the last consolidation (session only)" disabled />
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Batch Extract tab -->
|
|
<div class="charMemory_tabContent" id="charMemory_tabBatch" style="display:none;">
|
|
<div class="charMemory_buttonRow">
|
|
<input type="button" id="charMemory_batchRefresh" class="menu_button" value="Refresh" title="Load chat list for this character" />
|
|
<input type="button" id="charMemory_batchExtract" class="menu_button" value="Extract Selected" title="Run extraction on all selected chats" disabled />
|
|
<input type="button" id="charMemory_batchStop" class="menu_button" value="Stop" title="Cancel batch extraction" style="display:none;" />
|
|
</div>
|
|
<div id="charMemory_batchProgress" class="charMemory_batchProgress" style="display:none;">
|
|
<div class="charMemory_batchProgressText"></div>
|
|
<div class="charMemory_batchProgressBar"><div class="charMemory_batchProgressFill"></div></div>
|
|
</div>
|
|
<div class="charMemory_sectionHeader">
|
|
<small><b title="Chat files attached to this character. Select which ones to extract memories from.">Character Attachments</b></small>
|
|
<label class="checkbox_label">
|
|
<input type="checkbox" id="charMemory_batchSelectAll" />
|
|
<small>Select all</small>
|
|
</label>
|
|
</div>
|
|
<div id="charMemory_batchChatList" class="charMemory_batchChatList">
|
|
<div class="charMemory_diagEmpty">Click "Refresh" to load chats.</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Settings tab -->
|
|
<div class="charMemory_tabContent" id="charMemory_tabSettings" style="display:none;">
|
|
|
|
<!-- LLM Used for Extraction -->
|
|
<div class="charMemory_statusRow">
|
|
<label for="charMemory_source" title="Which LLM to use for memory extraction and consolidation">
|
|
<small>LLM Used for Extraction</small>
|
|
</label>
|
|
<select id="charMemory_source" class="text_pole">
|
|
<option value="provider">Dedicated API (recommended)</option>
|
|
<option value="webllm">WebLLM (browser-local)</option>
|
|
<option value="main_llm">Main LLM</option>
|
|
</select>
|
|
<small class="charMemory_helperText"><b>Dedicated API is recommended.</b> Main LLM pollutes the extraction prompt with chat context, system prompts, and other instructions that degrade memory quality.</small>
|
|
|
|
<div id="charMemory_providerSettings" style="display:none;">
|
|
<div class="charMemory_statusRow">
|
|
<label><small>Provider</small></label>
|
|
<select id="charMemory_providerSelect" class="text_pole">
|
|
</select>
|
|
</div>
|
|
<div class="charMemory_statusRow" id="charMemory_providerApiKeyRow">
|
|
<label><small>API Key <a id="charMemory_providerHelpLink" href="#" target="_blank" style="font-size:0.85em;">(get key)</a></small></label>
|
|
<div style="display:flex;gap:5px;align-items:center;">
|
|
<input type="password" id="charMemory_providerApiKey" class="text_pole" placeholder="Enter API key" style="flex:1;" />
|
|
<button type="button" id="charMemory_providerApiKeyReveal" class="menu_button" title="Show/hide API key" style="padding:3px 8px;">
|
|
<i class="fa-solid fa-eye fa-sm"></i>
|
|
</button>
|
|
<input type="button" id="charMemory_providerConnect" class="menu_button" value="Connect" title="Fetch available models using your API key" />
|
|
</div>
|
|
</div>
|
|
<small id="charMemory_providerConnectStatus" class="charMemory_helperText" style="display:none;"></small>
|
|
<div class="charMemory_statusRow" id="charMemory_providerBaseUrlRow" style="display:none;">
|
|
<label><small>Base URL</small></label>
|
|
<input type="text" id="charMemory_providerBaseUrl" class="text_pole" placeholder="https://your-server.com/v1" />
|
|
</div>
|
|
<div class="charMemory_statusRow" id="charMemory_providerModelDropdownRow">
|
|
<label><small>Model</small></label>
|
|
<div id="charMemory_nanogptFilters" style="display:none;">
|
|
<div class="charMemory_filterRow" style="display:flex;flex-wrap:wrap;gap:8px;margin-bottom:4px;">
|
|
<label class="checkbox_label"><input type="checkbox" id="charMemory_nanogptFilterSub" /> <small>Subscription</small></label>
|
|
<label class="checkbox_label"><input type="checkbox" id="charMemory_nanogptFilterOS" /> <small>Open Source</small></label>
|
|
<label class="checkbox_label"><input type="checkbox" id="charMemory_nanogptFilterRP" /> <small>Roleplay</small></label>
|
|
<label class="checkbox_label"><input type="checkbox" id="charMemory_nanogptFilterReasoning" /> <small>Reasoning</small></label>
|
|
</div>
|
|
</div>
|
|
<div style="display:flex;gap:5px;align-items:center;">
|
|
<select id="charMemory_providerModel" class="text_pole" style="flex:1;">
|
|
<option value="">-- Select model --</option>
|
|
</select>
|
|
<input type="button" id="charMemory_providerRefreshModels" class="menu_button" value="↻" title="Refresh model list" />
|
|
</div>
|
|
<small id="charMemory_providerModelInfo" class="charMemory_helperText"></small>
|
|
</div>
|
|
<div class="charMemory_statusRow" id="charMemory_providerTestRow">
|
|
<div style="display:flex;gap:5px;align-items:center;">
|
|
<input type="button" id="charMemory_providerTest" class="menu_button" value="Test Model" title="Send a test prompt to the selected model and verify it responds correctly" />
|
|
</div>
|
|
<small id="charMemory_providerTestStatus" class="charMemory_helperText" style="display:none;"></small>
|
|
</div>
|
|
<div class="charMemory_statusRow" id="charMemory_providerModelInputRow" style="display:none;">
|
|
<label><small>Model ID</small></label>
|
|
<input type="text" id="charMemory_providerModelInput" class="text_pole" placeholder="Enter model identifier" />
|
|
<small class="charMemory_helperText">Enter the model ID manually (e.g. claude-sonnet-4-5-20250929).</small>
|
|
</div>
|
|
<div class="charMemory_statusRow">
|
|
<label><small>System prompt (optional)</small></label>
|
|
<textarea id="charMemory_providerSystemPrompt" class="text_pole" rows="3" placeholder="Override the default system prompt. Leave blank for default."></textarea>
|
|
<small class="charMemory_helperText">Prepended to extraction/consolidation calls. Use for jailbreaks or custom instructions.</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Auto-Extraction -->
|
|
<hr class="charMemory_separator" />
|
|
<small><b>Auto-Extraction</b></small>
|
|
|
|
<div class="charMemory_sliderRow">
|
|
<label title="How many new messages trigger an automatic extraction.">
|
|
<small>Extract after every N messages</small>
|
|
</label>
|
|
<input class="neo-range-slider" type="range" id="charMemory_interval" min="3" max="100" step="1" value="20" />
|
|
<div class="wide100p">
|
|
<input class="neo-range-input" type="number" min="3" max="100" step="1"
|
|
data-for="charMemory_interval" id="charMemory_intervalCounter" />
|
|
</div>
|
|
</div>
|
|
|
|
<div class="charMemory_sliderRow">
|
|
<label title="Minimum time between auto-extractions, even if the message threshold is met.">
|
|
<small>Minimum wait between extractions (min)</small>
|
|
</label>
|
|
<input class="neo-range-slider" type="range" id="charMemory_minCooldown" min="0" max="30" step="1" value="10" />
|
|
<div class="wide100p">
|
|
<input class="neo-range-input" type="number" min="0" max="30" step="1"
|
|
data-for="charMemory_minCooldown" id="charMemory_minCooldownCounter" />
|
|
</div>
|
|
</div>
|
|
|
|
<small class="charMemory_helperText">These settings only affect automatic extraction. Manual extraction and batch extraction ignore them.</small>
|
|
|
|
<!-- Extraction Settings -->
|
|
<hr class="charMemory_separator" />
|
|
<small><b>Extraction Settings</b></small>
|
|
|
|
<div class="charMemory_sliderRow">
|
|
<label title="How many messages to include in each LLM call.">
|
|
<small>Messages per LLM call</small>
|
|
</label>
|
|
<input class="neo-range-slider" type="range" id="charMemory_maxMessages" min="10" max="200" step="1" value="50" />
|
|
<div class="wide100p">
|
|
<input class="neo-range-input" type="number" min="10" max="200" step="1"
|
|
data-for="charMemory_maxMessages" id="charMemory_maxMessagesCounter" />
|
|
</div>
|
|
</div>
|
|
|
|
<div class="charMemory_sliderRow">
|
|
<label title="Maximum tokens the LLM can use for its response.">
|
|
<small>Max response length</small>
|
|
</label>
|
|
<input class="neo-range-slider" type="range" id="charMemory_responseLength" min="100" max="4000" step="50" value="1000" />
|
|
<div class="wide100p">
|
|
<input class="neo-range-input" type="number" min="100" max="4000" step="50"
|
|
data-for="charMemory_responseLength" id="charMemory_responseLengthCounter" />
|
|
</div>
|
|
</div>
|
|
|
|
<div class="charMemory_statusRow">
|
|
<label class="checkbox_label" for="charMemory_mergeChunks" title="When enabled, extraction results from the same chat are merged into a single block. Disable for long chats to keep blocks smaller for consolidation.">
|
|
<input type="checkbox" id="charMemory_mergeChunks" />
|
|
<span>Merge extraction chunks</span>
|
|
</label>
|
|
<small class="charMemory_helperText">When enabled, multi-chunk extractions from the same chat are merged into one block. Disable for long chats to keep blocks smaller for consolidation.</small>
|
|
</div>
|
|
|
|
<!-- Storage -->
|
|
<hr class="charMemory_separator" />
|
|
|
|
<div class="charMemory_statusRow">
|
|
<label class="checkbox_label" for="charMemory_perChat" title="When enabled, each chat gets its own memory file.">
|
|
<input type="checkbox" id="charMemory_perChat" />
|
|
<span>Separate memories per chat</span>
|
|
</label>
|
|
<small class="charMemory_helperText">Each conversation gets its own memory file instead of sharing one per character.</small>
|
|
</div>
|
|
|
|
<div class="charMemory_statusRow">
|
|
<label for="charMemory_fileName" title="Override the auto-generated file name.">
|
|
<small>File name override</small>
|
|
</label>
|
|
<input type="text" id="charMemory_fileName" class="text_pole" placeholder="(auto-generated from character name)" />
|
|
<small class="charMemory_helperText">Leave blank for auto-naming. Set a custom name to override.</small>
|
|
</div>
|
|
|
|
<!-- Extraction Prompt -->
|
|
<hr class="charMemory_separator" />
|
|
|
|
<div class="charMemory_promptSection">
|
|
<label for="charMemory_extractionPrompt" title="The prompt sent to the LLM for memory extraction. Uses {{charName}}, {{charCard}}, {{existingMemories}}, {{recentMessages}}, {{char}}, and {{user}} placeholders.">
|
|
<small>Extraction prompt</small>
|
|
</label>
|
|
<textarea id="charMemory_extractionPrompt" class="text_pole textarea_compact" rows="8" placeholder="Enter extraction prompt..."></textarea>
|
|
<input type="button" id="charMemory_restorePrompt" class="menu_button" value="Restore Default Prompt" title="Replace the current prompt with the built-in default" />
|
|
</div>
|
|
|
|
<!-- Reset / Clear -->
|
|
<hr class="charMemory_separator" />
|
|
|
|
<div class="charMemory_statusRow">
|
|
<input type="button" id="charMemory_resetTracking" class="menu_button" value="Reset Extraction State" title="Reset extraction tracking for the current character's chats" />
|
|
<small class="charMemory_helperText">Resets extraction tracking for the current character. Use before 'Extract Now' or 'Batch Extract' to re-process from the beginning.</small>
|
|
<input type="button" id="charMemory_resetExtraction" class="menu_button charMemory_dangerBtn" value="Clear All Memories" title="Delete the memory file and reset extraction state for the current character." />
|
|
<small class="charMemory_helperText">Deletes the memory file and resets extraction tracking for the current character. This cannot be undone.</small>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Log tab -->
|
|
<div class="charMemory_tabContent" id="charMemory_tabLog" style="display:none;">
|
|
<div class="charMemory_buttonRow">
|
|
<input type="button" id="charMemory_clearLog" class="menu_button" value="Clear" title="Clear the activity log" />
|
|
<input type="button" id="charMemory_saveLog" class="menu_button" value="Save Log" title="Download the activity log as a text file" />
|
|
<label class="checkbox_label" for="charMemory_verboseLog" title="Show full LLM prompts and responses in the activity log">
|
|
<input type="checkbox" id="charMemory_verboseLog" />
|
|
<small>Verbose</small>
|
|
</label>
|
|
</div>
|
|
<div id="charMemory_activityLog" class="charMemory_activityLog" style="max-height:300px;overflow-y:auto;font-size:0.85em;font-family:monospace;">
|
|
<div class="charMemory_diagEmpty">No activity yet.</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Activity Log — always visible -->
|
|
<div class="charMemory_miniLog" id="charMemory_miniLog">
|
|
<small><b>Activity Log</b></small>
|
|
<div class="charMemory_miniLogContent" id="charMemory_miniLogContent">
|
|
<div class="charMemory_diagEmpty charMemory_miniLogEmpty">No activity yet.</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Diagnostics — always visible at bottom -->
|
|
<div class="charMemory_bottomDiagnostics">
|
|
<div class="charMemory_buttonRow">
|
|
<small><b>Diagnostics</b></small>
|
|
<input type="button" id="charMemory_refreshDiag" class="menu_button" value="Refresh" title="Capture current diagnostics (lorebook entries, extension prompts, memory file status)" />
|
|
</div>
|
|
<div id="charMemory_diagnosticsContent" class="charMemory_diagnosticsContent">
|
|
<div class="charMemory_diagEmpty">Click "Refresh" after a generation to see diagnostics.</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|