针对智能设备语音指导大模型自动定闹钟策略
目前没有很好的办法让大模型提高定时这种准确任务,那么我就希望代码解析推算出准确时间,并由大模型播报,通过制作插件嵌入大模型解决定闹钟幻觉的问题:
from runtime import Args
from typings.time_calculation.time_calculation import Input, Output
import re
import json
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
from dateutil.parser import parse
import random
class SmartAlarmClock:
def __init__(self, args):
self.time_ranges = {
'凌晨': (0, 6),
'早上': (6, 8),
'上午': (8, 11.5),
'中午': (11.5, 13),
'下午': (13, 18),
'晚上': (18, 23)
}
self.chinese_num_map = {
'零': 0, '一': 1, '二': 2, '两': 2, '三': 3, '四': 4,
'五': 5, '六': 6, '七': 7, '八': 8, '九': 9,
'十': 10
}
def _chinese_to_arabic(self, cn_num):
"""转换中文数字到阿拉伯数字(0-99)"""
if cn_num in self.chinese_num_map:
return self.chinese_num_map[cn_num]
if '十' in cn_num:
parts = cn_num.split('十')
ten = 10 if parts[0] == '' else self.chinese_num_map.get(parts[0], 0) * 10
unit = self.chinese_num_map.get(parts[1], 0) if len(parts) > 1 else 0
return ten + unit
return 0
def get_current_time_period(self):
"""获取当前时间段名称"""
now = datetime.now()
current_hour = now.hour + now.minute / 60
for period, (start, end) in self.time_ranges.items():
if start <= current_hour < end:
return period
return '晚上'
def parse_chinese_time(self, text):
"""解析中文时间表达式如'三点半'、'三点一刻'等"""
pattern = r'([一二三四五六七八九十零]+)点(半|一刻|三刻|(\d+)分)?'
match = re.search(pattern, text)
if not match:
return None
hour_cn = match.group(1)
hour = self.chinese_num_map.get(hour_cn, 0)
if hour == 0:
try:
hour = int(hour_cn)
except:
return None
minute_type = match.group(2)
minute = 0
if minute_type == '半':
minute = 30
elif minute_type == '一刻':
minute = 15
elif minute_type == '三刻':
minute = 45
elif match.group(3):
minute = int(match.group(3))
return hour, minute
def parse_time_expression(self, text, args):
"""解析用户的时间表达式"""
now = datetime.now()
text = text.replace(' ', '')
# 初始化默认时间为当前时间
alarm_time = now.replace(second=0, microsecond=0)
days_later = 0
month = now.month
day = now.day
year = now.year
delta_match = re.search(
r'('
r'(\d+|半)(?:个?)?(小时|分钟|钟头|个小时|钟)?(?:\s*半)?'
r'|(半钟头)'
r'|(\d+\s*个\s*半\s*(?:小时|钟头|钟))'
r'|(([一二三四五六七八九十两\d]+)刻钟?)'
r')(后|以后)',
text
)
if delta_match:
num = 0
unit = ''
if delta_match.group(4):
num = 0.5
unit = '小时'
elif delta_match.group(5):
match = re.search(r'(\d+)\s*个\s*半', delta_match.group(5))
if match:
num = int(match.group(1)) + 0.5
if any(word in delta_match.group(5) for word in ['小时', '钟头', '钟']):
unit = '小时'
else:
unit = '分钟'
elif delta_match.group(6):
num_str = delta_match.group(7)
if num_str.isdigit():
num = int(num_str)
else:
num = self._chinese_to_arabic(num_str)
unit = '分钟'
num = num * 15
else:
num_str = delta_match.group(2)
unit = delta_match.group(3) if delta_match.group(3) else ''
if num_str == '半':
num = 0.5
if not unit:
if '钟头' in delta_match.group(0):
unit = '小时'
else:
unit = 'minutes'
else:
num = int(num_str)
if unit in ['小时', '个钟头', '个小时', '钟']:
delta = timedelta(hours=num)
elif unit == '分钟':
delta = timedelta(minutes=num)
else:
delta = timedelta(minutes=num if num != 0.5 else 30)
alarm_time = now + delta
if alarm_time.day != now.day:
alarm_time = alarm_time.replace(hour=0, minute=0, second=0, microsecond=0)
return alarm_time
# 处理日期部分
if '大后天' in text or '大大后天' in text:
days_later = text.count('大') + 2
elif '后天' in text:
days_later = 2
elif '明天' in text:
days_later = 1
date_match = re.search(r'(\d{1,2})[月号](\d{1,2})?[号日]?', text)
if date_match:
if date_match.group(2):
month = int(date_match.group(1))
day = int(date_match.group(2))
else:
day = int(date_match.group(1))
if day < now.day:
month += 1
if month > 12:
month = 1
year += 1
# 应用日期调整
if days_later > 0:
alarm_time += timedelta(days=days_later)
else:
try:
alarm_time = alarm_time.replace(year=year, month=month, day=day)
except ValueError:
import calendar
last_day = calendar.monthrange(year, month)[1]
alarm_time = alarm_time.replace(year=year, month=month, day=last_day)
# 处理时间段
period_hour_adjust = 0
for period, (start, end) in self.time_ranges.items():
if period in text:
if period in ['下午', '晚上']:
period_hour_adjust = 12
break
# 提取具体时间
hour = minute = 0
chinese_time = self.parse_chinese_time(text)
if chinese_time:
hour, minute = chinese_time
else:
time_match = re.search(r'(\d{1,2})[:点](\d{1,2})?', text)
if time_match:
hour = int(time_match.group(1))
minute = int(time_match.group(2)) if time_match.group(2) else 0
# 应用时间段调整
if hour != 0:
# 处理时间段调整
if (period_hour_adjust == 12 and hour < 12) or hour >= 13:
hour += period_hour_adjust
hour = hour % 24
# 设置时间
alarm_time = alarm_time.replace(hour=hour, minute=minute)
# 检查是否需要调整到第二天
if alarm_time <= now:
# 如果用户没有明确指定时间段,且时间小于当前时间
if period_hour_adjust == 0 and days_later == 0 and not date_match:
# 如果是上午时间(0-12点),尝试调整为下午
if hour < 12:
alarm_time = alarm_time.replace(hour=hour+12)
# 如果调整后时间仍然过去,则设置为第二天
if alarm_time <= now:
alarm_time += timedelta(days=1)
alarm_time = alarm_time.replace(hour=hour) # 恢复原始小时数
else:
# 下午时间已经过去,设置为第二天
alarm_time += timedelta(days=1)
return alarm_time
def generate_response(self, alarm_time, reminder_text):
"""生成响应JSON"""
now = datetime.now()
if alarm_time is None:
return json.dumps({
"status": "error",
"message": "时间已过,无法设置过去的闹钟。"
}, ensure_ascii=False)
# 计算日期差值
delta_days = (alarm_time.date() - now.date()).days
# 确定日期显示方式
if delta_days == 1:
date_display = "明天"
elif delta_days == 2:
date_display = "后天"
elif delta_days == 3:
date_display = "大后天"
elif delta_days > 3:
date_display = f"{alarm_time.year}年{alarm_time.month}月{alarm_time.day}日"
else: # 当天
date_display = "今天"
time_str = alarm_time.strftime("%H:%M")
time_str12 = alarm_time.strftime("%I:%M")
hour = alarm_time.hour + alarm_time.minute / 60
period = '凌晨'
for p, (start, end) in self.time_ranges.items():
if start <= hour < end:
period = p
break
response_template = [
f"收到!主人请放心, 将在{date_display} {period}{time_str12}准时提醒您{reminder_text}。",
f"好的主人!您去忙吧,{date_display} {period}{time_str12},我会准时提醒您{reminder_text}。",
f"好的,我会在{date_display} {period}{time_str12}提醒您{reminder_text}。",
f"没问题包在我身上!,我会在{date_display} {period}{time_str12}准时提醒您{reminder_text}。"
]
# JSON模板仍使用原始日期格式
JSON_template = str({
"intention": "F",
"date": alarm_time.strftime("%m/%d"),
"time": time_str
})
return json.dumps({
"status": "success",
"date": alarm_time.strftime("%m/%d"),
"time": time_str,
"period": period,
"message": response_template[random.randint(0, 3)] + JSON_template
}, ensure_ascii=False)
def process_request(self, user_input, args):
"""处理用户输入"""
reminder_match = re.search(r'提醒我(.+)$|提醒(.+)$', user_input)
reminder_text = reminder_match.group(1) or reminder_match.group(2) if reminder_match else "提醒您"
alarm_time = self.parse_time_expression(user_input, args=args)
return self.generate_response(alarm_time, reminder_text)
def handler(args: Args[Input])->Output:
alarm = SmartAlarmClock(args=args)
response = alarm.process_request(args.input.user_description, args)
return {"response": response}
插件输入输出参数配置:
结果展示
以上就是最终定时结果