1、创建一个新的 CrewAI 项目 surprise_trip
crewai create crew surprise_trip
选择模型厂商和模型
生成.env
MODEL=gpt-4o
OPENAI_API_KEY=你的api_key
SERPER_API_KEY=你的SERPER api_key
2、探索项目结构
3、配置代理
修改 agents.yaml文件。
# 个性化活动规划师 Agent
personalized_activity_planner:
# 角色名称:用于识别 agent 的职责(对模型来说类似标题)
role: >
活动规划师
# 目标描述:告诉 agent 它要完成的任务目标
goal: >
调研并寻找目的地的有趣活动和事件,确保这些内容符合旅行者的兴趣和年龄段
# 背景故事:为 agent 赋予人设,增强语言模型的代入感,提升生成质量
backstory: >
你擅长根据旅行者的具体偏好和人群特点设计个性化的行程安排,
你能快速找到最适合他们的活动组合,打造难忘的旅程。
# 餐厅探索者 Agent
restaurant_scout:
role: >
餐厅侦查员
goal: >
寻找目的地评分高的餐厅和用餐体验,并推荐风景优美和有趣的场所
backstory: >
你是一个热爱美食的人,熟悉本地最棒的用餐地点,
你总能找到既美味又有氛围的餐厅,同时也能发现风景优美和适合游玩的好地方。
# 行程整合者 Agent
itinerary_compiler:
role: >
行程整合师
goal: >
整合所有调研到的信息,编排成一个完整的逐日行程安排,确保包含航班与酒店信息;
请用中文输出;
backstory: >
你擅长组织和呈现信息,注重细节,能够把零散内容整合为一个条理清晰、愉快易行的旅行计划。
4、配置任务
修改这个 tasks.yaml文件。
# 个性化活动规划任务
personalized_activity_planning_task:
# 任务描述:为旅行者寻找符合兴趣和年龄段的活动与事件
description: >
调研并发现适合在 {destination} 进行的有趣活动。
重点关注符合旅行者兴趣和年龄段的活动和事件。
利用互联网搜索工具和推荐引擎获取信息。
旅行者信息如下:
- 出发地: {origin}
- 目的地: {destination}
- 年龄: {age}
- 酒店位置: {hotel_location}
- 航班信息: {flight_information}
- 旅行时长: {trip_duration}
# 预期输出:旅行期间每天推荐的活动清单
expected_output: >
一份按天列出的活动与事件推荐清单。
每一项应包含活动名称、地点、简要描述、适合旅行者的理由,
并尽可能附上评论和评分信息。
# 餐厅与风景地点探索任务
restaurant_scenic_location_scout_task:
# 任务描述:寻找优质餐厅与适合游玩的风景地
description: >
在 {destination} 寻找高评分的餐厅和独特的用餐体验。
推荐风景优美的地点和有趣的活动,符合旅行者偏好。
使用互联网搜索工具、餐厅评论网站和旅行指南。
提供多样化选择,满足不同口味与预算,并提供评分信息。
旅行者信息如下:
- 出发地: {origin}
- 目的地: {destination}
- 年龄: {age}
- 酒店位置: {hotel_location}
- 航班信息: {flight_information}
- 旅行时长: {trip_duration}
# 预期输出:每天推荐的餐厅与景点清单
expected_output: >
一份按天列出的推荐餐厅、风景地点和活动清单。
每一项应包括名称、地址、菜系或活动类型、简要描述及评分信息。
# 行程整合任务
itinerary_compilation_task:
# 任务描述:整合所有信息为完整的行程规划文档
description: >
整合所有调研信息,编排出 {destination} 的完整日程安排。
行程应包含航班、酒店信息、计划的每日活动与用餐安排。
使用文本格式化与文档生成工具进行内容组织与美化。
# 预期输出:结构化的日程表
expected_output: >
一份详细的旅行行程文档。内容应包含逐日安排,
并整合航班、酒店、活动、餐厅和风景地点等信息。
格式为 Markdown,不带“```”
5、配置团队
修改这个 crew.py文件
from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task
# 如果你有自定义工具,可以取消以下注释导入自定义工具
# from surprise_travel.tools.custom_tool import MyCustomTool
# 以下是 CrewAI 提供的内置工具,用于网页搜索与抓取
from crewai_tools import SerperDevTool, ScrapeWebsiteTool
from pydantic import BaseModel, Field
from typing import List, Optional
# 活动模型类:表示一天中安排的某一项活动
class Activity(BaseModel):
name: str = Field(..., description="活动名称")
location: str = Field(..., description="活动地点")
description: str = Field(..., description="活动描述")
date: str = Field(..., description="活动日期")
cousine: str = Field(..., description="餐厅的菜系类型")
why_its_suitable: str = Field(..., description="为什么这项活动适合旅行者")
reviews: Optional[List[str]] = Field(..., description="活动的评论列表")
rating: Optional[float] = Field(..., description="活动评分")
# 每日旅行计划模型类
class DayPlan(BaseModel):
date: str = Field(..., description="当天的日期")
activities: List[Activity] = Field(..., description="当天的活动列表")
restaurants: List[str] = Field(..., description="当天推荐的餐厅列表")
flight: Optional[str] = Field(None, description="当天的航班信息(如有)")
# 整体行程模型类
class Itinerary(BaseModel):
name: str = Field(..., description="行程名称,可以有趣一点")
day_plans: List[DayPlan] = Field(..., description="每天的行程计划列表")
hotel: str = Field(..., description="酒店信息")
# 使用 CrewBase 装饰器标记为 Crew 项目的入口
@CrewBase
class SurpriseTravelCrew():
"""SurpriseTravel 旅行策划团队(crew)"""
# 代理配置文件路径(YAML 格式)
agents_config = 'config/agents.yaml'
# 任务配置文件路径(YAML 格式)
tasks_config = 'config/tasks.yaml'
# 个性化活动规划 agent
@agent
def personalized_activity_planner(self) -> Agent:
return Agent(
config=self.agents_config['personalized_activity_planner'], # 从配置文件加载 agent 设置
tools=[SerperDevTool(), ScrapeWebsiteTool()], # 使用搜索和网页抓取工具
verbose=True, # 输出详细执行日志
allow_delegation=False, # 禁止任务委托给其他代理
)
# 餐厅与景点推荐 agent
@agent
def restaurant_scout(self) -> Agent:
return Agent(
config=self.agents_config['restaurant_scout'],
tools=[SerperDevTool(), ScrapeWebsiteTool()],
verbose=True,
allow_delegation=False,
)
# 整合所有信息并输出最终行程的 agent
@agent
def itinerary_compiler(self) -> Agent:
return Agent(
config=self.agents_config['itinerary_compiler'],
tools=[SerperDevTool()],
verbose=True,
allow_delegation=False,
)
# 个性化活动规划任务
@task
def personalized_activity_planning_task(self) -> Task:
return Task(
config=self.tasks_config['personalized_activity_planning_task'],
agent=self.personalized_activity_planner() # 指定任务负责的 agent
)
# 餐厅与风景位置探索任务
@task
def restaurant_scenic_location_scout_task(self) -> Task:
return Task(
config=self.tasks_config['restaurant_scenic_location_scout_task'],
agent=self.restaurant_scout()
)
# 编译最终行程任务,并指定输出格式为 Itinerary 数据模型
@task
def itinerary_compilation_task(self) -> Task:
return Task(
config=self.tasks_config['itinerary_compilation_task'],
agent=self.itinerary_compiler(),
output_json=Itinerary # 指定结构化输出格式
)
@task
def reporting_task(self) -> Task:
return Task(
config=self.tasks_config['itinerary_compilation_task'], # type: ignore[index]
agent=self.itinerary_compiler(),
output_file='report-01.md'
)
# 将 agents 与 tasks 组装成一个完整的 crew 执行流
@crew
def crew(self) -> Crew:
"""创建 SurpriseTravel 团队,定义其执行流程"""
return Crew(
agents=self.agents, # 所有注册的代理(通过 @agent 自动生成)
tasks=self.tasks, # 所有注册的任务(通过 @task 自动生成)
process=Process.sequential, # 顺序执行所有任务
verbose=True,
# 如需使用分层流程,也可使用以下配置:
# process=Process.hierarchical, 参考:https://docs.crewai.com/how-to/Hierarchical/
)
6、配置主函数
修改这个 main.py文件
# 指定使用 Python 解释器运行该脚本
import sys
import warnings # 导入警告处理模块
from datetime import datetime # 导入处理日期和时间的模块
from surprise_trip.crew import SurpriseTravelCrew # 从项目中导入 SurpriseTravelCrew 类
# 关闭特定模块中的语法警告(此处为 pysbd 模块)
warnings.filterwarnings("ignore", category=SyntaxWarning, module="pysbd")
# 此主程序文件是为了在本地运行 crew 而设计的,请勿在此文件中添加不必要的逻辑。
# 你可以替换下面的 inputs 变量,它会自动填充任务和代理的信息。
def run():
"""
运行 crew 执行流程。
"""
# 设置输入参数,可以根据需要修改。它会自动被各个任务和 agent 使用。
inputs = {
'origin': '上海虹桥机场(SHA)', # 出发地
'destination': '北京大兴机场(PKX)', # 目的地
'age': 31, # 用户年龄
'hotel_location': '北京朝阳区', # 希望住的酒店位置
'flight_information': '国航 CA1234,起飞时间为 2025年6月30日 上午10:00', # 航班信息
'trip_duration': '14 天' # 旅行时长
}
try:
# 实例化 SurpriseTravelCrew 并运行 crew 的 kickoff 方法(启动执行流程)
SurpriseTravelCrew().crew().kickoff(inputs=inputs)
except Exception as e:
# 捕获并抛出异常,便于调试
raise Exception(f"运行 crew 时发生错误: {e}")
def train():
"""
训练 crew,执行指定次数的迭代。
"""
inputs = {
'origin': '上海虹桥机场(SHA)', # 出发地
'destination': '北京大兴机场(PKX)', # 目的地
'age': 31, # 用户年龄
'hotel_location': '北京朝阳区', # 希望住的酒店位置
'flight_information': '国航 CA1234,起飞时间为 2025年6月30日 上午10:00', # 航班信息
'trip_duration': '14 天' # 旅行时长
}
try:
# 通过命令行参数获取迭代次数和保存的模型文件名
# 使用 crew 的 train 方法进行训练
SurpriseTravelCrew().crew().train(n_iterations=int(sys.argv[1]), filename=sys.argv[2], inputs=inputs)
except Exception as e:
# 捕获并抛出异常,便于调试
raise Exception(f"训练 crew 时发生错误: {e}")
def replay():
"""
从指定的任务 ID 开始回放 crew 执行过程。
"""
try:
# 从命令行参数中获取任务 ID,并调用 replay 方法回放
SurpriseTravelCrew().crew().replay(task_id=sys.argv[1])
except Exception as e:
# 捕获并抛出异常,便于调试
raise Exception(f"回放 crew 时发生错误: {e}")
def test():
"""
测试 crew 的执行逻辑,并返回评估结果。
"""
# 设置测试输入
inputs = {
"topic": "AI LLMs", # 测试主题,例如大语言模型
"current_year": str(datetime.now().year) # 当前年份
}
try:
# 从命令行参数中获取迭代次数和用于评估的 LLM 名称,调用 test 方法进行测试
SurpriseTravelCrew().crew().test(n_iterations=int(sys.argv[1]), eval_llm=sys.argv[2], inputs=inputs)
except Exception as e:
# 捕获并抛出异常,便于调试
raise Exception(f"测试 crew 时发生错误: {e}")
7、运行crew 启动项目
7.1、项目初始化(可选)
crewai install
7.2、启动项目
#要到项目根目录下
crewai run
8、查看思考和执行过程
中间省略...