跳转到主要内容

为何要自定义提示?

虽然 CrewAI 的默认提示在许多场景下都表现良好,但低级自定义为实现更灵活、更强大的代理行为打开了大门。以下是您可能希望利用这种更深层次控制的原因:
  1. 为特定 LLM 优化 – 不同的模型(如 GPT-4、Claude 或 Llama)在针对其独特架构量身定制的提示格式下会表现得更好。
  2. 更改语言 – 构建专门使用英语以外的语言运行的代理,并能精确处理其中的细微差别。
  3. 针对复杂领域进行专门化 – 调整提示以适应高度专业化的行业,如医疗、金融或法律。
  4. 调整语气和风格 – 使代理变得更正式、休闲、富有创意或更具分析性。
  5. 支持超级定制化用例 – 利用高级提示结构和格式来满足复杂、特定项目的需求。
本指南将探讨如何在较低级别上利用 CrewAI 的提示,让您对代理的思考和交互方式进行精细控制。

理解 CrewAI 的提示系统

在底层,CrewAI 采用了一个模块化的提示系统,您可以对其进行广泛的自定义:
  • 代理模板 – 控制每个代理执行其指定角色的方式。
  • 提示片段 – 控制专业行为,如任务、工具使用和输出结构。
  • 错误处理 – 指导代理如何响应失败、异常或超时。
  • 工具特定提示 – 定义关于如何调用或使用工具的详细说明。
请查看 CrewAI 仓库中的原始提示模板,了解这些元素是如何组织的。您可以根据需要覆盖或调整它们,以解锁高级行为。

理解默认系统指令

生产透明度问题:CrewAI 会自动向您的提示中注入您可能不知道的默认指令。本节将解释底层发生了什么以及如何获得完全控制。
当您使用 `role`、`goal` 和 `backstory` 定义一个代理时,CrewAI 会自动添加额外的系统指令来控制格式和行为。理解这些默认注入对于需要完全提示透明度的生产系统至关重要。

CrewAI 自动注入了什么

根据您的代理配置,CrewAI 会添加不同的默认指令:

对于没有工具的代理

"I MUST use these formats, my job depends on it!"

对于有工具的代理

"IMPORTANT: Use the following format in your response:

Thought: you should always think about what to do
Action: 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."

查看完整的系统提示

要确切了解发送给 LLM 的提示是什么,您可以检查生成的提示:
from crewai import Agent, Crew, Task
from crewai.utilities.prompts import Prompts

# Create your agent
agent = 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 task
task = Task(
    description="Analyze the sales data and identify trends",
    expected_output="A detailed analysis with key insights and trends",
    agent=agent
)

# Create the prompt generator
prompt_generator = Prompts(
    agent=agent,
    has_tools=len(agent.tools) > 0,
    use_system_prompt=agent.use_system_prompt
)

# Generate and inspect the actual prompt
generated_prompt = prompt_generator.task_execution()

# Print the complete system prompt that will be sent to the LLM
if "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 formatted
print("\n=== TASK CONTEXT ===")
print(f"Task Description: {task.description}")
print(f"Expected Output: {task.expected_output}")

覆盖默认指令

您有多种选项可以完全控制提示:
from crewai import Agent

# Define your own system template without default instructions
custom_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:自定义提示文件

创建一个 `custom_prompts.json` 文件来覆盖特定的提示片段:
{
  "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 模型禁用系统提示

agent = Agent(
    role="Analyst",
    goal="Analyze data",
    backstory="Expert analyst",
    use_system_prompt=False  # Disables system prompt separation
)

使用可观测性工具进行调试

为了实现生产透明度,请与可观测性平台集成,以监控所有提示和 LLM 交互。这使您能够确切地看到发送给 LLM 的提示(包括默认指令)是什么。 请参阅我们的 可观测性文档,了解与 Langfuse、MLflow、Weights & Biases 以及自定义日志记录解决方案等各种平台的详细集成指南。

生产最佳实践

  1. 在部署到生产环境之前,务必检查生成的提示
  2. 当需要完全控制提示内容时,使用自定义模板
  3. 集成可观测性工具以进行持续的提示监控(请参阅可观测性文档
  4. 用不同的 LLM 进行测试,因为默认指令在不同模型上的效果可能不同
  5. 为您的提示自定义编写文档,以确保团队透明度
默认指令的存在是为了确保代理行为的一致性,但它们可能会与特定领域的需求冲突。使用上述自定义选项来在生产系统中保持对代理行为的完全控制。

管理提示文件的最佳实践

在进行低级提示自定义时,请遵循以下准则以保持代码的组织性和可维护性:
  1. 保持文件分离 – 将您的自定义提示存储在主代码库之外的专用 JSON 文件中。
  2. 版本控制 – 在您的代码仓库中跟踪更改,确保提示调整有清晰的文档记录。
  3. 按模型或语言组织 – 使用像 `prompts_llama.json` 或 `prompts_es.json` 这样的命名方案来快速识别专门的配置。
  4. 记录更改 – 提供注释或维护一个 README 文件,详细说明您自定义的目的和范围。
  5. 最小化修改 – 只覆盖您真正需要调整的特定片段,保持其他所有内容的默认功能不变。

自定义提示的最简单方法

一个直接的方法是为您想要覆盖的提示创建一个 JSON 文件,然后让您的 Crew 指向该文件:
  1. 创建一个包含您更新后提示片段的 JSON 文件。
  2. 通过您的 Crew 中的 `prompt_file` 参数引用该文件。
然后,CrewAI 会将您的自定义项与默认值合并,因此您不必重新定义每个提示。操作如下:

示例:基本提示自定义

创建一个 `custom_prompts.json` 文件,其中包含您想要修改的提示。确保您列出了它应包含的所有顶级提示,而不仅仅是您的更改:
{
  "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 normal
researcher = 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 file
crew = Crew(
    agents=[researcher],
    tasks=[research_task],
    prompt_file="path/to/custom_prompts.json",
    verbose=True
)

# Run the crew
result = crew.kickoff()
通过这几处编辑,您就可以对代理如何沟通和解决任务进行低级控制。

针对特定模型进行优化

不同的模型在不同结构的提示下表现更佳。进行更深层次的调整可以通过使您的提示与模型的细微差别保持一致,从而显著提升性能。

示例:Llama 3.3 提示模板

例如,在处理 Meta 的 Llama 3.3 时,更深层次的自定义可能需要反映其推荐的结构,详见:https://www.llama.com/docs/model-cards-and-prompt-formats/llama3_1/#prompt-template 以下是一个示例,展示了如何微调一个代理以在代码中利用 Llama 3.3:
from crewai import Agent, Crew, Task, Process
from crewai_tools import DirectoryReadTool, FileReadTool

# Define templates for system, user (prompt), and assistant (response) messages
system_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 layouts
principal_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 model
    system_template=system_template,
    prompt_template=prompt_template,
    response_template=response_template,
    tools=[DirectoryReadTool(), FileReadTool()]
)

# Define a sample task
engineering_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 task
llama_crew = Crew(
    agents=[principal_engineer],
    tasks=[engineering_task],
    process=Process.sequential,
    verbose=True
)

# Execute the crew
result = llama_crew.kickoff()
print(result.raw)
通过这种更深层次的配置,您可以对基于 Llama 的工作流进行全面的低级控制,而无需单独的 JSON 文件。

结论

CrewAI 中的低级提示自定义为超级定制化、复杂的用例打开了大门。通过建立组织良好的提示文件(或直接的内联模板),您可以适应各种模型、语言和专业领域。这种灵活性确保您可以精确地打造所需的 AI 行为,同时知道在您不覆盖时,CrewAI 仍然提供可靠的默认设置。
现在您已经掌握了在 CrewAI 中进行高级提示自定义的基础。无论您是为了适应特定模型的结构还是特定领域的约束,这种低级方法都能让您以高度专业化的方式塑造代理的交互。