AI Agents for Beginners 如何为多步骤任务实现 Planning 设计模式的任务分解与结构化输出
AI Agents for Beginners 如何为多步骤任务实现 Planning 设计模式的任务分解与结构化输出
📅 发布时间:2026/9/13 8:58:12👁 浏览次数:
AI Agents for Beginners 如何为多步骤任务实现 Planning 设计模式的任务分解与结构化输出【免费下载链接】ai-agents-for-beginners18 Lessons to Get Started Building AI Agents项目地址: https://gitcode.com/GitHub_Trending/ai/ai-agents-for-beginners如果你的 Agent 面对的是一个多步骤任务——比如为新加坡到墨尔本的三口之家制定旅行计划——直接让一个 Agent 端到端处理容易失控。AI Agents for Beginners 课程的 Lesson 7Planning Design给出的做法是:先让一个 planning agent 把请求拆成带分配对象的子任务,并以 Pydantic 模型约束的结构化输出返回,再让执行层按依赖顺序逐条落地。本文按 07-planning-design/code_samples/07-python-agent-framework.ipynb 的可运行 notebook 为主路径,结合 07-planning-design/README.md 的讲解,给出从环境准备到验证输出的完整操作路径。准备条件:Foundry 项目、Python 环境与认证按 00-course-setup/README.md 的说明,本 notebook 的运行前提如下:Python 3.12(课程明确要求,若没有请先生成 3.12 的虚拟环境);一个已部署模型的 Microsoft Foundry 项目(课程示例部署gpt-5-mini,模型需支持 Responses API);Azure CLI,用于登录认证。环境准备按以下顺序执行:python -m venv venv source venv/bin/activate # Windows 用: venv\Scripts\activate pip install -r requirements.txt仓库根目录的requirements.txt包含运行代码样本所需的全部 Python 包。登录 Azure 并确认订阅:az login az account shownotebook 使用DefaultAzureCredential从az login会话取凭据,不需要在.env里放 API key。az account show能正常返回订阅信息,说明认证已就绪。然后创建环境变量文件。仓库根目录提供了 .env.example,复制后填写两项:cp .env.example .envAZURE_AI_PROJECT_ENDPOINThttps://your-project.services.ai.azure.com/api/projects/your-project-id AZURE_AI_MODEL_DEPLOYMENT_NAMEgpt-5-miniyour-project和your-project-id替换为你自己的项目值:Endpoint 在 Foundry 门户项目Overview页复制,部署名在Models Endpoints中选择已部署的模型查看(示例项目用gpt-5-mini)。定义结构化计划模型:TravelSubTask 与 TravelPlan任务分解的核心是用 Pydantic 模型把计划变成机器可读的对象。notebook 定义了两个模型:每个子任务有责任分配(assigned_agent)、优先级和依赖关系,整份计划携带目的地、天数和预算:class TravelSubTask(BaseModel): task_id: int description: str assigned_agent: str # flight_agent, hotel_agent, activity_agent priority: str # high, medium, low dependencies: list[int] [] class TravelPlan(BaseModel): destination: str trip_duration_days: int subtasks: list[TravelSubTask] total_estimated_budget_usd: int notes: strnotebook 说明这种拆法的收益是:每个子任务单一职责、无依赖的子任务可并行、失败隔离在单个子任务内、成本可按子任务估算后汇总。创建 Planning Agent 并用 response_format 生成结构化输出创建客户端并初始化 planning agent。以下代码来自 notebook 的 Setup 与 Planning 两个部分:import logging logging.getLogger(agent_framework.foundry).setLevel(logging.ERROR) import os, asyncio import dotenv from pydantic import BaseModel from agent_framework import tool from agent_framework.foundry import FoundryChatClient from azure.identity import DefaultAzureCredential dotenv.load_dotenv() endpoint os.getenv(AZURE_AI_PROJECT_ENDPOINT) deployment_name os.getenv(AZURE_AI_MODEL_DEPLOYMENT_NAME) missing [k for k, v in { AZURE_AI_PROJECT_ENDPOINT: endpoint, AZURE_AI_MODEL_DEPLOYMENT_NAME: deployment_name }.items() if not v] if missing: raise ValueError( fMissing required environment variables: {, .join(missing)}. Please set them as environment variables (e.g., in your .env file or shell environment). ) client FoundryChatClient( project_endpointendpoint, modeldeployment_name, credentialDefaultAzureCredential() )缺少任一环境变量时,notebook 会直接抛出上面的ValueError并列出缺失的变量名——这是运行前最直接的失败判断方式。planning agent 扮演前台协调者:把高层旅行请求拆成子任务、分派给专职 Agent、设定优先级与依赖、估算总预算:planning_agent client.as_agent( nameTravelPlanner, instructionsYou are a travel planning agent. When given a travel request: 1. Break it into specific subtasks (flights, hotels, activities, logistics) 2. Assign each subtask to the appropriate specialist agent 3. Set priorities and identify dependencies between tasks 4. Estimate the total budget, ) result await planning_agent.run( Plan a 7-day trip to Paris for a couple interested in art, cuisine, and history. Budget around $5000., options{response_format: TravelPlan} ) if result: plan result.value print(fDestination: {plan.destination}) print(fDuration: {plan.trip_duration_days} days) print(fBudget: ${plan.total_estimated_budget_usd}) print(f\nSubtasks:) for task in plan.subtasks: print(f [{task.priority}] {task.task_id}. {task.description} → {task.assigned_agent})关键在options{response_format: TravelPlan}:Agent 返回的是经过校验的TravelPlan对象,而不是自由文本。notebook 的 Summary 部分强调,这让下游处理reliable——你可以直接访问plan.destination、plan.subtasks等字段,而不用写解析逻辑。验证计划输出:检查字段与子任务结构运行上面的planning_agent.run(...)后,验证方式就是代码中的打印:Destination:/Duration:/Budget:三行确认顶层字段已被填充;Subtasks:列表按优先级 编号 描述 → 负责 agent的形式逐条列出,确认每个子任务确实被分配到了assigned_agent,且task_id、priority等字段符合TravelSubTask模型。课程 Lesson 7 文档(README)还展示了一份规划输出的文档示例,用于说明结构化计划长什么样(该示例来自 README 中另一套较简单的main_task/subtasks方案,结构与 notebook 的TravelPlan不同,仅作格式参考):{ is_greeting: False, main_task: Plan a family trip from Singapore to Melbourne., subtasks: [ { assigned_agent: flight_booking, task_details: Book round-trip flights from Singapore to Melbourne. }, { assigned_agent: hotel_booking, task_details: Find family-friendly hotels in Melbourne. }, { assigned_agent: car_rental, task_details: Arrange a car rental suitable for a family of four in Melbourne. }, { assigned_agent: activities_booking, task_details: List family-friendly activities in Melbourne. }, { assigned_agent: destination_info, task_details: Provide information about Melbourne as a travel destination. } ] }可选:用 Concierge Agent 与专职工具执行计划如果不止要生成计划还要执行计划,notebook 提供了执行层:三个演示工具各负责一类子任务,一个 concierge agent 按依赖顺序分派。注意这三个工具返回的是确认字符串(演示实现,不接真实预订系统):tool def book_flight( destination: Annotated[str, The destination city], departure_date: Annotated[str, Departure date (YYYY-MM-DD)], return_date: Annotated[str, Return date (YYYY-MM-DD)], ) - str: Search and book flights for the trip. return fFlight booked to {destination}: {departure_date} → {return_date}, confirmation #FLT-{hash(destination) % 10000:04d} tool def reserve_hotel( city: Annotated[str, The city for the hotel], check_in: Annotated[str, Check-in date (YYYY-MM-DD)], check_out: Annotated[str, Check-out date (YYYY-MM-DD)], guests: Annotated[int, Number of guests], ) - str: Reserve a hotel room in the destination city. return fHotel reserved in {city}: {check_in} to {check_out} for {guests} guests, confirmation #HTL-{hash(city) % 10000:04d} tool def book_activity( activity_name: Annotated[str, Name of the activity or tour], date: Annotated[str, Date of the activity (YYYY-MM-DD)], participants: Annotated[int, Number of participants], ) - str: Book a tour, museum visit, or other activity. return fActivity booked: {activity_name} on {date} for {participants} people, confirmation #ACT-{hash(activity_name) % 10000:04d} concierge_agent client.as_agent( nameConcierge, instructionsYou are a travel concierge executing a structured travel plan. Use the available tools to fulfil each subtask. Work through the subtasks in order, respecting dependencies. Summarise the results when finished., tools[book_flight, reserve_hotel, book_activity], ) if result.value: subtask_lines \n.join( f- [{t.priority}] {t.task_id}. {t.description} (agent: {t.assigned_agent}, deps: {t.dependencies}) for t in plan.subtasks ) execution_prompt ( fExecute the following travel plan for {plan.destination} f({plan.trip_duration_days} days, ${plan.total_estimated_budget_usd} budget):\n f{subtask_lines} ) exec_response await concierge_agent.run(execution_prompt) print(exec_response)执行层把上一步的TravelPlan拼成一条执行提示词(含目的地、天数、预算和逐条子任务),交给带工具的 concierge agent,最终输出各子任务的执行汇总。更简单的替代方案:提示词中约定 JSON 并手动解析07-planning-design/README.md 还给出了一个不依赖response_format的轻量写法:在 system prompt 中列出可用 Agent 并要求按固定 JSON 结构回答,拿到输出后json.loads解析。这里的client即前面创建好的FoundryChatClient:system_prompt You are a planner agent. Your job is to decide which agents to run based on the users request. Provide your response in JSON format with the following structure: {main_task: Plan a family trip from Singapore to Melbourne., subtasks: [{assigned_agent: flight_booking, task_details: Book round-trip flights from Singapore to Melbourne.} Below are the available agents specialised in different tasks: - FlightBooking: For booking flights and providing flight information - HotelBooking: For booking hotels and providing hotel information - CarRental: For booking cars and providing car rental information - ActivitiesBooking: For booking activities and providing activity information - DestinationInfo: For providing information about destinations - DefaultAgent: For handling general requests user_message Create a travel plan for a family of 2 kids from Singapore to Melbourne response client.create_response(inputuser_message, instructionssystem_prompt) response_content response.output_text pprint(json.loads(response_content))两种写法的取舍:JSON-in-prompt 方案更直观,解析后可以直接按assigned_agent路由到对应 Agent 并汇总计划;而 notebook 的response_format方案有 Pydantic 校验,TravelPlan对象直接可用。若下游要进入多 Agent 编排(单任务直发专职 Agent、多任务经 group chat manager 协调),README 建议按上述结构化输出做路由。迭代规划:把上一轮计划作为上下文重新规划README 指出部分任务需要来回重规划:某个子任务的结果会影响下一步(比如订机票时遇到意外的数据格式,需要在继续订酒店前调整策略),用户反馈(如改乘更早的航班)也会触发局部重规划。README 给出的示例片段是省略写法(原文标注 e.g sample code),context参数处应传入上一轮生成的计划内容:response client.create_response( inputuser_message, instructionssystem_prompt, contextfPrevious travel plan - {TravelPlan}, ) # .. re-plan and send the tasks to respective agents使用时把context中的{TravelPlan}替换为你实际持有的上一轮计划(例如上一步得到的plan对象序列化后的内容),再让 planner 输出修订后的任务分派。边界与后续本路径依赖 Microsoft Foundry 项目与az login会话;课程 setup 文档说明 Lesson 7 之外的某些课时(如 Lesson 6、8)走 Azure OpenAI Responses API 直连,环境变量不同,不要混用.env配置。工具层(book_flight等)是返回确认串的演示实现;要接真实服务,需要自行替换为实际的工具函数,课程未提供现成实现。课程 README 指向 Magentic One 作为更完整的通用多 Agent 规划系统参考(orchestrator 生成任务特定计划、跟踪进度并在必要时重规划),可进一步阅读。同一课时的 .NET 实现见 07-planning-design/code_samples/07-dotnet-agent-framework.md:它用ChatResponseFormatJson.ForJsonSchema把TravelPlan类生成 JSON Schema 作为结构化输出约束,思路与本文的response_formatTravelPlan一致。【免费下载链接】ai-agents-for-beginners18 Lessons to Get Started Building AI Agents项目地址: https://gitcode.com/GitHub_Trending/ai/ai-agents-for-beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考