127 lines
4.5 KiB
Python
127 lines
4.5 KiB
Python
# -*- 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()
|