轻规划鸿蒙开发实战9:对接 Agent Framework Kit,用小艺智能体实现愿景项目体检与自动可行性打分


背景介绍

我们在制定人生规划时,最容易犯的毛病是**“假、大、空、全”**。例如豪言壮语写下“一个月成为鸿蒙专家并上架 10 款应用”,或者“每天运动 3 小时”。这种脱离身体负荷与时间客观规律的虚胖计划,非但不能落地,反而会在流产时带给用户强烈的挫败感。

在传统的软件中,用户的规划信息往往只是静态落库。为了让“轻规划”(AeroPlan)拥有更智能的规划指导能力,我们需要引入系统层面的 AI 赋能。如果我们的计划在制定之初,就能得到客观、理性的评估和诊断,那么用户在后续的执行中就能规避大部分由于规划不合理导致的放弃行为。

为此,“轻规划”(AeroPlan)集成了 HarmonyOS 原生 AI 智能体开放能力——Agent Framework Kit(智能体框架服务)

轻规划鸿蒙开发实战9:对接 Agent Framework Kit,用小艺智能体实现愿景项目体检与自动可行性打分-1.png

我们通过将底层的“里程碑拆解模型”与华为系统级助理“小艺智能体”打通,用户在制定好项目清单后,只需点击“小艺帮我体检”,应用就会自动将项目元数据作为上下文打包塞给小艺。小艺智能体会根据预设的科学诊断 Prompt,对该项目的可行性进行分析、诊断其逻辑稳定性风险、做出合理性评估打分(0-100分),甚至还可以基于用户的输入,反向帮助用户重构出更科学的甘特图排期参考。

今天,我们将实战解构小艺智能体的意图定义及槽位填充开发细节。


1. 架构纵览:小艺智能体数据交互与槽位提取管线

当用户向小艺发起项目体检时,系统需要完成意图的协议转换,通过端云协同的推理通道,最终将结构化诊断包返回并落盘。职责划分如下:

轻规划鸿蒙开发实战9:对接 Agent Framework Kit,用小艺智能体实现愿景项目体检与自动可行性打分.png

1.1 端云协同体系架构

在 HarmonyOS 中,智能体框架服务并不是一个孤立的端侧大模型,而是一套高效的端云双向协同引擎:

  • 应用客户端 (Client App):基于 Agent Framework Kit API 唤起会话,管理 AgentSession 生命周期,并负责本地参数的安全拦截与格式化。
  • 系统智能体引擎 (System Agent Engine):运行于独立的系统级 Service 中,通过 HarmonyOS 的高效跨进程通信 (IPC) 技术与应用建立低延迟的信道绑定,从而降低应用本身的内存占用。
  • 云端意图匹配与大模型层 (Cloud NLU & LLM):小艺智能体的云端引擎负责接收自然语言输入,运行实体识别 (NER) 算法,抽取我们在配置文件中预设的意图槽位 (Slot Filling),并根据特定领域的 System Prompt(系统预置提示词)进行大语言模型的推理生成。

这种架构设计的优势在于,客户端无需集成数十 GB 的大模型权重,只需关注简单的意图契约及槽位定义即可获取业界顶尖的泛化推理能力。


2. 小艺智能体意图配置文件与槽位(Slots)声明

为了能让系统助理小艺精准地理解我们的应用功能,我们首先需要在项目的 resources/base/profile 目录下,配置小艺意图配置文件 intent_schema.json。这个配置文件在应用打包和分发阶段,会被华为应用市场与系统意图管理模块解析并注册。它声明了我们需要小艺抽取的槽位信息(例如项目名称 projectName、预期天数 expectedDays 等元数据):

{
  "intents": [
    {
      "name": "com.aeroplan.intent.DIAGNOSE_PROJECT",
      "slots": [
        {
          "name": "projectName",
          "type": "string",
          "mandatory": true
        },
        {
          "name": "expectedDays",
          "type": "number",
          "mandatory": false
        }
      ]
    }
  ]
}
2.1 槽位参数类型与行为映射表

槽位(Slot)是智能体语义理解的基础单元。合理选择和配置槽位能显著提升小艺识别的准确率。以下是常用的槽位属性对比与行为解析:

槽位标识 (Slot Name) 槽位类型 (Type) 必须性 (Mandatory) NLU 识别倾向与语义特征 缺省回退处理策略
projectName string 规划的核心实体名称,小艺倾向于提取动词短语(例如“学习鸿蒙开发”) 必须前置校验,若为空则禁止发起智能体请求,避免引发无意义对话
expectedDays number 提取口语表达中的周期词汇(如“一个月”识别为 30,“两周”识别为 14 本地安全兜底拦截,默认为系统设定的基础评估周期(30天)
priorityLevel string 提取用户的情感强弱及重要度描述(如“紧急”、“不急”,映射为自定义枚举) 默认 fallback 至标准评估权重

3. Agent Framework Kit 通信:发起体检请求并获取诊断

在客户端应用侧,我们通过 @kit.AgentFrameworkKit 提供的端侧会话能力,构建结构化对话请求,并接收小艺的分析结果。

3.1 发起智能体分析核心代码

以下是“轻规划”中负责与小艺通信的网关类 XiaoyiAgentBridge 的完整实现。代码严格遵守了 TypeScript 语法规范,并针对底层 API 调用、内存生命周期管理及错误处理进行了行级中文注释说明。

import { agentFramework } from '@kit.AgentFrameworkKit'; // 引入 HarmonyOS 智能体框架基础包,处理跨进程 AI 对话
import { BusinessError } from '@kit.BasicServicesKit'; // 引入系统基础错误接口,方便在异常时提取错误码和错误信息

/**
 * 智能体体检诊断结果的结构化定义
 */
export interface DiagnoseResult {
  score: number; // 计划的最终可行性合理打分(范围为 0 到 100)
  suggestions: string[]; // 具体的合理性评估与稳定性改进建议
  recommendedSchedule: string; // 由智能体重新编排的 Markdown 格式的合理甘特图步骤
}

/**
 * 负责与小艺智能体进行底通信与会话管理的桥接类
 */
export class XiaoyiAgentBridge {
  // 维护与系统智能体的会话实例,其生命周期应在长会话交互期间持续存在,并在结束时显式释放以避免端侧内存泄漏
  private agentSession: agentFramework.AgentSession | null = null;

  /**
   * 发起项目合理性评估诊断的请求
   * @param projectName 用户规划的项目名
   * @param expectedDays 计划天数
   * @param onResult 诊断成功时的回调函数,回传结构化的 DiagnoseResult
   */
  public async requestProjectDiagnosis(
    projectName: string,
    expectedDays: number,
    onResult: (res: DiagnoseResult) => void
  ): Promise<void> {
    try {
      // 1. 初始化并拉起小艺智能体端侧会话
      // 系统会基于传入的 agentId,在小艺智能体服务进程中建立一个长连接实例
      this.agentSession = await agentFramework.createAgentSession({
        agentId: "aeroplan_planner_helper_agent" // 该 ID 必须与在华为开发者联盟平台注册的智能体ID一致
      });

      // 2. 本地前置过滤:防止非法的参数输入影响云端 NLU 的意图判定
      const finalExpectedDays = expectedDays > 0 ? expectedDays : 30; // 槽位缺省与有效性本地兜底

      // 3. 构造智能体意图协议请求体 (AgentRequest)
      // 包含意图标识、槽位填充信息以及云端大模型推理的 System Prompt 指示
      const intentRequest: agentFramework.AgentRequest = {
        intentName: "com.aeroplan.intent.DIAGNOSE_PROJECT", // 对应 intent_schema.json 中声明的唯一意图名称
        slots: {
          "projectName": projectName, // 槽位填充:项目名称
          "expectedDays": finalExpectedDays // 槽位填充:预期天数(已包含本地防御机制)
        },
        // 传递额外的科学指导 Prompt 作为系统指示,规范小艺大模型的输出格式与推理方向
        // 确保云端大模型以稳定的结构(包含特定的标记字“【诊断建议】”以及 JSON 结构)进行结果返回
        systemPrompt: "你是一个资深的人生规划理论专家。请针对以下项目进行可行性诊断," +
                      "指出它的执行不合理性以及合理性缺陷。打出 0 至 100 的可行性分数,并以精简的形式给出一套修正后的里程碑甘特图建议。" +
                      "输出格式中必须严格包含以 JSON 表达的 score 参数,例如:{\"score\": 85},并在其后附带【诊断建议】标记块。"
      };

      // 4. 发送异步请求并接收大模型的推理流响应
      // sendRequest 底层依赖 HarmonyOS 系统级 IPC 信道,调用时应捕获网络超时或系统服务崩溃等 BusinessError 异常
      this.agentSession.sendRequest(intentRequest).then((response: agentFramework.AgentResponse) => {
        const replyText = response.replyText; // 获取小艺回传的响应文本内容
        console.info("XiaoyiAgentBridge", "Xiaoyi agent reply raw text received successfully");
        
        // 5. 调用本地词法/正则解析方法,将非结构化的大模型文本转换为结构化对象
        const parsedResult = this.parseAgentReply(replyText);
        onResult(parsedResult); // 将解析后的对象回调给 UI 渲染层
      }).catch((err: BusinessError) => {
        // 处理请求发送期间的失败逻辑,例如网络丢包、云端限流等
        console.error("XiaoyiAgentBridge", `Send request failed: Code: ${err.code}, Message: ${err.message}`);
        this.fallbackToLocalAnalysis(projectName, finalExpectedDays, onResult);
      });

    } catch (err) {
      // 捕获会话初始化失败的异常(通常由于系统智能体进程异常、权限不足或服务未绑定导致)
      const businessErr = err as BusinessError;
      console.error("XiaoyiAgentBridge", `Failed to initialize session: Code: ${businessErr.code}, Message: ${businessErr.message}`);
      this.fallbackToLocalAnalysis(projectName, expectedDays, onResult);
    }
  }

  /**
   * 解析小艺智能体回传的混合文本,利用正则表达式和字符串切片分离出结构化指标与排期
   * @param replyText 原始文本响应
   */
  private parseAgentReply(replyText: string): DiagnoseResult {
    try {
      // 利用正则表达式从文本中提取形如 "score": 85 的可行性分数
      const scoreMatch = replyText.match(/\"score\"\s*:\s*(\d+)/);
      const score = scoreMatch ? parseInt(scoreMatch[1]) : 75; // 若正则匹配失败则默认给出 75 分的中庸保底分

      // 寻找输出中预定义的标志词,截取出大模型的诊断建议与建议排期
      const targetTag = "【诊断建议】";
      const tagIndex = replyText.indexOf(targetTag);
      const suggestionBlock = tagIndex !== -1 ? replyText.substring(tagIndex + targetTag.length) : replyText;

      return {
        score: score,
        suggestions: [suggestionBlock],
        recommendedSchedule: replyText
      };
    } catch (e) {
      // 捕获 JSON 解析或正则执行异常,避免因为大模型生成的不稳定结构导致整个调用栈崩溃
      console.warn("XiaoyiAgentBridge", "Parse agent reply failed, fall back to default parser state");
      return {
        score: 60, // 发生解析异常时的降级分数
        suggestions: ["未能成功解析小艺反馈,计划难度可能较高,请参考手动拆解建议。"],
        recommendedSchedule: replyText
      };
    }
  }

  /**
   * 当网络异常或云端不可达时,本地运行的简单规则引擎兜底分析
   */
  private fallbackToLocalAnalysis(projectName: string, expectedDays: number, onResult: (res: DiagnoseResult) => void): void {
    console.info("XiaoyiAgentBridge", "Entering offline local analysis mode");
    // 基于朴素规则引擎(判定字数与时间比例是否失衡)做出的本地兜底,保证用户界面能有所呈现
    let calculatedScore = 80;
    if (projectName.length > 20 && expectedDays < 7) {
      calculatedScore = 40; // 目标过长且计划周期过短,判定为不合理规划
    }
    
    onResult({
      score: calculatedScore,
      suggestions: ["本地评估提示:系统目前处于离线或高负载状态。根据项目的基本特征进行基础合理性分析,您的项目时间设定可能偏紧凑,请量力而行。"],
      recommendedSchedule: `### 推荐的本地兜底建议甘特图排期\n1. 前期准备与资源对齐 (0-2天)\n2. 核心任务冲刺与攻坚 (3-6天)\n3. 结果验证与成果上线 (7天)`
    });
  }

  /**
   * 显式销毁会话释放底层的 IPC 资源与内存引用
   * 在 UI 组件销毁或退出功能模块时,必须显式调用此方法,防止内存泄漏风险
   */
  public destroyBridge(): void {
    if (this.agentSession) {
      this.agentSession = null;
      console.info("XiaoyiAgentBridge", "AgentSession references cleared successfully");
    }
  }
}

拉起小艺智能体后效果:

轻规划鸿蒙开发实战9:对接 Agent Framework Kit,用小艺智能体实现愿景项目体检与自动可行性打分-2.png

轻规划鸿蒙开发实战9:对接 Agent Framework Kit,用小艺智能体实现愿景项目体检与自动可行性打分-3.png


4. 极客避坑:槽位提取(Slot Filling)失败时的本地兜底

在基于自然语言的端云交互设计中,用户输入的计划名称往往五花八门,例如“我要在明年春天暖和的时候去爬一次珠穆朗玛峰”。在这种高度口语化、包含复杂状语修饰的表达下,小艺在云端进行语义解析时,可能会发生**“ExpectedDays 槽位提取为空”或无法匹配的现象。这就是典型的槽位对齐偏差(Slot Filling Misalignment)**。

4.1 槽位未对齐现象深度解析

当云端语义识别组件提取槽位失败时,若没有处理机制,底层框架将由于槽位契约(Slot Contract)的破裂而触发返回值的默认错误代码。对于前台应用来说,如果直接抛错,会导致界面卡死在“AI 诊断中…”的 loading 状态。这种因大模型返回结构不符或者网络传输异常引发的不稳定问题,通常称为“大模型幻觉与不确定性行为风险”。

4.2 本地自适应槽位拦截清洗器

为了规避上述稳定性风险,我们设计了一套本地预处理拦截清洗器。在将槽位参数发送至小艺智能体框架之前,在本地先通过轻量级正则与规则引擎,对常见的时间词汇进行初步清洗,以提高云端槽位的提取召回率。

export class LocalSlotInterceptor {
  /**
   * 解析用户规划文本中的隐藏周期,用作槽位的本地自适应提取与修正
   * @param text 用户的口语化输入
   */
  public static extractDaysFromText(text: string): number {
    // 匹配如 "10天", "100天", "5天" 的数字特征
    const dayPattern = /(\d+)\s*天/;
    const dayMatch = text.match(dayPattern);
    if (dayMatch) {
      return parseInt(dayMatch[1]);
    }

    // 匹配如 "3个月", "6个月" 等月份特征
    const monthPattern = /(\d+)\s*个?月/;
    const monthMatch = text.match(monthPattern);
    if (monthMatch) {
      return parseInt(monthMatch[1]) * 30; // 粗略折算为 30 天/月
    }

    // 匹配如 "2周", "1周" 等星期特征
    const weekPattern = /(\d+)\s*个?星期|周/;
    const weekMatch = text.match(weekPattern);
    if (weekMatch) {
      return parseInt(weekMatch[1]) * 7;
    }

    return 0; // 若无明显时间信息,返回 0,交由上层逻辑回退到 30天 兜底配置
  }
}

在发起调用时,我们利用清洗器进行数据安全处理:

// 槽位安全性拦截与缺省防御,阻断非法输入带来的参数抖动
const parsedDays = LocalSlotInterceptor.extractDaysFromText(projectName);
const finalExpectedDays = expectedDays > 0 ? expectedDays : (parsedDays > 0 ? parsedDays : 30);

这一层拦截逻辑,确保了即使在极端输入(如“下个礼拜学完鸿蒙”)或网络延迟重试状态下,小艺分析链路也能保证 100% 成功回调,极大提升了智能诊断的用户体验。


5. 总结与下期预告

通过原生 Agent Framework Kit 对接小艺智能体,“轻规划”把冰冷的计划录入演变为有深度专家反馈的科学互动。我们不仅了解了端云协同体系的架构逻辑,也对如何定义结构化槽位意图(intent_schema.json)有了扎实的掌握。至此,我们完成了前 9 篇所有的业务核心和 Kit 接入。

但是,作为一个分布式同账号应用,如果用户在离线状态下编辑了数据,恢复连网时,多设备之间的数据并发合并冲突该如何优雅消解?

下一篇文章,我们将跨入分布式数据库的最深水区:分布式同步深度博弈,UserId 隔离与基于版本时钟的数据冲突消解机制! 敬请期待。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐