LLM之Agent(九)| 通过API集成赋能Autogen Multi-Agent系统

       随着大型语言模型的快速发展,构建基于LLM驱动的自治代理(autonomous agents)已经成为一个备受关注的话题。仅在过去一年中,就出现了许多基于这一理念的新技术和框架。

​      本文将探索微软开源的Agent框架:Autogen。它弥补了此类新技术未能解决的空白:允许多个Agent协作以实现共同目标。它在LLM之上添加了最小但重要的功能,以支持多个代理的初始化和协作,允许在多个Agent之间单聊以及群聊。

       但作为一个仍处于早期阶段的框架,通过API把Autogen集成到实际的生产环境中仍然是一个挑战,如Web APP。由于缺乏成熟的文档或资源,在Agent通信流中需要一些变通方法。

       因此,在本文中,我们将讨论Autogen Agent连接到API的详细过程。

一、Autogen介绍

       在之前的LLM之Agent(七)|  AutoGen介绍文章中介绍过Autogen,它是一个基于LLM的Agent通信框架,支持创建具有不同人物角色的代理。然后,这些代理可以进行单聊;也可以进行群聊,每个代理轮流发言。

Autogen提供了一些具有不同功能的内置代理类型,例如:

  • User Proxy Agent:可以检索用户输入并执行代码;
  • Assistant Agent:默认的系统消息代理,该消息允许Agent充当完成任务的助理;
  • Conversable Agent:在user proxy agents和assistant之间构建会话能力。

虽然Autogen主要支持OpenAI LLM,如GPT-3.5和GPT-4来创建代理,但用户也可以与本地或其他托管LLM一起使用。

二、Autogen群聊

       Autogen中的群聊功能允许多个代理在群设置中进行协作,主要特点如下:

  • 每个代理都可以看到组中其他代理发送的所有消息;
  • 一旦启动,群聊将继续,直到满足其中一个终止条件。(例如:代理在回复中使用终止消息,用户选择退出聊天,达到群的最大聊天次数等)
  • 每个群聊都有一个管理代理,负责监督消息广播、发言人选择和聊天终止。
  • Autogen在每轮聊天中选择下一位发言人,目前支持四种方法

        -manual:要求用户手动选择下一个发言人

        -random:随机选择下一个发言人

        -round robin:使用循环方法选择下一个发言人

        -auto:让LLM选择下一个有聊天历史记录作为上下文的发言人

       这些特性使Autogen群聊成为Agent协作的理想选择。然而,如果想控制Agent在此环境中更多的协作方式时,也会带来很多挑战。

三、使用Autogen开发应用程序

      目前,Autogen旨在作为一种工具使用,用户可以完全了解不同代理之间的所有内部通信。这使得将Autogen集成到用户不应该知道这些信息的应用程序中成为一项棘手的工作。

       例如,如果您构建了一个系统,其中多个代理共同担任销售助理,那么在决定对用户查询的最终响应之前,您可能不想公开他们是如何在内部规划和选择销售策略的。您也可能不想让用户暴露在这种内部沟通的复杂性中。

       除此之外,在尝试将Autogen代理系统与API集成时,我们还面临以下问题:

  • Autogen主要是一个CLI工具。(例如:它将代理消息打印到CLI,并提示用户通过CLI提供反馈);
  • Autogen无法在没有明确用户输入的情况下提供一致的方式来结束特定的聊天序列。

但好消息是,我们可以使用Autogen已经支持的某些定制来解决这些问题。我们能够将Autogen集成到API中。

下面通过旅游代理系统来演示一下如何将AutoGen与API进行集成:

四、基于Autogen的旅游代理系统

       该系统将由两个Autogen Assistant Agent和一个User Proxy Agent构建,在群聊中这些代理人中的每一位都有以下职责:

  • Tour Agent:主代理决定如何响应用户查询以及在生成对用户的最终响应之前应收集的信息;
  • Location Researcher:旅游代理的助理,在通过SERP API查询谷歌地图的函数调用的帮助下进行位置研究。它使代理商能够研究用户心目中与目的地相关的景点、餐厅、住宿等;
  • User Proxy:代理群聊天中用户的代理。

由于本教程依赖于OpenAI和SERP API,因此您需要每个服务的API密钥来尝试本示例。

4.1 Autogen config

首先,定义AutoGen的配置:

config_list = [{'model': 'gpt-3.5-turbo-1106','api_key': os.getenv("OPENAI_API_KEY"),}]

4.2 Assistant Agents

然后,创建两个助理代理:Tour AgentLocation Researcher

       Tour Agent是一个简单的Assistant Agent,具有一个自定义的系统提示,用于描述其角色和职责,它指定代理应如何将TERMINATE添加到针对用户的最终回答的末尾。

tour_agent = AssistantAgent("tour_agent",    human_input_mode="NEVER",    llm_config={"config_list": config_list,"cache_seed": None    },    system_message="You are a Tour Agent who helps users plan a trip based on user requirements. You can get help from the Location Researcher to research and find details about a certain location, attractions, restaurants, accommodation, etc. You use those details a answer user questions, create trip itineraries, make recommendations with practical logistics according to the user's requirements. Report the final answer when you have finalized it. Add TERMINATE to the end of this report.")

       另一方面,在创建Location Researcher时,定义一个函数,它可以调用并执行来搜索谷歌地图。将在下一节中介绍该函数的实际schema和具体实现。下面代码片段显示了如何通过自定义提示将它们附加到Assistant Agent。

location_researcher = AssistantAgent(    "location_researcher",    human_input_mode="NEVER",    system_message="You are the location researcher who is helping the Tour Agent plan a trip according to user requirements. You can use the `search_google_maps` function to retrieve details about a certain location, attractions, restaurants, accommodation, etc. for your research. You process results from these functions and present your findings to the Tour Agent to help them with itinerary and trip planning.",    llm_config={        "config_list": config_list,        "cache_seed": None,        "functions": [            SEARCH_GOOGLE_MAPS_SCHEMA,        ]    },    function_map={        "search_google_maps": search_google_maps    })

4.3 User Proxy

       然后,创建User Proxy。尽管User Proxy在该代理系统中没有发挥积极作用,但它对于接受用户消息和在向用户发送响应之前检测何时结束对用户查询的回复序列至关重要。

def terminate_agent_at_reply(        recipient: Agent,        messages: Optional[List[Dict]] = None,        sender: Optional[Agent] = None,        config: Optional[Any] = None,) -> Tuple[bool, Union[str, None]]:return True, Noneuser_proxy = UserProxyAgent("user_proxy",    is_termination_msg=lambda x: "TERMINATE" in x.get("content", ""),    human_input_mode="NEVER",    code_execution_config=False)user_proxy.register_reply([Agent, None], terminate_agent_at_reply)

       我已经向User Proxy注册了一个新的回复函数,它只返回TrueNone输出。要了解如何结束聊天序列的,必须了解Autogen是如何使用回复功能的。

       当代理生成回复时,Autogen依赖于注册到代理的回复函数列表。它接受这个列表中的第一个函数,如果它能生成最终的回复,则返回Truereply。如果返回False,表示函数无法生成回复,将转移到列表中的下一个函数。

       Autogen支持代理不同的回复方式,例如请求人工反馈、执行代码、执行函数或生成LLM回复。

       当我将terminate_agent_at_reply注册为回复函数时,它会被添加到此列表的开头,并成为第一个被调用的回复函数。由于默认情况下返回TrueNone,这将阻止用户代理发送自动回复或使用其他回复功能生成LLM回复。使用“None”作为回复会阻止群聊继续进行更多的聊天回合。

4.4 Group chat

       最后,我将创建允许所有这些代理进行协作的群聊和管理代理。

group_chat = GroupChat(    agents=[self.user_proxy, self.location_researcher, self.tour_agent],    messages=[],    allow_repeat_speaker=False,    max_round=20)group_chat_manager = GroupChatManager(self.group_chat,    is_termination_msg=lambda x: "TERMINATE" in x.get("content", ""),    llm_config={"config_list": config_list,"cache_seed": None    })

       在这里,我允许群聊使用默认的发言人选择方法,auto,因为这个用例没有其他合适的选项。我还设置了聊天管理器的is_terminate_msg参数,以检查消息内容中是否存在terminate

       那么,当我已经为用户代理使用了以前的terminate_at_agent_reply函数时,为什么我要在这里设置另一个终止条件呢?

       如果LLM在Tour agent的最终回答后选择用户代理以外的代理作为下一个发言人,它应该起到故障保护的作用。

4.5 把上述功能合并到一个class里

       现在,我可以把所有这些代理逻辑放在一个类中,还介绍了一种方法来接受来自API的用户消息,并在回复序列之后发送最终回复。

import osfrom autogen import AssistantAgent, UserProxyAgent, GroupChat, GroupChatManager, Agentfrom typing import Optional, List, Dict, Any, Union, Callable, Literal, Tuplefrom dotenv import load_dotenvfrom functions import search_google_maps, SEARCH_GOOGLE_MAPS_SCHEMAload_dotenv()config_list = [{'model': 'gpt-3.5-turbo-1106','api_key': os.getenv("OPENAI_API_KEY"),}]class AgentGroup:def __init__(self):        self.user_proxy = UserProxyAgent("user_proxy",            is_termination_msg=lambda x: "TERMINATE" in x.get("content", ""),            human_input_mode="NEVER",            code_execution_config=False        )        self.user_proxy.register_reply([Agent, None], AgentGroup.terminate_agent_at_reply)        self.location_researcher = AssistantAgent("location_researcher",            human_input_mode="NEVER",            system_message="You are the location researcher who is helping the Tour Agent plan a trip according to user requirements. You can use the `search_google_maps` function to retrieve details about a certain location, attractions, restaurants, accommodation, etc. for your research. You process results from these functions and present your findings to the Tour Agent to help them with itinerary and trip planning.",            llm_config={"config_list": config_list,"cache_seed": None,"functions": [                    SEARCH_GOOGLE_MAPS_SCHEMA,                ]            },            function_map={"search_google_maps": search_google_maps            }        )        self.tour_agent = AssistantAgent("tour_agent",            human_input_mode="NEVER",            llm_config={"config_list": config_list,"cache_seed": None            },            system_message="You are a Tour Agent who helps users plan a trip based on user requirements. You can get help from the Location Researcher to research and find details about a certain location, attractions, restaurants, accommodation, etc. You use those details a answer user questions, create trip itineraries, make recommendations with practical logistics according to the user's requirements. Report the final answer when you have finalized it. Add TERMINATE to the end of this report."        )        self.group_chat = GroupChat(            agents=[self.user_proxy, self.location_researcher, self.tour_agent],            messages=[],            allow_repeat_speaker=False,            max_round=20        )        self.group_chat_manager = GroupChatManager(            self.group_chat,            is_termination_msg=lambda x: "TERMINATE" in x.get("content", ""),            llm_config={"config_list": config_list,"cache_seed": None            }        )def process_user_message(self, message: str) -> str:        self.user_proxy.initiate_chat(self.group_chat_manager, message=message, clear_history=False)return self._find_last_non_empty_message()def _find_last_non_empty_message(self) -> str:        conversation = self.tour_agent.chat_messages[self.group_chat_manager]for i in range(len(conversation) - 1, -1, -1):if conversation[i].get("role") == "assistant":                reply = conversation[i].get("content", "").strip()                reply = reply.replace("TERMINATE", "")if reply:return replyreturn "No reply received"    @staticmethoddef terminate_agent_at_reply(            recipient: Agent,            messages: Optional[List[Dict]] = None,            sender: Optional[Agent] = None,            config: Optional[Any] = None,    ) -> Tuple[bool, Union[str, None]]:return True, None

       这里,每当代理组接收到用户消息时,用户代理都会启动与组管理器的聊天,其中clear_history=False,可以保留以前回复序列的历史记录。

       回复序列结束后,find_last_non_empty_message会从聊天记录中找到旅行社代理发送的最后一条非空消息,并将其作为答案返回。该函数在寻找应该返回答案时,会考虑到与代理回复和回复序列的一些不一致性。

4.6 API endpoint

         现在,我将创建API端点来接收FastAPI用户查询。

from fastapi import FastAPIfrom pydantic import BaseModelfrom typing import Dictfrom agent_group import AgentGroupclass ChatRequest(BaseModel):    session_id: str    message: strapp = FastAPI()sessions: Dict[str, AgentGroup] = {}@app.post("/chat")def chat(request: ChatRequest):    session_id = request.session_id    message = request.messageif session_id not in sessions.keys():        sessions[session_id] = AgentGroup()    agent_group = sessions[session_id]    reply = agent_group.process_user_message(message)return {"reply": reply, "status": "success"}

4.7 函数调用

    最后,回过头来处理在前一步中遗漏的内容:Location Researcher使用的函数调用的模式和实现。

import osfrom serpapi import GoogleSearchfrom dotenv import load_dotenvfrom typing import Dictload_dotenv()SEARCH_GOOGLE_MAPS_SCHEMA = {"name": "search_google_maps","description": "Search google maps using Google Maps API","parameters": {"type": "object","properties": {"query": {"type": "string","description": "A concise search query for searching places on Google Maps"            }        },"required": ["query"]    }}def search_google_maps(query):    params = {"engine": "google_maps","q": query,"type": "search","api_key": os.getenv("SERP_API_KEY")    }    results = _search(params)    results = results["local_results"]    top_results = results[:10] if len(results) > 10 else resultsdata = []for place in top_results:data.append(_populate_place_data(place["place_id"]))return datadef _populate_place_data(place_id: str):    params = {"engine": "google_maps","type": "place","place_id": place_id,"api_key": os.getenv("SERP_API_KEY")    }data = _search(params)return _prepare_place_data(data["place_results"])def _prepare_place_data(place: Dict):return {"name": place.get("title"),"rating": place.get("rating"),"price": place.get("price"),"type": place.get("type"),"address": place.get("address"),"phone": place.get("phone"),"website": place.get("website"),"description": place.get("description"),"operating_hours": place.get("operating_hours"),"amenities": place.get("amenities"),"service_options": place.get("service_options")    }def _search(params: Dict[str, str]):    search = GoogleSearch(params)    results = search.get_dict()return results

       search_google_maps函数获取代理提交的搜索查询,并将其发送到SERP的google maps API。然后,它使用位置ID检索结果中前10个位置的更多详细信息。最后,它使用这些详细信息创建一个简化的对象并将其发送回。

4.8 测试

         终于到了运行这个应用程序的时候了,看看它的效果如何。

        我正在尝试一个例子,用户发送一个请求来计划去巴厘岛旅行的行程。

Create a week long itinerary to Ubud, Bali for myself for May 2024. I’m going solo and I love exploring nature and going on hikes and activities like that. I have a mid-level budget and I want the itinerary to be relaxing not too packed.

       旅行社代理考虑了这一请求,并多次联系位置研究员,以获取岛上景点、餐厅和住宿选择的详细信息。

       旅行社代理根据这些信息提供最终答案。然后,用户对这个答案给出更多的反馈,使用更多的请求继续进行聊天。

五、改进和定制

       在上述的Tour Agent系统中,成功地配置了Autogen,以更好地适应基于API的应用程序,在该应用程序中,内部代理通信对用户是隐蔽的。然而,它仍然有一些缺点和不可预测的行为。

例如:

  • 我假设Tour Agent已经收集了所有所需的详细信息,并在用户代理被选为下一位发言人时完成了对用户查询的最终回答。考虑到使用LLM来选择下一个说话者的不可预测性,情况可能并不总是如此。
  • 之所以选择订单代理,是因为发言人并不总是一致的。有时,在用户查询后,位置研究员会被选为第一个发言人,而不是旅行社代理,等等。

       尽管这些缺点对于这样的用例来说并不重要,但对于另一个场景来说可能会有所不同。随着群聊中代理数量的增加,这些问题也变得更加明显。

       但是,如果你想为代理群聊带来更多的可预测性和一致性,仍然有一些方法可以定制Autogen的内置行为。

5.1 修改群聊发言人选择提示

      Autogen GroupChat类包含一个select_speaker_msg方法,可以覆盖该方法以指定如何管理发言人选择。

这是原始提示(供参考)。

def select_speaker_msg(self, agents: List[Agent]) -> str:"""Return the system message for selecting the next speaker. This is always the *first* message in the context."""return f"""You are in a role play game. The following roles are available:{self._participant_roles(agents)}.Read the following conversation.Then select the next role from {[agent.name for agent in agents]} to play. Only return the role."""

       您可以更新此信息,具体说明在何种情况下选择哪种代理,以使演讲者选择更加一致。

5.2 使用图模型强制执行更严格的说话者转移路径

       此笔记本[2]显示了如何将所有允许的说话者转换路径定义为有向图,并覆盖GroupChat的select_speaker方法来强制执行该行为。例如,对于这个用例,可以创建这样一个简单的图。

       这些只是几个例子。最终,适合您的解决方案将取决于您的特定需求。你还必须在提示和路由方面发挥创意,以确保所有代理的行为都符合你的意愿。

参考文献:

[1] https://levelup.gitconnected.com/harnessing-the-power-of-autogen-multi-agent-systems-via-api-integration-edb0b9651608

[2] https://github.com/microsoft/autogen/blob/main/notebook/agentchat_graph_modelling_language_using_select_speaker.ipynb

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

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

相关文章

快速搭建一个基于MVC架构的Spring Boot应用

提示:如果对 MVC 架构模式不熟悉可以看我的博客 > MVC架构模式与三层架构 快速搭建一个基于MVC架构的Spring Boot应用 一、Web 服务二、快速构建一个Spring Web MVC的 Web 应用1.使用脚手架快速的搭建环境:2.准备数据库:3.编写Dao层访问数…

一行命令在 wsl-ubuntu 中使用 Docker 启动 Windows

在 wsl-ubuntu 中使用 Docker 启动 Windows 0. 背景1. 验证我的系统是否支持 KVM?2. 使用 Docker 启动 Windows3. 访问 Docker 启动的 Windows4. Docker Hub 地址5. Github 地址 0. 背景 我们可以在 Windows 系统使用安装 wsl-ubuntu,今天玩玩在 wsl-ub…

黑群晖屏蔽更新

黑群晖屏蔽更新 修改Host删除控制面板的红点和更新提示 修改Host ssh连接群晖后执行以下命令 sudo vim /etc/hosts按i键进入编辑模式 光标移动定位到最后一行后追加以下两行 127.0.0.1 update.synology.com 127.0.0.1 update7.synology.com按esc键,然后输入:wq并…

《PCI Express体系结构导读》随记 —— 第I篇 第3章 PCI总线的数据交换(4)

接前一篇文章:《PCI Express体系结构导读》随记 —— 第I篇 第3章 PCI总线的数据交换(3) 3.2 PCI设备的数据传递 PCI设备的数据传递使用地址译码方式,当一个存储器读写总线事务到达PCI总线时,在这条总线上的所有PCI设…

[C++]priority_queue——优先级队列(含模拟实现)

一、priority_queue是什么 priority_queue 是容器适配器&#xff0c;它提供常数时间的&#xff08;默认&#xff09;最大元素查找&#xff0c;对数代价的插入与释出。 可用用户 提供的 Compare 更改顺序&#xff0c;例如&#xff0c;用 std::greater<T> 将导致最小元素作…

【LeetCode: 135. 分发糖果 + 贪心】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

物联网IOT视频设备如何快速对接阿里云生活物联网(Link Visual)并成功上云?

原文永久更新地址&#xff1a;https://www.yundashi168.com/472.html 文章来源&#xff1a;猿视野 如果有图片看不清楚&#xff0c;加载不出来&#xff0c;请阅读原文。 什么是Link Visual、 Link Visual是生活物联网平台针对视频产品推出的增值服务&#xff0c;提供视频数据上…

HDFS的standby节点启动过慢原因分析以及应对策略

HDFS的standby节点启动过慢原因分析以及应对策略 1. NN启动大致流程2. Editlog日志清理策略2.1 为什么需要合并editlog&#xff1f;2.2 什么时候删除editlog&#xff1f; 3. NN启动的日志加载策略4. Standby启动慢应对策略5. 疑问和思考5.1 如何人工阅读editlog和fsimage文件的…

在windows安装python版本的tensorrt

文章目录 一、进入官网&#xff0c;下载tensorrt包二、下载后解压并把相应文件拷入对应cuda的文件夹2.1 拷贝头文件2.2 拷贝静态库2.3 拷贝动态库 三、安装whl文件四、验证 一、进入官网&#xff0c;下载tensorrt包 https://developer.nvidia.com/tensorrt-download 这里需要…

ElasticSearch的集群管理命令

ElasticSearch版本 {"name" : "data-slave1","cluster_name" : "data-es","cluster_uuid" : "xxxxxxxxxx-eMwxw","version" : {"number" : "7.2.1","build_flavor" : &…

QT 范例阅读:Vector Deformation

效果图&#xff1a; 主要代码&#xff1a; 实现放大镜效果QPainter painter;//两种方式if (1) {m_lens_image QImage(bounds.size(), QImage::Format_ARGB32_Premultiplied);m_lens_image.fill(0);painter.begin(&m_lens_image);} else {m_lens_pixmap QPixmap(bounds.si…

云手机哪一款好用?

随着海外市场的不断发展&#xff0c;云手机市场也呈现蓬勃的态势&#xff0c;众多云设备软件纷纷涌现。企业在选择云手机软件时&#xff0c;如何找到性能卓越的软件成为一项关键任务。在众多选择中&#xff0c;OgPhone云手机凭借其卓越的性能和独特功能脱颖而出。以下是OgPhone…

C#在图片上输出文字和保存

winform&#xff0c;图片控件&#xff0c;加载一个图片&#xff0c;在图片上输出文字&#xff1b; 输出文字的代码如下&#xff1b; private void pictureBox1_Paint(object sender, PaintEventArgs e){Graphics g1 e.Graphics;g1.DrawString("测试", this.Font, B…

搞定App关键词和评论

从关键词优化的三大基本概念走起&#xff01; 关联性 优化师一般如何选择关联性高的关键词呢&#xff1f; 主要思路如下&#xff1a;品牌词-关联词-竞品词-竞品关键词&#xff0c;优先级从前到后依次降低&#xff0c;通过ASO优化工具筛选出合适的关键词。做ASO有一个好处就是…

大型语言模型基础知识的可视化指南

直观分解复杂人工智能概念的工具和文章汇总 如今&#xff0c;LLM&#xff08;大型语言模型的缩写&#xff09;在全世界都很流行。没有一天不在宣布新的语言模型&#xff0c;这加剧了人们对错过人工智能领域的恐惧。然而&#xff0c;许多人仍在为 LLM 的基本概念而苦苦挣扎&…

8.16单调递增的数字(LC738-M)

算法&#xff1a; 拿一个两位的数字来举例。 例如&#xff1a;98&#xff0c;一旦出现strNum[i - 1] > strNum[i]的情况&#xff08;非单调递增&#xff09;&#xff0c;首先想让strNum[i - 1]--&#xff0c;然后strNum[i]给为9&#xff0c;这样这个整数就是89&#xff0c…

《动手学深度学习(PyTorch版)》笔记4.1

注&#xff1a;书中对代码的讲解并不详细&#xff0c;本文对很多细节做了详细注释。另外&#xff0c;书上的源代码是在Jupyter Notebook上运行的&#xff0c;较为分散&#xff0c;本文将代码集中起来&#xff0c;并加以完善&#xff0c;全部用vscode在python 3.9.18下测试通过。…

tf卡被格式化怎么恢复里面的数据?恢复指南在此

在日常生活中&#xff0c;我们经常使用TF卡来存储各种数据&#xff0c;如照片、视频、文档等。然而&#xff0c;有时候我们会误将TF卡格式化&#xff0c;导致其中的数据丢失。为了挽救这些宝贵的数据&#xff0c;我们需要采取一些措施来进行恢复。本文将为你介绍如何恢复TF卡中…

华为二层交换机与防火墙配置上网示例

二层交换机与防火墙对接上网配置示例 组网图形 图1 二层交换机与防火墙对接上网组网图 二层交换机简介配置注意事项组网需求配置思路操作步骤配置文件相关信息 二层交换机简介 二层交换机指的是仅能够进行二层转发&#xff0c;不能进行三层转发的交换机。也就是说仅支持二层…

sklearn 学习-混淆矩阵 Confusion matrix

混淆矩阵Confusion matrix&#xff1a;也称为误差矩阵&#xff0c;通过计算得出矩阵的结果用来表示分类器的精度。其每一列代表预测值&#xff0c;每一行代表的是实际的类别。 from sklearn.metrics import confusion_matrixy_true [2, 0, 2, 2, 0, 1] y_pred [0, 0, 2, 2, 0…