Browse Source

feat:xiugai

wangchuanjin 5 months ago
parent
commit
6882dab988

+ 6 - 4
api/aiSearch/v1/aiSearchApi.go

@@ -63,15 +63,17 @@ type ProblemConfigurationRes struct {
 type ChatReq struct {
 	g.Meta   `path:"/chat" tags:"AiSearch" method:"post" summary:"聊天"`
 	SId      string `json:"sId" v:"required" dc:"当前会话id"`
-	Content  string `json:"content" v:"required" dc:"用户发送内容"`
 	Question string `json:"question" v:"required" dc:"用户发送内容"`
 	Item     int    `json:"item" v:"required" dc:"分类"`
 }
 
 type ChatRes struct {
-	Status int           `json:"status" dc:"状态;0:服务器繁忙 1:成功"`
-	Count  int           `json:"count" dc:"列表长度"`
-	List   []*ResBidding `json:"list" dc:"答案列表"`
+	Id              string                 `json:"id" dc:"id"`
+	Status          int                    `json:"status" dc:"状态;0:服务器繁忙 1:成功"`
+	Count           int                    `json:"count" dc:"列表长度"`
+	List            []*ResBidding          `json:"list" dc:"答案列表"`
+	LargeModelName  string                 `json:"largeModelName" dc:"大模型名称"`
+	LargeModelReply map[string]interface{} `json:"largeModelReply" dc:"大模型回复"`
 }
 
 type BiddingListReq struct {

+ 4 - 0
go.mod

@@ -51,6 +51,8 @@ require (
 	github.com/gorilla/websocket v1.5.3 // indirect
 	github.com/grokify/html-strip-tags-go v0.1.0 // indirect
 	github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect
+	github.com/jinzhu/inflection v1.0.0 // indirect
+	github.com/jinzhu/now v1.1.1 // indirect
 	github.com/josharian/intern v1.0.0 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
 	github.com/klauspost/compress v1.16.7 // indirect
@@ -118,6 +120,8 @@ require (
 	gopkg.in/inf.v0 v0.9.1 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
+	gorm.io/driver/mysql v1.0.5 // indirect
+	gorm.io/gorm v1.21.3 // indirect
 	jygit.jydev.jianyu360.cn/ApplicationCenter/publicService v0.0.0-20231023011746-38dc3b6aded8 // indirect
 	k8s.io/api v0.29.3 // indirect
 	k8s.io/apimachinery v0.29.3 // indirect

+ 4 - 0
go.sum

@@ -410,7 +410,9 @@ github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/U
 github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
 github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc=
 github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
+github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
 github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
+github.com/jinzhu/now v1.1.1 h1:g39TucaRWyV3dwDO++eEc6qf8TVIQ/Da48WmqjZ3i7E=
 github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
 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=
@@ -1174,11 +1176,13 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gorm.io/driver/mysql v1.0.4/go.mod h1:MEgp8tk2n60cSBCq5iTcPDw3ns8Gs+zOva9EUhkknTs=
+gorm.io/driver/mysql v1.0.5 h1:WAAmvLK2rG0tCOqrf5XcLi2QUwugd4rcVJ/W3aoon9o=
 gorm.io/driver/mysql v1.0.5/go.mod h1:N1OIhHAIhx5SunkMGqWbGFVeh4yTNWKmMo1GOAsohLI=
 gorm.io/driver/postgres v1.0.8/go.mod h1:4eOzrI1MUfm6ObJU/UcmbXyiHSs8jSwH95G5P5dxcAg=
 gorm.io/driver/sqlite v1.1.4/go.mod h1:mJCeTFr7+crvS+TRnWc5Z3UvwxUN1BGBLMrf5LA9DYw=
 gorm.io/gorm v1.20.7/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
 gorm.io/gorm v1.20.12/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
+gorm.io/gorm v1.21.3 h1:qDFi55ZOsjZTwk5eN+uhAmHi8GysJ/qCTichM/yO7ME=
 gorm.io/gorm v1.21.3/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
 honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

+ 42 - 59
internal/controller/aiSearch/aiSearch_v1_chat.go

@@ -19,6 +19,12 @@ import (
 	"github.com/gogf/gf/v2/util/gconv"
 )
 
+const (
+	DateTimeMill     = "Y-m-d h:i:s.u"
+	largeModelDouBao = "豆包"
+	largeModelZhiPu  = "智普"
+)
+
 func (c *ControllerV1) Chat(ctx context.Context, req *v1.ChatReq) (res *v1.ChatRes, err error) {
 	res = &v1.ChatRes{Status: 0}
 	sid := gconv.Int64(SE.Decode4HexByCheck(req.SId))
@@ -31,12 +37,11 @@ func (c *ControllerV1) Chat(ctx context.Context, req *v1.ChatReq) (res *v1.ChatR
 		g.Log().Error(ctx, "获取session出错", sessErr)
 		return
 	}
-	startTime := gtime.Now().Format("Y-m-d h:m:s.u")
+	startTime := gtime.Now().Format(DateTimeMill)
 	answerStatus := 0
-	prompt := fmt.Sprintf(g.Cfg("ai_search.yaml").MustGet(ctx, "doubaoPrompt").String(), gtime.Now().Format("Ymd"), req.Question)
-	largeModel := "doubao"
+	largeModel := largeModelDouBao
 	callLogs := g.List{}
-	content, largeModelReply, err, isLimit := c.doubao(ctx, prompt)
+	content, largeModelReply, err, isLimit := c.doubao(ctx, largeModelDouBao, req.Question)
 	if !isLimit {
 		large_model_success := 1
 		error_msg := ""
@@ -49,15 +54,14 @@ func (c *ControllerV1) Chat(ctx context.Context, req *v1.ChatReq) (res *v1.ChatR
 			"large_model":           largeModel,
 			"large_model_reply":     largeModelReply,
 			"large_model_starttime": startTime,
-			"large_model_endtime":   gtime.Now().Format("Y-m-d h:m:s.u"),
+			"large_model_endtime":   gtime.Now().Format(DateTimeMill),
 			"large_model_success":   large_model_success,
 			"error_msg":             error_msg,
 		})
 	}
 	if isLimit || err != nil {
-		prompt = fmt.Sprintf(g.Cfg("ai_search.yaml").MustGet(ctx, "zhipuPrompt").String(), gtime.Now().Format("Ymd"), req.Question)
-		content, largeModelReply, err, _ = c.zhipu(ctx, prompt)
-		largeModel = "zhipu"
+		content, largeModelReply, err, _ = c.zhipu(ctx, largeModelZhiPu, req.Question)
+		largeModel = largeModelZhiPu
 		large_model_success := 1
 		error_msg := ""
 		if err != nil {
@@ -69,12 +73,12 @@ func (c *ControllerV1) Chat(ctx context.Context, req *v1.ChatReq) (res *v1.ChatR
 			"large_model":           largeModel,
 			"large_model_reply":     largeModelReply,
 			"large_model_starttime": startTime,
-			"large_model_endtime":   gtime.Now().Format("Y-m-d h:m:s.u"),
+			"large_model_endtime":   gtime.Now().Format(DateTimeMill),
 			"large_model_success":   large_model_success,
 			"error_msg":             error_msg,
 		})
 	}
-	large_model_endtime := gtime.Now().Format("Y-m-d h:m:s.u")
+	large_model_endtime := gtime.Now().Format(DateTimeMill)
 	if err == nil {
 		answerStatus = 1
 	} else {
@@ -104,15 +108,17 @@ func (c *ControllerV1) Chat(ctx context.Context, req *v1.ChatReq) (res *v1.ChatR
 			v.InfoId = EncodeArticleId2ByCheck(v.InfoId)
 		}
 	}
+	var chatId int64
 	if err := g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
-		chatId, chatErr := tx.InsertAndGetId("ai_search_chat", g.Map{
+		var chatErr error
+		chatId, chatErr = tx.InsertAndGetId("ai_search_chat", g.Map{
 			"position_id":         sess.PositionId,
 			"item":                req.Item,
 			"question":            req.Question,
 			"answer":              answer,
 			"starttime":           startTime,
 			"large_model_endtime": large_model_endtime,
-			"endtime":             gtime.Now().Format("Y-m-d h:m:s.u"),
+			"endtime":             gtime.Now().Format(DateTimeMill),
 			"es_query":            query,
 			"list_count":          len(list),
 			"session_id":          sid,
@@ -165,8 +171,11 @@ func (c *ControllerV1) Chat(ctx context.Context, req *v1.ChatReq) (res *v1.ChatR
 		}
 		return nil
 	}); err == nil {
+		res.Id = SE.Encode2HexByCheck(gconv.String(chatId))
 		res.Status = 1
 		res.List = bestBids
+		res.LargeModelName = largeModel
+		res.LargeModelReply = gconv.Map(largeModelReply)
 	} else {
 		g.Log().Error(ctx, sess.PositionId, "保存数据库出错", err)
 	}
@@ -174,15 +183,9 @@ func (c *ControllerV1) Chat(ctx context.Context, req *v1.ChatReq) (res *v1.ChatR
 }
 
 //调用豆包大模型
-func (c *ControllerV1) doubao(ctx context.Context, content string) (string, string, error, bool) {
-	count, err := g.Redis("main").Incr(ctx, fmt.Sprintf("aiSearch_doubaoCall_%s", gtime.Now().Format("Ymd")))
-	if err != nil {
-		g.Log().Error(ctx, "从redis获取doubao调用次数出错", err)
-		return "", "", err, true
-	} else if doubaoCallMax := g.Cfg("ai_search.yaml").MustGet(ctx, "doubaoCallMax").Int64(); count > doubaoCallMax {
-		g.Log().Info(ctx, "doubao调用次数达到上限", doubaoCallMax, count)
-		return "", "", nil, true
-	}
+//{"choices":[{"finish_reason":"stop","index":0,"logprobs":null,"message":{"content":"```json\n{\n  \"关键词\": {\n    \"选择\": [\"华为\"],\n    \"排除\": []\n  },\n  \"发布时间范围\": \"20250128-20250227\",\n  \"信息类型\": [\"招标公告\"],\n  \"地区\": {\n    \"选择\": [],\n    \"排除\": []\n  },\n  \"金额\": \"不限\",\n  \"搜索范围\": [\"标题\", \"正文\"],\n  \"附件\": \"不限\",\n  \"匹配模式\": \"精准匹配\",\n  \"中标单位\": \"不限\",\n  \"采购单位\": \"华为\"\n}\n```","role":"assistant"}}],"created":1740638708,"id":"02174063870434056d8eac7f9446a6e5013632558f9a2392ad2ee","model":"deepseek-v3-241226","object":"chat.completion","usage":{"completion_tokens":115,"prompt_tokens":1036,"total_tokens":1151,"prompt_tokens_details":{"cached_tokens":0},"completion_tokens_details":{"reasoning_tokens":0}}}
+func (c *ControllerV1) doubao(ctx context.Context, largeModel, question string) (string, string, error, bool) {
+	content := fmt.Sprintf(g.Cfg("ai_search.yaml").MustGet(ctx, "doubaoPrompt").String(), gtime.Now().Format("Ymd"), question)
 	// 构造请求数据
 	messages := []map[string]interface{}{}
 	messages = append(messages, map[string]interface{}{
@@ -196,19 +199,13 @@ func (c *ControllerV1) doubao(ctx context.Context, content string) (string, stri
 		"top_p":       0.7,
 		"messages":    messages,
 	}
-	return c.post(ctx, "doubao", "https://ark.cn-beijing.volces.com/api/v3/chat/completions", "3dd861bf-b8a7-41d4-bb0b-5076362c572d", requestData)
+	return c.post(ctx, largeModel, "aiSearch_doubaoCall_%s", "doubaoCallMax", "https://ark.cn-beijing.volces.com/api/v3/chat/completions", "3dd861bf-b8a7-41d4-bb0b-5076362c572d", requestData)
 }
 
 //调用智普大模型
-func (c *ControllerV1) zhipu(ctx context.Context, content string) (string, string, error, bool) {
-	count, err := g.Redis("main").Incr(ctx, fmt.Sprintf("aiSearch_zhipuCall_%s", gtime.Now().Format("YYYYmmdd")))
-	if err != nil {
-		g.Log().Error(ctx, "从redis获取zhipu调用次数出错", err)
-		return "", "", err, true
-	} else if doubaoCallMax := g.Cfg("ai_search.yaml").MustGet(ctx, "zhipuCallMax").Int64(); count > doubaoCallMax {
-		g.Log().Info(ctx, "zhipu调用次数达到上限", doubaoCallMax, count)
-		return "", "", nil, true
-	}
+//{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"```json\n{\n  \"关键词\": {\n    \"选择\": [\"华为\"]\n  },\n  \"发布时间范围\": \"20250201-20250227\",\n  \"信息类型\": [\"招标公告\"],\n  \"地区\": {\n    \"选择\": []\n  },\n  \"金额\": \"不限\",\n  \"搜索范围\": [\"标题\", \"正文\"],\n  \"附件\": \"不限\",\n  \"匹配模式\": \"精准匹配\",\n  \"中标单位\": \"不限\",\n  \"采购单位\": \"不限\"\n}\n```","role":"assistant"}}],"created":1740639272,"id":"20250227145429c1507e742fc643f1","model":"glm-4-flash","request_id":"20250227145429c1507e742fc643f1","usage":{"completion_tokens":110,"prompt_tokens":1033,"total_tokens":1143}}
+func (c *ControllerV1) zhipu(ctx context.Context, largeModel, question string) (string, string, error, bool) {
+	content := fmt.Sprintf(g.Cfg("ai_search.yaml").MustGet(ctx, "zhipuPrompt").String(), gtime.Now().Format("Ymd"), question)
 	// 构造请求数据
 	messages := []map[string]interface{}{}
 	messages = append(messages, map[string]interface{}{
@@ -222,51 +219,37 @@ func (c *ControllerV1) zhipu(ctx context.Context, content string) (string, strin
 		"temperature": 0.1,
 		"max_tokens":  4096,
 	}
-	return c.post(ctx, "zhipu", "https://open.bigmodel.cn/api/paas/v4/chat/completions", "3d84d30b7ab4c94dbf71853cb7e44719.hLLS4CA2MqVQs6kR", requestData)
+	return c.post(ctx, largeModel, "aiSearch_zhipuCall_%s", "zhipuCallMax", "https://open.bigmodel.cn/api/paas/v4/chat/completions", "3d84d30b7ab4c94dbf71853cb7e44719.hLLS4CA2MqVQs6kR", requestData)
 }
 
-func (c *ControllerV1) post(ctx context.Context, t, apiURL, pass string, requestData map[string]interface{}) (string, string, error, bool) {
-	ddd := `{
-"关键词": {
-"选择": ["软件"],
-"排除": []
-},
-"发布时间范围": "20210126-20250226",
-"搜索范围": ["标题", "正文"],
-"匹配模式": "精准匹配",
-"信息类型": "招标公告",
-"地区": {
-"选择": ["广东", "广西", "海南","北京"],
-"排除": []
-},
-"金额": "0-2000万",
-"采购单位联系方式": "不限",
-"中标单位联系方式": "不限",
-"附件": "不限",
-"采购单位": "不限",
-"中标单位": "不限",
-"招标代理": "不限"
-}`
-	return ddd, "", nil, false
+func (c *ControllerV1) post(ctx context.Context, largeModel, redisKey, callMaxConf, apiURL, pass string, requestData map[string]interface{}) (string, string, error, bool) {
+	count, err := g.Redis("main").Incr(ctx, fmt.Sprintf(redisKey, gtime.Now().Format("Ymd")))
+	if err != nil {
+		g.Log().Error(ctx, largeModel, "从redis获取调用次数出错", err)
+		return "", "", err, true
+	} else if callMax := g.Cfg("ai_search.yaml").MustGet(ctx, callMaxConf).Int64(); count > callMax {
+		g.Log().Info(ctx, largeModel, "调用次数达到上限", callMax, count)
+		return "", "", nil, true
+	}
 	resp, err := g.Client().Timeout(time.Duration(g.Cfg("ai_search.yaml").MustGet(ctx, "timeout").Int())*time.Second).
 		SetHeader("Authorization", fmt.Sprintf("Bearer %s", pass)).
 		ContentType("application/json").
 		Post(ctx, apiURL, requestData)
 	if err != nil {
-		g.Log().Error(ctx, t, "请求出错", err)
+		g.Log().Error(ctx, largeModel, "请求出错", err)
 		return "", "", err, false
 	}
 	defer resp.Body.Close()
 	b, be := ioutil.ReadAll(resp.Body)
 	if be != nil {
-		g.Log().Error(ctx, t, "gjson.LoadJson出错", be)
+		g.Log().Error(ctx, largeModel, "gjson.LoadJson出错", be)
 		return "", "", err, false
 	}
 	largeModelReply := string(b)
-	g.Log().Info(ctx, t, "请求回复", largeModelReply)
+	g.Log().Info(ctx, largeModel, "请求回复", largeModelReply)
 	r, re := gjson.LoadJson(b)
 	if re != nil {
-		g.Log().Error(ctx, t, largeModelReply, "gjson.LoadJson出错", re)
+		g.Log().Error(ctx, largeModel, largeModelReply, "gjson.LoadJson出错", re)
 		return "", largeModelReply, err, false
 	}
 	content := ""

+ 142 - 180
internal/model/bidSearch/bidSearch.go

@@ -2,6 +2,7 @@ package bidSearch
 
 import (
 	"aiChat/api/aiSearch/v1"
+	"aiChat/utility"
 	"context"
 	"fmt"
 	"strconv"
@@ -10,6 +11,7 @@ import (
 
 	. "app.yhyue.com/moapp/jybase/common"
 	elastic "app.yhyue.com/moapp/jybase/es"
+	"app.yhyue.com/moapp/jybase/mapping"
 	"github.com/gogf/gf/v2/encoding/gjson"
 	"github.com/gogf/gf/v2/frame/g"
 	"github.com/gogf/gf/v2/os/gtime"
@@ -22,7 +24,6 @@ const (
 	QueryBoolShould         = `{"bool":{"should":[%s],"minimum_should_match": 1}}`
 	queryBoolMustBoolShould = `{"bool":{"must":[{"range":{"bidamount":{%s}}}]}},{"bool":{"must":[{"range":{"budget":{%s}}}],"must_not":[{"range":{"bidamount":{"gte":-1}}}]}}`
 	QueryBoolMustTermBool   = `{"bool": {"must": [{ "term": {"%s": %t }}]}}`
-	QueryBoolMustA          = `{"bool":{"must":[{"terms":{"%s":[%s]}}]}}`
 	queryExists             = `{"constant_score":{"filter":{"exists":{"field":"%s"}}}}`
 	gte                     = `"gte": %s`
 	lte                     = `"lte": %s`
@@ -30,6 +31,8 @@ const (
 	TYPE                    = "bidding"
 	BidSearchSort           = `{"dataweight":"desc","publishtime":"desc"}`
 	BidSearchFieldBase      = `"_id","title","publishtime","dataweight","toptype","subtype","type","area","city","s_subscopeclass","bidamount","budget","buyerclass","isValidFile","district"` //搜索列表基础字段
+	QueryTerms              = `{"terms":{"%s":["%s"]}}`
+	QueryTermsDh            = `","`
 )
 
 var (
@@ -45,30 +48,30 @@ var (
 )
 
 type BidSearch struct {
-	ctx             context.Context
+	Ctx             context.Context
 	PositionId      int64
-	PageNum         int64  //当前页码
-	PageSize        int64  //每页数量
-	Province        string //省份
-	City            string //城市
-	Subtype         string //信息类型-二级
-	TopType         string //信息类型-一级分类
-	PublishTime     string //发布时间
-	SelectType      string //搜索范围:标题;正文等
-	Price           string //价格
-	Industry        string //行业
-	BuyerClass      string //采购单位类型
-	BuyerTel        string //采购单位联系方式
-	WinnerTel       string //中标单位联系方式
-	FileExists      string //是否有附件
-	WordsMode       int64  //搜索关键词模式;默认0:包含所有,1:包含任意
-	KeyWords        string //关键词:多个空格隔开(主)
-	AdditionalWords string //关键词:附加关键词(副:五组,每组最多15个字符)
-	ExclusionWords  string //关键词:排除词(副:五组,每组最多15个字符)
-	District        string //区县
-	Buyer           string //采购单位
-	Winner          string //中标企业
-	Agency          string //代理机构
+	PageNum         int64    //当前页码
+	PageSize        int64    //每页数量
+	Province        []string //省份
+	City            []string //城市
+	Subtype         []string //信息类型-二级
+	TopType         []string //信息类型-一级分类
+	PublishTime     string   //发布时间
+	SelectType      string   //搜索范围:标题;正文等
+	Price           string   //价格
+	Industry        []string //行业
+	BuyerClass      []string //采购单位类型
+	BuyerTel        string   //采购单位联系方式 是或否
+	WinnerTel       string   //中标单位联系方式 是或否
+	FileExists      string   //是否有附件
+	WordsMode       int64    //搜索关键词模式;默认0:包含所有,1:包含任意
+	KeyWords        string   //关键词:多个空格隔开(主)
+	AdditionalWords string   //关键词:附加关键词(副:五组,每组最多15个字符)
+	ExclusionWords  string   //关键词:排除词(副:五组,每组最多15个字符)
+	District        []string //区县
+	Buyer           string   //采购单位
+	Winner          string   //中标企业
+	Agency          string   //代理机构
 }
 
 func NewBidSearch(ctx context.Context, positionId int64, content string) (*BidSearch, error) {
@@ -77,24 +80,67 @@ func NewBidSearch(ctx context.Context, positionId int64, content string) (*BidSe
 		g.Log().Error(ctx, positionId, "查询条件转换出错", e)
 		return nil, e
 	}
+	var paramFilter = func(v string) string {
+		if v == "全部" || v == "不限" {
+			return ""
+		}
+		return strings.ReplaceAll(v, " ", "")
+	}
+	//
 	keyWords, exclusionWords := []string{}, []string{}
 	if keyWordJson := c.GetJson("关键词"); keyWordJson != nil {
 		keyWords = keyWordJson.Get("选择").Strings()
 		exclusionWords = keyWordJson.Get("排除").Strings()
 	}
-	area, city := []string{}, []string{}
+	//
+	area, city, district := []string{}, []string{}, []string{}
 	if areaJson := c.GetJson("地区"); areaJson != nil {
-		area = areaJson.Get("选择").Strings()
+		for _, v := range areaJson.Get("选择").Strings() {
+			vvs := strings.Split(v, " ")
+			for kk, vv := range vvs {
+				vv = paramFilter(vv)
+				if vv == "" {
+					continue
+				}
+				vvv := strings.TrimSuffix(vv, "省")
+				_, ok := mapping.BidCodeMapping.Area[vvv]
+				if ok {
+					area = append(area, vvv)
+					continue
+				}
+				_, ok = mapping.BidCodeMapping.City[vv]
+				if ok {
+					city = append(city, vv)
+				}
+				if kk < 0 && mapping.BidCodeMapping.District[vvs[kk-1]] != nil {
+					_, ok = mapping.BidCodeMapping.District[vvs[kk-1]][vv]
+					if ok {
+						district = append(district, vv)
+					}
+				}
+				if !ok {
+					_, ok = utility.AllDistrict[vv]
+					if ok {
+						district = append(district, vv)
+					}
+				}
+			}
+		}
 		//exclusionArea = areaJson.Get("排除").Strings()
 	}
 	subtype, topType := []string{}, []string{}
-	publishTime := "lately-30"
-	var paramFilter = func(v string) string {
-		if v == "全部" || v == "不限" {
-			return ""
+	for _, v := range c.Get("信息类型").Strings() {
+		v = paramFilter(v)
+		if vv, ok := topTypeMap[v]; ok {
+			topType = append(topType, vv)
+		} else if _, ok := mapping.BidCodeMapping.Toptype[v]; ok {
+			topType = append(topType, v)
+		} else if _, ok := mapping.BidCodeMapping.Subtype[v]; ok {
+			subtype = append(subtype, v)
 		}
-		return strings.ReplaceAll(v, " ", "")
 	}
+	publishTime := "lately-30"
+	//
 	pt := paramFilter(c.Get("发布时间范围").String())
 	if pts := strings.Split(pt, "-"); len(pts) == 2 {
 		pt_s, pt_s_e := gtime.StrToTimeFormat(pts[0], "Ymd")
@@ -105,26 +151,31 @@ func NewBidSearch(ctx context.Context, positionId int64, content string) (*BidSe
 			publishTime = fmt.Sprintf("%d-%d", pt_s.Unix(), pt_e.Unix())
 		}
 	}
-	price := strings.ReplaceAll(paramFilter(c.Get("金额").String()), "万", "")
-	industry := paramFilter(c.Get("industry").String())
-	buyerClass := paramFilter(c.Get("采购单位类型").String())
-	buyerTel := paramFilter(c.Get("采购单位联系方式").String())
-	winnerTel := paramFilter(c.Get("中标单位联系方式").String())
+	//
+	price := paramFilter(c.Get("金额").String())
+	price = strings.ReplaceAll(price, "以上", "-")
+	price = strings.ReplaceAll(price, "万", "")
+	//
 	selectType := []string{}
-	for _, t := range strings.Split(paramFilter(c.Get("搜索范围").String()), ",") {
-		if t == "content" {
+	for _, t := range c.Get("搜索范围").Strings() {
+		t = paramFilter(t)
+		if t == "正文" {
 			selectType = append(selectType, "detail")
 		} else if t == "buyer" {
 			selectType = append(selectType, "buyer.mbuyer")
-		} else if t == "winner" {
+		} else if t == "中标企业" {
 			selectType = append(selectType, "s_winner.mwinner")
 		} else if t == "agency" {
 			selectType = append(selectType, "agency.magency")
-		} else if t == "title" {
+		} else if t == "标题" {
 			selectType = append(selectType, "title")
-		} else if t == "ppa" {
-			selectType = append(selectType, []string{"purchasing", "projectnamb.pname"}...)
-		} else if t == "file" { //dev4.7.8 标讯优化:搜索范围附件-》全部用户可用
+		} else if t == "项目名称/标的物" {
+			selectType = append(selectType, "purchasing", "projectnamb.pname")
+		} else if t == "项目名称" {
+			selectType = append(selectType, "projectnamb.pname")
+		} else if t == "标的物" {
+			selectType = append(selectType, "purchasing")
+		} else if t == "附件" { //dev4.7.8 标讯优化:搜索范围附件-》全部用户可用
 			selectType = append(selectType, "filetext")
 		}
 	}
@@ -136,26 +187,27 @@ func NewBidSearch(ctx context.Context, positionId int64, content string) (*BidSe
 		wordsMode = 1
 	}
 	bs := &BidSearch{
+		Ctx:             ctx,
 		PositionId:      positionId,
 		PageNum:         0,                                                                //当前页码
 		PageSize:        g.Cfg("ai_search.yaml").MustGet(ctx, "allBidListMaxLen").Int64(), //每页数量
-		Province:        strings.Join(area, ","),                                          //省份
-		City:            strings.Join(city, ","),                                          //城市
-		Subtype:         strings.Join(subtype, ","),                                       //信息类型-二级
-		TopType:         strings.Join(topType, ","),                                       //信息类型-一级分类
+		Province:        area,                                                             //省份
+		City:            city,                                                             //城市
+		Subtype:         subtype,                                                          //信息类型-二级
+		TopType:         topType,                                                          //信息类型-一级分类
 		PublishTime:     publishTime,                                                      //发布时间
 		SelectType:      strings.Join(selectType, ","),                                    //搜索范围:标题;正文等
 		Price:           price,                                                            //价格
-		Industry:        industry,                                                         //行业
-		BuyerClass:      buyerClass,                                                       //采购单位类型
-		BuyerTel:        buyerTel,                                                         //采购单位联系方式
-		WinnerTel:       winnerTel,                                                        //中标单位联系方式
+		Industry:        nil,                                                              //行业
+		BuyerClass:      nil,                                                              //采购单位类型
+		BuyerTel:        paramFilter(c.Get("采购单位联系方式").String()),                          //采购单位联系方式
+		WinnerTel:       paramFilter(c.Get("中标单位联系方式").String()),                          //中标单位联系方式
 		FileExists:      "",                                                               //是否有附件
 		WordsMode:       wordsMode,                                                        //搜索关键词模式;默认0:包含所有,1:包含任意
 		KeyWords:        strings.Join(keyWords, " "),                                      //关键词:多个空格隔开(主)
 		AdditionalWords: "",                                                               //关键词:附加关键词(副:五组,每组最多15个字符)
 		ExclusionWords:  strings.Join(exclusionWords, ","),                                //关键词:排除词(副:五组,每组最多15个字符)
-		District:        "",
+		District:        district,
 		Buyer:           paramFilter(c.Get("采购单位").String()),
 		Winner:          paramFilter(c.Get("中标企业").String()),
 		Agency:          paramFilter(c.Get("招标代理").String()),
@@ -199,14 +251,14 @@ func (b *BidSearch) Search() (string, []*v1.ResBidding) {
 
 // GetSearchQuery  整理关键词等查询条件
 func (b *BidSearch) GetSearchQuery() (qstr string) {
-	mustQuery := b.MustQuery()
+	musts := b.MustQuery()
 	var (
 		//搜索范围是否只有附件
 		//搜索范围只选择附件,是否有附件条件无效;
-		isFileSearch                            = b.SelectType == "filetext"
-		wordsMusts, wordsShould, musts, mustNot []string
-		findFields                              string
-		selectTypeArr                           = strings.Split(b.SelectType, ",")
+		isFileSearch                     = b.SelectType == "filetext"
+		wordsMusts, wordsShould, mustNot []string
+		findFields                       string
+		selectTypeArr                    = strings.Split(b.SelectType, ",")
 	)
 	if selectTypeArr == nil || len(selectTypeArr) == 0 {
 		findFields = `"title"`
@@ -214,9 +266,6 @@ func (b *BidSearch) GetSearchQuery() (qstr string) {
 		findFields = fmt.Sprintf(`"%s"`, strings.Join(selectTypeArr, "\",\""))
 	}
 	switchBool := strings.Contains(findFields, "detail") && strings.Contains(findFields, "title")
-	if mustQuery != "" {
-		musts = append(musts, mustQuery)
-	}
 	//采购单位
 	if b.Buyer != "" {
 		musts = append(musts, b.GetMatchArrSql("buyer.mbuyer", strings.Split(b.Buyer, ",")...))
@@ -330,8 +379,8 @@ func (b *BidSearch) GetSearchQuery() (qstr string) {
 		mustNot = append(mustNot, fmt.Sprintf(QueryBoolShould, strings.Join(notKeyMustNot, ",")))
 	}
 	//行业
-	if b.Industry != "" {
-		musts = append(musts, fmt.Sprintf(QueryBoolMustA, "s_subscopeclass", `"`+strings.ReplaceAll(b.Industry, ",", `","`)+`"`))
+	if len(b.Industry) > 0 {
+		musts = append(musts, fmt.Sprintf(QueryTerms, "s_subscopeclass", strings.Join(b.Industry, QueryTermsDh)))
 	}
 	//价格
 	if b.Price != "" && len(strings.Split(b.Price, "-")) > 1 {
@@ -368,84 +417,48 @@ func (b *BidSearch) GetSearchQuery() (qstr string) {
 		}
 	}
 	//采购单位联系方式
-	hasBuyerTel := b.BuyerTel
-	if hasBuyerTel != "" {
-		if hasBuyerTel == "y" {
+	if b.BuyerTel != "" {
+		if b.BuyerTel == "是" {
 			musts = append(musts, fmt.Sprintf(queryExists, "buyertel"))
-		} else {
+		} else if b.BuyerTel == "否" {
 			mustNot = append(mustNot, fmt.Sprintf(queryExists, "buyertel"))
 		}
 	}
 	//中标企业联系方式
-	hasWinnerTel := b.WinnerTel
-	if hasWinnerTel != "" {
-		if hasWinnerTel == "y" {
+	if b.WinnerTel != "" {
+		if b.WinnerTel == "是" {
 			musts = append(musts, fmt.Sprintf(queryExists, "winnertel"))
-		} else {
+		} else if b.WinnerTel == "否" {
 			mustNot = append(mustNot, fmt.Sprintf(queryExists, "winnertel"))
 		}
 	}
 	//附件--非BI
-	fileExists := b.FileExists
-	if !isFileSearch && fileExists != "" {
-		if fileExists == "1" { //有附件
+	if !isFileSearch && b.FileExists != "" {
+		if b.FileExists == "是" { //有附件
 			musts = append(musts, fmt.Sprintf(QueryBoolMustTermBool, "isValidFile", true))
-		} else if fileExists == "-1" { //无附件
+		} else if b.FileExists == "否" { //无附件
 			mustNot = append(mustNot, fmt.Sprintf(QueryBoolMustTermBool, "isValidFile", true))
 		}
 	}
 	//b.BidField  剑鱼默认招标信息搜索 此参数为空**
 	qstr = fmt.Sprintf(Query, strings.Join(musts, ","), strings.Join(mustNot, ","), fmt.Sprintf(`,"_source":[%s],"sort":[%s],"from":%d,"size":%d`, BidSearchFieldBase, BidSearchSort, b.PageNum, b.PageSize))
+	g.Log().Info(b.Ctx, b.PositionId, "es查询条件", qstr)
 	return
 }
 
 // GetBidSearchQuery  整理地区、城市、发布时间、信息类型、采购单位类型 查询条件
-func (b *BidSearch) MustQuery() string {
-	query := ``
+func (b *BidSearch) MustQuery() []string {
+	querys := []string{}
 	//省份
-	area := b.Province
-	if area != "" {
-		query += `{"terms":{"area":[`
-		for k, v := range strings.Split(area, ",") {
-			if k > 0 {
-				query += `,`
-			}
-			query += `"` + v + `"`
-		}
-		query += `]}}`
+	if len(b.Province) > 0 {
+		querys = append(querys, fmt.Sprintf(QueryTerms, "area", strings.Join(b.Province, QueryTermsDh)))
 	}
 	//市--未登录用户不能根据市和地区筛选
-	city := b.City
-	if city != "" {
-		if len(query) > 0 {
-			query += ","
-		}
-		query += `{"terms":{"city":[`
-		for k, v := range strings.Split(city, ",") {
-			if k > 0 {
-				query += `,`
-			}
-			query += `"` + v + `"`
-		}
-		query += `]}}`
-	}
-	district := b.District
-	if district != "" {
-		if len(query) > 0 {
-			query += ","
-		}
-		for k, v := range strings.Split(district, ",") {
-			if k > 0 {
-				query += `,`
-			}
-			cityName := strings.Split(v, "_")[0]
-			districtName := strings.Split(v, "_")[1]
-			queryBoolMustAndDistrict := `{"bool":{"must":[{"terms":{"city":["%s"]}},{"terms":{"district":["%s"]}}]}}`
-			query += fmt.Sprintf(queryBoolMustAndDistrict, cityName, districtName)
-		}
+	if len(b.City) > 0 {
+		querys = append(querys, fmt.Sprintf(QueryTerms, "city", strings.Join(b.City, QueryTermsDh)))
 	}
-	if query != "" {
-		query = fmt.Sprintf(QueryBoolShould, query)
+	if len(b.District) > 0 {
+		querys = append(querys, fmt.Sprintf(QueryTerms, "district", strings.Join(b.District, QueryTermsDh)))
 	}
 	//发布时间
 	publishTime := b.PublishTime
@@ -479,10 +492,7 @@ func (b *BidSearch) MustQuery() string {
 			}
 		}
 		if startTime != "" || endTime != "" {
-			if len(query) > 0 {
-				query += ","
-			}
-			query += `{"range":{"publishtime":{`
+			query := `{"range":{"publishtime":{`
 			if startTime != "" {
 				query += `"gte":` + startTime
 			}
@@ -493,69 +503,22 @@ func (b *BidSearch) MustQuery() string {
 				query += `"lt":` + endTime
 			}
 			query += `}}}`
+			querys = append(querys, query)
 		}
 	}
-	//信息类型-二级
-	subtype := b.Subtype
-	topType := If(b.TopType != "", strings.Split(b.TopType, ","), []string{}).([]string)
-	allType := ``
-	//二级分类
-	if subtype != "" {
-		var typeInt = 0
-		allType += `{"terms":{"subtype":[`
-		for k, v := range strings.Split(subtype, ",") {
-			if tType := If(topTypeMap[v] != "" && b.TopType == "", topTypeMap[v], "").(string); tType != "" {
-				topType = append(topType, tType)
-				typeInt += 1
-				continue
-			}
-			if k > typeInt {
-				allType += `,`
-			}
-			allType += `"` + v + `"`
-		}
-		allType += `]}}`
-		if typeInt == len(strings.Split(subtype, ",")) {
-			allType = ``
-		}
+	//信息类型  二级分类
+	if len(b.Subtype) > 0 {
+		querys = append(querys, fmt.Sprintf(QueryTerms, "subtype", strings.Join(b.Subtype, QueryTermsDh)))
 	}
 	//信息类型  一级分类
-	if len(topType) > 0 {
-		if allType != "" {
-			allType += ","
-		}
-		allType += `{"terms":{"toptype":[`
-		for k, v := range topType {
-			if k > 0 {
-				allType += `,`
-			}
-			allType += `"` + v + `"`
-		}
-		allType += `]}}`
-	}
-
-	if allType != "" {
-		if query != "" {
-			query += ","
-		}
-		query += fmt.Sprintf(QueryBoolShould, allType)
+	if len(b.TopType) > 0 {
+		querys = append(querys, fmt.Sprintf(QueryTerms, "toptype", strings.Join(b.TopType, QueryTermsDh)))
 	}
 	//采购单位类型
-	buyerClass := b.BuyerClass
-	if buyerClass != "" {
-		if len(query) > 0 {
-			query += ","
-		}
-		query += `{"terms":{"buyerclass":[`
-		for k, v := range strings.Split(buyerClass, ",") {
-			if k > 0 {
-				query += `,`
-			}
-			query += `"` + v + `"`
-		}
-		query += `]}`
+	if len(b.BuyerClass) > 0 {
+		querys = append(querys, fmt.Sprintf(QueryTerms, "buyerclass", strings.Join(b.BuyerClass, QueryTermsDh)))
 	}
-	return query
+	return querys
 }
 
 // DetailFileORTitle 包含正文或 附件 不包含标题
@@ -592,7 +555,7 @@ func (b *BidSearch) GetMatchArrSql(field string, val ...string) (sql string) {
 }
 
 // IndustryFormat 行业处理
-func (b *BidSearch) IndustryFormat(industry, subScopeClass string) (newIndustry string) {
+func (b *BidSearch) IndustryFormat(industry []string, subScopeClass string) (newIndustry string) {
 	commonSubstring := func(v string) (value string) {
 		bcs := strings.Split(v, "_")
 		if len(bcs) == 1 {
@@ -610,13 +573,12 @@ func (b *BidSearch) IndustryFormat(industry, subScopeClass string) (newIndustry
 		return
 	}
 	//搜索条件中没有行业的话,取查询结果中第一个行业
-	if industry == "" {
+	if len(industry) == 0 {
 		newIndustry = commonSubstring(bct[0])
 	} else { //搜索条件中有行业的话,取行业中和搜索条件相对应的第一个
-		industryArr := strings.Split(industry, ",")
 	L:
 		for _, bc := range bct {
-			for _, is := range industryArr {
+			for _, is := range industry {
 				if bc == is {
 					newIndustry = strings.TrimSpace(commonSubstring(bc))
 					break L

+ 27 - 9
internal/model/bidSearch/bidSearch_test.go

@@ -2,15 +2,13 @@ package bidSearch
 
 import (
 	"context"
+	"fmt"
 	"log"
 	"testing"
-
-	"app.yhyue.com/moapp/jybase/es"
 )
 
 func TestSearch(t *testing.T) {
-	es.NewEs("v7", "http://172.20.45.129:9206", 2, "", "")
-	bs, err := NewBidSearch(context.Background(), 0, `{
+	_ = `{
 "关键词": {
 "选择": ["软件"],
 "排除": []
@@ -20,19 +18,39 @@ func TestSearch(t *testing.T) {
 "匹配模式": "精准匹配",
 "信息类型": "招标公告",
 "地区": {
-"选择": ["广东", "广西", "海南","北京"],
+"选择": ["河南省","北京"],
 "排除": []
 },
-"金额": "0-2000万",
+"金额": "2000万以上",
 "采购单位联系方式": "不限",
 "中标单位联系方式": "不限",
 "附件": "不限",
 "采购单位": "不限",
 "中标单位": "不限",
 "招标代理": "不限"
-}`)
+}`
+	zhipu := `{
+	"关键词": {
+		"选择": ["华为"]
+	},
+	"发布时间范围": "20250201-20250227",
+	"信息类型": ["招标公告"],
+	"地区": {
+		"选择": []
+	},
+	"金额": "不限",
+	"搜索范围": ["标题", "正文"],
+	"附件": "不限",
+	"匹配模式": "精准匹配",
+	"中标单位": "不限",
+	"采购单位": "不限"
+}`
+	bs, err := NewBidSearch(context.Background(), 0, zhipu)
 	log.Println(err)
-	qstr, list := bs.Search()
+	qstr := bs.GetSearchQuery()
 	log.Println(qstr)
-	log.Println(list)
+	_, list := bs.Search()
+	for _, v := range list {
+		log.Println(fmt.Sprintf("%+v", v))
+	}
 }

+ 24 - 0
internal/model/bidSearch/logs/2025-02-27.log

@@ -0,0 +1,24 @@
+2025-02-27 13:37:54.218 [INFO] {b8566c8803fa27180203561ae502c35c} 初始化 elasticsearch {"address":"http://172.20.45.129:9206","size":3,"version":"v7","userName":"","password":""}
+2025-02-27 13:37:54.219 [INFO] {d01c909003fa27180303561a8beb2a36} 初始化mongodb
+2025-02-27 13:39:48.159 [INFO] {0833a90e1efa27188ff38c748b8ffc00} 初始化 elasticsearch {"address":"http://172.20.45.129:9206","size":3,"version":"v7","userName":"","password":""}
+2025-02-27 13:39:48.161 [INFO] {e8dc01181efa271890f38c7452ffec67} 初始化mongodb
+2025-02-27 13:41:32.505 [INFO] {2405ec5b36fa271857ba4e332596b114} 初始化 elasticsearch {"address":"http://172.20.45.129:9206","size":3,"version":"v7","userName":"","password":""}
+2025-02-27 13:41:32.508 [INFO] {f0e3896336fa271858ba4e331480e9cd} 初始化mongodb
+2025-02-27 13:41:50.044 [INFO] {90e2666b3afa27181d6dac4e806fe247} 初始化 elasticsearch {"address":"http://172.20.45.129:9206","size":3,"version":"v7","userName":"","password":""}
+2025-02-27 13:41:50.045 [INFO] {2811e3783afa27181e6dac4e15a290c1} 初始化mongodb
+2025-02-27 13:42:26.531 [INFO] {f0c2a4ee42fa2718909a4b3c951f8309} 初始化 elasticsearch {"address":"http://172.20.45.129:9206","size":3,"version":"v7","userName":"","password":""}
+2025-02-27 13:42:26.532 [INFO] {5c3eaff742fa2718919a4b3cb96880df} 初始化mongodb
+2025-02-27 13:43:30.499 [INFO] {64a266ca51fa27180f498e4d79dd6cbb} 初始化 elasticsearch {"address":"http://172.20.45.129:9206","size":3,"version":"v7","userName":"","password":""}
+2025-02-27 13:43:30.502 [INFO] {28ab8cdc51fa271810498e4da8decbe9} 初始化mongodb
+2025-02-27 14:31:59.967 [INFO] {08204135f7fc2718c5e48d305439c784} 初始化 elasticsearch {"address":"http://172.20.45.129:9206","size":3,"version":"v7","userName":"","password":""}
+2025-02-27 14:31:59.971 [INFO] {38a87246f7fc2718c6e48d30facb3d40} 初始化mongodb
+2025-02-27 14:33:40.447 [INFO] {cc8f46990efd271832db2c4488794b1a} 初始化 elasticsearch {"address":"http://172.20.45.129:9206","size":3,"version":"v7","userName":"","password":""}
+2025-02-27 14:33:40.450 [INFO] {b4036fab0efd271833db2c440ab84e69} 初始化mongodb
+2025-02-27 14:34:26.141 [INFO] {d4c82f4619fd2718374fa05bf59259d6} 初始化 elasticsearch {"address":"http://172.20.45.129:9206","size":3,"version":"v7","userName":"","password":""}
+2025-02-27 14:34:26.144 [INFO] {b002024f19fd2718384fa05ba2b8e5f8} 初始化mongodb
+2025-02-27 14:35:37.261 [INFO] {a0564cba29fd27188a51834ccc9af239} 初始化 elasticsearch {"address":"http://172.20.45.129:9206","size":3,"version":"v7","userName":"","password":""}
+2025-02-27 14:35:37.263 [INFO] {c86d0cde29fd27188b51834ccdf8dda6} 初始化mongodb
+2025-02-27 14:36:25.231 [INFO] {501a55f634fd2718c8b49a3bf3b0cd35} 初始化 elasticsearch {"address":"http://172.20.45.129:9206","size":3,"version":"v7","userName":"","password":""}
+2025-02-27 14:36:25.235 [INFO] {a0ac4b0935fd2718c9b49a3b2b5e2438} 初始化mongodb
+2025-02-27 15:01:38.371 [INFO] {68f1374f95fe271858652731d1b4d2de} 初始化 elasticsearch {"address":"http://172.20.45.129:9206","size":3,"version":"v7","userName":"","password":""}
+2025-02-27 15:01:38.373 [INFO] {7462765795fe27185965273170417782} 初始化mongodb

+ 21 - 15
manifest/config/ai_search.yaml

@@ -13,7 +13,7 @@ initConifg:
     isUsed: false
 aaa: 111
 timeout: 30000
-doubaoCallMax: 100
+doubaoCallMax: 0
 zhipuCallMax: 100
 bestBidListMaxLen: 5
 allBidListMaxLen: 10
@@ -25,8 +25,8 @@ doubaoPrompt: '######
 3. 信息类型,有以下选项:
 3.1、信息一级分类:拟建项目,采购意向,招标预告,招标公告,招标结果,招标信用信息
 3.2、信息二级分类:预告,预审,预审结果,论证意见,需求公示,招标,邀标,询价,竞谈,变更,中标,成交,废标,流标,合同,验收,违规
-4. 地区:【全国、国内所有省市县名称(不在一一列举,输出具体省市县名称)】(注意:把用户的意图转换为标准的省市名称,如:华北地区转换为["北京","天津","河北","山西","内蒙古自治区"]);若没有明确要求,可以选择「全国」
-5. 金额,项目金额范围,如:0-10万,10-20万,20-50万,50-100万,100万-200万,200万-500万,500万-1000万,1000万以上,自定义范围。若没有明确要求,可以选择"不限"
+4. 地区:【全国、国内所有省市县名称(不在一一列举,输出具体省市县名称)】(注意:把用户的意图转换为标准的省市县的名称,省市区县中间要空格隔开如:华北地区转换为["北京","天津","河北","山西","内蒙古自治区"]);若没有明确要求,可以选择[]
+5. 金额,项目金额范围,如:0-10万,10-20万,20-50万,50-100万,100万-200万,200万-500万,500万-1000万,1000万以上,自定义范围。若没有明确要求,可以选择"不限",金额输出以万为单位
 6. 搜索范围:标题,正文,附件,中标企业,项目名称/标的物,采购单位,招标代理机构。若没有明确要求,可以选择["标题","正文"]
 7. 附件:有附件,无附件,默认"不限"
 8.匹配模式:精准匹配,模糊匹配,若没有明确要求,可以选择"精准匹配"
@@ -47,12 +47,15 @@ doubaoPrompt: '######
         "选择": ["打印机"],
         "排除": ["进口"]
     },搜索范围:标题
-4、我想要河南省新乡市原阳县、延津县的笔记本销售信息
-分析:关键词:笔记本,"地区": {
-"选择": ["原阳县", "延津县"],
+4、我想要河南省新乡市原阳县、延津县的笔记本销售的招标和中标信息
+分析:关键词:笔记本,
+"地区": {
+"选择": ["河南省 新乡市 原阳县", "延津县"],
 "排除": []
 },
-
+"信息类型":["招标","中标"]
+5、给我找出中标金额在3000元以上的项目
+分析:信息类型:中标,金额:0.3万以上
 
 ######
 输出要求,不需要说明,不需要解释,直接输出结果。以JSON格式输出《剑鱼标讯检索系统》各个字段应该填充值,并进行JSON格式化。
@@ -63,7 +66,7 @@ doubaoPrompt: '######
 "匹配模式":精准匹配
 "信息类型":"全部",
 "地区":{
-    "选择":"全国",
+    "选择":[],
     "排除":[],
 },
 "金额":"不限",
@@ -87,8 +90,8 @@ zhipuPrompt: '######
 3. 信息类型,有以下选项:
 3.1、信息一级分类:拟建项目,采购意向,招标预告,招标公告,招标结果,招标信用信息
 3.2、信息二级分类:预告,预审,预审结果,论证意见,需求公示,招标,邀标,询价,竞谈,变更,中标,成交,废标,流标,合同,验收,违规
-4. 地区:【全国、国内所有省市县名称(不在一一列举,输出具体省市县名称)】(注意:把用户的意图转换为标准的省市名称,如:华北地区转换为["北京","天津","河北","山西","内蒙古自治区"]);若没有明确要求,可以选择「全国」
-5. 金额,项目金额范围,如:0-10万,10-20万,20-50万,50-100万,100万-200万,200万-500万,500万-1000万,1000万以上,自定义范围。若没有明确要求,可以选择"不限"
+4. 地区:【全国、国内所有省市县名称(不在一一列举,输出具体省市县名称)】(注意:把用户的意图转换为标准的省市县的名称,省市区县中间要空格隔开如:华北地区转换为["北京","天津","河北","山西","内蒙古自治区"]);若没有明确要求,可以选择[]
+5. 金额,项目金额范围,如:0-10万,10-20万,20-50万,50-100万,100万-200万,200万-500万,500万-1000万,1000万以上,自定义范围。若没有明确要求,可以选择"不限",金额输出以万为单位
 6. 搜索范围:标题,正文,附件,中标企业,项目名称/标的物,采购单位,招标代理机构。若没有明确要求,可以选择["标题","正文"]
 7. 附件:有附件,无附件,默认"不限"
 8.匹配模式:精准匹配,模糊匹配,若没有明确要求,可以选择"精准匹配"
@@ -109,12 +112,15 @@ zhipuPrompt: '######
         "选择": ["打印机"],
         "排除": ["进口"]
     },搜索范围:标题
-4、我想要河南省新乡市原阳县、延津县的笔记本销售信息
-分析:关键词:笔记本,"地区": {
-"选择": ["原阳县", "延津县"],
+4、我想要河南省新乡市原阳县、延津县的笔记本销售的招标和中标信息
+分析:关键词:笔记本,
+"地区": {
+"选择": ["河南省 新乡市 原阳县", "延津县"],
 "排除": []
 },
-
+"信息类型":["招标","中标"]
+5、给我找出中标金额在3000元以上的项目
+分析:信息类型:中标,金额:0.3万以上
 
 ######
 输出要求,不需要说明,不需要解释,直接输出结果。以JSON格式输出《剑鱼标讯检索系统》各个字段应该填充值,并进行JSON格式化。
@@ -125,7 +131,7 @@ zhipuPrompt: '######
 "匹配模式":精准匹配
 "信息类型":"全部",
 "地区":{
-    "选择":"全国",
+    "选择":[],
     "排除":[],
 },
 "金额":"不限",

+ 24 - 0
utility/tidb.go

@@ -0,0 +1,24 @@
+package utility
+
+import (
+	"strings"
+
+	"app.yhyue.com/moapp/jybase/mapping"
+	. "app.yhyue.com/moapp/jybase/mysql"
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/gogf/gf/v2/os/gctx"
+)
+
+var tidb *Mysql
+var AllDistrict = map[string]bool{}
+
+func init() {
+	ctx := gctx.New()
+	tidb = NewInit("mysql", strings.TrimPrefix(g.Cfg().MustGet(ctx, "database.default.link").String(), "mysql:"), g.Cfg().MustGet(ctx, "database.default.maxOpen").Int(), g.Cfg().MustGet(ctx, "database.default.maxIdle").Int())
+	mapping.BidCodeMapping.Init(tidb)
+	for _, v := range mapping.BidCodeMapping.District {
+		for kk, _ := range v {
+			AllDistrict[kk] = true
+		}
+	}
+}