Files
iAOP/core/rag-kb/tests/test_templating.py
T

127 lines
4.5 KiB
Python
Raw Normal View History

# -*- 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()