aps-agent/tests/golden/test_master_query_kb.py

174 lines
6.1 KiB
Python
Raw Permalink Normal View History

# ============================================================
# master.query + 机加工知识库黄金测试
# ============================================================
from __future__ import annotations
from server.aps_domain.kangni_intake import DEFAULT_ROUTE_XLSX, load_site_into_world
from server.aps_domain.master_query import format_master_query, run_master_query
from server.aps_domain.workflow import handle_intent
from server.contracts import IntentResult
from server.knowledge import get_knowledge
from server.state.seed import seed_world
from pathlib import Path
class _Mem:
def __init__(self, data):
self.data = data
def next_id(self, kind: str) -> int:
self.data[f"_c_{kind}"] = self.data.get(f"_c_{kind}", 100) + 1
return self.data[f"_c_{kind}"]
def save(self):
pass
def _world_site():
w = seed_world()
if Path(DEFAULT_ROUTE_XLSX).exists():
load_site_into_world(w, route_path=DEFAULT_ROUTE_XLSX, include_sibling_orders=False)
return w
def test_master_query_on_site_order():
w = _world_site()
if not Path(DEFAULT_ROUTE_XLSX).exists():
return
q = run_master_query(w, entity="order", code="102285668")
assert q["count"] >= 1
assert any(r["orderNo"] == "102285668" for r in q["rows"])
text = format_master_query(q)
assert "102285668" in text
bom = run_master_query(w, entity="bom", code="28200003654300")
assert bom["count"] >= 15
rt = run_master_query(w, entity="routing", code="28200003654300")
assert rt["count"] == 10
def test_master_query_requires_pi_structured_parameters():
w = _world_site()
missing_entity = run_master_query(w, text="帮我看看这个")
assert missing_entity["ok"] is False
assert "主数据类型" in missing_entity["error"]
missing_code = run_master_query(w, entity="order", text="查订单 102285668")
assert missing_code["ok"] is False
assert "编码" in missing_code["error"]
missing_aspect = run_master_query(w, entity="mrp", code="102285668")
assert missing_aspect["ok"] is False
assert "aspect" in missing_aspect["error"]
def test_machining_seed_assets_present():
kb = get_knowledge()
n = kb.ensure_seed_assets()
titles = {a["title"] for a in kb.assets}
assert "机加工工艺路线生成总则" in titles
assert "车削工艺路线模式" in titles
assert "机械装配工艺模式" in titles
assert "城轨机构装配路线模板" in titles
assert sum(1 for a in kb.assets if a.get("kind") == "process") >= 10
def test_chat_master_query_and_kb_catalog():
import asyncio
w = _world_site()
store = _Mem(w)
async def _run():
reply = await handle_intent(
store, "t",
IntentResult(intent="master.query", params={"entity": "overview", "query": "主数据概览"},
confidence=0.95, source="LLM"),
actor="test",
)
assert "主数据概览" in reply.text or "工厂" in reply.text
reply2 = await handle_intent(
store, "t",
IntentResult(intent="knowledge.query", params={"mode": "catalog", "query": "知识清单"},
confidence=0.95, source="LLM"),
actor="test",
)
assert "机加工工艺路线生成总则" in reply2.text
assert "知识库共" in reply2.text
asyncio.run(_run())
def test_schedule_this_order_deixis():
"""查完订单后带 orderRef=last 的 flex.schedule 请求应解析到会话焦点订单。"""
import asyncio
from server.agent_core.session_focus import get_last_order_no
w = _world_site()
if not Path(DEFAULT_ROUTE_XLSX).exists() or not w.get("flexOrders"):
return
store = _Mem(w)
sid = "deixis-sched"
r = IntentResult(intent="flex.schedule", params={"orderRef": "last"},
confidence=1.0, source="LLM")
async def _run():
q = IntentResult(intent="master.query",
params={"entity": "order", "code": "102285668"},
confidence=1.0, source="LLM")
await handle_intent(store, sid, q, actor="test")
assert get_last_order_no(sid) == "102285668"
reply = await handle_intent(store, sid, r, actor="test")
assert "闭环排产被阻断" in reply.text
assert "102285668" in reply.text
asyncio.run(_run())
def test_outsource_qa_and_plan_report():
"""委外查询(entity=mrp + orderRef=last)可答;排产方案报告可下载。"""
import asyncio
from server.agent_core.session_focus import set_focus
from server.aps_domain.flex import run_flex_schedule
from server.aps_domain.reports import build_plan_report
w = _world_site()
if not Path(DEFAULT_ROUTE_XLSX).exists() or not w.get("flexOrders"):
return
store = _Mem(w)
sid = "qa-report"
r = IntentResult(intent="master.query",
params={"entity": "mrp", "code": "102285668", "aspect": "outsource"},
confidence=1.0, source="LLM")
r_plan = IntentResult(intent="report.generate", params={"reportType": "plan"},
confidence=1.0, source="LLM")
run_flex_schedule(store, sort_mode="BOTTLENECK", actor="test")
plan = build_plan_report(w, order_no="102285668")
assert plan["reportId"]
assert plan.get("xlsxBytes")
assert plan["xlsxBytes"][:2] == b"PK" # zip/xlsx magic
assert "工作计划" in plan["markdown"] or "Excel" in plan["markdown"]
assert plan["snapshot"]["woCount"] == 0
assert plan["blocked"] is True
async def _run():
set_focus(sid, orderNo="102285668")
reply = await handle_intent(store, sid, r, actor="test")
assert "委外" in reply.text
assert "102285668" in reply.text
reply2 = await handle_intent(store, sid, r_plan, actor="test")
assert reply2.blocks and reply2.blocks[0].type == "report"
assert "排产阻断分析报告" in reply2.blocks[0].props["title"]
assert reply2.blocks[0].props.get("format") == "xlsx"
assert reply2.blocks[0].props.get("downloadUrl")
asyncio.run(_run())