跳到主要内容

【课件资料】AutoGen中人机交互的三种模式

公开课内容节选自《大模型与Agent开发》完整版付费课程!

公开课时间有限,若想深度学习大模型技术,欢迎大家报名由我主讲的《大模型与Agent开发实战课》

4a3bf26aef95abca48eafdec1f47397

《大模型与Agent开发实战课》 为【100+小时】体系大课,总共20大模块精讲精析,零基础直达大模型企业级应用!

公开课直播特惠,全年最低价!低至 5 折 !扫码咨询课程信息哦👇

1728478294264


  在Agent应用系统开发过程中,往往由大模型负责大部分的处理和决策,但在某些复杂、模糊或高风险的场景下,一般请求人工干预来提供判断、修改或确认。"Human in the loop"(HIL)是指在对话过程中,某些时刻需要人工干预或输入来完成任务或进行决策。基本上成熟的Agent开发框架都会设计人工交互的逻辑。简而言之,它是一种设计模式,其中Agent和人类共同参与决策或执行任务的过程。

  在 AutoGenConversableAgent 中,human_input_mode 就是控制是否启用“Human in the loop”的核心参数。这个参数决定了是否在每次消息接收时请求人工输入,以及在何种情况下终止对话。human_input_mode 主要有以下几种设置:

  1. "NEVER"
    • 代理完全不需要人工输入。所有决策和回复都由代理自动完成,不需要人工干预。这种模式适用于较为简单的任务或自动化流程。
    • 示例:在标准的问答系统或自动化对话中,代理会自动回复问题,并且不会主动请求人工输入。

2. **"ALWAYS"**: - 代理会在每轮对话中都请求人工输入。这意味着系统的每个回应都可能需要人工确认或补充才能继续进行。 - 示例:当代理进行复杂推理时,系统可能会将计算结果或推理步骤呈现给人工来确认是否正确。

3. **"TERMINATE"**: - 这种模式下,代理仅在满足特定条件时(如终止消息或连续自动回复次数超过最大值时)请求人工输入。代理在大多数情况下会自动完成对话,但在满足条件时会请求人工干预来决定是否继续或结束对话。 - 示例:如果在对话过程中代理无法确定某个问题的答案,或者有较高风险的决策需要人工确认时,系统会询问人工以继续对话。

  在到具体的流程设计中,人机交互组件位于自动回复组件之前。它可以拦截传入的消息并决定是将其传递给自动回复组件还是提供人工反馈。如下图所示:

图片来源于 AutoGen 官方文档:https://microsoft.github.io/autogen/0.2/docs/tutorial/human-in-the-loop

  我们就依次实践一下这三种不同的模式,首先来看ALWAYS

  • NRVER

  在此模式下,从不请求人工输入,并且使用终止条件来终止。所以当我们希望代理完全自主行动时,此模式非常有用。比如如下代码:

# 创建两个代理:数学专家和数据分析师
math_expert = ConversableAgent(
name="math_expert", # 数学专家
system_message="你是数学专家,将帮助解决统计问题。",
llm_config={"config_list": config_model}, # 这里使用 config_model
is_termination_msg=lambda msg: "22" in msg["content"], # 如果回答是22,结束对话
human_input_mode="NEVER", # 不允许人工介入

)

data_analyst = ConversableAgent(
name="data_analyst", # 数据分析师
system_message="你是一名数据分析师。你的工作是验证和确认对数学问题的分析。",
llm_config={"config_list": config_model}, # 这里使用 config_model
human_input_mode="NEVER", # 不允许人工介入
)

# 启动对话:数学专家提出问题
result = math_expert.initiate_chat(
recipient=data_analyst,
message="总共有30名学生。18人通过了数学考试,12人通过了英语考试,8人通过了两门考试。有多少学生通过了数学或英语考试??",
summary_method="reflection_with_llm",
summary_args = {
"summary_role": "system", # 设置角色为 system
"summary_prompt": "请仅返回计算出来的最终结果,不要输出任何与结果无关的内容,一定要简洁。" # 这里添加摘要的提示词
},
)

# 输出结果
print(result)
print(result.summary)

  这里就可以看到,当添加了human_input_mode="NEVER"参数后,对话代理当触发了is_termination_msg条件后会自动终止。

  • ALWAYS

  在此模式下,始终请求人工输入,并且人工可以选择跳过、拦截或终止对话。这个场景下的应用示例就非常多了,比如我们设计一个市场营销分析任务,让代理之间将逐步合作来解决实际的商业问题。具体步骤包括:

  • 数学专家首先根据提供的数据进行基础的分析,计算各个广告渠道的投资回报率(ROI)。
  • 数据分析师负责验证数学专家的结果,并基于分析进一步给出结论,例如哪些渠道效果最好。
  • 总结阶段:在得到合理的结果后,数据分析师总结并确认是否可以终止对话
# 创建数学专家代理
math_expert = ConversableAgent(
name="math_expert", # 数学专家
system_message="你是财务分析的数学专家,负责进行营销活动数据分析和预算计算。",
llm_config=False, # 这里可以使用 False,因为 human_input_mode 设置为了 人工输入,所以无需 大模型介入
is_termination_msg=lambda msg: "再见" in msg["content"].lower(), # 如果分析完成并说 再见,终止对话
human_input_mode="ALWAYS", # 每轮都需要数学专家确认结果和提出新一轮的问题
)

# 创建数据分析师代理
data_analyst = ConversableAgent(
name="data_analyst", # 数据分析师
system_message="你是数据分析师,负责验证和确认数学专家的分析结果。",
llm_config={"config_list": config_model}, # 这里使用 config_model
human_input_mode="NEVER", # 每轮都进行自主分析和处理,不需要人工确认
)

# 启动对话:数学专家提出预算计算问题
result = math_expert.initiate_chat(
recipient=data_analyst,
message="我们进行了一项市场营销活动,以下是广告渠道的投入与回报数据:\n"
"1. 搜索广告:投入100万,回报200万\n"
"2. 社交媒体广告:投入50万,回报120万\n"
"3. 电视广告:投入200万,回报500万\n"
"请计算各个广告渠道的投资回报率(ROI),并返回结果。",
summary_method="reflection_with_llm", # 使用 LLM 进行对话总结
summary_args={
"summary_role": "system", # 设置角色为 system
"summary_prompt": "请简洁地返回各广告渠道的投资回报率(ROI)。确保计算准确。" # 这里添加摘要的提示词
},
)

# 输出对话结果
print(result)
print(result.summary)

  除此外,当 human_input_mode 设置为 "ALWAYS" 时,可触发的三个行为分别是:

  1. 输入内容:如果在提示框中输入了内容,代理将使用你输入的内容作为反馈,继续进行对话。

  2. 按下 Enter 跳过:如果按下 Enter,则代理会使用自动回复(即代理的自动回应行为),而不会等待人工输入继续对话。

  3. 输入 exit 退出对话:如果在输入框中输入 "exit",对话将结束,触发终止条件,结束当前会话。

  如果用户输入了内容,reply 会是用户输入的内容。如果用户按 Enter 跳过,reply 就是空字符串 ""self._is_termination_msg(message):这段代码会检查是否当前消息符合终止条件(例如,消息包含 "exit" 或其他设定的终止条件)。如果没有收到输入且消息是终止消息,reply 会被强制设为 "exit",从而结束对话。

  如下过程所示,当进入到人工交互的阶段,直接敲击Enter,则给出的提示是NO HUMAN INPUT RECEIVED.,且内容为空。

# 创建数学专家代理
math_expert = ConversableAgent(
name="math_expert", # 数学专家
system_message="你是财务分析的数学专家,负责进行营销活动数据分析和预算计算。",
llm_config=False, # 这里可以使用 False,因为 human_input_mode 设置为了 人工输入,所以无需 大模型介入
is_termination_msg=lambda msg: "再见" in msg["content"].lower(), # 如果分析完成并说 再见,终止对话
human_input_mode="ALWAYS", # 每轮都需要数学专家确认结果和提出新一轮的问题
)

# 创建数据分析师代理
data_analyst = ConversableAgent(
name="data_analyst", # 数据分析师
system_message="你是数据分析师,负责验证和确认数学专家的分析结果。",
llm_config={"config_list": config_model}, # 这里使用 config_model
human_input_mode="NEVER", # 每轮都进行自主分析和处理,不需要人工确认
)

# 启动对话:数学专家提出预算计算问题
result = math_expert.initiate_chat(
recipient=data_analyst,
message="我们进行了一项市场营销活动,以下是广告渠道的投入与回报数据:\n"
"1. 搜索广告:投入100万,回报200万\n"
"2. 社交媒体广告:投入50万,回报120万\n"
"3. 电视广告:投入200万,回报500万\n"
"请计算各个广告渠道的投资回报率(ROI),并返回结果。",
summary_method="reflection_with_llm", # 使用 LLM 进行对话总结
summary_args={
"summary_role": "system", # 设置角色为 system
"summary_prompt": "请简洁地返回各广告渠道的投资回报率(ROI)。确保计算准确。" # 这里添加摘要的提示词
},
)

# 输出对话结果
print(result)

  这是因为在ConversableAgent基类中,default_auto_reply就是''(空字符串)。

  因此,我们也可以手动的去设置自动回复的内容,比如在定义Agent的时候,添加default_auto_reply参数。代码如下:

# 创建数学专家代理
math_expert = ConversableAgent(
name="math_expert", # 数学专家
system_message="你是财务分析的数学专家,负责进行营销活动数据分析和预算计算。",
llm_config=False, # 这里可以使用 False,因为 human_input_mode 设置为了 人工输入,所以无需 大模型介入
is_termination_msg=lambda msg: "再见" in msg["content"].lower(), # 如果分析完成并说 再见,终止对话
human_input_mode="ALWAYS", # 每轮都需要数学专家确认结果和提出新一轮的问题,
default_auto_reply="请验证你的计算结果,确保百分百的准确率。"
)

# 创建数据分析师代理
data_analyst = ConversableAgent(
name="data_analyst", # 数据分析师
system_message="你是数据分析师,负责验证和确认数学专家的分析结果。",
llm_config={"config_list": config_model}, # 这里使用 config_model
human_input_mode="NEVER", # 每轮都进行自主分析和处理,不需要人工确认
)

# 启动对话:数学专家提出预算计算问题
result = math_expert.initiate_chat(
recipient=data_analyst,
message="我们进行了一项市场营销活动,以下是广告渠道的投入与回报数据:\n"
"1. 搜索广告:投入100万,回报200万\n"
"2. 社交媒体广告:投入50万,回报120万\n"
"3. 电视广告:投入200万,回报500万\n"
"请计算各个广告渠道的投资回报率(ROI),并返回结果。",
summary_method="reflection_with_llm", # 使用 LLM 进行对话总结
summary_args={
"summary_role": "system", # 设置角色为 system
"summary_prompt": "请简洁地返回各广告渠道的投资回报率(ROI)。确保计算准确。" # 这里添加摘要的提示词
},
)

# 输出对话结果
print(result)

 以上,就是AutoGen框架设计下的一个典型“人机交互”的模式,允许用户在每一轮对话后决定是否需要进行进一步的反馈或直接结束对话。

  • TERMINATE

  在此模式下,仅当满足终止条件时才请求人工输入。也就是说:当不触发is_termination_msg时,不会要求人工介入。

# 创建两个代理:数学专家和数据分析师
math_expert = ConversableAgent(
name="math_expert", # 数学专家
system_message="你是数学专家,将帮助解决统计问题。",
llm_config={"config_list": config_model}, # 这里使用 config_model
is_termination_msg=lambda msg: "22" in msg["content"], # 如果回答是22,结束对话
human_input_mode="TERMINATE", # 触发特定条件后人工介入

)

data_analyst = ConversableAgent(
name="data_analyst", # 数据分析师
system_message="你是一名数据分析师。你的工作是验证和确认对数学问题的分析。",
llm_config={"config_list": config_model}, # 这里使用 config_model
human_input_mode="TERMINATE", # 触发特定条件后人工介入
)

# 启动对话:数学专家提出问题
result = math_expert.initiate_chat(
recipient=data_analyst,
message="总共有30名学生。18人通过了数学考试,12人通过了英语考试,8人通过了两门考试。有多少学生通过了数学或英语考试?",
summary_method="reflection_with_llm",
summary_args = {
"summary_role": "system", # 设置角色为 system
"summary_prompt": "请仅返回计算出来的最终结果,不要输出任何与结果无关的内容,一定要简洁。" # 这里添加摘要的提示词
},
)

# 输出结果
print(result)

  所以才有了我们在第二小节实践控制代理终止时出现的情况,因为默认情况下,人工交互的模式会被设置为TERMINATE

  在 ConversableAgent 中,human_input_mode是实现 "Human in the loop" 的关键。通过控制这个参数的设置,系统可以决定何时依赖于自动化回复,何时需要人工干预。通过这种设计,系统可以结合自动化处理和人工灵活性,在面对不确定情况时做出更精准的决策。比如在下面这些现实场景中:

  1. 任务决策:例如,在一个法律文件分析系统中,当代理发现某些段落的解释模糊或涉及到法律漏洞时,可以请求人工专家提供帮助,确保解释符合实际法律规定。

  2. 异常处理:例如,在自动化的银行客服系统中,如果系统在执行交易时遇到异常(如超出限额、账户冻结等),可以让系统请求人工审核,防止错误操作。

  3. 复杂决策:例如,在智能客服中,代理可以根据用户反馈生成初步解决方案,但当解决方案涉及到复杂的个人化判断时(如复杂的产品推荐),代理会请求人工干预,确保推荐方案更加精准。

  至此,我们就掌握了ConversableAgent这个最关键的通用对话代理的底层构建逻辑。接下来,我们进一步探讨基于ConversableAgent类最具代表性的子类AssistantAgentUserProxyAgent

公开课内容节选自《大模型与Agent开发》完整版付费课程!

公开课时间有限,若想深度学习大模型技术,欢迎大家报名由我主讲的《大模型与Agent开发实战课》

4a3bf26aef95abca48eafdec1f47397

《大模型与Agent开发实战课》 为【100+小时】体系大课,总共20大模块精讲精析,零基础直达大模型企业级应用!

公开课直播特惠,全年最低价!低至 5 折 !扫码咨询课程信息哦👇

1728478294264