def load_vec_data(db, cameo=""): """ 传入事件cameo号,到cameo号对应的列表中加载所有事件短句向量 :param cameo:(str)事件cameo号 """ # 游标对象 cursor = db.cursor() # 定义好sql语句,%s是字符串的占位符 if cameo and cameo is not None: sql = f"select * from event_vec_table where cameo='{cameo}'" else: sql = "select * from event_vec_table" # 数据向量字典 data = {} try: # 执行sql语句 cursor.execute(sql) # 获取所有结果集 results = cursor.fetchall() for once in results: # 将读取到的字节流转化为ndarray数组 try: numArr = np.array(json.loads(bytes.decode(bytes(once[2], encoding="utf-8"))), dtype=np.float32) except: numArr = np.array(json.loads(bytes.decode(bytes(once[2], encoding="gbk"))), dtype=np.float32) data[once[1]] = numArr except: trace = traceback.format_exc() logger.error(trace) raise trace finally: cursor.close() return data
def get_event_cameo(cameo_model, events: list): """ 传入事件cameo模型和事件列表,判断每个事件的cameo,并添加到事件列表中 :param cameo_model:事件cameo模型 :param events:(list) 事件列表 :return:events(list)事件列表 :raise:TypeError 事件列表类型 """ if not isinstance(events, list): logger.error("用于预测事件cameo的事件列表类型错误!") raise TypeError # 遍历事件列表 with cameo_sess.as_default(): with cameo_sess.graph.as_default(): for event in events: # 使用将主、谓、宾、否定词拼接为事件短句,预测事件cameo short_sentence = "".join([event["subject"], event["negative_word"], event["verb"], event["object"]]) # 使用bert分字器对事件短句进行分字并ids化 token_ids, segment_ids = TOKENIZER.encode(first_text=short_sentence) # 转化为数组,模型预测需要ndarray token_ids, segment_ids = np.array([token_ids]), np.array([segment_ids]) # 获取cameo预测值 [[0.001,0.002,0.005,0.2,0.100,0.51]] event_cameo = cameo_model.predict([token_ids, segment_ids]) # 获取cameo的id [cameo_id] event_cameo = np.argmax(event_cameo, axis=1) event_id = event_cameo[0] # 根据cameo_id获取cameo event["cameo"] = ID2CAMEO[f"{event_id}"] return events
def load_vec_data(cameo: str): """ 传入事件cameo号,到cameo号对应的列表中加载所有事件短句向量 :param cameo:(str)事件cameo号 :return:data(dict){事件id:向量} :raise:TypeError FileNotFoundError """ # 需要读取向量的文件路径 read_file_path = cat_path(pre_config.vec_data_dir, f"{cameo}.npy") data = {} # 判断文件是否存在,不存在则返回空值 if not os.path.exists(read_file_path): return data # 如果字典文件缺失则报错 elif not os.path.exists(pre_config.cameo2id_path): logger.error("cameo映射事件向量的字典文件缺失!") raise FileNotFoundError else: # cameo2id 字典 {cameo:[]} cameo2id = comm.read_cameo2id(pre_config.cameo2id_path) # 读取文件中的向量 x = comm.read_np(read_file_path) for key, value in zip(cameo2id[cameo], x): data[key] = value return data
def evaluate(sentence): """ 传入句子,调用模型对句子中的事件进行抽取,并添加实体信息。 :param sentence: (str)待抽取事件的句子 :return: results(list)事件列表 :raise:TypeError """ if not isinstance(sentence, str) or not sentence: logger.error("待抽取事件的句子格式错误,应该使用字符串格式且不能为空!") raise TypeError # 传入模型和句子进行事件抽取 events = extract_items(sentence, state_model, trigger_model, object_model, subject_model, loc_model, time_model, negative_model) results = [] for event in events: if not event['subject'] and not event['object']: continue else: results.append(event) # 对得到的事件列表进行实体信息补充 results = get_ners_lac(results) return results
def generate_trained_model_path(trained_model_dir: str, trained_model_name: str): """ 传入模型保存文件夹,和训练后模型名称,按照日期生成模型保存文件夹,并生成模型保存路径,返回模型保存路径 :param trained_model_dir: (str)模型保存文件夹 :param trained_model_name: (str)模型名称 :return: trained_model_path(str)模型保存路径 :raise:ValueError 文件夹不存在或者模型命名不以.h5结尾 """ # 判断保存训练后模型的文主文件夹是否存在,不存在则报错 if not os.path.exists(trained_model_dir) or not os.path.isdir( trained_model_dir): logger.error(f"{trained_model_dir} is wrong!") raise ValueError # 模型不以.h5结尾则报错 if not trained_model_name.endswith(".h5"): logger.error(f"{trained_model_name} must end with .h5") raise ValueError # 按照当前时间年月日生成文件夹,构建训练后模型的保存位置 trained_model_dir = cat_path( trained_model_dir, time.strftime('%Y-%m-%d', time.localtime(time.time()))) trained_model_path = cat_path(trained_model_dir, trained_model_name) # 如果文件夹不存在则生成 if not os.path.exists(trained_model_dir): os.mkdir(trained_model_dir) return trained_model_path
def worker(): """ 预测模块,对主队列传入的文本进行处理及事件匹配预测,通过子队列将结果返回 :return: None """ try: from jdqd.a01.event_match.algor.predict.execute import load_match_model, get_events, get_predict_result # 加载事件匹配模型 model = load_match_model() # 获取事件列表 event_list = get_events() except: trac = traceback.format_exc() logger.error(trac) raise trac while True: # 获取数据和子队列 logger.info("从主队列获取信息。。。") content, sample_type, sub_queue = main_queue.get() try: logger.info("开始进行事件识别。。。") content_pred = get_predict_result(model, event_list, content, sample_type) sub_queue.put((True, content_pred)) except: # 通过子队列发送异常信息 trace = traceback.format_exc() sub_queue.put((False, trace)) continue
def vev_delete(): """ 事件向量化接口,从前端接收事件id,将事件从事件cameo字典以及npy文件中删除。 :return: 删除状态 :raise:事件id为空--ValueError """ if request.method == "GET": # 事件id event_id = request.args.get("event_id", type=str, default=None) else: # 事件id event_id = request.form.get("event_id", type=str, default=None) try: # 判断短句是否为空 judge("event_id", event_id) # 删除事件id以及对应的向量 delete_vec.execute_delete(DB, event_id) # 删除向量字典中的向量 del VEC_DATA[event_id] for cameo in CAMEO2ID: if event_id in CAMEO2ID[cameo]: CAMEO2ID[cameo].remove(event_id) return jsonify(status="success", message="success") except: trace = traceback.format_exc() logger.error(trace) jsonify(status="failed", message=str(trace))
def get_abstract(content: str, n=3): """ 传入清洗后的文章内容,分别使用text rank 和mmr方法提取文章摘要,返回摘要语句列表 :param content: (str)清洗后的文本字符串 :return: summary_sentences(list) 摘要句子列表 :raise: TypeError """ if not isinstance(content, str): logger.error("待抽取摘要的内容格式错误!") raise TypeError # 摘要句子列表 summary_sentences = [] # 使用mmr方式抽取的摘要句子列表 mmr_summary_sentences = mmr_subtract(content, n) # 使用text rank抽取的摘要句子列表 text_rank_summary_sentences = text_rank_subtract(content, n) summary_sentences.extend(mmr_summary_sentences) summary_sentences.extend(text_rank_summary_sentences) # 将句子中的空格剔除 summary_sentences = [ once.replace(" ", "") for once in summary_sentences if once ] summary_sentences = list(set(summary_sentences)) return summary_sentences
def model_predict(): """ 模型预测接口。该接口完成了三个主要步骤:构建数据集、模型预测。 1、构建数据集。获取数据库中指定的预测数据,并且对数据集进行转换; 2、模型预测。使用指定的模型及数据集进行预测,预测结果记录到数据库。 返回数据,如:{"status":"success"} """ task_id = request.form.get("task_id") logger.info(f"开始根据模型预测id<{task_id}>数据进行预测") try: # 查询t_event_task表,获取模型任务信息,该方法返回的是EventTask实体 event_task = query_teventtask_by_id(task_id) # 1、构建数据集。获取数据库中指定的预测数据,并且对数据集进行转换; dates, data = combine_data(event_task.tables_name) data = data.values events_set, events_p_oh = get_event(dates, event_task.event_type) # 2、模型预测。使用指定的模型及数据集进行预测,预测结果记录到数据库。 update_task_status(task_id, ModelStatus.PROCESSING.value) # 任务状态修改为运行中 last_date_data_pred = predict_by_model(event_task.model_id, data, dates, events_set, task_id, event_task.sample_start_date, event_task.model_type, event_task.event) predict_task_finish(task_id, last_date_data_pred, ModelStatus.SUCCESS.value) # 任务状态修改为完成/成功 logger.info(f"模型id<{event_task.model_id}>的预测完成") return {"success": True} except Exception as e: logger.error(f"表 id {task_id} 预测发生异常:{traceback.format_exc()}") predict_task_finish(task_id, "", ModelStatus.FAILD.value) # 任务状态修改为失败 return {"success": False, "exception": e} finally: K.clear_session()
def load_cameo_dict(db): """ 传入数据库连接,获取数据库中的向量,获取其中所有的cameo,id用于构造cameo2id字典 :return:data(dict){cameo:[event_id]} """ # 游标对象 cursor = db.cursor() # 定义好sql语句,%s是字符串的占位符 sql = "select * from event_vec_table" # 数据向量字典 data = {} try: # 执行sql语句 cursor.execute(sql) # 获取所有结果集 results = cursor.fetchall() for once in results: event_ids = data.setdefault(once[0], []) event_ids.append(once[1]) except: trace = traceback.format_exc() logger.error(trace) raise trace finally: cursor.close() return data
def read_cameo2id(file_path: str): """ 传入json文件路径,读取文件内容,返回json解析后的数据。 :param file_path: (str)json文件路径 :return: data 读取得到的文章内容 :raise: ValueError 如果不是json文件则报错 """ # 判断文件是否为.json文件 if not os.path.exists(file_path) or os.path.isdir( file_path) or not file_path.endswith(".json"): logger.error(f"{file_path} 文件错误!") raise ValueError # 因为多线程,所有循环读取字典内容 while True: try: with open(file_path, "r", encoding="utf-8") as file: content = file.read() except TypeError: with open(file_path, "r", encoding="gbk") as file: content = file.read() # 读取到内容则跳出循环 if content and content is not None: try: data = json.loads(content) except: continue break return data
def test_loguru(): os.environ['LOGURU_LEVEL'] = "INFO" from loguru import logger logger.debug(f"调试 {datetime.datetime.now()}") logger.info(f"信息提示 {datetime.datetime.now()}") logger.warning(f"警告 ======= {datetime.datetime.now()}") logger.error(f"错误 !!!!!! {datetime.datetime.now()}")
def execute(raw_dir, target_dir): """ 传入原始标注数据文件夹路径和解析后文件存放的路径,按照时间生成json文件名称,将解析好的数据保存到目标文件夹 :param raw_dir: 存放原始标注数据的文件夹 :param target_dir: 存放解析后数据的文件夹 :return: status--解析状态, corpus_num--数据量 """ # 存放所有解析后的数据 all_datas = [] # 语料中的句子数量 all_sentence_num = 0 # 语料中的事件数量 all_event_num = 0 try: # 判断数据路径是否正确 if valid_dir(raw_dir): # 判断目标文件夹路径是否存在,不存在则创建 if not valid_dir(target_dir): os.makedirs(target_dir) file_name = f"{time.strftime('%Y-%m-%d', time.localtime(time.time()))}.json" target_file_path = cat_path(target_dir, file_name) # 获取文件夹下所有文件的名称 file_names = os.listdir(raw_dir) file_names = list( set(file_name.split(".")[0] for file_name in file_names)) # 遍历文件进行解析 for file_name in tqdm(file_names): file_path = os.path.join(raw_dir, file_name) # 判断两个文件是否都同时存在 if valid_file(f"{file_path}.ann") and valid_file( f"{file_path}.txt"): # 解析文件获取事件和文件中的句子以及事件数量 data, sentence_num, event_num = data_process(file_path) all_datas.extend(data) all_sentence_num += sentence_num all_event_num += event_num logger.info(f"总共有句子:{all_sentence_num},总共有事件:{all_event_num}") # 将解析后的数据保存到目标文件 save_json(all_datas, target_file_path) return { "status": "success", "results": { "sentences": all_sentence_num, "events": all_event_num } } else: logger.error(f"存放原始标注数据的文件夹:{raw_dir}没有找到") raise FileNotFoundError except: trace = traceback.format_exc() logger.error(trace) return {"status": "failed", "results": trace}
def judge(name, data): """ 传入数据,判断是否为空 :param name: 数据名称 :param data: 数据 :return: None """ if not data or data is None: logger.error(f"{name} is None!") raise ValueError
def test_mylog(): os.environ['HR_RUN_PROD'] = "y" os.environ['HR_LOG_FILE'] = "/tmp/logger-test.log" os.environ['HR_LOG_FILE_LEVEL'] = "ERROR" os.environ['HR_LOG_CONSOLE'] = "y" from feedwork.utils import logger logger.debug(f"调试 {datetime.datetime.now()}") logger.info(f"信息提示 {datetime.datetime.now()}") logger.warning(f"警告 ======= {datetime.datetime.now()}") logger.error(f"错误 !!!!!! {datetime.datetime.now()}")
def translate_any_2_anyone(article, target="en"): """ 临时用的,将任意语言的文章翻译为英文 :param article: String.文章 :param target: String.可选值有en、zh等 """ url = config.translate_url article_t = "" try: article_detect = detect(article) if article_detect == 'ja' or article_detect == 'zh-cn': article_array = article.split("。") for sentence in article_array: data = { "from": "auto", "to": target, "apikey": config.translate_user_key, "src_text": sentence } cur_time = date_util.sys_date("%Y-%m-%d %H:%M:%S") logger.info(f"-----------翻译句子开始----------- : {cur_time}") res = http_post(data, url) cur_time = date_util.sys_date("%Y-%m-%d %H:%M:%S") logger.info(f"-----------翻译句子结束----------- : {cur_time}") res_dict = json.loads(res) if "tgt_text" in res_dict: content = res_dict['tgt_text'] article_t += content + ". " else: article_array = article.split(".") for sentence in article_array: data = { "from": "auto", "to": target, "apikey": config.translate_user_key, "src_text": sentence } cur_time = date_util.sys_date("%Y-%m-%d %H:%M:%S") logger.info(f"-----------翻译句子开始----------- : {cur_time}") res = http_post(data, url) cur_time = date_util.sys_date("%Y-%m-%d %H:%M:%S") logger.info(f"-----------翻译句子结束----------- : {cur_time}") res_dict = json.loads(res) if "tgt_text" in res_dict: content = res_dict['tgt_text'] article_t += content + ". " return article_t except HTTPError as e: logger.error('翻译时发生的错误:', e) return ''
def coref_(query: str): """ 对传入的英文字符串进行指代消解,并返回消解后的文本 指代消解--翻译--中文 :param query:(str)待消解的英文字符串 :return:spacy_data(str)指代消解后并翻译成中文的字符串 :raise:TypeError """ if not isinstance(query, str) or not query: logger.error("待消解的内容格式错误,应该是字符串格式,且不能为空!") raise TypeError # 消除朝鲜和韩国的指代消歧问题,对两个国家进行指代符替换 # 防止指代消解因朝鲜韩国出现问题,提前将二者替换为NK SK,如果二者同时存在则只替换一个 if "North Korea" in query: query = query.replace("North Korea", "NK") elif "South Korea" in query: query = query.replace("South Korea", "SK") # 指代消解 spacy_data = coref_spacy.coref_data(nlp, query) # 限制字符翻译 temp = '' data = [] for once in nlp(spacy_data).sents: if len(temp) + len(str(once)) < 2000: temp = f"{temp} {str(once)}" else: # 使用免费接口进行翻译,报错则使用收费接口 trans = free_transform_any_2_zh(temp) if type(trans) != str: trans = transform_any_2_zh(temp) data.append(trans) temp = str(once) # 使用免费接口进行翻译,报错则使用收费接口 trans = free_transform_any_2_zh(temp) if type(trans) != str: trans = transform_any_2_zh(temp) data.append(trans) # 将翻译内容拼接为字符串 spacy_data = "".join(data) if "SK" in spacy_data: spacy_data = spacy_data.replace("SKn", "韩国").replace("SK", "韩国") elif "NK" in spacy_data: spacy_data = spacy_data.replace("NKn", "朝鲜").replace("NK", "朝鲜") return spacy_data
def get_data(train_data_path: str, dev_data_path: str, label2id_path: str, id2label_path: str): """ 传入训练集、验证集、标签字典路径,读取json文件内容,训练集、验证集数据以及标签字典。 :param train_data_path:(str)训练集数据路径 :param dev_data_path:(str)验证集数据路径 :param label2id_path:(str)label2id字典路径 :param id2label_path:(str)id2label字典路径 :return:train_data(list)、dev_data(list)、label2id(dict)、id2label(dict) """ if not valid_file(train_data_path): logger.error(f"训练数据{train_data_path} 路径错误!") elif not valid_file(dev_data_path): logger.error(f"验证数据{dev_data_path} 路径错误!") elif not valid_file(label2id_path): logger.error(f"cameo2id文件{label2id_path} 路径错误!") elif not valid_file(id2label_path): logger.error(f"id2cameo文件{id2label_path} 路径错误!") # 加载训练数据集 train_data = read_json(train_data_path) # 加载验证集 dev_data = read_json(dev_data_path) # 加载标签字典 label2id = read_json(label2id_path) id2label = read_json(id2label_path) # 构造模型训练数据集[(sentence, cameo), ] train_data = [(data, label2id[label]) for data, label in list(train_data.items())] # 构造模型验证数据集[(sentence, cameo), ] dev_data = [(data, label2id[label]) for data, label in list(dev_data.items())] return train_data, dev_data, label2id, id2label
def event_match(): """ 事件匹配,从前端获取事件短句、cameo编号、相似度阈值 :return: 匹配结果给前端 :raise:ValueError如果短句为空 """ if request.method == "GET": # 事件短句,由主语、谓语、否定词、宾语组成 short_sentence = request.args.get("short_sentence", type=str, default=None) # 事件cameo号 cameo = request.args.get("cameo", type=str, default=None) # 相似度阈值 threshold = request.args.get("threshold", type=float, default=0.5) else: # 事件短句,由主语、谓语、否定词、宾语组成 short_sentence = request.form.get("short_sentence", type=str, default=None) # 事件cameo号 cameo = request.form.get("cameo", type=str, default=None) # 相似度阈值 threshold = request.form.get("threshold", type=float, default=0.5) # 默认阈值为0.5 if not threshold or threshold is None: threshold = 0.5 try: # 判断短句是否为空 judge("short_sentence", short_sentence) # 短句向量化 main_vec = load_model.generate_vec(TOKENIZER, BERT_MODEL, short_sentence) # 最终的结果 results = [] for once in CAMEO2ID[cameo]: score = load_model.vec_match(main_vec, VEC_DATA[once], MATCH_MODEL) if score >= threshold: results.append({"event_id": once, "score": float(score)}) # 对输出的结果按照降序排序 results.sort(key=lambda x: x["score"], reverse=True) return jsonify(status="success", result=results) except: trace = traceback.format_exc() logger.error(trace) return jsonify(status="failed", result=trace)
def coref_data(nlp, line: str): """ 传入nlp模型和待消解的英文字符串,对英文文本进行指代消解,返回消解后的字符串。 :param nlp: 指代消解模型对象 :param line: (str)待消解的文本 :return: res(str)消解后的文本 """ if not isinstance(line, str): logger.error("The type of content for coreference must be string!") raise TypeError # 调用模型传入待消解的文本 doc = nlp(line) # 调用指代消解方法,得到指代消解后的文本内容 res = doc._.coref_resolved return res
def save_json(content, file_path: str): """ 传入需要保存的数据,将数据转换为json字符串保存到指定路径file_path :param content: 需要保存的数据 :param file_path: (str)指定路径 :return: None 无返回值 :raise: ValueError 如果不是json文件则报错 """ # 判断是否保存为.json if not file_path.endswith(".json"): logger.error(f"{file_path} 需保存为.json文件") raise ValueError # 将列表或者字典处理成json字符串 content = json.dumps(content, ensure_ascii=False, indent=4) with open(file_path, "w", encoding="utf-8") as file: file.write(content)
def load_vec_data(vector_data_dir: str): """ 传入向量数据保存的文件夹,加载所有的向量数据到内存中。 :param vector_data_dir: (str)向量数据保存的文件夹 :return: vec_data(dict)向量数据字典 :raise:ValueError 保存向量的文件夹路径不是文件夹或者不存在 """ if not os.path.exists(vector_data_dir) or os.path.isfile(vector_data_dir): logger.error(f"{vector_data_dir}向量保存文件夹错误!") raise ValueError # 将所有向量加载到内存中 vec_data = {} file_list = os.listdir(vector_data_dir) for file in file_list: vec_data["{}".format(file)] = np.load(cat_path(vector_data_dir, file)) return vec_data
def event_vectorization(): """ 事件向量化接口,从前端接收短句、cameo编号、事件id,将事件向量化保存到文件中。 :return: 保存状态 :raise:事件短句、事件id为空--ValueError """ if request.method == "GET": # 事件短句,由主语、谓语、否定词、宾语组成 short_sentence = request.args.get("short_sentence", type=str, default=None) # 事件cameo号 cameo = request.args.get("cameo", type=str, default=None) # 事件id event_id = request.args.get("event_id", type=str, default=None) else: # 事件短句,由主语、谓语、否定词、宾语组成 short_sentence = request.form.get("short_sentence", type=str, default=None) # 事件cameo号 cameo = request.form.get("cameo", type=str, default=None) # 事件id event_id = request.form.get("event_id", type=str, default=None) try: # 判断短句是否为空 judge("short_sentence", short_sentence) # 判断cameo是否为空 judge("cameo", cameo) # 判断事件id是否为空 judge("event_id", event_id) # 事件短句向量化 main_vec = load_model.generate_vec(TOKENIZER, BERT_MODEL, short_sentence) # 向量保存 save_vec.save_vec_data(DB, cameo, event_id, main_vec) # 加载到向量字典中 VEC_DATA[event_id] = main_vec event_ids = CAMEO2ID.setdefault(cameo, []) event_ids.append(event_id) return jsonify(status="success", message="success") except: trace = traceback.format_exc() logger.error(trace) return jsonify(status="failed", message=str(trace))
def get_bert_tokenizer(dict_path: str): """ 传入字典路径,读取字典内容,并使用字典初始化分字器,返回分字器对象 :param dict_path: (str)字典路径 :return: tokenizer(object)分字器 :raise: ValueError 如果字典文件不存在或者字典文件不是.txt文件 """ if not os.path.exists(dict_path) or os.path.isdir( dict_path) or not dict_path.endswith(".txt"): logger.error(f"{dict_path} bert 字典文件损坏!") raise ValueError # 加载bert字典 token_dict = get_token_dict(dict_path) # 构建tokenizer类 tokenizer = OurTokenizer(token_dict) return tokenizer
def file_list_indir(root_dir, index_mdfile): # root_dir目录下必须存在被检查的索引文件 if not os.path.isfile(os.path.join(root_dir, index_mdfile)): logger.error(f"{index_mdfile} is not real file") return None file_list = [] for cur_root_dir, sub_dirs, filenames in os.walk(root_dir): # for file in glob.glob(f"{root_dir}/*"): for filename in filenames: if filename == index_mdfile: continue cur_file = os.path.join(cur_root_dir, filename) # 每个文件名,都是 root_dir 开头的 file_list.append(os.path.join(cur_root_dir, filename)) logger.info(f"file={filename}") return file_list
def get_ners_lac(events: list): """ 传入事件列表,将事件论元拼接为字符串,使用lac抽取事件中的实体名词,补充到事件列表中 :param events: (list)事件列表 :return: events (list)补充实体成分后的事件字典列表 :raise:TypeError 事件列表类型错误 """ if not isinstance(events, list): logger.error("用于抽取实体的事件列表类型错误!") raise TypeError # 遍历事件列表 for event in events: # 获取事件所有论元,拼接成事件句子 sentence = ''.join([event[i] for i in event.keys() if i != 'state' and i != 'triggerloc_index']) # 使用hanlp对事件句子进行实体识别 words = lac.run(sentence) # 在事件字典中加入namedentity event["namedentity"] = {'organization': [], 'location': [], 'person': []} # 遍历实体识别后的词 for word, ner in zip(words[0], words[1]): # 判断是否为地点实体 if ner == "LOC": if str(word) in event["namedentity"]["location"]: pass else: event["namedentity"]["location"].append(str(word)) # 判断是否为人物实体 elif ner == "PER": if str(word) in event["namedentity"]["person"]: pass else: event["namedentity"]["person"].append(str(word)) # 判断是否为机构实体 elif ner == "ORG": if str(word) in event["namedentity"]["organization"]: pass else: event["namedentity"]["organization"].append(str(word)) return events
def load_data(file_path: str): """ 传入文件路径,按行读取文件内容,去除换行符,返回数据列表 :param file_path: (str)数据保存路径 :return: data(list)数据列表 :raise:ValueError """ if not os.path.exists(file_path) or os.path.isdir(file_path): logger.error(f"{file_path} 文件路径错误!") raise ValueError try: with open(file_path, "r", encoding="utf-8") as f: data = f.readlines() except TypeError: with open(file_path, "r", encoding="gbk") as f: data = f.readlines() # 按行读取样本 data = [once.replace("\n", "") for once in data if once] return data
def reload_model(): """ 从前端接收模型路径,重新加载模型 :return: status 加载状态 """ # 模型路径字典 model_path = {"extract": "", "cameo": "", "state": ""} if request.method == "POST": model_path["extract"] = request.form.get("extract", type=str, default=None) model_path["cameo"] = request.form.get("cameo", type=str, default=None) model_path["state"] = request.form.get("state", type=str, default=None) model_version = request.form.get("version", type=str, default=None) model_id = request.form.get("model_id", type=str, default=None) else: model_path["extract"] = request.args.get("extract", type=str, default=None) model_path["cameo"] = request.args.get("cameo", type=str, default=None) model_path["state"] = request.args.get("state", type=str, default=None) model_version = request.args.get("version", type=str, default=None) model_id = request.args.get("model_id", type=str, default=None) try: logger.info("开始重载模型参数。。。") for model_type in model_path: if model_path[model_type] != None and not model_path[model_type]: if os.path.exists(model_path[model_type]): exec( f"model_path[{model_type}] = cat_path(model_path[{model_type}], {model_type}_model_{model_version}_{model_id}.h5)") exec(f"PredictConfig.event_{model_type}_model_path = model_path[{model_type}]") exec(f"get_{model_type}_model()") else: logger.error(f"{model_type}模型路径:{model_path[model_type]}错误,请重新传入!") raise ValueError logger.info("模型参数重载完成!") return jsonify(status="success") except: trace = traceback.format_exc() logger.error(trace) return jsonify(status="error", message=trace)
def generate_vec(tokenizer, bert_model, sentence: str): """ 传入bert分词器、bert模型对象、待向量化的中文句子,对句子进行编码,然后使用bert进行向量化。 :param tokenizer:分字器 :param bert_model:模型对象 :param sentence:(str)待向量化的句子 :return:x(ndarray)句子向量(768,) :raise: TypeError """ if not isinstance(sentence, str): logger.error("待向量化的句子格式错误,应该使用字符串格式!") raise TypeError # 句子编码, 按照最大长度切分 token_ids, segment_ids = tokenizer.encode(first_text=sentence[:pre_config.maxlen]) with SESS_1.as_default(): with SESS_1.graph.as_default(): # 句子向量 x = bert_model.predict([np.array([token_ids]), np.array([segment_ids])])[0][0] return x
def get_token_dict(dict_path: str): """ 传入bert字典路径,按行读取文件内容,返回字典 :param dict_path: (str)字典文件路径 :return: token_dict(dict)模型字典 """ if not os.path.exists(dict_path) or os.path.isdir( dict_path) or not dict_path.endswith(".txt"): logger.error(f"{dict_path} bert 字典文件损坏!") raise ValueError token_dict = {} # 加载模型对应的字典 with codecs.open(dict_path, 'r', 'utf8') as reader: # 遍历读取文件内容的每一行 for line in reader: token = line.strip() # 将字典的长度作为字符的id token_dict[token] = len(token_dict) return token_dict