Skip to main content

与多模态模型互动:在 AutoGen 中使用 GPT-4V

在 AutoGen 中,可以通过两种不同的方法利用多模态模型:1. MultimodalAgent:该代理基于 GPT-4V 和其他 LMM(语言模态模型),具有视觉认知能力,能够进行与其他可对话代理相媲美的交互。2. VisionCapability:对于缺乏固有视觉理解能力的 LLM(语言模态模型)代理,我们通过将图像转换为描述性标题来引入视觉能力。

本指南将深入探讨每种方法,提供有关它们的应用和集成的见解。

在开始之前,使用 lmm 选项安装 AutoGen

安装 pyautogen

pip install "pyautogen[lmm]>=0.2.17"

有关更多信息,请参阅安装指南

import json
import os
import random
import time
from typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union

import matplotlib.pyplot as plt
import numpy as np
import requests
from PIL import Image
from termcolor import colored

import autogen
from autogen import Agent, AssistantAgent, ConversableAgent, UserProxyAgent
from autogen.agentchat.contrib.capabilities.vision_capability import VisionCapability
from autogen.agentchat.contrib.img_utils import get_pil_image, pil_to_data_uri
from autogen.agentchat.contrib.multimodal_conversable_agent import MultimodalConversableAgent
from autogen.code_utils import content_str

## 应用 1:图像对话

在本节中,我们介绍了一种简单的双代理架构,使用户能够与多模态代理进行对话。

首先,我们展示这张图片并提出一个问题。

在用户代理中,我们可以决定是否激活人工输入模式(在这里,我们使用 human_input_mode=“NEVER” 来简洁起见)。这使您可以与 LMM 进行多轮对话,随着对话的展开,您可以提供反馈。

config_list_4v = autogen.config_list_from_json(
"OAI_CONFIG_LIST",
filter_dict={
"model": ["gpt-4-vision-preview"],
},
)


config_list_gpt4 = autogen.config_list_from_json(
"OAI_CONFIG_LIST",
filter_dict={
"model": ["gpt-4", "gpt-4-0314", "gpt4", "gpt-4-32k", "gpt-4-32k-0314", "gpt-4-32k-v0314"],
},
)

gpt4_llm_config = {"config_list": config_list_gpt4, "cache_seed": 42}
config_list_4v = autogen.config_list_from_json(
"OAI_CONFIG_LIST",
filter_dict={
"model": ["gpt-4-vision-preview"],
},
)


config_list_gpt4 = autogen.config_list_from_json(
"OAI_CONFIG_LIST",
filter_dict={
"model": ["gpt-4", "gpt-4-0314", "gpt4", "gpt-4-32k", "gpt-4-32k-0314", "gpt-4-32k-v0314"],
},
)

gpt4_llm_config = {"config_list": config_list_gpt4, "cache_seed": 42}
config_list_4v = autogen.config_list_from_json(
"OAI_CONFIG_LIST",
filter_dict={
"model": ["gpt-4-vision-preview"],
},
)


config_list_gpt4 = autogen.config_list_from_json(
"OAI_CONFIG_LIST",
filter_dict={
"model": ["gpt-4", "gpt-4-0314", "gpt4", "gpt-4-32k", "gpt-4-32k-0314", "gpt-4-32k-v0314"],
},
)

gpt4_llm_config = {"config_list": config_list_gpt4, "cache_seed": 42}

了解有关为代理配置LLM的更多信息,请点击这里

image_agent = MultimodalConversableAgent(
name="image-explainer",
max_consecutive_auto_reply=10,
llm_config={"config_list": config_list_4v, "temperature": 0.5, "max_tokens": 300},
)

user_proxy = autogen.UserProxyAgent(
name="User_proxy",
system_message="A human admin.",
human_input_mode="NEVER", # 尝试 ALWAYS 或 NEVER
max_consecutive_auto_reply=0,
code_execution_config={
"use_docker": False
}, # 如果有可用的docker来运行生成的代码,请设置use_docker=True。使用docker比直接运行生成的代码更安全。
)

# 用一张图片提问
user_proxy.initiate_chat(
image_agent,
message="""这只狗是什么品种?
<img https://th.bing.com/th/id/R.422068ce8af4e15b0634fe2540adea7a?rik=y4OcXBE%2fqutDOw&pid=ImgRaw&r=0>.""",
)
User_proxy (to image-explainer):

这只狗是什么品种?
<image>.

--------------------------------------------------------------------------------

>>>>>>>> 使用自动回复...
image-explainer (to User_proxy):

这张图片中的狗看起来是一只Goldendoodle,它是金毛寻回犬和贵宾犬的混合品种。它们以卷曲的、不过敏的毛发而闻名,毛色各异,性格友好和亲切。

--------------------------------------------------------------------------------
/home/beibinli/autogen/autogen/agentchat/conversable_agent.py:1121: UserWarning: 无法使用last_msg提取摘要: 'list' object has no attribute 'replace'。使用空字符串作为摘要。
warnings.warn(f"Cannot extract summary using last_msg: {e}. Using an empty str as summary.", UserWarning)
ChatResult(chat_id=None, chat_history=[{'content': "这只狗是什么品种?\n<img https://th.bing.com/th/id/R.422068ce8af4e15b0634fe2540adea7a?rik=y4OcXBE%2fqutDOw&pid=ImgRaw&r=0>.", 'role': 'assistant'}, {'content': '这张图片中的狗看起来是一只Goldendoodle,它是金毛寻回犬和贵宾犬的混合品种。它们以卷曲的、不过敏的毛发而闻名,毛色各异,性格友好和亲切。', 'role': 'user'}], summary='', cost=({'total_cost': 0.013030000000000002, 'gpt-4-1106-vision-preview': {'cost': 0.013030000000000002, 'prompt_tokens': 1132, 'completion_tokens': 57, 'total_tokens': 1189}}, {'total_cost': 0}), human_input=[])

现在,再输入一张图片,并提出一个后续问题。

# 用一张图片提问
user_proxy.send(
message="""这是什么品种?
<img https://th.bing.com/th/id/OIP.29Mi2kJmcHHyQVGe_0NG7QHaEo?pid=ImgDet&rs=1>

在这些品种中,哪一种叫声较少?""",
recipient=image_agent,
)
User_proxy (对 image-explainer):

这是什么品种的狗?
<image>

在各种品种中,哪一种狗叫声较少?

--------------------------------------------------------------------------------

>>>>>>>> 使用自动回复...
image-explainer (对 User_proxy):

图片中的狗是一只西伯利亚哈士奇。它们以其引人注目的外貌而闻名,拥有浓密的毛发、竖立的三角形耳朵和独特的斑纹。

当比较西伯利亚哈士奇和金毛波比犬的叫声倾向时,一般认为哈士奇叫声较少。西伯利亚哈士奇更倾向于嚎叫和以其他方式发出声音,而不是叫喊。金毛波比犬的叫声倾向可能会因其从金毛猎犬和贵宾犬父母那里继承的特征而有所不同。然而,每只狗都是独立的个体,它们的环境、训练和社交化会极大地影响它们的叫声倾向。

--------------------------------------------------------------------------------

## 应用2:图形生成器

在这里,我们定义了一个FigureCreator代理,它包含三个子代理:指挥官、编码器和评论家。

  • 指挥官:与用户交互,运行代码,并协调编码器和评论家之间的流程。
  • 编码器:为可视化编写代码。
  • 评论家:基于LMM的代理,对生成的图像提供评论和反馈。
working_dir = "tmp/"
class FigureCreator(ConversableAgent):
def __init__(self, n_iters=2, **kwargs):
"""
初始化一个FigureCreator实例。

该代理通过其子代理(指挥官、编码器和评论家)的协作努力来促进可视化的创建。

参数:
- n_iters(int,可选):要运行的“改进”迭代次数。默认为2。
- **kwargs:父AssistantAgent的关键字参数。
"""
super().__init__(**kwargs)
self.register_reply([Agent, None], reply_func=FigureCreator._reply_user, position=0)
self._n_iters = n_iters

def _reply_user(self, messages=None, sender=None, config=None):
if all((messages is None, sender is None)):
error_msg = f"必须提供{messages=}{sender=}之一。"
logger.error(error_msg) # noqa: F821
raise AssertionError(error_msg)
if messages is None:
messages = self._oai_messages[sender]

user_question = messages[-1]["content"]

### 定义代理
commander = AssistantAgent(
name="指挥官",
human_input_mode="NEVER",
max_consecutive_auto_reply=10,
system_message="帮我运行代码,并告诉其他代理它在<img result.jpg>文件位置。",
is_termination_msg=lambda x: x.get("content", "").rstrip().endswith("TERMINATE"),
code_execution_config={"last_n_messages": 3, "work_dir": working_dir, "use_docker": False},
llm_config=self.llm_config,
)

critics = MultimodalConversableAgent(
name="评论家",
system_message="""批评输入的图形。如何重新绘制图形使其更好?找出图形的错误和问题。
注意颜色、格式和呈现方式。要考虑读者友好性。
如果您认为图形已经足够好了,只需说“NO_ISSUES”""",
llm_config={"config_list": config_list_4v, "max_tokens": 300},
human_input_mode="NEVER",
max_consecutive_auto_reply=1,
# use_docker=False,
)

coder = AssistantAgent(
name="编码器",
llm_config=self.llm_config,
)

coder.update_system_message(
coder.system_message
+ "始终将图形保存在`result.jpg`文件中。告诉其他代理它在<img result.jpg>文件位置。"
)

# 数据流开始
commander.initiate_chat(coder, message=user_question)
img = Image.open(os.path.join(working_dir, "result.jpg"))
plt.imshow(img)
plt.axis("off") # 隐藏坐标轴
plt.show()

for i in range(self._n_iters):
commander.send(
message=f"改进 <img {os.path.join(working_dir, 'result.jpg')}>",
recipient=critics,
request_reply=True,
)

feedback = commander._oai_messages[critics][-1]["content"]
if feedback.find("NO_ISSUES") >= 0:
break
commander.send(
message="这是对您的图形的反馈。请改进!将结果保存到`result.jpg`\n"
+ feedback,
recipient=coder,
request_reply=True,
)
img = Image.open(os.path.join(working_dir, "result.jpg"))
plt.imshow(img)
plt.axis("off") # 隐藏坐标轴
plt.show()

return True, os.path.join(working_dir, "result.jpg")
creator = FigureCreator(name="图表生成器~", llm_config=gpt4_llm_config)

user_proxy = autogen.UserProxyAgent(
name="用户", human_input_mode="NEVER", max_consecutive_auto_reply=0, code_execution_config={"use_docker": False}
)

user_proxy.initiate_chat(
creator,
message="""
使用以下数据绘制图表:
https://raw.githubusercontent.com/vega/vega/main/docs/data/seattle-weather.csv

我想展示温度的最高值和最低值。
""",
)
用户 (对图表生成器~):


使用以下数据绘制图表:
https://raw.githubusercontent.com/vega/vega/main/docs/data/seattle-weather.csv

我想展示温度的最高值和最低值。


--------------------------------------------------------------------------------
指挥官 (对程序员):


使用以下数据绘制图表:
https://raw.githubusercontent.com/vega/vega/main/docs/data/seattle-weather.csv

我想展示温度的最高值和最低值。


--------------------------------------------------------------------------------
程序员 (对指挥官):

好的,让我们首先使用Python从提供的URL下载CSV数据,然后绘制包含温度最高值和最低值的图表。

首先,我将提供一个Python脚本,该脚本将下载CSV文件,然后绘制温度的最高值和最低值。

请运行以下Python代码:

```python
# 文件名: plot_temperatures.py
import pandas as pd
import matplotlib.pyplot as plt

# 下载CSV数据的URL
url = "https://raw.githubusercontent.com/vega/vega/main/docs/data/seattle-weather.csv"

# 下载数据
data = pd.read_csv(url)

# 现在,让我们绘制最高温度和最低温度
plt.figure(figsize=(10, 5))
plt.plot(data['date'], data['temp_max'], label='最高温度')
plt.plot(data['date'], data['temp_min'], label='最低温度')

# 添加标签和标题
plt.xlabel('日期')
plt.ylabel('温度 (°C)')
plt.title('西雅图的最高温度和最低温度')
plt.legend()

# 旋转x轴上的日期以提高可读性
plt.xticks(rotation=45)
plt.tight_layout()

# 保存图表
plt.savefig('result.jpg')

print("图表已保存为'result.jpg'。")
```

请确保已安装所需的包(`pandas`和`matplotlib`)。如果尚未安装,可以使用`pip`进行安装:

```sh
pip install pandas matplotlib
```
运行脚本后,您应该会看到一条消息,指示图表已保存为'result.jpg'。

--------------------------------------------------------------------------------

>>>>>>>> 执行代码块 0 (推测语言为 python)...

>>>>>>>> 执行代码块 1 (推测语言为 sh)...
指挥官(对编码员):

退出码:0(执行成功)
代码输出:
图表已保存为'result.jpg'。

要求的软件包已在您的环境中安装完成,如您的输出所示,因此不需要进一步操作。

该图表显示了您提供的 CSV 文件中西雅图的高温和低温。如果您有其他要求或需要进一步帮助,请随时提问。如果没有,且您对结果满意,我们可以结束这个任务。

终止

--------------------------------------------------------------------------------
编码员(对指挥官):

Python 脚本执行成功,图表已保存为'result.jpg'。您现在应该能在指定的位置找到图表文件。

根据您的输出,所需的软件包已在您的环境中安装完成,因此不需要进一步操作。

该图表显示了您提供的 CSV 文件中西雅图的高温和低温。如果您有其他要求或需要进一步帮助,请随时提问。如果没有,且您对结果满意,我们可以结束这个任务。

终止

--------------------------------------------------------------------------------
![](agentchat_lmm_gpt-4v_files/figure-markdown_strict/cell-8-output-2.png)
指挥官(对评论家):

改进 <image>

--------------------------------------------------------------------------------
评论家(对指挥官):

西雅图高低温度的情节可以通过以下几种方式改进:

1. 日期轴:x轴上的日期不可见或不可读,这使得很难将温度数据与特定时间段关联起来。考虑调整日期轴的格式,使日期以可读的角度显示或具有足够的间距。

2. x轴标签:x轴标签或刻度存在问题,显示出密集的黑色区域,表明标签重叠或压缩。应调整标签的频率和格式,以防止重叠并实现清晰阅读。

3. y轴范围:如果温度数据允许,考虑从较低值开始y轴,以给温度线提供更多空间并提高可读性。

4. 网格线:添加水平网格线可以帮助快速阅读特定温度。

5. 图例:图例清楚地指示了哪种颜色对应高温和低温,这是好的。确保图例不会遮挡任何重要数据。

6. 分辨率:图像的实际分辨率可能很好,但x轴问题可能会给人一种低分辨率图像的错觉。一旦x轴被纠正,图表的整体清晰度可能会自然提高。

7. 颜色对比度:蓝色和橙色的选择通常对比度很好,但请确保它们对所有用户都可区分,包括那些可能有色盲的用户。考虑使用色盲友好的调色板。

8. 标题:标题 "High

--------------------------------------------------------------------------------
指挥官(对程序员):

这是对你的图表的反馈。请改进!将结果保存为 `result.jpg`
西雅图高低温度的情节可以通过以下几种方式改进:

1. 日期轴:x轴上的日期不可见或不可读,这使得很难将温度数据与特定时间段关联起来。考虑调整日期轴的格式,使日期以可读的角度显示或具有足够的间距。

2. x轴标签:x轴标签或刻度存在问题,显示出密集的黑色区域,表明标签重叠或压缩。应调整标签的频率和格式,以防止重叠并实现清晰阅读。

3. y轴范围:如果温度数据允许,考虑从较低值开始y轴,以给温度线提供更多空间并提高可读性。

4. 网格线:添加水平网格线可以帮助快速阅读特定温度。

5. 图例:图例清楚地指示了哪种颜色对应高温和低温,这是好的。确保图例不会遮挡任何重要数据。

6. 分辨率:图像的实际分辨率可能很好,但x轴问题可能会给人一种低分辨率图像的错觉。一旦x轴被纠正,图表的整体清晰度可能会自然提高。

7. 颜色对比度:蓝色和橙色的选择通常对比度很好,但请确保它们对所有用户都可区分,包括那些可能有色盲的用户。考虑使用色盲友好的调色板。

8. 标题:标题 "High

--------------------------------------------------------------------------------
程序员(对指挥官):

为了解决对图表的反馈,我们将对绘图进行以下改进:

1. 格式化日期轴以提高可读性。
2. 调整x轴标签的频率和格式,以防止重叠。
3. 如果可能,扩展y轴范围。
4. 添加水平网格线以便于阅读温度。
5. 确保图例放置正确,不会遮挡数据。
6. 解决x轴标签后,检查清晰度。
7. 使用色盲友好的调色板绘制图表。
8. 确保标题具有描述性和相关性。

以下是更新后的Python脚本,用于进行这些改进:

```python
# 文件名: improved_plot_temperatures.py
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

# 下载CSV数据的URL
url = "https://raw.githubusercontent.com/vega/vega/main/docs/data/seattle-weather.csv"

# 下载数据
data = pd.read_csv(url)
data['date'] = pd.to_datetime(data['date'])

# 现在,让我们绘制最高温度和最低温度
plt.figure(figsize=(10, 5))
plt.plot(data['date'], data['temp_max'], label='最高温度', color='tab:blue')
plt.plot(data['date'], data['temp_min'], label='最低温度', color='tab:orange')

# 设置x轴的主要定位器和格式化程序以获得更好的日期显示
plt.gca().xaxis.set_major_locator(mdates.AutoDateLocator())
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))

# 旋转x轴上的日期以提高可读性
plt.gcf().autofmt_xdate()

# 改进Y轴范围
temp_min = data['temp_min'].min() - 5 # 在最低温度下方留出一些空间
temp_max = data['temp_max'].max() + 5 # 在最高温度上方留出一些空间
plt.ylim(temp_min, temp_max)

# 添加网格线并格式化网格
plt.grid(True, which='both', linestyle='--', linewidth=0.5)

# 提供标签和标题
plt.xlabel('日期')
plt.ylabel('温度 (°C)')
plt.title('西雅图的高温和低温随时间变化')

# 调整图例位置
plt.legend(loc='upper right')

# 检查完成,不需要调整颜色对比度,因为使用了适合色盲的颜色

# 以高分辨率保存图像
plt.savefig('result.jpg', dpi=300)

print("改进后的图像已保存为'result.jpg'。")
指挥官(对评论家):

改进 <image>

--------------------------------------------------------------------------------
指挥官(对编码人员):

这是对你的图的反馈。请改进!将结果保存为 `result.jpg`
改进 <img tmp/result.jpg>

--------------------------------------------------------------------------------
编码人员(对指挥官):

对于可能造成的任何困惑,我表示歉意,但作为一名人工智能,我没有直接查看生成的图像的能力。然而,如果有任何特定的调整需求,我可以根据标准实践帮助您进一步完善绘图。

您提到了一个被引用为 "<img tmp/result.jpg>" 的图的反馈。由于我无法查看图像,我假设这个反馈是一个占位符。如果您希望在图中实施特定的更改或进一步改进,请明确提供这些细节。

例如:
- 是否还有需要重新调整的图例元素?
- 是否应进一步调整日期格式以提高清晰度?
- 是否还有其他需要修改的具体元素(例如颜色、线条、标签、标题)?

如果没有具体的反馈,我可以提供一些一般性的改进建议,例如:

- 确保绘图不显得杂乱。
- 检查纵横比是否适合所呈现的数据。
- 确认字体大小是否可读。

如果能提供具体的反馈,我们可以相应地进行。否则,请告诉我是否应该结束任务。

终止

--------------------------------------------------------------------------------
![](agentchat_lmm_gpt-4v_files/figure-markdown_strict/cell-8-output-6.png)

``` text
图表生成器~ (对用户):

tmp/result.jpg

--------------------------------------------------------------------------------
```

``` text
ChatResult(chat_id=None, chat_history=[{'content': '\n使用以下数据绘制图表:\nhttps://raw.githubusercontent.com/vega/vega/main/docs/data/seattle-weather.csv\n\n我想展示高温和低温。\n', 'role': 'assistant'}, {'content': 'tmp/result.jpg', 'role': 'user'}], summary='tmp/result.jpg', cost=({'total_cost': 0}, {'total_cost': 0}), human_input=[])
```

## 视觉能力:多模态代理的群聊示例

我们建议使用视觉能力来管理群聊,以便更好地组织和理解图像。

```python
agent1 = MultimodalConversableAgent(
name="image-explainer-1",
max_consecutive_auto_reply=10,
llm_config={"config_list": config_list_4v, "temperature": 0.5, "max_tokens": 300},
system_message="您的图像描述富有诗意且引人入胜。",
)
agent2 = MultimodalConversableAgent(
name="image-explainer-2",
max_consecutive_auto_reply=10,
llm_config={"config_list": config_list_4v, "temperature": 0.5, "max_tokens": 300},
system_message="您的图像描述准确而简洁。",
)

user_proxy = autogen.UserProxyAgent(
name="User_proxy",
system_message="为我描述图像。",
human_input_mode="TERMINATE", # 尝试 ALWAYS、NEVER 和 TERMINATE 之间的不同选项
max_consecutive_auto_reply=10,
code_execution_config={
"use_docker": False
}, # 如果可用于运行生成的代码,请将 use_docker 设置为 True。使用 docker 比直接运行生成的代码更安全。
)

# 我们将 max_round 设置为 5
groupchat = autogen.GroupChat(agents=[agent1, agent2, user_proxy], messages=[], max_round=5)

vision_capability = VisionCapability(lmm_config={"config_list": config_list_4v, "temperature": 0.5, "max_tokens": 300})
group_chat_manager = autogen.GroupChatManager(groupchat=groupchat, llm_config=gpt4_llm_config)
vision_capability.add_to_agent(group_chat_manager)

rst = user_proxy.initiate_chat(
group_chat_manager,
message="""为我的图像写一首诗:
<img https://th.bing.com/th/id/R.422068ce8af4e15b0634fe2540adea7a?rik=y4OcXBE%2fqutDOw&pid=ImgRaw&r=0>.""",
)
```
User_proxy (向 chat_manager 发送消息):

为我的图片写一首诗吧:
<img https://th.bing.com/th/id/R.422068ce8af4e15b0634fe2540adea7a?rik=y4OcXBE%2fqutDOw&pid=ImgRaw&r=0>.

--------------------------------------------------------------------------------

>>>>>>>> 使用自动回复...
image-explainer-1 (向 chat_manager 发送消息):

在门边的一个舒适角落里,冒险的低语涌动,
躺着一只卷曲的杏色梦想,眼睛柔和地闪耀。
西弗尔,他的标签上的名字,一根时髦的蝴蝶结,没有夸夸其谈的余地。

一只甜蜜的贵宾犬或混血犬,它的爪子几乎看不到
承载着它温柔身躯的地板,在这个宁静的家庭游戏中。
一位爱与喜悦的哨兵,比任何玩具都更迷人。

它的凝视,讲述着温柔的日子,以及在它心中燃烧的爱。
它身后的靴子,像无声的卫兵,无视世界的匆忙和潮汐,
在它宁静的住所里,它安心地逗留。

哦,炉边的守护者,你的价值不是由出生来定义的。
而是由你给生活带来的喜悦,是我们日常疲惫中的喘息。
在你身上,我们找到了一位如此真实的朋友,西弗尔,一个无价之宝。

--------------------------------------------------------------------------------

>>>>>>>> 使用自动回复...
image-explainer-2 (向 chat_manager 发送消息):

一只毛色金黄的小狗,
在一个故事不断展开的房子里。
西弗尔,你的蝴蝶结如此整洁,
你的狗眼,如此甜蜜。

蜷缩在轻盈的地板上,
你的毛发是柔软而令人愉悦的景象。
或许是多种品种的混血,
在你的脸上,我们找到了纯粹的快乐。

带着微弱的叮当声的标签,
还有一条如此明亮的领结,
你静静地躺在那里,
在这个地方,带来了平静的存在。

在你身后,靴子等待着雨水,
但在室内,你安静地停留。
爱的象征,毛茸茸的喜悦,
一束温暖的灯光,如此明亮地闪耀。

在这个快速而广阔的世界中,
你温和的精神将我们紧紧地抓住。
西弗尔,你的魅力如此伟大,
你给这个人类的土地带来了和平。

--------------------------------------------------------------------------------

>>>>>>>> 使用自动回复...
User_proxy (向 chat_manager 发送消息):



--------------------------------------------------------------------------------

>>>>>>>> 使用自动回复...
User_proxy (向 chat_manager 发送消息):



--------------------------------------------------------------------------------
## 有和没有视觉能力的Agent的行为

在这里,我们展示了有和没有视觉能力的Agent的行为。我们使用了与之前示例中相同的图片和问题。

```python
agent_no_vision = AssistantAgent(name="普通LLM Agent", llm_config=gpt4_llm_config)

agent_with_vision = AssistantAgent(name="具有视觉能力的普通LLM Agent", llm_config=gpt4_llm_config)
vision_capability = VisionCapability(lmm_config={"config_list": config_list_4v, "temperature": 0.5, "max_tokens": 300})
vision_capability.add_to_agent(agent_with_vision)


user = UserProxyAgent(
name="用户",
human_input_mode="NEVER",
max_consecutive_auto_reply=0,
code_execution_config={"use_docker": False},
)

message = """为我的图片写一首诗:
<img https://th.bing.com/th/id/R.422068ce8af4e15b0634fe2540adea7a?rik=y4OcXBE%2fqutDOw&pid=ImgRaw&r=0>."""
```


```python
user.send(message=message, recipient=agent_no_vision, request_reply=True)
```

``` text
用户 (给普通LLM Agent):

为我的图片写一首诗:
<img https://th.bing.com/th/id/R.422068ce8af4e15b0634fe2540adea7a?rik=y4OcXBE%2fqutDOw&pid=ImgRaw&r=0>.

--------------------------------------------------------------------------------
普通LLM Agent (给用户):

作为一个AI,我无法直接查看图片或网页内容。但是,我可以通过收集关于图片的信息来帮助您生成一首诗。请为我描述图片,包括场景、突出的颜色、所引发的情绪以及任何您希望在诗中突出的特定元素,如动物、自然、城市风景或人物。一旦您提供了图片的描述,我就可以根据该描述创作一首诗。

--------------------------------------------------------------------------------
```

```python
user.send(message=message, recipient=agent_with_vision, request_reply=True)
```
``` text
用户(对具备视觉能力的常规LLM代理):

为我的图片写一首诗:
<img https://th.bing.com/th/id/R.422068ce8af4e15b0634fe2540adea7a?rik=y4OcXBE%2fqutDOw&pid=ImgRaw&r=0>.

--------------------------------------------------------------------------------
具备视觉能力的常规LLM代理(回复用户):

在杏黄色的光晕中,一只卷毛小狗斜躺着,
胸牌上闪耀着威斯法尔的名字。
一只蝴蝶结在明亮的蓝天中绽放,
在光线洒满的地板上,柔软的爪子躺着。

他拥有深情的凝视,
在宁静的门厅里,他守望着。
在雨天的黑色橡胶护卫下,
他激起了一种舒适、温馨的拥抱。

他的血统源自贵宾犬的优雅,
或者是混血,带有一只波斯顿梗的面孔,
无论是金毛还是拉布拉多,他的卷毛同样可爱,
在每一步跳跃中,在每一次心跳中。

一张爱的照片,放在一个小小的相框里,
一颗心跳包裹在杏黄色的鬃毛中。
小狗在他的宁静中,邀请着欢呼,
在宠物爱好者的耳边轻声诉说着喜悦。

在他周围,生活的简单杂乱展开,
却不受忧虑的困扰,不受寒冷的侵袭。
每一次呼吸,他都宣告着这片土地属于他,
他是欢乐的主人,从他出生的那一刻起。

爪子伸展在柔软、宽容的土地上,
他那富有灵魂的眼睛无声地诉说着。
因为在他温柔休憩的宁静中,
蕴藏着一个简单的真理,那就是我们是幸福的。

终止

--------------------------------------------------------------------------------
```
## 用于视觉能力的自定义字幕功能

在许多应用场景中,我们可以在视觉能力中使用自定义函数将图像转录为字幕。

例如,我们可以使用基于规则的算法或其他模型来检测图像中的颜色、框和其他组件。

自定义模型应该接受图像的路径并返回一个字符串字幕。

在下面的示例中,视觉能力将调用 LMM 获取字幕,并调用自定义函数获取更多信息。

```python
def my_description(image_url: str, image_data: Image = None, lmm_client: object = None) -> str:
"""
此函数接受图像的 URL 并返回描述。

参数:
- image_url (str): 图像的 URL。
- image_data (PIL.Image): 图像数据。
- lmm_client (object): LLM 客户端对象。

返回:
- str: 图像的颜色描述。
"""
# 为了说明目的,打印参数
print("image_url", image_url)
print("image_data", image_data)
print("lmm_client", lmm_client)

img_uri = pil_to_data_uri(image_data) # 将数据转换为 URI(str)格式以进行 API 调用
lmm_out = lmm_client.create(
context=None,
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "用 10 个词描述这张图片。"},
{
"type": "image_url",
"image_url": {
"url": img_uri,
},
},
],
}
],
)
description = lmm_out.choices[0].message.content
description = content_str(description)

# 将图像转换为像素数组。
pixels = np.array(image_data)

# 计算平均颜色。
avg_color_per_row = np.mean(pixels, axis=0)
avg_color = np.mean(avg_color_per_row, axis=0)
avg_color = avg_color.astype(int) # 将颜色值转换为整数

# 将平均颜色格式化为字符串描述。
caption = f"""该图像来自 {image_url}
它是关于:{description}
图像的平均颜色是 RGB:
({avg_color[0]}, {avg_color[1]}, {avg_color[2]})"""

print(caption) # 为了说明目的

return caption
```


```python
agent_with_vision_and_func = AssistantAgent(
name="带有自定义函数和 LLM 的常规 LLM 代理", llm_config=gpt4_llm_config
)

vision_capability_with_func = VisionCapability(
lmm_config={"config_list": config_list_4v, "temperature": 0.5, "max_tokens": 300},
custom_caption_func=my_description,
)
vision_capability_with_func.add_to_agent(agent_with_vision_and_func)

user.send(message=message, recipient=agent_with_vision_and_func, request_reply=True)
```
用户(对于具有自定义函数和LMM的常规LLM代理):

为我的图片写一首诗:
<img https://th.bing.com/th/id/R.422068ce8af4e15b0634fe2540adea7a?rik=y4OcXBE%2fqutDOw&pid=ImgRaw&r=0>.

--------------------------------------------------------------------------------
image_url https://th.bing.com/th/id/R.422068ce8af4e15b0634fe2540adea7a?rik=y4OcXBE%2fqutDOw&pid=ImgRaw&r=0
image_data <PIL.Image.Image image mode=RGB size=1920x1080 at 0x7F599DA4CCA0>
lmm_client <autogen.oai.client.OpenAIWrapper object at 0x7f599da3ab20>
这张图片来自于 https://th.bing.com/th/id/R.422068ce8af4e15b0634fe2540adea7a?rik=y4OcXBE%2fqutDOw&pid=ImgRaw&r=0
它描述的是:可爱的棕色卷毛小狗,室内佩戴蓝色项圈。
图片的平均颜色是RGB:
(170, 155, 137)
具有自定义函数和LMM的常规LLM代理(对用户):

在一片家常色彩的天空下,
RGB混合成温柔的炖菜,
躺着一只卷毛小狗,欢快地蹦跳,
脖子上系着蓝色的围巾。

温柔凝视,他的眼神乞求,
温暖着人们的内心深处,
棕色的被毛,甜蜜的缠绕,
每只小脚都低语着游戏的声音。

在一个广阔而辽阔的世界里,
他坐在室内,自豪地坐着。
一个无声的愿望,一口气,一个开始,
卷曲的伴侣,一件艺术品。

在画框中,他静静地被捕捉,
然而,透过镜头,他的魅力溢出。
在宁静的房间里,有着微小的心跳,
他的存在驱散了所有的忧郁。

小狗的快乐,以棕色调为基调,
佩戴蓝色项圈,他独自统治。
一张照片的价值,这一刻的欢愉,
可爱的卷毛朋友,供所有人欣赏。

这首诗将可爱的棕色卷毛小狗佩戴蓝色项圈的本质与您提供的审美元素融为一体,既表达了情感,又展现了美感。

--------------------------------------------------------------------------------
# 标题1

这是一段普通的文本。

## 标题2

这是另一段普通的文本。

### 标题3

这是一张图片:

![图片描述](https://example.com/image.jpg)

这是一个链接:[链接描述](https://example.com)

这是一个无序列表:

- 项目1
- 项目2
- 项目3

这是一个有序列表:

1. 项目1
2. 项目2
3. 项目3

这是一段引用:

> 这是引用的内容。

这是一段代码:

```
print("Hello, world!")
```

这是一段公式:

$$
E = mc^2
$$

这是一段表格:

| 列1 | 列2 |
| --- | --- |
| 内容1 | 内容2 |

这是一段脚注[^1]。

[^1]: 这是脚注的内容。

这是一段注释[^2]。

[^2]: 这是注释的内容。

这是一段引用的论文[20]。

这是一段加粗的文本。

这是一段斜体的文本。

这是一段删除线的文本。

这是一段下划线的文本。

这是一段高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^3]。

这是一段行内注释[^4]。

这是一段行内引用的论文[21]。

这是一段行内加粗的文本。

这是一段行内斜体的文本。

这是一段行内删除线的文本。

这是一段行内下划线的文本。

这是一段行内高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^5]。

这是一段行内注释[^6]。

这是一段行内引用的论文[22]。

这是一段行内加粗的文本。

这是一段行内斜体的文本。

这是一段行内删除线的文本。

这是一段行内下划线的文本。

这是一段行内高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^7]。

这是一段行内注释[^8]。

这是一段行内引用的论文[23]。

这是一段行内加粗的文本。

这是一段行内斜体的文本。

这是一段行内删除线的文本。

这是一段行内下划线的文本。

这是一段行内高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^9]。

这是一段行内注释[^10]。

这是一段行内引用的论文[24]。

这是一段行内加粗的文本。

这是一段行内斜体的文本。

这是一段行内删除线的文本。

这是一段行内下划线的文本。

这是一段行内高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^11]。

这是一段行内注释[^12]。

这是一段行内引用的论文[25]。

这是一段行内加粗的文本。

这是一段行内斜体的文本。

这是一段行内删除线的文本。

这是一段行内下划线的文本。

这是一段行内高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^13]。

这是一段行内注释[^14]。

这是一段行内引用的论文[26]。

这是一段行内加粗的文本。

这是一段行内斜体的文本。

这是一段行内删除线的文本。

这是一段行内下划线的文本。

这是一段行内高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^15]。

这是一段行内注释[^16]。

这是一段行内引用的论文[27]。

这是一段行内加粗的文本。

这是一段行内斜体的文本。

这是一段行内删除线的文本。

这是一段行内下划线的文本。

这是一段行内高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^17]。

这是一段行内注释[^18]。

这是一段行内引用的论文[28]。

这是一段行内加粗的文本。

这是一段行内斜体的文本。

这是一段行内删除线的文本。

这是一段行内下划线的文本。

这是一段行内高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^19]。

这是一段行内注释[^20]。

这是一段行内引用的论文[29]。

这是一段行内加粗的文本。

这是一段行内斜体的文本。

这是一段行内删除线的文本。

这是一段行内下划线的文本。

这是一段行内高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^21]。

这是一段行内注释[^22]。

这是一段行内引用的论文[30]。

这是一段行内加粗的文本。

这是一段行内斜体的文本。

这是一段行内删除线的文本。

这是一段行内下划线的文本。

这是一段行内高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^23]。

这是一段行内注释[^24]。

这是一段行内引用的论文[31]。

这是一段行内加粗的文本。

这是一段行内斜体的文本。

这是一段行内删除线的文本。

这是一段行内下划线的文本。

这是一段行内高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^25]。

这是一段行内注释[^26]。

这是一段行内引用的论文[32]。

这是一段行内加粗的文本。

这是一段行内斜体的文本。

这是一段行内删除线的文本。

这是一段行内下划线的文本。

这是一段行内高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^27]。

这是一段行内注释[^28]。

这是一段行内引用的论文[33]。

这是一段行内加粗的文本。

这是一段行内斜体的文本。

这是一段行内删除线的文本。

这是一段行内下划线的文本。

这是一段行内高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^29]。

这是一段行内注释[^30]。

这是一段行内引用的论文[34]。

这是一段行内加粗的文本。

这是一段行内斜体的文本。

这是一段行内删除线的文本。

这是一段行内下划线的文本。

这是一段行内高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^31]。

这是一段行内注释[^32]。

这是一段行内引用的论文[35]。

这是一段行内加粗的文本。

这是一段行内斜体的文本。

这是一段行内删除线的文本。

这是一段行内下划线的文本。

这是一段行内高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^33]。

这是一段行内注释[^34]。

这是一段行内引用的论文[36]。

这是一段行内加粗的文本。

这是一段行内斜体的文本。

这是一段行内删除线的文本。

这是一段行内下划线的文本。

这是一段行内高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^35]。

这是一段行内注释[^36]。

这是一段行内引用的论文[37]。

这是一段行内加粗的文本。

这是一段行内斜体的文本。

这是一段行内删除线的文本。

这是一段行内下划线的文本。

这是一段行内高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^37]。

这是一段行内注释[^38]。

这是一段行内引用的论文[38]。

这是一段行内加粗的文本。

这是一段行内斜体的文本。

这是一段行内删除线的文本。

这是一段行内下划线的文本。

这是一段行内高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^39]。

这是一段行内注释[^40]。

这是一段行内引用的论文[39]。

这是一段行内加粗的文本。

这是一段行内斜体的文本。

这是一段行内删除线的文本。

这是一段行内下划线的文本。

这是一段行内高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^41]。

这是一段行内注释[^42]。

这是一段行内引用的论文[40]。

这是一段行内加粗的文本。

这是一段行内斜体的文本。

这是一段行内删除线的文本。

这是一段行内下划线的文本。

这是一段行内高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^43]。

这是一段行内注释[^44]。

这是一段行内引用的论文[41]。

这是一段行内加粗的文本。

这是一段行内斜体的文本。

这是一段行内删除线的文本。

这是一段行内下划线的文本。

这是一段行内高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^45]。

这是一段行内注释[^46]。

这是一段行内引用的论文[42]。

这是一段行内加粗的文本。

这是一段行内斜体的文本。

这是一段行内删除线的文本。

这是一段行内下划线的文本。

这是一段行内高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^47]。

这是一段行内注释[^48]。

这是一段行内引用的论文[43]。

这是一段行内加粗的文本。

这是一段行内斜体的文本。

这是一段行内删除线的文本。

这是一段行内下划线的文本。

这是一段行内高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^49]。

这是一段行内注释[^50]。

这是一段行内引用的论文[44]。

这是一段行内加粗的文本。

这是一段行内斜体的文本。

这是一段行内删除线的文本。

这是一段行内下划线的文本。

这是一段行内高亮的文本。

这是一段行内代码。

这是一段行内公式。

这是一段行内链接。

这是一段行内图片。

这是一段行内脚注[^51]。

这是一段行内注释[^52]。

这是一段行内引用的论文[45]。

这是一段行内加