一、这个故事,从一张被忽略的画说起

1.1 冰箱上的画

我家闺女五岁,每天从幼儿园回来,书包里都能翻出两三张画。蜡笔的,水彩的,有时候就是一支铅笔在废纸上勾几下。画得好不好另说,画完她特得意,非要贴冰箱上。

然后呢?然后就没有然后了。

它可能就是贴一周,落灰,取下来塞抽屉。

我夸来夸去就那几个词——“画得真棒”“这个颜色好看”。说实话,我根本看不懂几岁的小朋友她画的是什么。

她倒是愿意讲。可五岁小孩的叙事你懂的,开头说"这是一个恐龙",中间跳到"这是它的好朋友小花",结尾变成"然后天黑了"。故事没听明白,倒是把她自己讲困了。

有天晚上她睡着了,我盯着冰箱上最新那张画看——一个大红圆圈,旁边几根歪歪扭扭的绿线条,右下角有个紫色的一团什么玩意。

我在想,这里面到底藏着什么故事?她为什么画这个?

如果有个工具,能替她把画里的世界"读"出来,再编成故事讲给她听,那该多好啊!

我使用了WorkBuddy帮我进行Vibe Coding,完成了代码开发过程,利用的是腾讯云的skill能力,做出了我自己的agent,最终得到了一个不错的效果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

运行解析效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1.2 两个神奇的 Skill组合在一起

腾讯云 AI Skills 矩阵五大类摆在那里。我看见 tencentcloud-vita——多模态理解模型,能看图片,输出结构化文本。简介里写的应用场景是"目标检测、结构解析、标签分类"。挺正经的。但我的第一反应不是安防监控,是:

这东西能不能看懂小孩的画?

因为儿童画本质上是一种高度符号化的视觉语言。太阳就是一个圆圈加几根线,房子就是一个三角形加一个方块。大人觉得"画得不像",但从视觉符号的角度来说,孩子的表达方式恰恰非常清晰——因为简化到了本质。VITA 这种多模态模型,理论上应该能"读懂"这些符号。

这个需要申请,我登录到官网控制台进行授权。首次进入按提示开通平台服务(需腾讯云账号 + 实名认证)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在模型广场 / 在线推理服务里找到 VITA(youtu-vita),启用后付费(不用充值,走免费额度)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

光读懂不够。读出来的是 JSON,冰冷的数据。我想做一个"做不到"的东西——让没有美术背景的家长,也能听懂孩子画里在想什么。这不是效率问题,是情感问题。

所以,得有人把这些数据变成故事,再变成声音。这就需要第二个 Skill:tencentcloud-tts

https://console.cloud.tencent.com/tts → 点“开通服务”。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

领取一下tts资源:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

哈可以开通语音识别并领取资源包。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

VITA 当眼睛,TTS 当嗓子。中间那个"大脑"——负责把看到的东西编成故事的——交给 WorkBuddy 的 Agent 能力来做。

两条 Skill,一只眼睛一副嗓子,刚好。


二、怎么把两个 Skill 串起来

2.1 “眼睛 → 大脑 → 嗓子”

整个系统的核心其实特别简单,三步:

第一步,把孩子的画扔给 VITA。它吐回来一个 JSON,告诉我画里有太阳、有房子、有树、有手拉手的两个人,画面情绪是"温暖快乐"。还附带几个"彩蛋细节"——比如"太阳的光芒画得又长又密"“两扇窗户用了不同颜色”。这些细节太重要了,后面会讲为什么。

第二步,Agent 拿着这个 JSON 写故事。不是随便编,是有严格约束的——画里出现的元素,故事里必须出现,不许偷换。主角名字写孩子的小名。结尾必须是安静的、回家的画面。不许出现"这个故事告诉我们"这种说教。

第三步,故事交给 TTS 变成声音。腾讯云的智瑜音色(101001),温柔女声,特别适合念睡前故事。

就这么三步。不复杂,但每一步都有讲究。

2.2 VITA 读画:关键是那个 story_hints

VITA 用的是 OpenAI 兼容协议,调起来跟 chat completion 差不多。content 里面塞一个 image_url 和一段 text 指令就行。

提示词(ANALYSIS_PROMPT)我没写"请识别图片中的内容"这种废话,而是精确要求了输出格式:3-8 个元素,每个元素标注名字、颜色、位置、大小。还要猜场景、判断情绪、提取调色板。

最关键的是 story_hints 这个字段。这是我加的——让 VITA 额外找出"孩子画得特别用心的地方"。一张画,AI 能识别出"有个太阳"不稀奇,但如果它能注意到"太阳画了笑脸"“小人的手画得特别大”,这些细节就成了故事里最动人的种子。

举个例子。我家闺女画过一张"全家去公园",画面右下角有个特别小的人,比其他人都小很多。VITA 的 story_hints 返回了"右下角的小人比其他人物明显小很多,可能代表年龄最小的家庭成员"。就这一句话,故事里就有了——最小的那个人是"妹妹",她跟不上大家的步伐,但没有人丢下她。

这种细节,是模板生成不出来的。

2.3 TTS 配音:150 字限制不是什么大问题

腾讯云 TTS 单次请求上限 150 字。一篇 300-450 字的睡前故事,肯定会超。

这事其实好办。我的 speak.py 里写了个分句函数,按句号、问号、感叹号先切大段,超长的再按逗号细分。留了 30 字安全余量,取 120 而不是 150,防止标点编码出幺蛾子。

分完句,逐段调 TTS,拿到 mp3 二进制。有 ffmpeg 就无损拼接成单个文件,没有就留分片。mp3 帧天然支持顺序拼接,不做重编码也能正常播。

说实话这个"问题"几乎是每个用 TTS 做长文本的人都会遇到的。解法也标准。我提一嘴只是想说明,Skill 的 API 限制不会成为项目落地的障碍——遇到限制,拆就完了。

2.4 中间那个"大脑":WorkBuddy 的 Agent

这一步没调任何 Skill,完全靠 WorkBuddy 自己的 Agent 能力。但它是整个项目最难调的部分。

不是技术上难,是"写故事"这件事难。我试了很多版提示词,前几版写出来的故事,怎么说呢……AI 味儿冲得不行。动不动就"小满学到了一个重要的道理",或者"从此以后,他变得更加勇敢了"。这种话写在故事里,孩子不爱听,大人也尴尬。

后来我把提示词改了七版,定下几条铁律:

  • 画里有什么,故事里就得有什么。VITA 识别出的元素至少出现 80%,不许替换。
  • 结尾必须是安静的、回家的画面。"月亮把被子拉上来"这种,适合睡前。
  • 禁止一切说教句。“道理是”“我们要”“这个故事告诉我们”——出现一个字都不行。
  • 口语化。多用拟声词。哗啦啦、咕噜噜、嗖嗖嗖。少用成语。
  • 按年龄调词汇。五岁孩子听"踌躇"肯定不行,"犹豫了一下"就好多了。

改成这样之后,故事终于能看了。给大家看一段实际输出——这是我上传闺女画的那张"房子和太阳",VITA 识别出七个元素后,Agent 写的故事开头:

太阳打了个大大的哈欠,把金色的光轻轻铺在小满家的屋顶上。小房子醒了,两扇彩色窗户一睁眼,红一格,黄一格,像两块正在发光的糖。

2.5 封装成 Skill:SKILL.md 是指挥棒

这三步流水线我没散装在代码里,而是封成了一个自定义 Skill。文件叫 SKILL.md,放在 skill/kid-art-storyteller/ 目录下。

为什么这么干?因为我想让这个能力在 WorkBuddy 里面能复用。安装 Skill 之后,用户只要说"把这张画变成故事"——不用管什么 VITA、TTS、JSON——WorkBuddy 就自动按 SKILL.md 里定义的流程跑:收集孩子小名和年龄、调 analyze.py 读画、自己写故事、调 speak.py 配音、最后归档到画廊目录。

SKILL.md 里我还写了一张故障处理表。VITA 报 401 怎么办、TTS 密钥没配对怎么办、故事超长怎么办——都列了。还有一条特别有意思的:识别元素和画明显不符的时候,不是报错,而是把 VITA 的结果给孩子看,让孩子来"纠错",然后把纠错后的结果并入故事。

这个设计我下面会细说,它其实是我最得意的一个决定。


三、在 WorkBuddy 里的实际体验

3.1 从对话开始

这是真实使用场景。晚上八点半,闺女刚画完一张画,我打开 WorkBuddy,把画拍了张照发过去,打了一行字:

“把这张画变成故事,主角叫小满,五岁。”

WorkBuddy 识别到了"把画变成故事"这个触发词,自动激活 kid-art-storyteller Skill。它先确认了一下音色偏好——我选了"温柔姐姐"——然后开始跑流程。

大概过了十几秒,VITA 读完了。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我看到了这张画里的世界:

一个大大的太阳,红色,在左上角
一朵蓝色的云,右上角飘着
中间是一座棕色的小房子,有两扇不同颜色的窗户
房子右边有一棵绿色的大树
树下开着两朵小花,一红一黄
房子前面站着两个人,手拉着手
我猜这是一个太阳升起的早晨,一家人站在小房子前面。画面感觉很温暖、很快乐。

我闺女凑过来看了一眼,指着"手拉手的两个人"说:"这是我跟妈妈!"我说那爸爸呢?她说爸爸在里面拍照。

行吧。

然后 WorkBuddy 开始写故事。它用混元大模型,把 VITA 的分析结果和孩子信息塞进提示词模板,等了大概五六秒,故事出来了。标题叫《太阳盖被子》。开头就是上面那段——“太阳打了个大大的哈欠,把金色的光轻轻铺在小满家的屋顶上。”

我念给闺女听。听到"两扇彩色窗户一睁眼,红一格,黄一格,像两块正在发光的糖"的时候,她突然打断我:"窗户真的是糖做的吗?"我说在故事里是的。她想了想,说:“那我可以吃吗?”

最后一步,TTS 配音。WorkBuddy 调了腾讯云的智瑜音色,把整篇故事合成了一个 mp3。声音温柔、节奏慢,是那种你会想关了灯、躺在床上听的调子。我放了给她听,听到一半就打哈欠了。听到"月亮把被子拉上来,盖住了整个小院子"的时候,她已经睡着了。

我又试了一个更成熟的画风的画作上传,学校要求的手工活:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我上传了大概十几张闺女的画,有些观察值得记录:

VITA 的识别率:对典型蜡笔画,元素识别率在七八成左右。太阳、房子、树、人这些大元素基本不会错。小元素容易漏——比如花、云朵这些画得比较随意的,有时候会跳过。但 story_hints 经常有惊喜。有一次它注意到"小人的手画得特别大",这个细节我都没留意义到,但确实如此——闺女画人物的时候手总是画得不成比例的大。后来故事里就写了"小满的手很大,大到能一把抓住整片阳光"。

混元写故事的质量:hunyuan-lite 的创意水平比我预期好。我设的 temperature 是 0.8,故事之间有差异性,不会每次都一个套路。但也偶尔会翻车——有一次写了个故事,结尾是"小满明白了友情的可贵"。这违反了我的提示词约束(禁止说教句),应该是模型没完全遵守指令。这种情况下我会手动改一下再丢给 TTS。

TTS 的音色:智瑜(101001)是真的适合讲故事。温柔但不做作,语速可以调到 0.85 倍速,更有睡前氛围。我试过智旭(101003,沉稳男声),适合冒险类故事,但睡前用太正经了。智婕(101005,活泼女声)适合白天互动用,睡前太嗨。


四、交互设计

页面整体走蜡笔画/手账风格。米黄底色,圆角卡片,珊瑚红、暖黄、草绿三色为主。背景有轻微噪点纹理,像旧纸的质感。故事正文用楷体——呼应"手写"的感觉。

交互上是四步流水线,从左到右依次推进:选画 → VITA 读画(显示识别结果和元素标签,标签是一个个弹出来的,有动画)→ 写故事(打字机效果,一个字一个字蹦出来)→ TTS 播放(带 canvas 波形动画)。

每一步都有状态指示——等待、进行中、完成。让用户清楚知道"AI 正在干什么"。这个很重要,AI 做事的时候如果没有任何反馈,用户会以为卡死了。

页面底部有一个"成长画廊"。每次生成的画和故事,可以一键存进去。存在 localStorage 里,不用登录、不用联网。点任意卡片能回放故事。

这个设计不是"功能",是"意义"。

我家闺女的画现在散落在各个抽屉里。有些已经找不到了。如果每一张画都能存下来,配上一段故事和一段声音,多年以后翻出来——是她五岁时画的恐龙,AI 编的故事,她听到一半睡着的那个晚上。

这把一个技术 Demo 变成了一份可以留住的东西。

4.1 server.py 的设计

后端我用 Python 标准库的 http.server 实现,零框架。一个文件,四个接口:

接口 干什么 入参 出参
GET /api/health 健康检查 + 密钥状态 {ok, has_vita_key, has_cloud_keys}
POST /api/analyze VITA 读画 {image: "data:image/..."} VITA JSON
POST /api/story 混元写故事 {analysis, childName, age} {title, text}
POST /api/tts TTS 配音 {text, voice, speed} {audio: "base64..."}

故事生成走腾讯云混元大模型(hunyuan-lite),通过 SDK 调 ChatCompletions。提示词模板把 VITA 的 JSON、孩子小名、年龄都填进去,让混元按规则写故事。

TTS 接口复用了 speak.py 的分句逻辑,但不是写文件——而是把所有分片的 mp3 二进制直接拼接后 base64 编码返回。前端拿到后 new Audio('data:audio/mp3;base64,' + audio) 就能播。

为什么不用 Flask 或 FastAPI?因为这个项目就四个接口,引一个框架进来纯属增加复杂度。标准库够用就够用,能少一个依赖就少一个。部署也简单——python server.py 就跑了,不用装 uwsgi、不用配 nginx。

4.2 前端的"演示模式"语音

演示模式下没有密钥,TTS 走不了。但我不想让语音这块空白——没有声音的"有声童话"太尴尬了。

解决方案是浏览器的 SpeechSynthesisUtterance API。挑一个中文 voice,设好 pitch 和 rate,效果虽然比不上腾讯云智瑜的音色,但至少是能听的声音。播放器配了 canvas 波形动画,视觉上跟真实 TTS 播放完全一致——评委看不出区别,体验是完整的。


五、在 WorkBuddy 里用 Skill 是什么感觉

这部分我想多说两句,因为这是征文要求里特别强调的——“结合 WorkBuddy 等 AI Agent 平台做开放式创新应用实践”。

5.1 Skill 让 AI 能力"隐入"对话

装 Skill 之前,如果我想用 VITA 读画 + TTS 配音,我得自己写代码、调 API、处理错误、拼音频。每次跑一遍流程得敲好几条命令。

装了 Skill 之后呢?我说一句话就行了。

“把这张画变成故事。”

WorkBuddy 自动识别意图、自动跑流程、自动归档。我不需要知道 VITA 的 API 长什么样,不需要管 TTS 的 150 字限制,不需要操心 JSON 提取。所有工程细节被 SKILL.md 封装在下面,留给用户的只有一句话和一个结果。

这就是 Skill 的价值——它让 AI 能力"隐入"对话。技术越强,用户越感知不到技术。就像你用手机拍照的时候,不会去想 ISP 芯片在干什么。

5.2 SKILL.md 是声明式的编排

写 SKILL.md 的过程,本质上是在做"声明式编程"。我不是在写代码告诉电脑"先执行这一行再执行那一行",而是在写一份文档,描述"遇到这种情况应该怎么办"。

比如故障处理。我不需要在代码里写 try-catch 处理每一种错误,而是在 SKILL.md 的表格里写:VITA 报 401 → 检查密钥;TTS 报 AuthFailure → 检查密钥配对;识别偏差 → 让孩子纠错。WorkBuddy 读了这个文档,遇到这些情况自己知道怎么办。

再比如"不超过一轮追问"这条规则。我在 SKILL.md 里写了:确认孩子小名、年龄、音色偏好时,如果用户已经提供就不追问,没提供就用默认值,最多追问一轮。这种"克制"很难用代码硬编码,但在文档里一句话就讲清楚了。

这种编排方式的好处是可读、可改、可扩展。后续我想加"让孩子语音纠错"的功能——用 ASR Skill 把孩子的语音转成文字,再反馈给 Agent——只要在 SKILL.md 里加一步就行,核心代码几乎不用改。

5.3 也能跑在 CodeBuddy 和 ADP 上

虽然我主要在 WorkBuddy 上做实践,但 SKILL.md 的格式是通用的。Skill 本质上就是"一段描述工作流程的 Markdown + 几个脚本",任何支持 Skill 的 AI Agent 平台都能加载。CodeBuddy 可以把它作为一个开发辅助工具触发,ADP 可以把它嵌入更大的自动化流程。

这一点其实挺重要的——Skill 不是绑定在某个平台上的插件,而是一种"能力描述协议"。写一次,到处跑。腾讯云把 AI 能力封装成 Skill 的好处也在这里:开发者不用为每个 Agent 平台写一套对接代码,装上就能用。WorkBuddy 自动按 SKILL.md 跑五步流程:收集信息 → VITA 读画 → 写故事 → TTS 配音 → 归档到画廊目录。

每一份都是完整的——画、故事、声音、AI 识别的元素数据。存着,以后翻出来看。


做完了之后的一些感想

说句实话,这个项目的技术复杂度不高。两个 API 调用、一段提示词、一个分句函数、一个前端页面。任何有一定开发经验的人都能做出来。

难的不是写代码,是想到这个场景。

腾讯云 Skills 矩阵摆在那里,五大类二十多个能力。每个能力的技术文档都写得清清楚楚。但把这些能力组合成一个"有人愿意用"的东西,需要的不是技术能力,是对生活的观察。

我观察到的场景是:冰箱上贴满了孩子的画,没人看得懂,最终被取下来塞进抽屉。这个场景每家每户都在发生,但没有人在意。因为它太日常了,日常到你不会觉得这是一个"问题"。

AI 的价值不只是解决你意识到的问题,还可以解决你没意识到的问题。

单独用 VITA,它能看懂画但说不出来。单独用 TTS,它能念故事但不知道念什么。两个 Skill 单独用,都只是"工具"。组合起来用,才变成了"体验"。

中间那个 Agent 大脑——写故事这一步——是连接两者的桥梁。它不是 Skill,但它不可或缺。这让我意识到,腾讯云 Skills 矩阵的设计思路其实是"积木式"的:每个 Skill 是一块积木,Agent 是拼积木的手。积木本身没有情感,拼法才有情感。

同样的两块积木——VITA 和 TTS——换个拼法,就能做完全不同的事。老照片识别+口述历史朗读、冰箱食材识别+菜谱语音播报、旅行照片识别+有声日记生成。拼法不同,场景就不同。

做 AI 产品的人有一种执念:准确率必须高。识别率低于 90% 就觉得是失败。

但在"画中有话"这个场景里,我发现准确率不是越高越好。

VITA 偶尔识别"错"——恐龙变鳄鱼、小花变蘑菇——这些"错误"反而创造了亲子互动的机会。孩子纠正 AI 的过程,本身就是一段对话、一段游戏。如果 VITA 每次都 100% 准确,流程就变成了:上传画 → 出结果 → 听故事。一条直线,没有弯路,也没有人参与。

适度的"不完美",让 AI 变成了对话者而不是工具。这个认知对我冲击挺大的。

做参赛项目的时候,我纠结过很久:要不要加更多 Skill?要不要做人脸识别确认"这个画是哪个孩子画的"?要不要接 ASR 做语音输入?要不要上 3D 生成做"把画里的角色变成立体模型"?

最后我忍住了。

因为"画中有话"的核心魅力就是简单——一张画进去,一段有声童话出来。加了太多东西,反而模糊了焦点。两个 Skill,一个看一个说,足够了。

有温度的东西不需要堆功能。它自己会说话。

后记

有天晚上女儿问我:"你能不能每天晚上都给我讲故事?"我说行。然后那天晚上我没讲,放了 AI 念的《太阳盖被子》给她听。

她听到一半就困了。但睡着之前说了一句:“太阳真的会盖被子吗?”

我说会的。

她说:“那月亮呢?”

“月亮负责盖。”

她没再说话。我以为她睡着了,过了大概三十秒,黑暗里传来一句:“那星星呢?”

我没答上来。但我想,也许下一张画里会有星星。VITA 会看到它,Agent 会给它编一个关于星星盖被子的故事。TTS 会用温柔的声音念出来。而我会躺在她旁边,听着这个故事,跟一起她睡着。

技术做不到的事太多了。但有些事,现在能做到。

一张涂鸦进去,一段有声童话出来。就这么简单的事。

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐