فهرست منبع

字段清洗等方法

zhengkun 8 ماه پیش
والد
کامیت
5124be5b8f
4فایلهای تغییر یافته به همراه318 افزوده شده و 39 حذف شده
  1. 51 1
      clean/c_pcode.go
  2. 29 0
      clean/c_time.go
  3. 175 29
      main.go
  4. 63 9
      prompt/prompt_field.go

+ 51 - 1
clean/c_pcode.go

@@ -1,10 +1,16 @@
 package clean
 
 import (
+	"regexp"
 	"strings"
+	"unicode"
 	"unicode/utf8"
 )
 
+// 编号
+var codeUnConReg *regexp.Regexp = regexp.MustCompile("(null|勘察|包件|测试|设计|设备|项目|标段|工程|监理|范围|分包|月|日|天)")
+var codeUnLenReg *regexp.Regexp = regexp.MustCompile("([\u4e00-\u9fa5]{7,})")
+
 // 清洗项目编号
 func CleanPcode(pcode string, fns []string) string {
 	if pcode == "无" {
@@ -16,7 +22,9 @@ func CleanPcode(pcode string, fns []string) string {
 	if utf8.RuneCountInString(pcode) < 5 {
 		pcode = ""
 	}
-
+	if codeUnConReg.MatchString(pcode) || codeUnLenReg.MatchString(pcode) || !isAlphanumeric(pcode) || isRegTimeDateCode(pcode) {
+		return ""
+	}
 	//校验与附件名字否是一致-舍弃
 	for _, v := range fns {
 		if utf8.RuneCountInString(v) >= utf8.RuneCountInString(pcode) {
@@ -27,3 +35,45 @@ func CleanPcode(pcode string, fns []string) string {
 	}
 	return pcode
 }
+
+// 清洗其他编号
+func CleanOtherCode(ocode string) string {
+	if ocode == "无" || ocode == "" {
+		return ""
+	}
+	ocode = fieldReg1.ReplaceAllString(ocode, "")
+	ocode = pcodeReg1.ReplaceAllString(ocode, "")
+	ocode = pcodeReg2.ReplaceAllString(ocode, "")
+	if utf8.RuneCountInString(ocode) < 5 {
+		return ""
+	}
+	if codeUnConReg.MatchString(ocode) || codeUnLenReg.MatchString(ocode) || !isAlphanumeric(ocode) || isRegTimeDateCode(ocode) {
+		return ""
+	}
+	return ocode
+}
+
+// 是否含字母数字
+func isAlphanumeric(str string) bool {
+	var count int
+	for _, v := range str {
+		if unicode.IsNumber(v) || unicode.IsLetter(v) {
+			count++
+			break
+		}
+	}
+	return count > 0
+}
+
+// 连续数字
+func isRegTimeDateCode(str string) bool {
+	reg := `\d{8}`
+	regx, _ := regexp.Compile(reg)
+	if regx.FindString(str) != "" {
+		return false
+	}
+	if utf8.RuneCountInString(str) == 8 {
+		return true
+	}
+	return false
+}

+ 29 - 0
clean/c_time.go

@@ -12,12 +12,41 @@ import (
 var numReg = regexp.MustCompile("[0-9.]+")
 var symbolReg = regexp.MustCompile("[%%﹪!!]")
 
+var YMD_Reg1 = regexp.MustCompile("(\\d{4}年\\d{1,2}月\\d{1,2}日)")
+var YMD_Reg2 = regexp.MustCompile("(\\d{4}[-]\\d{1,2}[-]\\d{1,2})")
+
+var HMS_Reg1 = regexp.MustCompile("(\\d{1,2}时\\d{1,2}分\\d{1,2}秒)")
+var HMS_Reg2 = regexp.MustCompile("(\\d{1,2}[:]\\d{1,2}[:]\\d{1,2})")
+
+func convertYMD(ymd string) string {
+	if ymd1 := YMD_Reg1.FindString(ymd); ymd1 != "" {
+
+	}
+	return ""
+}
+func convertHMS(hms string) string {
+	if hms1 := YMD_Reg1.FindString(hms); hms1 != "" {
+
+	}
+	return ""
+}
+
 // 清洗时间
 func CleanTime(st string) int64 {
 	if st == "" || st == "无" {
 		return 0
 	}
 	//YYYY-MM-DD HH:MM:SS
+	/*
+		2024-02-28 09:00:00
+		2024年3月4日 08:00:00
+		2024年03月01日08时00分00秒
+		2024年3月8日 17:00:00
+		2024年03月08日09时30分00秒
+	*/
+	st = strings.ReplaceAll(st, ":", ":")
+	ymd, hms := convertYMD(st), convertHMS(st)
+	st = ymd + " " + hms
 	t, _ := time.ParseInLocation(ul.TimeLayout, st, time.Local)
 	return t.Unix()
 }

+ 175 - 29
main.go

@@ -75,38 +75,184 @@ func test() {
 
 func test1() {
 	arr := []string{
-		"下浮率:0.44%",
-		"下浮率:0.60%",
-		"下浮率:1.00%!",
-		"下浮率:0.39!",
-		"上浮率/下浮率:25%!",
-		"下浮率:1.500%!",
-		"上浮率/下浮率:25%!",
-		"下浮率:20%",
-		"下浮率:10%",
-		"下浮率:10%",
-		"下浮率:2.5!",
-		"下浮率:1.00%!",
-		"下浮率:0.39!",
-		"下浮率:0.44%",
-		"下浮率:6%!",
-		"下浮率:10%-30%!",
-		"下浮率:10%-25%",
-		"下浮率:15%-20%",
-		"下浮率:0.09%",
-		"下浮率:5.5!",
-		"下浮率:4.20%",
-		"下浮率:1.50%!",
-		"下浮率:12%!",
-		"上浮率/下浮率:0.60%!",
-		"下浮率:XX%",
-		"下浮率:5.9%",
-		"下浮率:40%",
+		"2024-01-24 09:15:00",
+		"2024-02-29 00:00:00",
+		"2024-02-23 00:00:00",
+		"2024-03-05 09:30:00",
+		"2024-02-21 09:30:00",
+		"2024-02-28",
+		"2024-02-28 09:00:00",
+		"2024-03-01 00:00:00",
+		"2024-02-06 17:30:00",
+		"2024-03-01 00:00:00",
+		"2024-02-06 17:30:00",
+		"2024-02-29 00:00:00",
+		"2024-02-29 00:00:00",
+		"2024-02-29 00:00:00",
+		"2024-02-28 08:30",
+		"2024-02-29 19:56:29",
+		"2024-03-29 10:30:00",
+		"2024-03-29 10:30:00",
+		"2024-01-12 00:00:00",
+		"2024-03-23 09:00:00",
+		"2024-02-28",
+		"2024-02-28 09:00:00",
+		"2024-02-02 10:00:00",
+		"2024-02-28 00:00:00",
+		"2024-02-27 00:00:00",
+		"2024-02-28",
+		"2024-02-29 15:30:00",
+		"2024-02-29 12:00:00",
+		"2024-02-28 09:00:00",
+		"2024-02-27 09:00:00",
+		"2024-02-27 09:00:00",
+		"2024-02-29 00:00:00",
+		"2024-02-29 00:00:00",
+		"2024-01-30 09:30:00",
+		"2024-02-27 09:00:00",
+		"2024-02-27 09:30:00",
+		"2024-03-01 00:00:00",
+		"2024-02-28 09:00:00",
+		"2024-02-27 09:00:00",
+		"2024-02-28 09:00",
+		"2024-02-26 08:30",
+		"2024-02-27 09:00:00",
+		"2024-02-27 09:30:00",
+		"2024-02-28 09:00:00",
+		"2024-02-27 09:00:00",
+		"2024-02-28 09:00",
+		"2024-02-26 08:30",
+		"2024-03-05 09:30:00",
+		"2024-02-27 17:54:28",
+		"2024-03-01 10:00:00",
+		"2024-03-01 10:00:00",
+		"2024-02-08 00:00:00",
+		"2024-03-01 09:00:00",
+		"2024-03-01 09:00:00",
+		"2024-03-08 19:30:00",
+		"2024-03-08 19:30:00",
+		"2024年3月4日 08:00:00",
+		"2024年03月01日08时00分00秒",
+		"2024年3月8日 17:00:00",
+		"2024年03月08日09时30分00秒",
+		"2024-03-07 17:00:00",
+		"2024-03-07 17:00:00",
+		"2024-02-26 08:30",
+		"2024-02-28 09:00",
+		"2024-02-27 09:00:00",
+		"2024-02-28 09:00:00",
+		"2024-02-27 09:30:00",
+		"2024-02-27 09:00:00",
+		"2024-01-30 09:30:00",
+		"2024-02-29 00:00:00",
+		"2024-02-29 00:00:00",
+		"2024-02-27 09:00:00",
+		"2024-02-27 09:00:00",
+		"2024-02-28 09:00:00",
+		"2024-02-29 12:00:00",
+		"2024-02-29 16:00:00",
+		"2024-02-29 15:30:00",
+		"2024-02-28 00:00:00",
+		"2024-02-27 00:00:00",
+		"2024-02-28 00:00:00",
+		"2024-02-02 10:00:00",
+		"2024-02-28 09:00:00",
+		"2024-02-28",
+		"2024-03-23 09:00:00",
+		"2024-01-12 00:00:00",
+		"2024-03-29 10:30:00",
+		"2024-03-29 10:30:00",
+		"2024-02-29 19:56:29",
+		"2024-02-28 08:30",
+		"2024-02-29 00:00:00",
+		"2024-02-29 00:00:00",
+		"2024-02-29 00:00:00",
+		"2024-02-06 17:30:00",
+		"2024-03-01 00:00:00",
+		"2024-02-06 17:30:00",
+		"2024-03-01 00:00:00",
+		"2024-02-28 09:00:00",
+		"2024-02-28",
+		"2024-02-21 09:30:00",
+		"2024-03-05 09:30:00",
+		"2024-02-23 00:00:00",
+		"2024-02-29 00:00:00",
+		"2024-01-24 09:15:00",
+		"2024-03-06 14:00:00",
+		"2024-03-06 00:00:00",
+		"2024-03-07 23:59:00",
+	}
+	arr = []string{
+		"2024年3月4日 08:00:00",
+		"2024年03月01日08时00分00秒",
+		"2024年3月8日 17:00:00",
+		"2024年03月08日09时30分00秒",
 	}
-
 	for _, v := range arr {
-		nv := clean.CleanDiscount(v)
+		nv := clean.ClezanTime(v)
 		log.Debug(v, "~~~", nv)
 	}
 
 }
+
+func test2() {
+	arr := []string{
+		"ZFGG包件",
+		"GC530100202400091001001",
+		"GC532300202400053001001",
+		"广州市白云区金沙街沙凤经济联合社留用地项目S2地块(金沙洲AB3708005地块)新建商业综合体全过程造价咨询服务",
+		"一标段",
+		"一标段",
+		"E6111013556240003001001",
+		"E6111013556240003001002",
+		"一标段",
+		"二标段",
+		"一标段",
+		"三标段",
+		"二标段",
+		"E61042235168rf556pk7001",
+		"第三标段",
+		"第二标段",
+		"第三标段",
+		"GC530500202400037001001",
+		"第17标段",
+		"第18标段",
+		"1",
+		"第23标段",
+		"标段二",
+		"标段二",
+		"一标段",
+		"一标段",
+		"一标段",
+		"e3100000151040117001001",
+		"e3100000151027733043001",
+		"e3100000151032001003001",
+		"2024ANNGZ00007",
+		"SYS20240206NTGC05002004",
+		"SYS20240206NTGC05002010",
+		"SYS20240206NTGC05002003",
+		"E341522001002634001",
+		"第1标段",
+		"第三标段",
+		"KJ06",
+		"四川省遂宁市第一中学西校区第三期建设项目及附属工程(遂宁一中新校区改、扩建工程)主体工程增加建设内容-施工-1",
+		"四川省遂宁市第一中学西校区第三期建设项目及附属工程(遂宁一中新校区改、扩建工程)增加建设内容-监理-1",
+		"射洪市绿色农业产业带建设项目(一期)-监理-1",
+		"HJFFJSZ2024020002001",
+		"一标段",
+		"E3702002313017682001001",
+		"E3702002313017722001001",
+		"1",
+		"1",
+		"标包一",
+		"C01",
+		"KJ06",
+		"五标段",
+		"二标段",
+		"1标段",
+	}
+	for _, v := range arr {
+		nv := clean.CleanOtherCode(v)
+		log.Debug(nv, "~~~", v)
+	}
+}

+ 63 - 9
prompt/prompt_field.go

@@ -17,18 +17,26 @@ var pmt_field_prefix = `
 	}
 	公告:` + `%s` + "\n结果JSON:"
 
+//三阶段 采购单位、中标单位、代理机构,联系人、联系电话
+
 var pmt_field1 = `
 你是一个文本处理模型,专门用于分析文本提取信息,你具备以下能力:
 1、实体识别抽取
 2、信息归属地域
 请根据我提供的正文做以下工作;
-首先,根据正文进行"项目所在地的省份"、"项目所在地的城市"、"采购单位"、"项目的中标单位" 进行实体抽取;
+首先,根据正文进行"项目所在地的省份"、"项目所在地的城市"、"采购单位"、"项目的中标单位"、"代理机构"、"采购单位联系人"、"采购单位联系电话"、"中标单位联系人"、"中标单位联系电话"、"代理机构联系人"、"代理机构联系电话"  进行实体抽取;
 
 你在识别"项目所在地的省份"的时候,如果找不到,请去找项目信息的省份、采购单位的省份,如果还找不到,请根据上下文思考,给出你认为的最佳匹配的省份;
 你在识别"项目所在地的城市"的时候,如果找不到,请去找项目信息的城市、采购单位所在的城市,如果匹配到三级区县信息,请推导出具体城市。如果还找不到,请根据上下文思考,给出你认为的最佳匹配的城市;
 你在识别"采购单位"的时候,请根据上下文思考,输出最佳匹配结果;包括但不限于采购人,采购方,甲方等;不要使用:代理机构与中标单位;
-你在识别"项目的中标单位"的时候,中标单位包括但不限于成交供应商(注:当入围供应商/中标人存在多个,选择第一位为中标单位)、中标人、中标方、承包方、中选单位、服务商、第一名中标候选人、第1名中标人(忽略其他中标候选人),如果正文明确指定了中标单位,请优先选正文的中标单位。联合体投标时,请列出所有单位名称使用","分割)。如果不能准确识别出"项目的中标单位",请填写"无";注:不要采购单位,不要代理机构;
-
+你在识别"项目的中标单位"的时候,中标单位包括但不限于成交供应商(注:当入围供应商/中标人存在多个,选择第一位为中标单位)、中标人、中标方、承包方、受让单位、中选单位、服务商、第一名中标候选人、第1名中标人(忽略其他中标候选人),如果正文明确指定了中标单位,请优先选正文的中标单位。联合体投标时,请列出所有单位名称使用","分割)。如果不能准确识别出"项目的中标单位",请填写"无";注:不要采购单位,不要代理机构;
+你在识别"代理机构"的时候,输出代理采购事务的机构名称,不能使用采购单位和中标单位;
+你在识别"采购单位联系人"的时候,输出负责采购的单位联系人,包括但不限于采购⼈或招标⼈或采购项目联系人;
+你在识别"采购单位联系方式"的时候,输出负责采购单位信息中的联系方式,包括但不限于采购⼈或招标⼈或采购单位信息的联系电话或联系方式,不能使用非电话号码;
+你在识别"中标单位联系人"的时候,输出项目的中标单位的联系人,通常为供应商或中标人;
+位联系方式"的时候,输出负责中标单位的联系方式,包括但不限于中标人的联系电话,中标单位联系人的联系电话等,不能使用非电话号码;
+你在识别"代理机构联系人"的时候你在识别"中标单,输出代理采购事务的机构的联系人;
+你在识别"代理机构联系方式"的时候,输出代理机构的联系号码或联系电话或联系方式,不能使用非电话号码;
 请将上述的识别结果、信息分类结果,按照JSON格式输出,
 严格按照json格式
 {
@@ -36,34 +44,73 @@ var pmt_field1 = `
 "城市":"项目所在地的城市",
 "采购单位":"采购单位",
 "中标单位":"项目的中标单位",
+"代理机构":"代理机构",
+"采购单位联系人":"采购单位联系人",
+"采购单位联系方式":"采购单位联系方式",
+"中标单位联系人":"中标单位联系人",
+"中标单位联系方式":"中标单位联系方式",
+"代理机构联系人":"代理机构联系人",
+"代理机构联系方式":"代理机构联系方式",
 }
 
 请回答我的问题,不要联想,不要无中生有,不要生成解释,对于尚未确定或未明确的信息请在JSON对应的值填写:无
 正文内容:` + "\n" + `%s` + "\n结果JSON:"
-
 var pmt_field2 = `
 你是一个文本处理模型,专门用于分析文本提取信息,你具备以下能力:
 1、实体识别抽取
 请根据我提供的正文做以下工作;
 首先,根据正文进行"项目名称"、"项目编号"、"项目的预算金额"、"项目的中标金额" 进行实体抽取;
 
-你在识别"项目名称"的时候,请根据上下文思考,输出最佳匹配结果;如果"项目名称"前面包含实体单位,请务必提取完整;
-你在识别"项目编号"的时候,请根据上下文思考,输出最佳匹配结果;项目编号和标段编号同时存在时,优先选项目编号;不要使用证书编号当做项目编号的值;
 你在识别"项目的预算金额"的时候,一定不要识别业绩相关的内容。(合同内容如果没有明确指出甲方的预算金额,请不要识别)如果有多个预算金额存在,优先取预算金额含税总价。如果识别出的预算金额含有单位比如万元等,请务必提取完整。如果不能准确识别出"项目的预算金额,"请填写"无";
 你在识别"项目的中标金额"的时候,一定不要识别业绩相关的内容。优先使用合同的金额,合同的总价当做"项目的中标金额"。如果有多个中标金额存在,优先取中标金额的含税总价。如果原文没有明确的中标金额,可以选取第一名中标候选人的投标报价(金额单位请提取完整)。如果识别出项目的中标金额含有单位比如万元等,请务必提取完整。如果不能准确识别出"项目的中标金额",请填写"无";
-
+你在识别"开标日期"时,输出开标的具体时间,输出格式为:YYYY-MM-DD HH:MM:SS,如果格式不对,请转化为:YYYY-MM-DD HH:MM:SS;
+你在识别"投标截止时间"时,输出投标⽂件提交的最后期限,输出格式为:YYYY-MM-DD HH:MM:SS,如果格式不对,请转化为:YYYY-MM-DD HH:MM:SS;
+你在识别"开标地点"时,输出开标的具体地址;
+你在识别"招标文件获取开始时间"时,输出招标文件的的具体开始时间,输出格式为:YYYY-MM-DD HH:MM:SS,如果格式不对,请转化为:YYYY-MM-DD HH:MM:SS;
+你在识别"招标文件获取结束时间"时,输出招标文件的的具体结束时间,输出格式为:YYYY-MM-DD HH:MM:SS,如果格式不对,请转化为:YYYY-MM-DD HH:MM:SS;
+你在识别"中标金额折扣率"时,输出中标费用的上浮率或者下浮率或者折扣率,输出格式为(上浮率:xx% 或 下浮率:xx% 或 折扣率;xx% ),如果格式不对,请转化为:(上浮率:xx% 或 下浮率:xx% 或 折扣率;xx% ),不要带具体价格费用的数据,没有识别出来,请填写"无",如果识别到多个值,请填写"无";
 请将上述的识别结果、信息分类结果,按照JSON格式输出,
 严格按照json格式
 {
-"项目名称":"项目名称",
-"项目编号":"项目编号",
 "预算金额":"项目的预算金额",
 "中标金额":"项目的中标金额",
+"开标日期":"开标日期",
+"投标截止时间":"投标截止时间",
+"开标地点":"开标地点",
+"招标文件获取开始时间":"招标文件获取开始时间",
+"招标文件获取结束时间":"招标文件获取结束时间"',
+"中标金额折扣率":"中标金额折扣率",
 }
 
 请回答我的问题,不要联想,不要无中生有,不要生成解释,对于尚未确定或未明确的信息请在JSON对应的值填写:无
 正文内容:` + "\n" + `%s` + "\n结果JSON:"
 
+// :招标编号(主数据)、项目编号(子包)、标段编号(子包)、合同编号(子包);
+// 外围字段全抽出
+var pmt_field3 = `
+你是一个文本处理模型,专门用于分析文本提取信息,你具备以下能力:
+1、实体识别抽取
+请根据我提供的正文做以下工作;
+首先,根据正文进行"项目名称"、"项目编号"、"招标编号"、"标段编号"、"合同编号" 进行实体抽取;
+
+你在识别"项目名称"的时候,请根据上下文思考,输出最佳匹配结果;如果"项目名称"前面包含实体单位,请务必提取完整;
+你在识别"项目编号"的时候,请根据上下文思考,输出最佳匹配结果;项目编号和标段编号同时存在时,优先选项目编号;不要使用证书编号当做项目编号的值;
+你在识别"招标编号"时,获取正文中招标过程中用于唯一标识一个特定招标项目的编号,不要使用项目编号和标段编号;
+你在识别"标段编号"时,获取正文中的标段编号,是标段的唯一识别码,由数字、字母或其组合构成,不要使用纯汉字;
+你在识别"合同编号"时,获取正文中合同编号,不要使用证书编号当做项目编号的值;
+请将上述的识别结果、信息分类结果,按照JSON格式输出,
+严格按照json格式
+{
+"项目名称":"项目名称",
+"项目编号":"项目编号",
+"招标编号":"招标编号",
+"标段编号":"标段编号",
+"合同编号":"合同编号",
+}
+ 
+请回答我的问题,不要联想,不要无中生有,不要生成解释,对于尚未确定或未明确的信息请在JSON对应的值填写:无
+正文内容:` + "\n" + `%s` + "\n结果JSON:"
+
 // 判断短文本
 func AcquireJudgeShortInfo(detail string) map[string]interface{} {
 	content := PromptFieldText(detail, pmt_field_prefix)
@@ -85,6 +132,13 @@ func AcquireExtractFieldInfoSecond(detail string) map[string]interface{} {
 	return zp
 }
 
+// 获取抽取字段第三次
+func AcquireExtractFieldInfoThird(detail string) map[string]interface{} {
+	content := PromptFieldText(detail, pmt_field3)
+	zp := ai.PostZhiPuInfo(content)
+	return zp
+}
+
 // 提示语构建
 func PromptFieldText(detail string, prompt string) string {
 	content := fmt.Sprintf(prompt, detail)