Files
iAOP/core/rag-kb/tests/test_templating.py
T
yunmei 1fb1d278d5 feat: 完成 issue #46 RAG 知识库模板化接入(工艺规范/SOP/国标)
- core/rag-kb:领域 RAG 知识库按模板配置(PRD 5.4/7.3,EPIC #6 子任务)
- templating.py:知识源三类分类 + 模板命名推导 + 零依赖轻量 YAML 配置加载
- documents.py:文档段落抽取分块,chunk 携带 文档/章节/段落 溯源信息
- store.py:from_template_config 按模板自动构建 + 中英混合词频检索 + 类别过滤
- config/kb.template.yaml:ti-cl4 模板 RAG 库资产示例(工艺规范/SOP/国标)
- tests:29 用例全绿(模板化/分块溯源/检索排序/类别过滤/配置校验)
2026-08-04 16:31:31 +08:00

127 lines
4.5 KiB
Python
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.
# -*- coding: utf-8 -*-
"""模板化(templating)单元测试:知识源分类 / 命名推导 / YAML 配置加载。"""
import os
import sys
import unittest
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import _bootstrap # noqa: F401
from rag_kb.templating import ( # noqa: E402
KbTemplateConfig,
KbTemplateNaming,
KnowledgeSourceKind,
SOURCE_KINDS,
load_kb_config,
sanitize,
)
CONFIG_PATH = os.path.join(
os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
"config", "kb.template.yaml",
)
class SanitizeTest(unittest.TestCase):
def test_lower_and_replace_unsafe(self):
# 小写 + 空格等非安全字符替换为 `_`;RAG 命名**保留中文**(文档对象键)
self.assertEqual(sanitize("Ti-Cl4 模板"), "ti-cl4_模板")
self.assertEqual(sanitize("A.B-c_d"), "a.b-c_d")
def test_chinese_kept(self):
self.assertEqual(sanitize("沸腾氯化工艺规范"), "沸腾氯化工艺规范")
# `/` 属非安全字符,替换为 `_`
self.assertEqual(sanitize("GB/T 氯气安全使用标准"), "gb_t_氯气安全使用标准")
def test_empty_fallback(self):
self.assertEqual(sanitize(""), "kb")
self.assertEqual(sanitize("..."), "kb")
class SourceKindTest(unittest.TestCase):
def test_kinds_registered(self):
# 三类知识源固定注册(PRD 7.3:工艺规范 / SOP / 国标)
self.assertEqual(
set(SOURCE_KINDS),
{"process", "sop", "standard"},
)
def test_labels(self):
self.assertEqual(KnowledgeSourceKind.PROCESS.label, "工艺规范")
self.assertEqual(KnowledgeSourceKind.SOP.label, "SOP/操作手册")
self.assertEqual(KnowledgeSourceKind.STANDARD.label, "国标/标准")
class NamingTest(unittest.TestCase):
def setUp(self):
self.naming = KbTemplateNaming(template="ti-cl4")
def test_collection(self):
# 向量库 collection:下划线形态(对齐 data-bus `tpl_{tpl}` schema)
self.assertEqual(self.naming.collection(), "ti_cl4_kb")
def test_index_and_namespace(self):
self.assertEqual(self.naming.index_name(), "ti_cl4_kb_idx")
self.assertEqual(self.naming.namespace(), "tpl-ti-cl4-kb")
def test_doc_object_key(self):
self.assertEqual(
self.naming.doc_object_key("沸腾氯化工艺规范"),
"kb/沸腾氯化工艺规范.md",
)
def test_default_template(self):
self.assertEqual(KbTemplateNaming("").collection(), "kb_kb")
class YamlLoadTest(unittest.TestCase):
def test_load_example_config(self):
config = load_kb_config(CONFIG_PATH)
self.assertEqual(config.template, "ti-cl4")
self.assertEqual(config.version, "1.0.0")
# 三类知识源各至少声明一份文档
self.assertIn(KnowledgeSourceKind.PROCESS, {s.kind for s in config.sources})
self.assertIn(KnowledgeSourceKind.SOP, {s.kind for s in config.sources})
self.assertIn(KnowledgeSourceKind.STANDARD, {s.kind for s in config.sources})
self.assertGreaterEqual(len(config.all_documents()), 3)
def test_documents_for_kind(self):
config = load_kb_config(CONFIG_PATH)
docs = config.documents_for(KnowledgeSourceKind.PROCESS)
self.assertIn("沸腾氯化工艺规范", docs)
self.assertEqual(
config.documents_for(KnowledgeSourceKind.STANDARD),
["GB/T 氯气安全使用标准", "GB/T 钛及钛合金加工标准"],
)
def test_unknown_kind_rejected(self):
# 未知知识源类别必须报错(杜绝配置拼写漂移)
import tempfile
with tempfile.NamedTemporaryFile("w", suffix=".yaml", delete=False,
encoding="utf-8") as fh:
fh.write("template: ti-cl4\nsources:\n - kind: hmm\n documents: [a]\n")
path = fh.name
try:
with self.assertRaises(ValueError):
load_kb_config(path)
finally:
os.unlink(path)
def test_missing_template_rejected(self):
import tempfile
with tempfile.NamedTemporaryFile("w", suffix=".yaml", delete=False,
encoding="utf-8") as fh:
fh.write("version: 1.0.0\nsources: []\n")
path = fh.name
try:
with self.assertRaises(ValueError):
load_kb_config(path)
finally:
os.unlink(path)
if __name__ == "__main__":
unittest.main()