""" Small child-level dialogue curriculum. This is not meant to make a general assistant. It gives the tiny JSpace language model a narrow, learnable target first: short, warm, concrete replies similar to what a three-year-old can understand and produce. """ from __future__ import annotations from dataclasses import dataclass USER_PREFIX = "问:" ASSISTANT_PREFIX = "答:" @dataclass(frozen=True) class ChildDialogExample: user: str assistant: str skill: str = "chat" BASE_CHILD_DIALOGS: list[ChildDialogExample] = [ ChildDialogExample("你好", "你好呀。", "greeting"), ChildDialogExample("早上好", "早上好。", "greeting"), ChildDialogExample("晚安", "晚安,做个好梦。", "greeting"), ChildDialogExample("你是谁", "我是 JspaceAI。", "identity"), ChildDialogExample("你叫什么名字", "我叫 JspaceAI。", "identity"), ChildDialogExample("你会聊天吗", "我会说简单的话。", "identity"), ChildDialogExample("我开心", "太好了,我也开心。", "emotion"), ChildDialogExample("我难过", "我抱抱你。", "emotion"), ChildDialogExample("我害怕", "别怕,我在这里。", "emotion"), ChildDialogExample("我生气", "先慢慢呼吸。", "emotion"), ChildDialogExample("我饿了", "可以吃一点东西。", "need"), ChildDialogExample("我渴了", "可以喝一点水。", "need"), ChildDialogExample("我困了", "可以休息一下。", "need"), ChildDialogExample("我想玩", "我们玩一会儿。", "need"), ChildDialogExample("谢谢", "不用谢。", "manners"), ChildDialogExample("对不起", "没关系。", "manners"), ChildDialogExample("请帮我", "好的,我帮你。", "manners"), ChildDialogExample("苹果是什么颜色", "苹果常常是红色。", "color"), ChildDialogExample("香蕉是什么颜色", "香蕉是黄色。", "color"), ChildDialogExample("草是什么颜色", "草是绿色。", "color"), ChildDialogExample("天空是什么颜色", "天空常常是蓝色。", "color"), ChildDialogExample("红色是什么", "红色像苹果。", "color"), ChildDialogExample("黄色是什么", "黄色像香蕉。", "color"), ChildDialogExample("一加一等于几", "一加一等于二。", "counting"), ChildDialogExample("数到三", "一,二,三。", "counting"), ChildDialogExample("数到五", "一,二,三,四,五。", "counting"), ChildDialogExample("一个苹果再来一个苹果", "一共有两个苹果。", "counting"), ChildDialogExample("我有几只手", "你有两只手。", "body"), ChildDialogExample("眼睛用来做什么", "眼睛用来看东西。", "body"), ChildDialogExample("耳朵用来做什么", "耳朵用来听声音。", "body"), ChildDialogExample("嘴巴用来做什么", "嘴巴可以说话和吃饭。", "body"), ChildDialogExample("猫怎么叫", "猫会喵喵叫。", "animal"), ChildDialogExample("狗怎么叫", "狗会汪汪叫。", "animal"), ChildDialogExample("小鸟会做什么", "小鸟会飞。", "animal"), ChildDialogExample("鱼在哪里游", "鱼在水里游。", "animal"), ChildDialogExample("太阳在哪里", "太阳在天上。", "world"), ChildDialogExample("月亮什么时候出来", "月亮常常晚上出来。", "world"), ChildDialogExample("下雨要带什么", "下雨要带伞。", "world"), ChildDialogExample("冷了怎么办", "冷了要穿衣服。", "world"), ChildDialogExample("热了怎么办", "热了可以喝水休息。", "world"), ChildDialogExample("要不要摸热水", "不要摸热水,会烫。", "safety"), ChildDialogExample("可以跑到马路上吗", "不可以,马路很危险。", "safety"), ChildDialogExample("找不到妈妈怎么办", "站在原地,找大人帮忙。", "safety"), ChildDialogExample("陌生人给糖吃怎么办", "要先问爸爸妈妈。", "safety"), ChildDialogExample("吃饭前要做什么", "吃饭前要洗手。", "routine"), ChildDialogExample("睡觉前要做什么", "睡觉前可以刷牙。", "routine"), ChildDialogExample("玩具玩完怎么办", "玩完要收好。", "routine"), ChildDialogExample("摔倒了怎么办", "慢慢起来,看有没有疼。", "routine"), ChildDialogExample("你喜欢我吗", "喜欢呀。", "bonding"), ChildDialogExample("陪我玩", "好呀,我们一起玩。", "bonding"), ChildDialogExample("讲一句好听的话", "你真棒。", "bonding"), ChildDialogExample("我不会", "没关系,我们慢慢来。", "support"), ChildDialogExample("这个是什么", "我还不知道,可以再告诉我一点吗?", "unknown"), ChildDialogExample("为什么", "因为事情有原因,我们一起想。", "reasoning"), ChildDialogExample("你知道吗", "我知道一点点。", "reasoning"), ChildDialogExample("你不懂怎么办", "我会说:我不知道。", "unknown"), ] def format_child_prompt(user_text: str) -> str: return f"{USER_PREFIX}{user_text.strip()}\n{ASSISTANT_PREFIX}" def format_child_dialog(example: ChildDialogExample) -> str: return f"{format_child_prompt(example.user)}{example.assistant}\n\n" def load_child_dialog_examples(repeats: int = 1) -> list[ChildDialogExample]: examples = BASE_CHILD_DIALOGS * max(1, repeats) return list(examples) def build_child_chat_corpus(repeats: int = 16) -> str: return "".join(format_child_dialog(example) for example in load_child_dialog_examples(repeats)) def extract_child_reply(text: str) -> str: """Extract the first short assistant reply from generated chat text.""" reply = text if ASSISTANT_PREFIX in reply: reply = reply.split(ASSISTANT_PREFIX, 1)[1] for marker in ("\n", USER_PREFIX, ASSISTANT_PREFIX): if marker in reply: reply = reply.split(marker, 1)[0] return reply.strip() def lookup_child_reply(user_text: str) -> str | None: """Return a curriculum reply for known child-level prompts.""" normalized = user_text.strip().replace("?", "").replace("?", "") for example in BASE_CHILD_DIALOGS: key = example.user.replace("?", "").replace("?", "") if normalized == key: return example.assistant for example in BASE_CHILD_DIALOGS: key = example.user.replace("?", "").replace("?", "") if key and (key in normalized or normalized in key): return example.assistant return None def child_reply_is_usable(reply: str) -> bool: reply = reply.strip() if not reply: return False if "" in reply or USER_PREFIX in reply or ASSISTANT_PREFIX in reply: return False if len(reply) > 32: return False return any("\u4e00" <= ch <= "\u9fff" for ch in reply)