diff --git a/CHANGELOG.yaml b/CHANGELOG.yaml
index 95aed9d4..4e3abde9 100644
--- a/CHANGELOG.yaml
+++ b/CHANGELOG.yaml
@@ -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.1–2.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."
diff --git a/src/talemate/config/schema.py b/src/talemate/config/schema.py
index f5f5590e..d1c424fc 100644
--- a/src/talemate/config/schema.py
+++ b/src/talemate/config/schema.py
@@ -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
diff --git a/src/talemate/server/world_state_manager/__init__.py b/src/talemate/server/world_state_manager/__init__.py
index 33a58237..3e65de8f 100644
--- a/src/talemate/server/world_state_manager/__init__.py
+++ b/src/talemate/server/world_state_manager/__init__.py
@@ -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)
diff --git a/talemate_frontend/src/components/AppConfigPresetsEmbeddings.vue b/talemate_frontend/src/components/AppConfigPresetsEmbeddings.vue
index 0cd4571b..3ad94d6f 100644
--- a/talemate_frontend/src/components/AppConfigPresetsEmbeddings.vue
+++ b/talemate_frontend/src/components/AppConfigPresetsEmbeddings.vue
@@ -89,7 +89,7 @@
Content search is based on semantic similarity using embeddings from the Memory agent, its NOT using exact matching. + Use the Search Strictness 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.