aps-agent/tests/golden/test_master_query_kb.py

174 lines
6.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ============================================================
# 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())