AITDBClient开发指导
# 1 开发规范
警告
禁止在master分支进行开发!
# 1.1 克隆代码仓库到本地
提示
仅有首次参与开发的同学需要进行这个操作
在个人PC安装好Git,新建空文件夹,用于存储项目代码,在空文件夹内右键鼠标,选择Git Bash Here,打开Git命令行窗口。
在命令行窗口执行
git clone http://172.16.111.6:10080/AIT/BaseInfrastructure/AITDBClient.git
# 1.2 更新master分支代码
提示
刚刚完成克隆代码仓库的同学不需要这个操作;
其他情况需要先更新master分支代码;
cd AITDBManager
git checkout master
git pull
2
3
命令行窗口显示如下信息则说明已更新为最新代码。
Administrator@Evi1-PC MINGW64 /e/doc_demo/AITDBClient (master)
$ git pull
Already up to date.
2
3
# 1.3 创建开发分支
注意
分支命名要有意义;
分支命名要使用英文。
举个例子,我要新增一项二维码识别用途的标注数据,其分支名称可以命名为add_qr_code_recognition_image
git checkout -b add_qr_code_recognition_image
执行成功的效果如下所示,可以看到命令行窗口的分支提示已经变为新创建的分支。
Administrator@Evi1-PC MINGW64 /e/doc_demo/AITDBClient (master)
$ git checkout -b add_qr_code_recognition_image
Switched to a new branch 'add_qr_code_recognition_image'
Administrator@Evi1-PC MINGW64 /e/doc_demo/AITDBClient (add_qr_code_recognition_image)
$
2
3
4
5
6
接下来可以在新分支上进行代码开发。
# 1.4 完成开发后提交合并请求
完成开发的定义是什么?
服务端AITDBManager和客户端AITDBClient均完成开发,自测通过。
提示
分支合并请求在GitLab项目仓库的版本库->分支菜单下,对需要合并的分支进行操作。
开发完成,测试通过后,通过GitLab创建分支合并请求,待项目管理员代码审查通过后合入主干分支。
# 2 概述
提示
- 使用Python3.7.7版本进行开发和运行;
- 使用PypiManager (opens new window)作为pip源;
- 强烈建议使用
virtualenv创建虚拟环境进行开发和运行
# 2.1 项目结构

对于开发人员来说,需要关注的主要内容为以下内容
点击查看
.
├── AITDBClient
│ ├── annotation 【定义新增标注数据的API服务请求体】
│ ├── interface 【定义新增标注数据的API服务请求URL和请求方式】
│ ├── meta
│ ├── models
│ │ ├── ann_model_map.py
│ │ ├── demo_data.py 【定义新增标注数据的示例】
│ │ ├── __init__.py
│ │ ├── sys_enum.py
│ │ ├── sys_model.py
│ │ ├── user_define_enum.py 【可选:增加标注数据对应的model字段枚举类型,用于声明枚举类型】
│ │ └── user_define_model.py 【增加标注数据对应的数据库model,定义标注数据结构】
│ ├── module
│ │ ├── build_meta.py
│ │ ├── __init__.py
│ │ ├── build_payload.py 【绑定标注数据的API请求体构造方法】
│ │ └── registry.py 【绑定标注数据的API接口方法】
│ ├── pipelines
│ ├── run.py
│ ├── utils
│ ├── cli.py
│ └── __init__.py
├── docs
├── HISTORY.md
├── LICENSE
├── MANIFEST.in
├── NOTICE
├── README.md
├── requirements-dev.txt
├── requirements.txt
├── setup.cfg
└── setup.py
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 3 开发要点
警告
禁止在master分支进行开发!
情景提示,下文均以此情景展开
我们以二维码识别的图片标注数据为例进行讲解,已知每一张二维码识别图片的标注信息主要有如下内容:
- 二维码的坐标(数组类型,4个点,8个整型数字)
- 二维码所编码的文本信息(字符串,长度可能会比较大,比如一些URL地址)
- 是否为核心测试场景(字符串)
# 3.1 定义标注数据结构
在models包的user_define_model.py文件中,新增如下代码:
点击查看
class AnnImageQRCodeRecognition(BaseModel, extra=Extra.forbid):
"""图片标注-二维码识别信息数据结构定义"""
data_source: DataSourceInfo = Field(..., description='数据源信息')
equipment: EquipmentInfo = Field(..., description='设备信息')
file_name: str = Field(..., description='图片文件名称')
coordinates_array: List[List[int]] = Field(..., description='标注框坐标数组')
annotation: str = Field(..., description='二维码对应标注内容')
is_core_scene: str = Field(..., description='二维码是否属于核心场景')
remark: Optional[str] = Field(None, description='备注信息')
status: Optional[DeleteStatusEnum] = Field(DeleteStatusEnum.not_delete, description='是否被逻辑删除')
2
3
4
5
6
7
8
9
10
# 3.1.1 model类名规范
标注数据的的model类名分为3段信息:Ann{FileType}{AnnotationDataType}
- 统一以
Ann开头, - 根据测试样本文件实体类型进行区分:
Image、Audio、Video - 最后是标注数据具体类别
class AnnImageQRCodeRecognition(BaseModel, extra=Extra.forbid):
"""图片标注-二维码识别信息数据结构定义"""
data_source: DataSourceInfo = Field(..., description='数据源信息')
equipment: EquipmentInfo = Field(..., description='设备信息')
file_name: str = Field(..., description='图片文件名称')
coordinates_array: List[List[int]] = Field(..., description='标注框坐标数组')
annotation: str = Field(..., description='二维码对应标注内容')
is_core_scene: str = Field(..., description='二维码是否属于核心场景')
remark: Optional[str] = Field(None, description='备注信息')
status: Optional[DeleteStatusEnum] = Field(DeleteStatusEnum.not_delete, description='是否被逻辑删除')
2
3
4
5
6
7
8
9
10
# 3.1.2 model注释规范
根据测试样本实体类型,标注信息类别进行注释:
- 图片标注-XXXX
- 视频标注-XXXX
- 音频标注-XXXX
class AnnImageQRCodeRecognition(BaseModel, extra=Extra.forbid):
"""图片标注-二维码识别信息数据结构定义"""
data_source: DataSourceInfo = Field(..., description='数据源信息')
equipment: EquipmentInfo = Field(..., description='设备信息')
file_name: str = Field(..., description='图片文件名称')
coordinates_array: List[List[int]] = Field(..., description='标注框坐标数组')
annotation: str = Field(..., description='二维码对应标注内容')
is_core_scene: str = Field(..., description='二维码是否属于核心场景')
remark: Optional[str] = Field(None, description='备注信息')
status: Optional[DeleteStatusEnum] = Field(DeleteStatusEnum.not_delete, description='是否被逻辑删除')
2
3
4
5
6
7
8
9
10
# 3.1.3 model字段规范
字段按照作用通常可以分为2类,
- 通用基础字段;
- 标注数据的描述信息。
通用基础字段为:
data_source:数据源信息【必填字段,无需修改】equipment:设备信息【选填字段,若没有设备信息可以不定义此字段】file_name:文件名称【必填字段,需要注意根据文件类型修改注释】remark:备注信息【选填字段,默认值为None】status:数据状态【选填字段,默认为未删除】
其他字段根据标注数据实际情况定义即可,标注数据字段定义必须与AITDBManager的API请求体结构定义相匹配。
枚举类型字段定义参照:AITDBManager开发指导 3.1.4.1 Enum类型定义
class AnnImageQRCodeRecognition(BaseModel, extra=Extra.forbid):
"""图片标注-二维码识别信息数据结构定义"""
data_source: DataSourceInfo = Field(..., description='数据源信息')
equipment: EquipmentInfo = Field(..., description='设备信息')
file_name: str = Field(..., description='图片文件名称')
coordinates_array: List[List[int]] = Field(..., description='标注框坐标数组')
annotation: str = Field(..., description='二维码对应标注内容')
is_core_scene: str = Field(..., description='二维码是否属于核心场景')
remark: Optional[str] = Field(None, description='备注信息')
status: Optional[DeleteStatusEnum] = Field(DeleteStatusEnum.not_delete, description='是否被逻辑删除')
2
3
4
5
6
7
8
9
10
# 3.2 增加标注数据样例
在models的demo_data.py中新增标注数据demo。
DEMO_DATA = {
'AnnAudioVoicePrint': {...},
'AnnAudioASRSpeech': {...},
'AnnImageQRCodeRecognition': {
"data_source": {
"category": "图片",
"cn_name": "二维码识别测试数据",
"en_name": "QRcode_recognition",
"description": "新疆海量、互联网采集、手机翻拍、程序生成的二维码图片"
},
"file_name": "10.jpg",
"equipment": {
"cn_name": "未知",
"en_name": "未知",
"manufacturer": "未知",
"category": "未知"
},
"coordinates_array": [[166, 298, 166, 417, 289, 417, 289, 298]],
"annotation": "https://weixin.qq.com/r/enWIkCrEtnfJrW7z9yBo",
"is_core_scene": "yes"
},
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 3.3 增加标注数据API请求体构造方法
在annotation目录新建ann_image_qrcode_recognition.py文件,新建get_ann_image_qrcode_recognition_payload方法,注意需要对请求体调用remove_none_item_from_dict方法进行预处理。
笔记
文件名命名规则: ann_{文件类型}_{标注数据类型}.py
方法命名规则: get_ann_{文件类型}_{标注数据类型}_payload
"""构造图片二维码识别信息标注样本信息"""
from AITDBClient.utils.data_transform import remove_none_item_from_dict
def get_ann_image_qrcode_recognition_payload(json_data: dict, md5: str, identity_id: int = 0):
"""
构造图片二维码识别信息标注样本信息
:param json_data:
:param md5:
:param identity_id:
:return:
"""
payload = {
'image': md5,
'coordinates_array': json_data.get('coordinates_array', None),
'annotation': json_data.get('annotation', None),
'is_core_scene': json_data.get('is_core_scene', None),
'remark': json_data.get('remark', None),
'status': json_data.get('status', '未删除')
}
return remove_none_item_from_dict(payload)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 3.4 增加标注数据API注册方法
在interface目录新建ann_image_qrcode_recognition.py文件,新建registry_ann_image_qrcode_recognition方法。
笔记
文件名命名规则: ann_{文件类型}_{标注数据类型}.py
方法命名规则: ``registry_ann_{文件类型}_{标注数据类型}`
"""注册图片二维码识别信息标注样本信息"""
import sys
from AITDBClient.utils.http_util import http_cli
from AITDBClient import __API_PREFIX__
from AITUtils.log import logger
@logger.catch(reraise=True)
def registry_ann_image_qrcode_recognition(ann_data: dict):
"""
注册二维码识别标注样本信息
"""
resp = http_cli(method='post',
url=f'{__API_PREFIX__}/ann_image_qrcode_recognition',
payload=ann_data)
if resp['message'] != 'ok':
logger.error(f'{registry_ann_image_qrcode_recognition.__doc__.strip()}失败: {resp} payload: {ann_data}')
sys.exit(-1)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 3.5 绑定标注数据API请求体构造方法
在module的build_payload.py中绑定构造请求体的方法。
导入“二维码识别”标注数据构造方法
增加根据``module_name`判断标注数据构造方法的条件判断
"""根据数据model判断使用哪个标注数据构造的方法"""
import sys
from AITUtils.log import logger
from AITDBClient.annotation.ann_audio_voiceprint import get_ann_audio_voiceprint_payload
from AITDBClient.annotation.ann_audio_asr_speech import get_ann_audio_asr_speech_payload
from AITDBClient.annotation.ann_image_qrcode_recognition import get_ann_image_qrcode_recognition_payload
def chose_build_payload_func(module_name):
"""
根据模型选择请求体构造的方法
:param module_name:
:return:
"""
if module_name == 'AnnAudioVoicePrint':
ann_func = get_ann_audio_voiceprint_payload
elif module_name == 'AnnAudioASRSpeech':
ann_func = get_ann_audio_asr_speech_payload
elif module_name == 'AnnImageQRCodeRecognition':
ann_func = get_ann_image_qrcode_recognition_payload
else:
# __get_model_name__方法已经做过校验了,此处的校验其实为冗余捕获
logger.error(f'请检查标注数据模型是否支持! 输入的标注数据模型: {module_name}')
sys.exit(-1)
return ann_func
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 3.6 绑定标注数据API注册方法
在module的registry.py中绑定标注数据API的方法。
- 导入“二维码识别”标注数据注册方法
- 增加根据``module_name`判断标注数据注册方法的条件判断
import sys
from AITUtils.log import logger
from AITDBClient.interface.common import registry_audio_meta, registry_image_meta, registry_video_meta
from AITDBClient.interface.ann_audio_voiceprint import registry_ann_audio_voiceprint
from AITDBClient.interface.ann_audio_asr_speech import registry_ann_audio_asr_speech
from AITDBClient.interface.ann_image_qrcode_recognition import registry_ann_image_qrcode_recognition
@logger.catch(reraise=True)
def registry_ann_data(model_name, ann_data_payload):
"""
注册标注数据
:param model_name:
:param ann_data_payload:
:return:
"""
if model_name == 'AnnAudioVoicePrint':
registry_ann_audio_voiceprint(ann_data=ann_data_payload)
elif model_name == 'AnnAudioASRSpeech':
registry_ann_audio_asr_speech(ann_data=ann_data_payload)
elif model_name == 'AnnImageQRCodeRecognition':
registry_ann_image_qrcode_recognition(ann_data=ann_data_payload)
else:
logger.error('注册标注数据失败,当前数据模型不支持...请联系管理员')
sys.exit(-1)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 3.7 更新版本号
更新__init__.py文件的__version__ = 'x.y.z'
版本号升级规则 :增加数据模型y加1,修改缺陷z加1,示例如下:
__version__ = '1.12.0'
__description__ = 'AI Test Data DataBase Manager Client.'
2
# 3.8 更新release-note
在HISTORY.md中添加本次代码修改内容,示例如下:
1.12.0 (2021-11-04)
------------------
- 发布1.12.0版本,支持护照识别`AnnImageBusinessRecognition` by jma
2
3
- 记得更新版本号
- 记得注明修改人
# 3.9 打包上传
在setup.py文件所在目录的命令行窗口执行python setup.py bdist_wheel命令,执行成功后会在dist目录下生成最新版本的whl包;
将whl包上传至PyPi Manager (opens new window)。
# 4 自测指导
# 4.1 更新服务端
# 4.1.1 进入容器
登录服务器,执行如下命令进入AITDBManager容器:
docker exec -it AITDBManager bash
# 4.1.2 更新开发分支代码
提示
前提是PC开发完成后的代码有提交到GitLab,才能在服务器更新服务端代码。
root@249289b26de8:/# cd /home/AITDBManager/
root@249289b26de8:/home/AITDBManager# git pull
root@249289b26de8:/home/AITDBManager# git checkout add_qr_code_recognition_image
2
3
4
# 4.1.3 重启服务
root@249289b26de8:/home/AITDBManager# systemctl restart aitdbmanager
root@249289b26de8:/home/AITDBManager# systemctl status aitdbmanager
● aitdbmanager.service - AITDBManager
Loaded: loaded (/etc/systemd/system/aitdbmanager.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2021-11-15 07:49:52 GMT; 5s ago
Main PID: 162780 (python)
Tasks: 3 (limit: 29491)
Memory: 65.3M
CGroup: /docker/249289b26de8f51e2cac9847a386d26f181ec78611f867437cfadaf9bcef63ee/system.slice/aitdbmanager.service
└─162780 /usr/local/bin/python /home/AITDBManager/manager.py
Nov 15 07:49:52 249289b26de8 systemd[1]: Started AITDBManager.
Nov 15 07:49:55 249289b26de8 python[162780]: 2021-11-15 07:49:55 | INFO | manager __create_bucket__:75 - 无需创建Minio存储桶
Nov 15 07:49:55 249289b26de8 python[162780]: 2021-11-15 07:49:55 | INFO | manager __load_sys_dict__:110 - 共计69个字典码
Nov 15 07:49:56 249289b26de8 python[162780]: 2021-11-15 07:49:56 | INFO | server serve:64 - Started server process [162780]
Nov 15 07:49:56 249289b26de8 python[162780]: 2021-11-15 07:49:56 | INFO | on startup:26 - Waiting for application startup.
Nov 15 07:49:56 249289b26de8 python[162780]: 2021-11-15 07:49:56 | INFO | on startup:38 - Application startup complete.
Nov 15 07:49:56 249289b26de8 python[162780]: 2021-11-15 07:49:56 | INFO | server _log_started_message:204 - Uvicorn running on http://0.0.0.0:5000 (Press CTRL+C to quit)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
显示信息如上,则说明代码正常,更新成功。
# 4.1.4 浏览器打开Swagger API Doc验证
Chrome浏览器打开 http://172.16.114.1:21212/docs,检查新增的API是否存在且符合预期。

# 4.2 更新客户端
pip install -U AITDBClient
# 4.3 小样本量自测
对新增的标注数据,选取若干条测试样本,按照使用文档说明,进行数据上传测试;
上传成功后,通过查询API,进行测试样本查询,看是否符合预期。
