封面信息图

十月七日的清晨,闹钟还没响,阳台上的薄荷叶已经被第一缕晨光晒得发亮。

我迷迷糊糊坐到原木书桌前,刚掀开轻薄本的屏幕,屏幕右下角便伴随着一声轻微的“叮咚”水滴声,滑出一个米宣色调的温和小卡片:

“早安,泠钰。今天是个少云的晴朗秋日,最高气温 21℃,昼夜温差比较大,下午出门记得带一件薄针织开衫。今日核心待办:① 检查 SQLite 备份硬盘;② 晚上七点前把老妈念叨的无添加生抽买齐。小狗 Token 已经在门口等你带它散步啦。”

读完这短短几行字,整个人仿佛被温热的毛巾轻轻敷过,原本刚刚醒来时的混沌与迷茫,在一瞬间化作了对新一天的踏实与期待。

在信息过载的时代,很多人早晨醒来的第一件事,是被手机上几十条新闻客户端的红点推送轰炸——哪里又堵车了、哪家大厂又裁员了、股市汇率又波动了。一睁开眼,脑子就被无数与自己无关的焦虑与喧嚣填满。

为什么我们不能给自己的生活定制一个专属的“私人早报机器人”?

它不关心宏大的资本叙事,它只在每天清晨你打开电脑的那一瞬间,安安静静地替你抓取当天的本地天气、查一查日历里的核心待办、顺便送上一句体贴生活细节的温柔提示。

用不到 80 行纯 Python 脚本,结合公开的免费天气开放接口与系统原生桌面通知机制,我们就能在本地亲手造出这样一个有温度的生活小管家。

私人早报的极简原则

一个好的生活机器人,绝不能演变成另一个打扰人的骚扰源。它必须坚守三条原则:

  1. 绝对克制的信息密度:字数控制在 150 字以内,不罗列一堆复杂的降水量毫米数或紫外线波长,只说人话(比如“记得带薄外套”)。
  2. 轻量无侵入(Zero Intrusion):只在清晨第一次亮屏时弹窗一次,点击或超时 8 秒后自动消失,绝不常驻红点或后台常驻长连接。
  3. 本地私密调度:待办事项直接从本地手账 Markdown 或离线 SQLite 数据库中提取,绝不将个人隐私行程上传到任何公网服务器。

核心实现:天气嗅探与原生通知管道

为了不依赖复杂的商业天气 SDK,我们可以调用国家气象局公开的免费 JSON 数据接口,或者使用免费免注册的轻量级开放接口(如 wttr.in 的 JSON 格式)。

配合 Python 标准库的 HTTP 请求与操作系统原生通知调用(macOS 的 osascript 或 Windows 的 PowerShell 气泡通知),整个脚本干净小巧:

import os
import json
import urllib.request
import datetime
from pathlib import Path

def fetch_local_weather(city: str = "Qingdao") -> dict:
    """获取本地天气概况(使用纯标准库)"""
    url = f"https://wttr.in/{city}?format=j1"
    req = urllib.request.Request(url, headers={"User-Agent": "curl/7.68.0"})
    
    try:
        with urllib.request.urlopen(req, timeout=3.5) as resp:
            data = json.loads(resp.read().decode("utf-8"))
            current = data["current_condition"][0]
            today = data["weather"][0]
            
            return {
                "temp": current.get("temp_C", "20"),
                "desc": current.get("weatherDesc", [{}])[0].get("value", "晴朗"),
                "max_temp": today.get("maxtempC", "22"),
                "min_temp": today.get("mintempC", "14")
            }
    except Exception:
        # 网络偶发异常时的温和兜底
        return {"temp": "20", "desc": "晴好微凉", "max_temp": "22", "min_temp": "15"}

def fetch_today_todos(journal_path: Path) -> list:
    """从本地 Markdown 手账中读取今天的未完成待办清单"""
    if not journal_path.exists():
        return ["整理今日手账"]
        
    todos = []
    content = journal_path.read_text(encoding="utf-8")
    for line in content.splitlines():
        # 匹配 Markdown 未勾选的待办项: - [ ] 事项
        if line.strip().startswith("- [ ]"):
            todo_text = line.replace("- [ ]", "").strip()
            todos.append(todo_text)
            if len(todos) >= 2:  # 最多提纯两条最核心的要务,绝不制造心理压力
                break
    return todos

def send_native_desktop_notification(title: str, message: str):
    """跨平台优雅调用系统原生桌面通知"""
    # 以 macOS 原生通知为例(Windows 可切换为 ToastNotifier)
    apple_script = f'''
    display notification "{message}" with title "{title}" sound name "Glass"
    '''
    os.system(f"osascript -e '{apple_script}'")

融入大模型的温情话语重塑

如果只是干瘪地打印“温度 20度,待办 A”,这依然是一个冰冷的报时闹钟。

最后一步是调用我们在本地运行的轻量 7B 模型,用一句话把天气与待办串联成一段如同家人在厨房里随口叮咛的早安便签:

def generate_warm_greeting(weather_info: dict, todos: list) -> str:
    prompt = f"""请根据以下生活信息,写一段不超过 70 个字、极其温和亲切的早晨问候。
天气:{weather_info['desc']},当前 {weather_info['temp']}℃,最高 {weather_info['max_temp']}℃。
待办要务:{'、'.join(todos)}。
口吻要求:像住在隔壁的知心老友,带有秋日生活质感,不要任何口号套话。"""

    # 调用本地运行的模型
    # 模拟本地模型返回的极简结果
    return (
        f"早安!今日{weather_info['desc']},最高温{weather_info['max_temp']}℃,早晚渐凉记得添衣。"
        f"今天先攻克:{todos[0] if todos else '享受生活'}。喝杯温水,慢慢开启新的一天。"
    )

def main():
    weather = fetch_local_weather()
    # 假定读取当前日期的本地手账文件
    vault_file = Path.home() / "Documents" / "Journal_Today.md"
    todos = fetch_today_todos(vault_file)
    
    greeting = generate_warm_greeting(weather, todos)
    send_native_desktop_notification("🌿 泠不丁的秋日生活早报", greeting)

if __name__ == "__main__":
    main()

唤醒一天最好的开始

将这个脚本配置在轻薄本的开机或早晨定时任务中。

每当清晨掀开电脑,不需要打开繁杂的网页,甚至不需要动一下手指,一条带着体温的小卡片便在屏幕角上静悄悄亮起,告诉你外面的风是暖是凉,告诉你今天有哪些重要的小事值得全心投入。

读完了,浅浅一笑,端起咖啡杯,新的一天就在这样平静而踏实的节奏中自然铺展。

生活需要这种小小的仪式感。用最简单的代码在日常的喧嚣中筑起一道过滤网,把杂音挡在门外,只让爱与关心流淌进每一个寻常的早晨。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐