Add Search Strictness slider with adjustable distance_mod for embeddings

This commit is contained in:
vegu-ai-tools
2026-04-04 00:20:05 +03:00
parent 2a36c779bc
commit 64d29e8c42
5 changed files with 78 additions and 3 deletions

View File

@@ -27,6 +27,7 @@
- "Contextual Generate: Fixed list-type generation prefilling an empty line after '1.', which caused some LLMs to produce empty lists."
- "Advance Time: Fixed toolbar time advancement being completely non-functional due to a missing websocket handler. Also fixed invalid ISO 8601 duration strings for the 1 week and 2 weeks options."
improvements:
- "Search Strictness: The distance_mod embedding preset value is now a float (was int) with a range of 0.12.0, allowing both tighter and looser similarity matching. A 'Search Strictness' slider is now available in the Context Database UI, letting users tune search sensitivity on the fly. Changes persist to the active embedding preset immediately."
- "Embeddings Device Switching: Changing the embeddings device (e.g., CPU to CUDA) no longer requires a restart. The old model is properly released from ChromaDB's class-level cache and GPU memory is freed before loading the new model."
- "Context Formatting: The |condensed template filter no longer permanently compacts multi-line context (e.g., world info, memories, pins) into a single line when sending prompts to the LLM. Formatting is now only compacted temporarily for deduplication comparison and restored to its original multi-line structure afterwards."
- "Client Config UX: Moved advanced settings (Inference Presets, Structured Data Format, Section Format, Response Length Enforcement, Prompt Caching, Rate Limit) into a dedicated Advanced tab to declutter the general view. A convenient link in the general tab provides quick access. Toggling Simple View on now resets to the General tab, and switching clients always starts on General."

View File

@@ -288,7 +288,7 @@ class EmbeddingFunctionPreset(pydantic.BaseModel):
trust_remote_code: bool = False
device: str = "cpu"
distance: float = 1.5
distance_mod: int = 1
distance_mod: float = 1.0
distance_function: str = "l2"
fast: bool = True
gpu_recommendation: bool = False

View File

@@ -13,6 +13,7 @@ from talemate.instance import get_agent
from talemate.world_state.manager import WorldStateManager, Suggestion
from talemate.status import set_loading
import talemate.game.focal as focal
from talemate.config import save_config
from talemate.server.websocket_plugin import Plugin
from .scene_intent import SceneIntentMixin
@@ -91,6 +92,10 @@ class WorldEntryReinforcementPayload(pydantic.BaseModel):
reset: bool = False
class UpdateDistanceModPayload(pydantic.BaseModel):
distance_mod: float = pydantic.Field(gt=0, le=2.0)
class QueryContextDBPayload(pydantic.BaseModel):
query: str
meta: dict = {}
@@ -213,6 +218,11 @@ class WorldStateManagerPlugin(
def scene(self):
return self.websocket_handler.scene
@property
def current_embeddings_config(self):
memory_agent = get_agent("memory")
return memory_agent.embeddings_config if memory_agent else None
@property
def world_state_manager(self):
return WorldStateManager(self.scene)
@@ -655,16 +665,48 @@ class WorldStateManagerPlugin(
payload.query, **payload.meta
)
embeddings_config = self.current_embeddings_config
self.websocket_handler.queue_put(
{
"type": "world_state_manager",
"action": "context_db_result",
"data": context_db.model_dump(),
"distance_mod": embeddings_config.distance_mod if embeddings_config else 1.0,
}
)
await self.signal_operation_done()
async def handle_get_distance_mod(self, data):
embeddings_config = self.current_embeddings_config
self.websocket_handler.queue_put(
{
"type": "world_state_manager",
"action": "distance_mod_updated",
"distance_mod": embeddings_config.distance_mod if embeddings_config else 1.0,
}
)
async def handle_update_distance_mod(self, data):
payload = UpdateDistanceModPayload(**data)
embeddings_config = self.current_embeddings_config
if not embeddings_config:
return
embeddings_config.distance_mod = payload.distance_mod
save_config()
self.websocket_handler.queue_put(
{
"type": "world_state_manager",
"action": "distance_mod_updated",
"distance_mod": payload.distance_mod,
}
)
async def handle_update_context_db(self, data):
payload = UpdateContextDBPayload(**data)

View File

@@ -89,7 +89,7 @@
<v-slider :disabled="busy" thumb-label="always" density="compact" v-model="config.embeddings[selected[0]].distance" min="0.1" max="10.0" step="0.1" label="Distance" @update:model-value="setPresetChanged(selected[0])"></v-slider>
<v-slider :disabled="busy" thumb-label="always" density="compact" v-model="config.embeddings[selected[0]].distance_mod" min="1" max="1000" step="10" label="Distance Mod" @update:model-value="setPresetChanged(selected[0])"></v-slider>
<v-slider :disabled="busy" thumb-label="always" density="compact" v-model="config.embeddings[selected[0]].distance_mod" min="0.1" max="2.0" step="0.1" label="Distance Mod" @update:model-value="setPresetChanged(selected[0])"></v-slider>
<v-select :disabled="busy" v-model="config.embeddings[selected[0]].distance_function" :items="distanceFunctions" label="Distance Function" @update:model-value="setPresetChanged(selected[0])"></v-select>
@@ -253,7 +253,7 @@ export default {
trust_remote_code: false,
device: 'cpu',
distance: 1.0,
distance_mod: 1,
distance_mod: 1.0,
distance_function: 'cosine',
fast: true,
gpu_recommendation: false,

View File

@@ -5,6 +5,7 @@
Manage your context entries through the <v-icon>mdi-earth</v-icon> <strong>World</strong>, <v-icon>mdi-clock</v-icon> <strong>History</strong> and <v-icon>mdi-account-group</v-icon> <strong>Characters</strong> tabs.
<p class="text-caption">
Content search is based on <strong class="text-primary">semantic similarity</strong> using embeddings from the Memory agent, its <strong class="text-error">NOT</strong> using exact matching.
Use the <strong>Search Strictness</strong> slider to control how closely results must match your query. Lower values require closer matches, higher values allow more loosely related results. This setting is saved to the active embedding preset.
</p>
</v-alert>
<div :style="{ maxWidth: MAX_CONTENT_WIDTH }">
@@ -38,6 +39,13 @@
:style="{ minWidth: '150px', maxWidth: '200px' }"
variant="underlined" single-line hide-details density="compact"></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="auto" class="pt-4">
<v-slider v-model="distanceMod" min="0.1" max="2.0" step="0.1"
:style="{ minWidth: '250px', maxWidth: '350px' }"
label="Search Strictness" hide-details
thumb-label="always"
@update:model-value="updateDistanceMod"></v-slider>
</v-col>
<v-col cols="12" sm="auto" md="auto" class="ml-auto d-flex flex-wrap ga-1">
<!-- button that opens the tools menu -->
<v-menu>
@@ -199,6 +207,7 @@
<script>
import { MAX_CONTENT_WIDTH } from '@/constants';
import { debounce } from 'lodash';
export default {
name: "WorldStateManagerContextDB",
@@ -212,6 +221,7 @@ export default {
data() {
return {
updateTimeout: null,
distanceMod: 1.0,
query: null,
queryMetaKey: null,
queryMetaValue: null,
@@ -390,6 +400,21 @@ export default {
}));
},
updateDistanceMod: debounce(function(value) {
this.getWebsocket().send(JSON.stringify({
type: 'world_state_manager',
action: 'update_distance_mod',
distance_mod: value,
}));
}, 300),
requestDistanceMod() {
this.getWebsocket().send(JSON.stringify({
type: 'world_state_manager',
action: 'get_distance_mod',
}));
},
resetDB() {
let confirm = window.confirm("Are you sure you want to reset the context database? This will remove all entries and reimport them from the current save file.");
if (!confirm) {
@@ -409,11 +434,17 @@ export default {
else if (message.action === 'context_db_result') {
this.contextDB = message.data;
this.currentQuery = this.contextDBQuery;
if (message.distance_mod !== undefined) {
this.distanceMod = message.distance_mod;
}
}
else if (message.action === 'context_db_updated') {
this.$emit('request-sync')
//this.load(message.data.id);
}
else if (message.action === 'distance_mod_updated') {
this.distanceMod = message.distance_mod;
}
else if (message.action === 'context_db_deleted') {
let entry_id = message.data.id;
for (let i = 0; i < this.contextDB.entries.length; i++) {
@@ -428,6 +459,7 @@ export default {
},
created() {
this.registerMessageHandler(this.handleMessage);
this.requestDistanceMod();
}
}