feat: 优化AI文本识别的prompt

- 增强意图识别:明确区分纪念日和提醒的规则
- 扩展农历节日识别:添加更多传统节日
- 扩展公历节日识别:添加情人节、妇女节、儿童节等
- 优化重复规则识别逻辑
- 优化mock函数:更智能的日期解析和标题提取

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
ddshi 2026-02-28 10:42:42 +08:00
parent c36a56e0a4
commit beedafc7d1

View File

@ -25,11 +25,36 @@ const SYSTEM_PROMPT = `你是一个帮助用户创建事件(纪念日或提醒
"response": "友好的确认消息"
}
##
### vs
- "生日""纪念日""结婚纪念日""节日""春节""中秋""端午""元宵" type = "anniversary"
- "提醒""任务""todo""待办""会议""约会""上课" type = "reminder"
- "reminder"
###
1. "农历正月初一""农历三月三""阴历八月十五" is_lunar = true
2.
3. "明天""后天""下周""下个月""明年"
4. "周一""周二"... "周日""星期天"
5. "3月8日""5月1日""10月1日"
###
- "上午9点""下午3点""晚上8点""14:30"
- 使 09:00:00Z
###
- "每天" repeat_type = "daily"
- "每周" repeat_type = "weekly"
- "每月" repeat_type = "monthly"
- "每年" repeat_type = "yearly"
- "不重复""仅一次" repeat_type = "none"
##
1. date ISO 8601: YYYY-MM-DDTHH:mm:ssZ
2. "明天"date = ( + 1)
3. "后天"date = ( + 2)
4. "下周三"date = 09:00:00Z
4. "下周三"date = 09:00:00Z
5. "下午3点"date = 今天下午15:00:00Z 或用户指定的日期的15:00:00Z
6. 使 09:00:00Z
7. NEVER 使 2024-01-02T15:00:00Z使
@ -39,7 +64,8 @@ const SYSTEM_PROMPT = `你是一个帮助用户创建事件(纪念日或提醒
->
is_holiday=true
-
-
- 使 "Asia/Shanghai"
@ -49,7 +75,8 @@ const SYSTEM_PROMPT = `你是一个帮助用户创建事件(纪念日或提醒
-
- "下周三"
- 使`;
- 使
- "提醒""帮我"`;
const parseMessageSchema = z.object({
message: z.string().min(1, 'Message is required').max(1000),
@ -187,17 +214,36 @@ function mockParseResponse(message: string): { parsed: any; response: string } {
// Simple mock parser for testing
const lowerMessage = message.toLowerCase();
// Detect if it's a reminder (contains "提醒", "提醒我", etc.)
const isReminder = lowerMessage.includes('提醒') || lowerMessage.includes('提醒我');
// 意图识别:纪念日 vs 提醒
const isReminder = lowerMessage.includes('提醒') || lowerMessage.includes('提醒我') ||
lowerMessage.includes('任务') || lowerMessage.includes('todo') ||
lowerMessage.includes('待办') || lowerMessage.includes('会议') ||
lowerMessage.includes('约会') || lowerMessage.includes('上课');
// 意图识别:纪念日
const isAnniversary = lowerMessage.includes('生日') || lowerMessage.includes('纪念日') ||
lowerMessage.includes('节日') || lowerMessage.includes('春节') ||
lowerMessage.includes('中秋') || lowerMessage.includes('端午') ||
lowerMessage.includes('元宵');
// 强制使用正确类型
const eventType = isAnniversary ? 'anniversary' : (isReminder ? 'reminder' : 'reminder');
// Detect lunar date
const isLunar = lowerMessage.includes('农历') || lowerMessage.includes('阴历');
const isLunar = lowerMessage.includes('农历') || lowerMessage.includes('阴历') ||
lowerMessage.includes('正月') || lowerMessage.includes('腊月');
// Detect holiday
const isHoliday = lowerMessage.includes('春节') || lowerMessage.includes('清明') ||
lowerMessage.includes('劳动节') || lowerMessage.includes('国庆') ||
lowerMessage.includes('元旦') || lowerMessage.includes('中秋') ||
lowerMessage.includes('端午');
const isHoliday = lowerMessage.includes('春节') || lowerMessage.includes('元宵') ||
lowerMessage.includes('清明') || lowerMessage.includes('端午') ||
lowerMessage.includes('七夕') || lowerMessage.includes('中元') ||
lowerMessage.includes('中秋') || lowerMessage.includes('重阳') ||
lowerMessage.includes('腊八') || lowerMessage.includes('小年') ||
lowerMessage.includes('除夕') || lowerMessage.includes('劳动节') ||
lowerMessage.includes('国庆') || lowerMessage.includes('元旦') ||
lowerMessage.includes('妇女节') || lowerMessage.includes('儿童节') ||
lowerMessage.includes('建军节') || lowerMessage.includes('教师节') ||
lowerMessage.includes('圣诞节') || lowerMessage.includes('情人节');
// Detect priority (color)
let priority: 'none' | 'red' | 'green' | 'yellow' = 'none';
@ -230,17 +276,40 @@ function mockParseResponse(message: string): { parsed: any; response: string } {
repeatType = 'yearly';
}
// Extract title (simple heuristic - first phrase before date or colon)
let title = message.split(/[:]/)[0] || message;
title = title.split(/[\s\d\u4e00-\u9fa5]+/)[0] || title.substring(0, 50);
// Extract title - 去除"提醒"、"帮我"等前缀
let title = message;
// 去除常见的开头
const prefixes = ['帮我', '提醒我', '提醒', '请帮我', '我要', '我想'];
for (const prefix of prefixes) {
if (title.startsWith(prefix)) {
title = title.slice(prefix.length);
break;
}
}
// 去除冒号后面的内容作为标题(保留标题)
if (title.includes('') || title.includes(':')) {
title = title.split(/[:]/)[0];
}
// 去除日期相关文字
title = title.replace(/[\d一二三四五六七八九十]+[月日号]/g, '').replace(/星期[一二三四五六日天]/g, '').trim();
title = title.substring(0, 50) || title;
// Mock date (tomorrow at 3 PM local time by default for China UTC+8)
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
tomorrow.setHours(15, 0, 0, 0); // 默认下午3点中国时区
// Mock date (tomorrow at 9 AM local time by default for China UTC+8)
const targetDate = new Date();
targetDate.setDate(targetDate.getDate() + 1);
targetDate.setHours(9, 0, 0, 0); // 默认上午9点中国时区
// 检测相对日期
if (lowerMessage.includes('今天')) {
targetDate.setDate(new Date().getDate());
} else if (lowerMessage.includes('后天')) {
targetDate.setDate(new Date().getDate() + 2);
} else if (lowerMessage.includes('下周')) {
targetDate.setDate(new Date().getDate() + 7);
}
// 检测消息中的时间(如"下午3点"、"下午四点"、"14:30"等)
const timePattern = message.match(/(?:下午|晚上)?(\d{1,2})(?::(\d{2}))?\s*(?:点|时)/);
const timePattern = message.match(/(?:上午|中午|下午|晚上)?(\d{1,2})(?::(\d{2}))?\s*(?:点|时)/);
if (timePattern) {
let hours = parseInt(timePattern[1]);
const minutes = timePattern[2] ? parseInt(timePattern[2]) : 0;
@ -248,14 +317,18 @@ function mockParseResponse(message: string): { parsed: any; response: string } {
if (message.includes('下午') || message.includes('晚上')) {
if (hours < 12) hours += 12;
}
tomorrow.setHours(hours, minutes, 0, 0);
// 中午时间
if (message.includes('中午') && hours < 12) {
hours = 12;
}
targetDate.setHours(hours, minutes, 0, 0);
}
// Build parsed result
const parsed: any = {
type: isReminder ? 'reminder' : 'anniversary',
type: eventType,
title: title.trim(),
date: tomorrow.toISOString(),
date: targetDate.toISOString(),
timezone: 'Asia/Shanghai', // 默认使用中国时区
is_lunar: isLunar,
repeat_type: repeatType,
@ -265,10 +338,10 @@ function mockParseResponse(message: string): { parsed: any; response: string } {
if (isHoliday) {
parsed.is_holiday = true;
}
if (isReminder && priority !== 'none') {
if (eventType === 'reminder' && priority !== 'none') {
parsed.priority = priority;
}
if (isReminder && content) {
if (eventType === 'reminder' && content) {
parsed.content = content;
}
@ -281,9 +354,11 @@ function mockParseResponse(message: string): { parsed: any; response: string } {
none: '不重复'
}[repeatType];
let responseMsg = `我帮你记的是:
const typeText = eventType === 'anniversary' ? '纪念日' : '提醒';
let responseMsg = `我帮你创建的是:
**${title.trim()}**
📅 ${tomorrow.toLocaleDateString('zh-CN')}`;
📅 ${targetDate.toLocaleDateString('zh-CN')} ${targetDate.getHours()}:${String(targetDate.getMinutes()).padStart(2, '0')}`;
if (repeatType !== 'none') {
responseMsg += `\n🔄 ${repeatText}`;
}
@ -293,7 +368,7 @@ function mockParseResponse(message: string): { parsed: any; response: string } {
if (isHoliday) {
responseMsg += `\n🎉 节假日`;
}
if (isReminder && priority !== 'none') {
if (eventType === 'reminder' && priority !== 'none') {
const colorText = { red: '红色', green: '绿色', yellow: '黄色', none: '无' };
responseMsg += `\n🏷 ${colorText[priority]}`;
}