分层Agent

分层Teams

    • 分层Agent
    • 创建tool
      • 研究团队工具
      • 文档编写团队工具
    • 通用能力
    • 定义Agent团队
      • 研究团队
      • 文档编写团队
    • 添加图层

分层Agent

在前面的示例(Agent管理)中,我们引入了单个管理节点的概念,用于在不同工作节点之间路由工作。
但是,如果单个worker的工作变得过于复杂怎么办?如果worker数量过多怎么办?
对于某些应用程序,如果工作按层次分布,系统可能会更有效。
您可以通过组合不同的子图并创建顶级管理和中级管理来实现此目的。
为此,让我们构建一个简单的研究助手!该图表将如下所示:
在这里插入图片描述
本笔记的灵感来自于 Wu 等人的论文《AutoGen:通过多代理对话启用下一代 LLM 应用程序》。等人。在本笔记的其余部分中,您将:

  1. 定义Agent访问网络和写入文件的工具
  2. 定义一些实用程序来帮助创建图形和代理
  3. 创建并定义每个团队(网络研究+文档写作)
  4. 将所有内容组合在一起。

创建tool

每个团队将由一名或多名Agent组成,每个Agent拥有一种或多种工具。下面定义了不同团队要使用的所有工具。

研究团队工具

研究团队可以使用搜索引擎和 URL 抓取工具在网络上查找信息。请随意添加以下附加功能以提高团队性能!

from typing import Annotated, Listfrom langchain_community.document_loaders import WebBaseLoader
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_core.tools import tooltavily_tool = TavilySearchResults(max_results=5)@tool
def scrape_webpages(urls: List[str]) -> str:"""Use requests and bs4 to scrape the provided web pages for detailed information."""loader = WebBaseLoader(urls)docs = loader.load()return "\n\n".join([f'\n{doc.page_content}\n'for doc in docs])

文档编写团队工具

接下来,我们将提供一些工具供文档编写团队使用。我们在下面定义了一些基本的文件访问工具。
请注意,这使Agent可以访问您的文件系统,这可能是不安全的。我们还没有针对性能优化工具描述。

from pathlib import Path
from tempfile import TemporaryDirectory
from typing import Dict, Optional, Annotated, Listfrom langchain_core.tools import tool
from langchain_experimental.utilities import PythonREPL
from typing_extensions import TypedDict_TEMP_DIRECTORY = TemporaryDirectory()
WORKING_DIRECTORY = Path(_TEMP_DIRECTORY.name)@tool
def create_outline(points: Annotated[List[str], "List of main points or sections."],file_name: Annotated[str, "File path to save the outline."],
) -> Annotated[str, "Path of the saved outline file."]:"""Create and save an outline."""with (WORKING_DIRECTORY / file_name).open("w") as file:for i, point in enumerate(points):file.write(f"{i + 1}. {point}\n")return f"大纲保存到 {file_name}"@tool
def read_document(file_name: Annotated[str, "File path to save the document."],start: Annotated[Optional[int], "The start line. Default is 0"] = None,end: Annotated[Optional[int], "The end line. Default is None"] = None,
) -> str:"""Read the specified document."""with (WORKING_DIRECTORY / file_name).open("r") as file:lines = file.readlines()if start is not None:start = 0return "\n".join(lines[start:end])@tool
def write_document(content: Annotated[str, "Text content to be written into the document."],file_name: Annotated[str, "File path to save the document."],
) -> Annotated[str, "Path of the saved document file."]:"""Create and save a text document."""with (WORKING_DIRECTORY / file_name).open("w") as file:file.write(content)return f"文档保存到 {file_name}"@tool
def edit_document(file_name: Annotated[str, "Path of the document to be edited."],inserts: Annotated[Dict[int, str],"Dictionary where key is the line number (1-indexed) and value is the text to be inserted at that line.",],
) -> Annotated[str, "Path of the edited document file."]:"""Edit a document by inserting text at specific line numbers."""with (WORKING_DIRECTORY / file_name).open("r") as file:lines = file.readlines()sorted_inserts = sorted(inserts.items())for line_number, text in sorted_inserts:if 1 <= line_number <= len(lines) + 1:lines.insert(line_number - 1, text + "\n")else:return f"错误: 行号{Line_number}超出范围。"with (WORKING_DIRECTORY / file_name).open("w") as file:file.writelines(lines)return f"文档编辑并保存到 {file_name}"# Warning: This executes code locally, which can be unsafe when not sandboxedrepl = PythonREPL()@tool
def python_repl(code: Annotated[str, "The python code to execute to generate your chart."],
):"""Use this to execute python code. If you want to see the output of a value,you should print it out with `print(...)`. This is visible to the user."""try:result = repl.run(code)except BaseException as e:return f"执行失败,错误: {repr(e)}"return f"执行成功:\n```python\n{code}\n```\nStdout: {result}"

通用能力

当我们想要执行以下操作时,我们将创建一些实用函数以使其更加简洁:

  1. 创建一个worker agent
  2. 为子图创建一个管理者

这些将为我们简化最后的图形组合代码,以便更容易看到发生了什么。

from typing import List, Optionalfrom langchain.agents import AgentExecutor, create_openai_functions_agent
from langchain.output_parsers.openai_functions import JsonOutputFunctionsParser
from langchain_core.messages import HumanMessage
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_openai import ChatOpenAIfrom langgraph.graph import END, StateGraphdef create_agent(llm: ChatOpenAI,tools: list,system_prompt: str,
) -> str:"""创建一个函数调用代理并将其添加到图中。"""system_prompt += "\n根据自己的专业,使用可用的工具自主工作。""不要询问说明。""您的其他团队成员(以及其他团队)将根据自己的专长与你合作。""你被选中是有原因的!你是以下团队成员之一: {team_members}。"prompt = ChatPromptTemplate.from_messages([("system",system_prompt,),MessagesPlaceholder(variable_name="messages"),MessagesPlaceholder(variable_name="agent_scratchpad"),])agent = create_openai_functions_agent(llm, tools, prompt)executor = AgentExecutor(agent=agent, tools=tools)return executordef agent_node(state, agent, name):result = agent.invoke(state)return {"messages": [HumanMessage(content=result["output"], name=name)]}# 创建团队管理
def create_team_supervisor(llm: ChatOpenAI, system_prompt, members) -> str:"""An LLM-based router."""options = ["FINISH"] + membersfunction_def = {"name": "route","description": "选择下一个角色。","parameters": {"title": "routeSchema","type": "object","properties": {"next": {"title": "Next","anyOf": [{"enum": options},],},},"required": ["next"],},}prompt = ChatPromptTemplate.from_messages([("system", system_prompt),MessagesPlaceholder(variable_name="messages"),("system","鉴于上述对话,下一步谁应该采取行动?""还是应该结束?选择其中一个:: {options}",),]).partial(options=str(options), team_members=", ".join(members))return (prompt| llm.bind_functions(functions=[function_def], function_call="route")| JsonOutputFunctionsParser())

定义Agent团队

现在我们可以开始定义我们的分层团队了。 “选择你的玩家!”

研究团队

研究团队将有一个搜索代理和一个网络抓取“research_agent”作为两个工作节点。让我们创建这些以及团队主管。

import functools
import operator
from typing import TypedDict, Annotated, Listfrom langchain_core.messages import BaseMessage
from langchain_openai.chat_models import ChatOpenAIfrom common.common import API_KEY, PROXY_URL
from researchteam_tool1 import scrape_webpages, tavily_tool
from utilities3 import create_team_supervisor, create_agent, agent_node# ResearchTeam graph state
class ResearchTeamState(TypedDict):# A message is added after each team member finishesmessages: Annotated[List[BaseMessage], operator.add]# The team members are tracked so they are aware of# the others' skill-setsteam_members: List[str]# Used to route work. The supervisor calls a function# that will update this every time it makes a decisionnext: strllm = ChatOpenAI(model_name="gpt-4o", api_key=API_KEY, base_url=PROXY_URL)search_agent = create_agent(llm,[tavily_tool],"你是一名研究助理,可以使用tavily搜索引擎搜索最新信息。",
)
search_node = functools.partial(agent_node, agent=search_agent, name="Search")research_agent = create_agent(llm,[scrape_webpages],"你是一名研究助理,可以使用scrape_webpages功能抓取指定的URL以获取更详细的信息。",
)
research_node = functools.partial(agent_node, agent=research_agent, name="WebScraper")supervisor_agent = create_team_supervisor(llm,"您是一名主管,负责管理以下worker之间的对话:Search、WebScraper。""给定以下用户请求,请与该工作人员一起响应以执行下一步操作。""每个工作人员将执行一项任务,并以其结果和状态进行响应。""完成后,以FINISH进行响应。",["Search", "WebScraper"],
)

现在我们已经创建了必要的组件,定义它们的交互就很容易了。将节点添加到团队图中,并定义边,这确定了转换标准。

import functools
import operator
from typing import TypedDict, Annotated, Listfrom langchain_core.messages import BaseMessage, HumanMessage
from langchain_openai.chat_models import ChatOpenAI
from langgraph.constants import END
from langgraph.graph import StateGraphfrom common.common import API_KEY, PROXY_URL, show_img
from researchteam_tool1 import scrape_webpages, tavily_tool
from utilities3 import create_team_supervisor, create_agent, agent_node# ResearchTeam graph state
class ResearchTeamState(TypedDict):# A message is added after each team member finishesmessages: Annotated[List[BaseMessage], operator.add]# The team members are tracked so they are aware of# the others' skill-setsteam_members: List[str]# Used to route work. The supervisor calls a function# that will update this every time it makes a decisionnext: strllm = ChatOpenAI(model_name="gpt-4o", api_key=API_KEY, base_url=PROXY_URL)search_agent = create_agent(llm,[tavily_tool],"你是一名研究助理,可以使用tavily搜索引擎搜索最新信息。",
)
search_node = functools.partial(agent_node, agent=search_agent, name="Search")research_agent = create_agent(llm,[scrape_webpages],"你是一名研究助理,可以使用scrape_webpages功能抓取指定的URL以获取更详细的信息。",
)
research_node = functools.partial(agent_node, agent=research_agent, name="WebScraper")supervisor_agent = create_team_supervisor(llm,"您是一名主管,负责管理以下worker之间的对话:Search、WebScraper。""给定以下用户请求,请与该工作人员一起响应以执行下一步操作。""每个工作人员将执行一项任务,并以其结果和状态进行响应。""完成后,以FINISH进行响应。",["Search", "WebScraper"],
)research_graph = StateGraph(ResearchTeamState)
research_graph.add_node("Search", search_node)
research_graph.add_node("WebScraper", research_node)
research_graph.add_node("supervisor", supervisor_agent)# Define the control flow
research_graph.add_edge("Search", "supervisor")
research_graph.add_edge("WebScraper", "supervisor")
research_graph.add_conditional_edges("supervisor",lambda x: x["next"],{"Search": "Search", "WebScraper": "WebScraper", "FINISH": END},
)research_graph.set_entry_point("supervisor")
chain = research_graph.compile()# The following functions interoperate between the top level graph state
# and the state of the research sub-graph
# this makes it so that the states of each graph don't get intermixed
def enter_chain(message: str):results = {"messages": [HumanMessage(content=message)],}return resultsresearch_chain = enter_chain | chain

在这里插入图片描述

文档编写团队

使用类似的方法创建下面的文档编写团队。这次,我们将为每个代理提供不同的文件写入工具的访问权限。
请注意,我们在这里向Agent授予文件系统访问权限,这在任何情况下并不安全。

import functools
import operator
from pathlib import Path
from typing import TypedDict, Annotated, Listfrom langchain_core.messages import BaseMessage, HumanMessage
from langchain_openai import ChatOpenAI
from langgraph.constants import END
from langgraph.graph import StateGraphfrom common.common import API_KEY, PROXY_URL, show_img
from doc_writing_team_tool2 import WORKING_DIRECTORY, write_document, edit_document, read_document, create_outline, \python_repl
from utilities3 import create_agent, agent_node, create_team_supervisor# Document writing team graph state
class DocWritingState(TypedDict):# This tracks the team's conversation internallymessages: Annotated[List[BaseMessage], operator.add]# This provides each worker with context on the others' skill setsteam_members: str# This is how the supervisor tells langgraph who to work nextnext: str# This tracks the shared directory statecurrent_files: str# This will be run before each worker agent begins work
# It makes it so they are more aware of the current state
# of the working directory.
def prelude(state):written_files = []if not WORKING_DIRECTORY.exists():WORKING_DIRECTORY.mkdir()try:written_files = [f.relative_to(WORKING_DIRECTORY) for f in WORKING_DIRECTORY.rglob("*")]except Exception:passif not written_files:return {**state, "current_files": "没有文件被写"}return {**state,"current_files": "\n以下是您的团队已写入目录的文件:\n"+ "\n".join([f" - {f}" for f in written_files]),}llm = ChatOpenAI(model_name="gpt-4o", api_key=API_KEY, base_url=PROXY_URL)doc_writer_agent = create_agent(llm,[write_document, edit_document, read_document],"你是一个写文档研究的专家。\n"# The {current_files} value is populated automatically by the graph state"以下是当前在您目录中的文件:\n{current_files}",
)
# Injects current directory working state before each call
context_aware_doc_writer_agent = prelude | doc_writer_agent
doc_writing_node = functools.partial(agent_node, agent=context_aware_doc_writer_agent, name="DocWriter"
)note_taking_agent = create_agent(llm,[create_outline, read_document],"你是一名专业的高级研究员,负责撰写论文提纲并做笔记,以撰写一篇完美的论文。{current_files}",
)
context_aware_note_taking_agent = prelude | note_taking_agent
note_taking_node = functools.partial(agent_node, agent=context_aware_note_taking_agent, name="NoteTaker"
)chart_generating_agent = create_agent(llm,[read_document, python_repl],"你是一名数据专家,负责为研究项目生成图表。""{current_files}",
)
context_aware_chart_generating_agent = prelude | chart_generating_agent
chart_generating_node = functools.partial(agent_node, agent=context_aware_note_taking_agent, name="ChartGenerator"
)doc_writing_supervisor = create_team_supervisor(llm,"你是一名主管,负责管理以下worker之间的对话: {team_members}。""给定以下用户请求,请与工作人员一起响应以执行下一步操作。""每个工作人员将执行一项任务,并以其结果和状态作出响应。""完成后,回复FINISH。",["DocWriter", "NoteTaker", "ChartGenerator"],
)# Create the graph here:
# Note that we have unrolled the loop for the sake of this doc
authoring_graph = StateGraph(DocWritingState)
authoring_graph.add_node("DocWriter", doc_writing_node)
authoring_graph.add_node("NoteTaker", note_taking_node)
authoring_graph.add_node("ChartGenerator", chart_generating_node)
authoring_graph.add_node("supervisor", doc_writing_supervisor)# Add the edges that always occur
authoring_graph.add_edge("DocWriter", "supervisor")
authoring_graph.add_edge("NoteTaker", "supervisor")
authoring_graph.add_edge("ChartGenerator", "supervisor")# Add the edges where routing applies
authoring_graph.add_conditional_edges("supervisor",lambda x: x["next"],{"DocWriter": "DocWriter","NoteTaker": "NoteTaker","ChartGenerator": "ChartGenerator","FINISH": END,},
)authoring_graph.set_entry_point("supervisor")
chain = authoring_graph.compile()# The following functions interoperate between the top level graph state
# and the state of the research sub-graph
# this makes it so that the states of each graph don't get intermixed
def enter_chain(message: str, members: List[str]):results = {"messages": [HumanMessage(content=message)],"team_members": ", ".join(members),}return results# We reuse the enter/exit functions to wrap the graph
authoring_chain = (functools.partial(enter_chain, members=authoring_graph.nodes)| authoring_graph.compile()
)

在这里插入图片描述

添加图层

在这个设计中,我们正在执行自上而下的规划政策。我们已经创建了两个图表,但我们必须决定如何在两个图表之间分配工作。
我们将创建第三个图来编排前两个图,并添加一些连接器来定义如何在不同图之间共享此顶级状态。

import operator
from typing import TypedDict, Annotated, Listfrom langchain_core.messages import BaseMessage
from langchain_openai.chat_models import ChatOpenAI
from langgraph.constants import END
from langgraph.graph import StateGraphfrom common.common import API_KEY, PROXY_URL, show_img
from research_team_agent4 import research_chain
from doc_writing_team_agent5 import authoring_chainllm = ChatOpenAI(model_name="gpt-4o", api_key=API_KEY, base_url=PROXY_URL)from utilities3 import create_team_supervisorsupervisor_node = create_team_supervisor(llm,"你是一名主管,负责管理以下团队之间的对话: {team_members}。""给定以下用户请求,与工作人员一起响应以执行下一步操作。""每个工作人员都将执行一项任务,并以其结果和状态作出响应。""完成后,回复FINISH。",["ResearchTeam", "PaperWritingTeam"],
)# Top-level graph state
class State(TypedDict):messages: Annotated[List[BaseMessage], operator.add]next: strdef get_last_message(state: State) -> str:return state["messages"][-1].contentdef join_graph(response: dict):return {"messages": [response["messages"][-1]]}# Define the graph.
super_graph = StateGraph(State)
# First add the nodes, which will do the work
super_graph.add_node("ResearchTeam", get_last_message | research_chain | join_graph)
super_graph.add_node("PaperWritingTeam", get_last_message | authoring_chain | join_graph
)
super_graph.add_node("supervisor", supervisor_node)# Define the graph connections, which controls how the logic
# propagates through the program
super_graph.add_edge("ResearchTeam", "supervisor")
super_graph.add_edge("PaperWritingTeam", "supervisor")
super_graph.add_conditional_edges("supervisor",lambda x: x["next"],{"PaperWritingTeam": "PaperWritingTeam","ResearchTeam": "ResearchTeam","FINISH": END,},
)
super_graph.set_entry_point("supervisor")
super_graph = super_graph.compile()

在这里插入图片描述

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

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

相关文章

Java学习笔记(一)Java内容介绍、程序举例、DOS命令、Java跨平台特性的本质

Hi i,m JinXiang ⭐ 前言 ⭐ 本篇文章主要介绍Java内容介绍、程序举例、DOS命令、Java跨平台特性的本质详细介绍以及部分理论知识 🍉欢迎点赞 👍 收藏 ⭐留言评论 📝私信必回哟😁 🍉博主收将持续更新学习记录获,友友们有任何问题可以在评论区留言 目录 1、内容介绍…

STM32学习和实践笔记(37):DMA实验

1.DMA简介 DMA&#xff0c;全称是Direct Memory Access&#xff0c;中文意思为直接存储器访问。DMA可用于实现外设与存储器之间或者存储器与存储器之间数据传输的高效性。 之所以高效&#xff0c;是因为DMA传输数据移动过程无需CPU直接操作&#xff0c;这样节省的 CPU 资源就可…

小程序使用接口wx.getLocation配置

开通时需详细描述业务&#xff0c;否则可能审核不通过 可能需要绑定腾讯位置服务&#xff0c;新建应该&#xff0c;绑定到小程序 配置 权限声明&#xff1a;在使用wx.getLocation前&#xff0c;需要在app.json的permission字段中声明对用户位置信息的使用权限&#xff0c;并提…

大数据学习-大数据介绍

意义 从海量的数据中分析出海量数据背后的价值 需要分析海量的数据&#xff0c;就需要存储、计算和分析 那就需要分布式多台计算机合适的工具来处理数据 工具 特点 大数据的核心工作&#xff1a;从海量的、高增长的、多类别的、信息密度低的数据中挖掘出高质量的结果 数据存储…

【CS.AI】决策树算法介绍: 原理与案例实现

文章目录 1. 简介1.1 决策树的基本原理核心概念: 2. 决策树的应用案例2.1 金融行业中的信用评分2.2 医疗诊断中的应用2.3 零售行业中的市场营销 3. 决策树的优缺点优点:缺点: 4. Python代码示例5 结论 [toc] ![在这里插入图片描述 1. 简介 决策树是一种常见且强大的机器学习算…

基坑监测的内容及其重要性概述

随着城市建设的不断深入&#xff0c;基坑工程作为基础建设的重要组成部分&#xff0c;其安全性和稳定性成为了关注的重点。为了确保基坑施工过程中的安全&#xff0c;基坑监测显得尤为重要。本文将围绕基坑监测的内容展开&#xff0c;旨在帮助读者更好地理解其重要性及实施方法…

卫星导航与gazebo仿真

全球卫星导航系统(Global Navigation Satelite System,GNSS)&#xff0c;简称卫星导航&#xff0c;是室外机器人定位的一个主要信息来源。 卫星导航能给机器人提供什么信息&#xff1f; 正常工作时&#xff0c;实际上可以提供机器人所需的所有定位信息&#xff0c;包括&#x…

用了这么久的群晖NAS,它到底能干些什么?

从21年开始玩群晖也有几年了&#xff0c;除非面临断电或升级&#xff0c;这个小伙伴都任劳任怨的工作着 现在NAS也广泛应用于家庭和企业环境中了&#xff0c;今天盘点一下我用群晖NAS都干了些什么~ 1.文件存储与共享&#xff1a; 群晖NAS可以作为文件服务器&#xff0c;提供…

【Autoware】Autoware.universe安装过程与问题记录

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍Autoware.universe安装过程与问题记录。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下…

七人拼团:互助共赢,电商新动力

在当前繁荣的电商领域中&#xff0c;七人互助拼团模式以其别具一格的激励机制和互助合作理念&#xff0c;成为了消费者和商家共同瞩目的焦点。接下来&#xff0c;我们将详细解读这一模式中的直推激励、滑落补偿以及团队成就奖&#xff0c;并探讨其如何体现互助合作的精神。 一、…

190.回溯算法:组合(力扣)

代码随想录 (programmercarl.com) 一、什么是回溯算法 回溯算法是一种通用的算法设计技巧&#xff0c;特别适用于解决组合、排列、子集等问题。它通过逐步构建解决方案&#xff0c;并在发现部分解决方案无效时撤销&#xff08;回溯&#xff09;部分计算&#xff0c;从而寻找所…

灵活的招聘管理系统有五种方法帮助成功招聘

还记得以前的时代吗&#xff1f;这取决于你的年龄&#xff0c;直到智能手机、流媒体电视和电子邮件出现。今天&#xff0c;任何活着的成年人都经历了技术上的巨大变化&#xff0c;这创造了一种新的行为方式。人才获取也是如此。 一个值得推荐的招聘管理系统 招聘团队被困在满足…

用于制作耳机壳的UV树脂耳机壳UV胶价格高不高?

用于制作耳机壳的UV树脂耳机壳UV胶价格高不高&#xff1f; 制作耳机壳的UV树脂价格相对于一些其他材料可能会略高&#xff0c;但具体的价格取决于多个因素&#xff0c;如品牌、型号、质量等。一些高端的UV树脂品牌和型号可能会价格较高&#xff0c;但它们也通常具有更好的性能…

nvidia历史版本驱动

打开官网 https://www.nvidia.cn windows GTX-1060为例 标准

【中学教资科目二】03中学教学

03中学教学 第一节 教学的任务1.1 教学的任务 第二节 教学过程2.1 教学过程的本质2.2 教学过程的基本规律 第三节 教学原则3.1 因材施教原则 第四节 教学方法4.1 我国中学常用的教学方法4.2 国外常用的教学方法 第五节 教学组织形式、教学工作基本环节和教学评价5.1 现代其他教…

OpenHarmony角落里的知识:WPA_Supplicant连接方式

WPA_Supplicant连接方式简析 /third_party/wpa_supplicant |-- CONTRIBUTIONS # 贡献说明 |-- COPYING # 版权说明 |-- wpa_supplicant-2.9 # 轻量级系统的wpa_supplicant | |-- hostapd # Wi-Fi热点相关功能&#xff08;Acces…

基于Web的图书管理系统运行教程

1.5、安装数据库和数据库管理工具 目前作者所有毕设源码数据库都用 MySQL5.7版本&#xff0c;强烈建议初学者跟作者保持一致&#xff0c;避免出现其他错误&#xff0c;待运行成功后再根据需要调整数据库版本。 MySQL5.7安装教程请看作者另一篇文章&#xff1a;《MySQL绿色版安…

设计模式(三)代理模式

目录 一、什么是代理模式 二、静态代理 1、定义 2、代码 2.1、接口 2.2、被代理对象 2.3、代理对象 2.4、测试 三、动态代理 1、定义 2、代码 2.1、接口 2.2、目标对象 2.3、代理对象 2.4、测试 一、什么是代理模式 代理模式(Proxy Pattern)是一种结构性模式。代理模…

【前端】[vue3] [uni-app] 组件样式击穿:deep

我是在开发uni-app时测试的思路&#xff0c;大家可以借鉴一下。 我这边测试的是uni组件&#xff0c;但是我觉得即便你用element-plus之类的&#xff0c;样式击穿的思路都相同。 我自定义了一个全局样式scss文件&#xff0c;并引入到了项目中。(如图) 利用vue3 中的 deep 方式…

人脸识别——可解释的人脸识别(XFR)人脸识别模型是根据什么来识别个人的

可解释性人脸识别&#xff08;XFR&#xff09;&#xff1f; 人脸识别有一个任务叫1:N&#xff08;识别&#xff09;。这个任务将一个人的照片与N张注册照片进行比较&#xff0c;找出相似度最高的人。 这项任务用于刑事调查和出入境点。在犯罪调查中&#xff0c;任务从监控摄像…