aps-agent/tests/golden/test_master_query_kb.py

177 lines
5.9 KiB
Python

# ============================================================
# master.query + 机加工知识库黄金测试
# ============================================================
from __future__ import annotations
from server.agent_core.intent import parse_fast
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_intent_master_query_orders():
w = seed_world()
r = parse_fast("有哪些订单", w)
assert r and r.intent == "master.query"
assert r.params.get("entity") == "order"
def test_intent_machining_knowledge():
w = seed_world()
r = parse_fast("机加工工艺怎么生成", w)
assert r and r.intent == "knowledge.query"
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_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="RULE_FAST"),
actor="test",
)
assert "主数据概览" in reply.text or "工厂" in reply.text
reply2 = await handle_intent(
store, "t",
IntentResult(intent="knowledge.query", params={"query": "知识清单"},
confidence=0.95, source="RULE_FAST"),
actor="test",
)
assert "机加工工艺路线生成总则" in reply2.text
assert "知识库共" in reply2.text
asyncio.run(_run())
def test_schedule_this_order_deixis():
"""查完订单后「把这个订单排产」应命中 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 = parse_fast("给我把这个订单进行计划排产", w)
assert r and r.intent == "flex.schedule"
assert r.params.get("orderRef") == "last"
r2 = parse_fast("给订单 102285668 计划排产", w)
assert r2 and r2.intent == "flex.schedule"
assert r2.params.get("orderNo") == "102285668"
async def _run():
q = parse_fast("查询订单 102285668", w)
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():
"""「这个订单有委外吗」可答;「生成排产方案报告」可下载。"""
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 = parse_fast("这个订单有委外订单吗?", w)
assert r and r.intent == "master.query"
assert r.params.get("entity") == "mrp"
assert r.params.get("orderRef") == "last"
r_plan = parse_fast("生成排产方案报告", w)
assert r_plan and r_plan.intent == "report.generate"
assert r_plan.params.get("reportType") == "plan"
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"] >= 1
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())