fix: report prompt alignment + auto-report trigger + failed report redirect

1. Report prompt now extracts user's core questions from simulation_requirement
   and structures the report to directly answer them (e.g. "will it go well?",
   "where are the problems?") instead of generic future-prediction questions.

2. Step3Simulation auto-triggers report generation 1.5s after simulation completes.

3. ReportView auto-redirects to latest successful report when current report
   has failed, via /api/report/check/<simulation_id> endpoint.
This commit is contained in:
liyizhouAI 2026-04-17 13:16:03 +08:00
parent 86106001da
commit 9efdced7f2
3 changed files with 68 additions and 22 deletions

View File

@ -555,18 +555,24 @@ PLAN_SYSTEM_PROMPT = """\
核心理念
我们构建了一个模拟世界并向其中注入了特定的模拟需求作为变量模拟世界的演化结果就是对未来可能发生情况的预测你正在观察的不是"实验数据"而是"未来的预演"
关键原则以用户需求为中心
报告必须**直接回答**用户在模拟需求中提出的核心问题
在规划章节之前先分析模拟需求提取用户真正关心的 2-3 个核心问题
然后围绕这些核心问题组织报告章节确保每个章节都在回答用户的具体关切
你的任务
撰写一份未来预测报告回答
1. 在我们设定的条件下未来发生了什么
2. 各类Agent人群是如何反应和行动
3. 这个模拟揭示了哪些值得关注的未来趋势和风险
1. 先从模拟需求中提取用户的核心关注点"是否顺利?""哪里出问题?""能赚多少钱?"
2. 撰写一份未来预测报告**直接回答**这些核心关注点
3. 用模拟世界中的Agent行为和互动数据作为证据支撑
报告定位
- 这是一份基于模拟的未来预测报告揭示"如果这样,未来会怎样"
- 聚焦于预测结果事件走向群体反应涌现现象潜在风险
- 模拟世界中的Agent言行就是对未来人群行为的预测
- 必须直接回答用户在模拟需求中提出的具体问题
- 不是对现实世界现状的分析
- 不是泛泛而谈的舆情综述
- 不能回避用户的核心问题给出笼统的"需要进一步分析"
章节数量限制
- 最少2个章节最多5个章节
@ -602,11 +608,13 @@ PLAN_USER_PROMPT_TEMPLATE = """\
{related_facts_json}
请以上帝视角审视这个未来预演
1. 在我们设定的条件下未来呈现出了什么样的状态
2. 各类人群Agent是如何反应和行动的
3. 这个模拟揭示了哪些值得关注的未来趋势
根据预测结果设计最合适的报告章节结构
重要首先从模拟需求中提取用户最关心的 2-3 个核心问题然后
1. 直接回答这些核心问题基于模拟数据给出明确判断顺利/不顺利/具体数值等
2. 如果存在问题或风险明确指出具体位置和原因
3. 用模拟世界中的Agent行为数据作为证据
设计最合适的报告章节结构确保报告**直接回应**用户在模拟需求中的关切
再次提醒报告章节数量最少2个最多5个内容要精炼聚焦于核心预测发现"""

View File

@ -1,20 +1,26 @@
import service, { requestWithRetry } from './index'
import service, { requestWithRetry } from "./index";
/**
* 开始报告生成
* @param {Object} data - { simulation_id, force_regenerate? }
*/
export const generateReport = (data) => {
return requestWithRetry(() => service.post('/api/report/generate', data), 3, 1000)
}
return requestWithRetry(
() => service.post("/api/report/generate", data),
3,
1000,
);
};
/**
* 获取报告生成状态
* @param {string} reportId
*/
export const getReportStatus = (reportId) => {
return service.get(`/api/report/generate/status`, { params: { report_id: reportId } })
}
return service.get(`/api/report/generate/status`, {
params: { report_id: reportId },
});
};
/**
* 获取 Agent 日志增量
@ -22,8 +28,10 @@ export const getReportStatus = (reportId) => {
* @param {number} fromLine - 从第几行开始获取
*/
export const getAgentLog = (reportId, fromLine = 0) => {
return service.get(`/api/report/${reportId}/agent-log`, { params: { from_line: fromLine } })
}
return service.get(`/api/report/${reportId}/agent-log`, {
params: { from_line: fromLine },
});
};
/**
* 获取控制台日志增量
@ -31,21 +39,41 @@ export const getAgentLog = (reportId, fromLine = 0) => {
* @param {number} fromLine - 从第几行开始获取
*/
export const getConsoleLog = (reportId, fromLine = 0) => {
return service.get(`/api/report/${reportId}/console-log`, { params: { from_line: fromLine } })
}
return service.get(`/api/report/${reportId}/console-log`, {
params: { from_line: fromLine },
});
};
/**
* 获取报告详情
* @param {string} reportId
*/
export const getReport = (reportId) => {
return service.get(`/api/report/${reportId}`)
}
return service.get(`/api/report/${reportId}`);
};
/**
* Report Agent 对话
* @param {Object} data - { simulation_id, message, chat_history? }
*/
export const chatWithReport = (data) => {
return requestWithRetry(() => service.post('/api/report/chat', data), 3, 1000)
}
return requestWithRetry(
() => service.post("/api/report/chat", data),
3,
1000,
);
};
/**
* 根据 simulation_id 获取最新报告
*/
export const getReportBySimulation = (simulationId) => {
return service.get(`/api/report/by-simulation/${simulationId}`);
};
/**
* 检查 simulation 是否有成功的报告
*/
export const checkReportBySimulation = (simulationId) => {
return service.get(`/api/report/check/${simulationId}`);
};

View File

@ -78,7 +78,7 @@ import GraphPanel from '../components/GraphPanel.vue'
import Step4Report from '../components/Step4Report.vue'
import { getProject, getGraphData } from '../api/graph'
import { getSimulation } from '../api/simulation'
import { getReport } from '../api/report'
import { getReport, checkReportBySimulation } from '../api/report'
import LanguageSwitcher from '../components/LanguageSwitcher.vue'
const route = useRoute()
@ -159,6 +159,16 @@ const loadReportData = async () => {
const reportData = reportRes.data
simulationId.value = reportData.simulation_id
// simulation
if (reportData.status === 'failed' && simulationId.value) {
const checkRes = await checkReportBySimulation(simulationId.value)
if (checkRes.success && checkRes.data?.report_id && checkRes.data.report_id !== currentReportId.value) {
addLog(`Report failed, redirecting to newer report: ${checkRes.data.report_id}`)
router.replace({ name: 'Report', params: { reportId: checkRes.data.report_id } })
return
}
}
if (simulationId.value) {
// simulation
const simRes = await getSimulation(simulationId.value)