extractMetric.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. import psycopg2
  2. from BiddingKG.dl.interface.extract import predict,test
  3. from BiddingKG.dl.common.Utils import getUnifyMoney,timeFormat
  4. from BiddingKG.dl.entityLink.entityLink import jaccard_score
  5. import re
  6. import json
  7. bidway_dict = {'询价': '询价', '竞争性谈判': '竞争性谈判',
  8. '公开比选': '其他', '国内竞争性磋商': '竞争性磋商',
  9. '招标方式:t公开': '公开招标', '竞价': '竞价',
  10. '竞标': '竞价', '电子竞价': '竞价',
  11. '电子书面竞投': '竞价', '单一来源': '单一来源',
  12. '网上竞价': '竞价', '公开招标': '公开招标',
  13. '询比': '询价', '定点采购': '其他',
  14. '招标方式:■公开': '公开招标', '交易其他,付款其他': '其他',
  15. '竞争性评审': '竞争性磋商', '公开招租': '其他', '\\N': '',
  16. '比选': '其他', '比质比价': '其他', '分散采购': '其他',
  17. '内部邀标': '邀请招标', '邀请招标': '邀请招标',
  18. '网上招标': '公开招标', '非定向询价': '询价',
  19. '网络竞价': '竞价', '公开询价': '询价',
  20. '定点采购议价': '其他', '询单': '询价',
  21. '网上挂牌': '其他', '网上直购': '其他',
  22. '定向询价': '询价', '采购方式:公开': '公开招标',
  23. '磋商': '竞争性磋商', '公开招投标': '公开招标',
  24. '招标方式:√公开': '公开招标', '公开选取': '公开招标',
  25. '网上电子投标': '公开招标', '公开竞谈': '竞争性谈判',
  26. '竞争性磋商': '竞争性磋商', '采购方式:邀请': '邀请招标',
  27. '公开竞价': '竞价', '其他': '其他', '公开招募': '其他',
  28. '网上询价': '询价'}
  29. # bidway名称统一规范
  30. def bidway_integrate(bidway):
  31. integrate_name = bidway_dict.get(bidway,"其他")
  32. return integrate_name
  33. class ExtractMetric():
  34. def __init__(self):
  35. self.conn1 = self.getConnection_postgres("iepy")
  36. self.conn2 = self.getConnection_postgres("iepy")
  37. def fitDataByRule(self,data):
  38. symbol_dict = {"(":")",
  39. "(":")",
  40. "[":"]",
  41. "【":"】",
  42. ")":"(",
  43. ")":"(",
  44. "]":"[",
  45. "】":"【"}
  46. leftSymbol_pattern = re.compile("[\((\[【]")
  47. rightSymbol_pattern = re.compile("[\))\]】]")
  48. leftfinds = re.findall(leftSymbol_pattern,data)
  49. rightfinds = re.findall(rightSymbol_pattern,data)
  50. result = data
  51. if len(leftfinds)+len(rightfinds)==0:
  52. return data
  53. elif len(leftfinds)==len(rightfinds):
  54. return data
  55. elif abs(len(leftfinds)-len(rightfinds))==1:
  56. if len(leftfinds)>len(rightfinds):
  57. if symbol_dict.get(data[0]) is not None:
  58. result = data[1:]
  59. else:
  60. #print(symbol_dict.get(leftfinds[0]))
  61. result = data+symbol_dict.get(leftfinds[0])
  62. else:
  63. if symbol_dict.get(data[-1]) is not None:
  64. result = data[:-1]
  65. else:
  66. result = symbol_dict.get(rightfinds[0])+data
  67. return result
  68. def getConnection_postgres(self,db):
  69. # Phase 1: PG 连接走 infra/db(原硬编码 host=192.168.2.103, password=postgres 已移除)
  70. from BiddingKG.dl.infra.db import get_connection
  71. return get_connection(db)
  72. def label2interface(self,list_anno,Htext):
  73. dict_result = {}
  74. dict_anno = {}
  75. for _anno in list_anno:
  76. value = _anno["value"]
  77. _split = value.split("\t")
  78. if _split[0][0]=="T":
  79. _type,_begin,_end = _split[1].split(" ")
  80. dict_anno[_split[0]] = {"id":_split[0],"type":_type,"text":_split[2],"begin":int(_begin),"end":int(_end)}
  81. elif _split[0][0]=="R":
  82. _type,arg1,arg2 = _split[1].split(" ")
  83. dict_anno[_split[0]] = {"id":_split[0],"type":_type,"arg1":arg1.split(":")[1],"arg2":arg2.split(":")[1]}
  84. dict_role = {}
  85. dict_money = {}
  86. dict_person2role = {}
  87. dict_name_freq_score = {}
  88. pattern_score = re.compile("工程|服务|采购|施工|项目|系统|招标|中标|公告|学校|[大中小]学校?|医院|公司|分公司|研究院|政府采购中心|学院|中心校?|办公室|政府|财[政务]局|办事处|委员会|[部总支]队|警卫局|幼儿园|党委|党校|银行|分行|解放军|发电厂|供电局|管理所|供电公司|卷烟厂|机务段|研究[院所]|油厂|调查局|调查中心|出版社|电视台|监狱|水厂|服务站|信用合作联社|信用社|交易所|交易中心|交易中心党校|科学院|测绘所|运输厅|管理处|局|中心|机关|部门?|处|科|厂|集团|图书馆|馆|所|厅|楼|区|酒店|场|基地|矿|餐厅|酒店")
  89. for k,v in dict_anno.items():
  90. if v.get("type") in ["code","product","person_review"]:
  91. if v.get("type") not in dict_result:
  92. dict_result[v.get("type")] = []
  93. dict_result[v.get("type")].append(v.get("text"))
  94. dict_result[v.get("type")] = list(set(dict_result[v.get("type")]))
  95. if v.get("type") in ["name","bidway","moneysource","serviceTime","time_release","time_bidopen","time_bidclose"]:
  96. if v.get("type")=="name":
  97. _name = self.fitDataByRule(v.get("text"))
  98. w = 1 if re.search('(项目|工程|招标|合同|标项|标的|计划|询价|询价单|询价通知书|申购)(名称|标题|主题)[::\s]', _name)!=None else 0.5
  99. if _name not in dict_name_freq_score:
  100. # dict_name_freq_score[_name] = [1,len(re.findall(pattern_score,_name))+len(_name)*0.1]
  101. dict_name_freq_score[_name] = [1, (len(re.findall(pattern_score, _name)) + len(_name) * 0.05)*w]
  102. else:
  103. dict_name_freq_score[_name][0] += 1
  104. max_score = 0
  105. for _k1,_v1 in dict_name_freq_score.items():
  106. if _v1[0]*_v1[1]>max_score:
  107. max_score = _v1[0]*_v1[1]
  108. dict_result[v.get("type")] = _k1
  109. if v.get("type") not in dict_result:
  110. if v.get("type") in ["time_release","time_bidopen","time_bidclose"]:
  111. _t = timeFormat(v.get("text"))
  112. else:
  113. _t = v.get("text")
  114. dict_result[v.get("type")] = _t
  115. if v.get("type")=="bidway":
  116. dict_result[v.get("type")] = bidway_integrate(v.get("text"))
  117. _split = v.get("type").split("_")
  118. if len(_split)>1:
  119. if _split[1]=="tenderee":
  120. dict_role["tenderee"] = {"subject":v.get("text")}
  121. if _split[1]=="agency":
  122. dict_role["agency"] = {"subject":v.get("text")}
  123. if _split[1]=="tenderer":
  124. dict_role["tenderer"] = {"subject":v.get("text")}
  125. if _split[1]=="secondTenderer":
  126. dict_role["secondTenderer"] = {"subject":v.get("text")}
  127. if _split[1]=="thirdTenderer":
  128. dict_role["thirdTenderer"] = {"subject":v.get("text")}
  129. tendereeMoney = 0
  130. for k,v in dict_anno.items():
  131. _split = v.get("type").split("_")
  132. if v.get("type") in ["money_tendereeMoney"]:
  133. _before_text = Htext[max(v["begin"]-10,0):v["begin"]]
  134. if re.search('总投资|投资总额|总预算|总概算|投资规模|投资|工程造价', _before_text):
  135. continue
  136. if re.search("万",_before_text) is not None and re.search("整",_before_text) is None:
  137. _unit = 10000
  138. else:
  139. _unit = 1
  140. tendereeMoney = float(getUnifyMoney(v["text"])*_unit)
  141. if v.get("type") in ["rel_tendereeMoney","rel_tendererMoney"]:
  142. arg1 = v.get("arg1")
  143. arg2 = v.get("arg2")
  144. for _k,_v in dict_role.items():
  145. if _v["subject"]==dict_anno[arg1]["text"]:
  146. _before_text = Htext[max(dict_anno[arg2]["begin"]-10,0):dict_anno[arg2]["begin"]]
  147. if re.search('总投资|投资总额|总预算|总概算|投资规模|投资|工程造价', _before_text):
  148. continue
  149. if re.search("万",_before_text) is not None and re.search("整",_before_text) is None:
  150. _unit = 10000
  151. else:
  152. _unit = 1
  153. _v["money"] = float(getUnifyMoney(dict_anno[arg2]["text"])*_unit)
  154. if v.get("type")=="person_tendereePerson":
  155. if "tenderee" in dict_role:
  156. if "person" not in dict_role["tenderee"]:
  157. dict_role["tenderee"]["person"] = []
  158. dict_role["tenderee"]["person"].append({"person":v["text"]})
  159. if v.get("type")=="person_agencyPerson":
  160. if "agency" in dict_role:
  161. if "person" not in dict_role["agency"]:
  162. dict_role["agency"]["person"] = []
  163. dict_role["agency"]["person"].append({"person":v["text"]})
  164. if v.get("type")=="rel_person":
  165. arg1 = v.get("arg1")
  166. arg2 = v.get("arg2")
  167. for _k,_v in dict_role.items():
  168. if _v["subject"]==dict_anno[arg1]["text"]:
  169. if "person" not in dict_role[_k]:
  170. dict_role[_k]["person"] = []
  171. dict_role[_k]["person"].append({"person":dict_anno[arg2]["text"]})
  172. dict_person2role[dict_anno[arg2]["text"]] = _k
  173. for k,v in dict_anno.items():
  174. if v.get("type")=="rel_phone":
  175. arg1 = v.get("arg1")
  176. arg2 = v.get("arg2")
  177. _person = dict_anno[arg1]["text"]
  178. if _person in dict_person2role:
  179. for item in dict_role[dict_person2role[_person]]["person"]:
  180. if item["person"]==_person:
  181. item["phone"] = dict_anno[arg2]["text"]
  182. roleList = []
  183. for k,v in dict_role.items():
  184. if k=="tenderee":
  185. _role = "tenderee"
  186. if k=="agency":
  187. _role = "agency"
  188. if k=="tenderer":
  189. _role = "win_tenderer"
  190. if k=="secondTenderer":
  191. _role = "second_tenderer"
  192. if k=="thirdTenderer":
  193. _role = "third_tenderer"
  194. list_person = []
  195. set_person = set()
  196. for item in v.get("person",[]):
  197. if item["person"] not in set_person:
  198. list_person.append([item["person"],item.get("phone","")])
  199. set_person.add(item["person"])
  200. roleList.append([_role,v.get("subject","").replace("(","(").replace(")",")"),v.get("money",0),list_person,""])
  201. dict_result["prem"] = {"Project":{"roleList":roleList,"tendereeMoney":tendereeMoney}}
  202. return dict_result
  203. def culExtractMetrics(self):
  204. conn = self.conn1
  205. cursor = conn.cursor()
  206. sql = ' select begin_time,end_time,"user",doc_count from corpus_payroll where end_time<=\'2021-07-25\' order by end_time desc limit 20'
  207. cursor.execute(sql)
  208. list_diff = []
  209. rows_payroll = cursor.fetchall()
  210. for _payroll in rows_payroll:
  211. _begin_time = _payroll[0]
  212. _end_time = _payroll[1]
  213. _user = _payroll[2]
  214. doc_count = _payroll[3]
  215. print(_user,_begin_time,_end_time,doc_count)
  216. _sql = "select document_id,value from brat_bratannotation where document_id in (select human_identifier from corpus_iedocument where edituser='%s' and to_char(edittime,'yyyy-mm-dd')>='%s' and to_char(edittime,'yyyy-mm-dd')<='%s' limit 100) order by document_id"%(_user,_begin_time,_end_time)
  217. cursor.execute(_sql)
  218. rows = cursor.fetchall()
  219. if len(rows)>0:
  220. current_docid = rows[0][0]
  221. _index = -1
  222. list_values = []
  223. while _index<len(rows)-1:
  224. _index += 1
  225. row = rows[_index]
  226. document_id = row[0]
  227. value = row[1]
  228. if document_id!=current_docid:
  229. print(current_docid)
  230. sql = "select text from corpus_iedocument where human_identifier='%s'"%(str(current_docid))
  231. cursor.execute(sql)
  232. content = cursor.fetchall()[0][0]
  233. _inter = self.label2interface(list_values,content)
  234. _inter2 = self.extractFromInterface(content)
  235. if not len(_inter2.get("prem").keys())>1:
  236. _diff = self.getDiff(_inter,_inter2)
  237. list_diff.append(_diff)
  238. _index -= 1
  239. current_docid = document_id
  240. list_values = []
  241. else:
  242. list_values.append({"document_id":document_id,"value":value})
  243. metrics = self.getMetrics(list_diff)
  244. print(metrics)
  245. def extractFromInterface(self,content):
  246. _json = test("",content)
  247. return json.loads(_json)
  248. def getDiff(self,_inter,_inter2):
  249. _dict = {}
  250. for k in ["code","product","person_review"]:
  251. set_k1 = _inter.get(k,set())
  252. set_k2 = _inter2.get(k,set())
  253. _dict["%s_inter"%k] = len(set_k1)
  254. _dict["%s_inter2"%k] = len(set_k2)
  255. _dict["%s_union"%k] = len(set(set_k1)&set(set_k2))
  256. for k in ["name","bidway","moneysource","serviceTime","time_release","time_bidopen","time_bidclose"]:
  257. _k1 = _inter.get(k,"")
  258. _k2 = _inter2.get(k,"")
  259. len_k1 = 0 if _k1=="" else 1
  260. len_k2 = 0 if _k2=="" else 1
  261. if k in ["name","serviceTime"]:
  262. _score = jaccard_score(_k1,_k2)
  263. if len_k1 and len_k2 and _score>0.9:
  264. len_union = 1
  265. else:
  266. len_union = 0
  267. else:
  268. len_union = 1 if _k1==_k2 and len_k1==1 else 0
  269. _dict["%s_inter"%k] = len_k1
  270. _dict["%s_inter2"%k] = len_k2
  271. _dict["%s_union"%k] = len_union
  272. dict_project = {}
  273. for k,v in _inter.get("prem",{}).items():
  274. if float(v.get("tendereeMoney",0))>0:
  275. dict_project["%s_inter"%("tendereeMoney")] = [float(v.get("tendereeMoney"))]
  276. for _role in v.get("roleList",[]):
  277. dict_project["%s_inter"%_role[0]] = [_role[1]]
  278. if _role[0] in ["win_tenderer","second_tenderer","third_tenderer"]:
  279. if float(_role[2])>0:
  280. dict_project["%s_money_inter"%_role[0]] = [float(_role[2])]
  281. for item in _role[3]:
  282. _person = item[0]
  283. _phone = item[1]
  284. if _person=="" or _phone=="":
  285. continue
  286. if "%s_person_inter"%_role[0] not in dict_project:
  287. dict_project["%s_person_inter"%_role[0]] = []
  288. dict_project["%s_person_inter"%_role[0]].append("%s-%s"%(_role[1],_person))
  289. if "person_phone_inter" not in dict_project:
  290. dict_project["person_phone_inter"] = []
  291. dict_project["person_phone_inter"].append("%s-%s"%(_person,_phone))
  292. for k,v in _inter2.get("prem",{}).items():
  293. if float(v.get("tendereeMoney",0))>0:
  294. dict_project["%s_inter2"%("tendereeMoney")] = [float(v.get("tendereeMoney"))]
  295. for _role in v.get("roleList",[]):
  296. dict_project["%s_inter2"%_role.get("role_type")] = [_role.get("role_text")]
  297. if _role.get("role_type") in ["win_tenderer","second_tenderer","third_tenderer"]:
  298. if float(_role.get("role_money").get("money",0))>0:
  299. dict_project["%s_money_inter2"%_role.get("role_type")] = [float(_role.get("role_money").get("money",0))]
  300. for item in _role.get("linklist"):
  301. _person = item[0]
  302. _phone = item[1]
  303. if _person=="" or _phone=="":
  304. continue
  305. if "%s_person_inter2"%_role.get("role_type") not in dict_project:
  306. dict_project["%s_person_inter2"%_role.get("role_type")] = []
  307. dict_project["%s_person_inter2"%_role.get("role_type")].append("%s-%s"%(_role.get("role_text"),_person))
  308. if "person_phone_inter2" not in dict_project:
  309. dict_project["person_phone_inter2"] = []
  310. dict_project["person_phone_inter2"].append("%s-%s"%(_person,_phone))
  311. set_k = set()
  312. for k,v in dict_project.items():
  313. k_split = k.split("_")
  314. base_key = "_".join(k_split[:-1])
  315. if k_split[-1]=="inter":
  316. k2 = "inter2"
  317. else:
  318. k2 = "inter"
  319. if base_key in set_k:
  320. continue
  321. k_other = "%s_%s"%(base_key,k2)
  322. _dict[k] = len(v)
  323. _dict[k_other] = len(dict_project.get(k_other,[]))
  324. if base_key=="tenderee":
  325. _dict["%s_union"%base_key] = 0
  326. if _dict[k]>0 and _dict[k_other]>0:
  327. _score = jaccard_score(dict_project.get(k),dict_project.get(k_other))
  328. if _score>0.9:
  329. _dict["%s_union"%base_key] = 1
  330. else:
  331. #通过规则召回的也算
  332. if dict_project.get("%s_%s"%(base_key,"inter")) is None and dict_project.get("%s_%s"%(base_key,"inter2")) is not None:
  333. _dict[k] = 1
  334. _dict[k_other] = 1
  335. _dict["%s_union"%base_key] = 1
  336. else:
  337. _dict["%s_union"%base_key] = len(set(v)&set(dict_project.get(k_other,[])))
  338. set_k.add(base_key)
  339. print("=========================")
  340. print(_inter)
  341. print("-----")
  342. print(_inter2)
  343. print("|||||")
  344. print(_dict)
  345. return _dict
  346. def getMetrics(self,list_diff):
  347. dict_key_count = {}
  348. # print("all_count:",list_diff)
  349. for _diff in list_diff:
  350. for k,v in _diff.items():
  351. if k not in dict_key_count:
  352. dict_key_count[k] = 0
  353. dict_key_count[k] += v
  354. set_k = set()
  355. for k,v in dict_key_count.items():
  356. k_split = k.split("_")
  357. base_k = "_".join(k_split[:-1])
  358. if base_k in set_k:
  359. continue
  360. set_k.add(base_k)
  361. _count_inter = max(dict_key_count.get("%s_inter"%base_k,-1),1)
  362. _count_inter2 = max(dict_key_count.get("%s_inter2"%base_k,-1),1)
  363. _count_union = dict_key_count.get("%s_union"%base_k,0)
  364. _precision = _count_union/_count_inter2
  365. _recall = _count_union/_count_inter
  366. _f1 = 2*(_precision*_recall)/(_precision+_recall)
  367. print("%s: recall:%.3f,precision:%.3f,f1_score:%.3f"%(base_k,_recall,_precision,_f1))
  368. print(base_k)
  369. print("%.3f"%_f1)
  370. print("%.3f"%_precision)
  371. print("%.3f"%_recall)
  372. if __name__=="__main__":
  373. em = ExtractMetric()
  374. em.culExtractMetrics()