83 lines
4.4 KiB
Python
83 lines
4.4 KiB
Python
"""HEL-835 synthetic-retrieval probe: seed an ISOLATED db (zero model calls).
|
|
|
|
Reviewer-approved plan (2026-10-24): 21+ synthetic old turns SQL-seeded with
|
|
handwritten gists; the single real DIALOGUE_MAIN call happens TOMORROW in the
|
|
same limited batch as the day-2 real question, against a throwaway service on
|
|
port 8351 that shares the ONE authoritative guard ledger. This script only
|
|
seeds and verifies - it never starts a service and never calls any model.
|
|
|
|
Run (server): cd /opt/cybergril-hel835/current && .venv/bin/python \
|
|
docs/r3/probe-seed-HEL-835.py /opt/cybergril-hel835-data/probe/seed.db
|
|
"""
|
|
import json
|
|
import sys
|
|
import time
|
|
from pathlib import Path
|
|
|
|
from cybergril.memory.store import Store
|
|
|
|
# Synthetic story: turn 0 holds the target memory (old poetry-collection chat);
|
|
# turns 1..20 are recent-window filler turns also mentioning the keyword, so a
|
|
# real retrieval must come from OUTSIDE the last-20-turn window by design.
|
|
TARGET_TURN = "00000000-probe-0000-4000-8000-000000000000"
|
|
FILLER_TURNS = [f"00000000-probe-0000-4000-8000-{i:012d}" for i in range(1, 21)]
|
|
TS0 = int(time.time() * 1000) - 26 * 3600 * 1000 # ~26h ago, before recent window
|
|
|
|
|
|
def seed(db_path: Path) -> dict:
|
|
db_path.parent.mkdir(parents=True, exist_ok=True)
|
|
if db_path.exists():
|
|
db_path.unlink()
|
|
with Store(db_path) as store:
|
|
with store.conn:
|
|
identity = {"name": "小满", "birth": "2001-05-21", "hour": "午时", "relation": "朋友",
|
|
"nickname": "", "boundary": "尊重彼此的节奏", "color": {}}
|
|
store.execute("INSERT INTO companion(id,identity_json) VALUES(1,?)",
|
|
(json.dumps(identity, ensure_ascii=False),))
|
|
rows = []
|
|
# Target old turn (outside the 20-turn window).
|
|
mid = store.execute(
|
|
"INSERT INTO chat_message(ts,role,text,turn_id,status) VALUES(?,?,?,?,'sent')",
|
|
(TS0, "user", "我今天在巷口旧书店买了一本蓝灰色封面的诗集。", TARGET_TURN),
|
|
).lastrowid
|
|
rows.append(("user", "我今天在巷口旧书店买了一本蓝灰色封面的诗集。",
|
|
"用户在巷口旧书店买了一本蓝灰色封面诗集。", TARGET_TURN, mid))
|
|
# Filler turns inside the recent window, same keyword, no poetry books.
|
|
for i, turn in enumerate(FILLER_TURNS, start=1):
|
|
text = f" filler topic {i}:雨天通勤和晚饭。"
|
|
mid = store.execute(
|
|
"INSERT INTO chat_message(ts,role,text,turn_id,status)"
|
|
" VALUES(?,?,?,?,'sent')", (TS0 + i * 60000, "user", text, turn),
|
|
).lastrowid
|
|
rows.append(("user", text, f"合成填充第{i}轮:与诗集无关。", turn, mid))
|
|
for role, raw, gist, turn, mid in rows:
|
|
store.execute(
|
|
"INSERT INTO mem_episodic(ts,role,raw,gist,salience,affect,source,accessibility,"
|
|
"turn_id,message_id) VALUES(?,?,?,?,0.5,NULL,'chat',1,?,?)",
|
|
(TS0, role, raw, gist, turn, mid),
|
|
)
|
|
store.execute("INSERT INTO life_control(key,value) VALUES('memory_search','on')"
|
|
" ON CONFLICT(key) DO UPDATE SET value='on'")
|
|
ids = {r["turn_id"]: r["id"] for r in store.query("SELECT id,turn_id FROM mem_episodic")}
|
|
n_msg = store.query_one("SELECT count(*) n FROM chat_message")["n"]
|
|
n_mem = store.query_one("SELECT count(*) n FROM mem_episodic")["n"]
|
|
return {"target_turn": TARGET_TURN, "target_memory_id": ids[TARGET_TURN],
|
|
"messages": n_msg, "memories": n_mem}
|
|
|
|
|
|
def main():
|
|
db_path = Path(sys.argv[1])
|
|
info = seed(db_path)
|
|
info["seeded_at"] = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
|
|
info["note"] = ("Synthetic fill for the approved retrieval probe. Handwritten gists, zero model "
|
|
"calls; target memory sits OUTSIDE the last-20-turn window by construction. "
|
|
"The single real DIALOGUE_MAIN runs tomorrow in the limited batch and is "
|
|
"counted against the shared authoritative guard ledger (6-turn cap).")
|
|
print(json.dumps(info, ensure_ascii=False, indent=1))
|
|
(db_path.parent / "seed-info.json").write_text(
|
|
json.dumps(info, ensure_ascii=False, indent=1), encoding="utf-8")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|