向服务器添加新模块CodeProject.AI

目录

介绍

30秒内完成CodeProject.AI服务器架构

向服务器添加新模块CodeProject.AI

添加先决条件

必需(用于开发)

可选(适用于最终用户)

编写模块

让我们添加一个模块

安装程序(安装程序)

对于Windows(setup_dev_env_win.bat)

对于Linux

模块的接口

模块的源代码

modulesettings.json文件

将调用新模块的客户端

安装和测试

接下来呢?


介绍

本文指的是 CodeProject.AI Server v1.5.0+版本

如果你乐于遵循曲折的迷宫,那么将 AI功能添加到应用程序是相当简单的,这是无穷无尽的库、工具、解释器、包管理器和所有其他有趣的东西,有时使编码和洗碗一样有趣。

我们构建 CodeProject.AI服务器是为了向开发人员隐藏所有烦人的事情,并给他们留下一个简单的AI包,该包可以做一些事情,并且易于与现有应用程序一起使用。

如果CodeProject.AI服务器没有满足您的需求,那么很容易添加可以填补空白的模块。

30秒内完成CodeProject.AI服务器架构

CodeProject.AI服务器是基于HTTPREST API服务器。它基本上只是一个Web服务器,您的应用程序向其发送请求。这些请求被放置在队列中,分析服务(也称为模块)从它们知道如何服务的队列中挑选请求。然后处理每个请求(根据请求执行AI操作),并将结果发送回API服务器,而API服务器又将其发送回进行初始调用的应用程序。

假设我们有3个分析模块,使用Python 3.7的人脸识别、使用.NET的对象检测和使用Python 3.10的文本分析:

  1. 应用程序向API服务器发送请求
  2. API服务器将请求放在相应的队列中
  3. 后端模块轮询它们感兴趣的队列,获取请求并处理它
  4. 然后,后端模块将结果发送回API服务器
  5. 然后,API服务器将结果发送回调用应用程序

CodeProject.AI服务器API服务器独立于调用应用程序运行。

CodeProject.AI服务器想象成数据库服务器或您在后台运行的任何其他服务:它作为服务或守护程序运行,您发送命令并响应结果。您不会担心它如何开展业务的细节,您只需专注于应用程序的核心业务。

向服务器添加新模块CodeProject.AI

添加新模块有2个任务

  1. 确保正确安装任何先决条件,例如模型、库或解释器
  2. 编写实际模块并将其连接到CodeProject.AI服务器

添加先决条件

需要将模型、解释器、编译器和工具等先决条件添加到开发设置脚本中,以便允许处理代码的每个人都拥有适用于该模块的开发环境。如果选择将模块包含在Windows安装程序或Docker镜像中,则还需要更新这两个环境。

必需(用于开发)

  1. 开发环境设置脚本/Installers/Dev 中是应运行的安装脚本,以便为构建、调试和测试设置开发环境。如果您需要下载和/或安装模型、程序或工具,请确保将命令添加到这些脚本中。

有两个脚本,一个用于Windows,一个用于Linux / macOS。脚本分为多个部分,包括常规设置、可重用函数和与每个给定模块相关的脚本块。

可选(适用于最终用户)

  1. Windows安装程序。如果您希望将新模块与现有模块一起安装在Windows上,则需要为需要放置的任何资产创建一个子安装程序。这并非易事,仅当您希望将工作作为主安装程序的一部分分发时才需要。

将来,模块的资产将简单地与清单文件压缩在一起,安装程序将自动检查并安装在正确的位置。

  1. Docker镜像如果您希望在Docker镜像中安装新模块,则需要更新主Docker镜像,以确保它包含所需的资产和工具。

这两者都不在本文的讨论范围之内。

编写模块

编写模块是有趣的部分。事实上,你通常不必编写一个新模块:有数百个优秀的开源、独立的人工智能项目可以制作出优秀的模块。您需要做的就是确保模块可以在已安装的环境中运行(在先决条件步骤中处理),下载所需的任何模型并将其放置在正确的位置(同样,应该已经完成),并且模块可以与CodeProject.AI服务器通信。

我们将为多种语言提供一个简单的SDK,这将有助于您编写适合模块和CodeProject.AI服务器之间的填充程序,并负责通信。

让我们添加一个模块

我们将添加 remgb 模块。这是一个简单但有趣的AI模块,可以拍摄任何包含主题的照片并从图像中删除背景。它在Python 3.9或更高版本下运行。

安装程序(安装程序)

REMBG模块包括以下内容

  1. Python代码
  2. Python 3.9解释器
  3. 一些Python包
  4. 人工智能模型

为了确保这些在开发环境中都到位,我们需要修改 /Installers/Dev 中的安装脚本。

对于Windowssetup_dev_env_win.bat

:: Background Remover :::::::::::::::::::::::::::::::::::::::::::::::::::::::::

:: The name of the dir containing the Background Remover module
set moduleDir=BackgroundRemover

:: The full path of the background remover module
set modulePath=%analysisLayerPath%\%moduleDir%

:: The name of the dir containing the background remover models
set moduleAssetsDir=models

:: The name of the file in our S3 bucket containing the assets required for this module
set modelsAssetFilename=rembg-models.zip

:: Install python and the required dependencies
call :SetupPython 3.9
call :InstallPythonPackages 3.9 "%modulePath%\requirements.txt" "onnxruntime"

:: Download the AI models
call :Download "%storageUrl%" "%downloadPath%\" "%modelsAssetFilename%" "%moduleDir%" ^
               "Downloading Background Remover models..."

:: Copy over the models to the working directory for this module.
if exist "%downloadPath%\%modulesDir%" (
    robocopy /e "%downloadPath%\%moduleDir% " "%modulePath%\%moduleAssetsDir% "
)

代码应该是不言自明的:

1、设置将保存模块的目录和子目录的名称,以及要下载的资产的名称。

analysisLayerPath 是包含所有模块的分析文件夹的完整路径。在我们的例子中,这目前是/src/AnalysisLayer

2、安装Python 3.9,然后安装 Python.txt 文件中列出的Python包

:SetupPython是一个安装给定版本的Python的子例程。我们目前仅支持3.73.9,但会根据需要添加更多版本。添加另一个版本真正需要的只是提供64python解释器的独立下载。

:InstallPythonPackages遍历提供的需求文件,并使用给定的python版本安装包。还有第二个参数(此处为“onnxruntime”)允许您提供软件包的名称,如果检测到该名称,可以假定表示已安装所有软件包,并且可以跳过此步骤。这在您需要重新运行安装时提供了优化。

3、下载模型

:Download source_base_url download_storage_path archive_filename extract_dir消息将从source_base_url下载archive_filename,将其存储在download_storage_path中,然后将其解压缩到名为extract_dir的目录中。它还将在下载开始时输出消息archive_filename必须是ZipGZip文件。

source_base_url包含包含所有下载内容的S3存储桶的URL

download_storage_path将是/Installers/Dev/downloads

在这种情况下,archive_filename将是“rembg-models.zip”

extract_dir“BackgroundRemover”

因此,我们将rembg-models.zip 中的模型从我们的S3存储桶下载,并将其存储在/Installers/Dev/downloads/BackgroundRemover 中。

我们将zip存储在 /downloads 目录中而不是直接解压缩到模块目录的原因是,我们可以轻松地重新运行安装脚本,而无需重新下载每个模块的每个资产。

4、将下载的模型复制到模块的工作目录。这里没有什么太花哨的。模型将被复制到 %modulePath%\%moduleAssetsDir%该模型将扩展到 /src/AnalysisLayer/BackgroundRemover/models

对于Linux

该脚本与Windows版本基本相同:

# Background Remover :::::::::::::::::::::::::::::::::::::::::::::::::::::::::

# The name of the dir containing the background remover module
moduleDir='BackgroundRemover'

# The name of the dir containing the background remover models
modulePath="${analysisLayerPath}/${moduleDir}"

# The name of the dir containing the background remover models
moduleAssetsDir='models'

# The name of the file in our S3 bucket containing the assets required for this module
modelsAssetFilename='rembg-models.zip'

setupPython 3.9
installPythonPackages 3.9 "${modulePath}/requirements.txt" "onnxruntime"

Download $storageUrl "${downloadPath}" $modelsAssetFilename "${moduleDir}" "Downloading models..."
if [ -d "${downloadPath}/${moduleDir}" ]; then
    mv -f "${downloadPath}/${moduleDir}" "${modulePath}/${moduleAssetsDir}"
fi

请注意,在我们的脚本中,我们包含了一些小的添加,允许您在需要时强制重新下载,但这些只是详细信息,因此为了简单起见,我们没有在此处包含它们。

模块的接口

我们应该从如何调用模块开始。它可以是我们喜欢的任何内容,所以让我们选择路由/v1/image/removebackground。我们将传入一个图像和一个布尔“use_alphamatting”,它告诉代码是否使用alpha遮罩(更适合模糊边缘)。

返回包将包含单个项目“imageBase64”,其中包含已删除背景的图像的base64编码版本。

模块的源代码

首先,我们在模块目录下创建一个文件夹,并复制模块的代码。在本例中,我们将代码存储在/src/AnalysisLayer/BackgroundRemover 中。为了方便起见,我们将为那些使用Visual Studio的人创建一个Python项目(在VS Code中工作同样简单)。

rembg模块有一个我们需要调用的主方法,名为remove。我们需要能够从客户端对此方法的请求中获取数据,然后将此方法的结果传递回客户端。为此,我们将使用该AnalysisLayer/SDK/codeprojectAI.py模块来提供帮助。

我们还将为rembg创建一个适配器(我们称之为rembg_adapter.py),它将rembg remove方法与我们的codeprojectAI.py帮助程序模块连接起来。

# Import the CodeProject.AI helper
import sys
sys.path.append("../SDK/Python")
from CodeProjectAI import ModuleWrapper, LogMethod

# Import the rembg method we need to call
from rembg.bg import remove

# Import the packages that we need to pass around the data
import base64
from io import BytesIO
import json
import traceback

# Create a CodeProject.AI helper
ai_module = ModuleWrapper()

# The main method containing the loop that will process the queue
def remove_background(thread_name):

    QUEUE_NAME = "removebackground_queue"

    # Hack for debug mode
    if ai_module.moduleId == "CodeProject.AI":
        ai_module.moduleId = "BackgroundRemoval";

    while True:
        queue_entries: list = ai_module.get_command(QUEUE_NAME)

        if len(queue_entries) > 0:
            timer: tuple = ai_module.start_timer("Remove Background")

            for queue_entry in queue_entries:

                req_data: dict = json.JSONDecoder().decode(queue_entry)

                req_id: str            = req_data.get("reqid", "")
                use_alphamatting: bool = ai_module.get_request_value(req_data, "use_alphamatting", "false") == "true"

                output: any = {}

                try:
                    img = ai_module.get_image_from_request(req_data, 0)

                    processed = remove(img, use_alphamatting)

                    buffered = BytesIO()
                    processed.save(buffered, format="PNG")
                    img_dataB64_bytes = base64.b64encode(buffered.getvalue())
                    img_dataB64 = img_dataB64_bytes.decode("ascii");

                    output = {"success": True, "imageBase64": img_dataB64}

                except Exception:
                    err_trace = traceback.format_exc()

                    output = {"success": False, "error": "unable to process the image", "code": 500}

                    ai_module.log(LogMethod.Error | LogMethod.Cloud | LogMethod.Server,
                               { "process": "removebackground",
                                 "file": "rembg_adapter.py",
                                 "method": "remove_background",
                                 "message": err_trace,
                                 "exception_type": "Exception"})

                finally:
                    ai_module.end_timer(timer)

                    try:
                        ai_module.send_response(req_id, json.dumps(output))
                    except Exception:
                        print("An exception occured")

if __name__ == "__main__":
    ai_module.log(LogMethod.Info | LogMethod.Server, {"message":"RemoveBackground module started."})
    remove_background("main_removebackground")

这是我们添加的唯一代码。rembg模块已按原样复制和粘贴,我们正在重用codeprojectAI.py帮助程序类。无需添加任何其他内容(代码方面)。

modulesettings.json文件

此文件位于 BackgroundRemover 文件夹中,指示API服务器如何启动我们的新分析服务。

{
    "Modules": {

        "BackgroundRemoval": {
            "Name": "Background Removal",
            "Activate": true,
            "Description": "Removes backgrounds from images.",
            "FilePath": "BackgroundRemover\\rembg_adapter.py",
            "Platforms": [ "windows", "linux", "macos", "docker" ],
            "Runtime":  "python39",

            "EnvironmentVariables": {
                "U2NET_HOME": "%MODULES_PATH%/BackgroundRemover/models" // where to store the models
            },

            "RouteMaps": [
                // ... (explained below)
            ]
        }
    }
}

环境变量部分定义键/值对,这些键/值对将用于设置模块可能需要的环境变量。在本例中为AI模型文件的路径。这是特定于rembg模块并由其定义的值。

MODULES_PATH是一个宏,它将扩展到包含模块的目录的位置。在本例中为/src/AnalysisLayer

模块配置部分包含有关启动模块的信息。名称和描述是不言自明的。FilePath是要执行的文件相对于MODULES_PATH目录的路径。激活设置是否在运行时启动此模块。

运行时定义将启动文件的运行时。我们目前支持dotnet.NET),python37python 3.7)和python39Python 3.9)。如果省略,CodeProject.AI服务器将尝试根据文件路径进行猜测。

平台数组包含可以运行服务的每个平台的条目。目前支持WindowsLinuxmacOSDocker

该文件还在路由映射部分下定义了模块的API路由

{
  "Modules": {
    "ModulesConfig": {
      "BackgroundRemoval": {
         "Name": "Background Removal",
         "Description": "Removes backgrounds from images.",

         ...

         "RouteMaps": [
           {
             "Path": "image/removebackground",
             "Command": "removebackground",
             "Queue": "removebackground_queue",
             "Description": "Removes the background from images.",
             "Inputs": [ ... ],
             "Outputs": [...]
           }
         ]
       }
     }
   }
}

路径是API路径,在本例中为 localhost5000/v1/image/removebackground。请记住,这是我们(任意)选择的API 。它可以是任何东西,只要它当前未被使用。

命令是API控制器中将调用的方法,在本例中为removebackground。队列是API服务器中将管理此服务请求的队列的名称。

在我们编写的适配器python模块中,我们有代码

QUEUE_NAME = "removebackground_queue"

路由映射中的队列应与此名称匹配。

描述、输入和输出在此阶段纯粹是文档。

将调用新模块的客户端

一个简单的JavaScript测试工具可用于演示新模块

// Assume we have a HTML INPUT type=file control with ID=fileChooser
var formData = new FormData();
formData.append('image', fileChooser.files[0]);
formData.append("use_alphamatting", 'false');

var url = 'http://localhost:5000/v1/image/removebackground';

fetch(url, { method: "POST", body: formData})
      .then(response => {
          if (response.ok) {
              response.json().then(data => {
                  // img is an IMG tag that will display the result
                  img.src = "data:image/png;base64," + data.imageBase64;
              })
          }
      })

该项目包含一个文件test.html用于实现此目的,提供用于收集信息和显示结果的UI

安装和测试

此时,我们有一个模块,一个安装脚本和一个测试客户端。让我们试一试。

  1. 确保已下载最新的 CodeProject.AI服务器存储库。这已经包含了我们上面讨论的所有代码
  2. 运行开发安装脚本。这将确保安装和设置Python 3.9,并安装所需的Python模块。
  3. 通过在Visual Studio或VS Code中启动新的调试会话来启动服务器。
  4. 在调试中,CodeProject.AI服务器仪表板在运行时自动启动。服务器启动后,仪表板将显示所有后端模块的状态,包括我们刚刚添加的后台删除模块。请注意,在下图中,我们已出于演示目的禁用了旧对象检测模块。
  5. 在浏览器中启动index.html文件,选择一个文件并单击“提交”按钮。应显示结果。

接下来呢?

这取决于你。我们演示了一个非常简单的AI模块,它可以从图像中删除背景。主要工作是

  1. 确保您在服务器上有可用的资产(例如模型),以便可以下载它们
  2. 更新安装脚本,以便可以下载资产并将其移动到位,并确保已安装必要的运行时和库
  3. 放入模块的代码并编写适配器,以便它可以与CodeProject.AI服务器通信
  4. 编写描述模块API的模块设置文件
  5. 测试!总是有趣的部分。

您可以添加的内容的可能性几乎是无限的。我们的目标是使开发人员能够轻松添加自己的AI模块,从而从其他人添加的模块中获益。混合搭配,使用不同的训练模块集,尝试设置,看看你可以把它带到哪里。

https://www.codeproject.com/Articles/5332075/Adding-a-new-module-to-CodeProject-AI-Server

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值