背景 大批量的excel、txt、压缩包等文件,要进行实现文件管理。
核心需求:需要能够对每一次标注(或其他)任务,提供以下信息
任务背景,描述大致情况,说明为啥要做这件事
任务规则,说明标注规则,每个标注要素的具体含义,或者数据处理的依据
任务问题,说明在当下的规则下,可能会遇到的问题,以及是否有对应措施。
任务迭代,子任务可能存在时间周期跨度较久问题,直接以新任务建文件夹,注明依赖项任务
任务输入与输出文件,对于标注来说,注明每个表字段的具体含义,语料的具体特征,如原始语料问题、某个字段大量为空,越具体越好。对于输出文件,注明处理逻辑。
现状:以语料为例,不同语料的标注规则各有不同,语料的格式不一(excel、doc、pdf、json、txt等),存储的硬件环境不一(本地、外网的不同服务器上、内网的不同服务器上、制品库等)
需求:算法需要某一份标注数据,需要经历如下步骤:回忆在哪=>查找手工记录的归档文件(如果有)=>登录服务器(包含切换网络)=>进入资源目录
上面的流程有一点麻烦,但并不是大问题,重要的不能保证找到的那一份数据文件,是历史上所有的数据文件,也有可能在另外服务器的某个角落,有着类似的数据文件。并且即使归档文件记录了全量的数据,但文件实际分布在不同的环境,取文件的时候也是个小麻烦。如果能全量提供 需求的数据,并在一个地方统一取文件 就好了。
文件夹与文件命名规范 以 四位序号_项目名
作为每个阶段项目的文件夹名,每个子任务以 batch_两位序号_任务核心要求
作为命名规范,如下:
每个子文件夹内部文件命名及存放方式如下:
对于处理的中间文件,不限于excel,python脚本等,都放在 middleware
文件夹中,多个阶段的中间件文件,以 01
序号自增建文件夹。
对于每个任务需求,除了需求方提供的文件,中间产生的任务文件,都属于中间文件。
另外需求方输入文件放 input
文件夹,可能需要备份,语料性质的原始文件,必须要备份。输出文件放在 output
文件夹,必须要备份。中间文件放在 middleware
文件夹,可能要备份。
每个 batch
的根目录,会自动生成一份 readme.txt
里面的内容,来源于在管理系统上填写的内容,具体字段库表 task_batch_list
功能模块 技术选型 前台:
后台:
规划 一期 能展示服务器下的资源目录(第三方标注工具的目录不在一起),这里的优化是统一到一个目录下,搭个文件服务器,界面提供下载
业务上时每个task对应一批(多个文件夹或多个文件)数据文件,可以给每个task打标签,通过标签以及分类来达到归档查询的目的,标签要带上是否加密的标签,未加密数据文件支持在线预览
实际业务多以要素标注为主,集成标注的每个要素:时间、地点、公司名等
涉及整理收集的文件,提供收集背景、下载及对应的说明即可
每个task提供原始数据文件、结果文件、工作区如果是第三方标注工具,应提供对应的第三方位置:如brat提供data的资源目录、labelstudio提供前台登录账号及projectID等;
支持关键字搜索,搜索的区域是每个task的标签及分类、展示的时候默认以时间降序
见《django》篇
二期 需求:
其他 语料管理系统
1.支持文件夹分类,或嵌套分类,以便区分日单位标注任务下的:原始语料、结果语料、说明文档等文件夹
至少是三栏布局,点击日任务时,右侧显示日任务的描述、关联关务、标注需求背景等字段
导出时,支持勾选,支持不同日,不同任务等细粒度勾选
预览应设置文件上线,过大的文件只能下载
文件夹中小文件语料过多时,要按需加载
任务指派时语料的处理,
目前只做语料管理系统,但要考虑到后期对接语料标注系统
语料标注系统
常见预料格式处理需求 pdf分页成pdf
pdf分页成图片
图片转pdf
支持多文件夹处理
常用工具xnConvert
语料管理平台开发 环境
后台
虚拟环境:env_python_tagData
python
包:
库表结构 登录模块 UI
废弃 以下内容为初期手动维护 json
文件的思路,
文件备份自动化 设计出一套文件管理规则后,基于json文件对每个标注任务进行管理,及时记录各个信息。
并使用脚本进行备份
下面两个json文件,可以拆分成四个左右的表,暂时不做可视化操作维护。
文件格式规则
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 [ { "id" : "0006" , "project" : "0006_苏粮合同单据_风控" , "file" : [ { "filename" : "" , "file_origin" : "" , "get_file_time" : "" } , { "filename" : "" , "file_origin" : "" , "get_file_time" : "" } ] , "tag" : [ { "batch" : "01" , "tag_filename" : "" , "desc" : "对苏粮合同中的各类pdf单据,进行切分,然后按类型汇总" , "start_time" : "" , "end_time" : "" , "file_type" : "" , "file_number" : "" , "tools" : "" , "tools_path" : "" , "category" : "03_数据整理" , "external_data" : [ ] , "sovled" : "1" } , { "batch" : "02" , "tag_filename" : "" , "desc" : "整理苏粮合同中的样例数据" , "start_time" : "" , "end_time" : "" , "file_type" : "" , "file_number" : "" , "tools" : "" , "tools_path" : "" , "category" : "03_数据整理" , "external_data" : [ ] , "sovled" : "1" } ] } , { "id" : "0007" , "project" : "0007_聊城审计档案_治理" , "file" : [ { "filename" : "0007_2022审计档案.rar" , "file_origin" : "知语群:聊城审计档案" , "get_file_time" : "2023-05-18" } ] , "tag" : [ { "batch" : "01" , "tag_filename" : "" , "desc" : "聊城审计的档案扫描样例数据已上传群共享,解压密码:8321055。请三位评估下:(1)客户的扫描文件我们能否处理,需不需要对客户的扫描做约束要求(2)客户提供的excel统计表格是否满足要求,是否需要调整 (3)对照南京市局,分析下聊城审计档案的数据跟南京的有多大差异,我们落地聊城审计档案需不需要额外的处理工作量" , "start_time" : "" , "end_time" : "" , "file_type" : "" , "file_number" : "" , "tools" : "" , "tools_path" : "" , "category" : "" , "external_data" : [ ] , "sovled" : "0" } ] } , { "id" : "0008" , "project" : "0008_海门检察院" , "file" : [ { "filename" : "0008_06海门检察院" , "file_origin" : "74/home/rhino/zkq/2023/06海门检察院/检察院土地执行" , "get_file_time" : "2023-05-19" } ] , "tag" : [ { "batch" : "01" , "tag_filename" : "0008_06海门检察院" , "desc" : "算法人员对文件夹中的行政决定处罚书pdf做了与处理后,给到txt,标注26号要求演示的8个要素" , "start_time" : "2023-05-22" , "end_time" : "2023-05-22" , "file_type" : "txt" , "file_number" : "238" , "tools" : "labelstudio" , "tools_path" : "http://10.45.150.74:8082/projects/76/data?tab=157" , "category" : "01_数据标注_NER" , "external_data" : [ ] , "sovled" : "1" } ] } ]
每个task下的json
1 2 3 4 5 6 7 8 [ { "batch" : "01" , "source_file_path" : "0008_海门检察院/batch_01_演示数据标注/tag_origin_v1/*.txt" , "tag_result_path" : "0008_海门检察院/batch_01_演示数据标注/tag_result_v1/project-76-at-2023-05-22-16-00-f4e5a0fd.json" , "backup_name" : "0008_海门检察院/batch_01_演示数据标注/0008_backup_batch_01.zip" } ]
backup.py
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 import osimport jsonimport globimport shutilimport asyncioods_path = './ods/readme.json' dwd_path = './dwd/' backup_path = './backup/' async def merge_readme (): ods_readme_content = [] paths = glob.glob(dwd_path + '/*/readme.json' ) with open (ods_path, 'r' , encoding='utf-8' ) as fr: ods_readme_content = json.load(fr) for task in ods_readme_content: id = task['id' ] for batch in task['tag' ]: external_data = batch['external_data' ] outer_batch_id = int (batch['batch' ]) for path in paths: if id in path: with open (path, 'r' , encoding='utf-8' ) as fr1: task_content = json.load(fr1) for task in task_content: inner_batch_id = int (task['batch' ]) if inner_batch_id == outer_batch_id: external_data.append(task) with open ('readme_merge.json' , 'w' ) as fw: json.dump(ods_readme_content, fw, ensure_ascii=False ) async def backup (): await merge_readme() zip_path_list = [] rel_path = [] with open ('./readme_merge.json' , 'r' , encoding='utf-8' ) as fr: content = json.load(fr) for task in content: for item in task['tag' ]: backup_name = item['external_data' ][0 ]['backup_name' ] if (backup_name != '' ): zip_path_list.append(backup_name.split('/' )[-1 ]) rel_path.append(os.path.join('./dwd' , backup_name)) print (zip_path_list, rel_path) backup_file_list = os.listdir('/app/tag/backup' ) for i in range (len (zip_path_list)): if zip_path_list[i] in backup_file_list: print ('{0} 已备份过,跳过备份!' .format (zip_path_list[i])) else : print ('正在备份{0}...' .format (zip_path_list[i])) shutil.copy(rel_path[i], backup_path) print ('备份完成' ) if __name__ == '__main__' : asyncio.run(backup())
必要的人工 平时只需要维护资源索引目录即可
定期如每月,上传至指定目录后,更新依赖的JSON配置文件(后期如果新增了后台管理),这个配置文件也可以复用,通过后台新增的数据,也同步到配置里