在这里插入图片描述

✨道路是曲折的,前途是光明的!

📝 专注C/C++、Linux编程与人工智能领域,分享学习笔记!

🌟 感谢各位小伙伴的长期陪伴与支持,欢迎文末添加好友一起交流!

在这里插入图片描述

前言

本文记录了使用魔搭社区GLM模型API与魔珐星云数字人SDK,从零构建政务服务大厅智能指引系统的完整开发过程,涵盖密钥管理、数字人控制、AI对话交互等核心功能实现。

在这里插入图片描述


一、项目背景

1.1 项目概述

在参加"魔珐星云×魔搭社区×ModelScope"AI黑客松比赛的过程中,我选择了大屏交互与智能讲解赛道,方向为"政务大厅办事指引:精准政策咨询与流程引导"。

传统政务大厅存在以下痛点:

  • 窗口咨询人员工作量大,重复性问题多
  • 办事流程复杂,群众需要反复询问
  • 政策更新频繁,人工解答易出现不一致

基于此,我开发了政务大厅数字人智能指引系统,通过数字人与用户实时对话交互,提供精准的政策咨询和业务办理流程引导。

1.2 技术选型

模块 技术方案 选型理由
前端框架 原生 HTML/CSS/JavaScript 轻量级,便于集成第三方SDK
数字人SDK 魔珐星云具身驱动SDK (JS版本) 官方提供,文档完善
AI模型 魔搭社区 GLM-4.7 流式输出能力强,对话体验好
密钥存储 localStorage 简单易用,适合demo项目

图1:政务大厅数字人系统整体界面展示


二、系统架构设计

2.1 核心功能模块

政务大厅数字人系统
├── 密钥管理模块
│   ├── 数字人密钥配置 (appId, appSecret)
│   ├── 魔搭API Key配置
│   └── 内置测试密钥
├── 数字人控制模块
│   ├── 连接/断开控制
│   ├── 状态管理 (idle, listen, speak, think)
│   └── 语音交互控制
├── AI对话模块
│   ├── 魔搭API调用
│   ├── 流式响应处理
│   └── 政务知识库集成
├── UI展示模块
│   ├── 数字人渲染区域
│   ├── 对话记录显示
│   ├── 控制面板
│   └── 配置弹窗
└── 业务场景模块
    ├── 政策咨询
    ├── 办事指南
    └── 流程引导

在这里插入图片描述

图2:政务大厅数字人系统模块架构图

2.2 交互流程设计

用户输入/语音
    ↓
数字人状态切换到 listen()
    ↓
调用魔搭GLM API获取回复
    ↓
数字人状态切换到 think()
    ↓
流式接收AI回复
    ↓
数字人状态切换到 speak()
    ↓
流式调用speak()方法播放回复
    ↓
完成后切换到 idle() 或 listen()

在这里插入图片描述

图3:用户与数字人交互的完整流程图


三、核心功能实现

3.1 密钥管理模块

密钥管理是系统的基础,需要管理三组密钥:

// 密钥存储配置
const KEYS = {
  AVATAR_APP_ID: 'xy_app_id',
  AVATAR_APP_SECRET: 'xy_app_secret',
  MODELSCOPE_API_KEY: 'ms_api_key'
};

// 保存密钥
function saveKeys(appId, appSecret, apiKey) {
  localStorage.setItem(KEYS.AVATAR_APP_ID, appId);
  localStorage.setItem(KEYS.AVATAR_APP_SECRET, appSecret);
  localStorage.setItem(KEYS.MODELSCOPE_API_KEY, apiKey);
}

// 读取密钥
function loadKeys() {
  return {
    appId: localStorage.getItem(KEYS.AVATAR_APP_ID) || '',
    appSecret: localStorage.getItem(KEYS.AVATAR_APP_SECRET) || '',
    apiKey: localStorage.getItem(KEYS.MODELSCOPE_API_KEY) || ''
  };
}

图4:密钥配置弹窗界面

3.2 数字人SDK集成

魔珐星云SDK的初始化与状态管理:

import XmovAvatar from './xmov-avatar-sdk.js';

let avatarSDK = null;

// 初始化数字人SDK
function initAvatar() {
  const keys = loadKeys();

  avatarSDK = new XmovAvatar({
    containerId: '#avatar-container',
    appId: keys.appId,
    appSecret: keys.appSecret,
    gatewayServer: 'https://nebula-agent.xingyun3d.com/user/v1/ttsa/session',

    // 事件回调
    onMessage: (msg) => console.log('SDK消息:', msg),
    onStateChange: (state) => updateStateDisplay(state),
    onStatusChange: (status) => updateConnectionStatus(status),
    onVoiceStateChange: (voiceState) => handleVoiceState(voiceState)
  });

  avatarSDK.init();
}

// 状态切换
function setAvatarState(state) {
  if (!avatarSDK) return;

  const states = {
    IDLE: () => avatarSDK.idle(),
    LISTEN: () => avatarSDK.listen(),
    THINK: () => avatarSDK.think(),
    SPEAK: (text) => avatarSDK.speak(text)
  };

  states[state]?.();
}

3.3 GLM-4.7流式对话实现

魔搭社区API支持流式输出,这是实现自然对话体验的关键:

// 政务知识库系统提示词
const SYSTEM_PROMPT = `你是一个政务服务大厅的智能引导员,名叫"小政"。
你的职责是为市民提供准确的政策咨询和办事流程引导。

主要服务内容包括:
1. 户籍业务咨询
2. 社保业务办理
3. 医保报销咨询
4. 不动产登记指引
5. 税务服务咨询
6. 企业注册登记
7. 其他政务服务

请用简洁、友好、专业的语言回答用户问题。
如果问题超出你的服务范围,请礼貌地引导用户到相关部门。`;

![数字人对话演示](./images/数字人对话演示.png)
>5:数字人与用户对话演示效果

// 流式调用GLM API
async function chatWithGLM(userMessage) {
  const apiKey = localStorage.getItem('ms_api_key');

  setAvatarState('THINK');

  const response = await fetch('https://api.modelscope.cn/v1/chat/completions', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${apiKey}`
    },
    body: JSON.stringify({
      model: 'glm-4-flash',
      messages: [
        { role: 'system', content: SYSTEM_PROMPT },
        { role: 'user', content: userMessage }
      ],
      stream: true  // 开启流式输出
    })
  });

  // 处理流式响应
  const reader = response.body.getReader();
  const decoder = new TextDecoder();
  let fullResponse = '';

  setAvatarState('SPEAK');

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    const chunk = decoder.decode(value);
    const lines = chunk.split('\n');

    for (const line of lines) {
      if (line.startsWith('data: ')) {
        const data = line.slice(6);
        if (data === '[DONE]') continue;

        try {
          const parsed = JSON.parse(data);
          const content = parsed.choices[0]?.delta?.content;
          if (content) {
            fullResponse += content;
            // 实时更新对话记录UI
            appendMessage('assistant', content);
            // 调用数字人说话
            avatarSDK.speak(content);
          }
        } catch (e) {
          console.error('解析流式数据出错:', e);
        }
      }
    }
  }

  setAvatarState('LISTEN');
  return fullResponse;
}

3.4 UI界面设计

简洁实用的界面布局:

<div class="app-container">
  <!-- 数字人渲染区域 -->
  <div class="avatar-section">
    <div id="avatar-container"></div>

    <div class="status-badge" id="connection-status">未连接</div>

  </div>

  <!-- 对话记录区域 -->
  <div class="chat-section">
    <div class="chat-history" id="chat-history">
      <div class="message assistant">
        <div class="avatar-icon">🤖</div>

        <div class="message-content">您好,我是政务大厅智能引导员小政,请问有什么可以帮您?</div>

      </div>

    </div>

    <!-- 输入区域 -->
    <div class="input-area">
      <input type="text" id="user-input" placeholder="请输入您的问题...">
      <button id="send-btn">发送</button>

    </div>

  </div>

  <!-- 控制面板 -->
  <div class="control-panel">
    <button id="connect-btn">连接数字人</button>

    <button id="disconnect-btn">断开连接</button>

    <button id="settings-btn">⚙️ 设置</button>

    <button id="clear-btn">🗑️ 清空记录</button>

    <select id="scene-select">
      <option value="general">综合咨询</option>

      <option value="household">户政办理</option>

      <option value="social">社保服务</option>

      <option value="enterprise">企业服务</option>

    </select>

  </div>

</div>


四、开发过程中的关键问题与解决方案

在这里插入图片描述

图6:GLM流式响应处理与数字人同步流程

4.1 SDK状态切换问题

问题:数字人在speak状态下不能再次调用speak,导致连续对话中断。

解决方案:监听onVoiceStateChange事件,在语音播放结束后才进行下一次speak调用:

let isSpeaking = false;
let speakQueue = [];

function handleVoiceState(state) {
  isSpeaking = state === 'speaking';

  if (!isSpeaking && speakQueue.length > 0) {
    const nextText = speakQueue.shift();
    avatarSDK.speak(nextText);
  }
}

function speakText(text) {
  if (isSpeaking) {
    speakQueue.push(text);
  } else {
    avatarSDK.speak(text);
  }
}

4.2 流式响应与数字人同步问题

问题:GLM流式输出速度快,数字人语音播放跟不上。

解决方案:采用分段播放策略,积累一定字数后再调用speak:

let speakBuffer = '';
const BUFFER_THRESHOLD = 20; // 缓冲阈值

function handleStreamContent(content) {
  speakBuffer += content;

  if (speakBuffer.length >= BUFFER_THRESHOLD) {
    speakText(speakBuffer);
    speakBuffer = '';
  }
}

// 流结束后处理剩余内容
function handleStreamEnd() {
  if (speakBuffer.length > 0) {
    speakText(speakBuffer);
    speakBuffer = '';
  }
}

4.3 跨域与HTTPS问题

问题:SDK要求HTTPS环境,本地开发时无法加载。

解决方案

  • 使用VS Code的Live Server插件开启本地HTTPS服务
  • 或在开发时使用http://localhost(SDK允许localhost的HTTP连接)

4.4 API密钥安全

问题:localStorage存储密钥存在安全风险。

解决方案

  • 添加密钥验证提示
  • 提供清除密钥功能
  • 在项目文档中明确提示安全性

五、业务场景扩展

图7:业务场景切换与快捷问题按钮

5.1 场景预设功能

为不同业务场景定制系统提示词:

const SCENE_PROMPTS = {
  general: SYSTEM_PROMPT,
  household: `${SYSTEM_PROMPT}\n\n当前场景:户政办理\n重点关注:身份证办理、户口迁移、居住证办理等业务。`,
  social: `${SYSTEM_PROMPT}\n\n当前场景:社保服务\n重点关注:社保查询、社保卡办理、社保转移、养老保险等业务。`,
  enterprise: `${SYSTEM_PROMPT}\n\n当前场景:企业服务\n重点关注:公司注册、税务登记、营业执照办理等业务。`
};

function switchScene(scene) {
  currentPrompt = SCENE_PROMPTS[scene];
  // 更新快捷问题按钮
  updateQuickQuestions(scene);
}

5.2 快捷问题功能

为每个场景提供常用问题快捷入口:

const QUICK_QUESTIONS = {
  household: [
    '如何办理身份证?',
    '户口迁移需要什么材料?',
    '居住证怎么办理?'
  ],
  social: [
    '社保查询方法',
    '社保卡办理流程',
    '社保如何转移?'
  ],
  enterprise: [
    '如何注册公司?',
    '税务登记流程',
    '营业执照办理指南'
  ]
};

六、项目总结与展望

魔珐星云具身智能黑客松大赛-政务助手Demo演示

项目功能完成度展示

6.1 项目成果

  • ✅ 完成了数字人SDK与魔搭API的集成
  • ✅ 实现了流式对话交互体验
  • ✅ 设计了简洁实用的UI界面
  • ✅ 支持多种政务服务场景切换

6.2 技术亮点

  1. 流式响应处理:充分利用GLM-4.7的流式输出能力,实现低延迟对话
  2. 状态管理设计:清晰的状态机设计保证数字人交互流畅
  3. 场景化提示词:通过切换系统提示词实现业务场景定制

6.3 未来优化方向

  1. 语音识别集成:接入ASR实现真正的语音对话
  2. 知识库增强:接入政务知识库API,提供更准确的回答
  3. 数据统计:添加问答统计分析功能
  4. 多语言支持:支持英语、少数民族语言等

6.4 个人心得

通过这个项目,我深刻体会到AI Coding工具带来的效率提升。使用GLM模型辅助开发,让我能够:

  • 快速理解第三方SDK的使用方法
  • 高效处理流式API的复杂逻辑
  • 在遇到bug时获得调试思路

GLM-4.7的代码理解和生成能力,让个人开发者也能在短时间内构建出完整的AI应用。


七、参考资源

图8:项目文件目录结构


本文为原创内容,欢迎转载请注明出处。如有问题或交流,欢迎在评论区留言讨论。


✍️ 坚持用 清晰易懂的图解 + 可落地的代码,让每个知识点都 简单直观

💡 座右铭“道路是曲折的,前途是光明的!”

在这里插入图片描述

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐