Arduino UNO Q 讲好中国儿童故事

本示例国产大模型睡前故事讲述器是一个使用Arduino UNO Q构建的生成式AI应用,通过HTTP API直接调用科大讯飞Spark X1.5大语言模型,根据用户选择的参数创建个性化中文睡前故事。应用使用Streamlit构建直观的用户界面,支持实时参数调整和故事生成。

主要功能:

使用科大讯飞Spark X1.5大语言模型生成高质量中文睡前故事。

通过HTTP API直接调用,无需额外的原厂LLM Brick,更加适合中国网络环境,

使用Streamlit构建的现代化UI界面,带有精美国产动画背景图片,

支持多种故事参数自定义:年龄、主题、语调、结局类型、叙事结构、时长等,

支持随机生成故事功能,一键创建中国元素的成语故事,红色经典等积极教育意义的故事,

响应式设计,适配不同设备屏幕。

硬件:

Arduino UNO Q (x1)

USB-C电缆(用于供电和编程)(x1)

软件:

Arduino App Lab

科大讯飞Spark X1.5 API密钥

此示例需要有效的互联网连接以访问AI提供商的API。您还需要使用的服务的有效API密钥,目前科大讯飞Spark X1.5提供免费服务值得推荐。此外科大讯飞开源了API调用的示例方便二次开发。

下图中密钥为APIPassword,点击文档在跳转页面下载示例程序

引入WebUI - Streamlit金砖配置

python程序main.py输入:

复制代码
# SPDX-FileCopyrightText: Copyright (C) ARDUINO SRL (http://www.arduino.cc)
#
# SPDX-License-Identifier: MPL-2.0

import re
import os
import json
import datetime
import hashlib
import hmac
import base64
import urllib.parse
import requests
from arduino.app_utils import App

# 科大讯飞Spark X1.5 API配置
SPARK_API_KEY = "你申请的密钥"
SPARK_API_URL = "https://spark-api-open.xf-yun.com/v2/chat/completions"

def call_spark_api(prompt):
    """调用科大讯飞Spark X1.5 API"""
    headers = {
        "Authorization": f"Bearer {SPARK_API_KEY}",
        "Content-Type": "application/json"
    }
    
    # 构建请求体
    data = {
        "model": "spark-x",
        "messages": [
            {
                "role": "system",
                "content": "你是一个擅长讲述中国传统文化故事的儿童睡前故事讲述者。你的回答必须是故事本身,直接用HTML格式呈现。不要将回答包装在markdown代码块或任何其他格式中。使用<h1>、<h2>等标签作为标题和副标题。使用<strong>或<b>标签表示粗体文本。包含相关的表情符号。如果故事是分章节的,使用标题标签作为章节标题。请用中文回复,确保故事内容适合儿童睡前阅读。特别擅长讲述成语故事、西游记等经典名著、红色经典故事等中国传统文化题材。"
            },
            {
                "role": "user",
                "content": prompt
            }
        ],
        "stream": False,  # Streamlit UI不适合流式响应,改为非流式
        "temperature": 0.8,
        "max_tokens": 2048
    }
    
    try:
        response = requests.post(SPARK_API_URL, headers=headers, json=data, timeout=60)
        
        if response.status_code == 200:
            result = response.json()
            if 'choices' in result and len(result['choices']) > 0:
                return result['choices'][0]['message']['content']
            else:
                return "API返回了无效的响应格式"
        else:
            return f"API请求失败,状态码: {response.status_code}, 错误信息: {response.text}"
    
    except Exception as e:
        return f"API调用异常: {str(e)}"

def generate_stories_app():
    """使用Streamlit UI构建故事生成应用"""
    import streamlit as st
    
    st.set_page_config(
        page_title="国产大模型睡前故事讲述器",
        page_icon="🏰",
        layout="wide"
    )
    
    # 读取并编码背景图片
    import base64
    try:
        with open("assets/img/storyteller-background.png", "rb") as image_file:
            encoded_string = base64.b64encode(image_file.read()).decode()
        
        st.markdown(
            f"""
            <style>
            .stApp {{
                background-image: url("data:image/png;base64,{encoded_string}");
                background-size: cover;
                background-position: center;
                background-repeat: no-repeat;
                background-attachment: fixed;
            }}
            </style>
            """,
            unsafe_allow_html=True
        )
    except Exception as e:
        st.error(f"无法加载背景图片: {e}")
    
    st.title("🏰 国产大模型睡前故事讲述器")
    
    # 创建侧边栏用于参数设置
    st.sidebar.header("📚 故事参数设置")
    
    # 年龄选择
    age_options = ["3-5岁", "6-8岁", "9-12岁", "13-16岁"]
    age = st.sidebar.selectbox("年龄段", age_options)
    
    # 主题选择
    theme_options = ["奇幻/冒险", "童话", "成语故事", "西游记", "科学/宇宙", "动物", "喜剧", "红色经典"]
    theme = st.sidebar.selectbox("故事主题", theme_options)
    
    # 语调选择
    tone_options = ["平静甜美", "史诗冒险", "活泼愉快", "神秘好奇", "智慧深思", "紧张怪诞"]
    tone = st.sidebar.selectbox("故事语调", tone_options)
    
    # 结局类型
    ending_options = ["快乐安心", "开放式神秘", "有道德寓意", "戏剧性但有希望"]
    ending_type = st.sidebar.selectbox("结局类型", ending_options)
    
    # 叙事结构
    structure_options = ["经典", "分章节", "系列剧式"]
    narrative_structure = st.sidebar.selectbox("叙事结构", structure_options)
    
    # 故事时长
    duration_options = ["短篇 5分钟", "中篇 10-15分钟", "长篇 20+分钟"]
    duration = st.sidebar.selectbox("故事时长", duration_options)
    
    # 其他要求
    other = st.sidebar.text_area("其他要求(可选)", height=100)
    
    # 生成按钮
    generate_button = st.sidebar.button("📖 生成故事", type="primary")
    
    # 随机生成按钮
    random_button = st.sidebar.button("🎲 随机生成")
    
    if random_button:
        import random
        age = random.choice(age_options)
        theme = random.choice(theme_options)
        tone = random.choice(tone_options)
        ending_type = random.choice(ending_options)
        narrative_structure = random.choice(structure_options)
        duration = random.choice(duration_options)
        st.sidebar.success("已随机选择参数!")
    
    # 主内容区域
    if generate_button:
        # 创建提示
        prompt = f"作为一个喜欢给{age}的孩子读睡前故事的家长,我需要一个愉快且适合年龄的故事。"
        
        # 根据主题类型添加特定提示
        if theme == "成语故事":
            prompt += " 请创作一个基于中国成语的故事,解释成语的由来和含义,使用生动有趣的方式讲述。"
        elif theme == "西游记":
            prompt += " 请创作一个基于西游记人物和情节的冒险故事,保持原著的风格和价值观。"
        elif theme == "红色经典":
            prompt += " 请创作一个类似《鸡毛信》、《小兵张嘎》、《闪闪的红星》等红色经典的故事,传承革命精神和爱国情怀。"
        else:
            prompt += f" 故事类型是{theme}。"
            
        prompt += f"语调应该是{tone}。"
        prompt += f"请确保故事有{narrative_structure}的叙事结构,给孩子留下{ending_type}的感觉。"
        prompt += f"长度应该大约是{duration}。语言应该易于理解,适合我孩子的年龄理解能力。"
        prompt += "请在故事中加入适合中国儿童的文化元素和价值观念。"
        
        if other:
            prompt += f"\n\n其他可选的故事元素:{other}"
        
        # 显示加载状态
        with st.spinner("正在生成故事..."):
            # 调用API生成故事
            story = call_spark_api(prompt)
        
        # 显示故事
        st.header("📖 生成的故事")
        st.markdown(story, unsafe_allow_html=True)
        
        # 添加复制按钮
        if st.button("📋 复制故事"):
            st.write("故事已复制到剪贴板")
    else:
        st.info("请在左侧设置参数后点击\"生成故事\"按钮")
        
        # 显示示例故事
        st.header("📖 示例故事")
        example_story = """
        <h1>小兔子的冒险</h1>
        <p>从前,有一只可爱的小兔子,它住在一个美丽的森林里...</p>
        """
        st.markdown(example_story, unsafe_allow_html=True)
        st.caption("这是一个示例故事,设置参数并点击生成按钮来创建您自己的故事!")

# 使用Streamlit运行应用
if __name__ == "__main__":
    generate_stories_app()

背景图片按照此路径assets/img/storyteller-background.png放置,尺寸笔者给的是1980x1024大小。

使用说明

  1. 启动应用后,您会看到一个带有精美背景的Streamlit界面,

  2. 在左侧边栏中设置故事参数:

年龄段: 选择适合的年龄段(3-5岁、6-8岁、9-12岁、13-16岁)

故事主题: 选择故事类型(奇幻/冒险、童话、成语故事、西游记、科学/宇宙、动物、喜剧、红色经典)

故事语调:选择叙述风格(平静甜美、史诗冒险、活泼愉快等)

结局类型:选择故事结尾方式(快乐安心、开放式神秘等)

叙事结构:选择故事结构(经典、分章节、系列剧式)

故事时长:选择故事长度(短篇、中篇、长篇)

  1. 点击"生成故事"按钮,科大讯飞Spark X1.5将根据您的设置生成个性化中文故事,

  2. 或点击"随机生成"按钮,系统会随机选择参数生成故事。

较原厂程序笔者的方案更加简单,更加容易理解。融入中国元素,契合国情使开源硬件在中国落地生根,枝繁叶茂。以此示例建议大家在应用中多采用国产大语言模型,这样国产大语言模型才能越做越好,越来越聪明。

相关推荐
Dust-Chasing3 小时前
Claude Code源码剖析 - Claude Code 上下文压缩机制
人工智能·python·ai
甲维斯3 小时前
MiMo Code 初体验,免费,易上手,适合新手!
人工智能
2301_764441333 小时前
主流手机pc品牌的端侧模型部署梳理
人工智能·windows·机器学习·智能手机·产品运营
虾壳云智能4 小时前
阿里云百炼 API 配置 OpenClaw 2.7.9 环境搭建
人工智能·阿里云百炼·open claw安装·open claw教程
Xzh04234 小时前
AI Agent 学习路线(Java 后端方向)
java·人工智能·学习
菜鸟的学习日记、4 小时前
GPIO的几种模式——以STM32为例
stm32·单片机·嵌入式硬件·gpio
醒醒该学习了!4 小时前
视觉与声音大模型(理论篇)
人工智能
Cloud_Shy6184 小时前
解读《Effective Python 3rd Edition》:从练气到老魔(第五章 Item 33 - 35)
开发语言·人工智能·笔记·python·学习方法
救救孩子把4 小时前
HyperFrames by HeyGen 入门教程
人工智能·视频生成·heygen
JS菌4 小时前
AI Agent 沙箱双层防护体系:从权限过滤到内核隔离的完整实现
前端·人工智能·后端