From ded2da121b596790e7452c26ca0d84fd27a7ae87 Mon Sep 17 00:00:00 2001 From: zhangyupeng <18246685007@163.com> Date: Thu, 31 Aug 2023 16:24:31 +0800 Subject: [PATCH] =?UTF-8?q?20230831=5F=E6=9F=A5=E9=87=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- check_version_1_0/CheckFalsk.py | 52 ++++++ check_version_1_0/SearchSimPaper.py | 254 ++++++++++++++++++++++++++ check_version_1_0/demo01_multiprocessimg.py | 85 +++++++++ check_version_1_0/demo01_test_redis.py | 110 +++++++++++ check_version_1_0/fasttext/fasttext_api.py | 35 ++++ check_version_1_0/fasttext/fasttext_config.py | 25 +++ check_version_1_0/flask_config.py | 27 +++ check_version_1_0/mysql_collect.py | 102 +++++++++++ check_version_1_0/roformer/roformer_api.py | 141 ++++++++++++++ check_version_1_0/roformer/roformer_config.py | 26 +++ check_version_1_0/util.py | 96 ++++++++++ check_version_1_0/word2vec/word2vec_api.py | 34 ++++ check_version_1_0/word2vec/word2vec_config.py | 26 +++ 13 files changed, 1013 insertions(+) create mode 100644 check_version_1_0/CheckFalsk.py create mode 100644 check_version_1_0/SearchSimPaper.py create mode 100644 check_version_1_0/demo01_multiprocessimg.py create mode 100644 check_version_1_0/demo01_test_redis.py create mode 100644 check_version_1_0/fasttext/fasttext_api.py create mode 100644 check_version_1_0/fasttext/fasttext_config.py create mode 100644 check_version_1_0/flask_config.py create mode 100644 check_version_1_0/mysql_collect.py create mode 100644 check_version_1_0/roformer/roformer_api.py create mode 100644 check_version_1_0/roformer/roformer_config.py create mode 100644 check_version_1_0/util.py create mode 100644 check_version_1_0/word2vec/word2vec_api.py create mode 100644 check_version_1_0/word2vec/word2vec_config.py diff --git a/check_version_1_0/CheckFalsk.py b/check_version_1_0/CheckFalsk.py new file mode 100644 index 0000000..ea98bb2 --- /dev/null +++ b/check_version_1_0/CheckFalsk.py @@ -0,0 +1,52 @@ +# -*- coding:utf-8 -*- +# @Time: 2023/8/15 16:09 +# @Author:ZYP +# @File:CheckFalsk.py +# @mail:zypsunshine1@gmail.com +# @Software: PyCharm +import json +from flask import Flask +from flask import request +from SearchSimPaper import search_sim_paper +import time +import requests +from mysql_collect import mysql +from util import Logging + +app_all_flask = Flask(__name__) + + +@app_all_flask.route('/check', methods=['POST']) +def check_paper(): + """ + 进行文本相似度检测,返回相似的文本 + :return: + """ + # + # message_json = { + # "title": "大型商业建筑人员疏散设计研究", + # "abst_zh": "在城市发展进程当中,逐渐呈现出一些综合性的大型建筑群。也称之为大型商业综合体,而近年来综合体出现的消防问题时主要体现在建筑群,建筑群也是对商务建筑和酒店型建筑的融合,建筑群成为了对城市发展具有重要建设意义的社会主义经济聚集体。我们可以根据其不同的特点和使用功能进行分类,比如城市综合体可分为交通枢纽城市内部综合体和城市内部办公综合体。在目前的城市发展过程中,要对城市建筑进行严格的设计和建造。大型建筑以空间大型为主,相对适应我国城市目前发展的规模,同时也满足城市的基本信使用要求,因此,建筑防火和人员安全疏散工作具有非常重要理论意义。首先,从客观上看,当前我国大型企业商建公司内部网络空间环境较为粗放,从而引发火灾较多,发生火灾的概率逐渐增大。大型商业建筑中有许多商品,如服装、日用品、家用电器等。这些物品大多是易燃易爆物品。这些商品的高密度摆放增加了起火的可能性。由于目前我国大型企业的商业建筑公司内部使用功能相对较多,在一定程度上也增加了火灾发生的可能性,大型商业建筑行业内部某个空间使用的多元化也会促进火灾的发生。大型商业建筑人员比较集中,人员消防安全意识不一样,发生火灾时做出不同的反应。发生火灾时就会造成人员混乱,大型商业建筑内部空间比较大,发生火灾时,消防救援难度大,过火面积比较大,可能无法及时扑灭火灾,造成巨大的生命财产损失。此外,有些大型企业商业建筑公司内部管理人员构成较为复杂,在实际作业人员疏散过程中会出现一系列社会问题。大型商业大厦的内部工作人员非常了解内部结构,在发生火灾时可以快速找到逃生路线。但客户对大型企业商业建筑公司内部控制结构不是很清楚,也会造成客户无法进行及时找到逃生路线,造成工作人员伤亡。而且受大型火灾事件的影响,会对公众心理造成相应的伤害,火灾发生后让人们产生恐惧、烦躁等心理现象,这也会妨碍对火灾的管理。", + # "content": "1大型商业建筑火灾的特点大型企业的商业建筑一般设计为商业综合体,其中包括办公,餐饮,商铺,娱乐等活动场所,具有建筑市场规模大、人数多、火灾荷载大、消防救援难等特点,其建筑火灾具有以下特点。1.1可燃物种类多,火灾荷载集中大型企业综合商业建筑设计一般主要包括室内步行街和大量的商铺柜台等部分。室内步行街是整体消防分区结构的大空间,通常建筑面积可高达数万平方米。包含各种各样的商品信息,这些商品信息的装饰品都是可燃易燃物品,商铺内大量集中摆放的商品都是可燃易燃,具有很大的火灾风险。商场的装修工程材料多采用木材和高分子有机结合材料,进一步增加了火灾荷载。一旦发生火灾,如果不能迅速有效地控制,就不可避免地会形成三维空间蔓延的立体燃烧形式,同时也会产生大量的烟热和有毒有害气体,严重威胁着综合体内的人员,增加了建筑物内人员安全疏散的难度。1.2功能复杂,火灾隐患多大型企业的商业建筑,人多,使用功能多种多样。他们的综合体不仅需要具备国内基本的商业管理功能,还可以进行餐饮、娱乐等活动。在方便我们消费者使用的同时,也增加了火灾安全隐患。一是社会功能的增加导致企业用火用电设备增多,使供配电线路复杂化,用电总量和不同使用时长导致线路荷载过大,增加火灾危险性。二是商业建筑人员较多,类型复杂,人员专业素质水平参差不齐,人为因素造成的火灾难以进行有效改善的监管。第三,餐饮区的热食加工企业作业过程中可能会通过使用明火,增加起火的概率。第四,一些商店的运营会定期进行调整,在调整期间,正常营业和装修施工同时进行,施工可能会产生电火花,增加火灾危险。1.3火灾会产生大量烟气及有毒气体与火灾中烟气产生有关的因素主要包括可燃物燃烧的特性、外部环境和通风条件。商场内有大量的纺织品,发生火灾时会分解产生大量的二氧化碳等有毒气体,不完全燃时大量的碳颗粒之间也会形成一种有毒烟雾:大量的烟气会降低企业建筑物内的能见度,对人员疏散造成困难。有毒气体同时危害人们的生命健康,增加人员伤亡的风险。1.4火灾扑救困难大型企业和各类商业开发建筑面积大、可燃物多、种类多,如果内部发生火灾,就更难采取外部救援的方式,GB50016-2014年《建筑工程设计消防规范》(以下简称《建筑管理条例》)规定,我国商业文化建筑企业必须设置消防安全设施,主要包括消防自动报警信息系统,控排烟系统和自动洒水灭火系统,在防火工作中需要采取有效的预防措施。但是,由于商场工作研究人员对消防安全问题不够重视,未能有效坚持消防工程管理制度,未能定期维护和维修消防设施设备,安装的消防控制系统在火灾初期我们无法及时有效地启动。由于物理力量和设备的限制,以及强热辐射和有毒气体的影响,灭火人员在采用“内攻”灭火方法时,扑救难度大,从而导致灭火效率降低。2大型商业建筑人员安全疏散特点商业活动场所的管理者主要类型是客户和工作研究者,客户类别复杂,密度高,流动性大。在发生重大火,人们的心理感到恐惧和恐慌,这对疏散不利。疏散的特点如下。2.1人员类别复杂商业建筑类型为公共服务建筑,内部人员种类多,部分人员消防安全意识低,在公共场所隐蔽角落吸烟,扔烟头,增加了火灾发生的可能性。此外,如果商场内发生火灾,弱势人群疏散难度大,导致人员疏散速度明显低于火势蔓延速度,无法在安全管理疏散时间内完成疏散。2.2人员密度大随着中国经济社会的快速发展,人们的生活质量和水平逐步提高,大型商厦也因此成为人们周末或节假日吃喝、娱乐、购物的主要场所。在这个时间节点的大型企业商业建筑中,存在大量的客流量,而且集中度也进一步加强。如果此时发生火灾,很容易造成大量人员群死群伤的火灾安全事故。2.3人员流动性强,不熟悉疏散通道商务管理人员对室内布局设计更熟悉一点,在经过一个系统消防安全教育培训后,可以成功找到疏散楼梯和安全出口位置,在发生火灾时,可根据实际发展情况选择合理的疏散逃生路线。但是,对于不熟悉商场平面设计和布局的顾客,在发生火灾的情况下,他们无法在短时间内到达最近的疏散楼梯和安全疏散出口进行逃生。如果建筑物的应急广播系统、疏散标志、应急照明系统出现故障,不能正常启动,不能有效引导疏散人员,就导致被困人员不能及时找到疏散楼梯和安全出口,这就会导致大量的人员在火灾发生时不能及时逃生。2.4人员心理行为复杂人员在火灾发生时,情绪波动大,心理发展状态复杂,包括存在恐慌、恐惧、冲动等心理活动,这就可能导致人员判断失误,同时火场被困人员的行为受心理状态影响较大。这些人员的心理发展状态可能造成比火灾本身更严重的伤害。3大型商业建筑人员安全疏散中存在的问题发生火灾时,在火场周围产生大量的在热辐射、有毒烟气以及让人们产生心理恐慌等问题,疏散过程中还有很多其他不利因素,主要表现为以下几点。3.1疏散路线长根据《建筑条例》的相关法律法规,大型企业商业开发建筑公司内部应设疏散通道,且距离最近的疏散出口直线距离不得超过30米。目前,大型商业建筑一般都有较大面积的中庭空间、大面积步行街、步行街经常设置各种商品促销面板和模型。在疏散工作过程中,实际疏散距离往往已经远远超过30m,放置的各种不同物品给疏散带来很多不便,增加了疏散时间。3.2疏散标志不明确,导向性差当前,为了更好地满足公众需求,进一步提高商业建筑的使用效率,大型商业综合体开始占据主要市场。与中国的一些传统商业建筑企业相比,中国的现代商业建筑也产生了相对较大的发展和变化。目前我国大型企业商业建筑设计不仅规模逐步扩大,而且建筑内部的复杂性也大大提高,大型商业建筑的一系列装修装饰环境变化增加了大型商业建筑行业内部的防火难度。目前,大型商业建筑在内部消防设计过程中存在的弊端主要包括以下几个方面。首先当前大型商业建筑规模的不断扩大也提升了对其进行安全设计过程中的审核考量方面,为了更好的对大型商业建筑的安全性做出相应保证,更好的满足大型商业建筑的功能性,设计人员会对建筑内部进行进一步的设计,这种设计形式也进一步增大了建筑防火疏散工作的困难程度。其次,大型商业建筑公司的空间布局和设计非常复杂,立足于目前我国商场的设计的需要,大多数商业建筑也出现了一些信息共享空间等破坏普通管理组织设计教学形式,这种系统设计的主要形式更为复杂,在满足客户需求的基础上也加大了消防疏散的难度。随着人们物质文化生活水平的不断发展提高,人们对大型商业建筑工程质量的要求也在逐步提高。在这种情况下,许多商业建筑进一步装修装饰。虽然提高了建筑的美观度,但也增加了建筑内的火灾发生的概率。在大型企业商业建筑公司内部,考虑到美观和整体室内装饰艺术风格,疏散楼梯和安全技术出口都采用传统装饰工程材料装饰,疏散标志不明显。在火灾发展的情况下,烟雾弥漫,各类疏散设施标识不明显,给疏散工作带来经济困难。3.3恐慌心理易造成重大伤亡火灾发生时,被困人员会惊慌,大多数人没有进行系统的消防安全教育,没有参加消防疏散演习,没有能力处理火灾和安全疏散逃生,感到危及生命的焦虑和恐惧,失去基本行动判断能力,容易做出危险行为。3.4消防安全管理不到位,影响正常疏散一个完善的消防安全风险管理制度体系,能够保证企业发生火灾时消防设备的及时启动,能够保证工作人员的顺利安全疏散,从而确保工作人员的生命安全。火灾事故发展初期,火灾探测器探测到火情信号后,启动报警装置和自动喷水灭火装置,自动喷水灭火系统通过启动自动喷水灭火操作系统,同时需要启动应急广播信息系统,通知楼内人员提供安全疏散。商场工作经理应有效引导被困顾客选择正确的路线进行安全疏散逃生。但是,在实际生活中,一些大型企业商业建筑的消防设施建设存在损坏或不完善、人员进行消防培训工作不到位、消防安全责任不严格落实、消防安全风险管理会计制度体系不完善等:4大型商业建筑人员安全疏散对策4.1防火安全设计首先,在选择建筑材料时,我们应该倾向于选择耐火性能高的材料,比如钢材。钢化玻璃可以有效阻断传热,减少火焰对人的损害,同时我们使用钢化玻璃为防火区域的建筑材料,灭火设施可以使用自动洒水系统,在发生火灾时通过洒水喷水功能,在钢化玻璃材料表面形成水膜覆盖,实现降低环境温度的目标。第二,在大型企业商业建筑的设计中,首先要确定系统总体战略布局,包括建筑的规模和朝向。建筑内部应划分防火区和防烟区,并用防火墙、耐火楼板等设施隔开,可有效防止火焰和烟雾蔓延,为安全疏散创造有利条件。再次,大型商业建筑防排烟系统设计的合理性决定了火灾蔓延速度和建筑排烟能力,关系到能否在短时间内将人们疏散到安全区域。四是大型企业发展商业建筑中安全管理技术型出口的数量、距离的设置同样具有非常重要的作用,规范中规定,一般可以通过分析商业建筑工程公司营业场所中室内任何一点到安全生产产品出口的直线距离我们应该在30m以内,在火灾情况下有利于缩短工作相关人员提供信息系统安全疏散时间。4.2人员安全疏散设计方法一是完善设计方式。二是加强性能设计。基于性能的设计方法是利用专家对建筑超标部分进行评估和设计,合理有效地设计超标部分。除此之外,还可以通过按照中国传统建筑工程管理结构的特征有针对性的进行防火设计,进一步研究其发展能力提升其安全性。三是建立商业建筑消防体系。建议建立符合商业建筑特点的消防体系,即在企业内部设置微型消防站,配备专职消防人员,设立消防管理部门,定期检查、维护和保养建筑物的消防设施,定期进行消防安全宣传,使商业人员和顾客树立消防安全意识,确保商业建筑安全,减少商业建筑火灾风险,营造安全购物环境,降低发生火灾的可能性。四是加强商业建筑消防建设监管。因此,对于我国商业建筑消防设施的建造,包括一定耐火极限耐火楼板和各种消防设施的配备建造,要保证设计研究阶段的所有消防设计都能在施工管理阶段之前得到有效实施,从根本上解决我国商业建筑的消防安全问题。4.3提升建筑物内部防火安全疏散设计和监督能力针对我国当前消防安全疏散设计研究工作,有关技术人员结合当前大型商业建筑的实际情况,对其内部控制结构方面进行充分把握和理解,进一步提高安全疏散和防火有效设计。在目前的设计过程中,相关专业人员需要关注建筑内部结构,详细记录和掌握大型商业建筑的火灾情况,并在此基础上完善整栋建筑的消防安全疏散设计。同时,在设计过程中,相关人员还可以继续完善相关课题的讨论和研究,将火灾事故原因与建筑内部实际设计因素相结合,使防火和安全疏散系统设计进一步规范,大大降低大型商业建筑内部环境发生火灾的概率。目前,在加强消防安全疏散的过程中,需要不断加强社会监督和防范机制,同时我们需要消防安全疏散设计工作人员的配合和协助,引入第三方监督成本管理制度体系并有效教学实施。由于部分大型商业建筑的内部安全管理属于公共安全事务,有关政府部门有效监督和企业内部管理防火安全设施是十分必要的。其次,在整顿大型企业商业建筑内部管理的过程中,要不断加强设计工作考核体系,运用模拟教学法对其安全教育机制进行有效的绩效考核,并相对有效地提高技术水平,进一步为大型商业建筑的防火和安全疏散奠定坚实的基础。4.4设计安全通道和防火区域一般企业来说,大型商业建筑居多,人员分布非常集中,走廊安全疏散的科学技术要求我们不断努力提高。确保疏散通道的安全性和实用性,在安全要求较高的人口密集区域设置疏散通道,更好地保障大型商业建筑与外界的连接,在一定时间内有效疏散群众。其次,一些建筑物内安全疏散通道的数量和方向,需要根据生活信息的实际需要确定。其次,在进行安全疏散通道的设计过程中,应对相应问题设置照明设备设施,以减少因光线不足而导致的一些踩踏事件,并加强企业的安全管理和疏散通道的通风。主要防火保护区的设置也是避免火灾的主要途径。其次,我们还需要安装一些自动灭火装置。比如自动喷水灭火系统等。其次,一些放置货物的仓库需要设计防火区域。特别是大型商业建筑仓库的防火区域,需要通过严格的设计后达到有效隔离火灾的目的。结论总体发展来看,随着我国大型企业商业建筑工程数量的不断增加,消防安全问题逐渐成为社会人们更加关注的焦点,因此有必要对大型商业综合体进行科学管理、有针对性的设计,如疏散和防火,以利于保护客户的生命财产安全。近年来,我国政府在大型商业综合体消防安全方面做了大量的渗漏检测和修复工作,但也存在相应的问题。因此,在大型商业建筑设计阶段,在紧密结合建筑内部特点的基础上,对建筑的消防安全进行了深入探讨,以达到良好的消防安全环境。" + # } + log = Logging() + message_json = json.loads(request.data.decode()) + start1_time = time.time() + class_res = json.loads(requests.post('http://192.168.31.145:50003/roformer', data=json.dumps(message_json)).text)[ + 'label_num'] + + log.log(class_res) + end1_time = time.time() + log.log('预测类别花费:{}s'.format(end1_time - start1_time)) + + # 查出的相似文档,以字典的形式进行返回,{doc_id: 与送检文档的相似度得分} + start2_time = time.time() + sim_paper_id_dict = search_sim_paper(message_json, class_res, mysql, log) + end2_time = time.time() + log.log('寻找相似文章花费时间:{}s'.format(end2_time - start2_time)) + log.log(sim_paper_id_dict) + log.log('=' * 100) + + return json.dumps(sim_paper_id_dict) + +# if __name__ == '__main__': +# app_all_flask.run(host='0.0.0.0', port=50004, debug=False) diff --git a/check_version_1_0/SearchSimPaper.py b/check_version_1_0/SearchSimPaper.py new file mode 100644 index 0000000..ade3388 --- /dev/null +++ b/check_version_1_0/SearchSimPaper.py @@ -0,0 +1,254 @@ +# -*- coding = utf-8 -*- +# @Time: 18:01 +# @Author:ZYP +# @File:SearchSimPaper.py +# @mail:zypsunshine1@gmail.com +# @Software: PyCharm +import gc +import time + +# ========================================================================================= +# 查找相似文档 +# · 文档之间关键词进行取交集 +# · 再对选取出的文档与送检文档进行关键词之间的相似度计算 +# · 最终选出最相似的文档,进行排序返回 +# ========================================================================================= + +import math +import numpy as np +from collections import defaultdict +from pymysql.converters import escape_string +from sklearn.metrics.pairwise import cosine_similarity +from util import cut_text, l2_normal, get_word_vec + + +def load_inverted_table(class_list, mysql, log): + """根据分类结果,将每个类别的倒排表进行聚合,返回一个几个类别的字典、几个类别库中总论文数量""" + # 记录总的倒排表 {word:[doc_id1,doc_id2,doc_id3, ...]} + total_inverted_dict1 = {} + # 记录每个类别的论文数量的和 + total_nums1 = 0 + + for label_num in class_list: + conn, cursor = mysql.open() + select_sql = """ + select word, paper_doc_id from word_map_paper_{}; + """.format(str(label_num)) + + s_time1 = time.time() + cursor.execute(select_sql) + for word, paper_doc_id in cursor.fetchall(): + if word not in total_inverted_dict1.keys(): + total_inverted_dict1[word] = paper_doc_id + else: + # total_inverted_dict1[word] = ','.join( + # set(total_inverted_dict1[word].split(',') + paper_doc_id.split(','))) + total_inverted_dict1[word] = total_inverted_dict1[word] + ',' + paper_doc_id + + e_time1 = time.time() + log.log('查找{}类倒排表花费的时间:{}s'.format(str(label_num), e_time1 - s_time1)) + + s_time2 = time.time() + select_paper_num_sql = """ + select count_number from count_map where label_num={}; + """.format(str(label_num)) + + cursor.execute(select_paper_num_sql) + + for nums in cursor.fetchall(): + total_nums1 += int(nums[0]) + + e_time2 = time.time() + log.log('查找{}类别下数据量花费:{}s'.format(str(label_num), e_time2 - s_time2)) + + mysql.close(cursor, conn) + + return total_inverted_dict1, total_nums1 + + +def select_sim_doc_message(sim_doc1, mysql): + """ + 通过相似的 doc_id 在库中查找相关的信息,然后计算每个 doc_id 的均值文档向量,以字典形式返回 {文档号:均值文档向量....} + :param sim_doc1: 相似文档的列表,[doc_id1, doc_id2, ...] + :return: 返回{doc_id:(doc_avg_vec, doc_path)} + """ + all_paper_vec_dict = {} + conn, cursor = mysql.open() + for doc_id in sim_doc1: + select_sql = """ + select tb1.doc_id, tb1.title, tb1.abst_zh, tb2.vsm, tb1.content from + ( + (select doc_id, title, abst_zh, content from main_table_paper_detail_message) tb1 + left join + (select doc_id, vsm from id_keywords_weights) tb2 + on + tb1.doc_id=tb2.doc_id + )where tb1.doc_id="{}"; + """.format( + escape_string(doc_id)) + + cursor.execute(select_sql) + + sim_doc_id, sim_title, sim_abst, sim_vsm, sim_content_path = cursor.fetchone() + sim_vsm_dict = {weight.split('@#$@')[0]: float(weight.split('@#$@')[1]) for weight in sim_vsm.split('&*^%')} + vector_paper = [] + value_sum = 0.0 + for word, weight in sim_vsm_dict.items(): + if word in sim_title: + value = 0.5 * weight + elif word in sim_abst: + value = 0.3 * weight + else: + value = 0.2 * weight + + word_vec = get_word_vec(word) + if isinstance(word_vec, int): + continue + vector_paper.append(word_vec * value) + value_sum += value + + del sim_vsm_dict + gc.collect() + + # 求一篇文档的关键词的向量均值 + # avg_vector = np.array(np.sum(np.array(vector_paper, dtype=np.float32), axis=0) / len(vector_paper)) + avg_vector = np.array(np.sum(np.array(vector_paper, dtype=np.float32), axis=0) / value_sum) + all_paper_vec_dict[doc_id] = (avg_vector, sim_content_path) + + mysql.close(cursor, conn) + + return all_paper_vec_dict + + +def submit_paper_avg_vec(paper_dict1, tf_weight_dict): + """根据送检的文档的 tf 值,计算这篇文档的均值向量,以 numpy 数组形式返回""" + vector_paper = [] + value_sum = 0.0 + for word, weight in tf_weight_dict.items(): + if word in paper_dict1['title']: + value = 0.5 * weight + elif word in paper_dict1['abst_zh']: + value = 0.3 * weight + else: + value = 0.2 * weight + + word_vec = get_word_vec(word) + if isinstance(word_vec, int): + continue + + vector_paper.append(word_vec * value) + value_sum += value + + # avg_vector = np.array(np.sum(np.array(vector_paper, dtype=np.float32), axis=0) / len(vector_paper)) + avg_vector = np.array(np.sum(np.array(vector_paper, dtype=np.float32), axis=0) / value_sum) + + return avg_vector + + +def compare_sim_in_papers(check_vector, sim_message, top=40): + """ + 计算文档间的相似度,使用的是余弦相似度 + :param check_vector: 送检文章的文本向量 + :param sim_message: 待检测的 50 篇相似文档,以字典形式存储 + :param top: 设置返回最相似的 N 篇文档 + :return: 返回相似文档的字典 形式:{doc_id:(相似得分, 文档路径)} + """ + sim_res_dict = {} + for doc_id, (vector, content_path) in sim_message.items(): + # sim_res_dict[doc_id] = cosine_similarity([scalar(check_vector), scalar(vector)])[0][1] + sim_res_dict[doc_id] = (str(cosine_similarity([check_vector, vector])[0][1]), content_path) + _ = sorted(sim_res_dict.items(), key=lambda x: float(x[1][0]), reverse=True) + return {key: value for key, value in _[:top]} + + +def search_sim_paper(paper_dict, class_list, mysql, log, top=100): + """ + 根据送检论文的字典,在库中进行相似文档的查询,最后返回最相似的 top 文章,用于逐句查重。 + :param paper_dict: 处理好的格式化送检论文 + :param class_list: 模型预测送检论文的类别 id 的列表 + :param top: 返回前 top 个文档 + :return: 返回相似文档的字典 形式:{doc_id:(相似得分, 文档路径)} + """ + all_str = paper_dict['title'] + '。' + paper_dict['abst_zh'] + '。' + paper_dict['content'] + # 合并倒排表,并统计 论文总量 total_inverted_dict:总的倒排表 + s0 = time.time() + total_inverted_dict, total_nums = load_inverted_table(class_list, mysql, log) + e0 = time.time() + log.log('查询倒排表花费时间为:{}s'.format(e0 - s0)) + + s1 = time.time() + # 计算送检文档的词频字典{word1:fre1, word2:fre2, ...} + word_fre_dict = cut_text(all_str, tokenizer='jieba') + e1 = time.time() + log.log('切词时间为:{}s'.format(e1 - s1)) + + s2 = time.time() + # 计算送检文档所有词语的 tf-idf 值 + tf_idf_dict = {} + for word, freq in word_fre_dict.items(): + if freq <= 2: + continue + tf = freq / sum(word_fre_dict.values()) + if word in total_inverted_dict.keys(): + idf = math.log(total_nums / (len(set(total_inverted_dict[word].split(','))) + 1)) + else: + idf = math.log(total_nums / 1) + + tf_idf = tf * idf + tf_idf_dict[word] = tf_idf + e2 = time.time() + log.log('计算送检文档关键词的TF-idf值花费的时间为:{}s'.format(e2 - s2)) + + s3 = time.time() + # 前 15 的单词、权重 + tf_dict = l2_normal(tf_idf_dict) + e3 = time.time() + log.log('权重正则化花费的时间为:{}s'.format(e3 - s3)) + + s4 = time.time() + # 统计交集的 + count_words_num = defaultdict(int) + for word, weight in tf_dict.items(): + if word in total_inverted_dict.keys(): + for doc_id in set(total_inverted_dict[word].split(',')): + count_words_num[doc_id] += 1 + else: + continue + e4 = time.time() + log.log('统计doc_id交集花费的时间为:{}s'.format(e4 - s4)) + + # 排序 + count_word_num = {i: j for i, j in sorted(count_words_num.items(), key=lambda x: x[1], reverse=True)} + + # 查找前 200 篇相似的文档 + sim_doc = list(count_word_num.keys())[:200] + + # 计算这 200 篇文档的 文档均值向量 + s_time1 = time.time() + sim_paper_vec_dict = select_sim_doc_message(sim_doc, mysql) + e_time1 = time.time() + log.log('计算200篇均值向量所花费的时间为:{}s'.format(e_time1 - s_time1)) + + # 计算送检文档的 文档均值向量 + s_time2 = time.time() + submit_vec = submit_paper_avg_vec(paper_dict, tf_dict) + e_time2 = time.time() + log.log('计算送检文档的均值向量所花费的时间为:{}s'.format(e_time2 - s_time2)) + + # 计算送检文档 和 查出来的文档的相似度 并排序, 取 top 10 文章用作整篇查重 + s_time3 = time.time() + sim_paper_dict = compare_sim_in_papers(submit_vec, sim_paper_vec_dict, top=top) + e_time3 = time.time() + log.log('计算送检文档和查出的文档的相似度(并排序)所花费的时间为:{}s'.format(e_time3 - s_time3)) + + del total_inverted_dict + del total_nums + del submit_vec + del sim_paper_vec_dict + del count_word_num + del sim_doc + del word_fre_dict + + gc.collect() + + return sim_paper_dict diff --git a/check_version_1_0/demo01_multiprocessimg.py b/check_version_1_0/demo01_multiprocessimg.py new file mode 100644 index 0000000..891c456 --- /dev/null +++ b/check_version_1_0/demo01_multiprocessimg.py @@ -0,0 +1,85 @@ +# -*- coding:utf-8 -*- +# @Time: 2023/8/29 18:58 +# @Author:ZYP +# @File:demo01_multiprocessimg.py +# @mail:zypsunshine1@gmail.com +# @Software: PyCharm +import json +import multiprocessing +import os +import time +import uuid +import signal +from util import Logging + +import redis +import requests + +from SearchSimPaper import search_sim_paper +from mysql_collect import mysql + +pool = redis.ConnectionPool(host='192.168.31.145', port=63179, max_connections=50, password='zhicheng123*', db=8) +redis_ = redis.Redis(connection_pool=pool, decode_responses=True) + +db_key_query = 'query' + +log = Logging() + + +def check_main_func(uuid_): + while True: + if redis_.llen(db_key_query) == 0: + continue + while True: + ss = redis_.rpop(db_key_query) + if ss is None: + time.sleep(2) + else: + break + + paper_data = json.loads(ss.decode()) + id_ = paper_data["id"] + message_dict = paper_data["paper"] + class_res = \ + json.loads(requests.post('http://192.168.31.145:50003/roformer', data=json.dumps(message_dict)).text)[ + 'label_num'] + # class_res = [117, 36, 81] + + sim_paper_id_dict = search_sim_paper(message_dict, class_res, mysql, log) + redis_.set(id_, json.dumps(sim_paper_id_dict)) + + pid = redis_.hget('process_pid', uuid_) + log.log("这个进程的 uuid 为:", uuid_) + redis_.hdel("process_pid", uuid_) + os.kill(int(pid), signal.SIGTERM) + break + + +# def set_process(): +# name = str(uuid.uuid1()) +# process = multiprocessing.Process(target=check_main_func, args=(), name=name) +# process.start() +# process.join() +# return name, process + + +if __name__ == '__main__': + # while redis_.llen('process_num') < 4: + # name, process = set_process() + # redis_.lpush('process_num', name) + # process.is_alive() + + # pool = multiprocessing.Pool(processes=4) + # while True: + # if redis_.llen('process_num') < 4: + # redis_.lpush('process_num', '1') + # pool.apply_async(check_main_func, args=()) + + # pool = multiprocessing.Pool(processes=4) + while True: + if redis_.hlen('process_pid') < 4: + uuid_ = str(uuid.uuid1()) + process = multiprocessing.Process(target=check_main_func, args=(uuid_,)) + process.start() + process_id = process.pid + redis_.hset('process_pid', uuid_, str(process_id)) diff --git a/check_version_1_0/demo01_test_redis.py b/check_version_1_0/demo01_test_redis.py new file mode 100644 index 0000000..4647360 --- /dev/null +++ b/check_version_1_0/demo01_test_redis.py @@ -0,0 +1,110 @@ +# -*- coding:utf-8 -*- +# @Time: 2023/8/28 15:03 +# @Author:ZYP +# @File:demo01_test_redis.py +# @mail:zypsunshine1@gmail.com +# # @Software: PyCharm +import time + +import flask +import redis +import uuid +import json +import requests +# from util import Logging +# from threading import Thread +# from mysql_collect import mysql +# from SearchSimPaper import search_sim_paper +# import jieba +from flask import request + +# import multiprocessing + +app_check = flask.Flask(__name__) +pool = redis.ConnectionPool(host='192.168.31.145', port=63179, max_connections=50, password='zhicheng123*', db=8) +redis_ = redis.Redis(connection_pool=pool, decode_responses=True) + +# pool1 = redis.ConnectionPool(host='192.168.31.145', port=63179, max_connections=50, password='zhicheng123*', db=11) +# redis_1 = redis.Redis(connection_pool=pool1, decode_responses=True) + +# jieba.initialize() + +db_key_query = 'query' + + +# db_key_result = 'result' + +# log = Logging() + + +# def check_main_func(): +# while True: +# if redis_.llen(db_key_query) == 0: +# continue +# while True: +# ss = redis_.rpop(db_key_query) +# if ss is None: +# time.sleep(2) +# else: +# break +# +# paper_data = json.loads(ss.decode()) +# id_ = paper_data["id"] +# message_dict = paper_data["paper"] +# class_res = \ +# json.loads(requests.post('http://192.168.31.145:50003/roformer', data=json.dumps(message_dict)).text)[ +# 'label_num'] +# +# sim_paper_id_dict = search_sim_paper(message_dict, class_res, mysql, log) +# redis_.set(id_, json.dumps(sim_paper_id_dict)) + + +@app_check.route("/check", methods=["POST"]) +def handle_query(): + s = time.time() + message_dict = json.loads(request.data.decode()) + uuid_request = str(message_dict['uuid']) + id_ = str(uuid.uuid1()) # 为query生成唯一标识 + d = {'id': id_, 'paper': message_dict} # 绑定文本和query id + redis_.rpush(db_key_query, json.dumps(d)) + while True: + result = redis_.get(id_) + if result is not None: + redis_.delete(id_) + result_text = {'uuid': uuid_request, 'data': result.decode('UTF-8')} + # result_text = json.loads(result.decode('UTF-8')) + break + e = time.time() + print('{} 花费了{} s 的时间'.format(uuid_request, (e - s))) + + redis_.lpush('query_recall', json.dumps(result_text)) + + return uuid_request # 返回结果 + + +# # return '1' + + +if __name__ == "__main__": + # for i in range(2): + # t = Thread(target=check_main_func, args=()) + # t.start() + # processes = [] + # + # # 创建并启动多个进程 + # for i in range(2): + # process = multiprocessing.Process(target=check_main_func, args=()) + # processes.append(process) + # process.start() + + app_check.run(debug=False, host='0.0.0.0', port=50004) + + # res = redis_.rpop(db_key_query) + # print(res) + + # id_ = "51bc72dc-464e-11ee-baf3-45147420c4fb" + # res = redis_.get(id_) + # if res is not None: + # redis_.delete(id_) + # result_text = {'code': "200", 'data': res.decode('UTF-8')} + # print(result_text) diff --git a/check_version_1_0/fasttext/fasttext_api.py b/check_version_1_0/fasttext/fasttext_api.py new file mode 100644 index 0000000..52a4321 --- /dev/null +++ b/check_version_1_0/fasttext/fasttext_api.py @@ -0,0 +1,35 @@ +# -*- coding:utf-8 -*- +# @Time: 2023/8/22 14:44 +# @Author:ZYP +# @File:fasttext_api.py +# @mail:zypsunshine1@gmail.com +# @Software: PyCharm +import json + +import numpy as np +from gensim.models.keyedvectors import KeyedVectors +import time +from flask import Flask, request + +app_fasttext = Flask(__name__) + +fasttext_path = '/home/zc-nlp-zyp/work_file/ssd_data/public_data/fasttext_model/fasttext.vector' +model_fasttext = KeyedVectors.load_word2vec_format(fasttext_path, binary=True) + + +@app_fasttext.route('/fasttext', methods=['POST']) +def get_word2vec(): + word_dict = json.loads(request.data.decode()) + try: + vec = model_fasttext.get_vector(word_dict["word"]) + str_vec = ','.join([str(i) for i in vec]) + # vec1 = np.array([float(j) for j in str_vec.split(',')], dtype=np.float64) + vec_dict = {'vec': str_vec} + return json.dumps(vec_dict) + except: + return 'error_fasttext' + + +# if __name__ == '__main__': +# app.run(host='0.0.0.0', port=50002, debug=False) + diff --git a/check_version_1_0/fasttext/fasttext_config.py b/check_version_1_0/fasttext/fasttext_config.py new file mode 100644 index 0000000..07c3101 --- /dev/null +++ b/check_version_1_0/fasttext/fasttext_config.py @@ -0,0 +1,25 @@ +# -*- coding:utf-8 -*- +# @Time: 2023/8/22 15:30 +# @Author:ZYP +# @File:fasttext_config.py +# @mail:zypsunshine1@gmail.com +# @Software: PyCharm +import logging +import logging.handlers +import os +import gevent.monkey + +gevent.monkey.patch_all() + +bind = '0.0.0.0:50002' # 绑定的ip已经端口号 +chdir = '/home/zc-nlp-zyp/work_file/ssd_data/program/check_paper/check1/change_demo/fasttext' # gunicorn要切换到的目的工作目录 +timeout = 60 # 超时 +worker_class = 'gevent' # 使用gevent模式,还可以使用sync 模式,默认的是sync模式 +workers = 4 # multiprocessing.cpu_count() * 2 + 1 # 启动的进程数 +threads = 4 +loglevel = "info" # 日志级别,这个日志级别指的是错误日志的级别,而访问日志的级别无法设置 +access_log_format = '%(t)s %(p)s %(h)s "%(r)s" %(s)s %(L)s %(b)s %(f)s" "%(a)s"' # 设置gunicorn访问日志格式,错误日志无法设置 +pidfile = "/home/zc-nlp-zyp/work_file/ssd_data/program/check_paper/check1/change_demo/fasttext/fasttext_log/gunicorn.pid" +accesslog = "/home/zc-nlp-zyp/work_file/ssd_data/program/check_paper/check1/change_demo/fasttext/fasttext_log/access.log" +errorlog = "/home/zc-nlp-zyp/work_file/ssd_data/program/check_paper/check1/change_demo/fasttext/fasttext_log/error.log" +daemon = True diff --git a/check_version_1_0/flask_config.py b/check_version_1_0/flask_config.py new file mode 100644 index 0000000..8f1ba14 --- /dev/null +++ b/check_version_1_0/flask_config.py @@ -0,0 +1,27 @@ +# -*- coding:utf-8 -*- +# @Time: 2023/8/21 14:36 +# @Author:ZYP +# @File:flask_config.py +# @mail:zypsunshine1@gmail.com +# @Software: PyCharm +import logging +import logging.handlers +import os +import multiprocessing +import gevent.monkey + +gevent.monkey.patch_all() + +bind = '0.0.0.0:50004' # 绑定的ip已经端口号 +chdir = '/home/zc-nlp-zyp/work_file/ssd_data/program/check_paper/check1/change_demo' # gunicorn要切换到的目的工作目录 +timeout = 200 # 超时 +worker_class = 'gevent' # 使用gevent模式,还可以使用sync 模式,默认的是sync模式 +workers = 5 # multiprocessing.cpu_count() * 2 + 1 # 启动的进程数 +threads = 1 +loglevel = "info" # 日志级别,这个日志级别指的是错误日志的级别,而访问日志的级别无法设置 +access_log_format = '%(t)s %(p)s %(h)s "%(r)s" %(s)s %(L)s %(b)s %(f)s" "%(a)s"' # 设置gunicorn访问日志格式,错误日志无法设置 +pidfile = "/home/zc-nlp-zyp/work_file/ssd_data/program/check_paper/check1/change_demo/gunicornLogs/gunicorn.pid" +accesslog = "/home/zc-nlp-zyp/work_file/ssd_data/program/check_paper/check1/change_demo/gunicornLogs/access.log" +errorlog = "/home/zc-nlp-zyp/work_file/ssd_data/program/check_paper/check1/change_demo/gunicornLogs/error.log" + +daemon = True diff --git a/check_version_1_0/mysql_collect.py b/check_version_1_0/mysql_collect.py new file mode 100644 index 0000000..b5b4a9d --- /dev/null +++ b/check_version_1_0/mysql_collect.py @@ -0,0 +1,102 @@ +# -*- coding:utf-8 -*- +# @Time: 2023/8/21 18:41 +# @Author:ZYP +# @File:mysql_collect.py +# @mail:zypsunshine1@gmail.com +# @Software: PyCharm +import pymysql +from dbutils.pooled_db import PooledDB + +host = '192.168.31.145' +port = 3306 +user = 'root' +password = '123456' +database = 'zhiwang_db' + + +class MySQLConnectionPool: + + def __init__(self, ): + self.pool = PooledDB( + creator=pymysql, # 使用链接数据库的模块 + mincached=20, # 初始化时,链接池中至少创建的链接,0表示不创建 + maxconnections=200, # 连接池允许的最大连接数,0和None表示不限制连接数 + blocking=True, # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错 + host=host, + port=port, + user=user, + password=password, + database=database + ) + + def open(self): + conn = self.pool.connection() + # self.cursor = self.conn.cursor(cursor=pymysql.cursors.DictCursor) # 表示读取的数据为字典类型 + cursor = conn.cursor() # 表示读取的数据为字典类型 + return conn, cursor + + def close(self, cursor, conn): + cursor.close() + conn.close() + + def select_one(self, sql, *args): + """查询单条数据""" + conn, cursor = self.open() + cursor.execute(sql, args) + result = cursor.fetchone() + self.close(conn, cursor) + return result + + def select_all(self, sql, args): + """查询多条数据""" + conn, cursor = self.open() + cursor.execute(sql, args) + result = cursor.fetchall() + self.close(conn, cursor) + return result + + def insert_one(self, sql, args): + """插入单条数据""" + self.execute(sql, args, isNeed=True) + + def insert_all(self, sql, datas): + """插入多条批量插入""" + conn, cursor = self.open() + try: + cursor.executemany(sql, datas) + conn.commit() + return {'result': True, 'id': int(cursor.lastrowid)} + except Exception as err: + conn.rollback() + return {'result': False, 'err': err} + + def update_one(self, sql, args): + """更新数据""" + self.execute(sql, args, isNeed=True) + + def delete_one(self, sql, *args): + """删除数据""" + self.execute(sql, args, isNeed=True) + + def execute(self, sql, args, isNeed=False): + """ + 执行 + :param isNeed 是否需要回滚 + """ + conn, cursor = self.open() + if isNeed: + try: + cursor.execute(sql, args) + conn.commit() + except: + conn.rollback() + else: + cursor.execute(sql, args) + conn.commit() + self.close(conn, cursor) + + +mysql = MySQLConnectionPool() +# sql_select_all = 'select * from `main_table_paper_detail_message` limit %s;' +# results = mysql.select_all(sql_select_all, (1,)) +# print(results) diff --git a/check_version_1_0/roformer/roformer_api.py b/check_version_1_0/roformer/roformer_api.py new file mode 100644 index 0000000..031f263 --- /dev/null +++ b/check_version_1_0/roformer/roformer_api.py @@ -0,0 +1,141 @@ +# -*- coding = utf-8 -*- +# @Time: 16:41 +# @Author:ZYP +# @File:roformer_api.py +# @mail:zypsunshine1@gmail.com +# @Software: PyCharm + +# ========================================================================================= +# 加载深度学习模型 +# · 加载论文分类模型 +# · 加载 BERT 模型 +# ========================================================================================= + +import json +import os +import numpy as np +from bert4keras.models import build_transformer_model +from keras.layers import Lambda, Dense +from keras.models import Model +from bert4keras.tokenizers import Tokenizer +from bert4keras.backend import K +import tensorflow as tf +from keras.backend import set_session +from flask import Flask, request + +# ========================================================================================================================= +# roformer 模型的参数 +# ========================================================================================================================= +class_nums = 168 +max_len = 512 +roformer_config_path = '/home/zc-nlp-zyp/work_file/ssd_data/program/zhiwang_VSM/class_analysis/max_class_train/model/chinese_roformer-v2-char_L-12_H-768_A-12/bert_config.json' +roformer_ckpt_path = '/home/zc-nlp-zyp/work_file/ssd_data/program/zhiwang_VSM/class_analysis/max_class_train/model/chinese_roformer-v2-char_L-12_H-768_A-12/bert_model.ckpt' +roformer_vocab_path = '/home/zc-nlp-zyp/work_file/ssd_data/program/zhiwang_VSM/class_analysis/max_class_train/model/chinese_roformer-v2-char_L-12_H-768_A-12/vocab.txt' +roformer_model_weights_path = '/home/zc-nlp-zyp/work_file/ssd_data/program/zhiwang_VSM/class_analysis/max_class_train/model/model3/best_model.weights' +label_path = '/home/zc-nlp-zyp/work_file/ssd_data/program/zhiwang_VSM/class_analysis/max_class_train/data/label_threshold.txt' + +tfconfig = tf.ConfigProto() +tfconfig.gpu_options.allow_growth = True +set_session(tf.Session(config=tfconfig)) # 此处不同 +global graph +graph = tf.get_default_graph() +sess = tf.Session(graph=graph) +set_session(sess) + +os.environ["CUDA_VISIBLE_DEVICES"] = "0" + +app_roformer = Flask(__name__) + + +def load_roformer_model(config, ckpt): + """加载训练好的168多标签分类模型""" + roformer = build_transformer_model( + config_path=config, + checkpoint_path=ckpt, + model='roformer_v2', + return_keras_model=False) + output = Lambda(lambda x: x[:, 0])(roformer.model.output) + output = Dense( + units=class_nums, + kernel_initializer=roformer.initializer + )(output) + model1 = Model(roformer.model.input, output) + model1.summary() + return model1 + + +def load_label(label_path1): + """加载label2id、id2label、每个类别的阈值,用于分类""" + with open(label_path1, 'r', encoding='utf-8') as f: + json_dict = json.load(f) + label2id1 = {i: j[0] for i, j in json_dict.items()} + id2label1 = {j[0]: i for i, j in json_dict.items()} + label_threshold1 = np.array([j[1] for i, j in json_dict.items()]) + return label2id1, id2label1, label_threshold1 + + +# 加载label的相关信息 +label2id, id2label, label_threshold = load_label(label_path) +# roformer 模型的分词器 +tokenizer_roformer = Tokenizer(roformer_vocab_path) + +# 加载模型 +model_roformer = load_roformer_model(roformer_config_path, roformer_ckpt_path) +set_session(sess) + +# 加载训练好的权重 +model_roformer.load_weights(roformer_model_weights_path) + + +def encode(text_list1): + """将文本列表进行循环编码""" + sent_token_id1, sent_segment_id1 = [], [] + for index, text in enumerate(text_list1): + if index == 0: + token_id, segment_id = tokenizer_roformer.encode(text) + else: + token_id, segment_id = tokenizer_roformer.encode(text) + token_id = token_id[1:] + segment_id = segment_id[1:] + if (index + 1) % 2 == 0: + segment_id = [1] * len(token_id) + sent_token_id1 += token_id + sent_segment_id1 += segment_id + if len(sent_token_id1) > max_len: + sent_token_id1 = sent_token_id1[:max_len] + sent_segment_id1 = sent_segment_id1[:max_len] + + sent_token_id = np.array([sent_token_id1]) + sent_segment_id = np.array([sent_segment_id1]) + return sent_token_id, sent_segment_id + + +@app_roformer.route('/roformer', methods=['POST']) +def pred_class_num(): + """将分类的预测结果进行返回,返回对应库的下标,同时对送检论文的要求处理成字典形式,包括 title、key_words、abst_zh、content 等""" + try: + target_paper_dict = json.loads(request.data.decode()) + text_list1 = [target_paper_dict['title']] # , target_paper_dict['key_words'] + abst_zh = target_paper_dict['abst_zh'] + + if len(abst_zh.split("。")) <= 10: + text_list1.append(abst_zh) + else: + text_list1.append("。".join(abst_zh.split('。')[:5])) + text_list1.append("。".join(abst_zh.split('。')[-5:])) + + sent_token, segment_ids = encode(text_list1) + + with graph.as_default(): + K.set_session(sess) + y_pred = model_roformer.predict([sent_token, segment_ids]) + + idx = np.where(y_pred[0] > label_threshold, 1, 0) + pred_label_num_dict = {'label_num': [index for index, i in enumerate(idx) if i == 1]} + return json.dumps(pred_label_num_dict) + except: + return 'error_roformer' + + +# if __name__ == '__main__': +# app_roformer.run('0.0.0.0', port=50003, debug=False) diff --git a/check_version_1_0/roformer/roformer_config.py b/check_version_1_0/roformer/roformer_config.py new file mode 100644 index 0000000..9f44e71 --- /dev/null +++ b/check_version_1_0/roformer/roformer_config.py @@ -0,0 +1,26 @@ +# -*- coding:utf-8 -*- +# @Time: 2023/8/22 16:06 +# @Author:ZYP +# @File:roformer_config.py +# @mail:zypsunshine1@gmail.com +# @Software: PyCharm +import logging +import logging.handlers +import os +import multiprocessing +import gevent.monkey + +gevent.monkey.patch_all() + +bind = '0.0.0.0:50003' # 绑定的ip已经端口号 +chdir = '/home/zc-nlp-zyp/work_file/ssd_data/program/check_paper/check1/change_demo/roformer' # gunicorn要切换到的目的工作目录 +timeout = 60 # 超时 +backlog = 2048 +worker_class = 'gevent' # 使用gevent模式,还可以使用sync 模式,默认的是sync模式 +workers = 1 # multiprocessing.cpu_count() * 2 + 1 # 启动的进程数 +loglevel = "info" # 日志级别,这个日志级别指的是错误日志的级别,而访问日志的级别无法设置 +access_log_format = '%(t)s %(p)s %(h)s "%(r)s" %(s)s %(L)s %(b)s %(f)s" "%(a)s"' # 设置gunicorn访问日志格式,错误日志无法设置 +pidfile = "/home/zc-nlp-zyp/work_file/ssd_data/program/check_paper/check1/change_demo/roformer/roformer_log/gunicorn.pid" +accesslog = "/home/zc-nlp-zyp/work_file/ssd_data/program/check_paper/check1/change_demo/roformer/roformer_log/access.log" +errorlog = "/home/zc-nlp-zyp/work_file/ssd_data/program/check_paper/check1/change_demo/roformer/roformer_log/error.log" +daemon = True \ No newline at end of file diff --git a/check_version_1_0/util.py b/check_version_1_0/util.py new file mode 100644 index 0000000..a2478ad --- /dev/null +++ b/check_version_1_0/util.py @@ -0,0 +1,96 @@ +# -*- coding = utf-8 -*- +# @Time: 18:02 +# @Author:ZYP +# @File:util.py +# @mail:zypsunshine1@gmail.com +# @Software: PyCharm +# ========================================================================================= +# 工具类 +# 用于加载停用词、数据库、word2vec、fasttext模型 +# ========================================================================================= +import os +import time +import math +import json +import jieba +import numpy as np +import requests +from collections import defaultdict +from textrank4zh import TextRank4Keyword + +jieba.initialize() + +stop_word_path = '/home/zc-nlp-zyp/work_file/ssd_data/program/check_paper/fasttext_train/data/total_stopwords.txt' + +class Logging: + def __init__(self): + pass + + def log(*args, **kwargs): + format = '%Y/%m/%d-%H:%M:%S' + format_h = '%Y-%m-%d' + value = time.localtime(int(time.time())) + dt = time.strftime(format, value) + dt_log_file = time.strftime(format_h, value) + log_file = 'gunicornLogs/access-%s-%s' % (str(os.getpid()), dt_log_file) + ".log" + if not os.path.exists(log_file): + with open(os.path.join(log_file), 'w', encoding='utf-8') as f: + print(dt, *args, file=f, **kwargs) + else: + with open(os.path.join(log_file), 'a+', encoding='utf-8') as f: + print(dt, *args, file=f, **kwargs) + + +def load_stopwords(path=stop_word_path): + """加载停用词""" + with open(path, 'r', encoding='utf-8') as f: + stop_words = {i.strip() for i in f.readlines()} + return stop_words + + +def cut_text(text_str, tokenizer='jieba'): + """使用相应的分词算法对文章进行分词,然后统计每个单词的词频,按照降序返回相应的字典""" + word_dict = defaultdict(int) + if tokenizer == 'jieba': + all_word_list = jieba.cut(text_str) + for word in all_word_list: + if word not in stop_word: + word_dict[word] += 1 + # elif tokenizer == 'hanlp': + # for i in HanLP.segment(text_str): + # if i.word not in stop_word and i.nature != 'w': + # word_dict[i.word] += 1 + else: + print('您输入的 tokenizer 参数有误!') + + return {k: v for k, v in sorted(word_dict.items(), key=lambda x: x[1], reverse=True)} + + +def l2_normal(tf_idf_dict): + """对计算出来的tf-idf字典进行归一化,归一到(0-1)之间""" + l2_norm = math.sqrt(sum(map(lambda x: x ** 2, tf_idf_dict.values()))) + tf_idf_dict1 = sorted(tf_idf_dict.items(), key=lambda x: x[1] / l2_norm, reverse=True) + tf_idf_dict2 = {key: value / l2_norm for key, value in tf_idf_dict1[:15]} + return tf_idf_dict2 + + +def get_word_vec(word): + """根据相应的词语,使用模型进行提取词语向量,如果不存在词表中返回0,存在词表中返回对应向量""" + vec = requests.post('http://192.168.31.74:50001/word2vec', data=json.dumps({'word': word}), timeout=100) + if len(vec.text) < 100: + vec = requests.post('http://192.168.31.74:50002/fasttext', data=json.dumps({'word': word}), timeout=100) + if len(vec.text) < 100: + vec = 0 + return vec + else: + json_dict = json.loads(vec.text) + res_vec = np.array([float(j) for j in json_dict["vec"].split(',')], dtype=np.float64) + return res_vec + else: + json_dict = json.loads(vec.text) + res_vec = np.array([float(j) for j in json_dict["vec"].split(',')], dtype=np.float64) + return res_vec + + +stop_word = load_stopwords() +tr4w = TextRank4Keyword(stop_words_file=stop_word_path) diff --git a/check_version_1_0/word2vec/word2vec_api.py b/check_version_1_0/word2vec/word2vec_api.py new file mode 100644 index 0000000..408e693 --- /dev/null +++ b/check_version_1_0/word2vec/word2vec_api.py @@ -0,0 +1,34 @@ +# -*- coding:utf-8 -*- +# @Time: 2023/8/22 14:44 +# @Author:ZYP +# @File:word2vec_api.py +# @mail:zypsunshine1@gmail.com +# @Software: PyCharm +import json + +import numpy as np +from gensim.models.keyedvectors import KeyedVectors +import time +from flask import Flask, request + +app_word2vec = Flask(__name__) + +word2vec_path = "/home/zc-nlp-zyp/work_file/ssd_data/public_data/word2vec_model/word2vec.vector" +model_word2vec = KeyedVectors.load_word2vec_format(word2vec_path, binary=True) + + +@app_word2vec.route('/word2vec', methods=['POST']) +def get_word2vec(): + word_dict = json.loads(request.data.decode()) + try: + vec = model_word2vec.get_vector(word_dict["word"]) + str_vec = ','.join([str(i) for i in vec]) + # vec1 = np.array([float(j) for j in str_vec.split(',')], dtype=np.float64) + vec_dict = {'vec': str_vec} + return json.dumps(vec_dict) + except: + return 'error_word2vec' + + +# if __name__ == '__main__': +# app.run(host='0.0.0.0', port=50001, debug=False) diff --git a/check_version_1_0/word2vec/word2vec_config.py b/check_version_1_0/word2vec/word2vec_config.py new file mode 100644 index 0000000..4a8dc72 --- /dev/null +++ b/check_version_1_0/word2vec/word2vec_config.py @@ -0,0 +1,26 @@ +# -*- coding:utf-8 -*- +# @Time: 2023/8/22 15:30 +# @Author:ZYP +# @File:word2vec_config.py +# @mail:zypsunshine1@gmail.com +# @Software: PyCharm +import logging +import logging.handlers +import os +import multiprocessing +import gevent.monkey + +gevent.monkey.patch_all() + +bind = '0.0.0.0:50001' # 绑定的ip已经端口号 +chdir = '/home/zc-nlp-zyp/work_file/ssd_data/program/check_paper/check1/change_demo/word2vec' # gunicorn要切换到的目的工作目录 +timeout = 60 # 超时 +worker_class = 'gevent' # 使用gevent模式,还可以使用sync 模式,默认的是sync模式 +workers = 4 # multiprocessing.cpu_count() * 2 + 1 # 启动的进程数 +threads = 4 +loglevel = "info" # 日志级别,这个日志级别指的是错误日志的级别,而访问日志的级别无法设置 +access_log_format = '%(t)s %(p)s %(h)s "%(r)s" %(s)s %(L)s %(b)s %(f)s" "%(a)s"' # 设置gunicorn访问日志格式,错误日志无法设置 +pidfile = "/home/zc-nlp-zyp/work_file/ssd_data/program/check_paper/check1/change_demo/word2vec/word2vec_log/gunicorn.pid" +accesslog = "/home/zc-nlp-zyp/work_file/ssd_data/program/check_paper/check1/change_demo/word2vec/word2vec_log/access.log" +errorlog = "/home/zc-nlp-zyp/work_file/ssd_data/program/check_paper/check1/change_demo/word2vec/word2vec_log/error.log" +daemon = True