使用 LangServe 构建和部署 MinIO 支持的 LangChain Agent API

news2025/1/11 9:58:23

我们在LangChain的创新世界中的旅程揭示了其在转变数据管理和应用程序功能方面的强大能力。

通过之前的讨论,我们深入探讨了几个主题,同时探索了LangChain的复杂功能。在本文中,我们将以“使用 MinIO 赋能 Langchain 代理”中涵盖的概念为基础,扩展 MinIO 代理的功能,以封装其他功能并通过 LangServe 部署自定义代理。

  • **使用 LangChain 创新 S3 存储桶检索:**利用 LangChain 的 S3 加载程序和 OpenAI API 制作自定义对话式 AI 代理,建立简化的数据管理方法的演练。

  • **使用 MinIO 为 LangChain 代理赋能:**深入探讨如何利用 MinIO,展示 LangChain 如何与 OpenAI 的 GPT 相结合,开创 AI 和 ML 数据处理的新领域。

基于这些见解,我们现在将重点转向LangServe,这是将LangChain应用程序从开发过渡到部署的关键工具,简化了启动生产就绪API的过程。

LangServe:简化LangChain应用程序的部署

LangServe 是开发人员的基石,消除了传统上与 API 部署相关的复杂性。它使集成了 MinIO 的 LangChain 应用程序能够平稳过渡到可访问、用户友好的 API。以下是 LangServe 如何重新定义部署环境:

  • **自动创建 API 端点:**LangServe 的自动化功能可以轻松生成必要的 API 端点,从而简化开发工作并显着缩短部署时间。

  • **模式生成和验证:**凭借其智能模式推理,LangServe 确保 API 提供定义明确的接口,从而促进更轻松的集成和无缝的用户体验。

  • **可定制的端点配置:**LangServe 提供各种端点,以满足从同步操作到实时更新的各种应用程序需求,为开发人员提供无与伦比的灵活性。

  • **轻松集成:**LangServe与现有LangChain代码无缝集成的能力也许是其最引人注目的功能,这意味着开发人员可以利用他们当前的代码库和专业知识,而无需进行重大更改。

深入了解LangChain和Langserve

我们将在以下步骤中更深入地探讨将 MinIO 与 LangChain 集成的过程。

1 . 使用 langchain-cli 创建 LangChain 应用程序。

2 . 在 agent.py 文件中开发自定义 LangChain 代理。

3 . 实现我们的代理 server.py 以作为 LangServe API 运行。

使用LangChain的命令行界面创建应用程序

使用LangServe部署LangChain应用程序带来了无缝的集成之旅,弥合了复杂的AI功能和RESTful API暴露之间的差距,使开发人员能够有效地利用LangChain的全部功能,为在当今快节奏的数字环境中部署智能应用程序树立了新标准。

LangChain提供了一种方便而简单的方法,使用他们的 langchain-cli 库创建应用程序,该库可以与 pip .该软件包提供了一个界面,允许用户通过使用现有的LangChain应用程序模板或创建自己的应用程序来轻松创建新应用程序。

**注意:**所有必要的文件都位于 MinIO 的“blog-assets”存储库中名为“minio-langserve-deployment”的目录下。

要创建一个新的LangChain应用程序,我们可以从以下命令开始创建一个虚拟环境并安装 langchain-cli 软件包:

mkdir minio-langserve-testing
cd minio-Langserve-testing


python -m venv .myenv
source .myenv/bin/activate


pip install langchain-cli

为了创建一个 langchain-cli 新的应用程序,我们可以在终端中键入 langchain ,编写以下命令以创建一个名为 my-app 的新应用程序目录。

langchain app new my-app

使用上述命令创建的 langchain 应用程序通过创建一致的开发环境来完成所有繁重的工作。开箱即用的新LangChain应用程序的结构如下所示:


./my-app
├── Dockerfile
├── README.md
├── app
│   ├── __init__.py
│   └── server.py ⇐ (This is where we will import our agent into)
├── packages ⇐  (This directory is where we will write our agent)
│   └── README.md
└── pyproject.toml

在以下步骤中,我们将通过编写一个名为 packages/agent.py 的新文件并更改 app/server.py 来对新创建的 LangChain 应用程序 ( my-app ) 进行更改。

这些是我们将在本文中讨论的文件:

  • my-app/packages/agent.py

  • my-app/app/server.py

开发 LangChain MinIO 代理以使用 LangServe 进行部署

为了说明如何使用 LangServe 部署集成了 MinIO 的 LangChain 代理,我们将首先将代理链代码保存在 agent.py 中。

首先,让我们初始化minio_client连接到“play.min.io:443”公共服务器的服务器。这个文件最终将调用LangChain的, agent_executor 允许我们将其传递给LangServe的 add_route 包装器。

**注意:**阅读之前的出版物“MinIO Langchain Tool”将为使用 LangChain 和 MinIO 一起开发提供有价值的见解。我们将遵循类似的概念方法,但使用额外的 MinIO 工具逻辑。

首先,使用文本编辑器打开 agent.py 文件:

sudo nano packages/agent.py

在文件的开头,导入必要的包,例如 os io minioChatOpenAI

import os
import io
from minio import Minio
from minio.error import S3Error
from langchain_openai import ChatOpenAI


os.environ["OPENAI_API_KEY"] = "<<Your API Key Here>>"

# Initialize llm
llm = ChatOpenAI(api_key=os.environ["OPENAI_API_KEY"]) 

# Initialize MinIO client
minio_client = Minio('play.min.io:443',
                     access_key='minioadmin',
                     secret_key='minioadmin',
                     secure=True)
                     

在此代码片段中,我们导入所需的包,并使用 OPENAI_API_KEY 存储在环境变量中的 OpenAI API 密钥初始化 ChatOpenAI 语言模型。我们还通过向“play.min.io”公共服务器提供必要的连接详细信息来初始化minio_client。

接下来,让我们定义 MinIO 存储桶,如果它不存在,则创建它:


# This variable will check if bucket exists
bucket_name = "test"


try:
    # Check if bucket exists
    if not minio_client.bucket_exists(bucket_name):
        # Create the bucket because it does not exist
        minio_client.make_bucket(bucket_name)
        print(f"Bucket '{bucket_name}' created successfully.")
    else:
        print(f"Bucket '{bucket_name}' already exists.")
except S3Error as err:
    print(f"Error encountered: {err}")
    

在这里,我们将 定义为 bucket_name “test”,并使用该 minio_client.bucket_exists() 方法检查它是否已经存在。如果存储桶不存在,则使用 minio_client.make_bucket() .如果存储桶已存在,我们会打印一条消息,指示该存储桶已存在。我们还使用try-exception块进行错误处理,以捕获和打印在此过程中可能发生的任何 S3Error 错误。

完成基本设置后,我们现在可以继续定义 MinIO 工具功能并创建代理执行器,我们将在后续步骤中介绍。

将LangChain的函数装饰器用于代理工具

Langchain和Langserve都提供了类似的方法来封装逻辑和功能,使其能够无缝集成到代理和链逻辑中。这是通过在定义的函数中使用带有详细文档字符串的@tool装饰器来实现的,该文档字符串将函数标记为可由 AI 代理使用和解释的可重用组件。

让我们仔细看看提供的代码示例:


from langchain.agents import tool

@tool
def upload_file_to_minio(bucket_name: str, object_name: str, data_bytes: bytes):
    """
    Uploads a file to MinIO.
    
    Parameters:
        bucket_name (str): The name of the bucket.
        object_name (str): The name of the object to create in the bucket.
        data_bytes (bytes): The raw bytes of the file to upload.
    """
    data_stream = io.BytesIO(data_bytes)
    minio_client.put_object(bucket_name, object_name, data_stream, length=len(data_bytes))
    return f"File {object_name} uploaded successfully to bucket {bucket_name}."

upload_file_to_minio 函数用 @tool 装饰,表示它是可重用的组件。它采用将文件上传到 MinIO 存储桶所需的参数,例如存储桶名称、对象名称和文件的原始字节。该函数利用 minio_client 执行文件上传操作,并在完成后返回成功消息。


@tool
def download_file_from_minio(file_info):
    """
    Custom function to download a file from MinIO.
    
    Expects file_info dict with 'bucket_name', 'object_name', and 'save_path' keys.
    'save_path' should be the local path where the file will be saved.
    """
    bucket_name = file_info['bucket_name']
    object_name = file_info['object_name']
    save_path = file_info['save_path']
    minio_client.get_object(bucket_name, object_name, save_path)
    

同样,该 download_file_from_minio 函数也标有 @tool 。它需要一个 file_info 字典,其中包含从 MinIO 存储桶下载文件所需的信息,例如存储桶名称、对象名称和应保存文件的本地路径。该函数使用 从minio_client指定存储桶中检索对象并将其保存到指定的本地路径。


@tool
def list_objects_in_minio_bucket(file_info):
    """
    Custom function to list objects in a MinIO bucket.
    
    Expects file_info dict with 'bucket_name' key.
    Returns a list of dictionaries containing 'ObjectKey' and 'Size' keys.
    """
    bucket_name = file_info['bucket_name']
    response = minio_client.list_objects(bucket_name)
    return [{'ObjectKey': obj.object_name, 'Size': obj.size} for obj in response.items]

list_objects_in_minio_bucket 函数也装饰用于 @tool 列出 MinIO 存储桶中存在的对象。它需要一个 file_info 带有键的 bucket_name 字典。该函数使用 检索 minio_client 指定存储桶中的对象列表,并返回包含每个对象的对象键和大小的字典列表。

通过将这些功能封装为工具,Langchain和Langserve使AI代理能够将它们无缝地整合到其逻辑和决策过程中。代理可以根据手头的任务智能地选择和执行适当的工具,从而增强其功能,并允许与 MinIO 存储系统进行更复杂和动态的交互。

了解LangChain的Runnable方法

LangChain提供了无数种使用自定义逻辑进行构建的方法,其中一种方法是“可运行”的方法。至于上面的演示逻辑, RunnableLambda 它是LangChain提供的一种结构,它允许将函数视为AI代理逻辑中的可执行单元。


from langchain_core.runnables import RunnableLambda


upload_file_runnable = RunnableLambda(upload_file_to_minio)
download_file_runnable = RunnableLambda(download_file_from_minio)
list_objects_runnable = RunnableLambda(list_objects_in_minio_bucket)

通过使用 RunnableLambda 包装工具函数,我们可以创建可运行的实例 ( upload_file_runnabledownload_file_runnable , 和 list_objects_runnable ),代理可以在其执行期间调用这些实例。这些可运行项封装了相应的工具功能,并为代理提供了与它们交互的统一接口。


tools = [upload_file_to_minio, download_file_from_minio, list_objects_in_minio_bucket]


llm_with_tools = llm.bind_tools(tools)

工具列表包含原始工具函数 ( upload_file_to_minio download_file_from_minio , 和 list_objects_in_minio_bucket ),这些函数用作代理功能的构建块。该 llm.bind_tools(tools) 行将工具绑定到语言模型 (llm),在模型的推理功能和工具提供的特定功能之间建立连接。结果 llm_with_tools 表示通过使用绑定工具的知识和能力增强的语言模型。

工具的使用 RunnableLambda 和工具与语言模型的绑定展示了LangChain和LangServe在创建强大且可定制的AI代理方面的灵活性和可扩展性。通过将语言模型的强大功能与工具中封装的特定功能相结合,AI 代理能够执行复杂的任务,例如将文件上传到 MinIO、从 MinIO 下载文件以及列出 MinIO 存储桶中的对象。

编写提示模板来指导我们的代理

接下来,我们将重点转移到提示模板上,该模板指导 AI 代理理解和响应用户输入。它是使用该 ChatPromptTemplate.from_messages() 方法定义的,该方法采用表示为包含角色和消息内容的元组的消息列表。

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.agents.format_scratchpad.openai_tools import format_to_openai_tool_messages
from langchain.agents.output_parsers.openai_tools import OpenAIToolsAgentOutputParser
from langchain_core.messages import AIMessage, HumanMessage


prompt_template = ChatPromptTemplate.from_messages([
    ("system", "You are a powerful assistant equipped with file management capabilities."),
    ("user", "{input}"),
    MessagesPlaceholder(variable_name="agent_scratchpad"),
])

提示由三条消息组成:

1 . 一条“系统”消息,将 AI 代理的上下文设置为具有文件管理功能的强大助手。

2 . 使用 {input} 占位符表示用户输入的“用户”消息。

3 . MessagesPlaceholder 一个名为“agent_scratchpad”,用于存储代理的中间步骤和思维过程。

format_to_openai_tool_messages 函数将代理的暂存器格式化为 OpenAI 工具的兼容格式,而 OpenAIToolsAgentOutputParser 类将模型的响应解析为可由代理解释的结构化格式。

AIMessage and HumanMessage 类表示代理和用户之间交换的消息,提供了一种标准化的方式来处理代理逻辑中的通信。

通过定义提示模板,我们为 AI 代理提供了一个清晰的结构和上下文,用于理解和响应用户输入,利用“agent_scratchpad”占位符在解决任务时跟踪其中间步骤和思维过程。

使用代理工具定义代理

最后,为了完成我们的 agent.py 代理,我们定义了我们的代理并创建了一个 AgentExecutor,可以使用 LangServe 库中的 add_route 函数从 server.py 脚本导入和调用它。

我们实例化必要的组件并将它们链接在一起以创建单个代理变量。


agent = (
    {
        "input": lambda x: x["input"],
        "agent_scratchpad": lambda x: format_to_openai_tool_messages(x["intermediate_steps"]),
    }
    | prompt_template
    | llm_with_tools
    | OpenAIToolsAgentOutputParser()
)

代理是使用字典和链式操作的组合来定义的。输入键从传入数据中提取用户输入,而 agent_scratchpad 键则使用该 format_to_openai_tool_messages 函数格式化代理思维过程的中间步骤。代理还合并了提示模板 ( prompt_template )、带有工具的语言模型 ( llm_with_tools ) 和输出解析器 ( OpenAIToolsAgentOutputParser() )。

定义 AgentExecutor 以执行代理

为了创建一个 AgentExecutor ,我们为其提供了定义的代理、可用的工具,并设置 verbose=True 了详细的输出。


from langchain.agents import tool, AgentExecutor


agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

AgentExecutor 使用提供的代理和工具来了解任务,并根据用户的输入选择适当的工具。代理不会为每个工具提供单独的提示,而是使用单个提示模板来指导它如何根据给定的输入使用这些工具。代理在执行过程中动态选择适当的工具。

使用我们的 AgentExecutor 定义 LangServe 路由

设置我们的应用程序并将其与LangServe集成,为将我们的LangChain应用程序部署和管理为API提供了简化的途径。选择 FastAPI 是因为它的性能和易用性,支持异步操作并自动生成 API 文档。

使用 FastAPI 构建的 LangServe 库通过简化 LangChain 对象作为 REST API 的部署来丰富这一点,为 CORS 设置提供内置中间件,以确保我们的 API 可以从不同的域安全地调用。

有关更深入/用例演示,可以通过访问 examples 目录下的 langchain-ai/langserve GitHub 存储库进行探索。


from fastapi import FastAPI


app = FastAPI(
    title="MinIO Agent API",
    version="1.0",
    description="A conversational agent facilitating data storage and retrieval with MinIO",
)

为了设置 CORS 标头,我们可以添加以下行来增强我们的安全性:


from fastapi.middleware.cors import CORSMiddleware


# Set all CORS enabled origins
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
    expose_headers=["*"],
)

使用 LangServe 实现代理

现在我们已经完成了 , packages/agent.py 我们可以导入它并在脚本 app/server.py 中使用 LangServe 库中的 add_route 函数。

from packages.agent import agent_executor
from langserve import add_routes


add_routes(
   app,
   agent_executor.with_types(input_type=Input, output_type=Output).with_config(
       {"run_name": "agent"}
   ), path=”/invoke”
)

通过调用 add_route(app, agent_executor(…), path="/invoke") ,我们向服务器应用程序 (app) 添加一个路由,将 /invoke 路径映射到 agent_executor() 函数。这允许在向 /invoke 终结点发出请求时调用代理执行程序。

通过此设置,服务器可以处理传入的请求,将它们传递给代理执行程序,并将代理的响应返回给客户端。代理执行程序利用定义的代理(包含提示模板、带工具的语言模型和输出解析器)来处理用户输入并根据可用工具生成适当的响应。

通过 Uvicorn 启动 LangServe 应用程序

为了启动LangServe应用程序,我们使用Uvicorn作为ASGI服务器,为我们的应用程序运行奠定了基础。这段代码至关重要,因为它激活了服务器,为应用程序的接入点指定了通用主机和指定端口。


if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

通过将此块嵌入到应用程序的主条目中,我们确保 Uvicorn 在直接执行脚本时掌舵,从而在预定义的主机和端口上点亮我们的 FastAPI 应用程序。此方法不仅简化了部署过程,而且还为在开发或生产环境中运行应用程序提供了明确的入口。

启动服务器应用程序

上面的代码已经演示了一种模块化方法,其中包括使用“langchain-cli”库,创建一个新的langchain应用程序,并将链逻辑保存到 agent.py ,同时将FastAPI和LangServe实现保存到 server.py

这是我们的最后一步,我们将保存我们的应用程序代码, server.py 用于构建应用程序的演示目的。

运行我们服务的最简单方法是:


python server.py

此命令将运行应用程序,同时返回仍需要调试的任何日志或错误消息。

LangServe 游乐场 LangServe

在 python 输出中,LangServe 日志标识 /invoke/playground 为应用程序终结点。现在,我们可以访问 playground WebUI 以及 API 的自动化文档,这些文档可通过访问 API 的 /docs 路径获得;通过为我们的每个应用程序功能提供试用按钮,以及我们可以从 WebUI 执行的预定义 cURL 请求,为我们提供了一种简化的测试和配置方法。

因此,我们集成了 MinIO 的 LangChain 代理现在已经熟练地转变为可部署的 API,可以为用户开发和扩展,其功能范围从批处理到实时交互。

LangServe API 的进一步使用

随着LangServe应用程序的启动和运行,我们可以从外部 server.py 使用它,方法是以我们的端点为目标,并将其封装在Langserve的 RemoteRunnable 模块中:


from langserve import RemoteRunnable


remote_runnable = RemoteRunnable("http://localhost:8000/<path>/")

LangChain在其库中拥有大量的模块,展示了一个多样化的工具包,旨在使开发人员能够构建复杂的人工智能驱动的应用程序。从复杂的链式结构到与各种AI模型的无缝集成,LangChain的模块化架构促进了广泛的功能,能够在AI和机器学习领域创建高度可定制和先进的解决方案。

使用 LangServe 开发 AI 管道

LangServe 不仅揭开了 LangChain 应用程序的神秘面纱,而且大大简化了部署 LangChain 应用程序的过程。通过弥合开发和部署之间的差距,它确保利用MinIO和LangChain的创新应用程序能够迅速从概念变为现实,准备好集成到更广泛的生态系统中并增强用户体验。

通过我们探索中涵盖的开发,我们已经看到MinIO与LangChain的无缝集成是绝对可能的,以及LangServe如何在部署这些高级解决方案方面发挥关键作用。随着我们继续驾驭不断发展的人工智能和机器学习领域,像LangServe这样的工具将继续在将尖端技术带到应用程序开发的最前沿方面发挥重要作用。

在MinIO,在这个技术丰富的时代,开发者社区的创造力和潜力让我们充满活力。

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

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

相关文章

数学建模系列(4/4):Matlab建模实战

目录 引言 1. Matlab简介与安装 1.1 Matlab简介 1.2 Matlab的安装 2. Matlab基础操作 2.1 Matlab基础语法和常用命令 2.2 Matlab中的数据类型和数据结构 3. 用Matlab进行建模 3.1 矩阵运算与线性代数 矩阵运算 3.2 Matlab中的绘图功能 绘制2D图形 绘制3D图形 3.3…

AI视频教程下载-用LangChain 开发 OpenAI、 LLAMA 、 Gemini 等AI应用

LangChain MasterClass- OpenAI LLAMA 2 GPT LLM Apps__ Python&#xff08;LangChain MasterClass-Develop 7 OpenAI LLM Apps using Python&#xff09; 探索LangChain、Pinecone、OpenAI、LLAMA 2及Google Gemini Pro LLM在现实世界中的应用。构建AI应用——拥抱脸&#xff…

VirtualBox出错,从主机复制文件,乱改内容

昨天烧录机器&#xff0c;测试对方更新的一个库&#xff1a; 开始正确。后来莫名其妙崩溃。反复烧了几次&#xff0c;都错误。复制了老版本的库&#xff0c;正常。再改回新版本&#xff0c;崩溃。 于是把整个打包目录给了对方&#xff0c;他一对比&#xff0c;发现文件不对&am…

Linux驱动开发(三)--新字符设备驱动开发 LED驱动开发升级

1、新字符设备驱动原理 使用 register_chrdev 函数注册字符设备的时候只需要给定一个主设备号即可&#xff0c;但是这样会 带来两个问题 需要我们事先确定好哪些主设备号没有使用 会将一个主设备号下的所有次设备号都使用掉&#xff0c;比如现在设置 LED 这个主设备号为200&…

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

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

U盘格式化后数据能恢复吗?1分钟了解答案!

“想问问大家如果不小心把u盘格式化后&#xff0c;还有机会恢复吗&#xff1f;一个不小心就按下了格式化按钮&#xff0c;现在后悔莫及&#xff0c;不知道应该怎么操作呢。” U盘就像是一个记忆小盒子&#xff0c;里面装满了珍贵的回忆、重要的文件和无数的心血。但某一天&…

Element 进度条样式优化

在开发后台管理系统时&#xff0c;经常会用到进度条这样一个控件&#xff0c;Element UI中提供了progress这样一个组件&#xff0c;如下图所示&#xff1a; 该组件默认的颜色会比较单一&#xff0c;为此时常需要对该组件的样式进行一些优化&#xff0c;以满足实际项目的需求。 …

世界奇观短视频制作,AI加持,新手也能月入上万

在这个数字化的时代&#xff0c;短视频已经成为了人们获取信息和娱乐的重要途径。特别是那些展示世界奇观的短视频&#xff0c;如极端的气候、危险的动物、美丽的自然景观等&#xff0c;这些主题具有很强的吸引力&#xff0c;能够引起观众的兴趣和好奇心。那么&#xff0c;如何…

香港优才计划适合你吗?官方标准、申请条件、适合申请人群分析

香港优才计划适合你吗&#xff1f; 众所周知&#xff0c;拥有香港身份&#xff0c;不仅可以享受到优质的教育资源、税收优惠、以及国际化的商业环境&#xff0c;还能在金融、商业、法律保障和生活品质等方面获得显著的好处。除此之外&#xff0c;获得香港护照&#xff0c;还能…

Springboot获取resources中的文件

1.Springboot以文件的形式获取resources中的文件 import com.google.gson.JsonIOException; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; import org.springframework.util.ResourceUtils; import j…

【数据结构与算法】线索二叉树 详解

为什么可在不增加指针域的情况下&#xff0c;对二叉树进行线索化&#xff1f; 不增加指针域&#xff1a;因为可以利用n1个空链域。 在线索二叉树中&#xff0c;为每个节点添加两个标志位&#xff0c;分别表示左指针和右指针是普通的孩子指针还是线索&#xff08;前驱或后继&a…

物联网APP设计艺术:技巧与未来科技的融合

从早期的智能家居&#xff0c;到今天的服装制造、医疗保健、物流运输、汽车工业...越来越多的行业开始使用物联网。物联网技术跨度大&#xff0c;适用范围广&#xff0c;设计师在面对物联网产品的UI设计项目时往往会感到受阻。这是什么原因呢&#xff1f;物联网应用程序界面设计…

【C++】哈希的概念及STL中有关哈希容器的使用

目录 前言一、unordered系列关联式容器1.1 标准库中的unordered_set1.1.1 unordered_set的介绍1.1.2 unordered_set的常用接口说明1.1.2.1 unordered_set对象的常见构造1.1.2.1.1 [无参构造函数](https://legacy.cplusplus.com/reference/unordered_map/unordered_map/)1.1.2.1…

“AI”科普丨Transformer架构图解最强教程!

今天给大家分享一篇关于深度学习模型Transformer的文章。我愿称之为讲解Transformer模型最好的文章。 文章内容主要介绍 Transformer 模型的具体实现&#xff1a; Transformer整体架构Transformer概览引入张量自注意力机制Self-Attention多头注意力机制Mutil-Head Attention位…

【RabbitMQ】一篇文章带你理解消息分发的六种模式

RabbitMQ共有6种工作模式&#xff08;消息分发模式&#xff09;&#xff0c;分别是简单模式、工作队列模式、发布订阅模式、路由模式、主题模式以及RPC模式。 简单模式是最基本的工作模式&#xff0c;也是最简单的消息传递模式。在简单模式中&#xff0c;一个生产者将消息发到…

银行存量客户运营与数字化转型

文章目录 银行运营的基础逻辑银行数字化的需求迷思 银行运营的基础逻辑 “运营”二字看似熟悉&#xff0c;但不同的人理解起来千差万别。商业银行不缺运营&#xff0c;缺少的是在数字化工具深度介入经营行为后各项配套要素的运营。明确运营的基础需求、必要性、目标、主要内容…

如何开发一套基于C#和.NET 6.0手术麻醉系统? 手术麻醉系统源码

如何开发一套基于C#和.NET 6.0手术麻醉系统&#xff1f; 手术麻醉系统源码 基于C#和.NET 6.0开发的手术麻醉系统是一个涉及多个层面的复杂项目。 以下是一个概述性的步骤&#xff0c;帮助你开始这个项目&#xff1a; 一、项目规划和需求分析 1、确定项目目标&#xff1a;明确…

微信小程序简易录音机

首先先创建一个项目&#xff08;想必大家都会啦那就直接开干&#xff09; 首先上html结构 <view class"wx-container"><view id"title">录音机</view><view id"time">{{hours}}:{{minute}}:{{second}}</view>&l…

Ubuntu 20.04安装显卡驱动、CUDA和cuDNN(2024.06最新)

一、安装显卡驱动 1.1 查看显卡型号 lspci | grep -i nvidia我们发现输出的信息中有Device 2230&#xff0c;可以根据这个信息查询显卡型号 查询网址&#xff1a;https://admin.pci-ids.ucw.cz/mods/PC/10de?actionhelp?helppci 输入后点击Jump查询 我们发现显卡型号为RTX …

【html】如何利用hbuilderX 开发一个自己的app并安装在手机上运行

引言&#xff1a; 相信大家都非常想开发一款自己的apk&#xff0c;手机应用程序&#xff0c;今天就教大家&#xff0c;如何用hbuilderX 开发一个自己的app并安装在手机上运行。 步骤讲解&#xff1a; 打开hbuilderX &#xff0c;选择新建项目 2.选择5app,想一个名字&#x…