#!/usr/bin/env python3 """ Per-component-type prompt templates registry. Each prompt follows the PRD v2 spec: exact field definitions, extraction rules, output format, and sample. Usage: from prompts.prompt_registry import get_prompt_template, get_input_fields tpl = get_prompt_template("mid_dialog_repeat") fields = get_input_fields("mid_dialog_repeat") """ # ============================================================ # 教研配置文本 → 结构化字段 解析 # ============================================================ # 所有可能的教研配置 section 标记 SECTION_MARKERS = [ "任务标题", "标题", "资源配置", "情境引入", "互动内容", "互动反馈", "后置对话", "互动描述", "学习意义构建", "语音识别热词", ] import re def parse_teaching_config_fields(teaching_config): """ 从教研配置文本中提取结构化字段。 教研配置格式: 【任务标题】 表示大家一起上学 【资源配置】 图片时机:互动内容 【情境引入】 User: Great! 【互动内容】 User: Let's go to school now. (朗读) 【后置对话】 无 Returns: dict: { "标题": "表示大家一起上学", "资源配置": "图片时机:\n互动内容", "情境引入": "User: Great!", "互动内容": "User: Let's go to school now. (朗读)", "后置对话": "无", ... } """ fields = {} # Build regex to split on 【xxx】 markers pattern = re.compile(r'【([^】]+)】') parts = pattern.split(teaching_config) # parts = [before_first_marker, marker1, content1, marker2, content2, ...] i = 1 # skip content before first marker while i < len(parts) - 1: key = parts[i].strip() value = parts[i + 1].strip() # Normalize key names — 同时保留原名和别名 if key in ("任务标题", "标题"): fields["标题"] = value fields["任务标题"] = value else: fields[key] = value i += 2 return fields # ============================================================ # Input field definitions per component type # ============================================================ # Maps cType → list of input field names that should be extracted # and passed as {field} placeholders in the prompt INPUT_FIELDS = { "mid_dialog_repeat": ["ID", "标题", "情境引入", "互动内容", "后置对话", "角色配置", "资源配置"], "mid_dialog_express": ["ID", "标题", "情境引入", "互动内容", "后置对话", "角色配置", "互动反馈", "语音识别热词", "资源配置"], "mid_dialog_choose": ["ID", "标题", "情境引入", "互动内容", "后置对话", "角色配置", "资源配置"], "mid_dialog_select": ["ID", "标题", "情境引入", "互动内容", "后置对话", "角色配置", "资源配置"], "mid_dialog_fillin": ["ID", "标题", "情境引入", "互动内容", "后置对话", "角色配置", "资源配置", "互动反馈"], "mid_dialog_sentence": ["ID", "标题", "情境引入", "互动内容", "后置对话", "角色配置", "互动反馈", "资源配置"], "mid_message_trace": ["ID", "标题", "互动内容", "互动描述", "角色配置"], "mid_message_spell": ["ID", "标题", "互动内容", "互动描述", "角色配置"], "mid_message_combine": ["ID", "标题", "互动内容", "互动描述", "角色配置"], "mid_message_fillin": ["ID", "标题", "互动内容", "互动描述", "角色配置"], "mid_message_word": ["ID", "标题", "互动内容", "互动描述", "角色配置"], "mid_message_sentence": ["ID", "标题", "互动内容", "互动描述", "角色配置"], "mid_image_choose": ["ID", "标题", "情境引入", "互动内容", "互动反馈", "后置对话", "学习意义构建", "角色配置", "互动描述"], "mid_image_multiple": ["ID", "标题", "情境引入", "互动内容", "互动反馈", "后置对话", "学习意义构建", "角色配置", "互动描述"], "mid_image_sequence": ["ID", "标题", "情境引入", "互动内容", "互动反馈", "后置对话", "学习意义构建", "角色配置", "互动描述"], "mid_image_drag": ["ID", "标题", "情境引入", "互动内容", "互动反馈", "后置对话", "学习意义构建", "角色配置", "互动描述"], } def get_input_fields(cType): """Get the list of input field names for a given cType.""" return INPUT_FIELDS.get(cType, ["ID", "标题", "互动内容"]) def build_input_section(cType, cId, parsed_fields, resource_mapping_str=""): """ Build the # 输入 section text for the prompt. Args: cType: component type cId: component ID parsed_fields: dict from parse_teaching_config_fields() resource_mapping_str: pre-formatted角色配置 string like "663-EVA, 653-peter, 658-Vicky" Returns: str: formatted input section """ field_names = get_input_fields(cType) parts = [] for field_name in field_names: if field_name == "ID": parts.append(f"{{ID}}: {cId}") elif field_name == "角色配置": parts.append(f"{{角色配置}}: {resource_mapping_str}") else: value = parsed_fields.get(field_name, "无") if not value: value = "无" parts.append(f"{{{field_name}}}: {value}") return "\n\n".join(parts) # ============================================================ # Prompt templates — one per component type # ============================================================ PROMPT_TEMPLATES = {} # ---------- 对话朗读 ---------- PROMPT_TEMPLATES["mid_dialog_repeat"] = r"""# 字段内容要求 { "cType": "mid_dialog_repeat", //固定 "cId": "{ID}", // 字符串类型 "title": {标题}, "resourceMapping"(抽取出{角色配置}中的全部 name:id映射,id必须为int类型。如果{角色配置}为空,则该字段为空): {"name":id, "name":id} // 样例:{"Ben":465, "Otis":234} "preDialog"(基于{情境引入}抽取,可为空): [ { "type": "npc", "npcName": "xxx", "content": "xxx" }, { "type": "user", "content": "xxx" }, ... ], "imgShowTimingList"(从{资源配置}中抽取,对应关系为:preDialog:情境引入、content:互动内容、feedback:互动反馈、postDialog:后置对话,如果为无则为空[]):["preDialog", "content", "feedback", "postDialog"], "img"({资源配置}中存在图片时机时才有该字段): "{ID}.png", "audioFile"({资源配置}中存在音频载体时才有该字段): "{ID}.mp3", "itemName"({资源配置}中存在音频载体时才有该字段,内容从音频载体中抽取): "xxxxx", "question"(基于{互动内容}抽取,"(朗读)"这两个字不用抽取): { "type": "user", "content": "xxx" }, "postDialog"(基于{后置对话}抽取,可为空): [ { "type": "npc", "npcName": "xxx", "content": "xxx" }, ... ] } # 输出格式: - 整个输出必须在一行内完成,**不要换行**。 - **不要使用 markdown 代码块**(如 ```json)包裹输出。 - 输出内容必须是合法的 JSON 格式,可直接用于 JSON.parse 样例: {"cType":"mid_dialog_repeat","cId":"0000037","title":"表达感谢","resourceMapping":{"Ben":465,"Otis":234},"preDialog":[{"type":"user","content":"And now, I've got a question ready for you."},{"type":"npc","npcName":"Otis","content":"What's that?"},{"type":"user","content":"It's about pirates."}],"imgShowTimingList":["content","feedback"],"img":"0000037.png","question":{"type":"user","content":"Thanks for helping me."},"postDialog":[{"type":"npc","npcName":"Otis","content":"I guess there is something on this spaceship."},{"type":"user","content":"I'm not sure. Maybe?"}]} # 输入 {input_section} # 输出 现在基于输入字段和格式要求,生成***可以直接解析的单行json文本***,***注意前后不要输出任何额外符号!!!***""" # ---------- 对话表达 ---------- PROMPT_TEMPLATES["mid_dialog_express"] = r"""# 字段内容要求 { "cType": "mid_dialog_express", //固定 "cId": {ID}, "title": {标题}, "asrPrompt": {语音识别热词} # 如果内容为"无",则返回"" "resourceMapping"(抽取出{角色配置}中的全部 name:id映射,id必须为int类型。如果{角色配置}为空,则该字段为空): {"name":id, "name":id} // 样例:{"Ben":465, "Otis":234} "preDialog"(基于{情境引入}抽取,可为空): [ { "type": "npc", "npcName": "xxx", "content": "xxx" }, { "type": "user", "content": "xxx" }, ... ], "imgShowTimingList"(从{资源配置}中抽取,对应关系为:preDialog:情境引入、content:互动内容、feedback:互动反馈、postDialog:后置对话,如果为无则为空[]):["preDialog", "content", "feedback", "postDialog"], "img"({资源配置}中存在图片时机时才有该字段): "{ID}.png", "audioFile"({资源配置}中存在音频载体时才有该字段): "{ID}.mp3", "itemName"({资源配置}中存在音频载体时才有该字段,内容从音频载体中抽取): "xxxxx", "tip"({互动内容}中的辅助信息): "xxx", //保留内容中的标点符号 "corFeedback"(基于{互动反馈}的正确抽取,如果没有则为空,即{}): { "type": "npc", "npcName": "xxx", "content": "xxx" }, "errFeedback"(基于{互动反馈}的错误抽取): { "type": "npc", "npcName": "xxx", "content": "xxx." }, "question"(基于{互动内容}中的表达抽取): { "desc": "xxxxx" }, "example"(基于{互动内容}中的示例回答抽取): { "type": "npc", "npcName": "xxx", "content": "xxx" }, "postDialog"(基于{后置对话}抽取,可为空): [ { "type": "npc", "npcName": "xxx", "content": "xxx" }, ... ] } # 输出格式: - 整个输出必须在一行内完成,**不要换行**。 - **不要使用 markdown 代码块**(如 ```json)包裹输出。 - 输出内容必须是合法的 JSON 格式,可直接用于 JSON.parse 样例: {"cType":"mid_dialog_express","cId":"12132","title":"表达感谢","asrPrompt":"thanks,help,door","resourceMapping":{"Ben":465,"Otis":234},"preDialog":[{"type":"npc","npcName":"Sarah","content":"We've seen something. Let's go and have a look right away."},{"type":"user","content":"It seems to be a slogan."}],"imgShowTimingList":["preDialog","conent","feedback","postDialog"],"img":"0000037.png","tip":"key 意思为 \"钥匙\"","corFeedback":{"type":"npc","npcName":"Tom","content":"You got it right."},"errFeedback":{"type":"npc","npcName":"Tom","content":"Wrong!Please continue to make a selection. Look for $key$ in the picture sent by Rebecca and click on it."},"question":{"desc":"对 Boss 表达感谢,比如:\"谢谢你帮我打开门\""},"example":{"type":"user","content":"Thanks for helping me with my luggage. That's true, thanks for helping me with my luggage."},"postDialog":[{"type":"npc","npcName":"Sarah","content":"Let's do as the slogan says."},{"type":"user","content":"It seems to be a slogan."}]} # 输入 {input_section} # 输出 现在基于输入字段和格式要求,生成***可以直接解析的单行json文本***,***注意前后不要输出任何额外符号!!!***""" # ---------- 对话选择 ---------- PROMPT_TEMPLATES["mid_dialog_choose"] = r"""# 字段内容要求 { "cType": "mid_dialog_choose", //固定 "cId": {ID}, "title": {标题}, "resourceMapping"(抽取出{角色配置}中的全部 name:id映射,id必须为int类型。如果{角色配置}为空,则该字段为空): {"name":id, "name":id} // 样例:{"Ben":465, "Otis":234} "preDialog"(基于{情境引入}抽取,可为空): [ { "type": "npc", "npcName": "xxx", "content": "xxx" }, { "type": "user", "content": "xxx" }, ... ], "imgShowTimingList"(从{资源配置}中抽取,对应关系为:preDialog:情境引入、content:互动内容、feedback:互动反馈、postDialog:后置对话,如果为无则为空[]):["preDialog", "content", "feedback", "postDialog"], "img"({资源配置}中存在图片时机时才有该字段): "{ID}.png", "audioFile"({资源配置}中存在音频载体时才有该字段): "{ID}.mp3", "itemName"({资源配置}中存在音频载体时才有该字段,内容从音频载体中抽取): "xxxxx", "optionList"(基于{互动内容}中的选项抽取): [ { "option": "My seat number is 3.", "needAudio":true, // 如果选项后有"(音频)"字样,则为true,否则为false }, { "option": "My seat number is 4.", "needAudio":true, // 如果选项后有"(音频)"字样,则为true,否则为false } ], "answer"(基于{互动内容}中的选项抽取,正确选项后有(正确)进行标识): [0], "corFeedback"(基于{互动内容}中选项的反馈抽取,注意是正确选项的反馈,如果反馈为无则为空,即{}): { "type": "npc", "npcName": "xxx", "content": "xxx" }, "errFeedback"(基于{互动内容}中选项的反馈抽取,注意是错误选项的反馈,如果反馈为无则为空,即{}): { "type": "npc", "npcName": "xxx", "content": "xxx." }, "postDialog"(基于{后置对话}抽取,可为空): [ { "type": "npc", "npcName": "xxx", "content": "xxx" }, ... ] } # 输出格式: - 整个输出必须在一行内完成,**不要换行**。 - **不要使用 markdown 代码块**(如 ```json)包裹输出。 - 输出内容必须是合法的 JSON 格式,可直接用于 JSON.parse 样例: {"cType":"mid_dialog_choose","cId":"0000037","title":"分析声音来源","resourceMapping":{"Ben":465,"Otis":234},"preDialog":[{"type":"user","content":"And now, I've got a question ready for you."},{"type":"npc","npcName":"Otis","content":"What's that?"},{"type":"user","content":"It's about pirates."}],"imgShowTimingList":["content","feedback"],"img":"0000037.png","optionList":[{"option":"My seat number is 3."},{"option":"My seat number is 4."}],"answer":[0],"corFeedback":{"type":"npc","npcName":"Tom","content":"You got it right."},"errFeedback":{"type":"npc","npcName":"Tom","content":"Wrong!Please continue to make a selection."},"postDialog":[{"type":"npc","npcName":"Otis","content":"I guess there is something on this spaceship."},{"type":"user","content":"I'm not sure. Maybe?"}]} # 输入 {input_section} # 输出 现在基于输入字段和格式要求,生成***可以直接解析的单行json文本***,***注意前后不要输出任何额外符号!!!***""" # ---------- 对话选读 ---------- PROMPT_TEMPLATES["mid_dialog_select"] = r"""# 字段内容要求 { "cType": "mid_dialog_select", //固定 "cId": {ID}, "title": {标题}, "resourceMapping"(抽取出{角色配置}中的全部 name:id映射,id必须为int类型。如果{角色配置}为空,则该字段为空): {"name":id, "name":id} // 样例:{"Ben":465, "Otis":234} "preDialog"(基于{情境引入}抽取,可为空): [ { "type": "npc", "npcName": "xxx", "content": "xxx" }, { "type": "user", "content": "xxx" }, ... ], "imgShowTimingList"(从{资源配置}中抽取,对应关系为:preDialog:情境引入、content:互动内容、feedback:互动反馈、postDialog:后置对话,如果为无则为空[]):["preDialog", "content", "feedback", "postDialog"], "img"({资源配置}中存在图片时机时才有该字段): "{ID}.png", "audioFile"({资源配置}中存在音频载体时才有该字段): "{ID}.mp3", "itemName"({资源配置}中存在音频载体时才有该字段,内容从音频载体中抽取): "xxxxx", "optionList"(基于{互动内容}中的选项抽取,如果选项下反馈为无,则feedback为空,即{};如果选项后有"(音频)",则每个选项的"needAudio"为true,否则为false): [ { "option": "xxxxxx", "needAudio":xxx, "feedback": { "type": "xxx", "npcName": "xxx", "content": "xxxxxxxxxxx" } }, { "option": "xxxxxx", "needAudio":xxx, "feedback": { "type": "xxx", "npcName": "xxx", "content": "xxxxxxxxxxx" } }, ...... ], "postDialog"(基于{后置对话}抽取,可为空): [ { "type": "npc", "npcName": "xxx", "content": "xxx" }, ... ] } # 输出格式: - 整个输出必须在一行内完成,**不要换行**。 - **不要使用 markdown 代码块**(如 ```json)包裹输出。 - 输出内容必须是合法的 JSON 格式,可直接用于 JSON.parse 样例: {"cType":"mid_dialog_select","cId":"0000037","title":"分析声音来源","resourceMapping":{"Ben":465,"Otis":234},"preDialog":[{"type":"user","content":"And now, I've got a question ready for you."},{"type":"npc","npcName":"Otis","content":"What's that?"},{"type":"user","content":"It's about pirates."}],"imgShowTimingList":["content","feedback"],"img":"0000037.png","optionList":[{"option":"That's great! I'm going to ask Otis and Skely to go together!","needAudio":false,"feedback":{"type":"npc","npcName":"Skylar","content":"Huh? You talk big too!"}},{"option":"Interesting! I can go on this trip alone.","needAudio":false,"feedback":{"type":"npc","npcName":"Skylar","content":"wrong!"}},{"option":"It's no fun. I'd better not participate.","needAudio":false,"feedback":{"type":"npc","npcName":"Skylar","content":"ok!"}}],"postDialog":[{"type":"npc","npcName":"Otis","content":"I guess there is something on this spaceship."},{"type":"user","content":"I'm not sure. Maybe?"}]} # 输入 {input_section} # 输出 现在基于输入字段和格式要求,生成***可以直接解析的单行json文本***,***注意前后不要输出任何额外符号!!!***""" # ---------- 对话挖空 ---------- PROMPT_TEMPLATES["mid_dialog_fillin"] = r"""# 字段内容要求 { "cType": "mid_dialog_fillin", //固定 "cId": "{ID}", // 字符串类型 "title": {标题}, "resourceMapping"(抽取出{角色配置}中的全部 name:id映射,id必须为int类型。如果{角色配置}为空,则该字段为空): {"name":id, "name":id} // 样例:{"Ben":465, "Otis":234} "preDialog"(基于{情境引入}抽取,可为空): [ { "type": "npc", "npcName": "xxx", "content": "xxx" }, { "type": "user", "content": "xxx" }, ... ], "imgShowTimingList"(从{资源配置}中抽取,对应关系为:preDialog:情境引入、content:互动内容、feedback:互动反馈、postDialog:后置对话,如果为无则为空[]):["preDialog", "content", "feedback", "postDialog"], "img"({资源配置}中存在图片时机时才有该字段): "{ID}.png", "audioFile"({资源配置}中存在音频载体时才有该字段): "{ID}.mp3", "itemName"({资源配置}中存在音频载体时才有该字段,内容从音频载体中抽取): "xxxxx", "question"(从{互动内容}中抽取): { "type": "user", "desc": "This is my picture,It's ___, ___ and ___. ", "content": "This is my picture,It's blue, gray and orange." // 将{互动内容}中各个内容组的正确选项填入到句子中组成的完整句子 }, "optionGroupList"(从{互动内容}中的内容组抽取,正确选项使用(正确)进行标识,抽取时不要将"(正确)"也抽取出来): [ { "optionList": [{ "option": "bule", "needAudio":true, // {互动内容}题干后如果有"(音频)"字样,则为true,否则为false }, { "option": "black", "needAudio":true, // {互动内容}题干后如果有"(音频)"字样,则为true,否则为false } ], "answer": [1] }, { "optionList": [{ "option": "gray", "needAudio":true, // {互动内容}题干后如果有"(音频)"字样,则为true,否则为false }, { "option": "green", "needAudio":true, // {互动内容}题干后如果有"(音频)"字样,则为true,否则为false } ], "answer": [0] } ], "corFeedback"(基于{互动反馈}的正确反馈抽取,如果为无则为空,即{}): { "type": "npc", "npcName": "Tom", "content": "You got it right." }, "errFeedback"(基于{互动反馈}的错误反馈抽取,如果为无则为空,即{}): { "type": "npc", "npcName": "Tom", "content": "Wrong!Please continue to make a selection." }, "postDialog"(基于{后置对话}抽取,可为空): [ { "type": "npc", "npcName": "xxx", "content": "xxx" }, ... ] } # 输出格式: - 整个输出必须在一行内完成,**不要换行**。 - **不要使用 markdown 代码块**(如 ```json)包裹输出。 - 输出内容必须是合法的 JSON 格式,可直接用于 JSON.parse 样例: {"cType":"mid_dialog_fillin","cId":"0000037","title":"分析声音来源","resourceMapping":{"Ben":465,"Otis":234},"preDialog":[{"type":"user","content":"And now, I've got a question ready for you."},{"type":"npc","npcName":"Otis","content":"What's that?"},{"type":"user","content":"It's about pirates."}],"imgShowTimingList":["content","feedback"],"img":"0000037.png","question":{"type":"user","content":"This is my picture,It's blue, gray and orange.","desc":"This is my picture,It's ___,___ and orange"},"optionGroupList":[{"optionList":[{"option":"bule"},{"option":"black"}],"answer":[1]},{"optionList":[{"option":"gray"},{"option":"green"}],"answer":[0]}],"corFeedback":{"type":"npc","npcName":"Tom","content":"You got it right."},"errFeedback":{"type":"npc","npcName":"Tom","content":"Wrong!Please continue to make a selection."},"postDialog":[{"type":"npc","npcName":"Otis","content":"I guess there is something on this spaceship."},{"type":"user","content":"I'm not sure. Maybe?"}]} # 输入 {input_section} # 输出 现在基于输入字段和格式要求,生成***可以直接解析的单行json文本***,***注意前后不要输出任何额外符号!!!***""" # ---------- 对话组句 ---------- PROMPT_TEMPLATES["mid_dialog_sentence"] = r"""# 字段内容要求 { "cType": "mid_dialog_sentence", //固定 "cId": {ID}, // 字符串类型 "title": {标题}, "resourceMapping"(抽取出{角色配置}中的全部 name:id映射,id必须为int类型。如果{角色配置}为空,则该字段为空): {"name":id, "name":id} // 样例:{"Ben":465, "Otis":234} "preDialog"(基于{情境引入}抽取,可为空): [ { "type": "npc", "npcName": "xxx", "content": "xxx" }, { "type": "user", "content": "xxx" }, ... ], "imgShowTimingList"(从{资源配置}中抽取,对应关系为:preDialog:情境引入、content:互动内容、feedback:互动反馈、postDialog:后置对话,如果为无则为空[]):["preDialog", "content", "feedback", "postDialog"], "img"({资源配置}中存在图片时机时才有该字段): "{ID}.png", "audioFile"({资源配置}中存在音频载体时才有该字段): "{ID}.mp3", "itemName"({资源配置}中存在音频载体时才有该字段,内容从音频载体中抽取): "xxxxx", "question"(基于{互动内容}抽取): { "desc": "xxxxx", // {互动内容}中的题目 "content": "xxxxxxxxxxxx" // {互动内容}中的答案 }, "optionList"(基于{互动内容}的选项抽取): [ { "option": "me", "needAudio":true, // {互动内容}题目后如果有"(音频)"字样,则为true,否则为false }, { "option": "let", "needAudio":true, }, { "option": "some trouble", "needAudio":true, }, { "option": "make", "needAudio":true, } ] "answer"(基于{互动内容}的答案抽取): [1,0,3,2], // 根据答案生成正确option的索引 "tip"({互动内容}中的辅助信息): "xxx", //保留内容中的标点符号 "corFeedback"(基于{互动反馈}的正确抽取,如果没有则为空,即{}): { "type": "npc", "npcName": "xxx", "content": "xxx" }, "errFeedback"(基于{互动反馈}的错误抽取): { "type": "npc", "npcName": "xxx", "content": "xxx." }, "postDialog"(基于{后置对话}抽取,可为空): [ { "type": "npc", "npcName": "xxx", "content": "xxx" }, ... ] } # 输出格式: - 整个输出必须在一行内完成,**不要换行**。 - **不要使用 markdown 代码块**(如 ```json)包裹输出。 - 输出内容必须是合法的 JSON 格式,可直接用于 JSON.parse 样例: {"cType":"mid_dialog_sentence","cId":"0000002","title":"向 Rebecca 说明方法","resourceMapping":{"Ben":465,"Otis":234},"preDialog":[{"content":"So? Did you figure it out?","npcName":"Rebecca","type":"npc"},{"content":"These words are all over the place...","npcName":"Rebecca","type":"npc"}],"imgShowTimingList":["content","feedback"],"img":"0000002.png","question":{"content":"Let me make some trouble.","desc":"解析秘密指令"},"optionList":[{"option":"me"},{"option":"let"},{"option":"some trouble"},{"option":"make"}],"answer":[1,0,3,2],"tip":"句子是 let 引导的祈使句","corFeedback":{"content":"Got it.","npcName":"Rebecca","type":"npc"},"errFeedback":{"content":"I'm still not sure what this means.","npcName":"Rebecca","type":"npc"},"postDialog":[]} # 输入 {input_section} # 输出 现在基于输入字段和格式要求,生成***可以直接解析的单行json文本***,***注意前后不要输出任何额外符号!!!***""" # ---------- 信息描写 ---------- PROMPT_TEMPLATES["mid_message_trace"] = r"""# 字段内容要求 { "cType": "mid_message_trace", //固定 "cId": {ID}, "title": {标题}, "resourceMapping"(抽取出{角色配置}中的全部 name:id映射,id必须为int类型。如果{角色配置}为空,则该字段为空): {"name":id, "name":id} // 样例:{"Ben":465, "Otis":234} "cDesc"(基于{互动描述}抽取): "xxx", "question"(基于{互动内容}抽取): { "desc": "xxxxx", // {互动内容}中的任务描述 }, "trace"(基于{互动内容}中的答案抽取): "xxx", "img": "{ID}.png", "inputSet": [] //固定 } # 输出格式: - 整个输出必须在一行内完成,**不要换行**。 - **不要使用 markdown 代码块**(如 ```json)包裹输出。 - 输出内容必须是合法的 JSON 格式,可直接用于 JSON.parse 样例: {"cType":"mid_message_trace","cId":"0000001","title":"填写菜单","cDesc":"You filled in the menu with the chosen fruits. (你在菜单上填好了选中的水果。)","question":{"desc":"在菜单上描写出需要选择的水果"},"trace":"help","img":"0000001.png","inputSet":[]} # 输入 {input_section} # 输出 现在基于输入字段和格式要求,生成***可以直接解析的单行json文本***,***注意前后不要输出任何额外符号!!!***""" # ---------- 信息拼词 ---------- PROMPT_TEMPLATES["mid_message_spell"] = r"""# 字段内容要求 { "cType": "mid_message_spell", //固定 "cId": {ID}, "title": {标题}, "resourceMapping"(抽取出{角色配置}中的全部 name:id映射,id必须为int类型。如果{角色配置}为空,则该字段为空): {"name":id, "name":id} // 样例:{"Ben":465, "Otis":234} "cDesc"(基于{互动描述}抽取): "xxx", "question"(基于{互动内容}抽取): { "desc": "xxxxx", // {互动内容}中的任务描述 }, "tip"(基于{互动内容}中的辅助信息抽取): "xxx", "inputConfig": [ { "stem"(基于{互动内容}中的题干抽取): "xxxx", "value"(基于{互动内容}中的答案抽取): "xxxx" } ], "stemList"((基于{互动内容}中的选项抽取)): [xxxxx], "img": "{ID}.png", "inputSet": [] //固定 } # 输出格式: - 整个输出必须在一行内完成,**不要换行**。 - **不要使用 markdown 代码块**(如 ```json)包裹输出。 - 输出内容必须是合法的 JSON 格式,可直接用于 JSON.parse 样例: {"cType":"mid_message_spell","cId":"0000001","title":"填写菜单","cDesc":"You spelled the fruit name correctly on the menu. (你在菜单上正确拼出了水果的名字。)","question":{"desc":"选择合适的字母拼出想要的水果"},"tip":"第二个字母是 r 哦,再想想最后一个空应该填什么吧","inputConfig":[{"stem":"G(2)pe","value":"ra"}],"stemList":["h","a","r","l","e"],"img":"0000001.png","inputSet":[]} # 输入 {input_section} # 输出 现在基于输入字段和格式要求,生成***可以直接解析的单行json文本***,***注意前后不要输出任何额外符号!!!***""" # ---------- 信息组句 ---------- PROMPT_TEMPLATES["mid_message_combine"] = r"""# 字段内容要求 { "cType": "mid_message_combine", //固定 "cId": {ID}, "title": {标题}, "resourceMapping"(抽取出{角色配置}中的全部 name:id映射,id必须为int类型。如果{角色配置}为空,则该字段为空): {"name":id, "name":id} // 样例:{"Ben":465, "Otis":234} "cDesc"(基于{互动描述}抽取): "xxx", "question"(基于{互动内容}抽取): { "desc": "xxxxx", // {互动内容}中的任务描述 }, "tip"(基于{互动内容}中的辅助信息抽取): "xxx", "optionList"(基于{互动内容}中的选项抽取): [ { "option": "xxxx" }, { "option": "xxxx" } ... ], "answer"(基于{互动内容}中的答案生成,根据答案抽取出optionList中对应选项的索引): [xxxxx], "img": "{ID}.png", "inputSet": [] //固定 } # 输出格式: - 整个输出必须在一行内完成,**不要换行**。 - **不要使用 markdown 代码块**(如 ```json)包裹输出。 - 输出内容必须是合法的 JSON 格式,可直接用于 JSON.parse 样例: {"cType":"mid_message_combine","cId":"0000001","title":"提交身份证件","cDesc":"You submitted the required ID details successfully online. (你成功提交了所需的身份证件信息。)","question":{"desc":"选择正确的选项组合出必要的填写内容"},"tip":" ","optionList":[{"option":"I am"},{"option":"a Pioneer!"},{"option":"going to be"}],"answer":[0,2,1],"img":"0000001.png","inputSet":[]} # 输入 {input_section} # 输出 现在基于输入字段和格式要求,生成***可以直接解析的单行json文本***,***注意前后不要输出任何额外符号!!!***""" # ---------- 信息补词 ---------- PROMPT_TEMPLATES["mid_message_fillin"] = r"""# 字段内容要求 { "cType": "mid_message_fillin", //固定 "cId": {ID}, "title": {标题}, "resourceMapping"(抽取出{角色配置}中的全部 name:id映射,id必须为int类型。如果{角色配置}为空,则该字段为空): {"name":id, "name":id} // 样例:{"Ben":465, "Otis":234} "cDesc"(基于{互动描述}抽取): "xxx", "question"(基于{互动内容}抽取): { "desc": "xxxxx", // {互动内容}中的任务描述 }, "tip"(基于{互动内容}中的辅助信息抽取): "xxx", "inputConfig": [ { "stem"(基于{互动内容}中的题干抽取): "xxxx", "value"(基于{互动内容}中的答案抽取): "xxxx" } ], "img": "{ID}.png", "inputSet": [] //固定 } # 输出格式: - 整个输出必须在一行内完成,**不要换行**。 - **不要使用 markdown 代码块**(如 ```json)包裹输出。 - 输出内容必须是合法的 JSON 格式,可直接用于 JSON.parse 样例: {"cType":"mid_message_fillin","cId":"0000001","title":"填写学习旅行申请单","cDesc":"You filled in the study trip application with needed words. (你在学习旅行申请单上填好了必要的单词。)","question":{"desc":"在申请单上填上必要的单词"},"tip":"需要填写的是\"知识\"的单词","inputConfig":[{"stem":"K(3)ledge","value":"new"}],"img":"0000001.png","inputSet":[]} # 输入 {input_section} # 输出 现在基于输入字段和格式要求,生成***可以直接解析的单行json文本***,***注意前后不要输出任何额外符号!!!***""" # ---------- 信息填词 ---------- PROMPT_TEMPLATES["mid_message_word"] = r"""# 字段内容要求 { "cType": "mid_message_word", //固定 "cId": {ID}, "title": {标题}, "resourceMapping"(抽取出{角色配置}中的全部 name:id映射,id必须为int类型。如果{角色配置}为空,则该字段为空): {"name":id, "name":id} // 样例:{"Ben":465, "Otis":234} "cDesc"(基于{互动描述}抽取): "xxx", "question"(基于{互动内容}抽取): { "desc": "xxxxx", // {互动内容}中的任务描述 }, "tip"(基于{互动内容}中的辅助信息抽取): "xxx", "answer"(基于{互动内容}中的答案抽取): [xxxxx], "img": "{ID}.png", "inputSet": [] //固定 } # 输出格式: - 整个输出必须在一行内完成,**不要换行**。 - **不要使用 markdown 代码块**(如 ```json)包裹输出。 - 输出内容必须是合法的 JSON 格式,可直接用于 JSON.parse 样例: {"cType":"mid_message_word","cId":"0000001","title":"填写学习旅行申请单","cDesc":"You filled in the study trip application with the needed words. (你在学习旅行申请单上填好了必要的单词。)","question":{"desc":"在申请单上填上必要的单词"},"tip":"需要填写的是\"知识\"的单词","answer":["knowledge","information","understanding"],"img":"0000001.png","inputSet":[]} # 输入 {input_section} # 输出 现在基于输入字段和格式要求,生成***可以直接解析的单行json文本***,***注意前后不要输出任何额外符号!!!***""" # ---------- 信息填句 ---------- PROMPT_TEMPLATES["mid_message_sentence"] = r"""# 字段内容要求 { "cType": "mid_message_sentence", //固定 "cId": {ID}, "title": {标题}, "resourceMapping"(抽取出{角色配置}中的全部 name:id映射,id必须为int类型。如果{角色配置}为空,则该字段为空): {"name":id, "name":id} // 样例:{"Ben":465, "Otis":234} "cDesc"(基于{互动描述}抽取): "xxx", "question"(基于{互动内容}抽取): { "desc": "xxxxx", // {互动内容}中的任务描述 }, "tip"(基于{互动内容}中的辅助信息抽取): "xxx", "answerHint"(基于{互动内容}中的推荐答案抽取): "xxxxx", "img": "{ID}.png", "inputSet": [] //固定 } # 输出格式: - 整个输出必须在一行内完成,**不要换行**。 - **不要使用 markdown 代码块**(如 ```json)包裹输出。 - 输出内容必须是合法的 JSON 格式,可直接用于 JSON.parse 样例: {"cType":"mid_message_sentence","cId":"0000001","title":"填写学习旅行申请单","cDesc":"You copied \"The main purpose of this tour\" onto the application form. (你把\"The main purpose of this tour\"抄写到了申请单上。)","question":{"desc":"请抄写 The main purpose of this tour"},"tip":"你可以使用 The main purpose of this tour is...","answerHint":"The main purpose of this tour is to learn knowledge about local traditional crafts.","img":"0000001.png","inputSet":[]} # 输入 {input_section} # 输出 现在基于输入字段和格式要求,生成***可以直接解析的单行json文本***,***注意前后不要输出任何额外符号!!!***""" # ---------- 图片单选 ---------- PROMPT_TEMPLATES["mid_image_choose"] = r"""# 字段内容要求 { "cType": "mid_image_choose",//固定值 "cId": "{ID}", "title": {标题}, "meaning": {学习意义构建}, // 如果为"无"则为空字符串"" "resourceMapping"(抽取出{角色配置}中的全部 name:id映射 可为空。id必须为int类型): {"name":id, "name":id} "question"(基于{互动内容}抽取):{ "desc":"xxx", "content":"xxx" // 如果有"(音频)"字样,则有该字段,内容和"desc"相同;如果没有"(音频)"字样,则没有该字段!注意"(音频)"不要提取出来! }, "imageInfo": { "questionImg": "{ID}_question.png", "answerImg": "{ID}_answer.png", }, "optionList"(基于{互动内容}中的选项抽取): [ { "option": "{ID}_option_00.png", }, { "option": "{ID}_option_01.png", }, ...... ], "answer"(基于{互动内容}中的答案抽取):[xx], "preDialog"(基于{情境引入}抽取): [...], "tip"(基于{互动内容}中的辅助信息抽取): "xxx", "corFeedback"(基于{互动反馈}中的正确抽取,如果为无则该字段整体为空,即{}): { "type": "npc", "npcName": "xxx", "content": "xxx" }, "errFeedback"(基于{互动反馈}的错误抽取): { "type": "npc", "npcName": "xxx", "content": "xxx" }, "postDialog"(基于{后置对话}抽取): [...], "cDesc": "xxx", // {互动描述}的全部内容 } # 输出格式: 单行json。 样例: {"cType":"mid_image_choose","cId":"12132","title":"猜Chloe的意图","meaning":"","resourceMapping":{"Ben":465,"Otis":234},"question":{"desc":"Look for $key$ in the picture sent by Rebecca and click on it."},"imageInfo":{"questionImg":"0000001_question.png","answerImg":"0000001_answer.png"},"optionList":[{"option":"00000001_option_00.png"},{"option":"00000001_option_01.png"}],"answer":[1],"preDialog":[{"type":"npc","npcName":"Sarah","content":"We've seen something. Let's go and have a look right away."},{"type":"user","content":"It seems to be a slogan."}],"tip":"key 意思为 \"钥匙\"。","corFeedback":{"type":"npc","npcName":"Tom","content":"You got it right."},"errFeedback":{"type":"npc","npcName":"Tom","content":"Wrong!Look for $key$ in the picture sent by Rebecca and click on it."},"postDialog":[{"type":"npc","npcName":"Sarah","content":"Let's do as the slogan says."},{"type":"user","content":"It seems to be a slogan."}],"cDesc":"You pressed the clean button on the drone. (你按下了无人机的清理按键。)"} # 输入 {input_section} # 输出 现在基于输入字段和格式要求,生成***可以直接解析的单行json文本***,***注意前后不要输出任何额外符号!!!***""" # ---------- 图片多选 ---------- PROMPT_TEMPLATES["mid_image_multiple"] = r"""# 字段内容要求 { "cType": "mid_image_multiple",//固定值 "cId": "{ID}", // 类型为字符串 "title": {标题}, "meaning": {学习意义构建}, // 如果为"无"则为空字符串"" "resourceMapping"(抽取出{角色配置}中的全部 name:id映射 可为空。id必须为int类型): {"name":id, "name":id} "question"(基于{互动内容}抽取):{ "desc":"xxx", "content":"xxx" // 如果有"(音频)"字样,则有该字段,内容和"desc"相同;如果没有"(音频)"字样,则没有该字段! }, "imageInfo": { "questionImg": "{ID}_question.png", "answerImg": "{ID}_answer.png", }, "optionList"(基于{互动内容}中的选项抽取): [ {"option": "{ID}_option_00.png"}, {"option": "{ID}_option_01.png"}, ...... ], "answer"(基于{互动内容}中的答案抽取):[xx,xx,...], "preDialog"(基于{情境引入}抽取): [...], "tip"(基于{互动内容}中的辅助信息抽取): "xxx", "corFeedback"(基于{互动反馈}抽取,如果没有正确反馈则为空,即{}): {...}, "errFeedback"(基于{互动反馈}抽取): {...}, "postDialog"(基于{后置对话}抽取): [...], "cDesc": "xxx", // {互动描述}的全部内容 } # 输出格式: 单行json。 样例: {"cType":"mid_image_multiple","cId":"12132","title":"猜Chloe的意图","meaning":"","resourceMapping":{"Ben":465,"Otis":234},"question":{"desc":"Look for $key$ in the picture sent by Rebecca and click on it."},"imageInfo":{"questionImg":"0000001_question.png","answerImg":"0000001_answer.png"},"optionList":[{"option":"00000001_option_00.png"},{"option":"00000001_option_01.png"},{"option":"00000001_option_02.png"},{"option":"00000001_option_03.png"},{"option":"00000001_option_04.png"}],"answer":[1,3,4],"preDialog":[{"type":"npc","npcName":"Sarah","content":"We've seen something. Let's go and have a look right away."},{"type":"user","content":"It seems to be a slogan."}],"tip":"key 意思为 \"钥匙\"","corFeedback":{"type":"npc","npcName":"Tom","content":"You got it right."},"errFeedback":{"type":"npc","npcName":"Tom","content":"Wrong!Look for $key$ in the picture sent by Rebecca and click on it."},"postDialog":[{"type":"npc","npcName":"Sarah","content":"Let's do as the slogan says."},{"type":"user","content":"It seems to be a slogan."}],"cDesc":"You pressed the clean button on the drone. (你按下了无人机的清理按键。)"} # 输入 {input_section} # 输出 现在基于输入字段和格式要求,生成***可以直接解析的单行json文本***,***注意前后不要输出任何额外符号!!!***""" # ---------- 图片有序 ---------- PROMPT_TEMPLATES["mid_image_sequence"] = r"""# 字段内容要求 { "cType": "mid_image_sequence",//固定值 "cId": {ID}, "title": {标题}, "meaning": {学习意义构建}, // 如果为"无"则为空字符串"" "resourceMapping"(抽取出{角色配置}中的全部 name:id映射 可为空。id必须为int类型): {"name":id, "name":id} "question"(基于{互动内容}抽取):{ "desc":"xxx" }, "imageInfo": { "questionImg": "{ID}_question.png", "answerImg": "{ID}_answer.png", }, "optionList"(请严格基于{互动内容}中给出的选项进行抽取,生成的结果数量必须与选项数量**完全一致**,**不得遗漏**任何选项。): [ {"option": "{ID}_option_00.png"}, {"option": "{ID}_option_01.png"}, ...... ], "answer"(基于{互动内容}中的答案抽取):[xx,xx...], "preDialog"(基于{情境引入}抽取): [...], "tip"(基于{互动内容}中的辅助信息抽取): "xxx", "corFeedback"(基于{互动反馈}抽取"正确",如果没有正确反馈则为空,即{}): {...}, "errFeedback"(基于{互动反馈}抽取"错误"): {...}, "postDialog"(基于{后置对话}抽取): [...], "cDesc": "xxx", // {互动描述}的全部内容 } # 输出格式: 单行json。 样例: {"cType":"mid_image_sequence","cId":"12132","title":"猜Chloe的意图","meaning":"","resourceMapping":{"Ben":465,"Otis":234},"question":{"desc":"Look for $key$ in the picture."},"imageInfo":{"questionImg":"0000001_question.png","answerImg":"0000001_answer.png"},"optionList":[{"option":"00000001_option_00.png"},{"option":"00000001_option_01.png"},{"option":"00000001_option_02.png"},{"option":"00000001_option_03.png"},{"option":"00000001_option_04.png"}],"answer":[1,3,4],"preDialog":[{"type":"npc","npcName":"Sarah","content":"We've seen something."},{"type":"user","content":"It seems to be a slogan."}],"tip":"key 意思为 \"钥匙\"","corFeedback":{"type":"npc","npcName":"Tom","content":"You got it right."},"errFeedback":{"type":"npc","npcName":"Tom","content":"Wrong!"},"postDialog":[{"type":"npc","npcName":"Sarah","content":"Let's do as the slogan says."}],"cDesc":"You found the ruler, hammer and screwdriver in order. (你依次找到了尺子、锤子和螺丝刀。)"} # 输入 {input_section} # 输出 现在基于输入字段和格式要求,生成***可以直接解析的单行json文本***,***注意前后不要输出任何额外符号!!!***""" # ---------- 图片拖拽 ---------- PROMPT_TEMPLATES["mid_image_drag"] = r"""# 字段内容要求 { "cType": "mid_image_drag",//固定值 "cId": "{ID}", // 类型为字符串 "title": {标题}, "meaning": {学习意义构建}, // 如果为"无"则为空字符串"" "resourceMapping"(抽取出{角色配置}中的全部 name:id映射 可为空。id必须为int类型): {"name":id, "name":id} "question"(基于{互动内容}抽取):{ "desc":"xxx", // 如果有"(音频)"字样,在抽取时略过"(音频)" "content":"xxx" // 如果有"(音频)"字样,则有该字段,内容和"desc"相同;如果没有"(音频)"字样,则没有该字段! }, "imageInfo": { "questionImg": "{ID}_question.png", "answerImg": "{ID}_answer.png", }, "optionList"(基于{互动内容}中的选项抽取): [ {"option": "{ID}_option_00.png"}, {"option": "{ID}_option_01.png"}, ...... ], "answer"(基于{互动内容}中的答案抽取):[xx,xx,...], "preDialog"(基于{情境引入}抽取): [...], "tip"(基于{互动内容}中的辅助信息抽取): "xxx", "corFeedback"(基于{互动反馈}抽取,如果没有正确反馈则为空,即{}): {...}, "errFeedback"(基于{互动反馈}抽取): {...}, "postDialog"(基于{后置对话}抽取): [...], "cDesc": "xxx", // {互动描述}的全部内容 } # 输出格式: 单行json。 样例: {"cType":"mid_image_drag","cId":"12132","title":"猜Chloe的意图","meaning":"","resourceMapping":{"Ben":465,"Otis":234},"question":{"desc":"Look for $key$ in the picture sent by Rebecca and click on it."},"imageInfo":{"questionImg":"0000001_question.png","answerImg":"0000001_answer.png"},"optionList":[{"option":"00000001_option_00.png"},{"option":"00000001_option_01.png"},{"option":"00000001_option_02.png"},{"option":"00000001_option_03.png"},{"option":"00000001_option_04.png"}],"answer":[1,3,4],"preDialog":[{"type":"npc","npcName":"Sarah","content":"We've seen something."},{"type":"user","content":"It seems to be a slogan."}],"tip":"key 意思为 \"钥匙\"","corFeedback":{"type":"npc","npcName":"Tom","content":"You got it right."},"errFeedback":{"type":"npc","npcName":"Tom","content":"Wrong!"},"postDialog":[{"type":"npc","npcName":"Sarah","content":"Let's do as the slogan says."}],"cDesc":"You pressed the clean button on the drone. (你按下了无人机的清理按键。)"} # 输入 {input_section} # 输出 现在基于输入字段和格式要求,生成***可以直接解析的单行json文本***,***注意前后不要输出任何额外符号!!!***""" # ============================================================ # cDesc 互动描述生成 prompt 模板 # ============================================================ CDESC_MESSAGE_TYPES = { "mid_message_trace", "mid_message_spell", "mid_message_combine", "mid_message_fillin", "mid_message_word", "mid_message_sentence", } CDESC_IMAGE_TYPES = { "mid_image_choose", "mid_image_multiple", "mid_image_sequence", "mid_image_drag", } CDESC_TYPES = CDESC_MESSAGE_TYPES | CDESC_IMAGE_TYPES CDESC_PROMPT_MESSAGE = """# 任务目标 你是一个儿童英语学习内容生成助手。现在有一个物品互动配置,需要将其转写为对话记录中的一句叙事化描述,用于回顾剧情。 # 输入信息 - 互动名称:{互动名称} - 互动内容:{互动内容} # 生成要求 1. **输出一句自然叙事**,表现为角色完成了物品操作或选择。 2. **以英文为主,中文放在括号中**,英文和中文必须在一句话里。 - 示例:You picked up the drone. (你捡起了无人机。) 3. **必须使用正确答案的词汇**来生成叙事,不要出现错误选项。 4. **避免教学感**,不能出现"题目""选项""正确答案"等表述。 5. **动作简洁、贴近剧情**,长度控制在 8–15 个英文词。 6. 输出时只返回最终的一句话结果,不要解释。 # 输出示例 输入: - 互动名称:捡起地上的无人机 - 互动题目:I need to "拾起" the drone on the ground. - 互动选项:A.pick out B.pick up - 正确答案:B - 选项描述:A.phr. v. 挑选 B.phr. v.捡起 输出: You picked up the drone on the ground. (你捡起了地上的无人机。)""" CDESC_PROMPT_IMAGE = """# 任务目标 你是一个儿童英语学习内容生成助手。现在有一个图片互动配置,需要将其转写为对话记录中的一句叙事化描述,用于回顾剧情。 # 背景知识 图片互动组件的定义: - 图片互动要求孩子在一张图像中点击特定位置完成任务。 - 任务通常以英文给出一个目标单词,孩子需通过理解该词的含义,在图中找出其对应位置。 - 交互方式是直接点击图片中对应区域,不提供文字选项。 - 重点训练孩子对词义的理解与视觉对应判断能力,强调中英词汇的实际配对与应用判断。 在对话记录中: - 情境引入对话、互动反馈、后置对话会原样保留。 - 互动内容(即孩子在图中找到目标物品的过程)需要转写为一句自然的叙事描述。 # 输入信息 - 互动名称:{互动名称} - 情境引入对话:{情境引入对话} - 互动内容:{互动内容} - 互动反馈:{互动反馈} - 后置对话:{后置对话} # 输出要求 1. 输出一句自然叙事,放在情境引入对话之后、互动反馈之前。 2. 以英文为主,中文放在括号中,必须在一句话里。 - 示例:You packed your clothes into the suitcase. (你把衣服装进了行李箱。) 3. 必须使用互动目标的关键词(如 $clothes$),强化学习点。 4. 避免教学感,不能出现"点击""选项""正确答案"等字眼。 5. 动作简洁、贴近剧情,长度控制在 8–15 个英文词。 6. 输出时只返回最终的一句话结果,不要解释。 # 输出示例 输入: - 互动名称:把衣服装进行李箱 - 情境引入对话: User: Let me check the list… What do I need? User: Most importantly, enough clothes! - 互动内容: User: So let me pack all my $clothes$. - 答案:{{-0.53,0.32,0.15,0.66}} - 辅助信息:clothes 意思为 "衣服" - 互动反馈: 正确:User:Nice! Clothes packed! 错误:User: Oops, I picked the wrong one. - 后置对话:无 输出: You packed your clothes into the suitcase. (你把衣服装进了行李箱。)""" def build_cdesc_prompt(cType, parsed_fields): """为中互动构建互动描述生成 prompt。 Args: cType: 组件类型 parsed_fields: parse_teaching_config_fields() 的返回值 Returns: str: 完整的互动描述生成 prompt """ 互动名称 = parsed_fields.get("标题", "无") 互动内容 = parsed_fields.get("互动内容", "无") if cType in CDESC_MESSAGE_TYPES: return CDESC_PROMPT_MESSAGE.format( 互动名称=互动名称, 互动内容=互动内容, ) elif cType in CDESC_IMAGE_TYPES: 情境引入 = parsed_fields.get("情境引入", "无") 互动反馈 = parsed_fields.get("互动反馈", "无") 后置对话 = parsed_fields.get("后置对话", "无") return CDESC_PROMPT_IMAGE.format( 互动名称=互动名称, 情境引入对话=情境引入, 互动内容=互动内容, 互动反馈=互动反馈, 后置对话=后置对话, ) return None # ============================================================ # Public API # ============================================================ def get_prompt_template(cType): """Get the prompt template for a given cType. Returns None if not found.""" return PROMPT_TEMPLATES.get(cType) def get_supported_types(): """Return list of cTypes that have prompt templates.""" return list(PROMPT_TEMPLATES.keys()) def build_full_prompt(cType, cId, parsed_fields, resource_mapping_str=""): """ Build the complete prompt by filling in the input section. Args: cType: component type (e.g. "mid_dialog_repeat") cId: component ID parsed_fields: dict from parse_teaching_config_fields() resource_mapping_str: formatted角色配置 string Returns: str: complete prompt ready for LLM, or None if cType not supported """ template = get_prompt_template(cType) if template is None: return None input_section = build_input_section(cType, cId, parsed_fields, resource_mapping_str) return template.replace("{input_section}", input_section)