1.7 【直播精华】提示词的艺术:如何让 AI 精准读懂你的每一个指令?

1 阅读1分钟

直播导语:大家好,欢迎来到我们第一周的直播课!在过去几天里,我们一头扎进了代码的世界,学习了 Function Calling、MCP 协议,甚至从零构建了一个 Agent 框架。我们似乎掌握了让 Agent “行动”的硬技能。然而,一个经常被忽视、却又至关重要的“软技能”是——我们该如何与 Agent 的“灵魂”,也就是大语言模型(LLM)本身进行有效沟通?这就是“提示词工程”(Prompt Engineering)的艺术。本期直播,我们将深入探讨在 Agentic AI 开发中,如何通过精心设计的提示词,精准地引导和控制模型的思想与行为,让你的 Agent 不仅能“做”,更能“做对”、“做好”。

目录

  1. 超越基础:为什么 Agent 开发中的提示词工程不一样?
    • 从“单次问答”到“持续对话与决策”
    • 提示词的三个新战场:系统指令、工具描述、动态上下文
    • 目标:从“让模型说话”到“塑造模型的‘人格’与‘思维模式’”
  2. 第一战场:系统指令(System Prompt)—— Agent 的“宪法”与“人格设定”
    • 角色扮演(Persona):赋予 Agent 个性与专业性
      • 案例对比:通用助手 vs. 资深软件架构师
    • 指令与约束(Instructions & Constraints):划定行为边界
      • 如何明确指示“你必须使用工具来回答”?
      • 设定安全红线:“绝不能执行删除文件的操作”
    • 思维框架(Thinking Framework):引导模型如何思考
      • 引入 ReAct (Reason + Act) 思想
      • COT (Chain of Thought):让模型“想清楚再回答”
    • 输出格式化(Output Formatting):强制规定回复的风格
      • JSON、Markdown 还是自然语言?
  3. 第二战场:工具描述(Tool Description)—— Agent 的“工具使用说明书”
    • description 的重要性:模型选择工具的唯一依据
    • 动词 + 效果原则:清晰描述工具“做什么”和“达到什么效果”
    • 举例说明:提供输入和输出的范例,帮助模型理解
    • 差异化描述:当多个工具功能相似时,如何帮助模型区分?
      • 案例:search_web vs. read_internal_doc
    • 参数描述的艺术parameter.description 同样关键
  4. 第三战场:动态上下文(Dynamic Context)—— Agent 的“短期记忆”与“情景感知”
    • user 输入:如何处理模糊、复杂的用户指令?
      • 指令分解的技巧
    • tool 输出:如何向模型有效呈现工具结果?
      • 数据清洗与摘要:避免将大量无关信息或 HTML 标签喂给模型
      • 错误信息呈现:如何让模型看懂错误并进行修复?
    • Few-Shot 示例:在 Prompt 中“预演”一次完整的交互流程
      • 提供一个完整的 user -> tool_call -> tool_response -> final_answer 示例
      • 在复杂任务或需要特定输出格式时效果显著
  5. 综合实战:重构我们的文件搜索 Agent 的提示词
    • 旧版问题分析:回顾之前简单的 Prompt 有哪些不足
    • 新版 System Prompt 设计:定义一个“文件大师”角色
    • 优化 Tool Description:让 list_files, read_file, search_content 的分工更明确
    • 构建 Few-Shot 示例:引导 Agent 如何处理“找不到文件”的情况
  6. 直播 Q&A 环节
    • Q1: System Prompt 越长越好吗?如何权衡详细程度和 Token 成本?
    • Q2: 如何系统地测试和迭代我的 Prompt?
    • Q3: 除了 OpenAI,开源模型(如 Llama)的提示词工程有什么特别之处?

1. 超越基础:为什么 Agent 开发中的提示词工程不一样?

很多开发者对提示词工程的理解,还停留在“如何写一个好的问题让 ChatGPT 回答”的阶段。但在构建 Agentic AI 时,提示词工程的内涵和外延都发生了深刻的变化。

从“单次问答”到“持续对话与决策”

  • 传统提示词:目标是为单次交互获得最佳答案。Prompt 是“一次性”的。
  • Agent 提示词:目标是引导一个持续运行的循环。Prompt 需要考虑多轮对话、状态管理和决策链条。它不仅影响当前的回复,更影响 Agent 的长期行为。

提示词的三个新战场

在 Agent 开发中,我们的“提示词”不再是单一的用户输入,而是一个被分解到不同部分的、立体的结构:

  1. 系统指令 (System Prompt):在对话开始前设定的、全局性的指令。它像 Agent 的“宪法”,定义了其角色、能力边界和基本行为准则。
  2. 工具描述 (Tool Description):我们提供给模型的每一个工具的 namedescription。这直接决定了 Agent 是否会使用、以及如何使用它的“双手”。
  3. 动态上下文 (Dynamic Context):在 Agent 运行过程中,动态生成的 user 输入、assistanttool_calls、以及 tool 的返回结果。这些共同构成了 Agent 的“短期记忆”。

目标:从“让模型说话”到“塑造模型的‘人格’与‘思维模式’”

我们的目标不再是简单地让模型生成一段通顺的文字。我们是在通过这三个战场的组合,去精心塑造一个虚拟的智能体。我们希望它有特定的“人格”(Persona),遵循特定的“思维模式”(Thinking Framework),并能熟练地使用我们赋予它的“工具”(Tools)。

2. 第一战场:系统指令(System Prompt)—— Agent 的“宪法”与“人格设定”

System Prompt 是整个提示词工程的基石。它在第一次调用 LLM 时作为 system 角色的消息传入,为整个对话定下基调。一个好的 System Prompt 通常包含以下四个部分。

角色扮演(Persona)

通过明确的角色设定,我们可以激活模型在特定领域的知识,使其回复更专业、更有风格。

  • 通用助手(弱 Persona)

    "You are a helpful assistant."

  • 资深软件架构师(强 Persona)

    "You are a principal software architect with 20 years of experience in distributed systems. You provide insightful, production-ready advice. You prefer to think step-by-step and always consider trade-offs like cost, performance, and security. When asked to design a system, you always start by clarifying requirements."

对于 Agent,强 Persona 设定能让它在面对任务时,自动代入该角色的行为模式。一个“架构师”Agent 在接到“设计一个秒杀系统”的任务时,可能会首先调用一个 clarify_requirements 的工具,而不是直接开始设计。

指令与约束(Instructions & Constraints)

这是你为 Agent 行为划定“可为”与“不可为”边界的地方。

  • 强制使用工具

    "You must use the provided tools to find the latest information. Do not rely on your internal knowledge for questions about current events or specific data."

  • 设定安全红线

    "You are strictly forbidden from executing any tool that can modify or delete user data (e.g., delete_file, update_database) unless you have received explicit confirmation from the user by them typing 'CONFIRMED'."

这些指令对于构建一个可靠、安全的 Agent至关重要。

思维框架(Thinking Framework)

我们可以引导模型采用特定的“思考”模式,让其决策过程更具逻辑性和可解释性。

  • 引入 ReAct (Reason + Act) 思想:ReAct 框架将 Agent 的每一步分解为 Thought (思考), Action (行动), Observation (观察)。我们可以在 System Prompt 中模仿这种模式。

    "You should always follow this process:

    1. Thought: Analyze the user's request and your current state. Decide if you need a tool and what tool to use.
    2. Action: If you need a tool, generate the tool call. If you can answer directly, generate the final response.
    3. Observation: (This will be provided by the system after a tool is called). You will repeat this Thought/Action loop until you can provide the final answer."
  • COT (Chain of Thought):在复杂问题上,鼓励模型“想清楚再回答”。

    "For complex questions, think step-by-step in your reasoning process before calling a tool or providing an answer. Break down the problem into smaller pieces."

输出格式化(Output Formatting)

你可以明确要求模型回复的格式,便于下游程序处理。

"Always wrap your final answer in <final_answer> tags. All code snippets must be in Markdown format with the language specified."

3. 第二战场:工具描述(Tool Description)—— Agent 的“工具使用说明书”

如果说 System Prompt 是 Agent 的“灵魂”,那么工具描述就是它“身体”各部分的使用手册。在 Function Calling 机制中,模型几乎完全依赖 function.descriptionparameter.description 来决定调用哪个工具以及如何填充参数。

description 的重要性:模型选择工具的唯一依据

description 的撰写是一门艺术,需要清晰、准确、并富有引导性。

  • 坏的描述

    name: "search" description: "Runs a search." (这太模糊了。搜索什么?在哪里搜索?)

  • 好的描述

    name: "search_internal_wiki" description: "Searches the company's internal wiki for articles, documents, and standard operating procedures (SOPs). Use this for questions about company policies, project documentation, and technical guides."

动词 + 效果原则

一个好的描述应该清晰地说明工具做什么(动词)以及它能达到什么效果

"Calculates the final price of an item after applying specified discounts and taxes. Returns a JSON object with the original price, discount amount, tax amount, and final price."

举例说明

在描述中提供一个简单的例子,可以极大地帮助模型理解参数的格式和用途。

description: "Converts a date from one format to another. For example, you can convert '2023-12-25' with target_format='%A, %B %d, %Y' to get 'Monday, December 25, 2023'."

差异化描述

当你有多个功能相似的工具时,在描述中明确指出它们的区别和适用场景至关重要。

  • Tool 1:

    name: "search_web" description: "Performs a general web search using Google. Use this for up-to-date information, news, and topics outside of the company's internal knowledge."

  • Tool 2:

    name: "search_internal_wiki" description: "Searches the company's internal wiki. This should be your default choice for questions about internal projects, policies, and team information."

通过加入 "This should be your default choice" 这样的引导性词语,你可以有效地设定工具的优先级。

参数描述的艺术

不要忽略参数的描述,它和函数描述同样重要。

parameters: { location: { type: "string", description: "The city name. Must be in English. For cities with multiple airports, you can specify the airport code, e.g., 'JFK'." } }

这个描述告诉模型 location 必须是英文,并且给出了一个如何处理歧义的例子。

4. 第三战场:动态上下文(Dynamic Context)—— Agent 的“短期记忆”与“情景感知”

除了预设的 System Prompt 和工具描述,Agent 在运行过程中接触到的信息——用户输入、工具输出——同样是其决策的重要依据。

user 输入:处理模糊指令

用户并不总是像程序员一样思考。他们的输入可能是模糊的、复杂的、甚至是矛盾的。你的 System Prompt 和工具设计需要考虑到这一点。

  • 模糊指令:"我司最近的财报咋样?"
  • Agent 的处理:一个好的 Agent,其 System Prompt 可能包含“当指令不明确时,首先进行澄清”的原则。它可能会调用一个 clarify_question 工具,或者直接回复:“您是指哪个季度的财报?是需要销售额、利润还是用户增长数据?”

tool 输出:如何有效呈现

将工具的原始输出直接、不加处理地丢给模型,往往不是最佳选择。

  • 数据清洗与摘要:一个网页搜索工具可能返回大量的 HTML 标签和广告。在将结果交给模型前,你应该先在你的应用代码中进行清洗,提取出正文内容。如果内容过长,还应该先调用一次 LLM 做一个摘要,再将摘要作为 tool 结果。

    • 坏实践:返回 <html><body>...</body></html> (大量无关 Token)
    • 好实践:返回 {"title": "...", "summary": "...", "key_points": [...]}
  • 错误信息呈现:当工具执行失败时,返回一个对模型友好的错误信息。

    • 坏实践:返回 Python 的 Traceback (模型可能无法理解)
    • 好实践:返回 {"error": "API request failed: Invalid API Key.", "suggestion": "Please check if the API key for the weather service is configured correctly."}

Few-Shot 示例:在 Prompt 中“预演”

对于特别复杂或需要严格格式的任务,可以在 System Prompt 或者最初的几轮对话中,手动插入一个完整的、高质量的交互示例。这被称为 Few-Shot Prompting

# 伪代码,在 messages 列表的开头插入示例
few_shot_example = [
    {
        "role": "user", 
        "content": "I can't find the project plan for 'Bluebird'. Can you help?"
    },
    {
        "role": "assistant",
        "tool_calls": [{
            "function": {
                "name": "search_content",
                "arguments": '{"keyword": "Project Bluebird plan"}'
            }
        }]
    },
    {
        "role": "tool",
        "name": "search_content",
        "content": '{"files_found": []}' # 模拟找不到文件
    },
    {
        "role": "assistant",
        "content": "I couldn't find a file with the exact name 'Project Bluebird plan'. Would you like me to try searching for just 'Bluebird' or list all files in the project directory?"
    }
]
# messages = few_shot_example + messages

这个例子“教会”了 Agent 在 search_content 找不到结果时,不应该直接放弃,而是应该向用户提出建议,尝试不同的策略。

5. 综合实战:重构我们的文件搜索 Agent 的提示词

让我们应用上面学到的所有知识,来优化我们在 1.4 节中创建的文件搜索 Agent。

旧版问题分析

  • System Prompt 缺失:我们根本没有 System Prompt,Agent 只是一个通用的助手,没有“文件专家”的身份。
  • Tool Description 简单:描述虽然清晰,但缺少引导性和差异化。当用户指令模糊时,Agent 可能不知道优先使用哪个工具。
  • 缺乏错误处理引导:没有告诉 Agent 在工具调用失败(如文件找不到)时该怎么办。

新版 System Prompt 设计

You are "FileMaster", an expert AI assistant specialized in navigating and searching local file systems.
Your primary goal is to help users find information within their files efficiently.

**Personality**: You are precise, efficient, and helpful. You always clarify with the user if their request is ambiguous.

**Core Instructions**:
1.  When asked to find something, your default strategy should be to use the `search_content` tool first, as it is the most efficient.
2.  If `search_content` yields no results, analyze the user's query and try a broader keyword. If that also fails, use `list_files` to explore relevant directories.
3.  Only use `read_file` when you are reasonably certain you have found the correct file. Do not read multiple large files unnecessarily.
4.  If a tool returns an error (e.g., 'File not found'), do not give up. Inform the user about the error and suggest an alternative step, like checking the file path or searching for the file first.
5.  Summarize your findings concisely. Do not return the entire content of a large file unless specifically asked.

优化 Tool Description

  • search_content:

    description: "Searches for a keyword in the content of all files within a directory. This is the most efficient tool and should be your first choice when looking for files based on their content."

  • list_files:

    description: "Lists all files and directories in a given path. Use this to explore the file system when you are unsure of file names or when a search_content has failed."

  • read_file:

    description: "Reads the entire content of a single file. Use this only after you have identified the specific file you need through searching or listing."

通过这些优化,我们为 Agent 设定了清晰的工具使用策略和优先级。

6. 直播 Q&A 环节

Q1: System Prompt 越长越好吗?如何权衡详细程度和 Token 成本?

A: 绝对不是越长越好。System Prompt 会被包含在每一次 LLM 调用中,直接影响你的 Token 成本和 API 响应时间。关键在于信息密度必要性

  • 权衡:问问自己,这条指令是“锦上添花”还是“不可或缺”?一个复杂的 Persona 描述可能很有趣,但如果对 Agent 的核心任务帮助不大,就可以精简。安全约束、核心指令和思维框架通常是不可或缺的。
  • 迭代:从一个相对简洁的 System Prompt 开始,通过测试发现 Agent 的行为偏差,然后针对性地增加或修改指令。例如,你发现 Agent 总是优先 list_files,这时就应该在 Prompt 中明确 search_content 的高优先级。

Q2: 如何系统地测试和迭代我的 Prompt?

A: 这是一个工程问题。

  1. 建立评估集(Eval Set):创建一组有代表性的用户输入和期望的 Agent 行为/最终答案。例如:
    • 输入:"Find the summary of project X." -> 期望行为:调用 search_content, 然后 read_file
    • 输入:"Delete all log files." -> 期望行为:向用户请求确认,而不是直接调用 delete 工具。
  2. 版本控制:像对待代码一样,使用 Git 对你的 Prompt 进行版本控制。
  3. 自动化测试:编写脚本,使用不同的 Prompt 版本运行你的评估集,并记录 Agent 的关键行为(如调用的工具序列)和最终输出。
  4. 对比分析:对比不同版本 Prompt 的测试结果,找出哪个版本的表现更好。像 Langfuse、LangSmith 这样的 LLMOps 平台就是专门用来做这件事的。

Q3: 除了 OpenAI,开源模型(如 Llama, DeepSeek)的提示词工程有什么特别之处?

A: 核心思想是通用的,但细节上有差异。

  • 指令遵循能力:不同模型对复杂指令的遵循能力有差异。一些开源模型可能需要更明确、更简单的指令。你可能需要把一条复杂指令分解成几条简单的指令。
  • Prompt 格式:不同的模型在训练时使用的 Prompt 格式不同。例如,Llama 2/3 有特定的 [INST]<<SYS>> 标签。虽然很多推理框架(如 vLLM, Ollama)会自动处理,但如果你需要极致的性能,了解并使用模型原生的 Prompt 格式会获得最好效果。DeepSeek 则很好地兼容了 OpenAI 的 API 格式,迁移成本较低。
  • Function Calling 支持:虽然很多开源模型都在努力支持 Function Calling,但其能力和稳定性可能仍与 GPT-4 有差距。有时,你可能需要降级为更简单的工具调用模式,比如让模型在回复中生成特定格式的文本(如 [TOOL_CALL] a=1, b=2 [/TOOL_CALL]),然后在客户端用正则表达式解析。

最终,提示词工程是一个实验科学。 没有一劳永逸的完美 Prompt。你需要不断地测试、观察、迭代,像一个驯兽师一样,逐步引导你的 Agent,直至它的行为符合你的最终期望。