仿照豆包实现 Prompt 变量模板输入框
2026/7/25 23:44:25 网站建设 项目流程

仿照豆包实现 Prompt 变量模板输入框

引言:为什么需要变量模板输入框?在 AI 应用开发中,我们经常需要让用户自定义 Prompt(提示词)模板。比如在豆包(字节跳动的 AI 助手)中,用户可以在输入框中插入{变量名}这样的占位符,系统会自动替换成实际内容。这种设计既灵活又易用,非常适合做对话系统、自动写作工具或客服机器人。如果你正在开发类似的产品,可能会遇到这样的需求:用户输入一个模板,比如“写一封关于 {主题} 的邮件”,然后程序自动把{主题}替换成用户指定的内容。本文将教你怎么用 Python 实现这个功能,从基础替换到完整交互界面。## 核心原理:字符串模板替换### 1. 基础替换方法Python 中可以用str.replace()str.format()实现简单替换。但最灵活的方式是使用正则表达式来提取变量名。pythonimport redef parse_prompt_template(template: str, variables: dict) -> str: """ 解析 Prompt 模板,将 {变量名} 替换为实际值 参数: template: 包含 {变量名} 的模板字符串 variables: 变量名到值的映射字典 返回: 替换后的完整字符串 """ # 正则匹配所有 {变量名} 格式的占位符 # 注意:变量名只能包含字母、数字和下划线 pattern = r'\{([a-zA-Z_][a-zA-Z0-9_]*)\}' def replace_match(match): # match.group(0) 是整个匹配(如 {name}) # match.group(1) 是括号内的变量名(如 name) var_name = match.group(1) if var_name in variables: return str(variables[var_name]) else: # 如果变量未定义,保留原样或抛出异常 # 这里选择保留原样,方便用户调试 return match.group(0) return re.sub(pattern, replace_match, template)# 使用示例template = "你好,{name}!今天是{date},天气{weather}。"variables = { "name": "小明", "date": "2024年1月15日", "weather": "晴朗"}result = parse_prompt_template(template, variables)print(result) # 输出:你好,小明!今天是2024年1月15日,天气晴朗。这段代码的核心是正则表达式r'\{([a-zA-Z_][a-zA-Z0-9_]*)\}',它匹配所有形如{变量名}的占位符。re.sub函数会遍历所有匹配,并用replace_match回调函数进行替换。如果某个变量没有提供值,我们选择保留原始占位符,这样用户能立刻发现问题。### 2. 提取所有变量名有时候我们需要先让用户输入变量值,再执行替换。比如在 GUI 中,先解析模板里有哪些变量,然后生成对应的输入框。pythonimport redef extract_variables(template: str) -> list: """ 从模板中提取所有变量名 参数: template: 包含 {变量名} 的模板字符串 返回: 变量名列表(按出现顺序) """ pattern = r'\{([a-zA-Z_][a-zA-Z0-9_]*)\}' # findall 返回所有匹配的变量名(括号内的部分) variables = re.findall(pattern, template) return list(dict.fromkeys(variables)) # 去重但保持顺序# 使用示例template = "写一封关于{主题}的邮件,发送给{收件人},语气要{语气}"vars_needed = extract_variables(template)print("需要输入的变量:", vars_needed)# 输出:需要输入的变量: ['主题', '收件人', '语气']这里用dict.fromkeys()去重,同时保持变量在模板中首次出现的顺序。这样在生成输入框时,用户能按逻辑顺序填写。## 构建完整的交互界面### 用 Tkinter 实现可视化模板输入框下面我们用 Python 内置的 Tkinter 库,仿照豆包的样子做一个完整的变量模板输入工具。这个例子包含三个部分:模板输入区、变量输入区、结果预览区。pythonimport tkinter as tkfrom tkinter import ttk, scrolledtextimport reclass PromptTemplateApp: def __init__(self, root): self.root = root self.root.title("Prompt 变量模板输入框 - 仿豆包风格") self.root.geometry("700x600") # 1. 模板输入区 tk.Label(root, text="输入模板(使用 {变量名} 作为占位符):", font=("Arial", 12)).pack(pady=10) self.template_entry = scrolledtext.ScrolledText( root, height=5, width=80, font=("Arial", 11) ) self.template_entry.pack(padx=20, pady=5) # 2. 解析按钮 self.parse_button = tk.Button( root, text="解析变量", command=self.parse_variables, bg="#4CAF50", fg="white", font=("Arial", 11) ) self.parse_button.pack(pady=10) # 3. 变量输入区(动态生成) self.variables_frame = tk.LabelFrame(root, text="变量值输入", font=("Arial", 12)) self.variables_frame.pack(pady=10, padx=20, fill="x") self.variable_entries = {} # 存储变量名到输入框的映射 # 4. 生成按钮和结果 self.generate_button = tk.Button( root, text="生成最终 Prompt", command=self.generate_prompt, bg="#2196F3", fg="white", font=("Arial", 11) ) self.generate_button.pack(pady=10) self.result_text = scrolledtext.ScrolledText( root, height=6, width=80, font=("Arial", 11), bg="#f0f0f0", state="disabled" ) self.result_text.pack(padx=20, pady=5) def extract_variables(self, template): """提取模板中的变量名""" pattern = r'\{([a-zA-Z_][a-zA-Z0-9_]*)\}' variables = re.findall(pattern, template) return list(dict.fromkeys(variables)) def parse_variables(self): """解析模板并生成变量输入框""" # 清空旧的变量输入框 for widget in self.variables_frame.winfo_children(): widget.destroy() self.variable_entries.clear() template = self.template_entry.get("1.0", tk.END).strip() if not template: return variables = self.extract_variables(template) if not variables: tk.messagebox.showinfo("提示", "模板中没有找到变量占位符") return # 动态生成变量输入框 for var_name in variables: frame = tk.Frame(self.variables_frame) frame.pack(fill="x", padx=10, pady=5) label = tk.Label(frame, text=f"{var_name}:", width=15, anchor="w", font=("Arial", 11)) label.pack(side="left") entry = tk.Entry(frame, font=("Arial", 11)) entry.pack(side="left", fill="x", expand=True) self.variable_entries[var_name] = entry def generate_prompt(self): """根据模板和变量值生成最终结果""" template = self.template_entry.get("1.0", tk.END).strip() if not template: return # 收集变量值 variables = {} for var_name, entry in self.variable_entries.items(): value = entry.get().strip() if value: variables[var_name] = value # 执行替换 pattern = r'\{([a-zA-Z_][a-zA-Z0-9_]*)\}' def replace_match(match): var_name = match.group(1) if var_name in variables: return variables[var_name] return match.group(0) result = re.sub(pattern, replace_match, template) # 显示结果 self.result_text.config(state="normal") self.result_text.delete("1.0", tk.END) self.result_text.insert("1.0", result) self.result_text.config(state="disabled")# 运行应用if __name__ == "__main__": root = tk.Tk() app = PromptTemplateApp(root) root.mainloop()这个程序的工作流程是:1. 用户在顶部文本框输入模板,比如写一封关于{主题}的邮件,语气要{语气}2. 点击“解析变量”按钮,程序自动提取{主题}{语气},并在下方生成对应的输入框3. 用户填入具体值,比如“产品发布”和“正式”4. 点击“生成最终 Prompt”,程序替换占位符并显示结果## 进阶优化:实时预览与错误处理在实际产品中,你可能希望用户输入模板时就能实时看到变量列表,或者在变量值变化时自动更新预览。下面是一个优化版本:pythonimport tkinter as tkfrom tkinter import scrolledtextimport reclass SmartPromptEditor: def __init__(self, root): self.root = root self.root.title("智能 Prompt 编辑器") self.root.geometry("800x600") # 主布局:左右分栏 main_frame = tk.Frame(root) main_frame.pack(fill="both", expand=True, padx=10, pady=10) # 左侧:模板编辑区 left_frame = tk.Frame(main_frame) left_frame.pack(side="left", fill="both", expand=True, padx=5) tk.Label(left_frame, text="模板编辑", font=("Arial", 14, "bold")).pack() self.template_text = scrolledtext.ScrolledText( left_frame, height=8, font=("Arial", 11) ) self.template_text.pack(fill="both", expand=True) self.template_text.bind("<KeyRelease>", self.on_template_change) # 变量状态显示 self.var_status = tk.Label(left_frame, text="检测到 0 个变量", font=("Arial", 10), fg="gray") self.var_status.pack(anchor="w") # 右侧:变量输入区 right_frame = tk.Frame(main_frame) right_frame.pack(side="right", fill="both", expand=True, padx=5) tk.Label(right_frame, text="变量值", font=("Arial", 14, "bold")).pack() self.var_canvas = tk.Canvas(right_frame, bg="white") self.var_scrollbar = tk.Scrollbar(right_frame, orient="vertical", command=self.var_canvas.yview) self.var_inner_frame = tk.Frame(self.var_canvas) self.var_canvas.configure(yscrollcommand=self.var_scrollbar.set) self.var_scrollbar.pack(side="right", fill="y") self.var_canvas.pack(side="left", fill="both", expand=True) self.var_canvas.create_window((0, 0), window=self.var_inner_frame, anchor="nw") self.var_inner_frame.bind("<Configure>", lambda e: self.var_canvas.configure(scrollregion=self.var_canvas.bbox("all"))) # 底部:预览区 bottom_frame = tk.Frame(root) bottom_frame.pack(fill="x", padx=10, pady=5) tk.Label(bottom_frame, text="实时预览", font=("Arial", 12, "bold")).pack(anchor="w") self.preview_text = scrolledtext.ScrolledText( bottom_frame, height=4, font=("Arial", 11), bg="#f9f9f9" ) self.preview_text.pack(fill="x") # 初始化变量存储 self.variable_widgets = {} self.current_variables = [] def extract_variables(self, template): pattern = r'\{([a-zA-Z_][a-zA-Z0-9_]*)\}' variables = re.findall(pattern, template) return list(dict.fromkeys(variables)) def on_template_change(self, event=None): template = self.template_text.get("1.0", tk.END).strip() variables = self.extract_variables(template) # 更新变量状态显示 self.var_status.config(text=f"检测到 {len(variables)} 个变量") # 更新变量输入区 self.update_variable_inputs(variables) # 更新预览 self.update_preview() def update_variable_inputs(self, new_variables): # 清除旧输入框 for widget in self.var_inner_frame.winfo_children(): widget.destroy() self.variable_widgets.clear() # 创建新输入框 for var_name in new_variables: frame = tk.Frame(self.var_inner_frame) frame.pack(fill="x", padx=5, pady=3) label = tk.Label(frame, text=f"{var_name}:", width=15, anchor="w", font=("Arial", 10)) label.pack(side="left") entry = tk.Entry(frame, font=("Arial", 10)) entry.pack(side="left", fill="x", expand=True) entry.bind("<KeyRelease>", lambda e: self.update_preview()) self.variable_widgets[var_name] = entry self.current_variables = new_variables def update_preview(self): template = self.template_text.get("1.0", tk.END).strip() if not template: return # 收集变量值 variables = {} for var_name, entry in self.variable_widgets.items(): value = entry.get().strip() if value: variables[var_name] = value # 执行替换 pattern = r'\{([a-zA-Z_][a-zA-Z0-9_]*)\}' def replace_match(match): var_name = match.group(1) if var_name in variables: return variables[var_name] return f"[{var_name}]" # 未填写的变量用中括号标记 result = re.sub(pattern, replace_match, template) # 更新预览 self.preview_text.delete("1.0", tk.END) self.preview_text.insert("1.0", result)# 运行if __name__ == "__main__": root = tk.Tk() app = SmartPromptEditor(root) root.mainloop()这个版本实现了实时更新:当用户输入模板或变量值时,预览区会自动更新。未填写的变量会被标记为[变量名],方便用户识别。## 总结本文从基本原理出发,逐步演示了如何仿照豆包实现 Prompt 变量模板输入框。核心要点包括:1.正则表达式提取变量:使用re.findallre.sub处理{变量名}占位符2.动态 UI 生成:根据解析出的变量名,动态创建对应的输入控件3.实时预览:通过绑定事件,让用户能即时看到替换结果在实际项目中,你可以进一步扩展这个思路:- 支持嵌套变量(如{用户.姓名})- 添加默认值或提示文本- 集成到 Web 应用(使用 Flask/Django 或前端框架)- 增加语法检查,防止变量名冲突变量模板输入框看似简单,却是提升 AI 应用用户体验的关键组件。希望本文能帮助你在自己的项目中实现类似功能。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询