autogen 源码 (UserProxyAgent 类)

目录

    • 1. 原始代码
    • 2. 代码测试
    • 3. 代码的运行逻辑
    • 4. UserProxyAgent 类的核心功能
    • 5. UserProxyAgent 类的使用
    • 6. 运行时流程
    • 7. 总结

1. 原始代码

import asyncio
from inspect import iscoroutinefunction
from typing import Awaitable, Callable, List, Optional, Sequence, Union, castfrom autogen_core.base import CancellationTokenfrom ..base import Response
from ..messages import ChatMessage, HandoffMessage, TextMessage
from ._base_chat_agent import BaseChatAgent# Define input function types more precisely
SyncInputFunc = Callable[[str], str]
AsyncInputFunc = Callable[[str, Optional[CancellationToken]], Awaitable[str]]
InputFuncType = Union[SyncInputFunc, AsyncInputFunc]class UserProxyAgent(BaseChatAgent):"""An agent that can represent a human user through an input function.This agent can be used to represent a human user in a chat system by providing a custom input function.Args:name (str): The name of the agent.description (str, optional): A description of the agent.input_func (Optional[Callable[[str], str]], Callable[[str, Optional[CancellationToken]], Awaitable[str]]): A function that takes a prompt and returns a user input string... note::Using :class:`UserProxyAgent` puts a running team in a temporary blockedstate until the user responds. So it is important to time out the user inputfunction and cancel using the :class:`~autogen_core.base.CancellationToken` if the user does not respond.The input function should also handle exceptions and return a default response if needed.For typical use cases that involveslow human responses, it is recommended to use termination conditionssuch as :class:`~autogen_agentchat.task.HandoffTermination` or :class:`~autogen_agentchat.task.SourceMatchTermination`to stop the running team and return the control to the application.You can run the team again with the user input. This way, the state of the teamcan be saved and restored when the user responds.See `Pause for User Input <https://microsoft.github.io/autogen/dev/user-guide/agentchat-user-guide/tutorial/teams.html#pause-for-user-input>`_ for more information."""def __init__(self,name: str,*,description: str = "A human user",input_func: Optional[InputFuncType] = None,) -> None:"""Initialize the UserProxyAgent."""super().__init__(name=name, description=description)self.input_func = input_func or inputself._is_async = iscoroutinefunction(self.input_func)@propertydef produced_message_types(self) -> List[type[ChatMessage]]:"""Message types this agent can produce."""return [TextMessage, HandoffMessage]def _get_latest_handoff(self, messages: Sequence[ChatMessage]) -> Optional[HandoffMessage]:"""Find the HandoffMessage in the message sequence that addresses this agent."""if len(messages) > 0 and isinstance(messages[-1], HandoffMessage):if messages[-1].target == self.name:return messages[-1]else:raise RuntimeError(f"Handoff message target does not match agent name: {messages[-1].source}")return Noneasync def _get_input(self, prompt: str, cancellation_token: Optional[CancellationToken]) -> str:"""Handle input based on function signature."""try:if self._is_async:# Cast to AsyncInputFunc for proper typingasync_func = cast(AsyncInputFunc, self.input_func)return await async_func(prompt, cancellation_token)else:# Cast to SyncInputFunc for proper typingsync_func = cast(SyncInputFunc, self.input_func)loop = asyncio.get_event_loop()return await loop.run_in_executor(None, sync_func, prompt)except asyncio.CancelledError:raiseexcept Exception as e:raise RuntimeError(f"Failed to get user input: {str(e)}") from easync def on_messages(self, messages: Sequence[ChatMessage], cancellation_token: Optional[CancellationToken] = None) -> Response:"""Handle incoming messages by requesting user input."""try:# Check for handoff firsthandoff = self._get_latest_handoff(messages)prompt = (f"Handoff received from {handoff.source}. Enter your response: " if handoff else "Enter your response: ")# print(prompt)user_input = await self._get_input(prompt, cancellation_token)# print(user_input)# Return appropriate message type based on handoff presenceif handoff:return Response(chat_message=HandoffMessage(content=user_input, target=handoff.source, source=self.name))else:return Response(chat_message=TextMessage(content=user_input, source=self.name))except asyncio.CancelledError:raiseexcept Exception as e:raise RuntimeError(f"Failed to get user input: {str(e)}") from easync def on_reset(self, cancellation_token: Optional[CancellationToken] = None) -> None:"""Reset agent state."""pass

2. 代码测试

import asyncio
from typing import Optional, Sequenceimport pytest
from autogen_agentchat.agents import UserProxyAgent
from autogen_agentchat.base import Response
from autogen_agentchat.messages import ChatMessage, HandoffMessage, TextMessage
from autogen_core.base import CancellationTokendef custom_input(prompt: str) -> str:return "The height of the eiffel tower is 324 meters. Aloha!"agent = UserProxyAgent(name="test_user", input_func=custom_input)
messages = [TextMessage(content="What is the height of the eiffel tower?", source="assistant")
]response = asyncio.run(agent.on_messages(messages, CancellationToken()))print(response)

运行结果

Response(chat_message=TextMessage(source='test_user', models_usage=None, content='The height of the eiffel tower is 324 meters. Aloha!'), inner_messages=None)

3. 代码的运行逻辑

这段代码主要分为两部分:

  • UserProxyAgent 类的定义:这是一个模拟人类用户交互的代理类,接收用户输入并根据 input_func(输入函数)来处理输入。
  • 使用 UserProxyAgent 的示例:通过创建 UserProxyAgent 实例并调用它的 on_messages 方法来模拟一个简单的交互过程。

我们一步步分析这段代码的运行逻辑:

4. UserProxyAgent 类的核心功能

  1. __init__ 方法

    def __init__(self, name: str, *, description: str = "A human user", input_func: Optional[InputFuncType] = None) -> None:super().__init__(name=name, description=description)self.input_func = input_func or input  # 默认使用内置 input 函数self._is_async = iscoroutinefunction(self.input_func)  # 检查 input_func 是否是异步函数
    
    • input_func:用于获取用户输入的函数。可以是同步或异步函数。
    • self._is_async:判断 input_func 是同步的还是异步的。如果 input_func 是异步函数(例如 async def),则 self._is_asyncTrue
  2. produced_message_types 属性

    @property
    def produced_message_types(self) -> List[type[ChatMessage]]:return [TextMessage, HandoffMessage]
    

    这个属性定义了 UserProxyAgent 可以产生的消息类型。这里返回了 TextMessageHandoffMessage,这两种类型的消息可以由代理生成。

  3. _get_input 方法

    async def _get_input(self, prompt: str, cancellation_token: Optional[CancellationToken]) -> str:try:if self._is_async:async_func = cast(AsyncInputFunc, self.input_func)return await async_func(prompt, cancellation_token)else:sync_func = cast(SyncInputFunc, self.input_func)loop = asyncio.get_event_loop()return await loop.run_in_executor(None, sync_func, prompt)except Exception as e:raise RuntimeError(f"Failed to get user input: {str(e)}")
    

    _get_input 方法是根据 input_func 的类型(异步或同步)来获取用户输入:

    • 如果是异步函数,直接调用 await async_func(prompt, cancellation_token)
    • 如果是同步函数,使用 run_in_executor 将同步函数放入线程池中异步执行。
  4. on_messages 方法

    async def on_messages(self, messages: Sequence[ChatMessage], cancellation_token: Optional[CancellationToken] = None) -> Response:try:# Check for handoff firsthandoff = self._get_latest_handoff(messages)prompt = (f"Handoff received from {handoff.source}. Enter your response: " if handoff else "Enter your response: ")user_input = await self._get_input(prompt, cancellation_token)if handoff:return Response(chat_message=HandoffMessage(content=user_input, target=handoff.source, source=self.name))else:return Response(chat_message=TextMessage(content=user_input, source=self.name))except Exception as e:raise RuntimeError(f"Failed to get user input: {str(e)}")
    

    on_messages 方法是处理接收到的消息并根据 input_func 请求用户输入的核心方法。

    • 它首先检查是否有 handoff 消息,handoff 是一种消息转交机制,用于指示代理需要等待用户输入。
    • 然后,根据是否有 handoff,设置 prompt 提示用户输入,并调用 _get_input 获取用户输入。
    • 最后,根据输入生成 TextMessageHandoffMessage,并通过 Response 返回。

5. UserProxyAgent 类的使用

  1. 定义一个同步输入函数 custom_input

    def custom_input(prompt: str) -> str:return "The height of the Eiffel Tower is 324 meters. Aloha!"
    

    这是一个简单的同步函数,模拟用户输入。无论传入什么 prompt,它总是返回 “The height of the Eiffel Tower is 324 meters. Aloha!”。

  2. 创建 UserProxyAgent 实例

    agent = UserProxyAgent(name="test_user", input_func=custom_input)
    

    创建一个 UserProxyAgent 实例,name 设置为 “test_user”,并将 input_func 设置为刚定义的 custom_input 函数。

  3. 创建消息列表 messages

    messages = [TextMessage(content="What is the height of the Eiffel Tower?", source="assistant")
    ]
    

    这是一个消息列表,包含一条来自 “assistant” 的 TextMessage,询问 “What is the height of the Eiffel Tower?”。

  4. 调用 on_messages 方法

    response = asyncio.run(agent.on_messages(messages, CancellationToken()))
    

    这里使用 asyncio.run() 来运行异步的 on_messages 方法。
    messages 传递给 on_messages,模拟一个对话。代理通过 custom_input 获取用户输入。

  5. 输出响应

    print(response)
    

    最终输出的 responseon_messages 返回的结果。根据输入的不同,代理可能返回 TextMessageHandoffMessage

6. 运行时流程

  • on_messages 被调用,代理开始等待用户输入。
  • prompt 被设置为 “Enter your response:”,并调用 custom_input 获取用户输入。
  • 用户输入被模拟为 “The height of the Eiffel Tower is 324 meters. Aloha!”。
  • 生成并返回一个 TextMessage,其内容为用户输入的文本。
  • 最终,response 将是一个包含 TextMessageResponse 对象。

7. 总结

UserProxyAgent 是一个模拟用户交互的代理,能够根据不同类型的输入函数(同步或异步)来获取用户的回答。
on_messages 方法负责处理来自其他代理或系统的消息,等待并获取用户输入,生成适当的消息类型并返回。
示例代码模拟了一个简单的对话,其中用户输入的文本通过 UserProxyAgent 处理并返回。

参考链接:https://github.com/microsoft/autogen/blob/main/python/packages/autogen-agentchat/tests/test_userproxy_agent.py

如果有任何问题,欢迎在评论区提问。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/63156.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

沪合共融 “汽”势如虹 | 昂辉科技参加合肥上海新能源汽车产业融合对接会

为积极响应制造业重点产业链高质量发展行动号召&#xff0c;促进合肥、上海两地新能源汽车产业链上下游企业融合对接、协同发展&#xff0c;共同打造长三角世界级新能源汽车产业集群&#xff0c;11月28日&#xff0c;合肥市工信局组织部分县区工信部门及全市30余户新能源汽车产…

taro小程序马甲包插件

插件名 maloulab/taro-plugins-socksuppet-ci maloulab/taro-plugins-socksuppet-ci安装 yarn add maloulab/taro-plugins-socksuppet-ci or npm i maloulab/taro-plugins-socksuppet-ci插件描述 taro官方是提供了小程序集成插件的tarojs/plugin-mini-ci &#xff0c;且支持…

SpringBoot 基于 MVC 高校办公室行政事务管理系统:设计构思与实现范例展示

摘 要 身处网络时代&#xff0c;随着网络系统体系发展的不断成熟和完善&#xff0c;人们的生活也随之发生了很大的变化&#xff0c;人们在追求较高物质生活的同时&#xff0c;也在想着如何使自身的精神内涵得到提升&#xff0c;而读书就是人们获得精神享受非常重要的途径。为了…

vue 通过 image-conversion 实现图片压缩

简介 vue项目中&#xff0c;上传图片时如果图片很大&#xff0c;通过 image-conversion 压缩到指定大小 1. 安装依赖 npm i image-conversion --save2. 引用 import * as imageConversion from image-conversion3. 使用 const newFile new Promise((resolve) > {// 压…

vite5+vue3+Ts5 开源图片预览器上线

images-viewer-vue3&#xff1a;一款Vue3的轻量级图像查看器&#xff0c;它基于Flip动画技术&#xff0c;支持PC和h5移动网页预览照片&#xff0c;如果它是Vue3开发的产品。 npm开源地址:https://www.npmjs.com/package/images-viewer-vue3?activeTabreadme Flip 动画 < …

人工智能驱动的骗局会模仿熟悉的声音

由于人工智能技术的进步&#xff0c;各种现代骗局变得越来越复杂。 这些骗局现在包括人工智能驱动的网络钓鱼技术&#xff0c;即使用人工智能模仿家人或朋友的声音和视频。 诈骗者使用来自社交媒体的内容来制作深度伪造内容&#xff0c;要求提供金钱或个人信息。个人应该通过…

qt QGraphicsScale详解

1、概述 QGraphicsScale是Qt框架中提供的一个类&#xff0c;它提供了一种简单而灵活的方式在QGraphicsView框架中实现缩放变换。通过设置水平和垂直缩放因子、缩放中心点&#xff0c;可以创建各种缩放效果&#xff0c;提升用户界面的交互性和视觉吸引力。结合QPropertyAnimati…

【基础编程】面向对象编程(OOP)详细解析

面向对象编程&#xff08;OOP&#xff09;详细解析 一、核心概念解析 1. 类&#xff08;Class&#xff09; 类是构建对象的蓝图&#xff0c;定义了对象的属性和方法。通过类的实例化&#xff0c;生成实际的对象。 关键特点&#xff1a; 属性&#xff08;字段&#xff09;&…

车载VR可视化解决方案

车载VR可视化解决方案是通过融合跟踪用户头部运动的特殊预测算法与惯性测量数据而开发的。该系统将大范围虚拟现实跟踪技术与IMU传感器相结合&#xff0c;为VR和AR应用打造了一套全面的运动跟踪与渲染流程&#xff0c;极大地方便了虚拟现实头显制造商定制可视化流程。 该车载VR…

Cesium 给大量建筑贴上PBR纹理

Cesium 给大量建筑贴上PBR纹理 —— 使用 TilesBuilder 从 SHP 文件转换 在Cesium中使用PBR&#xff08;物理基础渲染&#xff09;纹理给大量建筑物贴图时&#xff0c;TilesBuilder 是一个常用的图形化工具&#xff0c;它可以将原始数据转换成Cesium支持的 3D Tiles 格式。如果…

MySQL 性能优化详解

MySQL 性能优化详解 硬件升级系统配置优化调整buffer_pool数据预热降低日志的磁盘落盘 表结构设计优化SQL语句及索引优化SQL优化实战案例 MySQL性能优化我们可以从以下四个维度考虑&#xff1a;硬件升级、系统配置、表结构设计、SQL语句和索引。 从成本上来说&#xff1a;硬件升…

CSS 快速上手

目录 一. CSS概念 二. CSS语法 1. 基本语法规范 2. CSS的三种引入方式 (1) 行内样式 (2) 内部样式表 (3) 外部样式表 3. CSS选择器 (1) 标签选择器 (2) 类选择器 (3) id选择器 (4) 通配符选择器 (5) 复合选择器 <1> 空格 <2> 没有空格 <3> &q…

EasyRTC支持嵌入式智能硬件与微信小程序实时通话

基础建设如此发达的时代&#xff0c;各种物联网设备都越来越普及&#xff0c;尤其是可穿戴设备和智能家居设备的发展&#xff0c;而在物联网设备中&#xff0c;视频物联网设备又是特别受人关注的设备&#xff0c;因为他们具备有看得见的属性&#xff0c;像智能家居里面的摄像头…

00. Nginx-知识网络

知识目录 语雀知识网络&#xff0c;点击“”-- 点击“”查看知识网络 01. Nginx-基础知识 02. Nginx-虚拟主机 03. Nginx-Web模块 04. Nginx-访问控制 05. Nginx-代理服务 06. Nginx-负载均衡 07. Nginx-动静分离 08. Nginx-平滑升级 09. Nginx-日志切割 10. Nginx-…

TDesign:Checkbox 多选框,实现购物车中的多选,全选

Checkbox 多选框 实际开发时碰到的BUG&#xff1a; 1、当点击全选后&#xff0c;视图中的列表不会选中 // 01.点击全选&#xff0c;for循环向selectIds添加id selectIds.add(id); update(["card"]); // 02.视图中selectIds当前选中项的合集&#xff0c;id必须是Strin…

MATLAB数学建模之画图汇总

MATLAB是一种强大的数学软件&#xff0c;广泛应用于工程计算、控制设计、信号处理等领域。在数学建模中&#xff0c;MATLAB的绘图功能可以帮助我们直观地展示数据和模型结果。 1. 二维数据曲线图 1.1 绘制二维曲线的基本函数 plot函数用于绘制二维平面上的线性坐标曲线图&am…

HarmonyOS 5.0应用开发——UIAbility生命周期

【高心星出品】 文章目录 UIAbility组件创建AbilityUIAbility的生命周期Create状态WindowStageCreate状态Foreground和Background状态WindowStageWillDestroy状态Destroy状态 UIAbility组件 UIAbility组件是一种包含UI的应用组件&#xff0c;主要用于和用户交互。 UIAbility组…

Netty 入门应用:结合 Redis 实现服务器通信

在上篇博客中&#xff0c;我们了解了 Netty 的基本概念和架构。本篇文章将带你深入实践&#xff0c;构建一个简单的 Netty 服务端&#xff0c;并结合 Redis 实现一个数据存取的示例。在这个场景中&#xff0c;Redis 作为缓存存储&#xff0c;Netty 作为服务端处理客户端请求。通…

轨道力学:兰伯特问题

轨道力学&#xff1a;兰伯特问题 引言 在轨道力学中&#xff0c;兰伯特问题是指在已知两个位置矢量和它们之间的飞行时间的情况下&#xff0c;求解连接这两个位置的轨道路径问题。该问题以18世纪的数学家约翰海因里希兰伯特&#xff08;Johann Heinrich Lambert&#xff09;命…

word实践:正文/标题/表图等的共用模板样式设置

说在前面 最近使用word新建文件很多&#xff0c;发现要给大毛病&#xff0c;每次新建一个word文件&#xff0c;标题/正文的字体、大小和间距都要重新设置一遍&#xff0c;而且每次设置这些样式都忘记了参数&#xff0c;今天记录一下&#xff0c;以便后续方便查看使用。现在就以…