feat(roundtable): xdfx 左上角只显行动名/cop-task-detail可mock/抽取根节点用行动名
- xdfx 深链左上角「当前行动」只显示行动名称,去掉行动叙事 - cop-task-detail 加本地假数据开关 VITE_MOCK_COP_TASK_DETAIL(仿 VITE_MOCK_SQ_REPORT): true 走 mockCopTaskDetail(dev=true,sit/network=false);真实接口未就绪时调试用 - 结构化抽取(flow-json):FlowExtractRequest 加 root_label,xdfx 强制根节点 n1 的 label 用本次「行动名称」(前端 useStep3Summary 传 readActionDetail().actionName);extract+validate 两段都注入 注:行动详情 mock(actionName/narration) 在 config.yaml(按惯例不提交)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
b513a0d56c
commit
fba417918f
8 files changed
+55
-16
No files matched your search
@@ -10,6 +10,9 @@ VITE_MOCK_COP_TASK_DETAIL=true
|
||||
# 研判情报报告(大屏绘制智能体深链 selectSqReport)数据源:true 走本地样例假数据(真实接口未就绪时调试用);联调通过后置 false。
|
||||
VITE_MOCK_SQ_REPORT=true
|
||||
|
||||
# 深链任务详情(cop-task-detail:任务名称/描述)数据源:true 走本地假数据(真实接口未就绪时调试用);联调通过后置 false。
|
||||
VITE_MOCK_COP_TASK_DETAIL=true
|
||||
|
||||
# Gateway / DeerFlow API
|
||||
VITE_BACKEND_BASE_URL=http://127.0.0.1:8001
|
||||
VITE_LANGGRAPH_BASE_URL=http://127.0.0.1:8001/api
|
||||
|
||||
@@ -10,6 +10,9 @@ VITE_MOCK_COP_TASK_DETAIL=false
|
||||
# 研判情报报告(大屏绘制智能体深链 selectSqReport)数据源:默认真实接口;真实接口未就绪可改 true 走本地样例假数据。
|
||||
VITE_MOCK_SQ_REPORT=false
|
||||
|
||||
# 深链任务详情(cop-task-detail)数据源:默认真实接口;真实接口未就绪可改 true 走本地假数据。
|
||||
VITE_MOCK_COP_TASK_DETAIL=false
|
||||
|
||||
# Gateway / DeerFlow API
|
||||
VITE_BACKEND_BASE_URL=http://47.88.25.99:7001
|
||||
VITE_LANGGRAPH_BASE_URL=http://47.88.25.99:7001/api
|
||||
|
||||
@@ -10,6 +10,9 @@ VITE_MOCK_COP_TASK_DETAIL=false
|
||||
# 研判情报报告(大屏绘制智能体深链 selectSqReport)数据源:默认真实接口;真实接口未就绪可改 true 走本地样例假数据。
|
||||
VITE_MOCK_SQ_REPORT=false
|
||||
|
||||
# 深链任务详情(cop-task-detail)数据源:默认真实接口;真实接口未就绪可改 true 走本地假数据。
|
||||
VITE_MOCK_COP_TASK_DETAIL=false
|
||||
|
||||
# Gateway / DeerFlow API
|
||||
VITE_BACKEND_BASE_URL=https://ch1.b.sit.4.cn/deerflow
|
||||
VITE_LANGGRAPH_BASE_URL=https://ch1.b.sit.4.cn/deerflow/api
|
||||
|
||||
@@ -77,8 +77,28 @@ function consumerBaseUrl(): string {
|
||||
return typeof value === "string" ? value.replace(/\/+$/, "") : "";
|
||||
}
|
||||
|
||||
/** 拉取任务详情;缺少 consumer 地址 / 返回不合法时返回 null。 */
|
||||
/** cop-task-detail 是否走本地假数据:开关 `VITE_MOCK_COP_TASK_DETAIL=true`(真实接口未就绪时调试用)。 */
|
||||
function copTaskDetailMockEnabled(): boolean {
|
||||
return (import.meta.env as Record<string, unknown>).VITE_MOCK_COP_TASK_DETAIL === "true";
|
||||
}
|
||||
|
||||
/** cop-task-detail 本地假数据(与真实 data 字段同构;mock 开关开启时返回)。 */
|
||||
function mockCopTaskDetail(taskId: string): CopTaskDetail {
|
||||
return {
|
||||
id: taskId || "2055",
|
||||
overview: "暑期文旅消费高峰期间的舆情态势综合研判与引导任务(本地假数据)。",
|
||||
taskDirection: "正向引导 + 风险预警",
|
||||
taskName: "任务01:暑期文旅舆情综合研判",
|
||||
taskContent:
|
||||
"围绕暑期文旅消费高峰,对重点城市、重点景区的公众情绪与舆情态势做综合研判,识别情绪拐点与潜在风险,提出正向引导与处置建议。",
|
||||
};
|
||||
}
|
||||
|
||||
/** 拉取任务详情;``VITE_MOCK_COP_TASK_DETAIL=true`` 走假数据;缺少 consumer 地址 / 返回不合法时返回 null。 */
|
||||
export async function fetchCopTaskDetail(taskId: string): Promise<CopTaskDetail | null> {
|
||||
if (copTaskDetailMockEnabled()) {
|
||||
return mockCopTaskDetail(taskId);
|
||||
}
|
||||
const base = consumerBaseUrl();
|
||||
if (!base || !taskId) return null;
|
||||
// service 拦截器已统一注入 `Authorization: Bearer admin` 并返回 response.data(整包 body)。
|
||||
|
||||
@@ -84,6 +84,8 @@ export interface FlowExtractRequest {
|
||||
coordinatorPrompt?: string | null;
|
||||
/** 深链接业务码(rwfx→6BF 等)。非空 → 后端按业务链抽取规范强制注入完整层级。 */
|
||||
businessCode?: string | null;
|
||||
/** 根节点 label 强制值(xdfx:本次行动名称)。非空 → 根节点 n1 用它,不用任务名当根。 */
|
||||
rootLabel?: string | null;
|
||||
/** 推理模型名(沿用第三步所选)。 */
|
||||
model?: string;
|
||||
/** Phase 2 问答修改:当前流程图 + 指令 → 按指令改图(其余不变)。 */
|
||||
@@ -112,6 +114,7 @@ export async function streamFlowExtract(req: FlowExtractRequest): Promise<FlowGr
|
||||
chain_levels: req.chainLevels ?? [],
|
||||
coordinator_prompt: req.coordinatorPrompt ?? null,
|
||||
business_code: req.businessCode ?? null,
|
||||
root_label: req.rootLabel ?? null,
|
||||
model: req.model,
|
||||
current_graph: req.currentGraph ?? null,
|
||||
instruction: req.instruction ?? null,
|
||||
|
||||
@@ -49,6 +49,7 @@ import {
|
||||
type FlowIntent,
|
||||
} from "@/roundtable-planning/api/flow-extract";
|
||||
import { nowTime } from "@/roundtable-planning/lib/roundtable-constants";
|
||||
import { readActionDetail } from "@/core/auth/task-deeplink";
|
||||
|
||||
/** 报告输出文件的固定虚拟路径(恢复历史快照时用它重建 stub)。 */
|
||||
const SUMMARY_OUTPUT_PATH = "/mnt/user-data/outputs/方案总结报告.md";
|
||||
@@ -1142,6 +1143,9 @@ export function useStep3Summary(
|
||||
coordinatorPrompt,
|
||||
// 深链接业务码:后端按业务链抽取规范强制注入完整层级(根治"无论什么业务都按目的→行为体抽")。
|
||||
businessCode: ingestBusinessCodeRef.current,
|
||||
// xdfx(7BF):根节点用「行动名称」(流程图根节点显示当前行动,而非任务名)。
|
||||
rootLabel:
|
||||
ingestBusinessCodeRef.current === "7BF" ? readActionDetail()?.actionName ?? null : null,
|
||||
model: selectedModel || undefined,
|
||||
currentGraph: opts?.currentGraph ?? null,
|
||||
instruction: opts?.instruction,
|
||||
|
||||
@@ -2835,19 +2835,11 @@ function RoundtableEntryRail({
|
||||
</span>
|
||||
<h2 className="text-sm font-semibold tracking-wide text-slate-900">当前行动</h2>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<div>
|
||||
<p className="text-[10px] font-semibold uppercase tracking-wide text-slate-400">行动名称</p>
|
||||
<p className="mt-0.5 text-xs font-semibold leading-relaxed text-slate-800">
|
||||
{actionDetail?.actionName?.trim() || "(未获取到行动名称)"}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-[10px] font-semibold uppercase tracking-wide text-slate-400">行动叙事</p>
|
||||
<p className="mt-0.5 whitespace-pre-wrap text-[11px] leading-relaxed text-slate-600">
|
||||
{actionDetail?.narration?.trim() || "(未获取到行动叙事)"}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-[10px] font-semibold uppercase tracking-wide text-slate-400">行动名称</p>
|
||||
<p className="mt-0.5 text-xs font-semibold leading-relaxed text-slate-800">
|
||||
{actionDetail?.actionName?.trim() || "(未获取到行动名称)"}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
|
||||
@@ -64,6 +64,8 @@ class FlowExtractRequest(BaseModel):
|
||||
# 深链接业务码(rwfx→6BF 等)。非空 → 按该业务的「业务链抽取规范」**强制**注入完整层级
|
||||
# (覆盖默认/示例层级假设),根治"无论什么业务都按目的→行为体抽"。普通会商为空 → 不注入。
|
||||
business_code: str | None = Field(default=None)
|
||||
# 根节点 label 强制值(xdfx:本次「行动名称」)。非空 → 根节点 n1 的 label 必须用它,不要用任务名当根。
|
||||
root_label: str | None = Field(default=None)
|
||||
model: str | None = Field(default=None)
|
||||
# Phase 2 问答修改:带上当前图 + 用户指令 → 进 edit 模式(按指令改图,其余不变)。
|
||||
current_graph: dict[str, Any] | None = Field(default=None)
|
||||
@@ -462,6 +464,14 @@ def _hierarchy_hint(req: FlowExtractRequest) -> str:
|
||||
return "层级顺序:以「任务」为根,按报告/交付的逻辑结构合理分层展开。"
|
||||
|
||||
|
||||
def _root_label_hint(req: FlowExtractRequest) -> str:
|
||||
"""根节点 label 强制提示:xdfx 用「行动名称」当根节点(而非任务名)。无 root_label → 空。"""
|
||||
label = (req.root_label or "").strip()
|
||||
if not label:
|
||||
return ""
|
||||
return f"\n【根节点强制】整张图的根节点 n1 的 label **必须**用本次行动名称:「{label}」——不要用任务名/其它当根节点。"
|
||||
|
||||
|
||||
# 兜底系统提示:当 roundtable-structure 的 SOUL 缺失时用它(与 SOUL 同款契约)。
|
||||
_DEFAULT_SYSTEM = (
|
||||
"你是「结构化抽取智能体」。职责:读懂《方案总结报告》/ 各席位交付内容,分析其层级结构,"
|
||||
@@ -499,6 +509,7 @@ def _extract_messages(req: FlowExtractRequest) -> list[Any]:
|
||||
_material(req)
|
||||
+ "\n\n"
|
||||
+ _hierarchy_hint(req)
|
||||
+ _root_label_hint(req)
|
||||
+ "\n\n请分析以上数据来源,按你的职责设定输出一个完整的 ```flow-json 代码块。"
|
||||
)
|
||||
return [SystemMessage(content=_system_prompt()), HumanMessage(content=user)]
|
||||
@@ -520,9 +531,9 @@ def _edit_messages(req: FlowExtractRequest) -> list[Any]:
|
||||
|
||||
|
||||
def _validate_messages(req: FlowExtractRequest, extracted: str) -> list[Any]:
|
||||
# 深链接业务规范:校验阶段也带上完整层级,确保按规范补齐缺层(不只按抽取里出现的层级)。
|
||||
# 深链接业务规范:校验阶段也带上完整层级 + 根节点强制,确保按规范补齐缺层、根节点用行动名。
|
||||
spec = build_structure_directive(req.business_code)
|
||||
spec_block = (spec + "\n\n") if spec else ""
|
||||
spec_block = (spec + _root_label_hint(req) + "\n\n") if (spec or req.root_label) else ""
|
||||
user = (
|
||||
spec_block
|
||||
+ _material(req)
|
||||
|
||||
Reference in new issue
Block a user