178 lines
6.0 KiB
Python
178 lines
6.0 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"] == 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())
|