feat: 完成 issue #83 [树脂] 树脂 RAG 知识库导出
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
# GB/T 5475 离子交换树脂取样方法
|
||||
|
||||
- 规定离子交换树脂产品取样方法:从批中按规定数量抽取样品。
|
||||
- 取样要求代表性:不同包装单元均匀取样,混合后缩分。
|
||||
- 样品量:每批取样量按标准规定,样品密封保存并标识批次。
|
||||
- 取样记录:批次号、取样时间、取样人、样品编号(对齐 sample_id)。
|
||||
@@ -0,0 +1,6 @@
|
||||
# GB/T 8144 阳离子交换树脂交换容量测定方法
|
||||
|
||||
- 规定阳离子交换树脂交换容量(mmol/g)测定方法。
|
||||
- 原理:树脂经酸/碱转型后,用标准溶液滴定测定交换容量。
|
||||
- 结果用于质量分级:交换容量 ≥ 规定值(如 ≥ 4.2 mmol/g)为合格品。
|
||||
- 测定结果按批次录入 LIMS(tag_id: LIMS.ExchangeCapacity),供质量预测模型训练。
|
||||
@@ -0,0 +1,6 @@
|
||||
# GB/T 8330 离子交换树脂湿真密度测定方法
|
||||
|
||||
- 规定离子交换树脂湿真密度测定方法(比重瓶法)。
|
||||
- 湿真密度反映树脂交联度与孔结构,与交换容量、强度相关。
|
||||
- 测定条件:恒温(25℃)、湿态样品、排除气泡后称量。
|
||||
- 结果记录:按批次录入,作为工艺优化与质量追溯的辅助指标。
|
||||
@@ -0,0 +1,6 @@
|
||||
# 交接班报告生成规范
|
||||
|
||||
- 交接班报告须包含:生产概况、设备运行状态、异常与处置、安全注意事项、待办事项。
|
||||
- 异常事项必须标注发生时间、处理人与处置结果。
|
||||
- 待办事项需明确责任人与期望完成时间。
|
||||
- 每班次结束前 30 分钟生成,当班班长审核后交下一班。
|
||||
@@ -0,0 +1,7 @@
|
||||
# 交联度超标处置流程
|
||||
|
||||
1. 化验确认交联度超标(相对配方设计值偏差 > 5%)后,立即隔离该批树脂。
|
||||
2. 通知当班班长与质检科,暂停同一配方后续批次投料。
|
||||
3. 原因排查:DVB 计量偏差、搅拌不均、温度曲线漂移。
|
||||
4. 处置选项:回用(与低交联度批次调配)或降级(非标用途),由 QE 评审放行。
|
||||
5. 处置结果录入批次记录,并更新配方/工艺参数优化建议。
|
||||
@@ -0,0 +1,8 @@
|
||||
# 吸附树脂合成工艺规范
|
||||
|
||||
- 吸附树脂系列:ASC / ASD / HPR / ACD,采用悬浮聚合法,间歇/配方驱动生产。
|
||||
- 主要单体:苯乙烯(ST)+ 交联剂二乙烯苯(DVB),按配方比例投料。
|
||||
- 关键工艺参数:聚合温度 70–90℃,引发剂滴加速率按配方设定,搅拌转速 100–300 rpm。
|
||||
- 交联度(DVB 含量)直接影响树脂机械强度与交换容量,须按批次记录。
|
||||
- 生产批次按 batch_id 追踪,聚合时间 8–12 小时,出料后水洗、筛分。
|
||||
- 涉及车间:802(合成)、803(交联)、804(洗涤干燥),配污水/纯水/能源公用工程。
|
||||
@@ -0,0 +1,7 @@
|
||||
# 树脂合成异常处置SOP
|
||||
|
||||
- SOP-R-001:釜温超上限(>95℃)→ 立即停引发剂滴加、加大冷却水,10 分钟未回落按紧急排料流程。
|
||||
- SOP-R-002:釜压异常升高 → 停止加热、检查放空阀,联系仪表检修。
|
||||
- SOP-R-003:搅拌故障 → 降速至停止,启用备用搅拌(如有),未恢复则终止本批。
|
||||
- SOP-R-004:交联度超标(>设计值 15%)→ 该批隔离评审,按 QE 决定回用或降级。
|
||||
- 所有异常必须记录发生时间、处理人、处置措施与结果,纳入交接班报告。
|
||||
@@ -0,0 +1,8 @@
|
||||
# 离子交换树脂生产操作手册
|
||||
|
||||
- 开机前确认:原料计量罐、反应釜密封、加热/冷却系统、尾气处理正常。
|
||||
- 投料顺序:先加去离子水与分散剂,再按配方加入苯乙烯/二乙烯苯与引发剂。
|
||||
- 反应期间每 30 分钟记录一次釜温、釜压、搅拌转速。
|
||||
- 聚合完成判断:釜温回落且无明显放热,取样测交联度。
|
||||
- 洗涤:去离子水洗至 pH 中性;干燥:60–80℃ 流化干燥至含水率达标。
|
||||
- 停机:关闭加热与搅拌,釜内残余物料按危废流程处理。
|
||||
@@ -0,0 +1,67 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""树脂 RAG 知识库导出加载器 —— issue #83。
|
||||
|
||||
把已交付化工新材料AI平台(吸附树脂)的领域知识库**导出为模板资产**
|
||||
(`documents/*.md`),并提供与 `kb.resin.template.yaml` 清单一致的加载器:
|
||||
|
||||
- `resin_kb_loader(title)`:标题 → 文档文本(对齐 rag-kb 的 loader 约定,
|
||||
可直接用于 `RagKnowledgeBase.from_template_config(..., loader=resin_kb_loader)`);
|
||||
- `validate_export()`:校验 kb 清单声明的文档均有对应文件且非空
|
||||
(导出完整性检查,防止清单与文档漂移)。
|
||||
|
||||
标题规范化:`GB/T 5475 ...` → 文件名 `GB-T-5475 ....md`(`/` 不允许出现在文件名)。
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from typing import List, Optional
|
||||
|
||||
import yaml
|
||||
|
||||
#: 知识库配置资产(与模板清单同目录)
|
||||
DEFAULT_KB_CONFIG = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)), "kb.resin.template.yaml")
|
||||
|
||||
|
||||
def resin_documents_dir() -> str:
|
||||
"""文档集目录(documents/)。"""
|
||||
return os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
||||
"documents")
|
||||
|
||||
|
||||
def _doc_path(title: str) -> str:
|
||||
"""标题 → 文档文件路径(规范化:/ 与空格 → -,对齐导出文件名)。"""
|
||||
safe = title.replace("/", "-").replace(" ", "-")
|
||||
return os.path.join(resin_documents_dir(), f"{safe}.md")
|
||||
|
||||
|
||||
def resin_kb_loader(title: str) -> str:
|
||||
"""按标题返回文档文本(找不到返回空串,与 rag-kb loader 约定一致)。"""
|
||||
path = _doc_path(title)
|
||||
if not os.path.isfile(path):
|
||||
return ""
|
||||
with open(path, "r", encoding="utf-8") as fh:
|
||||
return fh.read()
|
||||
|
||||
|
||||
def load_kb_config(kb_config_path: str = DEFAULT_KB_CONFIG) -> dict:
|
||||
"""加载树脂知识库配置资产。"""
|
||||
with open(kb_config_path, "r", encoding="utf-8") as fh:
|
||||
return yaml.safe_load(fh) or {}
|
||||
|
||||
|
||||
def validate_export(kb_config_path: str = DEFAULT_KB_CONFIG) -> List[str]:
|
||||
"""校验导出完整性:清单声明的文档均有文件且非空。
|
||||
|
||||
Returns:
|
||||
缺失/为空的问题列表(空 = 导出完整)。
|
||||
"""
|
||||
problems: List[str] = []
|
||||
raw = load_kb_config(kb_config_path)
|
||||
for src in raw.get("sources", []):
|
||||
kind = src.get("kind")
|
||||
for doc in src.get("documents", []):
|
||||
text = resin_kb_loader(doc)
|
||||
if not text:
|
||||
problems.append(f"[{kind}] 文档缺失或为空: {doc}")
|
||||
return problems
|
||||
@@ -0,0 +1,84 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""树脂 RAG 知识库导出测试(issue #83)。
|
||||
|
||||
覆盖:
|
||||
1. kb.resin.template.yaml 清单声明的 9 篇文档全部导出且非空(validate_export);
|
||||
2. resin_kb_loader 按标题返回文本(含 GB/T 标题规范化);
|
||||
3. loader 可直接用于 RagKnowledgeBase(from_template_config + loader);
|
||||
4. 未知标题 → 空串。
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
_RAGKB_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
sys.path.insert(0, _RAGKB_DIR)
|
||||
from loader import ( # noqa: E402
|
||||
DEFAULT_KB_CONFIG,
|
||||
resin_kb_loader,
|
||||
validate_export,
|
||||
)
|
||||
|
||||
|
||||
class TestExportCompleteness(unittest.TestCase):
|
||||
"""导出完整性:清单 ↔ 文档文件一致。"""
|
||||
|
||||
def test_all_listed_documents_exported(self):
|
||||
problems = validate_export()
|
||||
self.assertEqual(problems, [], f"导出不完整: {problems}")
|
||||
|
||||
def test_document_count(self):
|
||||
docs = os.listdir(os.path.join(_RAGKB_DIR, "documents"))
|
||||
self.assertEqual(len(docs), 8)
|
||||
|
||||
|
||||
class TestLoader(unittest.TestCase):
|
||||
"""加载器行为。"""
|
||||
|
||||
def test_process_doc(self):
|
||||
text = resin_kb_loader("吸附树脂合成工艺规范")
|
||||
self.assertIn("悬浮聚合法", text)
|
||||
|
||||
def test_gbt_title_normalization(self):
|
||||
# 标题含 / → 文件名用 -(GB/T 5475 → GB-T-5475)
|
||||
text = resin_kb_loader("GB/T 5475 离子交换树脂取样方法")
|
||||
self.assertIn("取样", text)
|
||||
|
||||
def test_unknown_title_empty(self):
|
||||
self.assertEqual(resin_kb_loader("不存在的文档"), "")
|
||||
|
||||
def test_kb_config_loads(self):
|
||||
import yaml
|
||||
with open(DEFAULT_KB_CONFIG, "r", encoding="utf-8") as fh:
|
||||
raw = yaml.safe_load(fh)
|
||||
self.assertEqual(raw["template"], "resin")
|
||||
|
||||
|
||||
class TestRagKbIntegration(unittest.TestCase):
|
||||
"""与内核 rag-kb 集成(loader 直接可用)。"""
|
||||
|
||||
def test_build_kb_from_export(self):
|
||||
import importlib.util
|
||||
# 挂载 core/rag-kb(目录含连字符)
|
||||
repo_root = os.path.dirname(os.path.dirname(os.path.dirname(
|
||||
os.path.dirname(os.path.dirname(os.path.abspath(__file__))))))
|
||||
rag_kb_dir = os.path.join(repo_root, "core", "rag-kb")
|
||||
if "rag_kb" not in sys.modules:
|
||||
spec = importlib.util.spec_from_file_location(
|
||||
"rag_kb", os.path.join(rag_kb_dir, "__init__.py"),
|
||||
submodule_search_locations=[rag_kb_dir])
|
||||
_kb = importlib.util.module_from_spec(spec)
|
||||
sys.modules["rag_kb"] = _kb
|
||||
spec.loader.exec_module(_kb)
|
||||
|
||||
from rag_kb import RagKnowledgeBase, load_kb_config # noqa: E402
|
||||
|
||||
kb = RagKnowledgeBase.from_template_config(
|
||||
load_kb_config(DEFAULT_KB_CONFIG), loader=resin_kb_loader)
|
||||
self.assertGreater(kb.doc_count, 0)
|
||||
hits = kb.search("交换容量测定", top_k=3, categories=None)
|
||||
self.assertGreater(len(hits), 0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user