Files
iAOP/tests/e2e/test_cross_pipeline.py
T

108 lines
4.0 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
"""端到端联调用例(Issue #86)—— 跨链路集成场景。
验证数据流(采集 → 落库)与问答流(RAG → LLM 网关)的协同:
基于真实采集到的工艺数据,构建 RAG 知识并完成一次安全问答闭环,
模拟「采集 → 沉淀知识 → 智能问答」的完整业务闭环。
"""
from __future__ import annotations
# 引导加载四个内核模块(必须在测试导入前执行)
import tests.e2e._bootstrap # noqa: F401
import tempfile
import unittest
from collector.engine import CollectorEngine
from collector.metrics import HealthMetrics
from collector.spool import SpoolStore
from drivers import SimulatorDriver
from point_dict.loader import Point, PointDict
from data_bus import BatchWriter, MemorySink
from rag_kb import RagKnowledgeBase, build_document
from llm_gateway import (
GatewayResult,
LLMGateway,
LocalBackend,
PromptRegistry,
RouteTarget,
)
def _collect_samples(tmpdir: str):
"""跑一轮采集,返回(落库样本, 引擎健康度)。"""
points = [
Point(device_id="CLF-01", point_id="CLF-01.TEMP", name="1#炉温",
unit="℃", data_type="float", sample_rate=1000,
quality_code=True, row_number=2),
Point(device_id="CLF-01", point_id="CLF-01.PRES", name="1#炉压",
unit="kPa", data_type="float", sample_rate=1000,
quality_code=True, row_number=3),
]
pd = PointDict(points)
spool = SpoolStore(spool_dir=tmpdir, cache_limit_bytes=8 * 1024 * 1024)
metrics = HealthMetrics()
engine = CollectorEngine(
point_dict=pd,
driver_slots=[("simulator", SimulatorDriver(), [])],
spool=spool, metrics=metrics, interval_ms=1000, max_pending=100_000,
)
engine.collect_once()
sink = MemorySink()
writer = BatchWriter(sink=sink, batch_size=10, flush_interval=0.0)
for s in spool.pending_records():
writer.push(s)
spool.ack(s)
writer.flush()
return sink.rows, metrics
class CrossPipelineE2ETest(unittest.TestCase):
"""采集 → 落库 → 知识沉淀 → 安全问答 全业务闭环。"""
def test_collect_then_query_closed_loop(self) -> None:
"""采集数据落库后,结合工艺知识库完成一次安全问答。"""
tmpdir = tempfile.mkdtemp(prefix="iaop_cross_")
# 1) 数据流:采集并落库
rows, metrics = _collect_samples(tmpdir)
self.assertEqual(len(rows), 2) # 2 点位全部落库
self.assertTrue(metrics.meets_sla()) # 采集健康度达标
point_ids = {r["point_id"] for r in rows}
self.assertEqual(point_ids, {"CLF-01.TEMP", "CLF-01.PRES"})
# 2) 知识沉淀:工艺知识库(模拟由采集数据衍生的工艺规范)
kb = RagKnowledgeBase()
kb.add_documents([
build_document(
title="1#氯化炉工艺卡",
text="1#氯化炉(CLF-01)正常炉温 850~920℃,炉压 0.2~0.4MPa。"
"CLF-01.TEMP 与 CLF-01.PRES 为关键监控点位。",
category="process",
),
])
# 3) 问答流:基于知识库回答工艺问题
prompts = PromptRegistry()
prompts.update(name="qa", version="1.0.0",
text="工业 AI 助手回答:{query}")
gateway = LLMGateway(prompts=prompts, prompt_name="qa",
local=LocalBackend(echo_context=True))
query = "CLF-01 的关键监控点位和正常炉温范围?"
hits = kb.search(query, top_k=3)
sources = [h.chunk.title for h in hits]
self.assertGreater(len(sources), 0)
result = gateway.ask(query, rag_context=sources, confidence=0.95)
self.assertIsInstance(result, GatewayResult)
self.assertEqual(result.route.target, RouteTarget.LOCAL)
self.assertFalse(result.needs_human)
# 回答引用了知识库来源
self.assertIn(sources[0], result.answer)
if __name__ == "__main__":
unittest.main()