IoT-For-Beginners 实战:为 LUIS 智能定时器应用扩展“取消定时器“意图并接入 Serverless 代码
2026/9/16 3:25:06 网站建设 项目流程

IoT-For-Beginners 实战:为 LUIS 智能定时器应用扩展"取消定时器"意图并接入 Serverless 代码

【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners

在 IoT-For-Beginners 课程的"语音与语言理解"(6-consumer / 2-language-understanding)单元中,你已经训练了一个能够理解"设置定时器"(set timer)的语言理解模型,并编写了基于 HTTP 触发器的 Azure Functions 无服务器代码,将自然语言句子翻译成定时器秒数。本篇文章以该单元的课后作业(assignment)为核心,手把手讲解如何为 LUIS 应用新增一个cancel timer(取消定时器)意图:它不需要任何实体,只需若干示例句子;同时指导你在 serverless 代码中检测该意图是否为最高分意图(top intent)、记录日志并返回恰当的响应。学完本篇,你将掌握"在既有语言理解应用中低成本扩展新意图"的完整套路,并能将 cancel timer 与已有的 set timer 逻辑在同一个函数中协调工作。

1. 任务背景:从"设置定时器"到"取消定时器"

在正式动手前,先回顾一下你在本单元前序课程中已经完成的成果(完整流程见 README.md):

  1. 创建 LUIS 创作资源(Authoring Resource):在smart-timer资源组中使用az cognitiveservices account create创建免费层(F0 SKU)的smart-timer-luis-authoring资源,kindLUIS.Authoring。若提示InvalidApiSetId,说明所选区域不支持 LUIS,需要更换区域。
  2. 创建语言理解应用:在 luis.ai 门户中新建名为smart-timer的应用,并设置对应的 Culture(语言区域)。
  3. 定义实体(Entities):添加number预构建实体用于识别数值,以及一个列表类型(List)实体time unit,其归一化值为minute/second,同义词覆盖单复数形式(如minutesseconds)。
  4. 定义意图(Intents):创建set timer意图,并录入多条不同表达方式的示例句子(utterances),混合使用数字单词与阿拉伯数字,让模型学会泛化。
  5. 训练、测试并发布:点击Train训练模型,使用Test面板验证set a timer for 5 minutes and 4 seconds能返回最高分意图set timer,最后发布到Staging槽位。
  6. 编写 Serverless 函数:在 Azure Functions 应用smart-timer-trigger中创建 HTTP 触发器text-to-timer,通过init.py 调用 LUIS 运行时,把set timer意图的实体解析为总秒数,并以 JSON{"seconds": 147}返回。

作业文档 assignment.md 提出的新需求非常贴合真实场景:面包烤好了,希望在定时器结束前就把它从烤箱取出。因此,"取消定时器"和"设置定时器"一样,都是智能厨房助手的核心交互。

2. 回顾核心概念:意图(Intent)与实体(Entity)的分工

要正确设计 cancel timer,需要理解 LUIS 的两大抽象。语言理解模型围绕意图实体构建:

  • 意图(Intent):指这句话"想做什么",例如播放音乐、设置定时器、订餐。每个句子至少应映射到一个意图。
  • 实体(Entity):指意图作用的对象,例如专辑名、定时器时长、餐品种类。

原课程给出了一个直观的对照表:

句子意图实体
"Play the latest album by Taylor Swift"play musicthe latest album by Taylor Swift
"Set a 3 minute timer"set a timer3 minutes
"Cancel my timer"cancel a timerNone
"Order 3 large pineapple pizzas and a caesar salad"order food3 large pineapple pizzas,caesar salad

注意表中第三行:"Cancel my timer" 的实体为 None。这正是本作业的关键设计决策——取消定时器不需要任何时间数值或单位实体,LUIS 只需判断用户意图即可。这也意味着:

  • 无需再定义新的实体,省去了实体标注与同义词维护的成本;
  • 示例句子的质量成为模型准确率的决定性因素,你需要覆盖用户可能的各种表达方式。

3. 在 LUIS 应用中新增 cancel timer 意图

3.1 创建意图并录入示例句子

  1. 登录 LUIS 门户,打开上一课创建的smart-timer应用。

  2. 切换到Intents标签页,点击Create新建意图,命名为cancel timer

  3. 在示例(Examples)区域录入多种表达"取消定时器"的句子。由于本意图不需要实体,LUIS 只会对句子整体学习意图归属。参考示例可包括:

    • cancel my timer
    • cancel the timer
    • stop the timer
    • turn off the timer
    • remove the timer
    • cancel my 3 minute timer(注意:即使句子中出现了数字,也无须为其标注实体,cancel timer 意图本身不依赖实体完成动作)

    与训练 set timer 时"混合数字单词与数值"同理,这里应覆盖助词、时态、冠词等不同写法,让模型学会从大量近义表达中泛化出"取消定时器"这一意图。

  4. 录入完成后,点击顶部菜单的Train按钮训练模型。训练通常只需几秒,训练期间按钮呈灰色,完成后自动恢复可点击。

3.2 测试新意图

点击顶部Test按钮,输入诸如cancel my timerstop the timer等句子并回车。在结果框中检查top intent(最高分意图)是否为cancel timer,其后会跟随该意图的置信概率。点击Inspect可以查看更详细的结果拆解:Top 得分意图及其百分比、检测到的实体列表。

提示:为达到本作业评价标准中的"Exemplary(优秀)"级别,你不仅要"能添加意图",还要"能完成训练并让模型稳定地把取消类句子识别为最高分意图"。如果测试中cancel timer未排第一,应继续补充示例句子并重新训练,直到测试句稳定命中。

3.3 重新发布模型

LUIS 代码调用默认指向Staging槽位(下文 serverless 代码使用get_slot_prediction(app_id, 'Staging', ...)),因此添加新意图并训练后,需要点击顶部Publish按钮、确认选择Staging slot并点击Done重新发布,云端才会包含 cancel timer 意图的预测能力。

发布后可使用 curl 快速验证(各值从MANAGE标签页获取:App ID 在Settings中,Primary Key 与 Endpoint URL 在Azure ResourcesAuthoring Resource中):

curl "<endpoint url>/luis/prediction/v3.0/apps/<app id>/slots/staging/predict" \ --request GET \ --get \ --data "subscription-key=<primary key>" \ --data "verbose=false" \ --data "show-all-intents=true" \ --data-urlencode "query=cancel my timer"

响应 JSON 中prediction.topIntent应为cancel timer,且entities为空对象——这与"取消定时器无需实体"的设计完全吻合。

4. 在 Serverless 代码中处理 cancel timer

4.1 理解现有函数结构

仓库中已经提供了完整可运行的函数代码骨架,位于 code/functions/smart-timer-trigger/text-to-timer,由以下几部分组成:

  • init.py:函数主体,负责读取环境变量、创建 LUIS 客户端、发起预测、解析实体、返回 HTTP 响应;
  • function.json:HTTP 触发器绑定配置,authLevelfunction,支持GET/POST两种方法;
  • local.settings.json:本地运行配置,包含LUIS_KEYLUIS_ENDPOINT_URLLUIS_APP_ID三个占位值;
  • requirements.txt:依赖声明,包含azure-functionsazure-cognitiveservices-language-luis
  • host.json:函数宿主配置(2.0 版本、Extension Bundle、Application Insights 采样等)。

现有__init__.py的核心逻辑是:

prediction_response = client.prediction.get_slot_prediction(app_id, 'Staging', prediction_request) if prediction_response.prediction.top_intent == 'set timer': # 读取 number 与 time unit 实体,累加 total_seconds # 返回 {"seconds": total_seconds}, status_code=200 return func.HttpResponse(status_code=404) # 意图无法识别时的兜底

从这段源码结构可以清晰地看出:当前函数只对set timer一个意图给出成功响应,其余一切意图(包括尚未支持的cancel timer)都会落入 404 分支。因此,接入取消定时器本质上就是在if判定链上增加一个新的意图分支。

4.2 扩展意图判定与响应

作业要求:如果 cancel timer 是 top intent,则记录该意图已被识别,并返回一个适当的响应。参考现有代码风格,可以在set timer分支之后、404 兜底之前追加如下处理:

if prediction_response.prediction.top_intent == 'cancel timer': logging.info('Cancel timer intent recognized') return func.HttpResponse(json.dumps({'cancel': True}), status_code=200)

实现要点:

  1. 日志记录logging.info(...)会输出到函数控制台,便于在本地运行func start或云端 Application Insights 中观测模型识别结果,这与现有代码中logging.info(f'Request - {text}')logging.info(f'Timer required for {total_seconds} seconds')的观测风格保持一致。
  2. 返回适当的响应:这里返回 JSON{"cancel": true}与 HTTP 200。实际项目中,此响应会回到 IoT 设备(Wio Terminal / Raspberry Pi / 虚拟设备),由设备端真正清除当前计时器并(可结合下一课 6-consumer/lessons/3-spoken-feedback)通过语音向用户确认"定时器已取消"。响应体的具体字段可按你的设备端协议自行定义,关键是用一个明确的成功状态码区分于 404
  3. 保持兜底分支:如果 top intent 既不是set timer也不是cancel timer,函数仍应返回func.HttpResponse(status_code=404)(HTTP 404,表示"无法识别请求")。

修改后main函数的意图处理链路为:set timer(计算秒数)→cancel timer(确认取消)→ 其余情况 404。

4.3 本地验证与联调

  1. 确认虚拟环境已激活,执行pip install -r requirements.txt安装依赖(若提示 pip 版本过旧可先pip install --upgrade pip)。
  2. 在 local.settings.json 中填入真实的LUIS_KEYLUIS_ENDPOINT_URLLUIS_APP_ID(值来源同前文 MANAGE 标签页)。
  3. 运行函数应用,终端会输出 HTTP 触发器地址,例如http://localhost:7071/api/text-to-timer
  4. 使用 curl 发起 POST 请求进行验证:
curl --request POST 'http://localhost:7071/api/text-to-timer' \ --header 'Content-Type: application/json' \ --include \ --data '{"text":"cancel my timer"}'

期望看到类似如下的响应:

HTTP/1.1 200 OK ... {"cancel": true}

同时在函数控制台应出现Cancel timer intent recognized的日志输出——这正是作业评价标准中"能够检测到 top intent 并记录它"的落地证据。

若你是使用 Wio Terminal 的 Arduino 开发者,由于库依赖原因,建议将函数应用在本地运行、并通过本机局域网 IP 访问(如http://192.168.1.10:7071/api/text-to-timer),而不是部署到云端;使用 Raspberry Pi 或虚拟设备则可以选择部署到 Azure Functions,并通过az functionapp keys list获取默认函数密钥拼接到 URL 的?code=参数中。

5. 作业评估标准对照

原作业文档给出了明确的评价维度,可作为自查清单(对应英文原版 assignment.md):

评价标准优秀(Exemplary)合格(Adequate)需改进(Needs Improvement)
在 LUIS 应用中添加 cancel timer 意图能够添加意图并训练模型能添加意图但未训练模型无法添加意图也无法训练模型
在 serverless 应用中处理该意图能将意图识别为 top intent 并记录日志能识别为 top intent 但未记录无法识别为 top intent

对照自查:

  • LUIS 侧:意图是否已创建?示例句子是否覆盖多种表达?是否完成训练并通过 Test 面板验证 top intent?
  • Serverless 侧:代码是否检测prediction_response.prediction.top_intent == 'cancel timer'?是否调用logging.info记录识别结果?是否返回了与 404 不同的成功响应?

6. 延伸思考:挑战与下一步

课程还提供了两个可选的拓展方向:

  1. 🚀 Challenge:像"设置定时器"一样,"取消定时器"也存在大量等价表达。可以尝试把更多说法(如 "stop my kitchen timer"、"I don't need the timer anymore")加入示例句子,观察模型在不同说法下的识别鲁棒性,体验数据多样性对语言理解模型效果的影响。
  2. 下一课衔接:cancel timer 的响应最终要驱动设备端动作并给出语音反馈,这正是 6-consumer/lessons/3-spoken-feedback(文本转语音)要解决的问题——届时取消操作可被播报给用户,形成"听懂-执行-反馈"的完整闭环。

总结

通过本作业的实践,你在既有 LUIS + Azure Functions 架构上完成了一次低成本的意图扩展:cancel timer 不引入任何新实体,仅靠高质量示例句子与重新训练即可被模型识别;serverless 端则在现有set timer分支旁新增一个意图分支,用日志记录识别结果并以明确的状态码返回响应。这一模式可以复用到"暂停定时器""延长定时器"等更多意图上,是语言理解应用持续迭代的标准做法。

【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询