PMFlow/backend/tests/test_analysis_packet_golden...

408 lines
21 KiB
Python
Raw Permalink 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.

from __future__ import annotations
import pytest
from app.services.analysis_packet_builder import build_analysis_packet
from app.services.integrations.feishu_integration_service.mixin_receive_routing import (
FeishuReceiveRoutingMixin,
)
def _render_text(packet: dict[str, object]) -> str:
return FeishuReceiveRoutingMixin._build_feishu_qa_analysis_packet_reply_text(packet)
@pytest.mark.parametrize(
("case_name", "input_payload", "expected_fragments", "forbidden_fragments"),
[
(
"project_fit_inventory_responses_api",
{
"route_decision": {"route_mode": "external", "effective_source_policy": "external"},
"execution_recipe": {
"primary_lane": "external",
"fit_brief_required": True,
"external_evidence_required": True,
"plan_handoff_mode": "offer_after_answer",
},
"fit_brief": {"project_summary": "采购经理每日实时库存上报服务"},
"external_recommendation": {
"retrieval_status": "evidence_found",
"impact_status": "indirect_only",
},
"recommended_next_step": "先确认它在当前项目里具体承接哪个节点。",
"project_snapshot": {
"project_name": "采购经理每日实时库存上报服务",
"tasks": [
{
"id": 1,
"title": "每日固定时段生成并推送结构化摘要卡片",
"description": "每日凌晨触发全量计算,生成含标题、总水位摘要、TOP10表格的结构化文本卡片,并在上午10点前推送。",
},
{
"id": 2,
"title": "WMS库存快照自动拉取与清洗",
"description": "从WMS系统每小时拉取库存快照,按可用/在途/冻结三态聚合,清洗异常值后写入中台临时表。",
},
],
"signals": [
{
"id": 11,
"title": "外部信号源 - WMS实时库存接口",
"summary": "提供各仓库每小时更新的库存快照,作为水位与缺货计算的原始数据源。",
}
],
"analysis_object_refs": {
"fit_candidate_task_ref": {"kind": "task", "id": 1, "title": "每日固定时段生成并推送结构化摘要卡片"},
"fit_rejected_task_ref": {"kind": "task", "id": 2, "title": "WMS库存快照自动拉取与清洗"},
"primary_anchor_signal_ref": {"kind": "signal", "id": 11, "title": "外部信号源 - WMS实时库存接口"},
"primary_dependent_task_ref": {"kind": "task", "id": 2, "title": "WMS库存快照自动拉取与清洗"},
},
},
},
[
"每日固定时段生成并推送结构化摘要卡片",
"WMS库存快照自动拉取与清洗",
"先在这里试更稳",
"先定清楚它是给每日固定时段生成并推送结构化摘要卡片补说明",
],
["当前项目:", "先说我的判断", "到底承担什么角色"],
),
(
"project_fit_generic_titles_prefers_explicit_refs",
{
"route_decision": {"route_mode": "external", "effective_source_policy": "external"},
"execution_recipe": {
"primary_lane": "external",
"fit_brief_required": True,
"external_evidence_required": True,
"plan_handoff_mode": "offer_after_answer",
},
"fit_brief": {"project_summary": "库存异常播报助手"},
"external_recommendation": {
"retrieval_status": "evidence_found",
"impact_status": "indirect_only",
},
"recommended_next_step": "先确认它在项目里具体承接哪个节点。",
"project_snapshot": {
"project_name": "库存异常播报助手",
"tasks": [
{
"id": 21,
"title": "任务A",
"description": "每 15 分钟从仓储中台拉取异常库存快照,清洗后写入临时表供后续核算使用。",
},
{
"id": 22,
"title": "任务B",
"description": "根据前序结果生成发给值班同学的异常播报文本,并支持继续追问异常原因。",
},
],
"analysis_object_refs": {
"fit_candidate_task_ref": {"kind": "task", "id": 22, "title": "任务B"},
"fit_rejected_task_ref": {"kind": "task", "id": 21, "title": "任务A"},
},
},
},
["任务B", "任务A", "异常播报文本", "先在这里试更稳"],
["status_summary", "外部推荐"],
),
(
"project_fit_direct_match_inventory",
{
"route_decision": {"route_mode": "external", "effective_source_policy": "external"},
"execution_recipe": {
"primary_lane": "external",
"fit_brief_required": True,
"external_evidence_required": True,
"plan_handoff_mode": "offer_after_answer",
},
"fit_brief": {"project_summary": "采购经理每日实时库存上报服务"},
"external_recommendation": {
"retrieval_status": "evidence_found",
"impact_status": "direct_match",
"affected_signal_sources": ["外部信号源 - WMS实时库存接口"],
},
"recommended_next_step": "直接看它会影响哪条下游任务,再决定要不要进 plan。",
"project_snapshot": {
"project_name": "采购经理每日实时库存上报服务",
"tasks": [
{
"id": 31,
"title": "WMS库存快照自动拉取与清洗",
"description": "从WMS系统每小时拉取库存快照,按可用/在途/冻结三态聚合,清洗异常值后写入中台临时表。",
}
],
"signals": [
{
"id": 41,
"title": "外部信号源 - WMS实时库存接口",
"summary": "提供各仓库每小时更新的库存快照,作为水位与缺货计算的原始数据源。",
}
],
"analysis_object_refs": {
"primary_anchor_signal_ref": {"kind": "signal", "id": 41, "title": "外部信号源 - WMS实时库存接口"},
"primary_dependent_task_ref": {"kind": "task", "id": 31, "title": "WMS库存快照自动拉取与清洗"},
},
},
},
["WMS库存快照自动拉取与清洗", "外部信号源 - WMS实时库存接口"],
["当前项目:", "外部判断:"],
),
(
"external_verifier_blocked_inventory",
{
"route_decision": {"route_mode": "external", "effective_source_policy": "external"},
"external_recommendation": {
"retrieval_status": "verifier_blocked",
"impact_status": "no_direct_impact",
"external_action": "先修正证据质量,再决定是否继续外部推荐。",
},
"recommended_next_step": "先修正证据质量,再决定是否继续外部推荐。",
"project_snapshot": {
"project_name": "Alpha",
"tasks": [
{
"id": 51,
"title": "每日固定时段生成并推送结构化摘要卡片",
"description": "每日凌晨触发全量计算,生成结构化文本卡片,并在上午10点前推送。",
}
],
"signals": [
{
"id": 61,
"title": "外部信号源 - WMS实时库存接口",
"summary": "提供各仓库每小时更新的库存快照,作为水位与缺货计算的原始数据源。",
}
],
"analysis_object_refs": {
"primary_anchor_signal_ref": {"kind": "signal", "id": 61, "title": "外部信号源 - WMS实时库存接口"},
"primary_dependent_task_ref": {"kind": "task", "id": 51, "title": "每日固定时段生成并推送结构化摘要卡片"},
},
},
},
["外部信号源 - WMS实时库存接口", "每日固定时段生成并推送结构化摘要卡片", "核实清楚"],
["外部推荐", "证据质量"],
),
(
"external_direct_match_inventory",
{
"route_decision": {"route_mode": "external", "effective_source_policy": "external"},
"external_recommendation": {
"retrieval_status": "evidence_found",
"impact_status": "direct_match",
"affected_signal_sources": ["外部信号源 - WMS实时库存接口"],
},
"recommended_next_step": "直接看它会影响哪条下游任务,再决定要不要进 plan。",
"project_snapshot": {
"project_name": "采购经理每日实时库存上报服务",
"tasks": [
{
"id": 71,
"title": "WMS库存快照自动拉取与清洗",
"description": "从WMS系统每小时拉取库存快照,按可用/在途/冻结三态聚合,清洗异常值后写入中台临时表。",
}
],
"signals": [
{
"id": 72,
"title": "外部信号源 - WMS实时库存接口",
"summary": "提供各仓库每小时更新的库存快照,作为水位与缺货计算的原始数据源。",
}
],
"analysis_object_refs": {
"primary_anchor_signal_ref": {"kind": "signal", "id": 72, "title": "外部信号源 - WMS实时库存接口"},
"primary_dependent_task_ref": {"kind": "task", "id": 71, "title": "WMS库存快照自动拉取与清洗"},
},
},
},
["WMS库存快照自动拉取与清洗", "能对上的外部来源是外部信号源 - WMS实时库存接口", "不是泛泛相关"],
["status_summary", "当前项目:"],
),
(
"external_indirect_only_prefers_explanation_layer",
{
"route_decision": {"route_mode": "external", "effective_source_policy": "external"},
"external_recommendation": {
"retrieval_status": "evidence_found",
"impact_status": "indirect_only",
},
"recommended_next_step": "先确认它是不是只用在摘要卡片之后。",
"project_snapshot": {
"project_name": "采购经理每日实时库存上报服务",
"tasks": [
{
"id": 81,
"title": "每日固定时段生成并推送结构化摘要卡片",
"description": "每日凌晨触发全量计算,生成结构化文本卡片,并在上午10点前推送。",
},
{
"id": 82,
"title": "WMS库存快照自动拉取与清洗",
"description": "从WMS系统每小时拉取库存快照并写入中台临时表。",
},
],
"analysis_object_refs": {
"fit_candidate_task_ref": {"kind": "task", "id": 81, "title": "每日固定时段生成并推送结构化摘要卡片"},
"fit_rejected_task_ref": {"kind": "task", "id": 82, "title": "WMS库存快照自动拉取与清洗"},
},
},
},
["背景相关", "每日固定时段生成并推送结构化摘要卡片", "WMS库存快照自动拉取与清洗"],
["先说我的判断", "外部判断:"],
),
(
"internal_status_model_router",
{
"route_decision": {"route_mode": "internal", "effective_source_policy": "internal"},
"answer": "当前活动引擎是 Qwen 低阶引擎。",
"query_type": "status",
"evidence_pack": {"summary": {"conclusion": "当前活动引擎是 Qwen 低阶引擎。"}},
"internal_context_packet": {
"operation_contract": {"query_type": "status", "answer_contract": "status_summary"},
"target_resolution": {"primary_target_label": "模型路由配置"},
"query_plan": {"answer_contract": "status_summary"},
},
},
["当前活动引擎是 Qwen 低阶引擎", "模型路由配置", "当前情况回答"],
["status_summary", "泛化建议"],
),
(
"internal_status_with_uncertainty",
{
"route_decision": {"route_mode": "internal", "effective_source_policy": "internal"},
"answer": "当前活动引擎是 Qwen 低阶引擎。",
"query_type": "status",
"evidence_pack": {
"summary": {
"conclusion": "当前活动引擎是 Qwen 低阶引擎。",
"uncertainties": ["尚未确认是否已经切到最新灰度配置。"],
}
},
"internal_context_packet": {
"operation_contract": {"query_type": "status", "answer_contract": "status_summary"},
"target_resolution": {"primary_target_label": "模型路由配置"},
"query_plan": {"answer_contract": "status_summary"},
},
},
["当前活动引擎是 Qwen 低阶引擎", "模型路由配置", "先不展开方案"],
["status_summary", "contract"],
),
(
"followup_route_clarify",
{
"route_decision": {"route_mode": "uncertain", "effective_source_policy": "uncertain"},
"answer": "你是想问外部公开事实,还是系统内部配置/项目对象?",
"clarification_code": "query_route_clarify",
"anchor_kind": "reply_thread",
"meta_followup_kind": "route_selection",
"evidence_pack": {
"summary": {
"conclusion": "需要先确认查询来源。",
"uncertainties": ["内部还是外部"],
}
},
},
["需要先确认查询来源"],
["当前项目:", "status_summary"],
),
(
"feishu_render_fit_indirect",
{
"route_decision": {"route_mode": "external", "effective_source_policy": "external"},
"execution_recipe": {
"primary_lane": "external",
"fit_brief_required": True,
"plan_handoff_mode": "offer_after_answer",
},
"fit_brief": {"project_summary": "采购经理每日实时库存上报服务"},
"external_recommendation": {"retrieval_status": "evidence_found", "impact_status": "indirect_only"},
"recommended_next_step": "先确认它是不是只用在摘要卡片之后。",
"project_snapshot": {
"project_name": "采购经理每日实时库存上报服务",
"tasks": [
{
"id": 91,
"title": "每日固定时段生成并推送结构化摘要卡片",
"description": "每日凌晨触发全量计算,生成结构化文本卡片,并在上午10点前推送。",
},
{
"id": 92,
"title": "WMS库存快照自动拉取与清洗",
"description": "从WMS系统每小时拉取库存快照并写入中台临时表。",
},
],
"analysis_object_refs": {
"fit_candidate_task_ref": {"kind": "task", "id": 91, "title": "每日固定时段生成并推送结构化摘要卡片"},
"fit_rejected_task_ref": {"kind": "task", "id": 92, "title": "WMS库存快照自动拉取与清洗"},
},
},
},
["每日固定时段生成并推送结构化摘要卡片", "WMS库存快照自动拉取与清洗"],
["当前项目:", "先说我的判断"],
),
(
"feishu_render_verifier_blocked",
{
"route_decision": {"route_mode": "external", "effective_source_policy": "external"},
"external_recommendation": {"retrieval_status": "verifier_blocked", "impact_status": "no_direct_impact"},
"recommended_next_step": "先修正证据质量,再决定是否继续外部推荐。",
"project_snapshot": {
"project_name": "Alpha",
"tasks": [
{
"id": 101,
"title": "每日固定时段生成并推送结构化摘要卡片",
"description": "每日凌晨触发全量计算,生成结构化文本卡片,并在上午10点前推送。",
}
],
"signals": [
{
"id": 102,
"title": "外部信号源 - WMS实时库存接口",
"summary": "提供各仓库每小时更新的库存快照,作为水位与缺货计算的原始数据源。",
}
],
"analysis_object_refs": {
"primary_anchor_signal_ref": {"kind": "signal", "id": 102, "title": "外部信号源 - WMS实时库存接口"},
"primary_dependent_task_ref": {"kind": "task", "id": 101, "title": "每日固定时段生成并推送结构化摘要卡片"},
},
},
},
["核实清楚", "每日固定时段生成并推送结构化摘要卡片"],
["外部推荐", "证据质量"],
),
(
"feishu_render_internal_status",
{
"route_decision": {"route_mode": "internal", "effective_source_policy": "internal"},
"answer": "当前活动引擎是 Qwen 低阶引擎。",
"query_type": "status",
"evidence_pack": {"summary": {"conclusion": "当前活动引擎是 Qwen 低阶引擎。"}},
"internal_context_packet": {
"operation_contract": {"query_type": "status", "answer_contract": "status_summary"},
"target_resolution": {"primary_target_label": "模型路由配置"},
"query_plan": {"answer_contract": "status_summary"},
},
},
["当前活动引擎是 Qwen 低阶引擎", "模型路由配置"],
["status_summary", "泛化建议"],
),
],
)
def test_analysis_packet_golden_v2_cases(
case_name: str,
input_payload: dict[str, object],
expected_fragments: list[str],
forbidden_fragments: list[str],
) -> None:
_ = case_name
packet = build_analysis_packet(**input_payload)
assert packet["packet_type"]
rendered = _render_text(packet)
assert rendered
for fragment in expected_fragments:
assert fragment in rendered
for fragment in forbidden_fragments:
assert fragment not in rendered