v0.17.3: bug-fix maintenance pass — ingest origin exemption, FK safety, auto-search reset, deterministic ingest, WAL, config centralization, dead-code removal
- /api/ingest exempt from origin check for CLI/Bearer clients - recreate deleted conversations on bogus conversation_id (chat + search) - augmented auto-search emits reset:true; frontend clears first-pass text - image uploads stored as placeholders, never text-ingested - check_fact_conflicts requires shared subject keywords - deterministic ingest point ids (md5 chunk hash) - get_load() no longer crashes when rocm-smi yields no VRAM lines - SQLite WAL + busy_timeout; timing-safe API key compares - supervise fire-and-forget auto-ingest tasks; log missing logprobs - centralize EMBED_URL/EMBED_MODEL/QDRANT_URL/NODE_NAME in config - remove dead triage.py, select_node tests, is_state_changing, stray artifacts - add regression tests + autouse global-reset conftest
This commit is contained in:
@@ -38,6 +38,21 @@ AUTO_FACT_PATTERNS = [
|
||||
]
|
||||
SOCIAL_TRIGGERS = {"hi", "hello", "hey", "yo", "sup", "howdy", "good morning", "good evening"}
|
||||
|
||||
# Short filler words that shouldn't count as subject overlap between facts.
|
||||
_STOPWORDS = {
|
||||
"with", "that", "have", "this", "from", "they", "what", "when", "where",
|
||||
"which", "there", "your", "will", "would", "about", "these", "their",
|
||||
"been", "into", "than", "then", "them", "were", "being", "more", "most",
|
||||
"some", "other", "only", "still", "also", "after", "before", "during",
|
||||
"because", "through", "without",
|
||||
}
|
||||
|
||||
|
||||
def _subject_words(text: str) -> set:
|
||||
"""Meaningful subject tokens for overlap comparison."""
|
||||
words = re.findall(r"[A-Za-z0-9_]{4,}", text.lower())
|
||||
return {w for w in words if w not in _STOPWORDS}
|
||||
|
||||
|
||||
def _is_social(text: str) -> bool:
|
||||
t = text.strip().lower()
|
||||
@@ -86,6 +101,10 @@ def auto_detect_facts(user_message: str, assistant_message: str) -> list[str]:
|
||||
def check_fact_conflicts(facts: list[str]) -> list[dict]:
|
||||
"""Search for existing memories that conflict with detected facts.
|
||||
|
||||
A conflict is reported only when the existing memory is about the same
|
||||
subject (meaningful keyword overlap) but states something different —
|
||||
unrelated hits that merely share an FTS keyword are not conflicts.
|
||||
|
||||
Returns list of {memory_id, old_fact, new_fact} for each conflict.
|
||||
"""
|
||||
conflicts = []
|
||||
@@ -93,7 +112,7 @@ def check_fact_conflicts(facts: list[str]) -> list[dict]:
|
||||
related = search_memories(new_fact, limit=1)
|
||||
if related:
|
||||
old = related[0]["fact"]
|
||||
if old.rstrip(".") != new_fact.rstrip("."):
|
||||
if old.rstrip(".") != new_fact.rstrip(".") and (_subject_words(new_fact) & _subject_words(old)):
|
||||
conflicts.append({
|
||||
"memory_id": related[0]["rowid"],
|
||||
"old_fact": old,
|
||||
|
||||
Reference in New Issue
Block a user