UFO 提示词体系全解:从 YAML 模板到 Prompter 构造链路的完整指南
【免费下载链接】UFOUFO³: Weaving the Digital Agent Galaxy项目地址: https://gitcode.com/GitHub_Trending/uf/UFO
UFO(UI-Focused Agent)框架中的全部提示词均统一存放于ufo/prompts目录,通过结构化 YAML 模板组织,并由各 Agent 专属的Prompter类在运行时动态组装成发送给 LLM 的消息列表。本文以 Prompts 目录结构为主线,完整讲解 UFO 提示词的分类布局、三大组成组件(基础模板、API 文档、示例)、五步构造流程,并结合ufo/prompter源码与真实 YAML 模板,帮助你掌握从模板编写、运行时注入到多模态消息封装的完整链路。
提示词目录结构总览
UFO 遵循"模板即配置"的设计原则,所有提示词都存放在仓库的ufo/prompts目录下。其目录结构如下:
📦prompts ┣ 📂demonstration # Prompts for summarizing human demonstrations ┣ 📂evaluation # Prompts for the EvaluationAgent ┣ 📂examples # Demonstration examples for in-context learning ┣ 📂nonvisual # Examples for non-visual LLMs ┗ 📂visual # Examples for visual LLMs ┣ 📂experience # Prompts for summarizing agent self-experience ┣ 📂share # Shared prompt templates ┗ 📂base # Basic version of shared prompts ┣ 📜api.yaml # Basic API prompt ┣ 📜app_agent.yaml # Basic AppAgent prompt template ┗ 📜host_agent.yaml # Basic HostAgent prompt template ┗ 📂third_party # Third-party integration prompts (e.g., Linux agents)各子目录职责明确:
| 目录 | 职责 | 实际文件 |
|---|---|---|
demonstration | 将人工演示(Step Recorder 输出)总结为可学习示例 | demonstration_summary.yaml |
evaluation | 供 EvaluationAgent 评估任务是否成功 | evaluate.yaml |
examples/visual | 面向视觉 LLM 的上下文学习示例 | app_agent_example.yaml、host_agent_example.yaml等 |
examples/nonvisual | 面向纯文本 LLM 的示例 | 同名文件,但仅含文本控制信息 |
experience | 将 Agent 自身执行轨迹总结为经验 | experience_summary.yaml |
share/base | 各 Agent 共享的基础系统提示词模板 | api.yaml、app_agent.yaml、host_agent.yaml |
third_party | 第三方 Agent 集成提示词(如 Linux Agent、Mobile Agent) | linux_agent.yaml、mobile_agent.yaml等 |
关键差异点:视觉 LLM(Visual LLM)可以直接处理截图,而非视觉 LLM(Non-visual LLM)只能依赖纯文本形式的控件信息。这一差异贯穿整个模板体系——system与system_nonvisual两个字段分别对应两种模型形态,示例目录也据此拆分为visual/与nonvisual/两套。
Agent Prompts 的三大组成组件
UFO 中每类 Agent 的提示词并非单一文本,而是由以下三类组件拼接而成:
| 组件 | 说明 | 来源 |
|---|---|---|
| 基础模板(Basic Template) | 定义了系统角色与用户角色的基础模板,含系统指令与 JSON 输出格式要求 | share/base/下的 YAML 文件 |
| API 文档(API Documentation) | Agent 可用的技能与 API 说明,运行期由 MCP 工具信息动态生成 | MCP 工具(api.yaml为静态底座) |
| 示例(Examples) | 上下文学习(In-context Learning)演示样例 | examples/visual/或examples/nonvisual/下的 YAML |
其中基础模板是骨架,API 文档决定 Agent 的"手"能做什么,示例则决定 Agent 的输出"长什么样"。
基础模板字段解析
以 AppAgent 的核心模板 app_agent.yaml 为例,一个 YAML 模板由version与多个顶层字段构成:
system:视觉模式系统提示词,包含角色定义、截图理解规则(标注图+无标注图双版本、上一轮红色方框标注)、控件列表格式、状态机定义(CONTINUE/FINISH/FAIL/CONFIRM)以及 9 字段 JSON 输出格式要求;system_nonvisual:非视觉模式版本,删除了截图相关指导,控件信息改为label、control_text、control_type三元组,输出格式改用 PascalCase 键(ControlLabel、ControlText、Function、Args、Status等);system_as:动作序列(Action Sequence)模式,允许一次输出多个独立动作组成的列表以提升执行效率,但同时约束"仅当动作相互独立且前一动作不会导致后续动作失败时才可组合";user:用户消息模板,内含{retrieved_docs}、{control_item}、{user_request}、{prev_subtask}、{subtask}、{last_success_actions}、{current_application}、{host_message}、{prev_plan}等占位符,运行期由 Prompter 注入实际上下文。
模板中还有两处特殊的占位符:{apis}与{examples},分别由api_prompt_helper()与examples_prompt_helper()在系统提示词构造阶段填充,这是"模板静态、内容动态"的核心机制。
Prompter 如何构造提示词
每个 Agent 都拥有独立的Prompter类,其职责包括:加载 YAML 模板、格式化工具 API 文档、按模型类型(visual/nonvisual)选择示例、将所有组件组合为结构化的 LLM 消息列表、注入运行时上下文(观察、截图、检索知识)。
Prompter 系统采用分层设计(详见 Agent Prompter 设计文档):
BasicPrompter (抽象基类) ├── HostAgentPrompter ├── AppAgentPrompter ├── EvaluationAgentPrompter ├── ExperiencePrompter ├── DemonstrationPrompter └── customized/ └── LinuxAgentPrompter (继承 AppAgentPrompter)各 Prompter 实现位于 ufo/prompter 目录:basic.py(抽象基类)、agent_prompter.py(HostAgent/AppAgent)、eva_prompter.py(评估)、experience_prompter.py(经验总结)、demonstration_prompter.py(演示总结),以及customized/linux_agent_prompter.py(第三方 Linux Agent 定制)。
消息结构:发送给 LLM 的最终形态
无论哪种 Prompter,最终构造出的 prompt 都是一个字典列表,每个字典是一条消息:
| 键 | 说明 | 示例值 |
|---|---|---|
role | 消息角色 | system、user、assistant |
content | 消息内容 | 字符串或内容对象列表 |
对于视觉模型,content字段可以包含多个元素,实现"文字 + 图片"的多模态消息:
[ {"type": "text", "text": "Current Screenshots:"}, {"type": "image_url", "image_url": {"url": "data:image/png;base64,..."}} ]五步构造流程
最终的提示词经过以下多步流水线生成:
Step 1:加载模板(Template Loading)
初始化时从 YAML 文件加载模板。is_visual参数决定加载哪套变体:
def __init__(self, is_visual: bool, prompt_template: str, example_prompt_template: str): self.is_visual = is_visual self.prompt_template = self.load_prompt_template(prompt_template, is_visual) self.example_prompt_template = self.load_prompt_template(example_prompt_template, is_visual)在 basic.py 中,load_prompt_template()会把模板路径中的{mode}占位符替换为visual或nonvisual,再通过yaml.safe_load解析;文件不存在时抛出FileNotFoundError。
Step 2:构造系统提示词(System Prompt Construction)
系统提示词由system_prompt_construction()构建,组合基础指令、API 文档(api_prompt_helper())、演示示例(examples_prompt_helper()),HostAgent 额外追加第三方 Agent 指令(third_party_agent_instruction())。HostAgent 的视觉/非视觉切换通过system_key = "system" if self.is_visual else "system_nonvisual"选择模板字段完成(见 agent_prompter.py)。
Step 3:构造用户提示词(User Prompt Construction)
用户提示词由user_prompt_construction()依据 Agent 类型注入不同参数:
- HostAgent:可用应用/窗口列表、之前的子任务历史、之前的计划、用户原始请求、检索文档;
- AppAgent:可用 UI 控件、之前的子任务历史、之前的计划、用户请求、当前子任务、当前应用名、HostAgent 消息、检索文档、最近成功动作。
Step 4:构造用户内容(User Content Construction)
user_content_construction()为多模态模型构建内容对象列表:视觉模式下为每张截图追加"Screenshot N:"文本与image_url对象,最后追加文本型用户提示词。该逻辑在 HostAgent 与 AppAgent 的实现中一致(见 agent_prompter.py)。
Step 5:最终组装(Final Assembly)
prompt_construction()将系统提示词与用户内容合并为[{system}, {user}]消息列表:
@staticmethod def prompt_construction(system_prompt: str, user_content: List[Dict]) -> List: return [ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_content} ]该静态方法实现在 basic.py,随后消息列表即被交给 LLM 调用层。
API 文档:从 MCP 工具到 LLM 可读格式
api_prompt_helper()负责将可用工具格式化给 LLM。tool_to_llm_prompt()将单个MCPToolInfo转换为标准格式(见 basic.py),包含工具名、描述、参数表(类型/必选/默认值)与示例调用,其输出形如:
Tool name: click_input Description: Click on a control item Parameters: - id (string, required): The ID of the control item - button (string, optional): Mouse button to click. Default: left - double (boolean, optional): Whether to double-click. Default: false Returns: Result of the click action Example usage: click_input(id="42", button="left", double=false)tools_to_llm_prompt()则以---分隔符将多个工具拼接为完整 API 文档块。值得注意的是,HostAgentPrompter还支持create_api_prompt_template(tools)方法,可在运行期用真实的 MCP 工具列表覆盖静态模板,实现"API 文档动态生成"。
api.yaml 中预置了 UfoAutomator 的核心工具说明,例如:
click_input(button, double, pressed):点击控件,支持左右键、双击、组合键;click_on_coordinates(x, y, button, double):按相对坐标(0.0~1.0,原点为窗口左上角)点击,适用于控件未出现在列表/截图中的场景;drag_on_coordinates(start_x, start_y, end_x, end_y, ...):按相对坐标拖拽;set_edit_text(text, clear_current_text):向 Edit 控件输入文本(默认追加,可清空重设);annotation(control_labels):截图并对控件编号标注;summary(text):基于干净截图概括窗口内容;texts():读取 Edit 与 Document 控件的文本内容;wheel_mouse_input(wheel_dist):滚动,正数向上、负数向下;keyboard_input(keys, control_focus):模拟键盘输入与快捷键,如"{VK_CONTROL}c"表示 Ctrl+C、"{TAB 2}"表示连按两次 Tab。
示例注入:In-context Learning 的落地方式
examples_prompt_helper()从示例模板中取出以example开头的键,按[User Request]+[Response]模板格式化(Response 为 JSON 序列化后的动作字典),再通过retrieved_documents_prompt_helper()统一排版。示例文件按模型形态拆分为两套:视觉模型使用 examples/visual 下的app_agent_example.yaml、app_agent_example_as.yaml、host_agent_example.yaml,非视觉模型使用 examples/nonvisual 下的同名文件。
检索知识注入:Retrieved Documents 与 Blackboard
retrieved_documents_prompt_helper(header, separator, documents)将 RAG 检索结果或经验知识格式化为带编号的文档块(见 basic.py),输出形如:
<Retrieved Documentation:> [Document 1:] To create a new email in Outlook, click the "New Email" button... [Document 2:] The email composition window has three main fields: To, Subject, and Body...除此之外,Blackboard 黑板机制允许各 Agent 共享跨步信息,Prompter 可通过blackboard_to_prompt()将黑板状态转换为提示词文本,历史截图、思考等内容可被后续步骤引用。
三类核心 Prompter 的分工
HostAgentPrompter:桌面级编排
面向桌面级任务编排,负责应用选择与窗口管理、第三方 Agent 集成、桌面级任务规划。其独有的third_party_agent_instruction()会读取系统配置enabled_third_party_agents,把每个已启用第三方 Agent 的INTRODUCTION拼接为指令注入系统提示词(见 agent_prompter.py),对应 host_agent.yaml 中的{third_party_instructions}占位符。HostAgent 的响应含current_subtask、status(FINISH/CONTINUE/PENDING/ASSIGN)、plan、function、questions等字段,并以select_application_window等函数完成子任务指派。
AppAgentPrompter:应用内交互
面向应用窗口内的单步交互,具备 UI 控件操作、多动作序列支持、应用级 API 集成能力。其系统提示词模板有三套变体:
system:标准单动作模式;system_as:动作序列模式(多动作,由配置action_sequence控制);system_nonvisual:纯文本模式。
模板选择逻辑为:先按config.system.action_sequence选system_as或system,再按is_visual追加_nonvisual后缀(见 agent_prompter.py)。
EvaluationAgentPrompter:任务评估
用于判断某个 Session 或 Round 是否成功完成,使用 evaluate.yaml。该模板要求评估者基于<Original Request>与<Execution Trajectory>(含 thought、observation、plan、action、results 等)输出结构化 JSON:reason(判断理由)、sub_scores(子评分点列表,如"文本输入正确"、"格式正确"、"位置正确")、complete(yes/no/unsure)。模板还提供screenshots_head_tail与screenshots_all两种截图观察策略字段,分别对应首尾截图对比与全量逐步对比。
提示词路径配置与自定义扩展
Prompter 的行为由系统配置控制,核心路径配置见 config/ufo/system.yaml:
# Prompt template paths HOSTAGENT_PROMPT: "./ufo/prompts/share/base/host_agent.yaml" APPAGENT_PROMPT: "./ufo/prompts/share/base/app_agent.yaml" EVALUATION_PROMPT: "./ufo/prompts/evaluation/evaluate.yaml" # Example prompt paths (visual vs. non-visual) HOSTAGENT_EXAMPLE_PROMPT: "./ufo/prompts/examples/{mode}/host_agent_example.yaml" APPAGENT_EXAMPLE_PROMPT: "./ufo/prompts/examples/{mode}/app_agent_example.yaml" # Feature flags ACTION_SEQUENCE: False # Enable multi-action mode for AppAgent其中{mode}占位符会依据 LLM 能力自动替换为visual或nonvisual,这正是"同一套配置兼容两类模型"的实现基础。
若需定制提示词,可继承BasicPrompter或现有专用 Prompter 重写system_prompt_construction(),例如:
from ufo.prompter.agent_prompter import AppAgentPrompter class CustomAppPrompter(AppAgentPrompter): """Custom prompter for specialized application.""" def system_prompt_construction(self, **kwargs) -> str: base_prompt = super().system_prompt_construction(**kwargs) custom_instructions = self.load_custom_instructions() return base_prompt + "\n" + custom_instructions总结
UFO 的提示词体系以ufo/prompts目录为静态底座、以ufo/prompter下的 Prompter 类为动态装配引擎:YAML 模板定义角色与输出格式,MCP 工具动态生成 API 文档,视觉/非视觉双套示例实现上下文学习,五步构造流水线最终产出可直接投喂 LLM 的多模态消息列表。掌握这套机制后,无论是为新的第三方 Agent 编写模板,还是通过继承 Prompter 定制输出结构,都能以最小的侵入成本完成。更完整的 Prompter 架构、模板加载与消息构造细节,可进一步阅读 Agent Prompter 设计文档。
【免费下载链接】UFOUFO³: Weaving the Digital Agent Galaxy项目地址: https://gitcode.com/GitHub_Trending/uf/UFO
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考