Ver código fonte

Merge branch 'master' of http://192.168.2.103:3000/luojiehua/BIDI_ML_INFO_EXTRACTION

znj 2 meses atrás
pai
commit
bbfc078985

+ 7 - 0
BiddingKG/dl/entityLink/entityLink.py

@@ -574,6 +574,13 @@ def match_enterprise_max_first(sentence):
             else:
                 break
     # print("======",list_match)
+    long_names = ['乌鲁木齐经济技术开发区(乌鲁木齐市头屯河区)市场监督管理局(区知识产权局、区市场监管综合行政执法队)']
+    if len(sentence) > MAX_ENTERPRISE_LEN:
+        for name in long_names: # 规则补充超长实体
+            for it in re.finditer(name, sentence):
+                match_item = {"entity_text": "%s" % (name), "begin_index": it.start(), "end_index": it.end()}
+                list_match.append(match_item)
+
     return list_match
 
 def calibrateEnterprise(list_articles,list_sentences,list_entitys):

+ 7 - 2
BiddingKG/dl/interface/Preprocessing.py

@@ -3372,7 +3372,7 @@ def get_preprocessed_article(articles,cost_time = dict(),useselffool=True):
         article_processed = article_processed.replace('成交工程价款', '成交工程价')  # 2021/12/21 修正为中标价
         article_processed = re.sub('任务(?=编号[::])', '项目',article_processed)  # 2022/08/10 修正为项目编号
         article_processed = article_processed.replace('招标(建设)单位', '招标单位')  #2022/8/10 修正预测不到表达
-        article_processed = re.sub("采购商(?=[^\u4e00-\u9fa5]|名称)", "招标人", article_processed)
+        # article_processed = re.sub("采购商(?=[^\u4e00-\u9fa5]|名称)", "招标人", article_processed) # 20250227注销,避免588296281 03338-7	始兴县人民政府 成交信息:采购商名称: 其实是中标人
         article_processed = re.sub('(招标|采购)人(概况|信息):?[,。]', '采购人信息:', article_processed)  # 2022/8/10统一表达
         article_processed = article_processed.replace('\(%)', '')    # 中标(成交)金额(元)\(%):498888.00, 处理 江西省政府采购网  金额特殊问题
         article_processed = re.sub('金额:?((可填写下浮率?、折扣率?或费率|拟签含税总单价总计|[^万元()\d]{8,20})))?:?', '金额:', article_processed)    # 中标(成交)金额:(可填写下浮率、折扣率或费率):29.3万元  金额特殊问题 例:530377517
@@ -3749,6 +3749,11 @@ def get_preprocessed_entitys(list_sentences,useselffool=True,cost_time=dict()):
                 entity_type = ner_entity[2]
                 entity_text = ner_entity[3]
 
+                if entity_type in ["org", "company"] and re.search('^((特殊)?普通合伙)|^(有限合伙)', sentence_text[end_index_temp:]): # 规则补充合伙关键词
+                    partnership = re.search('^((特殊)?普通合伙)|^(有限合伙)', sentence_text[end_index_temp:]).group(0)
+                    end_index_temp += len(partnership)
+                    entity_text += partnership
+
                 if entity_type == 'location' and re.search('^\w{2,4}[市县]\w{2,15}(中心|监狱|殡仪馆|水利站)$', entity_text) and \
                     re.search('\d[楼层号]', entity_text)==None: # 2024/06/07 修改错误地址实体为角色
                     entity_type = 'org'
@@ -3833,7 +3838,7 @@ def get_preprocessed_entitys(list_sentences,useselffool=True,cost_time=dict()):
 
                     '''下面对公司实体进行清洗'''
                     entity_text = re.sub('\s', '', entity_text)
-                    if re.search('^(\d{4}年)?[\-\d月日份]*\w{2,3}分公司$|^\w{,6}某(部|医院)$', entity_text):  # 删除
+                    if re.search('^(\d{4}年)?[\-\d月日份]*\w{2,3}分公司$|^\w{,6}某(部|医院)$|空间布局$', entity_text):  # 删除
                         # print('公司实体不符合规范:', entity_text)
                         continue
                     elif re.match('xx|XX', entity_text):  # 删除

+ 1 - 1
BiddingKG/dl/interface/extract.py

@@ -488,7 +488,7 @@ def predict(doc_id,text,title="",page_time="",web_source_no='',web_source_name="
 
     # data_res = Preprocessing.union_result(Preprocessing.union_result(codeName, prem),list_punish_dic)[0]
     # data_res = Preprocessing.union_result(Preprocessing.union_result(Preprocessing.union_result(codeName, prem),list_punish_dic), list_channel_dic)[0]
-    version_date = {'version_date': '2025-02-19'}
+    version_date = {'version_date': '2025-03-10'}
     data_res = dict(codeName[0], **prem[0], **channel_dic, **product_attrs[0], **product_attrs[1], **payment_way_dic, **fail_reason, **industry, **district, **candidate_dic, **version_date, **all_moneys, **pb_json)
 
     if original_docchannel == 302:

+ 13 - 1
BiddingKG/dl/interface/getAttributes.py

@@ -4757,7 +4757,6 @@ def update_prem(old_prem, new_prem, in_attachment=False):
                                 for k in set(d2)-set(d): # 把表格提取加的属性补充过来,比如:multi_winner other_winner_dic等
                                     if d2[k]:
                                         d[k] = d2[k]
-
                     for d2 in v['roleList']:
                         if d2 not in tmp_l: # 把新预测有,旧没有的角色添加上去
                             old_prem['Project']['roleList'].append(d2)
@@ -4800,6 +4799,14 @@ def update_prem(old_prem, new_prem, in_attachment=False):
         if multi_tendereeMoney and 'Project' in old_prem and float(old_prem['Project']['tendereeMoney'])!=0: # 表格提取到多标段招标金额,去掉Project包招标金额
             old_prem['Project']['tendereeMoney'] = 0
 
+        tenderee_l = [d2['role_text'] for v in old_prem.values() for d2 in v['roleList'] if d2['role_name']=='tenderee']
+        winner_l = [d2['role_text'] for v in old_prem.values() for d2 in v['roleList'] if d2['role_name']=='win_tenderer']
+        if set(tenderee_l) & set(winner_l): # 删除与中标人冲突的招标人
+            for k in old_prem:
+                old_prem[k]['roleList'] = [d for d in old_prem[k]['roleList'] if
+                                          not(d['role_name'] == 'tenderee' and d['role_text'] in winner_l)]
+                # print('删除与中标人冲突的招标人')
+
     # return old_prem
 
 def confirm_prem(prem, channel_dic, is_deposit_project=False, total_tendereeMoney=0):
@@ -4849,6 +4856,11 @@ def confirm_prem(prem, channel_dic, is_deposit_project=False, total_tendereeMone
                 prem.pop(k)
     elif "Project" in prem:
         prem['Project']['uuid'] = str(uuid.uuid4())
+    if len(prem) == 2:
+        del_k = [k for k,v in prem.items() if v.get('roleList', [])==[] and v.get('tendereeMoney', 0)==0 and v.get('unit_tendereeMoney', 0)==0] # 20250310 删除掉没有角色且招标金额为0 的包
+        for k in del_k:
+            prem.pop(k)
+            # print('删除掉没有角色且招标金额为0 的包', k)
     if is_deposit_project and float(total_tendereeMoney)!=0 and len(prem)==1: #20241107 存款类项目有总投资没招标金额且只有一个标段,把总投资作招标金额
         for k in prem:
             if float(prem[k]['tendereeMoney'])==0:

+ 24 - 5
BiddingKG/dl/interface/predictor.py

@@ -925,6 +925,8 @@ class PREMPredict():
                     values[label] = 0.5
                 elif re.search('现由$', front) and re.search('^作为\d个单位的牵头(单位|公司)?', behind): # 修复 469369884 站源批量预测错误 现由第七合同段保利长大工程有限公司作为6个单位的牵头单位,
                     label = 5
+                elif re.search('(中标|成交)?|结果)?)(人|公告|公示),$|中标人信息:$', front): # 20250227修复中标错误 588005167 现确定贵公司为该项目的中标人,中国二冶集团有限公司,2025年01月26日,
+                    label = 5
             elif re.search('是否中标:是,供应商', front) and label == 5:
                 label = 2
                 values[label] = 0.9
@@ -1475,7 +1477,7 @@ class RoleRulePredictor():
                "(乙|竞得|受让|买受|签约|供货|供应?|合作|承做|承包|承建|承销|承保|承接|承制|承担|承修|承租((包))?|入围|入选|竞买)(候选|投标)?(人|单位|机构|供应商|方|公司|企业|厂商|商|社会资本方?|银行)(:?单位名称|:?名称|盖章)?[::是为]+$" \
                "|(选定单位|指定的中介服务机构|实施主体|中标银行|中标通知书,致|征集结果|选择中介|选择结果|成交对象|勘察人|(,|审计|处置|勘察|设计)服务单位|受托[人方])[::是为]+$" \
                "|((评审结果|名次|排名|中标结果)[::]*第?[一1]名?)[::是为]+$|成交供应商信息[,:]?(序号1)?:?|供应商名称$|竞争性选择申请人名称:$" \
-               "|单一来源(采购)?(供应商|供货商|服务商|方式向)$|((中标|成交)(结果|信息))[::是为]+$|(中标|成交)供应商、(中标|成交)(金额|价格),$" \
+               "|单一来源(采购)?(供应商|供货商|服务商|方式向)$|((中标|成交)(结果|信息))[::是为]+$|(中标|成交)供应商、(中标|成交)(金额|价格),$|合作伙伴名称:$" \
                "|现(公布|宣布|公示)中标单位如下:$|现将中标单位(公布|公示)如下:$|现宣布以下(企业|单位|公司)中标:$|经讨论,决定采用$|第\d+(包件?|标段?)(中标|中选|成交)候选人:$)"  # 承办单位:不作为中标 83914772  |施工 单位不作为中标人 例:386692187
         self.pattern_winTenderer_left_60 = "(?P<winTenderer_left_60>" \
                                            "(,|。|:|^)((中标(投标)?|[拟预]中标|中选|中价|中签|成交)(人|单位|机构|中介(服务)?机构|供应商|客户|方|公司|企业|厂商|商家?|社会资本方?|银行)|(中标候选人)?第?[一1]名|第[一1](中标|中选|成交)?候选人|服务机构)" \
@@ -1528,7 +1530,7 @@ class RoleRulePredictor():
 
         self.SET_NOT_TENDERER = set(["人民政府","人民法院","中华人民共和国","人民检察院","评标委员会","中国政府","中国海关","中华人民共和国政府"])
         
-        self.pattern_money_tenderee = re.compile("投?标?最高限价|采购计划金额|项目预算|招标金额|采购金额|项目金额|投资估算|采购(单位|人)委托价|招标限价|拦标价|预算金额|标底|总计|限额|资金来源,?[为:]+\w{2,4}资金|采购成本价|总费用约?为|(招标|采购)总?(规模|额度|资金)|资金来源")  # |建安费用 不作为招标金额
+        self.pattern_money_tenderee = re.compile("投?标?最高限价|采购计划金额|项目预算|招标金额|采购金额|项目金额|投资估算|采购(单位|人)委托价|招标限价|拦标价|预算金额|标底|总计|限额|资金来源,?[为:]+\w{2,4}资金|采购成本价|总费用约?为|(招标|采购)总?(规模|额度|资金)|资金来源|合同价暂定")  # |建安费用 不作为招标金额
         self.pattern_money_tenderer = re.compile("((合同|成交|中标|应付款|交易|投标|验收|订单)[)\)]?(综合)?(总?金额|结果|[单报总]?价))|标的基本情况|承包价|报酬(含税):|经评审的价格|报价不?含税")  # 单写 总价 不能作为中标金额,很多表格有单价、总价
         self.pattern_money_tenderer_whole = re.compile("(以金额.*中标)|中标供应商.*单价|以.*元(报价)?(中标|中选|成交)")
         self.pattern_money_other = re.compile("代理费|服务费")
@@ -1905,6 +1907,8 @@ class RoleRulePredictor():
                                     front_text = _span[0][re.search(self.pattern_money_tenderer, _span[0]).end():]
                                     if re.search('\d[万亿]?元|元)?:?\d', front_text):  # 当前金额与关键词中间有金额的过滤掉
                                         break
+                                    elif re.search('合同价暂定为?$', _span[0]): # 20250310 修复 598504921 合同价暂定 为招标金额
+                                        break
                                     if re.search(self.pattern_money_other, _span[0]) is not None:
                                         if re.search(self.pattern_money_tenderer, _span[0]).span()[1] > \
                                                 re.search(self.pattern_money_other, _span[0]).span()[1]:
@@ -2419,7 +2423,7 @@ class RoleGrade():
                 b = entity.wordOffset_begin
                 e = entity.wordOffset_end
                 not_found = 1
-                if re.search('(乙方:甲方:|甲方:乙方:)$', text[max(0, b-span):b]):
+                if re.search('(乙方:甲方:|甲方((买方)?,|)乙方((卖方)?)?:)$', text[max(0, b-span):b]):
                     entity.label = 0 if entity.entity_type == 'org' else 5   # 修复 290777022 乙方:甲方: 重庆机场集团有限公司 错分为中标
                     entity.values[entity.label] = 0.55
                     continue
@@ -3724,6 +3728,10 @@ class ProductAttributesPredictor():
             for link in product_link:  # 预防最后一列总价为所有产品总价,列补全后所有产品总价一样情况
                 if 'total_price' in link:
                     link['total_price'] = ""
+        if len(demand_link) > 2 and demand_link[0].get('budget', '') != '' and len(set([d.get('budget', '') for d in demand_link])) == 1: # 20250310 去掉多项目共用招标金额 例:598019007
+            for d in demand_link:
+                if 'budget' in d:
+                    d['budget'] = ""
         if len(unit_price_list)>0 and len(unit_price_list)==len(product_link) and len(set(unit_price_list))/len(unit_price_list)<=0.5:  # 2023/7/18 如果单价重复率高不算总产品价避免错误
             # print('如果单价重复率高不算总产品价避免错误')
             total_product_money = 0
@@ -5885,6 +5893,8 @@ class DistrictPredictor():
         text = re.sub('茂名滨海新区', '茂名市', text)
         text = re.sub('中山([东南西][部区环]|黄圃|南头|东凤|小榄|石岐|翠亨|南朗)', '中山市', text)
         text = re.sub('横州市', '横县', text)  # 例:547363890 修复广西南宁横州 不在地区表问题
+        text = re.sub('广东中山', '广东中山市', text)
+        text = re.sub('朝阳柳城经济开发区', '朝阳市', text)
         ser = re.search('海南(昌江|白沙|乐东|陵水|保亭|琼中)(黎族)?', text)
         if ser and '黎族' not in ser.group(0):
             text = text.replace(ser.group(0), ser.group(0) + '黎族')
@@ -5902,7 +5912,7 @@ class DistrictPredictor():
                 for k, v in it.groupdict().items():
                     if v != None:
                         if it.end() == it.end(k) and re.search('[省市区县州旗盟]$', v) == None and re.search(
-                                '^([东南西北中一二三四五六七八九十大小]?(村|镇|街|路|道|社区)|酒店|宾馆|经济开发区|开发区|新区)',
+                                '^([东南西北中一二三四五六七八九十大小]?(村|镇|街|路|道|社区|巷|坊)|酒店|宾馆|经济开发区|开发区|新区|公园|广场|医院|[大中小]学)',
                                 # 城市不匹配为区的地址 修复 滨州北海经济开发区 北海新区 等提取为北海
                                 text[it.end(k):]) != None:
                             continue
@@ -7827,6 +7837,7 @@ class WebsourceTenderee():
                                                                    'linklist': [],
                                                                    'serviceTime': '',
                                                                    'address': ''})
+
             else:
                 prem[0]['prem']['Project'] = {'code': '',
                                               'tendereeMoney': 0,
@@ -7839,6 +7850,14 @@ class WebsourceTenderee():
                                                    'serviceTime': '',
                                                    'address': ''}
                                               ]}
+            tenderee_l = [d2['role_text'] for v in prem[0]['prem'].values() for d2 in v['roleList'] if
+                          d2['role_name'] == 'tenderee']
+            winner_l = [d2['role_text'] for v in prem[0]['prem'].values() for d2 in v['roleList'] if
+                        d2['role_name'] == 'win_tenderer']
+            if set(tenderee_l) & set(winner_l) and web_ree in tenderee_l:  # 删除与站源招标人冲突的中标人
+                for k in prem[0]['prem']:
+                    prem[0]['prem'][k]['roleList'] = [d for d in prem[0]['prem'][k]['roleList'] if
+                                               not (d['role_name'] == 'win_tenderer' and d['role_text'] in tenderee_l)]
         return prem
 
 def get_header_line(list_item):
@@ -8583,7 +8602,7 @@ class EntityTypeRulePredictor():
         self.pattern_addr_bidopen = '([开评]标|开启|评选|比选|磋商|遴选|寻源|采购|招标|竞价|议价|委托|询比?价|比价|谈判|邀标|邀请|洽谈|约谈|选取|抽取|抽选))?(会议)?地[点址区]([((]网址[))])?[:为]'
         self.pattern_addr_bidsend = '((\w{,4}文件)?(提交|递交)(\w{,4}文件)?|投标)地[点址区]([((]网址[))])?[:为]'
         self.pattern_addr_delivery = '(交货|交付|收货|提货|交接|送货(安装)?|送达|到货|供货|卸货)((期|时间)[及和、])?)?(地[点址区]?|区域)[:为]'
-        self.pattern_addr_project = '(项目|施工|实施|建设|工程|服务|展示|看样|拍卖)(实施|服务|现场)?(地[点址区]|位置|所在地区?)(位于)?[:为]|项目位于|[^\w]所[属在](区域|地区):|存放地[点址]?[:为]' # 银行所属区域:北京市西城区 不作项目地址
+        self.pattern_addr_project = '(项目|施工|实施|建设|工程|服务|展示|看样|拍卖)(实施|服务|现场)?(地[点址区]|位置|所在地区?)(位于)?[:为]|项目位于|[^\w]所[属在](区域|地区?):|存放地[点址]?[:为]' # 银行所属区域:北京市西城区 不作项目地址
         self.pattern_addr_contact = '(联系|收件人?|邮寄)地[点址区][:为]|行政区:'
         self.pattern_time_planned = '(计划|预计|预期)(招标|采购|发标|发包)时间|招标(公告|文件)(预计|预期|计划)发布时间'
         self.pattern_code_investment = '投资(审批)?项目[编代]码[:为]'