链载Ai
标题: 剖析 LLM Agent 定义及返回结构体定义 [打印本页]
作者: 链载Ai 时间: 昨天 21:19
标题: 剖析 LLM Agent 定义及返回结构体定义
fromtypingimportList,Callable,Union,Optionalfromopenai.types.chatimportChatCompletionMessagefromopenai.types.chat.chat_completion_message_tool_callimport( ChatCompletionMessageToolCall, Function,)# Third-party importsfrompydanticimportBaseModel
AgentFunction =Callable[[],Union[str,"Agent",dict]]
classAgent(BaseModel): name:str="Agent" model:str="gpt-4o" instructions:Union[str,Callable[[],str]] ="You are a helpful agent." functions
ist[AgentFunction] = [] tool_choice:str=None parallel_tool_calls:bool=True
classResponse(BaseModel): messages
ist= [] agent:Optional[Agent] =None context_variables:dict= {} classResult(BaseModel): """ Encapsulates the possible return values for an agent function.
Attributes: value (str): The result value as a string. agent (Agent): The agent instance, if applicable. context_variables (dict): A dictionary of context variables """ value:str="" agent:Optional[Agent] =None context_variables:dict= {}
AgentFunction=Callable[[],Union[str,"Agent",dict]]
这是一个ingFang SC", miui, "Hiragino Sans GB", "Microsoft Yahei", sans-serif, "Source Han Serif";font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: 0.064px;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: pre-wrap;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;">类型别名(Type Alias),用于定义一个函数的签名,在 Python 的类型提示(Type Hints)中非常常见。我们来逐步分析它为什么这样定义、有什么好处,以及是否可以改进。ingFang SC", miui, "Hiragino Sans GB", "Microsoft Yahei", sans-serif, "Source Han Serif";font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: 0.064px;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;">📌 一、逐部分解释ingFang SC", miui, "Hiragino Sans GB", "Microsoft Yahei", sans-serif, "Source Han Serif";font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: 0.064px;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;">✅Callable[[], ...]ingFang SC", miui, "Hiragino Sans GB", "Microsoft Yahei", sans-serif, "Source Han Serif";font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.064px;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;" class="list-paddingleft-1">第一个[]表示参数列表(这里是空的),也可以写成Callable[[int, str], ...]等表示有参数的函数。ingFang SC", miui, "Hiragino Sans GB", "Microsoft Yahei", sans-serif, "Source Han Serif";font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: 0.064px;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;">✅Union[str, "Agent", dict]ingFang SC", miui, "Hiragino Sans GB", "Microsoft Yahei", sans-serif, "Source Han Serif";font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.064px;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;" class="list-paddingleft-1">str"Agent":字符串形式的类名(延迟求值,因为可能尚未定义);dict
ingFang SC", miui, "Hiragino Sans GB", "Microsoft Yahei", sans-serif, "Source Han Serif";font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.064px;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;">使用"Agent"而不是Agent是为了防止在类定义之前就引用它(比如在类内部定义函数时),Python 3.7+ 支持from __future__ import annotations后可以直接写Agent。
ingFang SC", miui, "Hiragino Sans GB", "Microsoft Yahei", sans-serif, "Source Han Serif";font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: 0.064px;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;">🧠 二、为什么要这样定义?ingFang SC", miui, "Hiragino Sans GB", "Microsoft Yahei", sans-serif, "Source Han Serif";font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: 0.064px;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;">✅ 1.提高可读性ingFang SC", miui, "Hiragino Sans GB", "Microsoft Yahei", sans-serif, "Source Han Serif";font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.064px;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;">将函数签名抽象为一个名字AgentFunction,可以让其他开发者更容易理解它的用途和结构。例如:
defmy_func()->AgentFunction:...
defmy_func()->Callable[[],Union[str,"Agent",dict]]:...
✅ 2.统一接口规范
如果你有很多函数或方法返回类似的结构(如状态、子代理、配置等),统一使用AgentFunction可以帮助你确保接口一致性。
✅ 3.支持多种行为
允许函数返回不同类型的值,适用于如下场景:
🔍 三、实际应用场景举例
假设你正在构建一个 Agent 框架,每个 agent 都可以决定下一步要做什么:
defdecide_next_action()->AgentFunction:ifshould_stop():return"STOP"elifneed_delegate():returnAnotherAgent()else:return{"action":"continue","data":...}🛠️ 四、是否有改进空间?
虽然当前定义已经很清晰,但根据你的具体需求,也可以考虑以下几点改进:
✅ 改进 1:使用Protocol定义更严格的函数接口(Python 3.8+)
如果你希望对函数的输入输出做更精确控制,可以用Protocol:
fromtypingimportProtocolclassAgentFunction(Protocol):def__call__(self)->Union[str,"Agent",dict]:...
这可以让你用类型检查器验证某个函数是否符合该协议。
✅ 改进 2:使用枚举代替字符串,提升语义清晰度(推荐)
如果你的返回值是一些固定的指令(如停止、继续、委托),建议用Enum替代字符串:
fromenumimportEnumclassAction(Enum):CONTINUE="continue"STOP="stop"DELEGATE="delegate"AgentFunction=Callable[[],Union[Action,"Agent",dict]]
这样可以避免拼写错误,并增强语义表达。
✅ 改进 3:封装返回值为统一的数据结构(推荐)
你可以定义一个统一的响应结构,让逻辑更清晰:
fromtypingimportOptional,Unionfromdataclassesimportdataclass@dataclassclassAgentResponse:action:str#如"continue","stop"next_agent:Optional["Agent"]=Noneoutput:Optional[dict]=NoneAgentFunction=Callable[[],AgentResponse]
这样可以避免多个返回类型带来的混乱,也方便后续扩展。这个Agent类定义基于 Python 的数据类(dataclass)或 Pydantic 的 BaseModel,假设是使用了 Pydantic 的BaseModel。它定义了一个代理(Agent)的模板,其中包含了一些属性来描述该代理的行为和功能。下面是对每个字段的分析以及潜在的改进点。
字段解析
name: str = "Agent"
- 改进建议:确保名字唯一性可能是一个好主意,尤其是在有多个代理实例时。
model: str = "gpt-4o"
- 改进建议:检查模型名称是否正确(例如,是否存在拼写错误如
gpt-4o应该是gpt-4或者其他有效模型名)。考虑使用枚举或者更严格的验证规则来限制允许的模型名称。
instructions: Union[str, Callable[[], str]] = "You are a helpful agent."
- 指令或初始化消息,可以是字符串或一个无参函数返回字符串。
- 改进建议:如果指令可能会根据某些条件动态生成,那么这种设计是非常灵活的。但是,如果大多数情况下都是静态文本,可能需要提供更好的默认示例或文档说明如何实现
Callable版本。
functions: List[AgentFunction] = []
- 改进建议:避免直接使用可变对象作为默认参数(即空列表),因为这可能导致意外的共享状态问题。应使用
None作为默认值,并在类内部处理初始化逻辑。
tool_choice: str = None
- 改进建议:明确工具的选择范围或类型,可以通过枚举或者自定义类型来增强类型安全性和代码可读性。
parallel_tool_calls: bool = True
- 改进建议:无需特别改进,但确保文档清晰地解释了这一选项的意义及其对性能的影响。
改进后的版本
fromtypingimportList,Optional,Union,CallablefrompydanticimportBaseModel# 假设 AgentFunction 是已经定义好的类型别名AgentFunction =Callable[[],Union[str,"Agent",dict]]classAgent(BaseModel): name:str="Agent"
# 确认模型名称的有效性 model:str="gpt-4"# 注意这里修正了模型名
# 提供了更详细的默认指令 instructions:Union[str,Callable[[],str]] ="You are an intelligent assistant designed to help users with their queries."
# 使用 None 代替直接定义可变默认值 functions:Optional[List[AgentFunction]] =None
# 定义工具选择的枚举或其他限制方式 tool_choice:Optional[str] =None
parallel_tool_calls:bool=True
# 初始化函数,用于设置默认值 def__init__(self, **data): super().__init__(**data) ifself.functionsisNone: self.functions = []
总结
- 对于可能变化的数据结构(如
functions),避免直接使用可变对象作为默认参数。 - 对于复杂或动态生成的属性(如
instructions),提供更加具体的指导或示例。 - 可以通过引入枚举或其他类型约束来提高
tool_choice的类型安全性。
| 欢迎光临 链载Ai (https://www.lianzai.com/) |
Powered by Discuz! X3.5 |