muse-agent-example/tests/集成/test_场景切片.py
zizi 6d1f635003 feat(上下文): 场景检索入口与片段参考进冻结链路——参考书场景原文可检索可改写
- 场景检索.py:切片语料两路等权RRF(键带slice:前缀),授权join过滤、代次陈旧拒绝、结果带书名预览双路得分;RRF抽公共融合入基础设施
- 参考材料双载体:references节判别式(方法/片段),片段冻结身份带来源内容哈希哨兵,现读核当前版本一致否则SOURCE_STALE
- 选段授权slice_references→范围授权→校验→依赖复检→装配→快照绑定全链贯通;片段不登记方法消费
- 范围校验source_ids基集、服务包装、依赖锁定键分派同步;B03接口增读取来源当前指纹(架构门禁禁私表)
- 集成a10032-a10036:检索知情候选/未建拒绝/撤回空/片段进快照/来源漂移失效
2026-09-20 00:08:29 +08:00

186 lines
7.3 KiB
Python

"""场景切片构建与读取:授权来源入池,用途撤回即退出候选;切片可全量重建。"""
import pytest
import test_模型修订任务 as 修订测试
from muse.资料研究.场景切片 import 计算切片
from muse.资料研究.接口 import (
导入请求,
构建场景索引,
读取场景切片,
资料服务,
)
pytestmark = pytest.mark.数据库
生成环境 = 修订测试.生成环境
def _导入(env, 连, *, 标题: str, origin: str, 用途: tuple[str, ...]) -> str:
来源 = 资料服务().导入(
连,
env["作者"].作者,
导入请求(
kind="reference",
title=标题,
origin=origin,
content="刀锋擦过装甲,反震顺着掌心爬上来。\n火花在真空中凝成细线。\n" * 400,
authorized_uses=用途,
),
)
return str(来源.source_id)
@pytest.fixture
def 切片环境(生成环境):
env = 生成环境
with env["装配"].要求数据库().连接() as 连:
env["授权来源"] = _导入(
env, 连, 标题="机甲打斗参考", origin="seed://slice-ref", 用途=("reference_reading",)
)
env["未授权来源"] = _导入(
env, 连, 标题="分析专用资料", origin="seed://slice-analysis", 用途=("analysis",)
)
return env
@pytest.mark.case_id(
"NC-w33-a10029",
environment="隔离PG与生成环境",
given="一个 reference_reading 授权来源与一个仅 analysis 来源",
when="构建场景索引并读取切片",
then=[
"仅授权来源入池,切片数与确定性计算一致",
"切片行携带书名、定位与来源版本内容哈希",
"重复构建为幂等重建,索引身份一致",
],
contract="docs/系统架构/新版设计/模块设计/B03-资料研究.md#场景片段切片与索引",
)
def test_构建场景索引只纳入授权来源__a10029(切片环境):
env = 切片环境
库 = env["装配"].要求数据库()
with 库.连接() as 连:
回执 = 构建场景索引(连, env["作者"].作者)
assert 回执["来源数"] == 1
assert 回执["切片数"] > 0
assert 回执["embedder"].startswith("hash-bigram-")
再次 = 构建场景索引(连, env["作者"].作者)
assert 再次["切片数"] == 回执["切片数"]
assert 再次["索引身份"] == 回执["索引身份"]
raw = 连.execute("SELECT slice_id FROM muse_source_slice").fetchall()
切片集 = [str(r[0]) for r in raw]
明细 = 读取场景切片(连, env["作者"].作者, 切片集)
assert len(明细) == 回执["切片数"]
assert all(条["书名"] == "机甲打斗参考" for 条 in 明细)
assert all(条["内容哈希"] for 条 in 明细)
# 未授权来源切片不出现。
assert all(条["source_id"] == env["授权来源"] for 条 in 明细)
@pytest.mark.case_id(
"NC-w33-a10030",
environment="隔离PG与生成环境",
given="已入池的授权来源",
when="撤回 reference_reading 用途后读取切片",
then=["读取返回空,切片行保留(派生缓存不删历史),重建后来源数归零"],
contract="docs/系统架构/新版设计/模块设计/B03-资料研究.md#场景片段切片与索引",
)
def test_用途撤回后切片退出候选__a10030(切片环境):
env = 切片环境
库 = env["装配"].要求数据库()
with 库.连接() as 连:
构建场景索引(连, env["作者"].作者)
当前 = 连.execute("SELECT slice_id FROM muse_source_slice LIMIT 1").fetchone()
# 测试关注读侧授权过滤,直接置空用途模拟撤回后的来源状态。
连.execute(
"UPDATE muse_source SET authorized_uses='[]'::jsonb WHERE source_id=%s",
(env["授权来源"],),
)
明细 = 读取场景切片(连, env["作者"].作者, [str(当前[0])])
assert 明细 == []
保留 = 连.execute("SELECT COUNT(*) FROM muse_source_slice").fetchone()[0]
assert 保留 > 0
回执 = 构建场景索引(连, env["作者"].作者)
assert 回执["来源数"] == 0 and 回执["切片数"] == 0
@pytest.mark.case_id(
"NC-w33-a10031",
environment="隔离PG与生成环境",
given="他人导入的授权来源",
when="以当前作者构建场景索引",
then=["来源不计入切片池:切片只对导入者视角构建"],
contract="docs/系统架构/新版设计/模块设计/B03-资料研究.md#场景片段切片与索引",
)
def test_非导入者来源不入池__a10031(切片环境):
env = 切片环境
with env["装配"].要求数据库().连接() as 连:
回执 = 构建场景索引(连, "other-author")
assert 回执["来源数"] == 0 and 回执["切片数"] == 0
assert 计算切片("有字。\n", env["授权来源"], 1)
@pytest.mark.case_id(
"NC-w33-a10032",
environment="隔离PG与生成环境",
given="已构建的授权来源切片索引",
when="以场景相关查询执行场景检索",
then=["两路融合返回切片:带书名、预览与双路得分;授权来源独占结果"],
contract="docs/系统架构/新版设计/模块设计/B09-上下文.md#场景片段检索",
)
def test_场景检索返回知情候选__a10032(切片环境):
env = 切片环境
库 = env["装配"].要求数据库()
from muse.上下文.接口 import 场景检索
with 库.连接() as 连:
构建场景索引(连, env["作者"].作者)
回执 = 场景检索(连, "刀锋擦过装甲 反震", 数量=3)
assert 回执["empty_reason"] is None
assert 1 <= len(回执["结果"]) <= 3
首 = 回执["结果"][0]
assert 首["书名"] == "机甲打斗参考"
assert "刀锋" in 首["预览"]
assert "关键词得分" in 首 and "向量得分" in 首 and 首["融合得分"] > 0
@pytest.mark.case_id(
"NC-w33-a10033",
environment="隔离PG与生成环境",
given="尚未构建切片索引的库",
when="执行场景检索",
then=["拒绝为索引陈旧,不静默返回空结果"],
contract="docs/系统架构/新版设计/模块设计/B09-上下文.md#场景片段检索",
)
def test_未建索引拒绝__a10033(生成环境):
env = 生成环境
from muse.上下文.接口 import 场景检索
from muse.上下文.模型 import 上下文错误
with env["装配"].要求数据库().连接(只读=True) as 连:
with pytest.raises(上下文错误):
场景检索(连, "任意查询")
@pytest.mark.case_id(
"NC-w33-a10034",
environment="隔离PG与生成环境",
given="授权来源用途被撤回后的切片索引",
when="执行场景检索",
then=["结果为空且说明可读,不扩大为索引不可用"],
contract="docs/系统架构/新版设计/模块设计/B09-上下文.md#场景片段检索",
)
def test_用途撤回后检索为空__a10034(切片环境):
env = 切片环境
库 = env["装配"].要求数据库()
from muse.上下文.接口 import 场景检索
with 库.连接() as 连:
构建场景索引(连, env["作者"].作者)
连.execute(
"UPDATE muse_source SET authorized_uses='[]'::jsonb WHERE source_id=%s",
(env["授权来源"],),
)
回执 = 场景检索(连, "刀锋", 数量=3)
assert 回执["结果"] == []