自定义 Prompt
深入了解 CrewAI 中底层 Prompt 的自定义方式,以支持适配不同模型和语言的高度定制化、复杂用例。
为什么要自定义 Prompt?
尽管 CrewAI 的默认 Prompt 在许多场景下都表现良好,但底层自定义能够让 Agent 的行为变得更加灵活和强大。你可能希望利用这种更深层控制的原因包括:
- 针对特定 LLM 进行优化 —— 不同模型(如 GPT-4、Claude 或 Llama)在针对其独特架构量身定制的 Prompt 格式下往往表现更好。
- 切换语言 —— 构建完全使用英语以外语言运行的 Agent,并精准处理细微差异。
- 面向复杂领域进行专业化 —— 为医疗、金融或法律等高度专业化行业调整 Prompt。
- 调整语气与风格 —— 让 Agent 更正式、更随意、更有创意,或更偏分析型。
- 支持高度定制的用例 —— 使用高级 Prompt 结构与格式来满足复杂、项目特定的需求。
本指南将介绍如何从更底层访问 CrewAI 的 Prompt 系统,从而让你能够精细控制 Agent 的思考与交互方式。
理解 CrewAI 的 Prompt 系统
在底层,CrewAI 使用的是一个模块化 Prompt 系统,你可以对其进行广泛自定义:
- Agent templates —— 控制每个 Agent 如何处理其被分配的角色。
- Prompt slices —— 控制任务、工具使用和输出结构等特定行为。
- Error handling —— 指导 Agent 如何应对失败、异常或超时。
- Tool-specific prompts —— 定义调用或使用工具时的详细说明。
你可以查看 CrewAI 仓库中的原始 Prompt 模板,了解这些元素是如何组织的。然后,你可以根据需要覆盖或调整它们,以解锁更高级的行为能力。
理解默认系统指令
当你通过 role、goal 和 backstory 定义一个 Agent 时,CrewAI 会自动附加额外的系统指令,以控制格式和行为。理解这些默认注入内容,对于需要完整 Prompt 透明性的生产系统至关重要。
CrewAI 会自动注入什么
根据你的 Agent 配置,CrewAI 会添加不同的默认指令:
对于没有工具的 Agent
"I MUST use these formats, my job depends on it!"
对于带工具的 Agent
"IMPORTANT: Use the following format in your response:Thought: you should always think about what to doAction: the action to take, only one name of [tool_names]Action Input: the input to the action, just a simple JSON object...
对于结构化输出(JSON / Pydantic)
"Ensure your final answer contains only the content in the following format: {output_format}Ensure the final output does not include any code block markers like ```json or ```python."
查看完整系统 Prompt
如果你想准确看到发送给 LLM 的 Prompt 内容,可以检查生成后的 Prompt:
from crewai import Agent, Crew, Taskfrom crewai.utilities.prompts import Prompts# Create your agentagent = Agent(role="Data Analyst",goal="Analyze data and provide insights",backstory="You are an expert data analyst with 10 years of experience.",verbose=True)# Create a sample tasktask = Task(description="Analyze the sales data and identify trends",expected_output="A detailed analysis with key insights and trends",agent=agent)# Create the prompt generatorprompt_generator = Prompts(agent=agent,has_tools=len(agent.tools) > 0,use_system_prompt=agent.use_system_prompt)# Generate and inspect the actual promptgenerated_prompt = prompt_generator.task_execution()# Print the complete system prompt that will be sent to the LLMif "system" in generated_prompt:print("=== SYSTEM PROMPT ===")print(generated_prompt["system"])print("\n=== USER PROMPT ===")print(generated_prompt["user"])else:print("=== COMPLETE PROMPT ===")print(generated_prompt["prompt"])# You can also see how the task description gets formattedprint("\n=== TASK CONTEXT ===")print(f"Task Description: {task.description}")print(f"Expected Output: {task.expected_output}")
覆盖默认指令
你有几种方式可以获得 Prompt 的完全控制权:
方案 1:自定义模板(推荐)
from crewai import Agent# Define your own system template without default instructionscustom_system_template = """You are {role}. {backstory}Your goal is: {goal}Respond naturally and conversationally. Focus on providing helpful, accurate information."""custom_prompt_template = """Task: {input}Please complete this task thoughtfully."""agent = Agent(role="Research Assistant",goal="Help users find accurate information",backstory="You are a helpful research assistant.",system_template=custom_system_template,prompt_template=custom_prompt_template,use_system_prompt=True # Use separate system/user messages)
方案 2:自定义 Prompt 文件
创建一个 custom_prompts.json 文件,用于覆盖特定 Prompt slice:
{"slices": {"no_tools": "\nProvide your best answer in a natural, conversational way.","tools": "\nYou have access to these tools: {tools}\n\nUse them when helpful, but respond naturally.","formatted_task_instructions": "Format your response as: {output_format}"}}
然后在你的 crew 中这样使用:
crew = Crew(agents=[agent],tasks=[task],prompt_file="custom_prompts.json",verbose=True)
方案 3:为 o1 模型禁用系统 Prompt
agent = Agent(role="Analyst",goal="Analyze data",backstory="Expert analyst",use_system_prompt=False # Disables system prompt separation)
使用可观测性工具进行调试
为了实现生产环境透明性,可集成可观测性平台来监控所有 Prompt 和 LLM 交互。这使你能够准确看到发送给 LLM 的 Prompt 内容(包括默认指令)。
详细的集成指南可参考我们的 可观测性文档,其中包含 Langfuse、MLflow、Weights & Biases 以及自定义日志方案等多个平台的说明。
面向生产环境的最佳实践
- 在部署到生产环境之前,始终检查生成后的 Prompt
- 当你需要完全控制 Prompt 内容时,使用自定义模板
- 集成可观测性工具,持续监控 Prompt(参见 可观测性文档)
- 针对不同 LLM 进行测试,因为默认指令在不同模型上的表现可能不同
- 记录你的 Prompt 自定义内容,以提高团队透明度
管理 Prompt 文件的最佳实践
在进行底层 Prompt 自定义时,请遵循以下建议,以保持内容有序且易于维护:
- 保持文件分离 —— 将自定义 Prompt 存放在独立的 JSON 文件中,而不是混在主代码中。
- 版本控制 —— 在仓库中跟踪这些文件的变更,确保能够清晰记录 Prompt 调整历史。
- 按模型或语言组织 —— 使用诸如
prompts_llama.json或prompts_es.json的命名方式,以快速识别特定配置。 - 记录变更 —— 通过注释或 README 说明自定义内容的目的和范围。
- 尽量少改动 —— 只覆盖你确实需要调整的 slice,其余部分尽量保留默认行为。
自定义 Prompt 最简单的方式
一种直接的方法是创建一个 JSON 文件,写入你想覆盖的 Prompt,然后在 Crew 中引用这个文件:
- 编写一个包含更新后 Prompt slice 的 JSON 文件。
- 通过 Crew 的
prompt_file参数引用该文件。
CrewAI 会将你的自定义内容与默认内容合并,因此你不需要重新定义所有 Prompt。示例如下:
示例:基础 Prompt 自定义
创建一个 custom_prompts.json 文件,写入你要修改的 Prompt。请确保其中列出了它应包含的所有顶层 Prompt,而不仅仅是你改动的部分:
{"slices": {"format": "When responding, follow this structure:\n\nTHOUGHTS: Your step-by-step thinking\nACTION: Any tool you're using\nRESULT: Your final answer or conclusion"}}
然后像这样集成:
from crewai import Agent, Crew, Task, Process# Create agents and tasks as normalresearcher = Agent(role="Research Specialist",goal="Find information on quantum computing",backstory="You are a quantum physics expert",verbose=True)research_task = Task(description="Research quantum computing applications",expected_output="A summary of practical applications",agent=researcher)# Create a crew with your custom prompt filecrew = Crew(agents=[researcher],tasks=[research_task],prompt_file="path/to/custom_prompts.json",verbose=True)# Run the crewresult = crew.kickoff()
通过这些简单修改,你就可以获得对 Agent 如何沟通和完成任务的底层控制能力。
针对特定模型进行优化
不同模型更适合不同结构的 Prompt。进行更深层的调整,能够通过适配模型特性显著提升性能。
示例:Llama 3.3 Prompt 模板
例如,在处理 Meta 的 Llama 3.3 时,更底层的自定义可以参考以下推荐结构: https://www.llama.com/docs/model-cards-and-prompt-formats/llama3_1/#prompt-template
下面的示例展示了如何通过代码对 Agent 进行微调,以更好地利用 Llama 3.3:
from crewai import Agent, Crew, Task, Processfrom crewai_tools import DirectoryReadTool, FileReadTool# Define templates for system, user (prompt), and assistant (response) messagessystem_template = """<|begin_of_text|><|start_header_id|>system<|end_header_id|>{{ .System }}<|eot_id|>"""prompt_template = """<|start_header_id|>user<|end_header_id|>{{ .Prompt }}<|eot_id|>"""response_template = """<|start_header_id|>assistant<|end_header_id|>{{ .Response }}<|eot_id|>"""# Create an Agent using Llama-specific layoutsprincipal_engineer = Agent(role="Principal Engineer",goal="Oversee AI architecture and make high-level decisions",backstory="You are the lead engineer responsible for critical AI systems",verbose=True,llm="groq/llama-3.3-70b-versatile", # Using the Llama 3 modelsystem_template=system_template,prompt_template=prompt_template,response_template=response_template,tools=[DirectoryReadTool(), FileReadTool()])# Define a sample taskengineering_task = Task(description="Review AI implementation files for potential improvements",expected_output="A summary of key findings and recommendations",agent=principal_engineer)# Create a Crew for the taskllama_crew = Crew(agents=[principal_engineer],tasks=[engineering_task],process=Process.sequential,verbose=True)# Execute the crewresult = llama_crew.kickoff()print(result.raw)
通过这种更深层的配置方式,你可以对基于 Llama 的工作流进行全面、底层的控制,而无需单独创建 JSON 文件。
结论
CrewAI 中底层 Prompt 自定义为高度定制化、复杂场景打开了大门。通过建立组织良好的 Prompt 文件(或直接使用内联模板),你可以适配不同模型、语言以及专业领域。这种灵活性使你能够精确塑造所需的 AI 行为,同时在未进行覆盖时,依然可以依赖 CrewAI 提供的稳定默认配置。
