Files
yawan-workbench/server/tests/test_kb_metrics.py
T

96 lines
3.6 KiB
Python
Raw Normal View History

"""知识库消费指标单元测试(mock 数据,不依赖数据库)。"""
from types import SimpleNamespace
from unittest.mock import patch
from app.kb_metrics import kb_metrics, kb_metrics_overview
def _usage(agent_id, kb_id, chunk_id, segment_id, status="consumed"):
return SimpleNamespace(agent_id=agent_id, kb_id=kb_id, chunk_id=chunk_id,
segment_id=segment_id, status=status, file_name="f.md",
heading="h", excerpt="e")
def _segment(sid, references=None, status="approved"):
return SimpleNamespace(id=sid, status=status, references=references or [])
def _session(usage_rows, segments, kbs=()):
def exec(*_a, **_k):
# 简化:按调用顺序不可靠,直接用鸭子类型区分——这里用闭包计数不必要,
# kb_metrics_overview 内部按顺序 exec 三次:usage / kbs / segments,
# kb_metrics 内部两次:usage / segments。用可迭代队列处理。
raise AssertionError("请使用带计划的 mock")
return SimpleNamespace(exec=exec)
class _PlannedSession:
def __init__(self, queues):
self.queues = list(queues)
def exec(self, *_a, **_k):
return SimpleNamespace(all=lambda: self.queues.pop(0) if self.queues else [])
def get(self, model, row_id):
return None
def test_metrics_empty():
session = _PlannedSession([[], []])
report = kb_metrics(session)
assert report["hit_rate"] == 0.0
assert report["repeat_rate"] == 0.0
assert report["reference_coverage"] == 0.0
def test_hit_rate_and_repeat_rate():
usage = [
_usage(1, 1, "c1", 101), _usage(1, 1, "c2", 101),
_usage(2, 1, "c1", 102),
# 重复消费:agent1 再次用 c1(segment 103)→ pair (1, c1) 两条
_usage(1, 1, "c1", 103),
]
session = _PlannedSession([usage, []])
report = kb_metrics(session)
assert report["detail"]["hit_requests"] == 3 # (1,101)(2,102)(1,103)
assert report["detail"]["repeated_pairs"] == 1
assert report["repeat_rate"] == round(1 / 3, 4)
assert report["reference_coverage"] == 0.0 # 没有 segment 数据
def test_reference_coverage():
usage = [_usage(1, 1, "c1", 101)]
segments = [_segment(101, references=[{"file": "f"}]), _segment(102, references=[])]
session = _PlannedSession([usage, segments])
report = kb_metrics(session)
assert report["reference_coverage"] == 0.5
def test_miss_requests_lower_hit_rate():
usage = [_usage(1, 1, "c1", 101)]
# 段 102 是已完成的生产段但完全没有消费记录 → 记一次未命中
segments = [_segment(101, references=[{"x": 1}]), _segment(102)]
session = _PlannedSession([usage, segments])
report = kb_metrics(session)
assert report["detail"]["search_requests"] == 2
assert report["detail"]["miss_requests"] == 1
assert report["hit_rate"] == 0.5
def test_overview_by_kb_sorted():
usage = [
_usage(1, 1, "c1", 101), _usage(1, 1, "c2", 101),
_usage(1, 2, "c3", 102),
]
kbs = [
SimpleNamespace(id=1, name="主库", file_count=2, chunk_count=10),
SimpleNamespace(id=2, name="副库", file_count=1, chunk_count=10),
]
# kb_metrics_overview 先调 kb_metrics(usage, segments),再查 usage 和 kbs
session = _PlannedSession([usage, [], usage, kbs])
report = kb_metrics_overview(session)
assert report["by_kb"][0]["kb_id"] == 1 # 消费比 0.2 > 0.1
assert report["by_kb"][0]["consumed"] == 2
assert report["top_chunks"][0]["chunk_id"] == "c1" # c1 有 2 条记录(同 agent 两段)