今天翻到一篇不错的技术分享,看完之后自己也琢磨了一下,把思路梳理记录下来。
基于DeepSeek+3D具身交互智能的垃圾分类助手落地实战
如何将我们的产品拟人化?先给大家抛出一个问题,大家也能思考一下。
这两年真的太明显了,不管是深圳还是全国,人形机器人、具身智能这个赛道直接彻底爆火,绝对是 AI 接下来的核心风口。
我最近闲下来总刷各类博主的实测测评,发现近两年人形硬件机器人赛道热度高涨,但实体设备成本高、线上大屏、社区科普等轻量化场景难以复用;而纯文本国产大模型又缺少可视化交互载体。很多企业、社区都有疑问:官网接待、科普大屏、24 小时宣教这类轻量化线上场景,该低成本搭建专属具身交互智能体?
常规我们的AI对话仅依托 DeepSeek 这类国产大模型搭建纯文本问答,交互模式极度单一冰冷,没有具象载体支撑自然沟通。是不是看起来蛮死板的?
早年间我们做线上服务、智能科普,方法真的尤其简陋。要么靠人工客服24小时值守,人力成本巨高还容易出错;要么搭个简单的RAG知识库问答,交互死板、功能单一,毫无体验感,用来做垃圾分类科普基本没人愿意看。
如今国产大模型能力日趋成熟,搭配AI具身智能数字人标准化具身交互智能底座,即可实现真人般的细腻表情、自然流畅的肢体动作、贴合场景的语音播报,再加上大模型的智能问答能力,接入难度极低,不用组建专业研发团队,就能直接落地到网站、大屏、线上科普场景中。
魔珐星云官网:点击查看链接
二、落地实拍:彻底换掉老旧死板的垃圾分类科普
大家平时小区里的垃圾分类大屏,基本都是摆设:几张静态海报、固定文字介绍,没人愿意看。社区、学校想做科普,要么靠人工值守讲解,费人费力;要么就是无人问津的展板,根本起不到效果。
但换成DeepSeek打造的的3D具身垃圾分类助手
之后,整个体验直接升级。一块普通大屏,直接变成24小时在岗的专属环保讲解员,不用人工看管,随时有人问就随时答。给大家描述下真实用场景:居民扔垃圾拿不准,直接对着大屏提问,“奶茶杯是什么垃圾”“废电池怎么扔”“破损陶瓷碗属于哪一类”。屏幕里的3DAI助手会带着自然的表情、抬手、点头,一边做动作一边口语化讲解,不仅说清分类类别,还会提醒投放注意事项。遇到复杂的混合垃圾,会一步步拆解说明,而且你随时也能打断它、问新问题,互动感拉满,完全不像机器。
对比传统方案,是不是看起来很拟人化。
三、硬核实战:单文件搭建DeepSeek+AI数字人垃圾分类智能助手
本次实战无需复杂后端架构,抛弃Node.js、FastAPI中转,仅通过单HTML文件+原生SSE流式解析+XmovAvatar**具身交互 SDK,快速搭建可直接运行、可实时交互的3D具身垃圾分类智能助手。全程前端轻量化部署,开发者零门槛复刻,快速落地垃圾分类具身AI场景。
3.1 前期准备干活
咱们先把准备干活说清楚,超级简单,没有任何复杂操作,小白照着弄就行。
首先需要两个核心凭证,一个是 DeepSeek 大模型的 API Key,另一个是AI数字人的应用密钥。
Ai-DeepSeek官网:https://deepseek.com/
DeepSeek 的 Key 大家自己去官网注册、开通额度就能拿到,现在国产大模型开户都很方便,免费额度完全够咱们测试 Demo 用,我这里就不啰嗦细讲流程了。
重点说下数字人这边:大家直接点击链接打开官网,注册登录之后,新建一个自己的具身交互智能应用。里面也能随便选喜欢的数字人形象、适配科普场景的音色、默认待机动作,全部可视化操作,点点鼠标就能配置好。
配置做好之后,后台会自动生成两个关键信息:App ID、App Secret,这两个东西一定要保存好,后面代码里必须用到。
所有准备干活就这三步,搞定之后,咱们直接上手写代码、跑项目。
先准备好大模型和数字人3D应用的配置:
这里我是用的deepseek作为大模型底座,这个自己去deepseek的平台创建API获取key就OK了 这里就不赘述了
3.2 完整可直接运行源码
我把所有代码都精简好了,整站就一个 HTML 文件,不用搭后端、不用装依赖、不用配置环境。大家直接复制下面全部代码,新建一个 index.html 文件粘贴进去,只需要替换里面三处自己的密钥,直接就能跑通完整的垃圾分类数字人交互效果,提示:此处Html文件只做学习参考方便大家阅读,以及引入数字人SDK,密钥要记的加密保存哦,通过后端代理中转的方法。
代码我也做了中文注释,每一块功能都分得清清楚楚,方便大家后期自己改样式、改话术、改交互逻辑。
垃圾分类小助手 - 3D 智能导览
body {
background: linear-gradient(180deg, #022c22 0%, #064e3b 50%, #0f766e 100%);
background-attachment: fixed;
}
#avatar-container {
background: linear-gradient(135deg, #047857, #022c22);
box-shadow: inset 0 0 100px rgba(0, 0, 0, 0.5);
}
.glass-panel {
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.category-card {
transition: all 0.3s ease;
}
.category-card:hover {
transform: translateY(-4px);
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3);
}
.glow-text {
text-shadow: 0 0 20px rgba(74, 222, 128, 0.5);
}
🌍
# ♻️ 垃圾分类智能助手
🌱
智能识别 · 精准分类 · 共建绿色家园
♻️
可回收物
☠️
有害垃圾
🥬
厨余垃圾
🗑️
其他垃圾
环保小助手正在准备中...
首次加载需下载资源,请耐心等待
环保小助手未就绪
💡 有任何垃圾分类的问题,随时问我哦!
表达层首响更快,完整问答耗时仍取决于大模型、网络和文本长度
发送
🛑 停止发言
让垃圾分类成为一种生活习惯 🌿
// ⚠️ 安全警告:此文件仅用于演示目的
// 生产环境中,API密钥不应硬编码在前端代码中
// 建议将DeepSeek请求放到后端代理,通过/api/chat中转
// 浏览器直连第三方API存在CORS限制和密钥泄露风险
const CONFIG = {
mofa: {
appId: "xxx",
appSecret: "xxx",
gatewayServer: "https://nebula-agent.xingyun3d.com/user/v1/ttsa/session"
},
deepseek: {
apiKey: "sk-xxx",
apiUrl: "https://api.deepseek.com/v1/chat/completions",
systemPrompt: "你是一个名叫‘小绿’的活泼可爱的垃圾分类小助手。你的语言风格亲切、热情,就像邻家妹妹一样。专门解答各类垃圾分类问题,帮助用户正确识别垃圾种类。回答控制在80字以内,适合口语表达,不要使用分点列表或代码块。"
}
};
let mofaSdk = null;
let isFirstSentence = true;
let textBuffer = "";
const punctReg = /[。!?;;!?]/;
let abortController = null;
let requestVersion = 0;
function toInteractiveIdle() {
if (!mofaSdk) return;
mofaSdk.interactiveidle?.() ?? mofaSdk.interactiveIdle?.();
}
function initMofaAvatar() {
if (typeof XmovAvatar === 'undefined') {
console.error("SDK 脚本未成功加载,请检查网络链接。");
return;
}
mofaSdk = new XmovAvatar({
containerId: '#sdk_canvas',
appId: CONFIG.mofa.appId,
appSecret: CONFIG.mofa.appSecret,
gatewayServer: CONFIG.mofa.gatewayServer,
onMessage: function(msg) {
console.log("SDK 收到通知:", msg);
}
});
mofaSdk.init({
onDownloadProgress: (progress) => {
console.log("资源下载进度:", progress + "%");
document.getElementById('status-text').innerText = `正在加载资源: ${progress}%`;
}
}).then(() => {
console.log("3D 渲染就绪!");
document.getElementById('loading-tips').style.display = 'none';
const statusEl = document.getElementById('status-text');
statusEl.innerText = "环保小助手已就绪";
statusEl.classList.add('text-emerald-300');
}).catch((err) => {
console.error("3D 初始化失败:", err);
document.getElementById('status-text').innerText = "初始化异常";
});
}
window.addEventListener('load', initMofaAvatar);
function processStreamText(textChunk, isFinal = false) {
textBuffer += textChunk;
let match;
while ((match = punctReg.exec(textBuffer)) !== null) {
const breakIndex = match.index + 1;
const sentence = textBuffer.substring(0, breakIndex).trim();
textBuffer = textBuffer.substring(breakIndex);
if (sentence.length > 0) {
driveAvatarSpeak(sentence, false);
}
}
if (isFinal && textBuffer.trim().length > 0) {
driveAvatarSpeak(textBuffer.trim(), true);
textBuffer = "";
}
}
function driveAvatarSpeak(text, isEnd) {
if (!mofaSdk) return;
console.log(`[驱动声音] isStart=${isFirstSentence}, isEnd=${isEnd}, 文本: ${text}`);
mofaSdk.speak(text, isFirstSentence, isEnd);
if (isFirstSentence) {
isFirstSentence = false;
}
}
async function handleSendMessage() {
const inputEl = document.getElementById('user-input');
const outputEl = document.getElementById('chat-output');
const query = inputEl.value.trim();
if (!query) return;
inputEl.value = "";
textBuffer = "";
isFirstSentence = true;
requestVersion++;
const currentVersion = requestVersion;
if (abortController) {
abortController.abort();
}
abortController = new AbortController();
outputEl.innerHTML += `
你:**${query}
`;
const aiBubbleContainer = document.createElement('div');
aiBubbleContainer.className = "text-left";
const aiBubble = document.createElement('span');
aiBubble.className = "bg-green-800/80 border border-green-600/50 text-green-100 inline-block px-4 py-2 rounded-xl rounded-tl-none max-w-[85%] shadow-lg";
aiBubble.innerHTML = `**小绿:**`;
aiBubbleContainer.appendChild(aiBubble);
outputEl.appendChild(aiBubbleContainer);
outputEl.scrollTop = outputEl.scrollHeight;
try {
const response = await fetch(CONFIG.deepseek.apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${CONFIG.deepseek.apiKey}`
},
body: JSON.stringify({
model: "deepseek-chat",
messages: [
{ role: "system", content: CONFIG.deepseek.systemPrompt },
{ role: "user", content: query }
],
stream: true
}),
signal: abortController.signal
});
if (!response.ok) throw new Error(`HTTP 异常: ${response.status}`);
const reader = response.body.getReader();
const decoder = new TextDecoder('utf-8');
streamLoop: while (true) {
const { done, value } = await reader.read();
if (done) {
if (currentVersion !== requestVersion) break;
processStreamText("", true);
break;
}
const chunkStr = decoder.decode(value, { stream: true });
const lines = chunkStr.split('\n');
for (let line of lines) {
line = line.trim();
if (!line || line === 'data: [DONE]') continue;
if (line.startsWith('data:')) {
try {
if (currentVersion !== requestVersion) break streamLoop;
const jsonStr = line.replace('data:', '').trim();
const parsed = JSON.parse(jsonStr);
const token = parsed.choices[0]?.delta?.content || "";
if (token) {
aiBubble.innerHTML += token;
outputEl.scrollTop = outputEl.scrollHeight;
processStreamText(token, false);
}
} catch (err) {}
}
}
}
} catch (error) {
if (error.name === 'AbortError') return;
console.error(error);
aiBubble.innerHTML += `
[连接异常]`;
}
}
document.getElementById('send-btn').addEventListener('click', handleSendMessage);
document.getElementById('user-input').addEventListener('keydown', (e) => {
if (e.key === 'Enter') handleSendMessage();
});
document.getElementById('stop-btn').addEventListener('click', () => {
requestVersion++;
if (abortController) {
abortController.abort();
abortController = null;
}
toInteractiveIdle();
textBuffer = "";
isFirstSentence = true;
document.getElementById('chat-output').innerHTML += `
⚠️ 已停止
`;
});
温馨提示:
Tips:本html示例仅作为学习参考,ApiKey,appSecret不能硬编码展示在项目中,易受CORS和密钥泄露影响,千万不能将我们的密钥给泄露哦~
更多项目以及生产环境项目Vue版本参考请移步Gitee:仓库地址:https://gitee.com/xiaotietou/wangl-xingyun
3.3 核心功能简单讲解
这几十行代码就能引入我们的数字人功能。
第一:彻底解决延迟问题
传统预制视频数字人属于单向播报,无完整具身交互链路,必须等待全文生成再渲染;参数流架构分段流式驱动,是实现流畅具身交互智能的基础,大模型分段文本即可同步驱动表情、语音,大幅降低等待延迟。
数字人的运行流程我们可以在工作台里面去看到,我们可以进行一个测试,500ms就能进行从SDK的调用到成功渲染具身智能形象。
重点就是这句 interactiveIdle(),它可以直接清空当前所有播放东西,让数字人瞬间回到待机状态。不管它讲到哪,你随时提问、随时打断,不会出现声音重叠、画面卡死的情况,这也是商用级具身智能的核心能力。
document.getElementById('stop-btn').addEventListener('click', () => {
if (mofaSdk) {
mofaSdk.interactiveIdle();
textBuffer = "";
isFirstSentence = true;
document.getElementById('chat-output').innerHTML += `
⚠️ 已停止
`;
}
});
第三:AI大模型的引入和运行
配置文件
const CONFIG = {
mofa: {
appId: "xxx",
appSecret: "xxx",
gatewayServer: "https://nebula-agent.xingyun3d.com/user/v1/ttsa/session"
},
deepseek: {
apiKey: "sk-xxx",
apiUrl: "https://api.deepseek.com/v1/chat/completions",
systemPrompt: "你是一个名叫‘小绿’的活泼可爱的垃圾分类小助手。你的语言风格亲切、热情,就像邻家妹妹一样。专门解答各类垃圾分类问题,帮助用户正确识别垃圾种类。回答控制在80字以内,适合口语表达,不要使用分点列表或代码块。"
}
};
配置文件
AI数字人提示词
你是一个名叫‘小绿’的活泼可爱的垃圾分类小助手。你的语言风格亲切、热情,就像邻家妹妹一样。
专门解答各类垃圾分类问题,帮助用户正确识别垃圾种类。回答控制在80字以内,适合口语表达,不要使用分点列表或代码块。
LLM引入大模型
const response = await fetch(CONFIG.deepseek.apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${CONFIG.deepseek.apiKey}`
},
body: JSON.stringify({
model: "deepseek-chat",
messages: [
{ role: "system", content: CONFIG.deepseek.systemPrompt },
{ role: "user", content: query }
],
stream: true
})
});
五、运行避坑指南
很多人第一次跑会翻车,基本都是两个小问题,我提前给大家避坑,百分百能跑通。
1. 绝对不能直接双击打开HTML文件
cnpm install serve
serve -p 3000
然后打开浏览器
2. 正式业务一定要后端中转
咱们这个Demo为了简单,直接把API密钥写在前端了,适合测试学习。但如果是社区、学校、企业正式落地,一定要把大模型请求、密钥验签放到后端,防止密钥泄露,这是商用项目的基本规范。
六、最终总结
现在大家应该彻底看懂了:为什么说大模型负责动脑,3D具身数字人负责落地。
DeepSeek、千问这些国产大模型,已经把知识问答、逻辑判断做到极致了,垃圾分类这种知识性问题,对大模型来说根本没难度。但空有知识,只能困在对话框里,冷冰冰的没人看、没人用,根本落不了地。
而的具身交互智能,就是给 AI 装上身体、表情和动作,通过 AI 端渲、端侧解算与参数流,把枯燥的文字问答,变成可视化、可交互、有温度、全天候在线的真人级服务。
从硬件人形机器人的火爆,到软件端具身数字人的普及,AI的下半场早就不是“比谁更聪明”,而是比谁更贴近场景、更会服务人、更自然好用**。
大家可以复制html运行,也可以在html之上通过AI编辑器进行延申。
魔珐星云官网:点击跳转官网
就写这么多吧,内容比较基础,适合入门回顾。有补充的地方欢迎留言一起完善。
评论 (0)
暂无评论