- V0061:切片台账(窗计划哈希锁切窗方案、禁原地改写)、切片向量索引与代次台账,代次守卫仿 V0059 - 场景切片.py:段落聚合切窗纯函数(目标1800字符、末窗并邻)、确定性切片身份、全量重建命令与授权读取 - 只纳入 reference_reading 用途来源的导入者视角;用途撤回即退出候选,切片行保留 - 底座种子表登记切片代次单例;单元4例+集成3例全过
81 lines
3.4 KiB
Python
81 lines
3.4 KiB
Python
"""场景切片纯函数:段落聚合切窗与确定性身份;同输入同输出。"""
|
||
|
||
import pytest
|
||
|
||
from muse.资料研究.场景切片 import 切片计划哈希, 切片身份, 段落切窗
|
||
from muse.资料研究.接口 import 计算切片
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"NC-w33-a10025",
|
||
environment="离线纯函数",
|
||
given="含多段落的参考书原文与目标窗长",
|
||
when="执行段落聚合切窗",
|
||
then=["窗内长度达目标即闭合;末窗过短并入邻窗;窗口首尾相接覆盖全文"],
|
||
contract="docs/系统架构/新版设计/模块设计/B03-资料研究.md#场景片段切片与索引",
|
||
)
|
||
def test_段落聚合切窗覆盖全文且末窗并邻__a10025():
|
||
段 = "机甲的合金装甲在月光下泛着冷光。\n"
|
||
文本 = 段 * 200 # 每段约 17 字,200 段约 3400 字
|
||
窗口 = 段落切窗(文本, 窗长=1800)
|
||
assert 窗口[0]["起点"] == 0
|
||
assert 窗口[-1]["终点"] == len(文本) - 1 # 尾部换行不是内容,不入窗
|
||
for 甲, 乙 in zip(窗口, 窗口[1:], strict=False):
|
||
assert 乙["起点"] > 甲["终点"] # 段间换行符不入窗
|
||
assert 甲["终点"] - 甲["起点"] >= 1800
|
||
assert len(窗口) == 2
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"NC-w33-a10026",
|
||
environment="离线纯函数",
|
||
given="短于最短窗长的原文",
|
||
when="执行段落切窗",
|
||
then=["整文成单窗,不因短而拒绝"],
|
||
contract="docs/系统架构/新版设计/模块设计/B03-资料研究.md#场景片段切片与索引",
|
||
)
|
||
def test_短文成单窗__a10026():
|
||
文本 = "短打斗。\n一刀封喉。\n"
|
||
窗口 = 段落切窗(文本, 窗长=1800)
|
||
assert len(窗口) == 1
|
||
assert 窗口[0] == {"起点": 0, "终点": len(文本) - 1}
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"NC-w33-a10027",
|
||
environment="离线纯函数",
|
||
given="同一原文、来源身份与窗参数",
|
||
when="重复计算切片",
|
||
then=["切片身份、窗计划哈希与检索文本哈希逐次一致(确定性)"],
|
||
contract="docs/系统架构/新版设计/模块设计/B03-资料研究.md#场景片段切片与索引",
|
||
)
|
||
def test_切片计算确定性__a10027():
|
||
文本 = "刀锋擦过装甲。\n火花四散。\n" * 300
|
||
甲 = 计算切片(文本, "11111111-1111-1111-1111-111111111111", 1)
|
||
乙 = 计算切片(文本, "11111111-1111-1111-1111-111111111111", 1)
|
||
assert [r["slice_id"] for r in 甲] == [r["slice_id"] for r in 乙]
|
||
assert 甲[0]["窗计划哈希"] == 切片计划哈希(段落切窗(文本, 窗长=1800), 1800)
|
||
assert 甲[0]["slice_id"] == 切片身份(
|
||
"11111111-1111-1111-1111-111111111111", 1, 甲[0]["窗计划哈希"], 甲[0]["起点"]
|
||
)
|
||
# 版本号变化即身份变化:同文本不同版本不同身份。
|
||
丙 = 计算切片(文本, "11111111-1111-1111-1111-111111111111", 2)
|
||
assert 甲[0]["slice_id"] != 丙[0]["slice_id"]
|
||
|
||
|
||
@pytest.mark.case_id(
|
||
"NC-w33-a10028",
|
||
environment="离线纯函数",
|
||
given="空原文或非法窗长",
|
||
when="执行段落切窗",
|
||
then=["拒绝为资料错误,不产出空窗"],
|
||
contract="docs/系统架构/新版设计/模块设计/B03-资料研究.md#场景片段切片与索引",
|
||
)
|
||
def test_空文与非法窗长拒绝__a10028():
|
||
from muse.资料研究.模型 import 资料错误
|
||
|
||
with pytest.raises(资料错误):
|
||
段落切窗("", 窗长=1800)
|
||
with pytest.raises(资料错误):
|
||
段落切窗("有字。\n", 窗长=100)
|