memoryweave/scripts/verify_7d_quality.py

153 lines
5.9 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
7 维度记忆质量验证脚本
用法: python3 scripts/verify_7d_quality.py [--id <memory_id>]
检查 LanceDB 中记忆的 7 个质量维度:
1. recall_count — 被召回次数(应随使用增加)
2. importance — 重要性 = recency × (1+log(1+recall_count))
3. quality_score — 综合质量评分0-1
4. useful_count — positive 反馈总数
5. not_useful_count — negative 反馈总数
6. tier — normal/corecore 永不衰减)
7. version — 版本号(更新溯源)
"""
import sys
import argparse
import lancedb
from pathlib import Path
DB_PATH = "/var/lib/memoryweave"
API_KEY = "zhiyi-dev-key-2026"
API_URL = "http://127.0.0.1:7821"
def get_memories(limit=2000):
db = lancedb.connect(DB_PATH)
tbl = db.open_table("memories")
return tbl.head(limit).to_pylist()
def check_recall_count(memories):
"""维度1: recall_count 应该 > 0 (被用过的记忆)"""
zero = sum(1 for r in memories if r.get("recall_count", 0) == 0)
nonzero = len(memories) - zero
pct = nonzero / len(memories) * 100 if memories else 0
status = "⚠️" if zero > len(memories) * 0.8 else ""
print(f" recall_count: {nonzero}/{len(memories)} ({pct:.1f}%) > 0 {status}")
if zero > len(memories) * 0.8:
print(" ⚠️ recall_count 几乎全为 0 → Go Update() 未正确处理 map[string]string $inc")
return zero <= len(memories) * 0.8
def check_importance(memories):
"""维度2: importance 应有差异recency × log(1+recall_count)"""
vals = [r.get("importance", 0) for r in memories]
unique = len(set(vals))
all_one = all(abs(v - 1.0) < 0.01 for v in vals)
status = "⚠️" if all_one else ""
print(f" importance: {unique} unique values, all≈1.0: {all_one} {status}")
if all_one:
print(" ⚠️ 所有 importance=1.0 → recall_count=0 导致公式退化")
return not all_one
def check_quality_score(memories):
"""维度3: quality_score 应有分布(不是全 0 或全 1"""
vals = [r.get("quality_score", 0) for r in memories if r.get("quality_score", 0) > 0]
if not vals:
print(" quality_score: 全为 0 ⚠️")
return False
unique = len(set(vals))
print(f" quality_score: {unique} unique, range [{min(vals):.2f}, {max(vals):.2f}] ✅")
return True
def check_feedback(memories):
"""维度4+5: useful_count / not_useful_count"""
useful = sum(1 for r in memories if r.get("useful_count", 0) > 0)
not_useful = sum(1 for r in memories if r.get("not_useful_count", 0) > 0)
print(f" useful_count: {useful} memories > 0")
print(f" not_useful_count: {not_useful} memories > 0")
return True
def check_tier(memories):
"""维度6: tier 分布"""
tiers = {}
for r in memories:
t = r.get("tier", "normal")
tiers[t] = tiers.get(t, 0) + 1
print(f" tier: {tiers}")
return True
def check_version(memories):
"""维度7: version 应 >= 1"""
v0 = sum(1 for r in memories if r.get("version", 0) < 1)
print(f" version: {v0}/{len(memories)} memories with version < 1 {'⚠️' if v0 else ''}")
return v0 == 0
def check_timestamps(memories):
"""时间戳: created_at / updated_at / last_recalled_at"""
zero_created = sum(1 for r in memories if r.get("created_at", "") == "" or "0001-01-01" in str(r.get("created_at", "")))
zero_updated = sum(1 for r in memories if r.get("updated_at", "") == "" or "0001-01-01" in str(r.get("updated_at", "")))
zero_recalled = sum(1 for r in memories if r.get("last_recalled_at", "") == "" or "0001-01-01" in str(r.get("last_recalled_at", "")))
print(f" timestamps: created_at zero={zero_created}, updated_at zero={zero_updated}, last_recalled_at zero={zero_recalled}")
return zero_created == 0
def verify_specific_memory(mem_id):
"""验证指定记忆的 7 维度详细值"""
memories = get_memories(5000)
target = [r for r in memories if r.get("id") == mem_id]
if not target:
print(f"Memory {mem_id} not found in first 5000 records")
return
r = target[0]
print(f"\n7维度详情 [{r.get('id', '?')[:20]}...]:")
print(f" recall_count: {r.get('recall_count', 0)}")
print(f" importance: {r.get('importance', 0):.4f}")
print(f" quality_score: {r.get('quality_score', 0):.4f}")
print(f" useful_count: {r.get('useful_count', 0)}")
print(f" not_useful_count: {r.get('not_useful_count', 0)}")
print(f" tier: {r.get('tier', 'normal')}")
print(f" version: {r.get('version', 1)}")
print(f" created_at: {r.get('created_at', '?')}")
print(f" updated_at: {r.get('updated_at', '?')}")
print(f" last_recalled_at: {r.get('last_recalled_at', '?')}")
def main():
parser = argparse.ArgumentParser(description="7维度记忆质量验证")
parser.add_argument("--id", help="检查特定记忆 ID")
parser.add_argument("--limit", type=int, default=2000, help="采样数量")
args = parser.parse_args()
print("=" * 50)
print("7维度记忆质量验证")
print("=" * 50)
if args.id:
verify_specific_memory(args.id)
return
memories = get_memories(args.limit)
print(f"\n采样 {len(memories)} 条记忆\n")
checks = [
("维度1: recall_count", check_recall_count),
("维度2: importance", check_importance),
("维度3: quality_score", check_quality_score),
("维度4+5: feedback", check_feedback),
("维度6: tier", check_tier),
("维度7: version", check_version),
("时间戳", check_timestamps),
]
all_ok = True
for name, fn in checks:
print(f"\n{name}:")
if not fn(memories):
all_ok = False
print("\n" + "=" * 50)
if all_ok:
print("✅ 所有维度正常")
else:
print("⚠️ 存在维度异常,见上方详情")
print("=" * 50)
if __name__ == "__main__":
main()