feat(steward): 前端支持 off_topic 与引导话术
- assistantSessionScope.js:新增 ASSISTANT_SCOPE_ACTION_FILL_COMPOSER 常量 - assistantSuggestedActionPrefill.js:识别 fill_composer 与 payload.fill_text - stewardPlanModel.js:normalizeStewardPlan 透传 suggestedPrompts; buildStewardPlanMessageText / buildStewardSuggestedActions 新增 off_topic 分支,按钮填充输入框不提交 - useStewardPlanFlow.js:isPendingStewardActionMessage 排除 off_topic - steward-plan-off-topic.test.mjs:覆盖 normalize/文案/按钮/兼容路径
This commit is contained in:
@@ -2,6 +2,8 @@ import ontologyBusinessContract from '../../../shared/ontology_business_contract
|
||||
|
||||
export const ASSISTANT_SCOPE_ACTION_SWITCH = 'switch_assistant_session'
|
||||
export const ASSISTANT_SCOPE_ACTION_UNSUPPORTED = 'unsupported_business_intent'
|
||||
// 点击后把 payload.fill_text 填充到输入框,不切换会话、不自动提交,交由用户编辑后自行发送。
|
||||
export const ASSISTANT_SCOPE_ACTION_FILL_COMPOSER = 'fill_composer'
|
||||
|
||||
export const ASSISTANT_SCOPE_SESSION_APPLICATION = 'application'
|
||||
export const ASSISTANT_SCOPE_SESSION_EXPENSE = 'expense'
|
||||
@@ -286,27 +288,84 @@ function shouldAllowContextualFollowUp(rawText, currentSessionType, options = {}
|
||||
)
|
||||
}
|
||||
|
||||
function buildUnsupportedBusinessScopeText() {
|
||||
const message = ONTOLOGY_BUSINESS_CONTRACT.unsupportedIntentMessage || {}
|
||||
function buildUnsupportedBusinessScopeSuggestedActions(options = {}) {
|
||||
const sharedOptions = {
|
||||
attachmentCount: options.attachmentCount || 0
|
||||
}
|
||||
const applicationAction = buildScopeSwitchAction(ASSISTANT_SCOPE_SESSION_APPLICATION, '申请下周去上海出差,支撑客户系统上线', sharedOptions)
|
||||
const expenseAction = buildScopeSwitchAction(ASSISTANT_SCOPE_SESSION_EXPENSE, '我要报销昨天的交通费', sharedOptions)
|
||||
const knowledgeAction = buildScopeSwitchAction(ASSISTANT_SCOPE_SESSION_KNOWLEDGE, '差旅住宿标准是多少', sharedOptions)
|
||||
const approvalAction = buildScopeSwitchAction(ASSISTANT_SCOPE_SESSION_APPROVAL, '帮我查询待我审核的单据', sharedOptions)
|
||||
|
||||
return [
|
||||
message.title || '此意图系统不支持。',
|
||||
'',
|
||||
`当前系统支持的业务范围:${SUPPORTED_BUSINESS_SCOPE_TEXT.join('、')}。`,
|
||||
'',
|
||||
message.body || '你这条内容没有识别到相关财务业务意图,系统暂不支持处理。',
|
||||
'',
|
||||
message.retryHint || '请重新描述你的财务业务要求,例如“申请下周去上海出差”“查询我的报销单进度”或“解释差旅住宿标准”。'
|
||||
].join('\n')
|
||||
{ ...applicationAction, label: '去申请助手', description: '发起费用申请和事前审批' },
|
||||
{ ...expenseAction, label: '去报销助手', description: '继续处理报销和票据' },
|
||||
{ ...knowledgeAction, label: '去知识助手', description: '查看标准和流程规则' },
|
||||
{ ...approvalAction, label: '去审核助手', description: '查看待审单据和风险' }
|
||||
]
|
||||
}
|
||||
|
||||
function buildUnsupportedBusinessScopeGuard() {
|
||||
function buildUnsupportedBusinessScopeText(rawText, options = {}) {
|
||||
const message = ONTOLOGY_BUSINESS_CONTRACT.unsupportedIntentMessage || {}
|
||||
const text = String(rawText || '').trim()
|
||||
const intro = text
|
||||
? `**小财管家暂时不处理「${text}」这类内容。**`
|
||||
: `**${message.title || '此意图系统不支持。'}**`
|
||||
const attachmentHint = options.attachmentCount
|
||||
? '你刚刚上传的附件我会先保留,切换到合适场景后可以继续使用。'
|
||||
: ''
|
||||
return [
|
||||
intro,
|
||||
'',
|
||||
'### 当前可继续的场景',
|
||||
`- ${SUPPORTED_BUSINESS_SCOPE_TEXT[0] || '费用申请/事前审批'}`,
|
||||
`- ${SUPPORTED_BUSINESS_SCOPE_TEXT[1] || '报销与票据识别'}`,
|
||||
`- ${SUPPORTED_BUSINESS_SCOPE_TEXT[3] || '财务制度、报销标准和流程规则问答'}`,
|
||||
`- ${SUPPORTED_BUSINESS_SCOPE_TEXT[4] || '预算、应收、应付等财务经营查询'}`,
|
||||
'',
|
||||
message.body || '这条内容没有识别到当前系统支持的财务业务意图,暂时不能继续处理。',
|
||||
attachmentHint,
|
||||
'你可以直接点下面的场景继续,或者重新描述你的财务业务需求。',
|
||||
'',
|
||||
message.retryHint || '请重新描述你的财务业务要求,例如“申请下周去上海出差”“查询我的报销单进度”或“解释差旅住宿标准”。'
|
||||
].filter(Boolean).join('\n')
|
||||
}
|
||||
|
||||
export function buildUnsupportedBusinessScopeConversation(rawText, options = {}) {
|
||||
const suggestedActions = buildUnsupportedBusinessScopeSuggestedActions(options)
|
||||
return {
|
||||
state_json: {
|
||||
session_type: ASSISTANT_SCOPE_SESSION_STEWARD
|
||||
},
|
||||
messages: [
|
||||
{
|
||||
id: 'unsupported-business-intent',
|
||||
role: 'assistant',
|
||||
content: buildUnsupportedBusinessScopeText(rawText, options),
|
||||
created_at: new Date().toISOString(),
|
||||
message_json: {
|
||||
assistant_name: '小财管家',
|
||||
assistant_variant: 'compact_guidance',
|
||||
orchestrator_payload: {
|
||||
result: {
|
||||
suggested_actions: suggestedActions
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
function buildUnsupportedBusinessScopeGuard(rawText, options = {}) {
|
||||
const suggestedActions = buildUnsupportedBusinessScopeSuggestedActions(options)
|
||||
return {
|
||||
targetSessionType: '',
|
||||
targetLabel: '不支持的意图',
|
||||
blocked: true,
|
||||
text: buildUnsupportedBusinessScopeText(),
|
||||
text: buildUnsupportedBusinessScopeText(rawText, options),
|
||||
meta: ['意图不支持'],
|
||||
suggestedActions: [],
|
||||
suggestedActions,
|
||||
actionType: ASSISTANT_SCOPE_ACTION_UNSUPPORTED
|
||||
}
|
||||
}
|
||||
@@ -318,7 +377,7 @@ export function resolveAssistantScopeGuard(rawText, currentSessionType, options
|
||||
if (shouldAllowContextualFollowUp(rawText, normalizedCurrent, options)) {
|
||||
return null
|
||||
}
|
||||
return normalizeText(rawText) ? buildUnsupportedBusinessScopeGuard() : null
|
||||
return normalizeText(rawText) ? buildUnsupportedBusinessScopeGuard(rawText, options) : null
|
||||
}
|
||||
|
||||
if (targetSessionType === normalizedCurrent) {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ASSISTANT_SCOPE_ACTION_FILL_COMPOSER } from './assistantSessionScope.js'
|
||||
|
||||
const APPLICATION_FIELD_PREFILLS = {
|
||||
time: '申请时间段:',
|
||||
time_range: '申请时间段:',
|
||||
@@ -14,6 +16,7 @@ export function resolveSuggestedActionPrefill(action = {}) {
|
||||
payload.prompt_prefill
|
||||
|| payload.input_prefill
|
||||
|| payload.prefill_text
|
||||
|| payload.fill_text
|
||||
|| ''
|
||||
).trim()
|
||||
if (explicitPrefill) {
|
||||
@@ -21,7 +24,7 @@ export function resolveSuggestedActionPrefill(action = {}) {
|
||||
}
|
||||
|
||||
const actionType = String(action?.action_type || '').trim()
|
||||
if (actionType !== 'prefill_composer') {
|
||||
if (actionType !== 'prefill_composer' && actionType !== ASSISTANT_SCOPE_ACTION_FILL_COMPOSER) {
|
||||
return ''
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user