fix: 优化AI解析,智能提取标题和内容

- 改进标题提取:去除"提醒"、"帮我"等前缀,保留事件名称
- 改进内容提取:提取日期时间后的描述性文字
- 添加优先级识别:红色、绿色、黄色标记
- 添加提前提醒识别:提前X天/小时/分钟提醒
- 更新SYSTEM_PROMPT:指导AI正确提取各字段

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
ddshi 2026-02-28 11:05:30 +08:00
parent beedafc7d1
commit 1ff0693901

View File

@ -16,11 +16,14 @@ const SYSTEM_PROMPT = `你是一个帮助用户创建事件(纪念日或提醒
{
"parsed": {
"type": "anniversary 或 reminder",
"title": "事件标题",
"title": "事件标题(简洁准确,去除""、""等前缀)",
"content": "详细内容(仅提醒类型,如会议主题、待办事项等)",
"date": "2026-02-13T15:00:00Z",
"timezone": "Asia/Shanghai",
"is_lunar": true false,
"repeat_type": "daily, weekly, monthly, yearly 或 none"
"repeat_type": "daily, weekly, monthly, yearly 或 none",
"priority": "none, red, green 或 yellow仅提醒red=重要紧急green=绿色yellow=黄色)",
"reminder_times": ["提前提醒时间点数组,如 2026-02-12T09:00:00Z"]
},
"response": "友好的确认消息"
}
@ -32,6 +35,18 @@ const SYSTEM_PROMPT = `你是一个帮助用户创建事件(纪念日或提醒
- "提醒""任务""todo""待办""会议""约会""上课" type = "reminder"
- "reminder"
###
-
- "提醒我""帮我""请帮我"
-
- "提醒我明天上午9点开会" title = "开会"
- "提醒我春节回家" title = "春节回家"
###
- content
-
- "提醒我明天上午9点开会讨论项目进度" content = "讨论项目进度"
###
1. "农历正月初一""农历三月三""阴历八月十五" is_lunar = true
2.
@ -50,6 +65,17 @@ const SYSTEM_PROMPT = `你是一个帮助用户创建事件(纪念日或提醒
- "每年" repeat_type = "yearly"
- "不重复""仅一次" repeat_type = "none"
###
- "重要""紧急""红色" priority = "red"
- "绿色" priority = "green"
- "黄色" priority = "yellow"
- priority = "none"
###
- "提前1天提醒" reminder_times = [eventDate - 1]
- "提前2小时提醒" reminder_times = [eventDate - 2]
- "提前30分钟提醒" reminder_times = [eventDate - 30]
##
1. date ISO 8601: YYYY-MM-DDTHH:mm:ssZ
2. "明天"date = ( + 1)
@ -255,15 +281,6 @@ function mockParseResponse(message: string): { parsed: any; response: string } {
priority = 'yellow';
}
// Detect content (after colon or special markers)
let content = '';
if (message.includes('') || message.includes(':')) {
const parts = message.split(/[:]/);
if (parts.length > 1) {
content = parts[1].trim();
}
}
// Detect repeat type
let repeatType: 'daily' | 'weekly' | 'monthly' | 'yearly' | 'none' = 'none';
if (lowerMessage.includes('每天') || lowerMessage.includes('每日')) {
@ -276,23 +293,88 @@ function mockParseResponse(message: string): { parsed: any; response: string } {
repeatType = 'yearly';
}
// Extract title - 去除"提醒"、"帮我"等前缀
// Detect reminder times (提前提醒)
let reminderTimes: string[] = [];
// 提前X天提醒
const daysMatch = lowerMessage.match(/提前(\d+)天/);
if (daysMatch) {
const days = parseInt(daysMatch[1]);
const reminderDate = new Date(targetDate);
reminderDate.setDate(reminderDate.getDate() - days);
reminderTimes.push(reminderDate.toISOString());
}
// 提前X小时提醒
const hoursMatch = lowerMessage.match(/提前(\d+)小时?/);
if (hoursMatch) {
const hours = parseInt(hoursMatch[1]);
const reminderDate = new Date(targetDate);
reminderDate.setHours(reminderDate.getHours() - hours);
reminderTimes.push(reminderDate.toISOString());
}
// 提前X分钟提醒
const minutesMatch = lowerMessage.match(/提前(\d+)分钟/);
if (minutesMatch) {
const minutes = parseInt(minutesMatch[1]);
const reminderDate = new Date(targetDate);
reminderDate.setMinutes(reminderDate.getMinutes() - minutes);
reminderTimes.push(reminderDate.toISOString());
}
// 默认提醒(不提前)
if (reminderTimes.length === 0) {
reminderTimes = [];
}
// Extract title - 智能提取标题
let title = message;
let extractedContent = '';
// 去除常见的开头
const prefixes = ['帮我', '提醒我', '提醒', '请帮我', '我要', '我想'];
const prefixes = ['帮我', '提醒我', '提醒', '请帮我', '我要', '我想', '帮我提醒'];
for (const prefix of prefixes) {
if (title.startsWith(prefix)) {
if (title.toLowerCase().startsWith(prefix)) {
title = title.slice(prefix.length);
break;
}
}
// 去除冒号后面的内容作为标题(保留标题)
if (title.includes('') || title.includes(':')) {
title = title.split(/[:]/)[0];
// 处理"提醒XXX提醒时间YYY"这种格式 - 提取标题和内容
// 查找最后一个"提醒"或"在"后面的内容作为内容
const reminderMatch = message.match(/(?:提醒|在|于)\s*(.+)$/);
if (reminderMatch && reminderMatch[1]) {
extractedContent = reminderMatch[1].trim();
}
// 去除日期相关文字
title = title.replace(/[\d一二三四五六七八九十]+[月日号]/g, '').replace(/星期[一二三四五六日天]/g, '').trim();
title = title.substring(0, 50) || title;
// 去除冒号后面的内容
if (title.includes('') || title.includes(':')) {
const colonParts = title.split(/[:]/);
title = colonParts[0].trim();
if (!extractedContent && colonParts.length > 1) {
extractedContent = colonParts.slice(1).join(':').trim();
}
}
// 去除日期和时间相关文字
// 去除"明天"、"后天"、"下周"等相对日期
title = title.replace(/(?:明天|后天|今天|下周|下个月|明年|今年|去年)/g, '');
// 去除具体日期如"3月8日"、"2024年5月1日"
title = title.replace(/\d{1,4}[年/-]\d{1,2}[月/-]\d{1,2}[日号]?/g, '');
title = title.replace(/[\d一二三四五六七八九十]+[月日号]/g, '');
// 去除星期几
title = title.replace(/星期[一二三四五六日天]/g, '');
title = title.replace(/周一|周二|周三|周四|周五|周六|周日/g, '');
// 去除时间如"上午9点"、"下午3点"、"14:30"
title = title.replace(/(?:上午|中午|下午|晚上)?\s*\d{1,2}(?::\d{2})?\s*(?:点|时)/g, '');
// 去除"在"、"于"等介词
title = title.replace(/^[在于是于]\s*/g, '');
// 去除多余空格
title = title.trim();
// 如果标题为空或太短,使用原始消息
if (title.length < 2) {
title = message.substring(0, 30);
}
// 限制标题长度
title = title.substring(0, 50);
// Mock date (tomorrow at 9 AM local time by default for China UTC+8)
const targetDate = new Date();
@ -341,8 +423,11 @@ function mockParseResponse(message: string): { parsed: any; response: string } {
if (eventType === 'reminder' && priority !== 'none') {
parsed.priority = priority;
}
if (eventType === 'reminder' && content) {
parsed.content = content;
if (eventType === 'reminder' && extractedContent) {
parsed.content = extractedContent;
}
if (eventType === 'reminder' && reminderTimes.length > 0) {
parsed.reminder_times = reminderTimes;
}
// Generate response