From 1568c25ac4f211e603e9dca155ad818eadb4b5fb Mon Sep 17 00:00:00 2001 From: duffyduck Date: Fri, 3 Jul 2026 02:34:17 +0200 Subject: [PATCH] =?UTF-8?q?fix(projects):=20Backfill=20v2=20=E2=80=94=20ro?= =?UTF-8?q?buster=20Match=20trotz=20GPS/Barge-In/FILE-Marker?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v1 matchte text==content exakt und verfehlte damit Nachrichten, bei denen die Bridge den Brain-Text anreichert oder cleant: - User-Turns: _build_core_text PREPENDT [Hinweis: Barge-In]-/[GPS-Position]- Bloecke — die stehen in conversation.jsonl, nicht in chat_backup. - Assistant-Turns: conversation enthaelt [FILE: /shared/uploads/...]-Marker, chat_backup hat sie schon rausgecleant. _norm entfernt jetzt FILE-Marker + fuehrende [..]-Bloecke, kollabiert Whitespace und vergleicht einen 120-Zeichen-Praefix. Neuer Marker (v2) → laeuft einmal neu und fuellt die von v1 verbliebenen Luecken. Nicht-destruktiv (eigene .pre-backfill-v2.bak), bestehende Tags bleiben unangetastet. Mit Tests gegen GPS-/Barge-In-/FILE-Marker-Faelle verifiziert. Co-Authored-By: Claude Opus 4.8 (1M context) --- aria-brain/migrate_backfill_projectid.py | 28 +++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/aria-brain/migrate_backfill_projectid.py b/aria-brain/migrate_backfill_projectid.py index c7b4386..ac798a4 100644 --- a/aria-brain/migrate_backfill_projectid.py +++ b/aria-brain/migrate_backfill_projectid.py @@ -25,6 +25,7 @@ from __future__ import annotations import json import logging import os +import re from collections import defaultdict, deque from pathlib import Path @@ -32,13 +33,30 @@ logger = logging.getLogger("aria.migrate.backfill_projectid") CONVERSATION_FILE = Path(os.environ.get("CONVERSATION_FILE", "/data/conversation.jsonl")) CHAT_BACKUP_FILE = Path(os.environ.get("CHAT_BACKUP_FILE", "/shared/config/chat_backup.jsonl")) -MARKER_FILE = Path("/shared/config/.chat_backup_projectid_backfill_v1") +# v2: robusterer Match (Marker-Strip + Praefix). v1 verlangte exakte Gleichheit +# von text==content und verfehlte damit alle Nachrichten bei denen die Bridge +# den Brain-Text anreichert (GPS/Barge-In-Hints prepended) oder cleant +# (FILE-Marker entfernt). Neuer Marker → laeuft einmal neu, fuellt die Luecken. +MARKER_FILE = Path("/shared/config/.chat_backup_projectid_backfill_v2") + +# _build_core_text (Bridge) PREPENDT bei User-Nachrichten Hinweis-/GPS-Bloecke +# in eckigen Klammern vor den eigentlichen Text; conversation.jsonl speichert +# diesen angereicherten Text, chat_backup nur den rohen. FILE-Marker stehen in +# conversation-Assistant-Turns, sind in chat_backup aber schon rausgecleant. +_FILE_MARKER_RE = re.compile(r"\[FILE:\s*/shared/uploads/[^\]]+\]", re.IGNORECASE) +_LEADING_BRACKET_RE = re.compile(r"^\s*(?:\[[^\]]*\]\s*)+") +_WS_RE = re.compile(r"\s+") def _norm(text: str) -> str: - """Match-Key: getrimmt + auf 500 Zeichen begrenzt. Reicht um Turns eindeutig - zu unterscheiden, ist aber tolerant gegen minimale Trailing-Unterschiede.""" - return (text or "").strip()[:500] + """Match-Key: FILE-Marker + fuehrende [Hinweis]/[GPS]-Bloecke entfernen, + Whitespace kollabieren, auf 120-Zeichen-Praefix kuerzen. Toleriert damit + die Anreicherungs-/Cleaning-Unterschiede zwischen conversation und backup, + bleibt durch den 120er-Praefix aber spezifisch genug gegen Fehl-Matches.""" + t = _FILE_MARKER_RE.sub("", text or "") + t = _LEADING_BRACKET_RE.sub("", t) + t = _WS_RE.sub(" ", t).strip() + return t[:120] def run() -> dict: @@ -112,7 +130,7 @@ def run() -> dict: # 4) Sicherung + atomarer Rewrite. try: - bak = CHAT_BACKUP_FILE.with_suffix(".jsonl.pre-backfill-v1.bak") + bak = CHAT_BACKUP_FILE.with_suffix(".jsonl.pre-backfill-v2.bak") if not bak.exists(): bak.write_bytes(CHAT_BACKUP_FILE.read_bytes()) tmp = CHAT_BACKUP_FILE.with_suffix(".jsonl.tmp")