65.9K
CodeProject 正在变化。 阅读更多。
Home

CodeProject.AI 模块创建:Python 全面演练

starIconstarIconstarIconstarIconstarIcon

5.00/5 (3投票s)

2024 年 2 月 15 日

CPOL

12分钟阅读

viewsIcon

22226

downloadIcon

418

使用 Python 为 CodeProject.AI 创建一个最基本的模块的全面演练

引言

CodeProject.AI 服务器提供了粘合剂、基础设施和前端,可以将您希望暴露给应用程序的任何 AI 项目捆绑在一起。通过为您的 AI 项目代码创建一个简单的包装器,您可以获得一个具有完整生命周期管理、部署、更新以及暴露给任何应用程序、任何语言的模块。您有趣的控制台项目现在随处可用。

我们的示例 CodeProject.AI 服务器模块

在我们的示例中,我们将采用一个简单的 Python 程序,该程序使用 PyTorch 和 YOLOv8 模型进行对象检测。我们将使用的程序是一个在控制台上运行的单个 Python 文件,使用

python3 detect.py --input test.jpg --assets assets --model yolov8m --threshold 0.6

它将产生类似以下的输出

Label        confidence    bounding box
====================================================
chair           91%        (102, 272)   - (242, 421)
potted plant    88%        (9, 226)     - (71, 337)
chair           72%        (235, 203)   - (336, 358)
laptop          69%        (231, 221)   - (300, 259)
chair           66%        (0, 361)     - (91, 439)

我们将把它变成一个可以通过 API 调用来调用的 CodeProject.AI 模块

https://:32168/v1/vision/detect

并将返回

{
   "success":true,
   "message":"Found chair, potted plant, chair...",
   "count":5,
   "predictions":[
      {
         "confidence":0.9158754944801331,
         "label":"chair",
         "x_min":102,
         "y_min":272,
         "x_max":242,
         "y_max":421
      },
      ...
      {
         "confidence":0.665546715259552,
         "label":"chair",
         "x_min":0,
         "y_min":361,
         "x_max":91,
         "y_max":439
      }
   ],
   "processMs":398,
   "inferenceMs":386
}

您希望处理的图像通过简单的 HTTP POST 调用传递给此 API。这意味着任何能够发出 HTTP 调用的应用程序现在都可以使用您的 Python 代码。

再也不用担心设置 Python 和虚拟环境,也不用想如何在 .NET 应用中使用您的 Python 代码。CodeProject.AI Server 将您的 Python 页面暴露给所有人。

构建模块的步骤

  1. 定义模块的设置。这允许 CodeProject.AI 安装程序为我们设置环境,并向服务器提供有关如何启动模块以及模块将服务的 API 路由的信息。
  2. 创建设置脚本。允许我们下载资产或安装所需的任何支持库
  3. 编写一个适配器来包装我们现有的代码。它提供了我们代码与 CodeProject.AI 服务器之间的通信。
  4. 编写一个测试页面。允许我们轻松测试模块
  5. 编写一个打包脚本。不是必需的,但它允许您将模块以 zip 形式重新分发到模块注册表中

开始吧:modulesettings.json 文件

modulesettings.json 文件是所有内容的真正核心。

模块设置存储在 modulesettings.json 文件中。如果您针对不同平台有不同的设置,例如不同版本的运行时,您可以使用 modulesettings.<target>.json 文件。有关文件名目标选项的解释,请参阅文档

对于本练习,我们将在 Windows 上运行 Python 3.9,在 Linux 上运行 Python 3.8。旧版本,是的,但 AI 项目通常会因为其使用的包的要求而使用旧版本的 Python。随意使用您的代码适用的任何版本。

modulesettings.json 文件具有基本格式

{
  "Modules": {

    "DemoModulePython": {
      "Name": "My module name",
      "Version": "2.0.0",

      "PublishingInfo" : {
         ...
      },

      "LaunchSettings": {
         ...
      },

      "EnvironmentVariables": {
         ...
      },

      "GpuOptions" : {
         ...
      },

      "InstallOptions" : {
         ...
      },

      "UIElements" : {
         ...
      },

      "RouteMaps": [
      {
         ...
      }]
    }
  }
}

让我们一步一步地填写这些值

Name 和 version 应该是显而易见的,而 module ID 是您希望提供的任何不与其他模块冲突的 ID。我们将我们的模块标记为DemoModulePython。

我们的 PublishingInfo 部分将包含

"PublishingInfo" : {
  "Description" : "Provides Object Detection YOLOv8",
  "Category"    : "Computer Vision",
  "Stack"       : "Python, PyTorch, YOLO",
  "License"     : "AGPL-3.0",
  "LicenseUrl"  : "https://gnu.ac.cn/licenses/agpl-3.0.en.html",
  "Author"      : "Chris Maunder",
  "Homepage"    : "https://codeproject.com/ai",
  "BasedOn"     : "ultralytics",                         // What project is this based on?
  "BasedOnUrl"  : "https://github.com/ultralytics/ultralytics" // The URL for that project
}

LaunchSettings 将包含

"LaunchSettings": {
  "AutoStart"          : true,                // Start this when the server starts
  "FilePath"           : "detect_adapter.py", // Name of file that gets launched  
  "Runtime"            : "python3.8",         // file is launched by Python
  "RuntimeLocation"    : "Local",             // We want our own virt. env., not a shared one
  "PostStartPauseSecs" : 1,                   // Generally 1 if using GPU, 0 for CPU
  "Queue"              : "objdetect_queue",   // Can be left as null if you wish
  "Parallelism"        : 0                    // 0 = Default (number of CPUs - 1)
}
  • FilePathRuntime 是这里最重要的字段。如果您愿意,可以省略所有其他字段。
  • Queue 指定服务器将从客户端放置请求的位置,以及模块将在其中查找要处理的请求的队列名称。您可以将其留空,也可以提供一个名称,以防您希望有多个模块服务于同一队列。
  • Parallelism 表示将运行以服务此队列的并行任务数量。
  • RuntimeLocation 目前仅用于 Python,可以是“shared”(表示此模块将使用共享虚拟环境以节省空间)或“local”(表示 venv 将位于此模块的本地,以避免包冲突)。

EnvironmentVariables 部分包含我们在启动前希望设置的任何环境变量。

"EnvironmentVariables": {
  "CPAI_MODEL_YOLODEMO_MODEL_SIZE" : "Medium",   // tiny, small, medium, large
  "CPAI_MODEL_YOLODEMO_MODELS_DIR" : "%CURRENT_MODULE_PATH%/assets"
}

注意 CURRENT_MODULE_PATH 宏的使用。有关此信息,请参阅

GpuOptions 仅用于 GPU 设置。

"GpuOptions": {
  "InstallGPU"            : true,    // Should we install GPU enabled code?
  "EnableGPU"             : true,    // Should we enable GPU support (if installed)
  "AcceleratorDeviceName" : null,    // eg "cuda:0" or just leave blank for default
  "HalfPrecision"         : "enable" // For code that supports half-precision. Use 'Force', 'Enable', 'Disable'
}
  • HalfPrecision 允许您禁用不支持半精度操作的旧 CUDA 卡。通常可以省略此项,因为 CodeProject.AI 服务器可以为您做出一些明智的猜测。

InstallOptions 描述模块应该或可能如何、在哪里安装。

"InstallOptions": {
  "Platforms":      [ "windows", "linux" ], 
  "ModuleReleases": [ 
      { "ModuleVersion": "1.0.0", "ServerVersionRange": [ "1.0.0", "2.4.9" ],
        "ReleaseDate": "2023-01-01", "ReleaseNotes": "Initial Release", 
        "Importance": "Major" },
     { "ModuleVersion": "2.0.0", "ServerVersionRange": [ "2.5.0", "" ],
       "ReleaseDate": "2023-02-14", "ReleaseNotes": "Updated for Server 2.5.0",
       "Importance": "Major" } 
  ]
}
  • Platforms 是一个平台列表。支持的选项包括:windows、macos、linux、raspberrypi、orangepi、jetson,以及 arm64 变体:windows-arm64、macos-arm64、linux-arm64。或者,使用“all”表示它可以在任何地方运行。
  • ModuleReleases 是一个版本数组以及它们兼容的服务器版本。在这种情况下,版本 1 兼容 CodeProject.AI Server 版本 1 到 2.4.9,而模块版本 2 兼容 CodeProject.AI 版本 2.5 及更高版本。

UIElements 向服务器提供有关 UI 选项的信息。我们只讨论出现在仪表板上模块行的上下文菜单。我们可以提供一个提供模型大小的菜单。添加第二个菜单选项就像添加另一个菜单对象一样简单({ "Label": .... "Options": ...})。

"UIElements" : {
  "Menus": [{
     "Label": "Half Precision",
     "Options": [
       { "Label": "Force on",    "Setting": "CPAI_HALF_PRECISION", "Value": "force"   },
       { "Label": "Use Default", "Setting": "CPAI_HALF_PRECISION", "Value": "enable"  },
       { "Label": "Disable",     "Setting": "CPAI_HALF_PRECISION", "Value": "disable" }
     ]
  }]
},

RouteMaps 定义了您模块的 API 路由。

"RouteMaps": [{
  "Name": "Python YOLOv8 Object Detector",
  "Route": "vision/detection",
  "Method": "POST",
  "Command": "detect",
  "Description": "Detects objects",

  "Inputs": [
    {
      "Name": "image",
      "Type": "File",
      "Description": "The HTTP file object (image) to be analyzed."
    },
    {
      "Name": "min_confidence",
      "Type": "Float",
      "Description": "The minimum confidence level (0.0 - 1.0) for an object will be detected.",
      "DefaultValue": 0.4,
      "MinValue": 0.0,
      "MaxValue": 1.0
    }],

  "Outputs": [{
    "Name": "success",
    "Type": "Boolean",
    "Description": "True if successful."
    },
    ... 
  ]
 }
]
  • Route 是调用者将用于调用此模块的路由。vision/detection 路由将对应于 API 调用 https://:32168/v1/vision/detection
  • Command 是将发送到此路由的命令。您可以设置转到同一路径但发送不同命令的路由。由您的模块负责适当地处理命令。
  • InputsOutputs 定义输入参数和输出结果,并用于自动记录您的模块。

为 Windows 添加一个变体 modulesettings 文件

为了本演示的方便,我们将添加一个专门针对 Windows 的 modulesettings 文件,并将 Python 版本从 3.8 更改为 Windows 上的 3.9。我们将文件命名为 modulesettings.windows.json,它将只包含被覆盖的值。

{
  "Modules": {
    "DemoModulePython": {
      "LaunchSettings": {
        "Runtime": "python3.9"
      }
    }
  }
}

设置系统

我们模块的大部分设置将根据模块设置文件的内容自动处理,因此在某些情况下,您的设置脚本将是空的。在我们的例子中,我们将下载 YOLOv8 模型,因此我们的设置脚本非常基础。

@if "%1" NEQ "install" (
    echo This script is only called from ..\..\setup.bat
    @pause
    @goto:eof
)

REM Download the YOLO models from the CodeProject models/ folder and store in /assets
call "%sdkScriptsDirPath%\utils.bat" GetFromServer "models/" "models-yolo8-pt.zip" "assets" "Downloading Standard YOLO models..."
if [ "$1" != "install" ]; then
    read -t 3 -p "This script is only called from: bash ../../setup.sh"
    echo
    exit 1 
fi

# Download the YOLO models from the CodeProject models/ folder and store in /assets 
getFromServer "models/" "models-yolo8-pt.zip"  "assets" "Downloading Standard YOLO models..."

在这里,我们使用 CodeProject.AI SDK 中的 getFromServer 方法。有关这些方法的更多信息,请参阅安装脚本文档。请注意,除非您的资产托管在 CodeProject 服务器上,否则您需要从存储资产的任何位置手动下载它们。

设置的核心由 CodeProject.AI 服务器设置脚本处理。它们将检测运行时(Python),确保安装了我们选择的版本,设置虚拟环境,并安装所需的 Python 包(如在相应的 requirements.txt 文件中指定的那样)。

安装后

在某些情况下,您可能需要执行一些安装后命令来处理诸如修补库之类的场景。这是通过包含 post-install.bat / post-install.sh 文件来完成的,如果存在,安装程序将执行这些文件。在我们的演示中,我们包含了修补 ultralytics 库的安装后脚本。

Requirements.txt

如果您针对不同的平台有不同的 requirements.txt 文件,请参阅requirements.txt 文档

.NET

对于 .NET 模块,.NET 已经作为服务器设置的一部分安装。

编写模块本身:适配器

我们要包装的代码在与本文相关的 zip 下载文件中。在detect.py 文件中,您会发现我们希望在 do_detection 方法中公开的代码的核心。

def do_detection(img: any, threshold: float = 0.4, models_dir: str = "assets",
                 model_name: str = "yolov8m", resolution: int = 640,
                 use_Cuda: bool = False, accel_device_name: int = 0,
                 use_MPS: bool = False, use_DirectML: bool = False,
                 half_precision: str = "enable"):

此方法将输出一个对象,其形式为

{
  "message"     : "Detected car, bike and person",
  "count"       : 3,
  "predictions" : [ ... ],
  "success"     : True,
  "processMs"   : 50,
  "inferenceMs" : 20
}

其中 predictions 是一个对象数组,其形式为

{
  "confidence": 0.87,
  "label": "car",
  "x_min": 20,
  "y_min": 10,
  "x_max": 100,
  "y_max": 50,
}

传递给 do_detection 方法的参数在这里不太重要。只要您了解您的代码需要什么,您就可以跟随。

要包装此方法,我们创建一个从 CodeProject.AI Server SDK 中的 ModuleRunner 类派生的适配器。

适配器的基本骨架是

# Import or general libraries
import os
import sys

# Import the CodeProject.AI SDK. This will add to the PATH var for future imports
sys.path.append("../../SDK/Python")
from common import JSON
from request_data import RequestData      # RequestData is passed to 'process'
from module_options import ModuleOptions  # Handle options passed to the module
from module_runner import ModuleRunner    # The ModuleRumne core
from module_logging import LogMethod      # For logging

# Import the method of the module we're wrapping
from detect import do_detection

# Our adapter
class YOLOv8_adapter(ModuleRunner):

    def initialize(self):
        # (optional) initialise the module. 

    def process(self, data: RequestData) -> JSON:
        # process the request and return the results as JSON

    def status(self) -> JSON:
        # (optional) return the module status as JSON

    def update_statistics(self, response):
        # (optional) Update statistics if required    

    def selftest(self) -> JSON:
        # (optional but encouraged) Perform a self-test

    def cleanup(self) -> None:
        # (optional) Perform any cleanup required

if __name__ == "__main__":
    YOLOv8_adapter().start_loop()

这些方法中的每一个都覆盖了父 ModuleRunner 类中相应的方法。您实际上只需要覆盖 process,但对于我们的示例,我们将展示典型的 initializeselftest,并展示 statusupdate_statistics 的工作方式。

initialize。或 initialise

您可以选择其中一个。此方法为我们设置了东西。在这里,我们将检测 GPU 代码是否已启用,设置一些值,并初始化一些统计信息。

    def initialise(self):
        # Can we use the GPU (via PyTorch / CUDA)?
        if self.system_info.hasTorchCuda:
            self.can_use_GPU       = True
            self.inference_device  = "GPU"
            self.inference_library = "CUDA"

        self.models_dir        = ModuleOptions.getEnvVariable("CPAI_MODULE_YOLODEMO_MODEL_DIR",  "assets")
        self.std_model_name    = ModuleOptions.getEnvVariable("CPAI_MODULE_YOLODEMO_MODEL_NAME", "yolov8m")
        self.resolution_pixels = ModuleOptions.getEnvVariable("CPAI_MODULE_YOLODEMO_RESOLUTION", 640)
        self.accel_device_name = "cuda" if self.can_use_GPU else "cpu"
       
        # Let's store some stats
        self._num_items_found = 0
        self._histogram       = {}

ModuleRunner 有一个 system_info 属性,它提供了关于当前环境的大量信息,并执行一些基本的功能检查,以用于 PyTorch 等常见库。在这里,我们检查 CUDA 是否已启用。如果是,我们将 can_use_GPU 设置为 True,以指示我们的模块可以使用 GPU,并设置推理设备和库,以便在仪表板上报告。

我们使用 ModuleOptions 类来帮助检测环境变量中设置的值,同时提供默认值。

_num_items_found_histogram 属性将存储我们找到的内容的信息。这些将补充 ModuleRunner 类中默认收集的统计信息。

process

在这个演示中,我们的 process 方法将通过两种不同的方式(默认和自定义模型)执行一件事(检测对象),以演示路由和命令。我们有两个路由:/v1/vision/detect/v1/vision/custom/<model>,其中 <model> 是用于对象检测的自定义模型名称。

我们使用 data (RequestData) object 来获取传递给方法的参数和文件。您将在下面的 selftest 和 explorer 讨论中看到如何将参数和文件传递给服务器 API。

data.command 属性具有传递给路由的命令,而 data.segments 包含路由后的路由段。例如,路由 /v1/vision/custom 使用“/v1/vision/custom/model-name”调用,因此 segments 将包含单个条目“model-name”。

我们还使用 ModuleRunner.log 方法将日志条目发送回服务器。

process 方法非常简单:它收集参数并将它们发送到我们的 do_detection 方法,然后返回结果。这是一个 JSON 响应,因此我们无需进行任何后处理。

    def process(self, data: RequestData) -> JSON:
        
        response = None

        if data.command == "detect": # Detection using standard models (API: /v1/vision/detection)

            threshold: float = float(data.get_value("min_confidence", "0.4"))
            img: Image       = data.get_image(0)
            model_name: str  = "yolov8m"

            response = do_detection(img, threshold, self.models_dir, model_name, 
                                    self.resolution_pixels, self.can_use_GPU, self.accel_device_name,
                                    False, False, self.half_precision)

        elif data.command == "custom": # Detection using custom model (API: /v1/vision/custom/<model>)

            threshold: float  = float(data.get_value("min_confidence", "0.4"))
            img: Image        = data.get_image(0)
            model_name: str   = None

            if data.segments and data.segments[0]:
                model_name = data.segments[0]

            if not model_name:
                return { "success": False, "error": "No custom model specified" }
            
            if not os.path.exists(os.path.join(self.models_dir, model_name + ".pt")):
                return { "success": False, "error": f"Could not find custom model {model_name}" }

            self.log(LogMethod.Info | LogMethod.Server,
            { 
                "filename": __file__,
                "loglevel": "information",
                "method": sys._getframe().f_code.co_name,
                "message": f"Detecting using {model_name}"
            })

            response = do_detection(img, threshold, self.models_dir, model_name, 
                                    self.resolution_pixels, self.can_use_GPU, self.accel_device_name,
                                    False, False, self.half_precision)
            
        else:
            response = { "success" : False }
            self.report_error(None, __file__, f"Unknown command {data.command}")

        return response

update_statistics

此方法在每次 process 调用后调用。我们将覆盖此方法,以便我们可以检测到什么并生成一些统计信息。

    def update_statistics(self, response):
        super().update_statistics(response)
        if "success" in response and response["success"] and "predictions" in response:
            predictions = response["predictions"]
            self._num_items_found += len(predictions) 
            for prediction in predictions:
                label = prediction["label"]
                if label not in self._histogram:
                    self._histogram[label] = 1
                else:
                    self._histogram[label] += 1

状态

此方法返回模块的状态。默认实现返回诸如调用次数和平均推理时间之类的统计信息,因此我们将添加一些我们的统计信息。

    def status(self) -> JSON:
        statusData = super().status()
        statusData["numItemsFound"] = self._num_items_found
        statusData["histogram"]     = self._histogram
        return statusData    

selftest

我们将讨论的最后一个方法。selftest 方法在设置过程结束时调用,以便让用户知道模块是否成功安装。

process 方法需要一个 RequestData 对象,因此我们将创建一个新的 RequestData 对象,设置命令,添加一个属性/值对,并添加一个文件。然后我们将调用我们的 process 方法并返回结果。

在此示例中,我们将在项目下的 test 文件夹中包含一个 home-office.jpg 图像。

    def selftest(self) -> JSON:
        
        file_name = os.path.join("test", "home-office.jpg")

        request_data = RequestData()
        request_data.command = "detect"
        request_data.add_file(file_name)
        request_data.add_value("min_confidence", 0.4)

        result = self.process(request_data)
        print(f"Info: Self-test for {self.module_id}. Success: {result['success']}")

        return { "success": result['success'], "message": "Object detection test successful"}

模块的测试页面和 Explorer UI

CodeProject.AI Server 提供了一个 HTTP API,因此最简单的测试方法是使用 Postman、Swagger 或您自己编写的简单 HTML 页面等工具。我们将采用后者。

我们将编写一个简单的网页,通过其 API 调用模块并显示结果。我们通过一个特殊的 `explore.html` 文件来实现这一点,该文件将以一种方式编写,允许 CodeProject.AI Server 的 Explorer 从此 explore.html 文件中提取 UI 并将其合并到服务器主 explorer.html 文件中。

完整的 HTML 文件显示如下。注意由标记的 3 个部分

  1. START/END EXPLORER STYLE
  2. START/END EXPLORER MARKUP
  3. START/END EXPLORER SCRIPT

这三个部分将从该文件中提取并插入到服务器主 explorer.html 文件中。为了使其无缝工作,最好让您模块的 explore.html 测试文件使用相同的脚本并遵循与服务器主 Explorer 文件 explorer.html 相同的命名约定。

具体来说

  1. 我们包含了 explorer.js 类以访问用于调用服务器 API 的方法。
  2. 我们包含了 imgPreviewimgMask 元素用于显示图像结果。
  3. 我们包含了一个 results 元素用于显示文本结果。
  4. 我们使用 _MID_ 宏为可能发生命名冲突的 ID 添加前缀。此标记将在服务器主 explorer.html 文件中被模块的 ID 替换,以避免名称冲突。

我们的页面是

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Object Detection (YOLOv8) Module Test</title>

    <!-- CSS and script helpers from the server -->
    <link id="bootstrapCss" rel="stylesheet" type="text/css" href="https://:32168/assets/bootstrap-dark.min.css">
    <link rel="stylesheet" type="text/css" href="https://:32168/assets/server.css?v=2.5.0.0">
    <script type="text/javascript" src="https://:32168/assets/server.js"></script>
    <script type="text/javascript" src="https://:32168/assets/explorer.js"></script>

    <style>
/* START EXPLORER STYLE */
/* styles for this module if needed */
/* END EXPLORER STYLE */
    </style>

</head>
<body class="dark-mode">

<!-- START EXPLORER MARKUP -->
    <div class="form-group row">
        <label class="col-form-label col-2">Image</label>
        <input id="_MID_image" class="col form-control btn-light" type="file" style="width:17rem"
               onchange="return previewImage(this)" />
        <input id="_MID_things" class="form-control btn-success" type="button" value="Detect Objects"
               style="width:11rem" onclick="_MID_onDetectThings(_MID_image)"/>
    </div>
<!-- END EXPLORER MARKUP -->

    <div class="w-100 position-relative form-control my-4 p-0">
        <div id="imgMask" class="position-absolute"
             style="left:0;top:0;pointer-events:none;z-index:10"></div>
        <img src="" id="imgPreview" class="w-100" style="height:250px;visibility:hidden">
    </div>
    <div>
        <h2>Results</h2>
        <div id="results" name="results" class="bg-light p-3" style="min-height: 100px;"></div>
    </div>

    <script type="text/javascript">
// START EXPLORER SCRIPT

        async function _MID_onDetectThings(fileChooser) {

            clearImagePreview();

            if (fileChooser.files.length == 0) {
                alert("No file was selected for vision detection");
                return;
            }

            showPreviewImage(fileChooser.files[0]);
            let images = [fileChooser.files[0]];

            setResultsHtml("Detecting objects...");
            let data = await submitRequest('vision', 'detection', images, null);
            if (data) {
                showResultsBoundingBoxes(data.predictions);
                showPredictionSummary(data)
            };
        }

// END EXPLORER SCRIPT
    </script>
</body>
</html>

创建打包器

最后(可选)一步是创建打包器。CodeProject.AI Server 代码包含一个脚本 create_packages.bat(适用于 Windows)和 create_packages.sh(适用于 macOS/Linux),它将遍历模块并使用您创建的 package.bat / package.sh 脚本创建一个包。此包是一个简单的 zip 文件,安装程序可以使用您上面创建的 install.bat / install.sh 文件进行安装。

@Echo off
REM Module Packaging script. To be called from create_packages.bat

set moduleId=%~1
set version=%~2

tar -caf %moduleId%-%version%.zip --exclude=__pycache__  --exclude=*.development.* --exclude=*.log ^
    rembg\* *.py modulesettings.* requirements.* install.sh install.bat explore.html test\*
#!/bin/bash
# Module Packaging script. To be called from create_packages.sh

moduleId=$1
version=$2

tar -caf ${moduleId}-${version}.zip --exclude=__pycache__  --exclude=*.development.* --exclude=*.log \
    rembg/* *.py modulesettings.* requirements.* install.sh install.bat explore.html test/*

整合:安装和测试

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

  1. 确保您已下载最新的CodeProject.AI 存储库。其中已经包含了我们之前讨论过的所有代码。

  2. 将您的模块文件夹复制到 CodeProject.AI Server 代码的 src/modules 文件夹下。打开终端并导航到该文件夹,然后运行主 CodeProject.AI Server 安装脚本。

    ..\..\setup.bat
    
    bash ../../setup.sh
    
    您将看到类似以下内容:
    Installing CodeProject.AI Analysis Module
    
    ======================================================================
    
                       CodeProject.AI Installer
    
    ======================================================================
    
    47.6Gb of 380Gb available on BOOTCAMP
    
    General CodeProject.AI setup
    
    Creating Directories...Done
    
    GPU support
    
    CUDA Present...No
    ROCm Present...No
    
    Reading DemoModulePython settings.......Done
    Installing module Python Object Detector (YOLOv8) 1.0.0
    
    Installing Python 3.9
    Python 3.9 is already installed
    Creating Virtual Environment (Shared)...Virtual Environment already present
    Confirming we have Python 3.9 in our virtual environment...present
    Downloading Standard YOLO models...already exists...Expanding...Done.
    Copying contents of models-yolo8-pt.zip to assets...done
    Downloading Custom YOLO models...already exists...Expanding...Done.
    Copying contents of custom-models-yolo8-pt.zip to custom-models...done
    Installing Python packages for Python Object Detector (YOLOv8)
    Installing GPU-enabled libraries: If available
    Ensuring Python package manager (pip) is installed...Done
    Ensuring Python package manager (pip) is up to date...Done
    Python packages specified by requirements.txt
      - Installing PyTorch, for Tensor computation and Deep neural networks...checked...done
      - Installing TorchVision, for Computer Vision based AI...checked...done
      - Installing Ultralytics package for object detection in images...checked...done
    Installing Python packages for the CodeProject.AI Server SDK
    Ensuring Python package manager (pip) is installed...Done
    Ensuring Python package manager (pip) is up to date...Done
    Python packages specified by requirements.txt
      - Installing Pillow, a Python Image Library...checked...done
      - Installing Charset normalizer...checked...done
      - Installing aiohttp, the Async IO HTTP library...checked...done
      - Installing aiofiles, the Async IO Files library...checked...done
      - Installing py-cpuinfo to allow us to query CPU info...checked...done
      - Installing Requests, the HTTP library...checked...done
    Executing post-install script for Python Object Detector (YOLOv8)
    Applying Ultralytics patch
            1 file(s) copied.
    Self test: Self-test passed
    Module setup time 00:00:28.37
    
    Setup complete
    
    Total setup time 00:00:29.28	    
    	

    Python 已安装,虚拟环境已设置,requirements.txt 文件用于安装 Python 包,模型已下载,安装后脚本已运行。您的模块也已测试,现在可以启动了。

    请注意,如果您在 Linux 或 macOS 上运行此设置,将使用 Python 3.8。在 Windows 上,由于我们的 modulesettings.windows.json 文件,我们将安装 Python 3.9。
     
  3. 通过在 Visual Studio 或 VS Code 中启动新的调试会话来启动服务器。
     
  4. 在 Debug 模式下,CodeProject.AI Dashboard 会在运行时自动启动。服务器启动后,所有后端模块(包括您的新模块)都将启动,并且 Dashboard 将显示类似以下内容:

  5. 在浏览器中打开 explore.html 文件,选择一个文件,然后单击“Submit”按钮。结果应会显示出来。也可以在服务器的 explorer.html 中进行测试。

结论

为 CodeProject.AI 编写模块并不难,尽管您确实需要注意一些事项。modulesettings.json 文件定义了设置和启动参数,并且可以通过不同的变体覆盖模块设置文件的能力,从而提供对环境的精细控制。类似的 Python requirements 文件系统支持在各种硬件和软件组合上安装 Python 应用程序通常涉及的巨大复杂性。

选择您希望包装并向世界公开的代码确实需要您考虑将该代码安装在远程用户计算机上的实用性,但安装和安装后脚本提供了很大的灵活性来绕过可能出现的微妙(或完全的障碍)。

对于普通开发人员来说,唯一剩下的就是托管下载并将您的模块发送给我们。我们很乐意将模块包含在主 CodeProject.AI 模块注册表中。

展示您的创造力,让我们一起努力将您所有出色的 AI 项目从您的桌面和 Jupyter Notebook 中解放出来,并将它们转化为 CodeProject.AI 服务器数十万用户可以享受的模块。

© . All rights reserved.