langgraph通过专门的模型对请求进行结构化处理(比如规定字段、日期格式等),可以避免因格式不规范而导致的错误

发布于:2025-03-16 ⋅ 阅读:(23) ⋅ 点赞:(0)

示例代码:

primary_assistant_runnable = AGENT_PROMPTS.primary_assistant_prompt | CFG.llm.bind_tools(
            primary_assistant_tools
            + [
                ToFlightBookingAssistant,
                ToBookCarRentalAssistant,
                ToHotelBookingAssistant,
                ToBookExcursionAssistant,
            ]
        )

# Primary Assistant
class ToFlightBookingAssistant(BaseModel):
    """Transfers work to a specialized assistant to handle flight updates and cancellations."""

    request: str = Field(
        description="Any necessary followup questions the update flight assistant should clarify before proceeding."
    )


class ToBookCarRentalAssistant(BaseModel):
    """Transfers work to a specialized assistant to handle car rental bookings."""

    location: str = Field(
        description="The location where the user wants to rent a car."
    )
    start_date: str = Field(description="The start date of the car rental.")
    end_date: str = Field(description="The end date of the car rental.")
    request: str = Field(
        description="Any additional information or requests from the user regarding the car rental."
    )

    class Config:
        schema_extra = {
            "example": {
                "location": "Basel",
                "start_date": "2023-07-01",
                "end_date": "2023-07-05",
                "request": "I need a compact car with automatic transmission.",
            }
        }


class ToHotelBookingAssistant(BaseModel):
    """Transfer work to a specialized assistant to handle hotel bookings."""

    location: str = Field(
        description="The location where the user wants to book a hotel."
    )
    checkin_date: str = Field(description="The check-in date for the hotel.")
    checkout_date: str = Field(description="The check-out date for the hotel.")
    request: str = Field(
        description="Any additional information or requests from the user regarding the hotel booking."
    )

    class Config:
        schema_extra = {
            "example": {
                "location": "Zurich",
                "checkin_date": "2023-08-15",
                "checkout_date": "2023-08-20",
                "request": "I prefer a hotel near the city center with a room that has a view.",
            }
        }


class ToBookExcursionAssistant(BaseModel):
    """Transfers work to a specialized assistant to handle trip recommendation and other excursion bookings."""

    location: str = Field(
        description="The location where the user wants to book a recommended trip."
    )
    request: str = Field(
        description="Any additional information or requests from the user regarding the trip recommendation."
    )

    class Config:
        schema_extra = {
            "example": {
                "location": "Lucerne",
                "request": "The user is interested in outdoor activities and scenic views.",
            }
        }
        

这段代码中分了很多个Assistant,对整个系统模块化设计,这样所有任务不会在一个“大杂烩”里处理。


1. 绑定工具到主助手

primary_assistant_runnable = AGENT_PROMPTS.primary_assistant_prompt | CFG.llm.bind_tools(
            primary_assistant_tools
            + [
                ToFlightBookingAssistant,
                ToBookCarRentalAssistant,
                ToHotelBookingAssistant,
                ToBookExcursionAssistant,
            ]
        )

作用和含义

  • AGENT_PROMPTS.primary_assistant_prompt
    这部分可以理解为“主助手”的提示信息或初始上下文,告诉系统主助手应该怎么工作。

  • CFG.llm.bind_tools(…)
    这部分功能是将一系列“工具”(也就是不同任务的处理模块)绑定到主助手上。简单来说,就是告诉主助手:遇到具体的任务时,应该调用哪个“专门的小助手”来完成。

  • 工具列表中的各个 Assistant
    这里列出了四个专门的助手:

    • ToFlightBookingAssistant:负责处理航班相关的更新或取消。
    • ToBookCarRentalAssistant:负责处理租车业务。
    • ToHotelBookingAssistant:负责处理酒店预订。
    • ToBookExcursionAssistant:负责处理旅游行程或其他相关推荐。

举例说明

假设用户发出这样一个请求:“帮我取消明天的航班。”

  • 主助手会从整体提示中识别出这是与航班相关的请求,随后把任务转交给 ToFlightBookingAssistant
  • 如果用户请求:“帮我在巴塞尔租辆车,从2023-07-01到2023-07-05,要求小型自动挡车辆。”
    系统就会调用 ToBookCarRentalAssistant,并传递具体的参数:
    • location: “Basel”
    • start_date: “2023-07-01”
    • end_date: “2023-07-05”
    • request: “I need a compact car with automatic transmission.”

2. 各个专用 Assistant 的定义

2.1 ToFlightBookingAssistant

class ToFlightBookingAssistant(BaseModel):
    """Transfers work to a specialized assistant to handle flight updates and cancellations."""

    request: str = Field(
        description="Any necessary followup questions the update flight assistant should clarify before proceeding."
    )
  • 含义
    这个类用于处理与航班更新或取消相关的任务。

    • 它只包含一个字符串字段 request,用于记录用户的后续问题或额外需求。例如,用户可能会问:“请确认我的航班是否已取消?”这类信息会存入 request 字段。
  • 举例
    假如用户输入:“请帮我确认明天航班的状态。”
    那么这里的 request 字段就会被赋值为“请帮我确认明天航班的状态。”


2.2 ToBookCarRentalAssistant

class ToBookCarRentalAssistant(BaseModel):
    """Transfers work to a specialized assistant to handle car rental bookings."""

    location: str = Field(
        description="The location where the user wants to rent a car."
    )
    start_date: str = Field(description="The start date of the car rental.")
    end_date: str = Field(description="The end date of the car rental.")
    request: str = Field(
        description="Any additional information or requests from the user regarding the car rental."
    )

    class Config:
        schema_extra = {
            "example": {
                "location": "Basel",
                "start_date": "2023-07-01",
                "end_date": "2023-07-05",
                "request": "I need a compact car with automatic transmission.",
            }
        }
  • 含义
    这个类专门用于处理租车预订。它包含了四个必要的参数:

    • location:租车的地点(例如:巴塞尔)。
    • start_date:租车开始日期(例如:2023-07-01)。
    • end_date:租车结束日期(例如:2023-07-05)。
    • request:用户的额外要求(例如:要求小型自动挡车辆)。
  • 举例
    用户输入:“我想在巴塞尔租一辆车,从2023-07-01到2023-07-05,要求是小型车自动挡。”
    系统就会把这些信息对应填入各个字段,形成一个结构化数据,方便后续调用专门的租车预订服务。


2.3 ToHotelBookingAssistant

class ToHotelBookingAssistant(BaseModel):
    """Transfer work to a specialized assistant to handle hotel bookings."""

    location: str = Field(
        description="The location where the user wants to book a hotel."
    )
    checkin_date: str = Field(description="The check-in date for the hotel.")
    checkout_date: str = Field(description="The check-out date for the hotel.")
    request: str = Field(
        description="Any additional information or requests from the user regarding the hotel booking."
    )

    class Config:
        schema_extra = {
            "example": {
                "location": "Zurich",
                "checkin_date": "2023-08-15",
                "checkout_date": "2023-08-20",
                "request": "I prefer a hotel near the city center with a room that has a view.",
            }
        }
  • 含义
    这个类是为处理酒店预订而设计的,包含以下字段:

    • location:预订酒店所在的城市(例如:苏黎世)。
    • checkin_date:入住日期(例如:2023-08-15)。
    • checkout_date:退房日期(例如:2023-08-20)。
    • request:用户可能的其他要求(例如:希望酒店位于市中心且房间有好视野)。
  • 举例
    用户说:“我想在苏黎世预订一家酒店,8月15日入住,8月20日退房,最好房间有个大窗户看市景。”
    这些信息就会分别传递给 locationcheckin_datecheckout_daterequest 字段,帮助专门的酒店预订助手完成任务。


2.4 ToBookExcursionAssistant

class ToBookExcursionAssistant(BaseModel):
    """Transfers work to a specialized assistant to handle trip recommendation and other excursion bookings."""

    location: str = Field(
        description="The location where the user wants to book a recommended trip."
    )
    request: str = Field(
        description="Any additional information or requests from the user regarding the trip recommendation."
    )

    class Config:
        schema_extra = {
            "example": {
                "location": "Lucerne",
                "request": "The user is interested in outdoor activities and scenic views.",
            }
        }
  • 含义
    此类用于处理与旅游行程或户外活动相关的预订请求。

    • location:目的地(例如:卢塞恩)。
    • request:用户的具体需求描述(例如:对户外活动和美丽风景感兴趣)。
  • 举例
    用户可能说:“我想在卢塞恩参加一次户外探险,最好能看到美丽的山景。”
    这些信息会分别存入 locationrequest 字段,然后传递给对应的行程预订助手。


3. 没有这些专用 Assistant 的副作用

如果没有把任务划分给这些专门的 Assistant,会带来以下问题:

  1. 逻辑混乱

    • 主助手需要同时处理航班、租车、酒店和行程等多种类型的预订请求。这样不仅会使代码变得庞大而难以维护,而且每种业务逻辑会混在一起,出错的可能性增加。
  2. 难以扩展和维护

    • 每增加一个预订类型(例如增加火车票预订),都需要修改主助手的代码。而使用专用 Assistant 后,每个模块都是独立的,方便日后单独修改、扩展和测试。
  3. 用户请求处理不准确

    • 通过专门的模型对请求进行结构化处理(比如规定字段、日期格式等),可以避免因格式不规范而导致的错误。如果没有这些结构化的助手,可能会出现数据格式混乱、日期解析错误等问题。
  4. 复用性低

    • 模块化设计可以使各个助手独立部署和调用,从而在不同场景中复用这些功能。如果所有功能混在一起,就难以在其他系统中复用。

总结

这段代码通过定义四个专用助手类(分别处理航班、租车、酒店和行程预订)实现了业务逻辑的模块化设计,并将这些模块绑定到主助手中,使得整个系统能根据用户请求自动转交到相应的服务模块中处理。举例来说,当用户输入“在巴塞尔租车,从2023-07-01到2023-07-05,要求小型自动挡”时,**系统会自动将数据转化为结构化格式,**交给 ToBookCarRentalAssistant 处理。如果没有这些助手,主助手需要同时处理所有细节,不仅使代码臃肿,也容易引发各种错误和维护难题。

ToBookExcursionAssistant 类等其他工具类是如何在工具中被使用的,为什么bind_tools可以这样直接使用一个类

下面详细解释这个类在工具系统中是如何使用的,以及为什么像这样的类可以直接传给bind_tools使用,搞懂内部机制。


1. 这个类的作用和使用场景

ToBookExcursionAssistant 继承自 BaseModel(通常是Pydantic模型),它的主要作用是定义一个“行程预定助手”的数据结构。

  • 作用:
    • 规范用户输入:类中定义了两个字段 —— location(目的地)和 request(用户关于行程的其他要求)。
    • 自动验证数据:因为继承自Pydantic的 BaseModel,所以当系统把用户输入转换为这个类的实例时,会自动校验数据格式、类型和必填项。
  • 使用场景举例:
    假设用户发送请求:“我想在卢塞恩参加一次户外探险。”
    • 系统会自动将这个请求解析成一个数据结构,例如:
      • location: “Lucerne”
      • request: “The user is interested in outdoor activities and scenic views.”
    • 这个数据结构会作为参数传给专门处理行程推荐的逻辑。

2. bind_tools如何使用这个类

bind_tools 函数的主要作用是把一组工具(这里指各种任务的处理模块或助手)“绑定”到主助手上,使得在遇到特定请求时,主助手能够自动调用相应的工具来处理任务。

  • 工作原理:
    • 自动解析参数: bind_tools接受一个工具列表,这些工具其实就是一些定义了参数结构的类(比如继承了BaseModel的类)
    • 反射和元编程: 在内部,bind_tools会利用反射机制(即检查类中的字段、类型、描述等信息),动态地生成这些工具的接口或者调用函数。
    • 注册为可调用工具: 绑定后,当LLM在解析用户请求时,会根据提示信息识别出具体任务(例如行程预定),并且根据绑定的类自动生成一个带有正确参数结构的调用。

3. 为什么bind_tools可以直接使用一个类

直接使用一个类(而不是实例化后的对象)有以下优点:

  • 清晰的结构描述:

    • 类定义中包括了所有必要的字段、数据类型、说明和示例,这些信息可以帮助系统自动生成文档、参数验证规则以及用户界面的提示信息。
  • 自动参数验证:

    • 由于继承了Pydantic的BaseModel,系统可以在接收到用户输入时自动构造该类的实例,从而进行数据格式校验和错误提示。这避免了手动解析参数的繁琐操作。
  • 动态构建工具接口:

    • bind_tools内部会使用反射技术直接读取类中的元数据(如字段名称、描述等),进而生成一个与之对应的接口。这样一来,就不需要预先实例化对象,而是直接利用类定义来注册工具。
  • 模块化和扩展性:

    • 每个任务对应一个独立的类,使得代码高度模块化。以后如果需要增加其他功能,只需定义新的继承自BaseModel的类,然后把它加入到bind_tools中即可,不需要改动其他部分。

总结

  • 使用方式:
    这个类被当作一个工具的蓝图,通过bind_tools传入主助手模块。当用户请求行程预定时,系统会根据这个蓝图自动解析输入、校验数据,并调用相应的行程推荐逻辑。

  • 直接使用类的原因:
    因为类本身提供了清晰的参数结构、自动验证和描述信息,bind_tools可以直接利用这些信息来生成工具接口,而不需要额外包装或实例化。这样设计不仅提高了代码的复用性和模块化程度,也使得系统更易于维护和扩展。

在 Pydantic 中,class Config 是一个内置的特殊配置类,用来控制模型的一些行为和属性,而 schema_extra 则是 Config 类中的一个固定字段,用于提供额外的 JSON Schema 信息(例如示例数据)


网站公告

今日签到

点亮在社区的每一天
去签到