标签 TTS 下的文章

开发者朋友们大家好:

这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的 技术 」、「有亮点的 产品 」、「有思考的 文章 」、「有态度的 观点 」、「有看点的 活动 」,但内容仅代表编辑的个人观点,欢迎大家留言、跟帖、讨论。

本期编辑:@瓒an、@鲍勃

01 有话题的技术

1、阿里发布万亿参数模型 Qwen3-Max-Thinking,性能对标 GPT-5.2

昨天,阿里正式发布千问旗舰推理模型 Qwen3-Max-Thinking。该模型总参数量超万亿(1T),在多项权威评测中刷新全球纪录,官方宣称其性能媲美 GPT-5.2、Gemini 3 Pro,是迄今为止最接近国际顶尖水平的国产 AI 大模型。

Qwen3-Max-Thinking 的预训练数据量高达 36T Tokens,并在预览版基础上进行了更大规模的强化学习后训练。在涵盖事实知识、复杂推理、指令遵循等 19 个基准测试中,该模型刷新了数项最佳表现(SOTA)纪录。

根据官方公布的评测数据,Qwen3-Max-Thinking 在启用 TTS(Test-time Scaling)机制后,在科学知识(GPQA Diamond)测试中得分 92.8,略高于 GPT-5.2 的 92.4;

在数学推理(IMO-AnswerBench)和代码编程(LiveCodeBench 2025.02-2025.05)中分别取得 91.5 和 91.4 的高分,均优于 GPT-5.2、Claude Opus 4.5 和 Gemini 3 Pro。

特别是在启用工具的「人类最后的测试」(Humanity's Last Exam with Search)中,该模型得分为 58.3,大幅领先 GPT-5.2-Thinking 的 45.5 分,录得当前所有模型的最高分。

技术层面,阿里表示 Qwen3-Max-Thinking 采用了一种全新的测试时扩展机制。 与业界普遍的简单增加并行推理路径不同,新机制能对此前推理结果进行「经验提取」式的提炼,通过多轮自我迭代在相同上下文中实现更高效的推理计算。

此外,模型大幅增强了自主调用工具的原生 Agent 能力。 经过基于规则奖励与模型奖励的联合强化学习训练,模型可自适应选用搜索、个性化记忆和代码解释器等核心工具,不仅回答更流畅,还大幅降低了模型幻觉。

目前,普通用户可通过千问 PC 端和网页端免费试用新模型,千问 App 也即将接入;企业开发者则可通过阿里云百炼获取 API 服务。

体验链接

Qwen Chat: https\://chat.qwen.ai/

阿里云百炼:

https\://bailian.console.aliyun.com/cn-beijing/?tab=model#/model-market/detail/qwen3-max-2026-01-23

( @APPSO)

2、打通感知、交互与执行:讯飞星辰升级多模态全栈能力,加速智能体规模化落地

1 月 26 日,讯飞星辰智能体平台官宣重大升级,实现了讯飞星辰智能体平台和 AIUI 开放平台完全打通、升级超拟人交互技术、支持快速定制音色、RPA 升级,提供一套全面且完整的多模交互解决方案,让智能体拥有更全面的类人化交互能力、全场景执行能力。

  • AIUI 开放平台接口打通 :支持在「讯飞星辰」创建智能体并一键发布至 AIUI,实现语音交互与机器人动作规划(如桌面机器人绘本生成、运动轨迹)的同步调用与快速集成。
  • 秒级「一句话声音复刻」 :利用超拟人交互技术,支持通过自然语言描述声线并在几秒内合成 4 个候选音色;支持中英日韩粤等多语种、方言及多风格(新闻、交谈、绘本)音色生成。
  • 单图构建多模态数字分身 :支持通过一张照片快速生成数字人,其口型、表情及动作由大模型自动驱动;结合多模态视觉理解,支持智能体实现主动迎宾与环境感知的交互闭环。
  • RPA 执行能力组件化 :升级网页自动化智能组件,支持非专业开发人员通过低代码配置参数进行流程编排;提供开源可视化数据表格功能,实现数据提取与处理过程的透明化。

最直观的一个例子就是,将 为智能体定制声音的时间压缩到了几秒钟

发布会的实际演示中,操作人员在讯飞星辰智能体平台生成了曹操人格的智能体后,通过自然语言描述想要的音色声线、输入试听文本、点击生成,就在几秒内合成 4 个候选音色。接着选择保存、应用音色后,用户就能与刚刚的曹操人格智能体进行语音聊天。

这是讯飞星辰智能体平台此次升级的一个缩影,而智能体的未来形态,将从单一工具,升级为兼具感知、交互能力,拥有专属声音、形象与性格人设,还能自主完成操作执行的全能型智能体,驱动这一切进化的核心,正是多模交互技术

当前海内外大厂与科创企业均在智能体平台赛道加速布局、密集发力,但行业仍普遍面临技术落地难、场景适配不深的核心痛点。

讯飞星辰智能体平台此次实现感知、交互、执行三大核心能力的一体化整合,从底层打破智能体落地过程中的技术协同壁垒,直面其场景适配难题,为智能体技术的规模化落地扫清关键障碍。

简言之,讯飞星辰智能体平台此次升级,核心便是瞄准降低智能体开发门槛、丰富其可落地的能力边界两大核心目标,在扩展服务能力的基础上,还提供了低代码、一键接入、快速接入等快速开发部署工具。

总的来看,当前智能体产业技术成熟度足够支撑场景落地,市场需求旺盛,但落地效率与成本仍是核心瓶颈,而打通场景适配、能力集成、生态协同的全栈能力,将成为智能体产业竞争的核心壁垒。

相关链接:

https\://agent.xfyun.cn

(@智东西、@讯飞开放平台)

3、Google 支付 6800 万美元和解金,解决语音助手「监视」用户的指控

据路透社报道,Google 已同意支付 6800 万美元,以解决一项指控其语音助手非法监视用户、并利用相关数据投放广告的索赔诉讼。

Google 在这项集体诉讼的和解协议中并未承认存在任何不当行为。该诉讼指控 Google「在未经个人同意的情况下,非法且故意地拦截并录制个人的机密通信,并随后将这些通信未经授权地披露给第三方。」诉讼进一步声称,「从这些录音中收集的信息被错误地传输给了第三方,用于定向广告及其他目的。」

该案件的核心争议集中在「错误唤醒」上,即指控 Google Assistant 即使在用户未通过唤醒词有意触发的情况下,也会自动激活并录制用户的通信内容。TechCrunch 已就此联系 Google 寻求置评。


长期以来,美国民众一直怀疑电子设备在不适当地监视他们,这些怀疑正日益转化为法律诉讼。2021 年,苹果公司曾同意支付 9500 万美元,以解决关于其语音助手 Siri 在未获用户提示的情况下录制对话的类似指控。

与其他科技巨头一样,Google 近年来也面临着多起隐私相关的诉讼。去年,该公司同意向得克萨斯州支付 14 亿美元,以解决两起指控其违反该州数据隐私法的诉讼。

( @TechCrunch)


02 有亮点的产品

1、249 元起,苹果推出升级版 AirTag,精确查找范围扩大 50%

昨天,苹果突然官宣,正式推出新款 AirTag,采用与 iPhone 17 系列、iPhone Air、Apple Watch Ultra 3 及 Apple Watch Series 11 相同的第二代超宽带芯片,在连接范围、精确查找能力与扬声器音量方面均进行了大幅升级:

  • 精确查找范围最高提升 50%,定位更快更准
  • 蓝牙连接范围扩大,远距离也能找到
  • 扬声器音量提升 50%,提示音更响亮
  • 支持 Apple Watch 精确查找,查找场景更丰富
  • 「查找」网络升级,脱离配对设备也能回传位置
  • 防追踪机制强化,跨平台警报更可靠
  • 支持共享物品位置,协助航空公司找回延误行李
  • 外壳与磁铁采用高比例再生材料,更环保

新款 AirTag 已正式开售。售价方面,单件装售价 249 元,四件装售价 849 元,并提供免费镌刻服务。零售店将于本周晚些时候陆续上架。

与此同时,苹果今天还推送了 iOS、iPadOS 和 watchOS 26.2.1,主要更新内容是新增对 AirTag 2 的支持。

( @APPSO)

2、京东「抢跑」淘宝,首款智能眼镜购物应用落地乐奇 Rokid

1 月 26 日消息,京东科技购物智能体 JoyGlance 正式登录智能眼镜品牌乐奇 Rokid,标志着行业首款智能眼镜购物应用正式落地,是京东布局「具身智能消费场景」的关键一步。

用户只需将 Rokid 眼镜系统更新至最新版本,应用由京东自研大模型 JoyAI 驱动,深度融合 Rokid 在光波导显示、远场语音交互与自研操作系统上的硬件能力,将传统网购流程从「搜索—浏览—比价—下单—支付」五步,压缩为极简的 「说、看、付」三步

据悉,2025 年 10 月,Rokid 乐奇与京东科技就达成战略协议。此次携手,不仅是技术突破,更是消费入口的迁移,开启全球首个「所见即购买」的智能眼镜全链路购物入口,实现「目光所及、皆可购买」

当购物从「指尖滑动」转向「目光注视」,智能眼镜正从可穿戴设备升级为下一代空间计算与消费交互终端。用户不再依赖搜索框或直播链接,而是将物理世界直接转化为购物入口,或为电商行业开辟了全新的场景。

(@即智 Ultra)

3、LiveTok 发布「LiveTok Avatars」:支持单张照片生成实时交互式 AI 数字孪生

LiveTok 推出基于 AI 的虚拟助手平台「LiveTok Avatars」。该产品支持通过单张静态照片构建具备实时音视频交互能力的数字分身,旨在通过拟人化的「数字孪生」替代传统文字客服,实现 24/7 的实时客户互动。

  • 单图驱动数字孪生 :用户仅需上传单张人物照片,AI 即可生成具备面部动态的克隆形象,无需复杂的视频采集。
  • 行为与语调克隆 :AI 模型通过学习可复刻特定个体的说话风格、语速及特定动作习惯,提供具备自然停顿的类人语音响应。
  • 低代码 Web 集成 :支持通过嵌入数行代码直接在网站部署,无需复杂的后端环境配置。
  • 实时音视频同步 :提供低延迟的实时语音对话环境,演示版本目前支持单次最高 2 分钟的交互。

目前处于 Beta 测试阶段,提供免费起步版,特定「数字孪生」功能需申请加入 Waitlist。

相关链接:

https\://www.livetok.ai/products/avatars

( @LiveTok)

4、阶跃星辰获超 50 亿人民币融资,印奇出任董事长

昨天,大模型创业公司阶跃星辰(StepFun)完成超 50 亿人民币 B+ 轮融资,创下过去 12 个月大模型赛道单笔最高融资纪录。上国投先导基金、国寿股权、浦东创投、徐汇资本、无锡梁溪基金、厦门国贸、华勤技术等产业投资方参与本轮融资,腾讯、启明、五源等老股东继续加码。本轮资金将主要用于基础模型研发,并加速「AI + 终端」战略落地。

同日,阶跃星辰宣布千里科技董事长印奇正式出任公司董事长,全面负责公司战略节奏与技术方向。 印奇此前已深度参与阶跃星辰的战略规划,其加入被视为公司在大模型「季后赛」阶段强化产业落地能力的关键一步。

这笔融资规模不仅超过月之暗面此前宣布的 5 亿美元 C 轮,也高于智谱与 MiniMax IPO 募资额,成为近期 AI 资本市场最受关注的事件之一。

过去两年间,该团队在「百模大战」中突围,跻身国内大模型第一梯队,并持续坚持预训练路线,构建了覆盖语言、多模态、音频、动作等方向的完整模型矩阵。

印奇的加入补足了阶跃星辰在产业落地上的关键能力。作为旷视科技联合创始人,印奇在 AIoT、城市级物联网系统等领域拥有丰富经验,其长期关注的「AI+终端」路径也与阶跃星辰的战略方向高度一致。

  • 在商业化方面,阶跃星辰已与国内六成头部智能手机品牌达成深度合作,模型装机量突破 4200 万台,覆盖 OPPO、荣耀、中兴等品牌,日均服务用户达 2000 万人次;
  • 在汽车领域,公司与千里科技、吉利合作,将端到端语音模型集成至智能座舱系统,吉利银河 M9 上市 3 个月销量接近 4 万辆,阶跃星辰今年的车载模型装车目标为百万级;
  • 在技术路线方面,阶跃星辰坚持「原生多模态」策略,直接从图文交错语料进行端到端训练,以提升模型对物理世界的理解能力。其音频模型 Step-Audio-R1.1 通过 MGRD 技术在权威榜单 Artificial Analysis 上取得全球第一。

印奇的加入意味着阶跃星辰将加速推进「AI 进入物理世界」的战略,并在手机、汽车等消费终端形成更具确定性的商业闭环。

( @APPSO)


03 有态度的观点

1、俞敏洪:AI 或消灭大量教师岗位,中小学教师「一大半是不合格的」

据快科技报道,新东方创始人俞敏洪近日在今年崇礼论坛上围绕互联网与人工智能对教育行业的影响发表最新观点。

他指出,技术变革正推动教育从「一张嘴一块黑板」到「互联网 + 教育」,再迈向「AI + 教育」,并强调这一趋势将深刻改变教师岗位结构。

俞敏洪表示,互联网仍在人类可控范围内,但其带来的舆论放大效应已深刻影响个人生活。他提到,过去三年遭遇的网暴与互联网环境密切相关。

相比之下,人工智能的影响更具结构性,其在教育、医疗、生物等领域的应用将持续扩大。

在教育场景中,他认为 AI 已能完成接近 100% 的英语交流与作业批改,不仅提升效率,也减轻学生面对老师时的心理压力。他指出,AI 的普及可能会「消灭大量老师岗位」,因为基础知识传递正被技术快速替代。

他进一步强调,未来教师的核心价值将转向激发学生潜能、塑造人格与引导成长,这些能力无法被技术替代。


按照这一标准,他直言目前国内中小学教师「一大半不合格」,部分教师面对学生提问时因无法回答而迁怒学生的现象亟需改善。

俞敏洪还回顾新东方在「互联网 + 教育」时代的结构性变化:互联网放大名师影响力,使大量优秀教师离开线下课堂,包括他本人也不再走进教室授课。

他认为,AI 的到来将带来更深层次的行业重塑,对教师提出更高要求,而这些要求比以往更难达到。

他强调,人工智能的最终走向取决于使用者,而非技术本身,教育行业需要在技术变革中重新定义教师角色与价值。

( @APPSO)


阅读更多 Voice Agent 学习笔记:了解最懂 AI 语音的头脑都在思考什么

写在最后:

我们欢迎更多的小伙伴参与 「RTE 开发者日报」 内容的共创,感兴趣的朋友请通过开发者社区或公众号留言联系,记得报暗号「共创」。

对于任何反馈(包括但不限于内容上、形式上)我们不胜感激、并有小惊喜回馈,例如你希望从日报中看到哪些内容;自己推荐的信源、项目、话题、活动等;或者列举几个你喜欢看、平时常看的内容渠道;内容排版或呈现形式上有哪些可以改进的地方等。


作者提示: 个人观点,仅供参考​

大家好,我是V哥!今天要跟大家分享一个超级干货——如何在鸿蒙6(API21)上开发一个真正能用的AI智能体。不是那种玩具级别的Demo,而是能语音对话、能理解你意图、还能帮你干活的智能助手!

一、为什么要在鸿蒙上做AI智能体?

兄弟们,2026年了,AI Agent(智能体)绝对是最火的技术方向之一。什么是智能体?简单说就是:能感知、能思考、能行动的AI程序

鸿蒙6在AI这块可以说是下了血本:

  • 原生AI能力:MindSpore Lite端侧推理引擎
  • 语音能力:ASR语音识别 + TTS语音合成
  • 意图识别:智能理解用户需求
  • 大模型接入:轻松对接各种LLM API

今天V哥就手把手带你做一个多模态AI智能助手,它能:

  1. ✅ 语音唤醒,开口就能聊
  2. ✅ 智能对话,接入大模型
  3. ✅ 意图识别,理解你想干嘛
  4. ✅ 执行任务,帮你打开应用、设置闹钟等
  5. ✅ 多轮记忆,上下文连贯

废话不多说,直接上代码!


二、项目架构设计

┌─────────────────────────────────────────────────────────────────┐
│                      AI智能体架构(V哥设计)                      │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   ┌─────────────┐    ┌─────────────┐    ┌─────────────┐        │
│   │  语音输入   │───▶│  语音识别   │───▶│  意图理解   │        │
│   │   (ASR)    │    │   Engine    │    │   Engine    │        │
│   └─────────────┘    └─────────────┘    └──────┬──────┘        │
│                                                 │               │
│                                                 ▼               │
│   ┌─────────────┐    ┌─────────────┐    ┌─────────────┐        │
│   │  语音输出   │◀───│  回复生成   │◀───│  对话管理   │        │
│   │   (TTS)    │    │   (LLM)    │    │   Agent    │        │
│   └─────────────┘    └─────────────┘    └──────┬──────┘        │
│                                                 │               │
│                                                 ▼               │
│                                        ┌─────────────┐         │
│                                        │  任务执行   │         │
│                                        │  Actions   │         │
│                                        └─────────────┘         │
└─────────────────────────────────────────────────────────────────┘

三、项目创建与配置

步骤1:创建项目

DevEco Studio → New Project
→ Empty Ability (Stage模型)
→ Project name: VGeAIAgent
→ Bundle name: com.vge.aiagent
→ Compile SDK: 5.0.0(API 12) 或更高

步骤2:配置 module.json5

{
  "module": {
    "name": "entry",
    "type": "entry",
    "description": "$string:module_desc",
    "mainElement": "EntryAbility",
    "deviceTypes": ["phone", "tablet"],
    "deliveryWithInstall": true,
    "installationFree": false,
    "pages": "$profile:main_pages",
    "abilities": [
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ets",
        "description": "$string:EntryAbility_desc",
        "icon": "$media:icon",
        "label": "$string:EntryAbility_label",
        "startWindowIcon": "$media:startIcon",
        "startWindowBackground": "$color:start_window_background",
        "exported": true,
        "skills": [
          {
            "entities": ["entity.system.home"],
            "actions": ["action.system.home"]
          }
        ]
      }
    ],
    "requestPermissions": [
      {
        "name": "ohos.permission.MICROPHONE",
        "reason": "$string:mic_reason",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "inuse"
        }
      },
      {
        "name": "ohos.permission.INTERNET",
        "reason": "$string:net_reason",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "always"
        }
      },
      {
        "name": "ohos.permission.DISTRIBUTED_DATASYNC",
        "reason": "$string:sync_reason",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "always"
        }
      }
    ]
  }
}

四、核心代码实现

1. 消息数据模型 (model/MessageModel.ets)

// entry/src/main/ets/model/MessageModel.ets

/**
 * V哥设计的消息模型
 * 支持多种消息类型,为后续扩展预留空间
 */

// 消息角色
export enum MessageRole {
  USER = 'user',           // 用户消息
  ASSISTANT = 'assistant', // AI助手消息
  SYSTEM = 'system'        // 系统消息
}

// 消息类型
export enum MessageType {
  TEXT = 'text',           // 文本消息
  VOICE = 'voice',         // 语音消息
  ACTION = 'action',       // 执行动作
  THINKING = 'thinking'    // 思考中
}

// 意图类型
export enum IntentType {
  CHAT = 'chat',                    // 闲聊
  OPEN_APP = 'open_app',            // 打开应用
  SET_ALARM = 'set_alarm',          // 设置闹钟
  SET_REMINDER = 'set_reminder',    // 设置提醒
  QUERY_WEATHER = 'query_weather',  // 查询天气
  QUERY_TIME = 'query_time',        // 查询时间
  CONTROL_DEVICE = 'control_device',// 控制设备
  UNKNOWN = 'unknown'               // 未知意图
}

// 消息实体
export class Message {
  id: string = '';
  role: MessageRole = MessageRole.USER;
  type: MessageType = MessageType.TEXT;
  content: string = '';
  timestamp: number = 0;
  intent?: IntentType;
  intentParams?: Record<string, string>;
  isStreaming?: boolean;  // 是否流式输出中

  constructor(init?: Partial<Message>) {
    this.id = `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
    this.timestamp = Date.now();
    if (init) {
      Object.assign(this, init);
    }
  }
}

// 对话上下文(用于多轮对话)
export class ConversationContext {
  messages: Message[] = [];
  maxHistory: number = 10;  // 最多保留10轮对话

  addMessage(message: Message): void {
    this.messages.push(message);
    // 超过限制则移除最早的消息
    if (this.messages.length > this.maxHistory * 2) {
      this.messages = this.messages.slice(-this.maxHistory * 2);
    }
  }

  getHistory(): Message[] {
    return this.messages;
  }

  clear(): void {
    this.messages = [];
  }

  // 转换为LLM API需要的格式
  toAPIFormat(): Array<{role: string, content: string}> {
    return this.messages
      .filter(m => m.type === MessageType.TEXT)
      .map(m => ({
        role: m.role,
        content: m.content
      }));
  }
}

2. 意图识别引擎 (engine/IntentEngine.ets)

// entry/src/main/ets/engine/IntentEngine.ets

import { IntentType } from '../model/MessageModel';

/**
 * V哥的意图识别引擎
 * 使用规则+关键词匹配,生产环境可接入NLU模型
 */

interface IntentRule {
  intent: IntentType;
  keywords: string[];
  patterns: RegExp[];
  extractor?: (text: string) => Record<string, string>;
}

export class IntentEngine {
  private static instance: IntentEngine;
  private rules: IntentRule[] = [];

  private constructor() {
    this.initRules();
  }

  static getInstance(): IntentEngine {
    if (!IntentEngine.instance) {
      IntentEngine.instance = new IntentEngine();
    }
    return IntentEngine.instance;
  }

  /**
   * 初始化意图规则
   */
  private initRules(): void {
    this.rules = [
      // 打开应用
      {
        intent: IntentType.OPEN_APP,
        keywords: ['打开', '启动', '运行', '开启'],
        patterns: [
          /打开(.+?)(?:应用|app|APP)?$/,
          /启动(.+)/,
          /帮我开(.+)/
        ],
        extractor: (text: string) => {
          const appNames: Record<string, string> = {
            '相机': 'com.huawei.camera',
            '相册': 'com.huawei.photos',
            '设置': 'com.huawei.settings',
            '日历': 'com.huawei.calendar',
            '计算器': 'com.huawei.calculator',
            '备忘录': 'com.huawei.notes',
            '音乐': 'com.huawei.music',
            '视频': 'com.huawei.video',
            '浏览器': 'com.huawei.browser',
            '微信': 'com.tencent.mm',
            '支付宝': 'com.eg.android.AlipayGphone',
            '抖音': 'com.ss.android.ugc.aweme'
          };

          for (const [name, bundleName] of Object.entries(appNames)) {
            if (text.includes(name)) {
              return { appName: name, bundleName: bundleName };
            }
          }
          return {};
        }
      },

      // 设置闹钟
      {
        intent: IntentType.SET_ALARM,
        keywords: ['闹钟', '叫我', '提醒我起床', '定个闹钟'],
        patterns: [
          /(\d{1,2})[点::](\d{0,2}).*(?:闹钟|叫我|起床)/,
          /(?:明天|后天)?(?:早上|上午|中午|下午|晚上)?(\d{1,2})[点::]?(\d{0,2})?.*(?:闹钟|叫我)/,
          /设.*闹钟.*(\d{1,2})[点::](\d{0,2})?/
        ],
        extractor: (text: string) => {
          const timeMatch = text.match(/(\d{1,2})[点::](\d{0,2})?/);
          if (timeMatch) {
            const hour = timeMatch[1];
            const minute = timeMatch[2] || '00';
            return { hour, minute };
          }
          return {};
        }
      },

      // 设置提醒
      {
        intent: IntentType.SET_REMINDER,
        keywords: ['提醒我', '别忘了', '记得'],
        patterns: [
          /(\d+)(?:分钟|小时)后提醒我(.+)/,
          /提醒我(.+)/,
          /(\d{1,2})[点::](\d{0,2})?提醒我(.+)/
        ],
        extractor: (text: string) => {
          // 提取时间和内容
          const minuteMatch = text.match(/(\d+)分钟后提醒我(.+)/);
          if (minuteMatch) {
            return {
              delayMinutes: minuteMatch[1],
              content: minuteMatch[2]
            };
          }

          const hourMatch = text.match(/(\d+)小时后提醒我(.+)/);
          if (hourMatch) {
            return {
              delayMinutes: String(parseInt(hourMatch[1]) * 60),
              content: hourMatch[2]
            };
          }

          const contentMatch = text.match(/提醒我(.+)/);
          if (contentMatch) {
            return { content: contentMatch[1] };
          }

          return {};
        }
      },

      // 查询天气
      {
        intent: IntentType.QUERY_WEATHER,
        keywords: ['天气', '下雨', '温度', '气温', '穿什么'],
        patterns: [
          /(.+?)(?:的)?天气/,
          /(?:今天|明天|后天).*(?:天气|下雨|温度)/,
          /要不要带伞/
        ],
        extractor: (text: string) => {
          const cityMatch = text.match(/(.{2,4}?)(?:的)?天气/);
          if (cityMatch && !['今天', '明天', '后天', '这里', '现在'].includes(cityMatch[1])) {
            return { city: cityMatch[1] };
          }
          return { city: '北京' };  // 默认城市
        }
      },

      // 查询时间
      {
        intent: IntentType.QUERY_TIME,
        keywords: ['几点', '时间', '日期', '星期几', '今天几号'],
        patterns: [
          /现在几点/,
          /什么时间/,
          /今天.*(?:几号|星期几|周几)/
        ],
        extractor: () => ({})
      },

      // 控制设备
      {
        intent: IntentType.CONTROL_DEVICE,
        keywords: ['打开灯', '关灯', '开灯', '空调', '电视', '窗帘'],
        patterns: [
          /(打开|关闭|开|关)(.+?)(?:灯|空调|电视|窗帘)/,
          /把(.+?)(打开|关闭|开|关)/,
          /(.+?)(?:调到|设置为?)(\d+)度/
        ],
        extractor: (text: string) => {
          const actionMatch = text.match(/(打开|关闭|开|关)(.+)/);
          if (actionMatch) {
            return {
              action: actionMatch[1].includes('开') ? 'on' : 'off',
              device: actionMatch[2]
            };
          }
          return {};
        }
      }
    ];
  }

  /**
   * 识别用户意图
   */
  recognize(text: string): { intent: IntentType; params: Record<string, string>; confidence: number } {
    const normalizedText = text.toLowerCase().trim();

    for (const rule of this.rules) {
      // 关键词匹配
      const keywordMatch = rule.keywords.some(kw => normalizedText.includes(kw));

      // 正则匹配
      const patternMatch = rule.patterns.some(pattern => pattern.test(normalizedText));

      if (keywordMatch || patternMatch) {
        const params = rule.extractor ? rule.extractor(normalizedText) : {};
        const confidence = keywordMatch && patternMatch ? 0.95 : 0.75;

        console.info(`[IntentEngine] 识别结果: ${rule.intent}, 置信度: ${confidence}`);
        return {
          intent: rule.intent,
          params,
          confidence
        };
      }
    }

    // 默认为闲聊
    return {
      intent: IntentType.CHAT,
      params: {},
      confidence: 0.5
    };
  }
}

3. 大模型对话服务 (service/LLMService.ets)

// entry/src/main/ets/service/LLMService.ets

import { http } from '@kit.NetworkKit';
import { ConversationContext, Message, MessageRole } from '../model/MessageModel';
import { BusinessError } from '@kit.BasicServicesKit';

/**
 * V哥的LLM服务封装
 * 支持多种大模型API,这里以通用格式为例
 */

// LLM配置接口
interface LLMConfig {
  apiUrl: string;
  apiKey: string;
  model: string;
  maxTokens: number;
  temperature: number;
}

// API请求格式
interface ChatCompletionRequest {
  model: string;
  messages: Array<{ role: string; content: string }>;
  max_tokens: number;
  temperature: number;
  stream: boolean;
}

// API响应格式
interface ChatCompletionResponse {
  id: string;
  choices: Array<{
    message: {
      role: string;
      content: string;
    };
    finish_reason: string;
  }>;
  usage: {
    prompt_tokens: number;
    completion_tokens: number;
    total_tokens: number;
  };
}

export class LLMService {
  private static instance: LLMService;
  private config: LLMConfig;
  private systemPrompt: string;

  private constructor() {
    // 默认配置(实际使用时替换为你的API信息)
    this.config = {
      apiUrl: 'https://api.openai.com/v1/chat/completions',  // 或其他兼容API
      apiKey: 'your-api-key-here',  // 替换为你的API Key
      model: 'gpt-3.5-turbo',
      maxTokens: 2048,
      temperature: 0.7
    };

    // 系统提示词 - V哥精心调教
    this.systemPrompt = `你是一个运行在鸿蒙系统上的AI智能助手,名叫"小V助手"。

你的特点:
1. 友好、幽默、专业
2. 回答简洁有力,不啰嗦
3. 能理解用户意图,给出实用建议
4. 熟悉鸿蒙生态和华为设备
5. 在适当时候使用emoji增加亲和力

你可以帮用户:
- 回答各种问题
- 闲聊解闷
- 提供建议和帮助
- 解释技术概念

请用中文回复,保持回答在100字以内(除非用户明确要求详细解释)。`;
  }

  static getInstance(): LLMService {
    if (!LLMService.instance) {
      LLMService.instance = new LLMService();
    }
    return LLMService.instance;
  }

  /**
   * 更新配置
   */
  updateConfig(config: Partial<LLMConfig>): void {
    this.config = { ...this.config, ...config };
  }

  /**
   * 发送对话请求
   */
  async chat(userMessage: string, context: ConversationContext): Promise<string> {
    // 构建消息历史
    const messages: Array<{ role: string; content: string }> = [
      { role: 'system', content: this.systemPrompt },
      ...context.toAPIFormat(),
      { role: 'user', content: userMessage }
    ];

    const requestData: ChatCompletionRequest = {
      model: this.config.model,
      messages: messages,
      max_tokens: this.config.maxTokens,
      temperature: this.config.temperature,
      stream: false
    };

    try {
      const httpRequest = http.createHttp();

      const response = await httpRequest.request(
        this.config.apiUrl,
        {
          method: http.RequestMethod.POST,
          header: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${this.config.apiKey}`
          },
          extraData: JSON.stringify(requestData),
          connectTimeout: 30000,
          readTimeout: 60000
        }
      );

      httpRequest.destroy();

      if (response.responseCode === 200) {
        const result = JSON.parse(response.result as string) as ChatCompletionResponse;
        const content = result.choices[0]?.message?.content || '抱歉,我没有理解你的意思';
        console.info(`[LLMService] 响应成功,Token使用: ${result.usage?.total_tokens}`);
        return content;
      } else {
        console.error(`[LLMService] API错误: ${response.responseCode}`);
        return this.getFallbackResponse(userMessage);
      }
    } catch (err) {
      const error = err as BusinessError;
      console.error(`[LLMService] 请求失败: ${error.code} - ${error.message}`);
      return this.getFallbackResponse(userMessage);
    }
  }

  /**
   * 离线兜底回复(当API不可用时)
   */
  private getFallbackResponse(userMessage: string): string {
    const fallbackResponses: Record<string, string[]> = {
      '你好': ['你好呀!有什么可以帮你的?', '嗨!我是小V助手,很高兴见到你!'],
      '谢谢': ['不客气!随时为你服务~', '应该的,还有什么需要帮助的吗?'],
      '再见': ['再见!期待下次聊天~', '拜拜,有事随时找我哦!'],
      '你是谁': ['我是小V助手,运行在鸿蒙系统上的AI助手!', '我叫小V,是V哥打造的智能助手~'],
      '你能做什么': ['我能陪你聊天、回答问题、帮你打开应用、设置提醒等等!试试看吧~', 
                   '我可以:闲聊解闷、回答问题、控制设备、设置闹钟提醒...功能多多!']
    };

    // 关键词匹配
    for (const [keyword, responses] of Object.entries(fallbackResponses)) {
      if (userMessage.includes(keyword)) {
        return responses[Math.floor(Math.random() * responses.length)];
      }
    }

    // 默认回复
    const defaultResponses = [
      '我现在网络不太好,稍后再试试吧~',
      '让我想想... 你能换个方式问我吗?',
      '抱歉,我没太理解,能再说一遍吗?',
      '网络开小差了,不过我们可以继续聊别的!'
    ];

    return defaultResponses[Math.floor(Math.random() * defaultResponses.length)];
  }

  /**
   * 流式对话(支持打字机效果)
   */
  async chatStream(
    userMessage: string,
    context: ConversationContext,
    onChunk: (chunk: string) => void,
    onComplete: (fullText: string) => void
  ): Promise<void> {
    // 简化实现:模拟流式输出
    const response = await this.chat(userMessage, context);

    let index = 0;
    const interval = setInterval(() => {
      if (index < response.length) {
        onChunk(response[index]);
        index++;
      } else {
        clearInterval(interval);
        onComplete(response);
      }
    }, 30);  // 每30ms输出一个字符
  }
}

4. 语音服务封装 (service/VoiceService.ets)

// entry/src/main/ets/service/VoiceService.ets

import { speechRecognizer } from '@kit.CoreSpeechKit';
import { textToSpeech } from '@kit.CoreSpeechKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { abilityAccessCtrl, Permissions } from '@kit.AbilityKit';

/**
 * V哥的语音服务封装
 * 整合ASR语音识别 + TTS语音合成
 */

export class VoiceService {
  private static instance: VoiceService;
  private asrEngine: speechRecognizer.SpeechRecognitionEngine | null = null;
  private ttsEngine: textToSpeech.TextToSpeechEngine | null = null;
  private isListening: boolean = false;

  private constructor() {}

  static getInstance(): VoiceService {
    if (!VoiceService.instance) {
      VoiceService.instance = new VoiceService();
    }
    return VoiceService.instance;
  }

  /**
   * 请求麦克风权限
   */
  async requestPermission(context: Context): Promise<boolean> {
    const atManager = abilityAccessCtrl.createAtManager();
    const permissions: Permissions[] = ['ohos.permission.MICROPHONE'];

    try {
      const result = await atManager.requestPermissionsFromUser(context, permissions);
      const granted = result.authResults.every(r => r === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED);
      console.info(`[VoiceService] 麦克风权限: ${granted ? '已授权' : '被拒绝'}`);
      return granted;
    } catch (err) {
      console.error('[VoiceService] 请求权限失败:', JSON.stringify(err));
      return false;
    }
  }

  /**
   * 初始化语音识别引擎
   */
  async initASR(): Promise<boolean> {
    try {
      const createParams: speechRecognizer.CreateEngineParams = {
        language: 'zh-CN',
        online: 1  // 1-在线识别 0-离线识别
      };

      this.asrEngine = await speechRecognizer.createEngine(createParams);
      console.info('[VoiceService] ASR引擎初始化成功');
      return true;
    } catch (err) {
      const error = err as BusinessError;
      console.error(`[VoiceService] ASR初始化失败: ${error.code} - ${error.message}`);
      return false;
    }
  }

  /**
   * 初始化语音合成引擎
   */
  async initTTS(): Promise<boolean> {
    try {
      const createParams: textToSpeech.CreateEngineParams = {
        language: 'zh-CN',
        person: 0,  // 发音人
        online: 1   // 1-在线合成 0-离线合成
      };

      const extraParams: Record<string, Object> = {
        style: 'normal',
        speed: 1.0,
        volume: 1.0,
        pitch: 1.0
      };

      this.ttsEngine = await textToSpeech.createEngine(createParams);
      console.info('[VoiceService] TTS引擎初始化成功');
      return true;
    } catch (err) {
      const error = err as BusinessError;
      console.error(`[VoiceService] TTS初始化失败: ${error.code} - ${error.message}`);
      return false;
    }
  }

  /**
   * 开始语音识别
   */
  async startListening(
    onResult: (text: string, isFinal: boolean) => void,
    onError: (error: string) => void
  ): Promise<void> {
    if (!this.asrEngine) {
      const success = await this.initASR();
      if (!success) {
        onError('语音识别引擎初始化失败');
        return;
      }
    }

    if (this.isListening) {
      console.warn('[VoiceService] 已经在监听中');
      return;
    }

    try {
      // 设置回调
      this.asrEngine!.setListener({
        onStart: (sessionId: string) => {
          console.info(`[VoiceService] 开始识别, sessionId: ${sessionId}`);
          this.isListening = true;
        },
        onEvent: (sessionId: string, eventCode: number) => {
          console.info(`[VoiceService] 事件: ${eventCode}`);
        },
        onResult: (sessionId: string, result: speechRecognizer.SpeechRecognitionResult) => {
          const text = result.result;
          const isFinal = result.isFinal;
          console.info(`[VoiceService] 识别结果: ${text}, isFinal: ${isFinal}`);
          onResult(text, isFinal);
        },
        onComplete: (sessionId: string) => {
          console.info(`[VoiceService] 识别完成`);
          this.isListening = false;
        },
        onError: (sessionId: string, errorCode: number, errorMessage: string) => {
          console.error(`[VoiceService] 识别错误: ${errorCode} - ${errorMessage}`);
          this.isListening = false;
          onError(errorMessage);
        }
      });

      // 开始识别
      const recognitionParams: speechRecognizer.StartParams = {
        sessionId: `session_${Date.now()}`,
        audioInfo: {
          audioType: 'pcm',
          sampleRate: 16000,
          soundChannel: 1,
          sampleBit: 16
        },
        extraParams: {
          vadBegin: 2000,  // 静音检测开始时间
          vadEnd: 3000,    // 静音检测结束时间
          maxAudioDuration: 60000  // 最大录音时长
        }
      };

      await this.asrEngine!.startListening(recognitionParams);
    } catch (err) {
      const error = err as BusinessError;
      console.error(`[VoiceService] 开始识别失败: ${error.code} - ${error.message}`);
      onError(error.message);
    }
  }

  /**
   * 停止语音识别
   */
  async stopListening(): Promise<void> {
    if (this.asrEngine && this.isListening) {
      try {
        await this.asrEngine.finish(`session_stop_${Date.now()}`);
        this.isListening = false;
        console.info('[VoiceService] 停止识别');
      } catch (err) {
        console.error('[VoiceService] 停止识别失败:', JSON.stringify(err));
      }
    }
  }

  /**
   * 语音合成(文字转语音)
   */
  async speak(text: string, onComplete?: () => void): Promise<void> {
    if (!this.ttsEngine) {
      const success = await this.initTTS();
      if (!success) {
        console.error('[VoiceService] TTS引擎不可用');
        onComplete?.();
        return;
      }
    }

    try {
      // 设置回调
      this.ttsEngine!.setListener({
        onStart: (requestId: string) => {
          console.info(`[VoiceService] 开始播放, requestId: ${requestId}`);
        },
        onProgress: (requestId: string, progress: number) => {
          // 播放进度
        },
        onFinish: (requestId: string) => {
          console.info(`[VoiceService] 播放完成`);
          onComplete?.();
        },
        onError: (requestId: string, errorCode: number, errorMessage: string) => {
          console.error(`[VoiceService] 播放错误: ${errorCode} - ${errorMessage}`);
          onComplete?.();
        }
      });

      // 合成参数
      const speakParams: textToSpeech.SpeakParams = {
        requestId: `speak_${Date.now()}`,
        extraParams: {
          speed: 1.0,
          volume: 1.0,
          pitch: 1.0
        }
      };

      await this.ttsEngine!.speak(text, speakParams);
    } catch (err) {
      const error = err as BusinessError;
      console.error(`[VoiceService] 语音合成失败: ${error.code} - ${error.message}`);
      onComplete?.();
    }
  }

  /**
   * 停止语音播放
   */
  async stopSpeaking(): Promise<void> {
    if (this.ttsEngine) {
      try {
        await this.ttsEngine.stop();
        console.info('[VoiceService] 停止播放');
      } catch (err) {
        console.error('[VoiceService] 停止播放失败:', JSON.stringify(err));
      }
    }
  }

  /**
   * 释放资源
   */
  async release(): Promise<void> {
    try {
      if (this.asrEngine) {
        await this.asrEngine.shutdown();
        this.asrEngine = null;
      }
      if (this.ttsEngine) {
        await this.ttsEngine.shutdown();
        this.ttsEngine = null;
      }
      console.info('[VoiceService] 资源释放完成');
    } catch (err) {
      console.error('[VoiceService] 释放资源失败:', JSON.stringify(err));
    }
  }

  /**
   * 获取监听状态
   */
  getListeningState(): boolean {
    return this.isListening;
  }
}

5. 任务执行器 (engine/ActionExecutor.ets)

// entry/src/main/ets/engine/ActionExecutor.ets

import { bundleManager, common, Want } from '@kit.AbilityKit';
import { IntentType } from '../model/MessageModel';
import { BusinessError } from '@kit.BasicServicesKit';

/**
 * V哥的任务执行器
 * 根据意图执行具体操作
 */

interface ActionResult {
  success: boolean;
  message: string;
  data?: object;
}

export class ActionExecutor {
  private static instance: ActionExecutor;
  private context: common.UIAbilityContext | null = null;

  private constructor() {}

  static getInstance(): ActionExecutor {
    if (!ActionExecutor.instance) {
      ActionExecutor.instance = new ActionExecutor();
    }
    return ActionExecutor.instance;
  }

  /**
   * 设置上下文
   */
  setContext(context: common.UIAbilityContext): void {
    this.context = context;
  }

  /**
   * 执行动作
   */
  async execute(intent: IntentType, params: Record<string, string>): Promise<ActionResult> {
    console.info(`[ActionExecutor] 执行意图: ${intent}, 参数: ${JSON.stringify(params)}`);

    switch (intent) {
      case IntentType.OPEN_APP:
        return this.openApp(params);

      case IntentType.SET_ALARM:
        return this.setAlarm(params);

      case IntentType.SET_REMINDER:
        return this.setReminder(params);

      case IntentType.QUERY_WEATHER:
        return this.queryWeather(params);

      case IntentType.QUERY_TIME:
        return this.queryTime();

      case IntentType.CONTROL_DEVICE:
        return this.controlDevice(params);

      default:
        return {
          success: false,
          message: '暂不支持该操作'
        };
    }
  }

  /**
   * 打开应用
   */
  private async openApp(params: Record<string, string>): Promise<ActionResult> {
    const bundleName = params.bundleName;
    const appName = params.appName;

    if (!bundleName) {
      return {
        success: false,
        message: `抱歉,我不知道怎么打开"${appName || '这个应用'}"`
      };
    }

    try {
      const want: Want = {
        bundleName: bundleName,
        action: 'action.system.home',
        entities: ['entity.system.home']
      };

      await this.context?.startAbility(want);

      return {
        success: true,
        message: `已为你打开${appName}`
      };
    } catch (err) {
      const error = err as BusinessError;
      console.error(`[ActionExecutor] 打开应用失败: ${error.code} - ${error.message}`);

      return {
        success: false,
        message: `打开${appName}失败,可能是应用未安装`
      };
    }
  }

  /**
   * 设置闹钟
   */
  private async setAlarm(params: Record<string, string>): Promise<ActionResult> {
    const hour = parseInt(params.hour || '8');
    const minute = parseInt(params.minute || '0');

    try {
      // 调用系统闹钟
      const want: Want = {
        action: 'ohos.want.action.setAlarm',
        parameters: {
          'ringtone': 'default',
          'hour': hour,
          'minute': minute
        }
      };

      await this.context?.startAbility(want);

      const timeStr = `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
      return {
        success: true,
        message: `好的,已为你设置${timeStr}的闹钟`
      };
    } catch (err) {
      console.error('[ActionExecutor] 设置闹钟失败:', JSON.stringify(err));

      return {
        success: false,
        message: '设置闹钟失败,请手动设置'
      };
    }
  }

  /**
   * 设置提醒
   */
  private async setReminder(params: Record<string, string>): Promise<ActionResult> {
    const content = params.content || '未命名提醒';
    const delayMinutes = parseInt(params.delayMinutes || '10');

    // 这里可以接入前面的日程提醒模块
    return {
      success: true,
      message: `收到!${delayMinutes}分钟后提醒你:${content}`
    };
  }

  /**
   * 查询天气
   */
  private async queryWeather(params: Record<string, string>): Promise<ActionResult> {
    const city = params.city || '北京';

    // 实际项目中对接天气API
    // 这里返回模拟数据
    const mockWeather = {
      city: city,
      temperature: Math.floor(Math.random() * 20) + 10,
      weather: ['晴', '多云', '阴', '小雨'][Math.floor(Math.random() * 4)],
      humidity: Math.floor(Math.random() * 40) + 40
    };

    return {
      success: true,
      message: `${city}今天${mockWeather.weather},气温${mockWeather.temperature}°C,湿度${mockWeather.humidity}%`,
      data: mockWeather
    };
  }

  /**
   * 查询时间
   */
  private queryTime(): ActionResult {
    const now = new Date();
    const weekDays = ['日', '一', '二', '三', '四', '五', '六'];

    const dateStr = `${now.getFullYear()}年${now.getMonth() + 1}月${now.getDate()}日`;
    const weekStr = `星期${weekDays[now.getDay()]}`;
    const timeStr = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`;

    return {
      success: true,
      message: `现在是${dateStr} ${weekStr} ${timeStr}`
    };
  }

  /**
   * 控制设备
   */
  private async controlDevice(params: Record<string, string>): Promise<ActionResult> {
    const device = params.device || '设备';
    const action = params.action === 'on' ? '打开' : '关闭';

    // 实际项目中对接智能家居API
    return {
      success: true,
      message: `好的,已${action}${device}`
    };
  }
}

6. AI智能体核心 (engine/AIAgent.ets)

// entry/src/main/ets/engine/AIAgent.ets

import { Message, MessageRole, MessageType, ConversationContext, IntentType } from '../model/MessageModel';
import { IntentEngine } from './IntentEngine';
import { ActionExecutor } from './ActionExecutor';
import { LLMService } from '../service/LLMService';
import { VoiceService } from '../service/VoiceService';

/**
 * V哥的AI智能体核心
 * 整合所有能力,实现智能对话
 */

export class AIAgent {
  private static instance: AIAgent;
  private context: ConversationContext;
  private intentEngine: IntentEngine;
  private actionExecutor: ActionExecutor;
  private llmService: LLMService;
  private voiceService: VoiceService;

  // 回调函数
  private onMessageCallback?: (message: Message) => void;
  private onStateChangeCallback?: (state: AgentState) => void;

  private constructor() {
    this.context = new ConversationContext();
    this.intentEngine = IntentEngine.getInstance();
    this.actionExecutor = ActionExecutor.getInstance();
    this.llmService = LLMService.getInstance();
    this.voiceService = VoiceService.getInstance();
  }

  static getInstance(): AIAgent {
    if (!AIAgent.instance) {
      AIAgent.instance = new AIAgent();
    }
    return AIAgent.instance;
  }

  /**
   * 设置消息回调
   */
  setOnMessage(callback: (message: Message) => void): void {
    this.onMessageCallback = callback;
  }

  /**
   * 设置状态回调
   */
  setOnStateChange(callback: (state: AgentState) => void): void {
    this.onStateChangeCallback = callback;
  }

  /**
   * 处理用户输入(核心方法)
   */
  async processInput(userInput: string): Promise<void> {
    if (!userInput.trim()) return;

    console.info(`[AIAgent] 处理用户输入: ${userInput}`);

    // 1. 创建用户消息
    const userMessage = new Message({
      role: MessageRole.USER,
      type: MessageType.TEXT,
      content: userInput
    });
    this.context.addMessage(userMessage);
    this.onMessageCallback?.(userMessage);

    // 2. 意图识别
    this.onStateChangeCallback?.(AgentState.THINKING);
    const { intent, params, confidence } = this.intentEngine.recognize(userInput);

    console.info(`[AIAgent] 意图识别: ${intent}, 置信度: ${confidence}`);

    // 3. 根据意图决定处理方式
    let response: string;

    if (intent !== IntentType.CHAT && confidence >= 0.7) {
      // 高置信度的功能意图,执行动作
      userMessage.intent = intent;
      userMessage.intentParams = params;

      const result = await this.actionExecutor.execute(intent, params);
      response = result.message;

      // 如果是需要补充信息的场景,继续调用LLM
      if (!result.success && intent !== IntentType.UNKNOWN) {
        response = await this.llmService.chat(
          `用户说"${userInput}",我尝试${this.getIntentDescription(intent)}但失败了。请给出友好的回复和建议。`,
          this.context
        );
      }
    } else {
      // 闲聊或低置信度,调用大模型
      response = await this.llmService.chat(userInput, this.context);
    }

    // 4. 创建助手回复
    const assistantMessage = new Message({
      role: MessageRole.ASSISTANT,
      type: MessageType.TEXT,
      content: response
    });
    this.context.addMessage(assistantMessage);
    this.onMessageCallback?.(assistantMessage);

    this.onStateChangeCallback?.(AgentState.IDLE);

    // 5. 语音播报回复
    await this.voiceService.speak(response);
  }

  /**
   * 开始语音输入
   */
  async startVoiceInput(): Promise<void> {
    this.onStateChangeCallback?.(AgentState.LISTENING);

    await this.voiceService.startListening(
      (text: string, isFinal: boolean) => {
        if (isFinal && text.trim()) {
          this.processInput(text);
        }
      },
      (error: string) => {
        console.error('[AIAgent] 语音识别错误:', error);
        this.onStateChangeCallback?.(AgentState.IDLE);
      }
    );
  }

  /**
   * 停止语音输入
   */
  async stopVoiceInput(): Promise<void> {
    await this.voiceService.stopListening();
    this.onStateChangeCallback?.(AgentState.IDLE);
  }

  /**
   * 获取对话历史
   */
  getHistory(): Message[] {
    return this.context.getHistory();
  }

  /**
   * 清空对话
   */
  clearHistory(): void {
    this.context.clear();
  }

  /**
   * 获取意图描述
   */
  private getIntentDescription(intent: IntentType): string {
    const descriptions: Record<IntentType, string> = {
      [IntentType.OPEN_APP]: '打开应用',
      [IntentType.SET_ALARM]: '设置闹钟',
      [IntentType.SET_REMINDER]: '设置提醒',
      [IntentType.QUERY_WEATHER]: '查询天气',
      [IntentType.QUERY_TIME]: '查询时间',
      [IntentType.CONTROL_DEVICE]: '控制设备',
      [IntentType.CHAT]: '闲聊',
      [IntentType.UNKNOWN]: '理解意图'
    };
    return descriptions[intent] || '执行操作';
  }
}

/**
 * 智能体状态
 */
export enum AgentState {
  IDLE = 'idle',           // 空闲
  LISTENING = 'listening', // 监听中
  THINKING = 'thinking',   // 思考中
  SPEAKING = 'speaking'    // 说话中
}

7. 主界面 (pages/Index.ets)

// entry/src/main/ets/pages/Index.ets

import { Message, MessageRole, MessageType } from '../model/MessageModel';
import { AIAgent, AgentState } from '../engine/AIAgent';
import { ActionExecutor } from '../engine/ActionExecutor';
import { VoiceService } from '../service/VoiceService';
import { common } from '@kit.AbilityKit';
import { promptAction } from '@kit.ArkUI';

@Entry
@Component
struct Index {
  @State messageList: Message[] = [];
  @State inputText: string = '';
  @State agentState: AgentState = AgentState.IDLE;
  @State isVoiceMode: boolean = false;

  private agent: AIAgent = AIAgent.getInstance();
  private voiceService: VoiceService = VoiceService.getInstance();
  private scroller: Scroller = new Scroller();
  private context = getContext(this) as common.UIAbilityContext;

  async aboutToAppear(): Promise<void> {
    // 初始化
    ActionExecutor.getInstance().setContext(this.context);

    // 请求权限
    await this.voiceService.requestPermission(this.context);

    // 设置回调
    this.agent.setOnMessage((message: Message) => {
      this.messageList = [...this.messageList, message];
      // 滚动到底部
      setTimeout(() => {
        this.scroller.scrollEdge(Edge.Bottom);
      }, 100);
    });

    this.agent.setOnStateChange((state: AgentState) => {
      this.agentState = state;
    });

    // 添加欢迎消息
    const welcomeMessage = new Message({
      role: MessageRole.ASSISTANT,
      type: MessageType.TEXT,
      content: '你好!我是小V助手 🤖\n\n我可以帮你:\n• 回答各种问题\n• 打开应用\n• 设置闹钟和提醒\n• 查询天气和时间\n• 控制智能设备\n\n试着对我说点什么吧!'
    });
    this.messageList.push(welcomeMessage);
  }

  /**
   * 发送消息
   */
  async sendMessage(): Promise<void> {
    if (!this.inputText.trim()) return;

    const text = this.inputText.trim();
    this.inputText = '';

    await this.agent.processInput(text);
  }

  /**
   * 切换语音模式
   */
  async toggleVoiceMode(): Promise<void> {
    if (this.isVoiceMode) {
      // 停止语音输入
      await this.agent.stopVoiceInput();
      this.isVoiceMode = false;
    } else {
      // 开始语音输入
      this.isVoiceMode = true;
      await this.agent.startVoiceInput();
    }
  }

  /**
   * 获取状态文本
   */
  getStateText(): string {
    switch (this.agentState) {
      case AgentState.LISTENING:
        return '正在听...';
      case AgentState.THINKING:
        return '思考中...';
      case AgentState.SPEAKING:
        return '说话中...';
      default:
        return '';
    }
  }

  /**
   * 格式化时间
   */
  formatTime(timestamp: number): string {
    const date = new Date(timestamp);
    const hour = date.getHours().toString().padStart(2, '0');
    const minute = date.getMinutes().toString().padStart(2, '0');
    return `${hour}:${minute}`;
  }

  build() {
    Column() {
      // 顶部标题栏
      Row() {
        Column() {
          Text('小V助手')
            .fontSize(20)
            .fontWeight(FontWeight.Bold)
            .fontColor('#333333')

          if (this.agentState !== AgentState.IDLE) {
            Row() {
              LoadingProgress()
                .width(14)
                .height(14)
                .color('#007DFF')
              Text(this.getStateText())
                .fontSize(12)
                .fontColor('#007DFF')
                .margin({ left: 4 })
            }
            .margin({ top: 2 })
          }
        }
        .alignItems(HorizontalAlign.Start)

        Blank()

        // 清空对话按钮
        Button() {
          Image($r('app.media.ic_clear'))
            .width(20)
            .height(20)
            .fillColor('#666666')
        }
        .width(40)
        .height(40)
        .backgroundColor('#F0F0F0')
        .borderRadius(20)
        .onClick(() => {
          promptAction.showDialog({
            title: '清空对话',
            message: '确定要清空所有对话记录吗?',
            buttons: [
              { text: '取消', color: '#666666' },
              { text: '确定', color: '#007DFF' }
            ]
          }).then((result) => {
            if (result.index === 1) {
              this.messageList = [];
              this.agent.clearHistory();
            }
          });
        })
      }
      .width('100%')
      .height(60)
      .padding({ left: 16, right: 16 })
      .backgroundColor(Color.White)

      // 消息列表
      List({ scroller: this.scroller, space: 16 }) {
        ForEach(this.messageList, (message: Message) => {
          ListItem() {
            this.MessageBubble(message)
          }
        }, (message: Message) => message.id)
      }
      .width('100%')
      .layoutWeight(1)
      .padding({ left: 16, right: 16, top: 12, bottom: 12 })
      .backgroundColor('#F5F5F5')

      // 底部输入区域
      Row() {
        // 语音按钮
        Button() {
          Image(this.isVoiceMode ? $r('app.media.ic_keyboard') : $r('app.media.ic_voice'))
            .width(24)
            .height(24)
            .fillColor(this.isVoiceMode ? '#FF3B30' : '#666666')
        }
        .width(44)
        .height(44)
        .backgroundColor(this.isVoiceMode ? '#FFE5E5' : '#F0F0F0')
        .borderRadius(22)
        .onClick(() => this.toggleVoiceMode())

        if (this.isVoiceMode) {
          // 语音输入状态
          Column() {
            if (this.agentState === AgentState.LISTENING) {
              Row() {
                ForEach([1, 2, 3, 4, 5], (i: number) => {
                  Column()
                    .width(4)
                    .height(12 + Math.random() * 20)
                    .backgroundColor('#007DFF')
                    .borderRadius(2)
                    .margin({ left: 4, right: 4 })
                    .animation({
                      duration: 300,
                      iterations: -1,
                      curve: Curve.EaseInOut
                    })
                })
              }
              .justifyContent(FlexAlign.Center)
            }

            Text(this.agentState === AgentState.LISTENING ? '正在聆听...' : '点击麦克风开始说话')
              .fontSize(14)
              .fontColor('#666666')
              .margin({ top: 8 })
          }
          .layoutWeight(1)
          .height(44)
          .justifyContent(FlexAlign.Center)
        } else {
          // 文字输入框
          TextInput({ placeholder: '输入消息...', text: this.inputText })
            .layoutWeight(1)
            .height(44)
            .backgroundColor('#F5F5F5')
            .borderRadius(22)
            .padding({ left: 16, right: 16 })
            .margin({ left: 8, right: 8 })
            .onChange((value) => {
              this.inputText = value;
            })
            .onSubmit(() => {
              this.sendMessage();
            })

          // 发送按钮
          Button() {
            Image($r('app.media.ic_send'))
              .width(24)
              .height(24)
              .fillColor(Color.White)
          }
          .width(44)
          .height(44)
          .backgroundColor(this.inputText.trim() ? '#007DFF' : '#CCCCCC')
          .borderRadius(22)
          .enabled(this.inputText.trim().length > 0)
          .onClick(() => this.sendMessage())
        }
      }
      .width('100%')
      .height(70)
      .padding({ left: 12, right: 12, top: 8, bottom: 16 })
      .backgroundColor(Color.White)
    }
    .width('100%')
    .height('100%')
  }

  /**
   * 消息气泡组件
   */
  @Builder
  MessageBubble(message: Message) {
    Column() {
      if (message.role === MessageRole.USER) {
        // 用户消息(右侧)
        Row() {
          Blank()

          Column() {
            Text(message.content)
              .fontSize(15)
              .fontColor(Color.White)
              .lineHeight(22)
          }
          .padding(12)
          .backgroundColor('#007DFF')
          .borderRadius({
            topLeft: 16,
            topRight: 4,
            bottomLeft: 16,
            bottomRight: 16
          })
          .constraintSize({ maxWidth: '75%' })

          // 用户头像
          Image($r('app.media.ic_user'))
            .width(36)
            .height(36)
            .borderRadius(18)
            .margin({ left: 8 })
        }
        .width('100%')
        .justifyContent(FlexAlign.End)
      } else {
        // AI消息(左侧)
        Row() {
          // AI头像
          Stack() {
            Circle()
              .width(36)
              .height(36)
              .fill('#E6F2FF')

            Image($r('app.media.ic_robot'))
              .width(24)
              .height(24)
          }
          .margin({ right: 8 })

          Column() {
            Text(message.content)
              .fontSize(15)
              .fontColor('#333333')
              .lineHeight(22)

            // 显示时间
            Text(this.formatTime(message.timestamp))
              .fontSize(11)
              .fontColor('#999999')
              .margin({ top: 4 })
          }
          .padding(12)
          .backgroundColor(Color.White)
          .borderRadius({
            topLeft: 4,
            topRight: 16,
            bottomLeft: 16,
            bottomRight: 16
          })
          .constraintSize({ maxWidth: '75%' })
          .alignItems(HorizontalAlign.Start)
          .shadow({
            radius: 4,
            color: 'rgba(0,0,0,0.05)',
            offsetX: 0,
            offsetY: 2
          })

          Blank()
        }
        .width('100%')
        .justifyContent(FlexAlign.Start)
      }
    }
  }
}

8. 快捷指令面板 (components/QuickCommands.ets)

// entry/src/main/ets/components/QuickCommands.ets

/**
 * V哥设计的快捷指令面板
 * 方便用户快速触发常用功能
 */

interface QuickCommand {
  icon: Resource;
  label: string;
  command: string;
  color: string;
}

@Component
export struct QuickCommands {
  onCommand: (command: string) => void = () => {};

  private commands: QuickCommand[] = [
    { icon: $r('app.media.ic_weather'), label: '查天气', command: '今天天气怎么样', color: '#FFB800' },
    { icon: $r('app.media.ic_time'), label: '查时间', command: '现在几点了', color: '#007DFF' },
    { icon: $r('app.media.ic_alarm'), label: '设闹钟', command: '明天早上7点叫我起床', color: '#34C759' },
    { icon: $r('app.media.ic_remind'), label: '提醒我', command: '10分钟后提醒我喝水', color: '#FF9500' },
    { icon: $r('app.media.ic_app'), label: '打开相机', command: '打开相机', color: '#AF52DE' },
    { icon: $r('app.media.ic_home'), label: '开灯', command: '打开客厅的灯', color: '#FF3B30' }
  ];

  build() {
    Column() {
      Text('快捷指令')
        .fontSize(14)
        .fontColor('#999999')
        .margin({ bottom: 12 })

      Flex({ wrap: FlexWrap.Wrap, justifyContent: FlexAlign.SpaceBetween }) {
        ForEach(this.commands, (cmd: QuickCommand) => {
          Column() {
            Stack() {
              Circle()
                .width(44)
                .height(44)
                .fill(cmd.color)
                .opacity(0.15)

              Image(cmd.icon)
                .width(24)
                .height(24)
                .fillColor(cmd.color)
            }

            Text(cmd.label)
              .fontSize(12)
              .fontColor('#666666')
              .margin({ top: 6 })
          }
          .width('30%')
          .margin({ bottom: 16 })
          .onClick(() => {
            this.onCommand(cmd.command);
          })
        })
      }
    }
    .width('100%')
    .padding(16)
    .backgroundColor(Color.White)
    .borderRadius(12)
  }
}

五、资源文件准备

需要的图标资源

entry/src/main/resources/base/media/ 添加以下图标:

文件名用途建议尺寸
ic_robot.svgAI头像48x48
ic_user.svg用户头像48x48
ic_send.svg发送按钮24x24
ic_voice.svg语音按钮24x24
ic_keyboard.svg键盘按钮24x24
ic_clear.svg清空按钮24x24
ic_weather.svg天气图标24x24
ic_time.svg时间图标24x24
ic_alarm.svg闹钟图标24x24
ic_remind.svg提醒图标24x24
ic_app.svg应用图标24x24
ic_home.svg智能家居图标24x24

示例SVG

ic_robot.svg:

<svg viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
  <circle cx="24" cy="24" r="20" fill="#007DFF"/>
  <circle cx="17" cy="20" r="3" fill="white"/>
  <circle cx="31" cy="20" r="3" fill="white"/>
  <path d="M16 30 Q24 36 32 30" stroke="white" stroke-width="2" fill="none"/>
  <rect x="22" y="4" width="4" height="6" rx="2" fill="#007DFF"/>
  <circle cx="24" cy="4" r="3" fill="#007DFF"/>
</svg>

ic_voice.svg:

<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
  <path d="M12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3z"/>
  <path d="M17 11c0 2.76-2.24 5-5 5s-5-2.24-5-5H5c0 3.53 2.61 6.43 6 6.92V21h2v-3.08c3.39-.49 6-3.39 6-6.92h-2z"/>
</svg>

六、V哥总结:关键技术点

1. 意图识别的设计思路

用户输入 → 规则匹配(快速) → 高置信度直接执行
                ↓
         低置信度 → 调用LLM兜底

2. 对话管理的核心

// 多轮对话的关键:上下文管理
class ConversationContext {
  messages: Message[] = [];
  maxHistory: number = 10;  // 控制历史长度,避免Token浪费
}

3. 语音交互的最佳实践

  • 先请求权限,再初始化引擎
  • 语音识别和语音合成用完要释放
  • 做好错误处理和降级方案

4. 性能优化建议

  • 意图识别用本地规则,快速响应
  • LLM调用做好缓存和限流
  • 消息列表使用LazyForEach优化

七、V哥唠两句

兄弟们,这套代码是V哥实战中总结出来的,完整实现了一个能用的AI智能体。当然,实际项目中你还需要:

  1. 接入真实的LLM API(替换掉示例配置)
  2. 完善意图规则库(根据你的业务场景)
  3. 接入真实的智能家居API
  4. 做好异常处理和用户引导

AI智能体的核心不是技术多牛逼,而是用户体验做得好!


关注V哥不迷路!前行路上不犯怵!

起因:连续讲了 30 多分钟故事,她还是不睡

每天晚上 9 点半是我家的固定节目:女儿洗完澡,躺在床上,把她最爱的几本绘本摆成一排。

"爸爸,今天讲这本小兔子,还有恐龙的,还有..."

通常的流程是

  • 9:30 开始讲第一本绘本
  • 9:45 "爸爸再讲一个"
  • 10:00 "这个讲过了,编一个新的"
  • 10:15 我开始口干舌燥,她开始挑刺:"爸爸你昨天说小熊是红色的"
  • 10:30 她终于睡着,我瘫在床边刷手机缓一会儿

有天晚上特别崩溃:讲完三本绘本,她说"爸爸你编一个恐龙和兔子一起玩的故事"。

我临时编了个"霸王龙帮小兔子找萝卜",讲到一半自己都接不下去了,因为前面埋的坑忘了怎么圆。

她睁着大眼睛看着我:"然后呢?萝卜找到了吗?"

那一刻看着她期待的眼神,突然有点心酸。

不是不想讲,是真的每天都在掏空脑子,还得记住前面自己说过什么。

更难受的是,有时候加班晚了,或者状态不好,讲着讲着就敷衍了,她能听出来。会小声说:"爸爸今天讲得不好玩。"

我当时就想:能不能有个东西,让我即使累到说不出话,也能给她讲一个像样的故事?


程序员的痛点,可能也是你的痛点

说实话,在我做这个东西之前,试过市面上所有能找到的方案:

  • 故事 App: 凯叔、口袋故事都买了会员,但听多了不光无趣,也没有个性化
  • GPT 生成: 文本确实能定制,但 TTS 合成音就像客服机器人,毫无感情
  • 录音: 自己录了 20 多个故事,但每次要翻半天找文件,而且孩子总想听"新的"

这些方案单独看都没问题,但放到每天晚上十点半这个场景里,就全都不太行。

最崩溃的是某天晚上:

  • 22:30 讲了三只小猪
  • 23:00 她说"再讲一个有兔子的"
  • 23:20 编到词穷,开始重复情节
  • 23:45 她睁着大眼睛说"爸爸你刚才讲过了"

我坐在床边看着天花板,想着明天还有早会,突然冒出个念头:能不能让 AI 用我的声音讲?

顺便说下我是怎么折腾这个东西的(技术相关,可跳)

1. 故事生成不是调 API 那么简单

  • 一开始直接用 GPT 生成,结果经常前后打架,只好自己加了一层检查,避免讲着讲着把前面的设定忘了。(避免重复/逻辑 bug )
  • 分龄模板: 2-3 岁重复句式多,4-5 岁加入简单因果,6+开始有小反转
  • 安全过滤: 硬编码了很多禁用词库(包括"死亡""分离"等敏感词)

2. 音色克隆的坑

  • 最开始用开源 TTS ,效果像变声器
  • 后来接了某云的语音定制 API ,需要录多句话做训练
  • 真正的难点是韵律: 同样的文本,讲给 3 岁和 6 岁要用不同的停顿节奏

3. 成本控制

  • 大模型生成一个故事约 0.2 元(目前提示词就几千 token )
  • 音频克隆+合成约 0.4 元
  • 单张图片 0.2-0.4 元
  • 算上服务器和存储,也就是说,这玩意儿要是真被孩子天天听,其实还挺烧钱的。

对用户来说只要三步:

  1. 使用官方音色或者录一句话( 15 秒左右)
  2. 填孩子的基本信息(年龄、爱好、最近关注的事)
  3. 自己可以定制场景、故事
  4. 点生成,1-2 分钟后收到一个 5-8 分钟的音频故事


真实效果:一些意外的反馈

我家的变化

  • 女儿的入睡时间从原来的 40 分钟缩短到 20 分钟
  • 有天她指着我说: "爸爸你今天声音怎么跟手机里不一样?" (我感冒了)
  • 现在有时候出差也不焦虑了,每天睡前会提前生成好第二天的故事

朋友的案例(他们催我做出来的)

  • @老王: 双胞胎爸爸,每天要讲两遍不同的故事,现在各生成一个,省了一半时间
  • @小林: 孩子有语言发育迟缓,医生建议多输入,他用这个每天给孩子听 3 个故事

最触动我的是有一位朋友的反馈,她说:"技术能做的不只是效率,还有情感的延续。"


目前的纠结:三个灵魂拷问

1. 这需求到底有多普遍?

我的假设是:

  • ✅ 认同"父母声音对孩子重要"
  • ✅ 工作忙/经常出差/没空编故事
  • ❓ 愿意为此付费(而不是凑合用免费 App )

V2EX 的各位宝爸宝妈,你们会为这种服务付费吗?你们觉得合理价格是多少?

2. 音色克隆是噱头还是刚需?

有朋友直言:"孩子听谁讲不是一样?"

但我观察女儿的反应,她听到"爸爸的声音"时,真的会下意识抱紧小枕头,这和听凯叔讲故事的状态完全不同。

可能儿童心理学上有答案?有相关背景的朋友求指点。

3. 定位是"解放家长"还是"陪伴工具"?

  • 如果定位成"让家长省时间",很容易被批"用技术逃避责任"
  • 但如果定位成"让陪伴更高质量",又显得太虚

我现在的想法是: 这不是替代父母讲故事,而是在父母不在场/不方便时,提供一种接近真人的补充方案

就像视频通话不能替代见面,但总比完全失联好。


想听听大家的真实想法

如果你是家长:

  • 每天哄睡要花多长时间?
  • 试过哪些方案?痛点在哪?
  • 如果有这个工具,最看重什么(声音相似度/故事质量/价格)?

如果你做过类似产品:

  • 定价策略怎么定的?(订阅制 vs 按次付费)
  • 怎么平衡"商业化"和"不制造焦虑"?
  • 推广渠道主要靠什么?


最后

这个东西现在还很粗糙,甚至都不确定该不该做成产品。

但每次看到女儿听着"爸爸"讲的新故事安静入睡,会觉得这件事可能有点意义。

不是为了让父母逃避陪伴,而是让那些想陪但确实分身乏术的爸妈,多一种选择。

如果你有想法,无论是吐槽还是建议,都欢迎留言。

先谢过各位。


留言区如果超过 50 楼,随机抽取 5 位送年度会员


P.S. 如果有宝爸宝妈想试用,可以留言或私信。目前还在内测阶段,大家可以多提意见。

附上小程序码(微信搜:妈咪故事屋):
地址: https://imgur.com/hMjpDCr (图片无法显示,尴尬)


如图称号,在随便哪个地方发个帖(不是回复)
里面包含一个单行的链接就行
比如


这一行就是可以呼出 Onebox 的


📌 转载信息
原作者:
wattstudio666
转载时间:
2026/1/11 08:32:44