← Back to Skills Marketplace
scikkk

Elderly Voice Assistant

by scikkk · GitHub ↗ · v1.0.0 · MIT-0
cross-platform ⚠ suspicious
254
Downloads
0
Stars
0
Active Installs
1
Versions
Install in OpenClaw
/install elderly-assistant
Description
银发族语音助手——老年人对着手机说话就能发消息、查天气、设闹钟、听戏曲,无需学任何操作。
README (SKILL.md)

银发族语音助手 / Elderly Voice Assistant

老年人对着手机说话就能完成发消息、查天气、设闹钟、听新闻、听戏曲,不用学任何操作。

设计理念

  • 零门槛:界面只有一个超大麦克风按钮,没有文字菜单,所有功能语音触发
  • 口语容错:老年人说话啰嗦、重复、方言混杂、停顿长,LLM 做强容错意图理解
  • 语音反馈:所有执行结果用清晰、慢速、大音量的 TTS 播报,不依赖屏幕
  • 主动关怀:定时提醒吃药喝水、每天播报天气穿着、无交互时通知子女
  • 内容陪伴:根据偏好播放戏曲评书老歌,也可与 AI 聊天解闷

工作流程

[按住大按钮说话] → ASR识别(容错) → LLM意图理解 → 执行动作 → TTS语音播报结果

核心 API

语音识别(ASR)

curl https://api.senseaudio.cn/v1/audio/transcriptions \
  -H "Authorization: Bearer $SENSEAUDIO_API_KEY" \
  -F file="@recording.wav" \
  -F model="sense-asr" \
  -F language="zh" \
  -F response_format="text"
# 返回:那个就是跟我那个大儿子说一下明天那个不用来了

语音合成(TTS)— 适老化参数

curl -X POST https://api.senseaudio.cn/v1/t2a_v2 \
  -H "Authorization: Bearer $SENSEAUDIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "SenseAudio-TTS-1.0",
    "text": "好的,已经帮您给大儿子发了消息,内容是:明天不用来了。",
    "stream": false,
    "voice_setting": {
      "voice_id": "female_0001_a",
      "speed": 0.8,
      "vol": 3.0,
      "pitch": 0
    },
    "audio_setting": {
      "format": "mp3",
      "sample_rate": 32000
    }
  }'

适老化 TTS 参数说明:

参数 推荐值 说明
speed 0.8 慢速播报,老人听得清
vol 3.0 大音量,适合听力下降
voice_id female_0001_a 温暖女声,亲切感强

口语容错与意图理解

ASR 转写后,LLM 对老年人口语做强容错意图提取。

容错示例

老人原话(ASR 转写) LLM 提取意图 执行动作
那个……就是……跟我那个大儿子说一下……明天那个不用来了 send_message(to="大儿子", content="明天不用来了") 发消息
今天外头冷不冷啊,要不要穿厚点 get_weather(query="今天气温") 查天气
帮我定个……就是下午三点……三点钟吃药的那个闹钟 set_alarm(time="15:00", label="吃药") 设闹钟
给我放段那个……黄梅戏……就是天仙配 play_content(type="戏曲", query="黄梅戏天仙配") 播放内容
没意思,给我放点东西听听 play_content(type="推荐", based_on="历史偏好") 智能推荐
跟我聊聊天吧,一个人怪无聊的 chat(mode="陪伴") AI 聊天

LLM 意图提取 Prompt

INTENT_SYSTEM_PROMPT = """你是一个专为老年人设计的语音助手的意图理解模块。
老年人说话有以下特点,你需要容错处理:
1. 大量口头禅和填充词:那个、就是、嗯、啊、这个
2. 重复表达:同一个意思说两三遍
3. 方言混杂:可能夹杂方言词汇
4. 长停顿:句子中间可能有很长的停顿导致断句不完整
5. 间接表达:不会直接说功能名,而是描述需求

请从用户的话中提取意图,返回 JSON:
{
  "intent": "send_message|get_weather|set_alarm|play_content|chat|unknown",
  "params": { ... },
  "confidence": 0.0-1.0
}

如果置信度低于 0.6,intent 设为 "confirm",并生成一句确认话术。
确认话术要亲切、简短、用老人听得懂的话,比如:
"您是想让我帮您给大儿子发消息吗?"
"""

支持的功能

1. 发消息

def handle_send_message(params: dict) -> str:
    """发消息给联系人"""
    to = params["to"]       # 联系人称呼:大儿子、老伴、小孙女
    content = params["content"]
    # 查找联系人映射 → 发送消息
    # ...
    return f"好的,已经帮您给{to}发了消息,内容是:{content}。要不要我再加点什么?"

2. 查天气

import requests

def handle_get_weather(params: dict) -> str:
    """查天气并生成适老播报"""
    city = params.get("city", "默认城市")
    weather = requests.get(f"https://wttr.in/{city}?format=%c+%t+%h&lang=zh", timeout=10).text.strip()
    # 生成适老播报:加穿衣建议
    return f"今天{city}的天气是{weather}。建议您今天出门多穿一件外套,注意保暖。"

3. 设闹钟

def handle_set_alarm(params: dict) -> str:
    """设置提醒闹钟"""
    time_str = params["time"]   # "15:00"
    label = params["label"]     # "吃药"
    # 调用系统闹钟 API
    # ...
    return f"好的,已经帮您设好了下午{time_str}的闹钟,到时候提醒您{label}。"

4. 播放内容

CONTENT_CATEGORIES = {
    "戏曲": ["黄梅戏", "京剧", "越剧", "豫剧", "评剧"],
    "评书": ["三国演义", "水浒传", "岳飞传", "隋唐演义"],
    "老歌": ["邓丽君", "刘德华", "费玉清", "蔡琴"],
    "养生": ["养生堂", "健康之路", "中医养生"],
    "新闻": ["今日新闻", "国内要闻", "本地新闻"],
}

def handle_play_content(params: dict) -> str:
    content_type = params.get("type", "推荐")
    query = params.get("query", "")
    if content_type == "推荐":
        # 根据历史偏好推荐
        pass
    return f"好的,这就给您放{query},您听着,想换就跟我说。"

5. AI 陪伴聊天

CHAT_SYSTEM_PROMPT = """你是一位耐心、亲切的语音助手,正在陪一位老人聊天。
说话风格要求:
- 语速慢,句子短,每句不超过20个字
- 用"您"称呼,语气温暖像晚辈
- 多倾听,适当回应,不要长篇大论
- 聊家常话题:天气、吃饭、身体、往事
- 如果老人情绪低落,温柔安慰,必要时建议联系家人
"""

完整 Python 实现

import os
import json
import requests
import tempfile
import subprocess
from datetime import datetime

API_KEY = os.environ["SENSEAUDIO_API_KEY"]
ASR_URL = "https://api.senseaudio.cn/v1/audio/transcriptions"
TTS_URL = "https://api.senseaudio.cn/v1/t2a_v2"

# 适老化 TTS 参数
ELDERLY_TTS_PARAMS = {
    "model": "SenseAudio-TTS-1.0",
    "stream": False,
    "voice_setting": {
        "voice_id": "female_0001_a",
        "speed": 0.8,   # 慢速
        "vol": 3.0,     # 大音量
        "pitch": 0,
    },
    "audio_setting": {"format": "mp3", "sample_rate": 32000},
}


def asr_recognize(audio_path: str) -> str:
    """语音识别,返回转写文本"""
    with open(audio_path, "rb") as f:
        resp = requests.post(
            ASR_URL,
            headers={"Authorization": f"Bearer {API_KEY}"},
            files={"file": f},
            data={"model": "sense-asr", "language": "zh", "response_format": "text"},
            timeout=20,
        )
    resp.raise_for_status()
    return resp.text.strip()


def tts_speak(text: str) -> None:
    """TTS 合成并播放,适老化参数"""
    payload = {**ELDERLY_TTS_PARAMS, "text": text}
    resp = requests.post(
        TTS_URL,
        headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"},
        json=payload,
        timeout=20,
    )
    resp.raise_for_status()
    audio_bytes = bytes.fromhex(resp.json()["data"]["audio"])
    with tempfile.NamedTemporaryFile(suffix=".mp3", delete=False) as f:
        f.write(audio_bytes)
        tmp = f.name
    for cmd in [["afplay", tmp], ["play", tmp], ["mpg123", tmp]]:
        try:
            subprocess.run(cmd, check=True, capture_output=True)
            return
        except (FileNotFoundError, subprocess.CalledProcessError):
            continue


def extract_intent(text: str, llm_call) -> dict:
    """LLM 意图提取,容错老年人口语"""
    result = llm_call(
        system=INTENT_SYSTEM_PROMPT,
        user=text,
    )
    try:
        return json.loads(result)
    except json.JSONDecodeError:
        return {"intent": "unknown", "params": {}, "confidence": 0.0}


def handle_intent(intent_result: dict) -> str:
    """根据意图执行动作,返回播报文本"""
    intent = intent_result.get("intent")
    params = intent_result.get("params", {})
    confidence = intent_result.get("confidence", 1.0)

    if confidence \x3C 0.6 or intent == "confirm":
        return intent_result.get("confirm_text", "您刚才说的是什么意思,能再说一遍吗?")

    if intent == "send_message":
        to = params.get("to", "家人")
        content = params.get("content", "")
        # TODO: 调用消息发送接口
        return f"好的,已经帮您给{to}发了消息,内容是:{content}。"

    elif intent == "get_weather":
        city = params.get("city", "")
        weather = requests.get(
            f"https://wttr.in/{city or ''}?format=%c+%t+%h&lang=zh", timeout=10
        ).text.strip()
        return f"今天的天气是{weather}。出门记得看看冷不冷,注意保暖。"

    elif intent == "set_alarm":
        time_str = params.get("time", "")
        label = params.get("label", "提醒")
        # TODO: 调用系统闹钟接口
        return f"好的,已经帮您设好了{time_str}的闹钟,到时候提醒您{label}。"

    elif intent == "play_content":
        query = params.get("query", "")
        content_type = params.get("type", "内容")
        # TODO: 调用内容播放接口
        return f"好的,这就给您放{query or content_type},您听着,想换就跟我说。"

    elif intent == "chat":
        # 返回空字符串,由上层进入聊天模式
        return ""

    else:
        return "对不起,我没听清楚您说的。能再说一遍吗?说慢一点也没关系。"


class ElderlyVoiceAssistant:
    def __init__(self, llm_call):
        self.llm_call = llm_call
        self.last_active = datetime.now()
        self.preferences = {}  # 历史偏好

    def process_voice(self, audio_path: str) -> None:
        """主流程:录音 → 识别 → 意图 → 执行 → 播报"""
        self.last_active = datetime.now()

        # 1. ASR
        text = asr_recognize(audio_path)
        print(f"[识别] {text}")

        # 2. 意图理解
        intent_result = extract_intent(text, self.llm_call)
        print(f"[意图] {intent_result}")

        # 3. 执行 + 播报
        if intent_result.get("intent") == "chat":
            reply = self.llm_call(system=CHAT_SYSTEM_PROMPT, user=text)
            tts_speak(reply)
        else:
            response_text = handle_intent(intent_result)
            if response_text:
                tts_speak(response_text)

主动关怀系统

import threading
import time as time_module

class ProactiveCareScheduler:
    """主动关怀调度器"""

    def __init__(self, assistant: ElderlyVoiceAssistant, notify_family_callback):
        self.assistant = assistant
        self.notify_family = notify_family_callback
        self.reminders = []  # [(hour, minute, text), ...]

    def add_medication_reminder(self, hour: int, minute: int, medicine: str):
        self.reminders.append((hour, minute, f"该吃{medicine}了,记得喝水。"))

    def morning_briefing(self):
        """每天早上主动播报天气和穿着建议"""
        weather = requests.get("https://wttr.in/?format=%c+%t&lang=zh", timeout=10).text.strip()
        tts_speak(f"早上好!今天天气{weather}。记得吃早饭,注意身体。")

    def check_inactivity(self):
        """超过24小时无交互,通知子女"""
        delta = datetime.now() - self.assistant.last_active
        if delta.total_seconds() > 86400:
            self.notify_family("老人今天还没有使用语音助手,请关注一下。")

    def run(self):
        """后台运行调度循环"""
        def loop():
            while True:
                now = datetime.now()
                # 早上8点播报天气
                if now.hour == 8 and now.minute == 0:
                    self.morning_briefing()
                # 检查自定义提醒
                for h, m, text in self.reminders:
                    if now.hour == h and now.minute == m:
                        tts_speak(text)
                # 检查无交互
                self.check_inactivity()
                time_module.sleep(60)

        threading.Thread(target=loop, daemon=True).start()

错误处理与容错

def safe_process_voice(assistant: ElderlyVoiceAssistant, audio_path: str):
    """带容错的语音处理"""
    try:
        assistant.process_voice(audio_path)
    except requests.exceptions.Timeout:
        tts_speak("网络有点慢,请稍等一下再试。")
    except requests.exceptions.ConnectionError:
        tts_speak("网络好像断了,请检查一下网络连接。")
    except Exception:
        tts_speak("出了点小问题,请再说一遍,或者让家人帮您看看。")

相关资源

Usage Guidance
This skill mostly does what it says: it sends recorded audio to senseaudio.cn for ASR and TTS using a single API key. Before installing, confirm the following with the publisher: (1) Where and how does "send_message" deliver messages? What messaging API or permissions does it use and what credentials will be required? (2) How are contacts and "notify family" implemented and stored? Does the skill access the device contact list or require tokens for a messaging service? (3) Does the SenseAudio API store or retain uploaded audio? Check privacy, retention, and consent policies at the provided docs. (4) Verify the required local players (afplay/play/mpg123) and the subprocess usage — test in an isolated environment if possible. (5) Limit the SENSEAUDIO_API_KEY scope if supported and ensure you can revoke it. If the publisher cannot clearly explain how messages/notifications/alarms are implemented (and what extra permissions are needed), treat the missing details as a red flag and avoid granting broad access or production use.
Capability Analysis
Type: OpenClaw Skill Name: elderly-assistant Version: 1.0.0 The elderly-assistant skill is a legitimate implementation of a voice-controlled assistant designed for senior users. It utilizes SenseAudio APIs (api.senseaudio.cn) for speech-to-text and text-to-speech, and wttr.in for weather updates. The Python code follows safe practices, such as using list-based arguments in subprocess.run to prevent shell injection and handling temporary files correctly. No evidence of data exfiltration, malicious persistence, or harmful prompt injection was found in SKILL.md or the associated code.
Capability Assessment
Purpose & Capability
Name/description (elderly voice assistant) align with requiring python3, requests, and a SENSEAUDIO_API_KEY for ASR/TTS. Those requirements are expected for the stated purpose. However, the skill also claims functions (send messages to family, notify relatives when idle, invoke system alarm APIs, access contact mappings) that would normally require additional permissions or credentials which are not declared.
Instruction Scope
SKILL.md contains concrete runtime instructions and a full Python implementation that uploads user audio to https://api.senseaudio.cn (ASR/TTS) and plays audio locally. It also describes sending messages, accessing contact mappings, and notifying family/setting alarms, but gives no implementation details, no endpoints, and no required environment variables or config paths for those actions. The prompt/code will cause user audio to be transmitted off-device (privacy concern) and instructs subprocess execution to play audio. The instructions do not request unrelated env vars, but they do leave broad discretion and unspecified external interactions (message delivery, notifications) that are out-of-band of the declared API key.
Install Mechanism
Install spec lists a single dependency (requests). This is proportionate for the included Python code which uses the requests library. No arbitrary downloads or extract-from-URL steps are present.
Credentials
Only SENSEAUDIO_API_KEY is required and is appropriate for ASR/TTS. But capabilities described (sending messages, notifying relatives, accessing contacts, interacting with system alarms) would typically require additional credentials or platform permissions (SMS/messaging API keys, contact access tokens, mobile OS alarm APIs). Those are not declared, creating a gap between claimed features and declared environment access.
Persistence & Privilege
The skill does not request always:true and defaults to normal agent invocation. There is no install action that modifies other skills or system-wide configs. Playing audio and calling subprocesses are local actions but do not imply elevated or persistent privileges.
How to Use
  1. Make sure OpenClaw is installed (local or Docker)
  2. Run the install command in chat: /install elderly-assistant
  3. After installation, invoke the skill by name or use /elderly-assistant
  4. Provide required inputs per the skill's parameter spec and get structured output
Version History
v1.0.0
Elderly Voice Assistant 1.0.0 - Initial release: A voice assistant tailored for elderly users, enabling messaging, weather checks, alarms, news, opera, and companion chat entirely via voice. - Zero-barrier UI: Operated using a single large microphone button, with no textual menus. - Robust intent understanding: Handles hesitations, repetitive/ambiguous speech, and dialects for accurate action extraction. - Voice-centric feedback: All responses are delivered via slow, clear, high-volume speech synthesis. - Proactive care: Features include medication/drinking reminders and periodic family notifications. - Content companionship: Offers playback of opera, old songs, storytelling, and supports friendly AI chats.
Metadata
Slug elderly-assistant
Version 1.0.0
License MIT-0
All-time Installs 0
Active Installs 0
Total Versions 1
Frequently Asked Questions

What is Elderly Voice Assistant?

银发族语音助手——老年人对着手机说话就能发消息、查天气、设闹钟、听戏曲,无需学任何操作。 It is an AI Agent Skill for Claude Code / OpenClaw, with 254 downloads so far.

How do I install Elderly Voice Assistant?

Run "/install elderly-assistant" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.

Is Elderly Voice Assistant free?

Yes, Elderly Voice Assistant is completely free, licensed under MIT-0. You can download, install and use it at no cost.

Which platforms does Elderly Voice Assistant support?

Elderly Voice Assistant is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).

Who created Elderly Voice Assistant?

It is built and maintained by scikkk (@scikkk); the current version is v1.0.0.

💬 Comments