Compare commits

...

6 Commits

Author SHA1 Message Date
ArvinLovegood
1d81fdba87 chore(deps):指标选股问题
- 将 User-Agent 中的 Firefox 版本从 140.0 更新为 145.0
2025-10-27 18:16:25 +08:00
ArvinLovegood
6aca0e15cc fix(backend): 指标选股问题
- 修改fingerprint和requestId为新的固定值
- 将timestamp设置为动态生成的时间戳
- 更新xcId为新的标识符
- 在测试中增加返回结果的日志输出
2025-10-27 18:15:02 +08:00
ArvinLovegood
173ce6f243 fix(backend):修复新闻列表排序逻辑
- 将新闻列表按ID降序排列,确保最新新闻优先显示
- 保持is_red字段的降序排序,确保重要新闻优先显示
- 修复了查询条件中缺少的排序字段逗号问题
2025-09-29 18:10:55 +08:00
ArvinLovegood
e7875e73d3 feat(backend):新增并使用GetNewsList2方法以支持标签功能
- 在MarketNewsApi中添加GetNewsList2方法,支持根据source和limit获取新闻列表
- GetNewsList2方法中预加载TelegraphTags并关联标签名称
- 修改openai_api.go中调用GetNewsList的地方为GetNewsList2- 调整获取新闻列表的参数,使用固定source和随机limit值
2025-09-29 17:34:31 +08:00
ArvinLovegood
ca4727db80 fix(app):更新股票研究报告工具描述
- 修改了GetStockResearchReport函数的描述信息
- 简化了描述文本,去除冗余的"机构的"前缀
- 保持了原有功能和参数结构不变
2025-09-27 19:12:51 +08:00
ArvinLovegood
84ffe7c5fd refactor(openai_api):移除行业板块相关工具调用逻辑
- 注释掉QueryBKDictInfo工具的调用实现
- 注释掉GetIndustryResearchReport工具的调用实现
- 移除对freecache包的依赖引用- 保留GetStockResearchReport工具的调用逻辑
- 简化工具调用处理流程
2025-09-27 18:55:28 +08:00
5 changed files with 150 additions and 127 deletions

50
app.go
View File

@@ -131,37 +131,37 @@ func AddTools(tools []data.Tool) []data.Tool {
},
})
tools = append(tools, data.Tool{
Type: "function",
Function: data.ToolFunction{
Name: "QueryBKDictInfo",
Description: "获取所有板块/行业名称或者代码(bkCode,bkName)",
},
})
//tools = append(tools, data.Tool{
// Type: "function",
// Function: data.ToolFunction{
// Name: "QueryBKDictInfo",
// Description: "获取所有板块/行业名称或者代码(bkCode,bkName)",
// },
//})
tools = append(tools, data.Tool{
Type: "function",
Function: data.ToolFunction{
Name: "GetIndustryResearchReport",
Description: "获取行业/板块研究报告,请先使用QueryBKDictInfo工具获取行业代码然后输入行业代码调用",
Parameters: data.FunctionParameters{
Type: "object",
Properties: map[string]any{
"bkCode": map[string]any{
"type": "string",
"description": "板块/行业代码",
},
},
Required: []string{"bkCode"},
},
},
})
//tools = append(tools, data.Tool{
// Type: "function",
// Function: data.ToolFunction{
// Name: "GetIndustryResearchReport",
// Description: "获取行业/板块研究报告,请先使用QueryBKDictInfo工具获取行业代码然后输入行业代码调用",
// Parameters: data.FunctionParameters{
// Type: "object",
// Properties: map[string]any{
// "bkCode": map[string]any{
// "type": "string",
// "description": "板块/行业代码",
// },
// },
// Required: []string{"bkCode"},
// },
// },
//})
tools = append(tools, data.Tool{
Type: "function",
Function: data.ToolFunction{
Name: "GetStockResearchReport",
Description: "获取机构的股票分析/研究报告",
Description: "获取股票分析/研究报告",
Parameters: data.FunctionParameters{
Type: "object",
Properties: map[string]any{

View File

@@ -117,6 +117,27 @@ func (m MarketNewsApi) GetNewsList(source string, limit int) *[]*models.Telegrap
}
return news
}
func (m MarketNewsApi) GetNewsList2(source string, limit int) *[]*models.Telegraph {
news := &[]*models.Telegraph{}
if source != "" {
db.Dao.Model(news).Preload("TelegraphTags").Where("source=?", source).Order("id desc,is_red desc").Limit(limit).Find(news)
} else {
db.Dao.Model(news).Preload("TelegraphTags").Order("id desc,is_red desc").Limit(limit).Find(news)
}
for _, item := range *news {
tags := &[]models.Tags{}
db.Dao.Model(&models.Tags{}).Where("id in ?", lo.Map(item.TelegraphTags, func(item models.TelegraphTags, index int) uint {
return item.TagId
})).Find(&tags)
tagNames := lo.Map(*tags, func(item models.Tags, index int) string {
return item.Name
})
item.SubjectTags = tagNames
logger.SugaredLogger.Infof("tagNames %v SubjectTags%s", tagNames, item.SubjectTags)
}
return news
}
func (m MarketNewsApi) GetTelegraphList(source string) *[]*models.Telegraph {
news := &[]*models.Telegraph{}
if source != "" {

View File

@@ -16,7 +16,6 @@ import (
"github.com/PuerkitoBio/goquery"
"github.com/chromedp/chromedp"
"github.com/coocood/freecache"
"github.com/duke-git/lancet/v2/convertor"
"github.com/duke-git/lancet/v2/random"
"github.com/duke-git/lancet/v2/strutil"
@@ -325,7 +324,7 @@ func (o *OpenAi) NewSummaryStockNewsStreamWithTools(userQuestion string, sysProm
}()
wg.Wait()
news := NewMarketNewsApi().GetNewsList("财联社电报", random.RandInt(100, 500))
news := NewMarketNewsApi().GetNewsList2("财联社电报", random.RandInt(100, 500))
messageText := strings.Builder{}
for _, telegraph := range *news {
messageText.WriteString("## " + telegraph.Time + ":" + "\n")
@@ -474,7 +473,7 @@ func (o *OpenAi) NewSummaryStockNewsStream(userQuestion string, sysPromptId *int
wg.Wait()
news := NewMarketNewsApi().GetNewsList("", 100)
news := NewMarketNewsApi().GetNewsList2("财联社电报", random.RandInt(100, 500))
messageText := strings.Builder{}
for _, telegraph := range *news {
messageText.WriteString("## " + telegraph.Time + ":" + "\n")
@@ -1367,98 +1366,98 @@ func AskAiWithTools(o *OpenAi, err error, messages []map[string]interface{}, ch
"tool_call_id": currentCallId,
})
}
//
//if funcName == "QueryBKDictInfo" {
// ch <- map[string]any{
// "code": 1,
// "question": question,
// "chatId": streamResponse.Id,
// "model": streamResponse.Model,
// "content": "\r\n```\r\n开始调用工具QueryBKDictInfo\n参数" + funcArguments + "\r\n```\r\n",
// "time": time.Now().Format(time.DateTime),
// }
// res := NewMarketNewsApi().EMDictCode("016", freecache.NewCache(100))
// bytes, err := json.Marshal(res)
// if err != nil {
// return
// }
// dict := &[]models.BKDict{}
// json.Unmarshal(bytes, dict)
// md := util.MarkdownTableWithTitle("行业/板块代码", dict)
// logger.SugaredLogger.Infof("行业/板块代码=\n%s", md)
// messages = append(messages, map[string]interface{}{
// "role": "assistant",
// "content": currentAIContent.String(),
// "tool_calls": []map[string]any{
// {
// "id": currentCallId,
// "tool_call_id": currentCallId,
// "type": "function",
// "function": map[string]string{
// "name": funcName,
// "arguments": funcArguments,
// "parameters": funcArguments,
// },
// },
// },
// })
// messages = append(messages, map[string]interface{}{
// "role": "tool",
// "content": md,
// "tool_call_id": currentCallId,
// })
//}
if funcName == "QueryBKDictInfo" {
ch <- map[string]any{
"code": 1,
"question": question,
"chatId": streamResponse.Id,
"model": streamResponse.Model,
"content": "\r\n```\r\n开始调用工具QueryBKDictInfo\n参数" + funcArguments + "\r\n```\r\n",
"time": time.Now().Format(time.DateTime),
}
res := NewMarketNewsApi().EMDictCode("016", freecache.NewCache(100))
bytes, err := json.Marshal(res)
if err != nil {
return
}
dict := &[]models.BKDict{}
json.Unmarshal(bytes, dict)
md := util.MarkdownTableWithTitle("行业/板块代码", dict)
logger.SugaredLogger.Infof("行业/板块代码=\n%s", md)
messages = append(messages, map[string]interface{}{
"role": "assistant",
"content": currentAIContent.String(),
"tool_calls": []map[string]any{
{
"id": currentCallId,
"tool_call_id": currentCallId,
"type": "function",
"function": map[string]string{
"name": funcName,
"arguments": funcArguments,
"parameters": funcArguments,
},
},
},
})
messages = append(messages, map[string]interface{}{
"role": "tool",
"content": md,
"tool_call_id": currentCallId,
})
}
if funcName == "GetIndustryResearchReport" {
bkCode := gjson.Get(funcArguments, "bkCode").String()
ch <- map[string]any{
"code": 1,
"question": question,
"chatId": streamResponse.Id,
"model": streamResponse.Model,
"content": "\r\n```\r\n开始调用工具GetIndustryResearchReport\n参数" + bkCode + "\r\n```\r\n",
"time": time.Now().Format(time.DateTime),
}
bkCode = strutil.ReplaceWithMap(bkCode, map[string]string{
"-": "",
"_": "",
"bk": "",
"BK": "",
"bk0": "",
"BK0": "",
})
logger.SugaredLogger.Debugf("code:%s", bkCode)
codeStr := convertor.ToString(bkCode)
res := NewMarketNewsApi().IndustryResearchReport(codeStr, 7)
md := strings.Builder{}
for _, a := range res {
d := a.(map[string]any)
md.WriteString(NewMarketNewsApi().GetIndustryReportInfo(d["infoCode"].(string)))
}
logger.SugaredLogger.Infof("bkCode:%s IndustryResearchReport:\n %s", bkCode, md.String())
messages = append(messages, map[string]interface{}{
"role": "assistant",
"content": currentAIContent.String(),
"tool_calls": []map[string]any{
{
"id": currentCallId,
"tool_call_id": currentCallId,
"type": "function",
"function": map[string]string{
"name": funcName,
"arguments": funcArguments,
"parameters": funcArguments,
},
},
},
})
messages = append(messages, map[string]interface{}{
"role": "tool",
"content": md.String(),
"tool_call_id": currentCallId,
})
}
//if funcName == "GetIndustryResearchReport" {
// bkCode := gjson.Get(funcArguments, "bkCode").String()
// ch <- map[string]any{
// "code": 1,
// "question": question,
// "chatId": streamResponse.Id,
// "model": streamResponse.Model,
// "content": "\r\n```\r\n开始调用工具GetIndustryResearchReport\n参数" + bkCode + "\r\n```\r\n",
// "time": time.Now().Format(time.DateTime),
// }
// bkCode = strutil.ReplaceWithMap(bkCode, map[string]string{
// "-": "",
// "_": "",
// "bk": "",
// "BK": "",
// "bk0": "",
// "BK0": "",
// })
//
// logger.SugaredLogger.Debugf("code:%s", bkCode)
// codeStr := convertor.ToString(bkCode)
// res := NewMarketNewsApi().IndustryResearchReport(codeStr, 7)
// md := strings.Builder{}
// for _, a := range res {
// d := a.(map[string]any)
// md.WriteString(NewMarketNewsApi().GetIndustryReportInfo(d["infoCode"].(string)))
// }
// logger.SugaredLogger.Infof("bkCode:%s IndustryResearchReport:\n %s", bkCode, md.String())
// messages = append(messages, map[string]interface{}{
// "role": "assistant",
// "content": currentAIContent.String(),
// "tool_calls": []map[string]any{
// {
// "id": currentCallId,
// "tool_call_id": currentCallId,
// "type": "function",
// "function": map[string]string{
// "name": funcName,
// "arguments": funcArguments,
// "parameters": funcArguments,
// },
// },
// },
// })
// messages = append(messages, map[string]interface{}{
// "role": "tool",
// "content": md.String(),
// "tool_call_id": currentCallId,
// })
//}
if funcName == "GetStockResearchReport" {
stockCode := gjson.Get(funcArguments, "stockCode").String()

View File

@@ -3,9 +3,10 @@ package data
import (
"encoding/json"
"fmt"
"github.com/go-resty/resty/v2"
"go-stock/backend/logger"
"time"
"github.com/go-resty/resty/v2"
)
// @Author spark
@@ -25,25 +26,25 @@ func (s SearchStockApi) SearchStock(pageSize int) map[string]any {
SetHeader("Host", "np-tjxg-g.eastmoney.com").
SetHeader("Origin", "https://xuangu.eastmoney.com").
SetHeader("Referer", "https://xuangu.eastmoney.com/").
SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0").
SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:145.0) Gecko/20100101 Firefox/145.0").
SetHeader("Content-Type", "application/json").
SetBody(fmt.Sprintf(`{
"keyWord": "%s",
"pageSize": %d,
"pageNo": 1,
"fingerprint": "e38b5faabf9378c8238e57219f0ebc9b",
"fingerprint": "02efa8944b1f90fbfe050e1e695a480d",
"gids": [],
"matchWord": "",
"timestamp": "1751113883290349",
"timestamp": "%d",
"shareToGuba": false,
"requestId": "8xTWgCDAjvQ5lmvz5mDA3Ydk2AE4yoiJ1751113883290",
"requestId": "RMd3Y76AJI98axPvdhdbKvbBDVwLlUK61761559950168",
"needCorrect": true,
"removedConditionIdList": [],
"xcId": "xc0af28549ab330013ed",
"xcId": "xc0d61279aad33008260",
"ownSelectAll": false,
"dxInfo": [],
"extraCondition": ""
}`, s.words, pageSize)).Post(url)
}`, s.words, pageSize, time.Now().Unix())).Post(url)
if err != nil {
logger.SugaredLogger.Errorf("SearchStock-err:%+v", err)
return map[string]any{}

View File

@@ -2,16 +2,18 @@ package data
import (
"encoding/json"
"github.com/duke-git/lancet/v2/convertor"
"go-stock/backend/db"
"go-stock/backend/logger"
"testing"
"github.com/duke-git/lancet/v2/convertor"
)
func TestSearchStock(t *testing.T) {
db.Init("../../data/stock.db")
res := NewSearchStockApi("算力股;净利润连续3年增长").SearchStock(10)
logger.SugaredLogger.Infof("res:%+v", res)
data := res["data"].(map[string]any)
result := data["result"].(map[string]any)
dataList := result["dataList"].([]any)