Преглед изворни кода

情报标签,支持大模型新字段 tag_topinformation_zp

wcc пре 9 месеци
родитељ
комит
942c4a380d

+ 1 - 0
bidding_tags/config.go

@@ -28,6 +28,7 @@ type EnvConf struct {
 	Rulec         string
 	Ruled         string
 	Rulee         string
+	Doai          bool
 }
 
 type EsConf struct {

+ 30 - 18
bidding_tags/config.toml

@@ -1,31 +1,43 @@
 [mongo]  ## 标讯地址
-    host = "127.0.0.1:27083"
-    #        host = "172.17.189.140:27080"
-    db = "qfw"
-    coll = ""
-    username = "SJZY_RWbid_ES"
-    password = "SJZY@B4i4D5e6S"
-    direct = true  ## 本地代理时需要打开,
-
+#    host = "127.0.0.1:27083"
+#    #host = "172.17.189.140:27080"
+#    db = "qfw"
+#    coll = "bidding"
+#    username = "SJZY_RWbid_ES"
+#    password = "SJZY@B4i4D5e6S"
+#    direct = true  ## 本地代理时需要打开,
 
+## 测试环境
+    host = "192.168.3.149:27102"
+    db = "qfw_data"
+    coll = "bidding"
+    username = "root"
+    password = "root"
 
 [esa] ## 华为云集群2
 #    url = "http://172.17.4.184:19908" ## 线上地址
-    url = "http://127.0.0.1:19908"
-    username = "jybid"
-    password = "Top2023_JEB01i@31"
+#    url = "http://127.0.0.1:19908"
+#    username = "jybid"
+#    password = "Top2023_JEB01i@31"
+
+##
+    url = "http://192.168.3.149:9201"
+    username = ""
+    password = ""
+
+
 
 [esb] ## 华为云集群1
 #    url = "http://172.17.4.184:19905" ## 线上地址
-    url = "http://127.0.0.1:19905"
-    username = "jybid"
-    password = "Top2023_JEB01i@31"
+#    url = "http://127.0.0.1:19905"
+#    username = "jybid"
+#    password = "Top2023_JEB01i@31"
 
 [env]
-
-    start = -2 ## 开始取2天前的数据,
-    end = -1 ## 截止取1天前的数据,
+    start = -1 ## 开始取2天前的数据,
+    end = 0 ## 截止取1天前的数据,
     spec = "0 00 01 * * *"  ## 定时任务,每天凌晨1点执行
+    doai = true  ## 是否启用调用大模型标记
     ## 情报_环境采购
     rulea = "A021004\nA021006\nA021018\nA021019\nA021027\nA021205\nA021304\nA021305\nA021401\nA021402\nA021403\nA022211\nA023600\nA023601\nA023602\nA023603\nA023604\nA023605\nA023606\nA023607\nA023608\nA023609\nA023699\nA070801\nC010319\nC070000\nC070100\nC070101\nC070102\nC070103\nC070104\nC070199\nC070200\nC070201\nC070202\nC070203\nC070204\nC070205\nC070206\nC070207\nC070208\nC070209\nC070299\nC079900\nC110517\nC120200\nC120201\nC120202\nC120203\nC120204\nC120299\nC200208\nC240500"
     ## 情报_印务商机
@@ -35,4 +47,4 @@
     ## 情报_车辆租赁
     ruled = "C23110300"
     ## 情报_安防
-    rulee ="A02091107\nA02370400\nA02370500\nA02370900\nB05100000\nB06010000\nB06010100\nB06010200\nB06010300\nB06010400\nB06019900\nB06020000\n B06020100\nB06020200\nB06020300\nB06020400\nB06020500\nB06020600\nB06020700\nB06020800\nB06029900\nC16020100\nC16020200\nC16020400\nC16070100"
+    rulee ="A02091107\nA023704\nA023705\nA023709\nB0510\nB0601\nB060101\nB060102\nB060103\nB060104\nB060199\nB0602\nB060201\nB060202\nB060203\nB060204\nB060205\nB060206\nB060207\nB060208\nB060299\nC160201\nC160202\nC160204\nC160701"

+ 5 - 2
bidding_tags/go.mod

@@ -1,9 +1,11 @@
 module bidding_tags
 
-go 1.20
+go 1.21.1
+
+toolchain go1.22.6
 
 require (
-	github.com/robfig/cron v1.2.0
+	github.com/itcwc/go-zhipu v0.0.0-20241009091621-5cc379cf0ada
 	github.com/spf13/viper v1.19.0
 	jygit.jydev.jianyu360.cn/data_processing/common_utils v0.0.0-20240412074219-927f3f682cb3
 )
@@ -13,6 +15,7 @@ require (
 	github.com/andybalholm/cascadia v1.3.1 // indirect
 	github.com/dchest/captcha v1.0.0 // indirect
 	github.com/fsnotify/fsnotify v1.7.0 // indirect
+	github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
 	github.com/golang/snappy v0.0.1 // indirect
 	github.com/hashicorp/hcl v1.0.0 // indirect
 	github.com/josharian/intern v1.0.0 // indirect

+ 14 - 2
bidding_tags/go.sum

@@ -13,6 +13,7 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/dchest/captcha v1.0.0 h1:vw+bm/qMFvTgcjQlYVTuQBJkarm5R0YSsDKhm1HZI2o=
 github.com/dchest/captcha v1.0.0/go.mod h1:7zoElIawLp7GUMLcj54K9kbw+jEyvz2K0FDdRRYhvWo=
 github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@@ -22,11 +23,14 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
 github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
 github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
 github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
+github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
 github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
 github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
 github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
 github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
 github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
+github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
+github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -52,9 +56,14 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
 github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
 github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/itcwc/go-zhipu v0.0.0-20240626065325-ffc8bf1cfaaa h1:iOly0dSYv9AdoWfWt3uk4IF4O/nW+fyXV9rnC87UC7s=
+github.com/itcwc/go-zhipu v0.0.0-20240626065325-ffc8bf1cfaaa/go.mod h1:z7QZm7ol2nikFFGHwArJr1NTtBSE0M0g9MvHKxm1Sw0=
+github.com/itcwc/go-zhipu v0.0.0-20241009091621-5cc379cf0ada h1:zNcSPmPckACx60xc8N3MtK7uUcZDL14ig8VrSg/o4dg=
+github.com/itcwc/go-zhipu v0.0.0-20241009091621-5cc379cf0ada/go.mod h1:z7QZm7ol2nikFFGHwArJr1NTtBSE0M0g9MvHKxm1Sw0=
 github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
 github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
 github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@@ -64,9 +73,11 @@ github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/
 github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
 github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
 github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
@@ -86,12 +97,12 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
-github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
 github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
 github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
 github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
+github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
 github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
 github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
 github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
@@ -234,6 +245,7 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
 gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw=

+ 354 - 44
bidding_tags/main.go

@@ -1,15 +1,17 @@
 package main
 
 import (
-	"log"
-	"strings"
-	"time"
-
+	"fmt"
 	"github.com/robfig/cron/v3"
 	"github.com/spf13/viper"
 	util "jygit.jydev.jianyu360.cn/data_processing/common_utils"
 	es "jygit.jydev.jianyu360.cn/data_processing/common_utils/elastic"
 	"jygit.jydev.jianyu360.cn/data_processing/common_utils/mongodb"
+	"log"
+	"regexp"
+	"strings"
+	"sync"
+	"time"
 )
 
 var (
@@ -24,6 +26,13 @@ var (
 	RuleE = make([]string, 0)
 )
 
+type RequestData struct {
+	Title       string
+	Projectname string
+	Class       []string
+	ID          string
+}
+
 const timeTypeAll = 1
 const timeTypeInc = 2
 
@@ -47,7 +56,12 @@ func InitConfig() (err error) {
 }
 
 func Init() {
-	InitConfig()
+	err := InitConfig()
+	if err != nil {
+		log.Println("配置文件错误", err)
+		return
+	}
+
 	Mgo = &mongodb.MongodbSim{
 		MongodbAddr: GF.Mongo.Host,
 		//MongodbAddr: "127.0.0.1:27083",
@@ -67,13 +81,15 @@ func Init() {
 	}
 	Esa.InitElasticSize()
 
-	Esb = &es.Elastic{
-		S_esurl:  GF.Esb.URL,
-		I_size:   5,
-		Username: GF.Esb.Username,
-		Password: GF.Esb.Password,
+	if GF.Esb.URL != "" {
+		Esb = &es.Elastic{
+			S_esurl:  GF.Esb.URL,
+			I_size:   5,
+			Username: GF.Esb.Username,
+			Password: GF.Esb.Password,
+		}
+		Esb.InitElasticSize()
 	}
-	Esb.InitElasticSize()
 
 	RuleA = strings.Split(GF.Env.Rulea, "\n")
 	RuleB = strings.Split(GF.Env.Ruleb, "\n")
@@ -84,7 +100,11 @@ func Init() {
 
 func main() {
 	Init()
-	// dealAll() //存量数据
+	//dealAll() //规则处理存量数据
+	//dealInc()
+	//dealAllAi() //大模型
+
+	//select {}
 
 	local, _ := time.LoadLocation("Asia/Shanghai")
 	c := cron.New(cron.WithLocation(local), cron.WithSeconds())
@@ -101,6 +121,7 @@ func main() {
 
 // dealInc 处理增量数据
 func dealInc() {
+	log.Println("开始处理增量数据")
 	now := time.Now()
 	start := time.Date(now.Year(), now.Month(), now.Day()+GF.Env.Start, 0, 0, 0, 0, now.Location())
 	end := time.Date(now.Year(), now.Month(), now.Day()+GF.Env.End, 0, 0, 0, 0, now.Location())
@@ -112,39 +133,69 @@ func dealInc() {
 		},
 	}
 	dealTopInformation(where, timeTypeInc)
+	//大模型处理,保存字段 tag_topinformation_zp
+	if GF.Env.Doai {
+		log.Println("开始处理大模型结果")
+		go dealTopInformationAi4(where)
+	}
+
+	log.Println("增量数据处理完毕")
 }
 
 // dealAll 处理存量数据
 func dealAll() {
 	where := map[string]interface{}{
 		"comeintime": map[string]interface{}{
-			"$gte": 1726070400,
-			"$lt":  1726156800,
+			"$gte": 1704038400,
+			"$lt":  1726851634,
 		},
 	}
 
 	dealTopInformation(where, timeTypeAll) //处理情报标签一级
 }
 
-// dealTopInformation  处理情报标签一级
+func dealAllAi() {
+	//where := map[string]interface{}{
+	//	//"comeintime": map[string]interface{}{
+	//	//	//"$gte": 1726070400,
+	//	//	"$lt": 1727078591,
+	//	//},
+	//}
+
+	log.Println("开始处理数据")
+	//dealTopInformationAi(where) //处理情报标签一级
+	//dealTopInformationAi2(where) //处理情报标签一级;50个一组调用
+	//dealTopInformationAi3(where) //单个数据调用
+	dealTopInformationAi4(nil) //5一组,开启携程
+	//dealTopInformationAi5(nil) //单条调用智普,开启携程
+}
+
+// dealTopInformation  处理情报标签一级;剑鱼码 处理方式
 func dealTopInformation(where interface{}, timeType int) {
 	if where == nil {
 		log.Println("查询条件为空")
-		return
 	}
+
+	log.Println(where)
 	defer util.Catch()
 	sess := Mgo.GetMgoConn()
 	defer Mgo.DestoryMongoConn(sess)
 	count := 0
-	it := sess.DB("qfw").C("bidding").Find(where).Select(nil).Iter()
+	ch := make(chan bool, 5)
+	wg := &sync.WaitGroup{}
+	it := sess.DB(GF.Mongo.DB).C("bidding").Find(where).Select(nil).Iter()
 	for tmp := make(map[string]interface{}); it.Next(&tmp); count++ {
-		if count%5000 == 0 {
-			log.Println("current:", count, tmp["title"])
+		if count%1000 == 0 {
+			log.Println("dealTopInformation,current:", count, tmp["title"], tmp["_id"])
 		}
-
-		if gov_classify, ok := tmp["gov_classify"]; !ok {
-			continue
-		} else {
+		ch <- true
+		wg.Add(1)
+		go func(tmp map[string]interface{}) {
+			defer func() {
+				<-ch
+				wg.Done()
+			}()
+			//
 			topinformation := make([]string, 0) //
 			hasNew := false
 			if existTop, okk := tmp["tag_topinformation"]; okk {
@@ -155,21 +206,25 @@ func dealTopInformation(where interface{}, timeType int) {
 				}
 			}
 
-			if govMap, ok3 := gov_classify.(map[string]interface{}); ok3 {
+			if govMap, ok3 := tmp["gov_classify"].(map[string]interface{}); ok3 {
 				zc_code := util.ObjToString(govMap["zc_code"])
 				if IsInStringArray(zc_code, RuleA) {
 					hasNew = true
 					topinformation = append(topinformation, "情报_环境采购")
-				} else if IsInStringArray(zc_code, RuleB) {
+				}
+				if IsInStringArray(zc_code, RuleB) {
 					hasNew = true
 					topinformation = append(topinformation, "情报_印务商机")
-				} else if IsInStringArray(zc_code, RuleC) {
+				}
+				if IsInStringArray(zc_code, RuleC) {
 					hasNew = true
 					topinformation = append(topinformation, "情报_家具招投标")
-				} else if IsInStringArray(zc_code, RuleD) {
+				}
+				if IsInStringArray(zc_code, RuleD) {
 					hasNew = true
 					topinformation = append(topinformation, "情报_车辆租赁")
-				} else if IsInStringArray(zc_code, RuleE) {
+				}
+				if IsInStringArray(zc_code, RuleE) {
 					hasNew = true
 					topinformation = append(topinformation, "情报_安防")
 				}
@@ -190,29 +245,284 @@ func dealTopInformation(where interface{}, timeType int) {
 				//log.Println("hasNew", " ====== ", biddingID)
 				Mgo.UpdateById("bidding", biddingID, map[string]interface{}{"$set": updateMgo})
 				//ToDo 2.更新es
-				// 存量数据
-				if timeType == timeTypeAll {
-					if util.IntAll(tmp["extracttype"]) != 1 {
-						continue
-					}
-				} else {
-					// 增量数据
-					if util.IntAll(tmp["dataprocess"]) != 8 {
-						continue
-					}
+				if GF.Esa.URL != "" {
+					_ = Esa.UpdateDocument("bidding", biddingID, updateEs)
 				}
 
-				err := Esa.UpdateDocument("bidding", biddingID, updateEs)
-				if err != nil && err.Error() != "Document not updated: noop" {
-					log.Println("esa update err", biddingID, err)
+				if GF.Esb.URL != "" {
+					_ = Esb.UpdateDocument("bidding", biddingID, updateEs)
 				}
-				err = Esb.UpdateDocument("bidding", biddingID, updateEs)
-				if err != nil && err.Error() != "Document not updated: noop" {
-					log.Println("esb update err", biddingID, err)
+			}
+
+		}(tmp)
+		tmp = make(map[string]interface{})
+	}
+
+	wg.Wait()
+	log.Println("剑鱼码规则处理数据处理完毕")
+}
+
+// dealTopInformationAi2的基础上,开启协程
+func dealTopInformationAi4(where interface{}) {
+	defer util.Catch()
+	sess := Mgo.GetMgoConn()
+	defer Mgo.DestoryMongoConn(sess)
+	count := 0
+
+	key := "4d5206b1b297c1e7b77f9578edcb2cf7.TNU2i8G1oUNdR02i"
+	model := "glm-4-flash"
+	//key := "6c86cea8659ff1d33b161ea7213ea97c.m4OcENaRan8NeLSZ" //我自己的key
+
+	re := regexp.MustCompile(`title:(.*?),projectname:(.*?),id:(.*?),class:(.*?)(?:\s*$|\n)`)
+	var lines = make([]string, 0)
+	it := sess.DB(GF.Mongo.DB).C(GF.Mongo.Coll).Find(where).Select(nil).Sort("-_id").Iter()
+	resultsChan := make(chan map[string]string, 5000)
+	sem := make(chan struct{}, 100) // 控制并发数量
+	wg := sync.WaitGroup{}
+	wg.Add(1)
+	go func() {
+		defer wg.Done()
+		count2 := 0
+		for item := range resultsChan {
+			count2++
+			// 处理返回结果,例如更新数据库
+			tags := make([]string, 0)
+			class := util.ObjToString(item["class"])
+			if class == "其他分类" || class == "" || item["id"] == "" {
+				continue
+			}
+			for _, v2 := range strings.Split(class, ",") {
+				if v2 == "车辆领域" {
+					tags = append(tags, "情报_车辆租赁")
+				} else if v2 == "安防领域" {
+					tags = append(tags, "情报_安防")
+				} else if v2 == "印务领域" {
+					tags = append(tags, "情报_印务商机")
+				} else if v2 == "环境领域" {
+					tags = append(tags, "情报_环境采购")
+				} else if v2 == "家具领域" {
+					tags = append(tags, "情报_家具招投标")
 				}
 			}
+			if len(tags) > 0 {
+				id := util.ObjToString(item["id"])
+				updateMgo := map[string]interface{}{
+					"tag_topinformation_zp": tags,
+					//"topinformation_time":   time.Now().Unix(),
+				}
+				Mgo.UpdateById("bidding", id, map[string]interface{}{"$set": updateMgo})
+				updateEs := map[string]interface{}{
+					"tag_topinformation_zp": tags,
+				}
+
+				if count2%100 == 0 {
+					log.Println("update es", id, tags)
+				}
+				if GF.Esa.URL != "" {
+					_ = Esa.UpdateDocument("bidding", id, updateEs)
+				}
+
+				if GF.Esb.URL != "" {
+					_ = Esb.UpdateDocument("bidding", id, updateEs)
+				}
+			}
+		}
+	}()
+
+	for tmp := make(map[string]interface{}); it.Next(&tmp); count++ {
+		if count%1000 == 0 {
+			log.Println("current:", count, tmp["title"], tmp["_id"])
+		}
+		title := util.ObjToString(tmp["title"])
+		projectname := util.ObjToString(tmp["projectname"])
+		biddingID := mongodb.BsonIdToSId(tmp["_id"])
+		lines = append(lines, fmt.Sprintf("title:%s,projectname:%s,id:%s", title, projectname, biddingID))
+		if len(lines) == 5 {
+			sem <- struct{}{} // 增加并发控制
+			go func(lines []string) {
+				defer func() { <-sem }() // 释放并发控制
+				report := strings.Join(lines, "\n")
+				resu, err := ZpAI4(key, model, report)
+				lines = make([]string, 0)
+
+				if err != nil {
+					log.Println("智普请求失败,", err, report)
+					return
+				}
+				splitLines := strings.Split(resu, `;`)
+				for _, line := range splitLines {
+					matches := re.FindStringSubmatch(line)
+					if len(matches) == 5 {
+						result := map[string]string{
+							"title":       matches[1],
+							"projectname": matches[2],
+							"id":          matches[3],
+							"class":       matches[4],
+						}
+						resultsChan <- result
+					}
+				}
+			}(lines)
+			// 清空 lines 切片而不是 reportBuilder
+			lines = make([]string, 0)
 		}
 	}
 
+	if len(lines) > 0 {
+		report := strings.Join(lines, "\n")
+		resu, err := ZpAI4(key, model, report)
+		if err != nil {
+			log.Println("智普请求失败,尝试再次请求", err)
+		}
+		resu, err = ZpAI4(key, model, report)
+		if err == nil && resu != "" {
+			splitLines := strings.Split(resu, "\n")
+			for _, line := range splitLines {
+				matches := re.FindStringSubmatch(line)
+				if len(matches) == 5 {
+					result := map[string]string{
+						"title":       matches[1],
+						"projectname": matches[2],
+						"id":          matches[3],
+						"class":       matches[4],
+					}
+					resultsChan <- result
+				}
+			}
+		}
+	}
+
+	close(resultsChan) // 关闭 channel
+	wg.Wait()
+	log.Println("大模型处理数据处理完毕")
+}
+
+// dealTopInformationAi5 单个调用ZpAI4,多协程
+func dealTopInformationAi5(where interface{}) {
+	defer util.Catch()
+	sess := Mgo.GetMgoConn()
+	defer Mgo.DestoryMongoConn(sess)
+	count := 0
+
+	key := "4d5206b1b297c1e7b77f9578edcb2cf7.TNU2i8G1oUNdR02i"
+	model := "glm-4-flash"
+	re := regexp.MustCompile(`title:(.*?),projectname:(.*?),id:(.*?),class:(.*?)(?:\s*$|\n)`)
+	ch := make(chan bool, 50)
+	wg := &sync.WaitGroup{}
+	it := sess.DB(GF.Mongo.DB).C(GF.Mongo.Coll).Find(where).Select(nil).Sort("-_id").Iter()
+	for tmp := make(map[string]interface{}); it.Next(&tmp); count++ {
+		if count%100 == 0 {
+			log.Println("current:", count, tmp["title"], tmp["_id"])
+		}
+
+		ch <- true
+		wg.Add(1)
+
+		go func(tmp map[string]interface{}) {
+			defer func() {
+				<-ch
+				wg.Done()
+			}()
+			////
+			title := util.ObjToString(tmp["title"])
+			projectname := util.ObjToString(tmp["projectname"])
+			biddingID := mongodb.BsonIdToSId(tmp["_id"])
+			text := fmt.Sprintf("title:%s,projectname:%s,id:%s\n", title, projectname, biddingID)
+			resu, err := ZpAI4(key, model, text)
+			if len(resu) > 0 && err != nil {
+				splitLines := strings.Split(resu, `;`)
+				for _, line := range splitLines {
+					matches := re.FindStringSubmatch(line)
+					if len(matches) == 5 {
+						class := matches[4]
+						if class != "" && class != "其他分类" {
+							tags := make([]string, 0)
+							for _, v2 := range strings.Split(class, ",") {
+								if v2 == "车辆领域" {
+									tags = append(tags, "情报_车辆租赁")
+								} else if v2 == "安防领域" {
+									tags = append(tags, "情报_安防")
+								} else if v2 == "印务领域" {
+									tags = append(tags, "情报_印务商机")
+								} else if v2 == "环境领域" {
+									tags = append(tags, "情报_环境采购")
+								} else if v2 == "家具领域" {
+									tags = append(tags, "情报_家具招投标")
+								}
+							}
+							if len(tags) > 0 {
+								if biddingID != "" {
+									updateMgo := map[string]interface{}{
+										"tag_topinformation_zp": tags,
+										"topinformation_time":   time.Now().Unix(),
+									}
+									Mgo.UpdateById("bidding", biddingID, map[string]interface{}{"$set": updateMgo})
+
+									if count%100 == 0 {
+										log.Println("update es", biddingID, tags)
+									}
+									updateEs := map[string]interface{}{
+										"tag_topinformation_zp": tags,
+									}
+									if GF.Esa.URL != "" {
+										log.Println("更新es ,", biddingID)
+										err := Esa.UpdateDocument("bidding", biddingID, updateEs)
+										if err != nil && err.Error() != "Document not updated: noop" {
+											log.Println("esa update err", biddingID, err)
+										}
+									}
+
+									if GF.Esb.URL != "" {
+										err := Esb.UpdateDocument("bidding", biddingID, updateEs)
+										if err != nil && err.Error() != "Document not updated: noop" {
+											log.Println("esb update err", biddingID, err)
+										}
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+		}(tmp)
+
+		wg.Wait()
+		tmp = make(map[string]interface{})
+
+	}
+
 	log.Println("数据处理完毕")
 }
+
+func dealAi(datas []RequestData) {
+
+	// 有匹配新的标签,需要更新MongoDB以及ES 数据
+	//if hasNew {
+	//	topinformation = removeDuplicates(topinformation) //去重
+	//	//ToDo 1.更新MongoDB
+	//	updateMgo := map[string]interface{}{
+	//		"tag_topinformation":  topinformation,
+	//		"topinformation_time": time.Now().Unix(),
+	//	}
+	//	updateEs := map[string]interface{}{
+	//		"tag_topinformation": topinformation,
+	//	}
+	//	//log.Println("hasNew", " ====== ", biddingID)
+	//	Mgo.UpdateById("bidding", biddingID, map[string]interface{}{"$set": updateMgo})
+	//	//ToDo 2.更新es
+	//
+	//	if GF.Esa.URL != "" {
+	//		err := Esa.UpdateDocument("bidding", biddingID, updateEs)
+	//		if err != nil && err.Error() != "Document not updated: noop" {
+	//			log.Println("esa update err", biddingID, err)
+	//		}
+	//	}
+	//
+	//	if GF.Esb.URL != "" {
+	//		err := Esb.UpdateDocument("bidding", biddingID, updateEs)
+	//		if err != nil && err.Error() != "Document not updated: noop" {
+	//			log.Println("esb update err", biddingID, err)
+	//		}
+	//	}
+	//}
+}

+ 4 - 3
bidding_tags/readme.md

@@ -1,8 +1,9 @@
 # 给bidding 标讯数据打标签
 
-## 补充 tag_topinformation 
+## 补充 tag_topinformation
 
 - 说明:
-  `tag_topinformation` 字段是一个字符串数组,目前分类程序打的有 `情报_物业` ,现在要根据 李俊良 那边字段 `gov_classify.zc_code`,
-去扩充 `tag_topinformation`,需要追加 `情报_环境采购`,`情报_印务商机`,`情报_家具招投标`,`情报_车辆租赁`。
+  `tag_topinformation` 字段是一个字符串数组,目前分类程序打的有 `情报_物业` ,现在要根据 李俊良
+  那边字段 `gov_classify.zc_code`,
+  去扩充 `tag_topinformation`,需要追加 `情报_环境采购`,`情报_印务商机`,`情报_家具招投标`,`情报_车辆租赁`,`情报_安防`。
 

+ 204 - 0
bidding_tags/tag_test.go

@@ -0,0 +1,204 @@
+package main
+
+import (
+	"fmt"
+	util "jygit.jydev.jianyu360.cn/data_processing/common_utils"
+	"jygit.jydev.jianyu360.cn/data_processing/common_utils/mongodb"
+	"log"
+	"regexp"
+	"strings"
+	"testing"
+	"time"
+)
+
+func TestZpAI(t *testing.T) {
+	InitConfig()
+	Init()
+	//key := "4d5206b1b297c1e7b77f9578edcb2cf7.TNU2i8G1oUNdR02i"
+	key := "6c86cea8659ff1d33b161ea7213ea97c.m4OcENaRan8NeLSZ" //我自己的key
+	model := "glm-4-flash"
+
+	//	data := `标题:海南陵水黎安国际教育创新试验区置地有限公司公务车租赁和垃圾处理项目,项目名称:海南陵水黎安国际教育创新试验区置地有限公司公务车租赁和垃圾处理项目
+	//标题:2024年广西柳城北区块桂融地3井野外车辆租赁项目,项目名称:2024年广西柳城北区块桂融地3井野外车辆租赁项目
+	//标题:泰山玻璃纤维有限公司-车队-班车客车租赁,项目名称:泰山玻璃纤维有限公司-车队-班车客车租赁`
+	//
+	//	res := ZpAI(key, model, data)
+	//	log.Println(res)
+
+	defer util.Catch()
+	sess := Mgo.GetMgoConn()
+	defer Mgo.DestoryMongoConn(sess)
+	//requestData := make([]string, 0)
+	it := sess.DB(GF.Mongo.DB).C(GF.Mongo.Coll).Find(nil).Select(nil).Sort("-_id").Limit(20).Iter()
+	count := 0
+	var lines []string
+	var reportBuilder strings.Builder
+	// 正则表达式用于提取数据
+	//re := regexp.MustCompile(`title:(.*?),projectname:(.*?),id:(.*?),class:(.*?)`)
+	re := regexp.MustCompile(`title:(.*?),projectname:(.*?),id:(.*?),class:(.*?)(?:\s*$|\n)`)
+
+	for tmp := make(map[string]interface{}); it.Next(&tmp); count++ {
+		title := util.ObjToString(tmp["title"])
+		projectname := util.ObjToString(tmp["projectname"])
+		biddingID := mongodb.BsonIdToSId(tmp["_id"])
+		lines = append(lines, fmt.Sprintf("title:%s,projectname:%s,id:%s\n", title, projectname, biddingID))
+		if len(lines)%10 == 0 {
+			// 将 lines 的内容写入 reportBuilder
+			for _, line := range lines {
+				reportBuilder.WriteString(line)
+			}
+			report := reportBuilder.String()
+			resu, _ := ZpAI4(key, model, report)
+
+			splitLines := strings.Split(resu, `;`)
+			//results := []map[string]string{}
+			for _, line := range splitLines {
+				matches := re.FindStringSubmatch(line)
+				if len(matches) == 5 {
+					//result := map[string]string{
+					//	"title":       matches[1],
+					//	"projectname": matches[2],
+					//	"id":          matches[3],
+					//	"class":       matches[4],
+					//}
+					tags := make([]string, 0)
+					class := matches[4]
+					id := matches[3]
+					if id == "" || class == "" || class == "其他分类" {
+						continue
+					}
+					for _, v2 := range strings.Split(class, ",") {
+						if v2 == "车辆领域" {
+							tags = append(tags, "情报_车辆租赁")
+						} else if v2 == "安防领域" {
+							tags = append(tags, "情报_安防")
+						} else if v2 == "印务领域" {
+							tags = append(tags, "情报_印务商机")
+						} else if v2 == "环境领域" {
+							tags = append(tags, "情报_环境采购")
+						} else if v2 == "家具领域" {
+							tags = append(tags, "情报_家具招投标")
+						}
+					}
+					if len(tags) > 0 {
+						log.Println(tags, matches[1])
+					}
+				}
+			}
+			lines = lines[:0]
+		}
+	}
+	//
+	if len(lines) > 0 {
+		for _, line := range lines {
+			reportBuilder.WriteString(line)
+		}
+		report := reportBuilder.String()
+		resu, _ := ZpAI4(key, model, report)
+		splitLines := strings.Split(resu, "\n")
+		results := []map[string]string{}
+
+		for _, line := range splitLines {
+			matches := re.FindStringSubmatch(line)
+			if len(matches) == 5 {
+				result := map[string]string{
+					"title":       matches[1],
+					"projectname": matches[2],
+					"id":          matches[3],
+					"class":       matches[4],
+				}
+				results = append(results, result)
+			}
+		}
+
+		// 打印结果
+		for _, r := range results {
+			fmt.Println(r)
+		}
+	}
+
+}
+
+func TestZpAI4(t *testing.T) {
+	InitConfig()
+	Init()
+	key := "4d5206b1b297c1e7b77f9578edcb2cf7.TNU2i8G1oUNdR02i"
+	//key := "6c86cea8659ff1d33b161ea7213ea97c.m4OcENaRan8NeLSZ" //我自己的key
+	model := "glm-4-flash"
+
+	defer util.Catch()
+	sess := Mgo.GetMgoConn()
+	defer Mgo.DestoryMongoConn(sess)
+	where := map[string]interface{}{
+		"title": "数字警务安防设备招标公告",
+	}
+	it := sess.DB(GF.Mongo.DB).C(GF.Mongo.Coll).Find(where).Select(nil).Sort("-_id").Iter()
+	count := 0
+	re := regexp.MustCompile(`title:(.*?),projectname:(.*?),id:(.*?),class:(.*?)(?:\s*$|\n)`)
+	for tmp := make(map[string]interface{}); it.Next(&tmp); count++ {
+		if count%100 == 0 {
+			log.Println("current:", count, tmp["title"])
+		}
+
+		title := util.ObjToString(tmp["title"])
+		projectname := util.ObjToString(tmp["projectname"])
+		biddingID := mongodb.BsonIdToSId(tmp["_id"])
+		text := fmt.Sprintf("title:%s,projectname:%s,id:%s\n", title, projectname, biddingID)
+		resu, err := ZpAI4(key, model, text)
+		if err != nil {
+			log.Println(err)
+			continue
+		}
+		if err == nil {
+			splitLines := strings.Split(resu, `;`)
+			for _, line := range splitLines {
+				matches := re.FindStringSubmatch(line)
+				if len(matches) == 5 {
+					class := matches[4]
+					if class != "" && class != "其他分类" {
+						tags := make([]string, 0)
+						for _, v2 := range strings.Split(class, ",") {
+							if v2 == "车辆领域" {
+								tags = append(tags, "情报_车辆租赁")
+							} else if v2 == "安防领域" {
+								tags = append(tags, "情报_安防")
+							} else if v2 == "印务领域" {
+								tags = append(tags, "情报_印务商机")
+							} else if v2 == "环境领域" {
+								tags = append(tags, "情报_环境采购")
+							} else if v2 == "家具领域" {
+								tags = append(tags, "情报_家具招投标")
+							}
+						}
+						if len(tags) > 0 {
+							if biddingID != "" {
+								updateMgo := map[string]interface{}{
+									"tag_topinformation_zp": tags,
+									"topinformation_time":   time.Now().Unix(),
+								}
+								Mgo.UpdateById("bidding", biddingID, map[string]interface{}{"$set": updateMgo})
+								//更新es
+								updateEs := map[string]interface{}{
+									"tag_topinformation_zp": tags,
+								}
+								if GF.Esa.URL != "" {
+									err := Esa.UpdateDocument("bidding", biddingID, updateEs)
+									if err != nil && err.Error() != "Document not updated: noop" {
+										log.Println("esa update err", biddingID, err)
+									}
+								}
+
+								if GF.Esb.URL != "" {
+									err := Esb.UpdateDocument("bidding", biddingID, updateEs)
+									if err != nil && err.Error() != "Document not updated: noop" {
+										log.Println("esb update err", biddingID, err)
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+}

+ 286 - 0
bidding_tags/tools.go

@@ -1,7 +1,12 @@
 package main
 
 import (
+	"encoding/json"
+	"fmt"
+	zhipu "github.com/itcwc/go-zhipu/model_api"
+	"log"
 	"strings"
+	"time"
 )
 
 // IsInStringArray 判断数组中是否存在字符串
@@ -33,3 +38,284 @@ func removeDuplicates(strs []string) []string {
 	}
 	return result
 }
+
+// ZpAI 调用智普大模型
+func ZpAI(apiKey, model, data string) (rest map[string]interface{}) {
+	expireAtTime := int64(1719803252) // token 过期时间
+	//	sys := `
+	//	你是一位招投标行业的信息分类专家
+	//# 安防信息定义
+	//请根据以下定义,判断文本内容是否属于安防领域。安防领域涉及但不限于以下方面:
+	//视频监控:使用摄像头进行实时监控或录像存储;
+	//入侵检测:通过传感器或探测器检测非法入侵;
+	//安全警报:安装警报系统,如声音警报器或报警按钮;
+	//门禁系统:控制物理访问的门禁控制技术;
+	//防盗报警:安装用于检测盗窃行为的报警装置;
+	//周界防护:保护周界免受非法侵入的措施;
+	//智能安防解决方案:集成多种技术提供全面的安全解决方案;
+	//火灾报警与应急处理:火灾探测与警报系统,以及紧急应对措施;
+	//人员识别与追踪:使用生物识别或技术手段对人员进行识别和追踪;
+	//安全巡逻:定期或随机对区域进行安全巡逻;
+	//数据分析与风险评估:对安全数据进行分析以评估风险和制定策略。
+	//应急响应:在紧急情况下,如火灾、入侵等,进行快速响应和处置。
+	//安全咨询与服务:提供安全评估、风险评估、安全培训、安全系统设计等咨询服务。
+	//网络安全:保护计算机系统、网络和数据免受未经授权的访问和攻击。
+	//若文本内容明确提及或描述了上述任一安防相关概念、技术、设备、工程、应用或服务,请输出“true”。
+	//若文本内容不涉及上述任何一点,或信息不明确无法判断,请输出“false”。请确保仅基于文本内容直接判断,不进行任何联想或推测。
+	//文本内容如下:
+	//标题:`
+	//	text := sys + title
+	//
+	//	if projectName != "" {
+	//		text = text + ";项目名称:" + projectName
+	//	}
+	//
+	//	text = text + `#输出格式严格使用json(不用解释是或否的原因,直接输出结果):
+	//{"result":"true/false"}`
+
+	text := `我有以下类别:
+1. 车辆领域:根车辆相关的内容,车辆租赁、车辆购买等;
+2. 安防领域:跟安全防护相关的内容,如电子栅栏、安全锁、监控系统等;
+3. 印务领域:跟印刷、广告服务相关的内容;
+4. 环境领域:跟环境保护相关的内容,如电子废物处理、垃圾处理、生态污水处理等
+5. 家具领域:跟家具相关的内容,如办公桌、电脑桌、文件柜、人体工学椅等
+请根据以上分类,对我提供的文本内容的每一行数据进行分类。
+请根据以上类别定义,对我提供的文本内容的每一行数据进行分类;可以适当联想;但不要联网,不要发散,不要解释,你判断不准的,可以标识为其他分类,但不能有空缺。
+输出结果以JSON格式返回,格式如下:
+{
+  "result":[
+      {"title":"文本","projectname":"class","class":"分类1,分类2"},
+      {"title":"制造业","projectname":"食品制造业","class":"罐头食品制造"}
+    ]
+};
+同一个文本内容分到多个类别,class 用英文逗号拼接
+以下是文本内容:
+==============================
+`
+
+	text = text + data
+
+	originalValue := 0.01
+	originalValue2 := 0.7
+	mssage := zhipu.PostParams{
+		Model: model,
+		Messages: []zhipu.Message{
+			{
+				Role:    "user", // 消息的角色信息 详见文档
+				Content: text,
+			},
+		},
+		Temperature: &originalValue,
+		TopP:        &originalValue2,
+	}
+
+	postResponse, err := zhipu.BeCommonModel(expireAtTime, mssage, apiKey)
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
+
+	if choices, ok := postResponse["choices"].([]interface{}); ok {
+		if choice, ok2 := choices[0].(map[string]interface{}); ok2 {
+			if message, ok3 := choice["message"].(map[string]interface{}); ok3 {
+				if content, ok4 := message["content"].(string); ok4 {
+					content = strings.ReplaceAll(content, "\n", "")
+					content = strings.ReplaceAll(content, "json", "")
+					content = strings.ReplaceAll(content, "`", "")
+					err = json.Unmarshal([]byte(content), &rest)
+					if err != nil {
+						log.Println("Unmarshal err", err, "content:", content)
+					}
+				}
+			}
+		}
+	}
+	return
+}
+
+func ZpAI2(apiKey, model, data string) (rest map[string]interface{}) {
+	expireAtTime := int64(1719803252) // token 过期时间
+
+	text := `我有以下类别:
+1. 车辆领域:根车辆相关的内容,车辆租赁、车辆购买等;
+2. 安防领域:跟安全防护相关的内容,如电子栅栏、安全锁、监控系统等;
+3. 印务领域:跟印刷、广告服务相关的内容;
+4. 环境领域:跟环境保护相关的内容,如电子废物处理、垃圾处理、生态污水处理等
+5. 家具领域:跟家具相关的内容,如办公桌、电脑桌、文件柜、人体工学椅等
+请根据以上分类,对我提供的文本内容的每一行数据进行分类。
+请根据以上类别定义,对我提供的文本内容的每一行数据进行分类;可以适当联想;但不要联网,不要发散,不要解释,你判断不准的,可以标识为其他分类,但不能有空缺。
+输出结果以JSON格式返回,格式如下:
+{
+  "result":[
+      {"title":"文本","projectname":"class","id":"11111111111111111111",class":"分类1,分类2"},
+      {"title":"制造业","projectname":"食品制造业","id":"22222222222222222222","class":"罐头食品制造"}
+    ]
+};
+同一个文本内容分到多个类别,class 用英文逗号拼接
+以下是文本内容:
+==============================
+`
+
+	text = text + data
+
+	originalValue := 0.01
+	originalValue2 := 0.7
+	mssage := zhipu.PostParams{
+		Model: model,
+		Messages: []zhipu.Message{
+			{
+				Role:    "user", // 消息的角色信息 详见文档
+				Content: text,
+			},
+		},
+		Temperature: &originalValue,
+		TopP:        &originalValue2,
+	}
+
+	postResponse, err := zhipu.BeCommonModel(expireAtTime, mssage, apiKey)
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
+
+	if choices, ok := postResponse["choices"].([]interface{}); ok {
+		if choice, ok2 := choices[0].(map[string]interface{}); ok2 {
+			if message, ok3 := choice["message"].(map[string]interface{}); ok3 {
+				if content, ok4 := message["content"].(string); ok4 {
+					content = strings.ReplaceAll(content, "\n", "")
+					content = strings.ReplaceAll(content, "json", "")
+					content = strings.ReplaceAll(content, "`", "")
+					err = json.Unmarshal([]byte(content), &rest)
+					if err != nil {
+						log.Println("Unmarshal err", err, "content:", content)
+					}
+				}
+			}
+		}
+	}
+	return
+}
+
+// ZpAI3 单个文本调用
+func ZpAI3(apiKey, model, data string) (rest map[string]interface{}) {
+	expireAtTime := int64(1719803252) // token 过期时间
+
+	text := `我有以下类别:
+1. 车辆领域:根车辆相关的内容,车辆租赁、车辆购买等;
+2. 安防领域:跟安全防护相关的内容,如电子栅栏、安全锁、监控系统等;
+3. 印务领域:跟印刷、广告服务相关的内容;
+4. 环境领域:跟环境保护相关的内容,如电子废物处理、垃圾处理、生态污水处理等
+5. 家具领域:跟家具相关的内容,如办公桌、电脑桌、文件柜、人体工学椅等
+请根据以上分类,对我提供的文本内容的每一行数据进行分类。
+请根据以上类别定义,对我提供的文本内容的进行分类;可以适当联想;但不要联网,不要发散,不要解释,你判断不准的,可以标识为其他分类,但不能有空缺。
+输出结果以JSON格式返回,格式如下:
+ {"title":"制造业","projectname":"食品制造业","class":"罐头食品制造"}
+;
+同一个文本内容分到多个类别,class 用英文逗号拼接,例如:
+ {"title":"制造业","projectname":"食品制造业","class":"罐头食品制造,食品加工"}
+以下是文本内容:
+==============================
+`
+
+	text = text + data
+
+	originalValue := 0.01
+	originalValue2 := 0.7
+	mssage := zhipu.PostParams{
+		Model: model,
+		Messages: []zhipu.Message{
+			{
+				Role:    "user", // 消息的角色信息 详见文档
+				Content: text,
+			},
+		},
+		Temperature: &originalValue,
+		TopP:        &originalValue2,
+	}
+
+	postResponse, err := zhipu.BeCommonModel(expireAtTime, mssage, apiKey)
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
+
+	if choices, ok := postResponse["choices"].([]interface{}); ok {
+		if choice, ok2 := choices[0].(map[string]interface{}); ok2 {
+			if message, ok3 := choice["message"].(map[string]interface{}); ok3 {
+				if content, ok4 := message["content"].(string); ok4 {
+					content = strings.ReplaceAll(content, "\n", "")
+					content = strings.ReplaceAll(content, "json", "")
+					content = strings.ReplaceAll(content, "`", "")
+					err = json.Unmarshal([]byte(content), &rest)
+					if err != nil {
+						log.Println("Unmarshal err", err, "content:", content)
+					}
+				}
+			}
+		}
+	}
+	return
+}
+
+// ZpAI4 文本格式返回
+func ZpAI4(apiKey, model, data string) (rest string, err error) {
+	expireAtTime := int64(1735660800) // token 过期时间
+
+	text := `我有以下类别:
+1. 车辆领域:根车辆相关的内容,车辆租赁、车辆购买等;
+2. 安防领域:跟安全防护相关的内容,如电子栅栏、安全锁、监控系统等;
+3. 印务领域:跟印刷、广告服务相关的内容;
+4. 环境领域:跟环境保护相关的内容,如电子废物处理、垃圾处理、生态污水处理等
+5. 家具领域:跟家具相关的内容,如办公桌、电脑桌、文件柜、人体工学椅等
+6. 其他分类:不属于以上分类或者判断不出来的分类属于其他分类
+请根据以上分类,对我提供的文本内容的每一行数据进行分类;不要联想,不要联网,不要发散,不要解释,你判断不准的,可以标识为其他分类。
+请根据以上类别定义,对我提供的文本内容的每一行数据进行分类;可以适当联想;但不要联网,不要发散,不要解释,你判断不准的,可以标识为其他分类,但不能有空缺。
+请按照文本形式输出,每一条数据用\n换行符分割,没有到class结束前不要给我换行,class内容结尾用英文分号";"。每条数据只要返回一个结果就好,不要重复返回;并且一条完整的数据要放在一行,不要拆分开。输出内容包括:
+title:文本,projectname:文本,id:13123123,class:文本;
+title:文本,projectname:文本,id:13123123,class:文本;
+同一个文本内容分到多个类别,类别用逗号拼接
+以下是文本内容:
+==============================
+
+`
+
+	text = text + data
+
+	originalValue := 0.01
+	originalValue2 := 0.7
+	mssage := zhipu.PostParams{
+		Model: model,
+		Messages: []zhipu.Message{
+			{
+				Role:    "user", // 消息的角色信息 详见文档
+				Content: text,
+			},
+		},
+		Temperature: &originalValue,
+		TopP:        &originalValue2,
+	}
+
+	postResponse, err := zhipu.BeCommonModel(expireAtTime, mssage, apiKey, time.Minute*8)
+	if err != nil {
+		log.Println("请求智普失败", err)
+		return
+	}
+
+	if choices, ok := postResponse["choices"].([]interface{}); ok {
+		if choice, ok2 := choices[0].(map[string]interface{}); ok2 {
+			if message, ok3 := choice["message"].(map[string]interface{}); ok3 {
+				if content, ok4 := message["content"].(string); ok4 {
+					return content, nil
+					//content = strings.ReplaceAll(content, "\n", "")
+					//content = strings.ReplaceAll(content, "json", "")
+					//content = strings.ReplaceAll(content, "`", "")
+					//err = json.Unmarshal([]byte(content), &rest)
+					//if err != nil {
+					//	log.Println("Unmarshal err", err, "content:", content)
+					//}
+				}
+			}
+		}
+	}
+	return
+}

+ 1 - 1
project_portrait/main.go

@@ -27,7 +27,7 @@ var (
 	portraitMgo   = ""                // MongoDB 的表名
 	GF            GlobalConf
 	// 情报分类一级标签
-	topInfos = []string{"情报_物业", "情报_环境采购", "情报_印务商机", "情报_家具招投标", "情报_车辆租赁"}
+	topInfos = []string{"情报_物业", "情报_环境采购", "情报_印务商机", "情报_家具招投标", "情报_车辆租赁", "情报_安防"}
 )
 
 type PortraitData struct {