feat(agents): v1.0 post-completion re-evaluation with forceReassess parameter
When users correct or update personal info after assessment completion, Coordinator can now re-run run_professional_assessment with forceReassess: true to bypass the 30-day dedup and produce an updated report. Changes: - Add forceReassess boolean param to run_professional_assessment tool definition - Skip already_assessed check when forceReassess=true in handler - Add prompt rules for identifying info corrections and triggering re-evaluation - Document the re-evaluation flow in sections 3.5 and 4.4 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
a72e718510
commit
aa9f31ff20
|
|
@ -493,6 +493,7 @@ invoke_assessment_expert 仅用于内部快速分析,结果不保存,不作
|
||||||
- userInfo:必须包含 age、nationality、education_level、work_experience_years
|
- userInfo:必须包含 age、nationality、education_level、work_experience_years
|
||||||
- targetCategories:用户感兴趣的类别(可选)
|
- targetCategories:用户感兴趣的类别(可选)
|
||||||
- conversationContext:最近对话摘要(可选)
|
- conversationContext:最近对话摘要(可选)
|
||||||
|
- forceReassess:布尔值(可选)。仅当用户在评估完成后**更正或补充了关键信息**时设为 true,跳过30天限制重新评估
|
||||||
- **返回的 status 值及处理方式**:
|
- **返回的 status 值及处理方式**:
|
||||||
- **payment_required**:用户未付费 → 说明费用,用户确认后调用 generate_payment
|
- **payment_required**:用户未付费 → 说明费用,用户确认后调用 generate_payment
|
||||||
- **info_incomplete**:信息不完整 → 根据 missingFieldLabels 向用户询问缺失信息
|
- **info_incomplete**:信息不完整 → 根据 missingFieldLabels 向用户询问缺失信息
|
||||||
|
|
@ -643,7 +644,7 @@ run_professional_assessment 会返回带 status 字段的结果,按以下方
|
||||||
3. **status: 'already_assessed'** → 已有有效评估(30天内)
|
3. **status: 'already_assessed'** → 已有有效评估(30天内)
|
||||||
- 告知用户已有评估报告
|
- 告知用户已有评估报告
|
||||||
- 展示 existingReport 中的结果
|
- 展示 existingReport 中的结果
|
||||||
- 如果用户有新信息想更新,告知30天后可重新评估
|
- 如果用户想更正信息重新评估,使用 forceReassess: true 重新调用(见下方「信息更正后重评估」)
|
||||||
|
|
||||||
4. **status: 'completed'** → 评估成功完成
|
4. **status: 'completed'** → 评估成功完成
|
||||||
- 按下方「评估结果的呈现」框架呈现结果
|
- 按下方「评估结果的呈现」框架呈现结果
|
||||||
|
|
@ -663,6 +664,17 @@ run_professional_assessment 会返回带 status 字段的结果,按以下方
|
||||||
b. **create_timeline** — 根据推荐路径创建「申请时间规划」
|
b. **create_timeline** — 根据推荐路径创建「申请时间规划」
|
||||||
3. 在回复中告知用户:"我已经为您生成了材料准备清单和申请时间规划,供您参考。"
|
3. 在回复中告知用户:"我已经为您生成了材料准备清单和申请时间规划,供您参考。"
|
||||||
|
|
||||||
|
**信息更正后重评估**:
|
||||||
|
|
||||||
|
评估完成后,用户可能会更正或补充关键个人信息(如"其实我工作经验是12年不是10年"、"我忘了说我有博士学位"等)。
|
||||||
|
遇到这种情况时:
|
||||||
|
|
||||||
|
1. **识别信息变更**:判断用户更正的信息是否会显著影响评估结果(如年龄、学历、工作年限、收入、国籍等核心字段)
|
||||||
|
2. **主动重新评估**:如果信息变更可能影响结果,主动调用 run_professional_assessment,传入**更新后的完整 userInfo**,并设置 **forceReassess: true**
|
||||||
|
3. **告知用户**:"您提供了新的信息,我正在用更新后的资料为您重新评估……"
|
||||||
|
4. 重新评估完成后,同样自动更新材料清单和时间线
|
||||||
|
5. **不要频繁重评估**:如果用户只是做小的澄清(如拼写错误、无关紧要的补充),不需要重新评估
|
||||||
|
|
||||||
**评估结果的呈现**:
|
**评估结果的呈现**:
|
||||||
|
|
||||||
评估是咨询的关键节点,呈现方式至关重要。
|
评估是咨询的关键节点,呈现方式至关重要。
|
||||||
|
|
|
||||||
|
|
@ -544,6 +544,12 @@ export const DIRECT_TOOLS: ToolDefinition[] = [
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: '最近几轮对话的简要摘要,帮助评估专家理解背景',
|
description: '最近几轮对话的简要摘要,帮助评估专家理解背景',
|
||||||
},
|
},
|
||||||
|
forceReassess: {
|
||||||
|
type: 'boolean',
|
||||||
|
description:
|
||||||
|
'强制重新评估(仅当用户在评估完成后更正了个人信息时使用)。' +
|
||||||
|
'设为 true 时跳过30天限制,用更新后的信息重新评估。',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
required: ['userInfo'],
|
required: ['userInfo'],
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1437,16 +1437,17 @@ export class ImmigrationToolsService {
|
||||||
context: ConversationContext,
|
context: ConversationContext,
|
||||||
onProgress?: (text: string) => void,
|
onProgress?: (text: string) => void,
|
||||||
): Promise<unknown> {
|
): Promise<unknown> {
|
||||||
const { userInfo, targetCategories, conversationContext } = input as {
|
const { userInfo, targetCategories, conversationContext, forceReassess } = input as {
|
||||||
userInfo: Record<string, unknown>;
|
userInfo: Record<string, unknown>;
|
||||||
targetCategories?: string[];
|
targetCategories?: string[];
|
||||||
conversationContext?: string;
|
conversationContext?: string;
|
||||||
|
forceReassess?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const tenantId = this.tenantContext.getCurrentTenantId() || '';
|
const tenantId = this.tenantContext.getCurrentTenantId() || '';
|
||||||
const userId = context.userId;
|
const userId = context.userId;
|
||||||
|
|
||||||
console.log(`[Tool:run_professional_assessment] User ${userId} - Starting assessment pipeline`);
|
console.log(`[Tool:run_professional_assessment] User ${userId} - Starting assessment pipeline (force=${!!forceReassess})`);
|
||||||
|
|
||||||
// ── Step 1: Check existing assessment ──
|
// ── Step 1: Check existing assessment ──
|
||||||
const existingReport = await this.artifactRepo.findOne({
|
const existingReport = await this.artifactRepo.findOne({
|
||||||
|
|
@ -1454,7 +1455,7 @@ export class ImmigrationToolsService {
|
||||||
order: { updatedAt: 'DESC' },
|
order: { updatedAt: 'DESC' },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (existingReport) {
|
if (existingReport && !forceReassess) {
|
||||||
const daysSinceReport = (Date.now() - existingReport.updatedAt.getTime()) / (1000 * 60 * 60 * 24);
|
const daysSinceReport = (Date.now() - existingReport.updatedAt.getTime()) / (1000 * 60 * 60 * 24);
|
||||||
|
|
||||||
if (daysSinceReport < 30) {
|
if (daysSinceReport < 30) {
|
||||||
|
|
@ -1475,6 +1476,10 @@ export class ImmigrationToolsService {
|
||||||
console.log(`[Tool:run_professional_assessment] Existing report is ${daysSinceReport.toFixed(1)} days old, allowing re-assessment`);
|
console.log(`[Tool:run_professional_assessment] Existing report is ${daysSinceReport.toFixed(1)} days old, allowing re-assessment`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (forceReassess && existingReport) {
|
||||||
|
console.log(`[Tool:run_professional_assessment] Force re-assessment requested — skipping 30-day check`);
|
||||||
|
}
|
||||||
|
|
||||||
// ── Step 2: Validate payment ──
|
// ── Step 2: Validate payment ──
|
||||||
if (!this.paymentClient) {
|
if (!this.paymentClient) {
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue