Compare commits

..

6 Commits

Author SHA1 Message Date
ArvinLovegood
c4287f9b78 feat(ai):新增了机构/券商的研究报告AI工具函数
- 添加 QueryBKDictInfo 工具用于获取板块/行业字典信息
- 实现 GetIndustryResearchReport 工具用于获取行业研究报告
- 实现 GetStockResearchReport 工具用于获取股票研究报告
- 在数据库中新增 BKDict 模型并自动迁移
- 更新 MarketNewsApi 测试用例以支持新工具调用
- 在 OpenAI API 中集成新工具的调用逻辑与响应处理
2025-09-27 15:39:37 +08:00
ArvinLovegood
87441d8923 feat(ai):新增了机构/券商的研究报告AI工具函数
- 添加 QueryBKDictInfo 工具用于获取板块/行业字典信息
- 实现 GetIndustryResearchReport 工具用于获取行业研究报告
- 实现 GetStockResearchReport 工具用于获取股票研究报告
- 在数据库中新增 BKDict 模型并自动迁移
- 更新 MarketNewsApi 测试用例以支持新工具调用
- 在 OpenAI API 中集成新工具的调用逻辑与响应处理
2025-09-27 15:39:25 +08:00
ArvinLovegood
ebd166e72b fix(agent):调整代理最大步骤数并修复前端显示逻辑
- 减少代理工具调用的最大步骤数计算方式
- 启用并修复前端聊天组件中的推理内容显示
- 修复删除分组时传递正确参数类型
- 更新依赖项,移除旧版本的 chromedp 和 golang.org/x/sys
2025-09-27 10:59:45 +08:00
ArvinLovegood
494a60debe refactor(backend):注释掉获取股势通资讯的代码
- 在 openai_api.go 中注释掉了获取股势通资讯的相关代码
- 在 openai_api_test.go 中添加了对 SearchGuShiTongStockInfo 函数的测试用例
2025-09-16 15:14:38 +08:00
ArvinLovegood
b3e2565a02 build: 更新多个依赖至最新版本 2025-09-16 14:19:11 +08:00
ArvinLovegood
c0a87d5d2e perf(app):优化股票基础信息更新逻辑
- 移除了定时任务中重复的股票基础信息检查逻辑
- 在获取股票基础信息前增加数据库记录数量检查,避免重复更新
2025-08-26 18:28:10 +08:00
12 changed files with 290 additions and 45 deletions

55
app.go
View File

@@ -131,6 +131,50 @@ 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: "GetIndustryResearchReport",
Description: "获取行业/板块研究报告",
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: "获取机构的股票分析/研究报告",
Parameters: data.FunctionParameters{
Type: "object",
Properties: map[string]any{
"stockCode": map[string]any{
"type": "string",
"description": "股票代码",
},
},
Required: []string{"stockCode"},
},
},
})
return tools
}
@@ -465,11 +509,7 @@ func (a *App) domReady(ctx context.Context) {
//检查新版本
go func() {
a.CheckUpdate(0)
count := int64(0)
db.Dao.Model(&data.StockBasic{}).Count(&count)
if count <= 0 {
go a.CheckStockBaseInfo(a.ctx)
}
go a.CheckStockBaseInfo(a.ctx)
a.cron.AddFunc("0 0 2 * * *", func() {
logger.SugaredLogger.Errorf("Checking for updates...")
@@ -524,6 +564,11 @@ func (a *App) CheckStockBaseInfo(ctx context.Context) {
SetResult(stockBasics).
Get("http://8.134.249.145:18080/go-stock/stock_basic.json")
count := int64(0)
db.Dao.Model(&data.StockBasic{}).Count(&count)
if count == int64(len(*stockBasics)) {
return
}
for _, stock := range *stockBasics {
stockInfo := &data.StockBasic{
TsCode: stock.TsCode,

View File

@@ -73,13 +73,14 @@ func GetStockAiAgent(ctx *context.Context, aiConfig data.AIConfig) *react.Agent
tools.GetFinancialReportTool(),
tools.GetQueryStockNewsTool(),
tools.GetIndustryResearchReportTool(),
tools.GetQueryBKDictTool(),
},
}
// 创建 agent
agent, err := react.NewAgent(*ctx, &react.AgentConfig{
ToolCallingModel: toolableChatModel,
ToolsConfig: aiTools,
MaxStep: len(aiTools.Tools)*3 + 2,
MaxStep: len(aiTools.Tools)*1 + 3,
MessageModifier: func(ctx context.Context, input []*schema.Message) []*schema.Message {
return input
},

View File

@@ -0,0 +1,34 @@
package tools
import (
"context"
"encoding/json"
"go-stock/backend/data"
"github.com/cloudwego/eino/components/tool"
"github.com/cloudwego/eino/schema"
"github.com/coocood/freecache"
)
// @Author spark
// @Date 2025/9/27 14:09
// @Desc
// -----------------------------------------------------------------------------------
type ToolQueryBKDict struct{}
func (t ToolQueryBKDict) Info(ctx context.Context) (*schema.ToolInfo, error) {
return &schema.ToolInfo{
Name: "QueryBKDictInfo",
Desc: "获取所有板块/行业名称或者代码(bkCode,bkName)",
}, nil
}
func (t ToolQueryBKDict) InvokableRun(ctx context.Context, argumentsInJSON string, opts ...tool.Option) (string, error) {
resp := data.NewMarketNewsApi().EMDictCode("016", freecache.NewCache(100))
bytes, err := json.Marshal(resp)
return string(bytes), err
}
func GetQueryBKDictTool() tool.InvokableTool {
return &ToolQueryBKDict{}
}

View File

@@ -4,6 +4,7 @@ import (
"encoding/json"
"go-stock/backend/db"
"go-stock/backend/logger"
"go-stock/backend/models"
"go-stock/backend/util"
"strings"
"testing"
@@ -75,6 +76,9 @@ func TestStockResearchReport(t *testing.T) {
resp := NewMarketNewsApi().StockResearchReport("600584.sh", 7)
for _, a := range resp {
logger.SugaredLogger.Debugf("value: %+v", a)
data := a.(map[string]any)
logger.SugaredLogger.Debugf("value: %s infoCode:%s", data["title"], data["infoCode"])
NewMarketNewsApi().GetIndustryReportInfo(data["infoCode"].(string))
}
}
@@ -108,7 +112,11 @@ func TestEMDictCode(t *testing.T) {
if err != nil {
return
}
dict := &[]models.BKDict{}
json.Unmarshal(bytes, dict)
logger.SugaredLogger.Debugf("value: %s", string(bytes))
md := util.MarkdownTableWithTitle("行业/板块代码", dict)
logger.SugaredLogger.Debugf(md)
}

View File

@@ -16,6 +16,7 @@ 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"
@@ -808,25 +809,25 @@ func (o *OpenAi) NewChatStream(stock, stockCode, userQuestion string, sysPromptI
return
}
messages := SearchGuShiTongStockInfo(stockCode, o.CrawlTimeOut)
if messages == nil || len(*messages) == 0 {
logger.SugaredLogger.Error("获取股势通资讯失败")
//ch <- "***❗获取股势通资讯失败,分析结果可能不准确***<hr>"
//go runtime.EventsEmit(o.ctx, "warnMsg", "❗获取股势通资讯失败,分析结果可能不准确")
return
}
var newsText strings.Builder
for _, message := range *messages {
newsText.WriteString(message + "\n")
}
msg = append(msg, map[string]interface{}{
"role": "user",
"content": stock + "相关新闻资讯",
})
msg = append(msg, map[string]interface{}{
"role": "assistant",
"content": newsText.String(),
})
//messages := SearchGuShiTongStockInfo(stockCode, o.CrawlTimeOut)
//if messages == nil || len(*messages) == 0 {
// logger.SugaredLogger.Error("获取股势通资讯失败")
// //ch <- "***❗获取股势通资讯失败,分析结果可能不准确***<hr>"
// //go runtime.EventsEmit(o.ctx, "warnMsg", "❗获取股势通资讯失败,分析结果可能不准确")
// return
//}
//var newsText strings.Builder
//for _, message := range *messages {
// newsText.WriteString(message + "\n")
//}
//msg = append(msg, map[string]interface{}{
// "role": "user",
// "content": stock + "相关新闻资讯",
//})
//msg = append(msg, map[string]interface{}{
// "role": "assistant",
// "content": newsText.String(),
//})
}()
go func() {
@@ -1367,6 +1368,140 @@ func AskAiWithTools(o *OpenAi, err error, messages []map[string]interface{}, ch
})
}
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 == "GetStockResearchReport" {
stockCode := gjson.Get(funcArguments, "stockCode").String()
ch <- map[string]any{
"code": 1,
"question": question,
"chatId": streamResponse.Id,
"model": streamResponse.Model,
"content": "\r\n```\r\n开始调用工具GetStockResearchReport\n参数" + stockCode + "\r\n```\r\n",
"time": time.Now().Format(time.DateTime),
}
res := NewMarketNewsApi().StockResearchReport(stockCode, 7)
md := strings.Builder{}
for _, a := range res {
logger.SugaredLogger.Debugf("value: %+v", a)
d := a.(map[string]any)
logger.SugaredLogger.Debugf("value: %s infoCode:%s", d["title"], d["infoCode"])
md.WriteString(NewMarketNewsApi().GetIndustryReportInfo(d["infoCode"].(string)))
}
logger.SugaredLogger.Infof("stockCode:%s StockResearchReport:\n %s", stockCode, 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,
})
}
}
AskAiWithTools(o, err, messages, ch, question, tools)
}

View File

@@ -3,6 +3,7 @@ package data
import (
"context"
"go-stock/backend/db"
log "go-stock/backend/logger"
"testing"
)
@@ -52,9 +53,12 @@ func TestGetTopNewsList(t *testing.T) {
func TestSearchGuShiTongStockInfo(t *testing.T) {
db.Init("../../data/stock.db")
SearchGuShiTongStockInfo("hk01810", 60)
SearchGuShiTongStockInfo("sh600745", 60)
SearchGuShiTongStockInfo("gb_goog", 60)
//SearchGuShiTongStockInfo("hk01810", 60)
msgs := SearchGuShiTongStockInfo("sh600745", 60)
for _, msg := range *msgs {
log.SugaredLogger.Infof("%s", msg)
}
//SearchGuShiTongStockInfo("gb_goog", 60)
}

View File

@@ -1,9 +1,10 @@
package models
import (
"time"
"gorm.io/gorm"
"gorm.io/plugin/soft_delete"
"time"
)
// @Author spark
@@ -687,3 +688,16 @@ type CailianpressWeb struct {
Author string `json:"author" md:"资讯发布者"`
} `json:"list"`
}
type BKDict struct {
gorm.Model `md:"-"`
BkCode string `json:"bkCode" md:"行业/板块代码"`
BkName string `json:"bkName" md:"行业/板块名称"`
FirstLetter string `json:"firstLetter" md:"first_letter"`
FubkCode string `json:"fubkCode" md:"fubk_code"`
PublishCode string `json:"publishCode" md:"publish_code"`
}
func (b BKDict) TableName() string {
return "bk_dict"
}

View File

@@ -14,7 +14,7 @@
<template #content="{ item, index }">
<t-chat-reasoning v-if="item.role === 'assistant'" expand-icon-placement="right">
<t-chat-loading v-if="isStreamLoad" text="思考中..." />
<!-- <t-chat-content v-if="item.reasoning.length > 0" :content="item.reasoning" />-->
<t-chat-content v-if="item.reasoning.length > 0" :content="item.reasoning" />
</t-chat-reasoning>
<t-chat-content v-if="item.content.length > 0" :content="item.content" />
</template>
@@ -97,9 +97,9 @@ EventsOn("agent-message", (data) => {
if(data['role']==="assistant"){
loading.value = false;
const lastItem = chatList.value[0];
// if (data['reasoning_content']){
// lastItem.reasoning = data['reasoning_content'];
// }
if (data['reasoning_content']){
lastItem.reasoning += data['reasoning_content'];
}
if (data['content']){
lastItem.content +=data['content'];
}

View File

@@ -1853,8 +1853,8 @@ function updateTab(name) {
})
}
function delTab(name) {
let infos = groupList.value = groupList.value.filter(item => item.ID === Number(name))
function delTab(groupId) {
let infos = groupList.value = groupList.value.filter(item => item.ID === Number(groupId))
dialog.create({
title: '删除分组',
type: 'warning',
@@ -1862,7 +1862,7 @@ function delTab(name) {
positiveText: '确定',
negativeText: '取消',
onPositiveClick: () => {
RemoveGroup(name).then(result => {
RemoveGroup(Number(groupId)).then(result => {
message.info(result)
GetGroupList().then(result => {
groupList.value = result

7
go.mod
View File

@@ -4,7 +4,7 @@ go 1.25.0
require (
github.com/PuerkitoBio/goquery v1.10.1
github.com/chromedp/chromedp v0.11.2
github.com/chromedp/chromedp v0.14.1
github.com/cloudwego/eino v0.4.1
github.com/cloudwego/eino-ext/components/model/ark v0.1.19
github.com/cloudwego/eino-ext/components/model/deepseek v0.0.0-20250804092122-8845979a2228
@@ -26,7 +26,7 @@ require (
github.com/wailsapp/wails/v2 v2.10.1
go.uber.org/zap v1.27.0
golang.org/x/net v0.38.0
golang.org/x/sys v0.35.0
golang.org/x/sys v0.36.0
golang.org/x/text v0.26.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gorm.io/gorm v1.25.12
@@ -41,7 +41,7 @@ require (
github.com/bytedance/sonic v1.14.0 // indirect
github.com/bytedance/sonic/loader v0.3.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/chromedp/cdproto v0.0.0-20241022234722-4d5d5faf59fb // indirect
github.com/chromedp/cdproto v0.0.0-20250803210736-d308e07a266d // indirect
github.com/chromedp/sysutil v1.1.0 // indirect
github.com/cloudwego/base64x v0.1.6 // indirect
github.com/cloudwego/eino-ext/libs/acl/openai v0.0.0-20250804062529-6e67726a4b3f // indirect
@@ -52,6 +52,7 @@ require (
github.com/evanphx/json-patch v0.5.2 // indirect
github.com/getkin/kin-openapi v0.118.0 // indirect
github.com/glebarez/go-sqlite v1.21.2 // indirect
github.com/go-json-experiment/json v0.0.0-20250910080747-cc2cfa0554c3 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect

14
go.sum
View File

@@ -24,10 +24,10 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA
github.com/certifi/gocertifi v0.0.0-20190105021004-abcd57078448/go.mod h1:GJKEexRPVJrBSOjoqN5VNOIKJ5Q3RViH6eu3puDRwx4=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chromedp/cdproto v0.0.0-20241022234722-4d5d5faf59fb h1:noKVm2SsG4v0Yd0lHNtFYc9EUxIVvrr4kJ6hM8wvIYU=
github.com/chromedp/cdproto v0.0.0-20241022234722-4d5d5faf59fb/go.mod h1:4XqMl3iIW08jtieURWL6Tt5924w21pxirC6th662XUM=
github.com/chromedp/chromedp v0.11.2 h1:ZRHTh7DjbNTlfIv3NFTbB7eVeu5XCNkgrpcGSpn2oX0=
github.com/chromedp/chromedp v0.11.2/go.mod h1:lr8dFRLKsdTTWb75C/Ttol2vnBKOSnt0BW8R9Xaupi8=
github.com/chromedp/cdproto v0.0.0-20250803210736-d308e07a266d h1:ZtA1sedVbEW7EW80Iz2GR3Ye6PwbJAJXjv7D74xG6HU=
github.com/chromedp/cdproto v0.0.0-20250803210736-d308e07a266d/go.mod h1:NItd7aLkcfOA/dcMXvl8p1u+lQqioRMq/SqDp71Pb/k=
github.com/chromedp/chromedp v0.14.1 h1:0uAbnxewy/Q+Bg7oafVePE/6EXEho9hnaC38f+TTENg=
github.com/chromedp/chromedp v0.14.1/go.mod h1:rHzAv60xDE7VNy/MYtTUrYreSc0ujt2O1/C3bzctYBo=
github.com/chromedp/sysutil v1.1.0 h1:PUFNv5EcprjqXZD9nJb9b/c9ibAbxiYo4exNWZyipwM=
github.com/chromedp/sysutil v1.1.0/go.mod h1:WiThHUdltqCNKGc4gaU50XgYjwjYIhKWoHGPTUfWTJ8=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
@@ -76,6 +76,8 @@ github.com/go-check/check v0.0.0-20180628173108-788fd7840127 h1:0gkP6mzaMqkmpcJY
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
github.com/go-ego/gse v0.80.3 h1:YNFkjMhlhQnUeuoFcUEd1ivh6SOB764rT8GDsEbDiEg=
github.com/go-ego/gse v0.80.3/go.mod h1:Gt3A9Ry1Eso2Kza4MRaiZ7f2DTAvActmETY46Lxg0gU=
github.com/go-json-experiment/json v0.0.0-20250910080747-cc2cfa0554c3 h1:02WINGfSX5w0Mn+F28UyRoSt9uvMhKguwWMlOAh6U/0=
github.com/go-json-experiment/json v0.0.0-20250910080747-cc2cfa0554c3/go.mod h1:uNVvRXArCGbZ508SxYYTC5v1JWoz2voff5pm25jU1Ok=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
@@ -409,8 +411,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=

View File

@@ -228,6 +228,7 @@ func AutoMigrate() {
db.Dao.AutoMigrate(&models.TelegraphTags{})
db.Dao.AutoMigrate(&models.LongTigerRankData{})
db.Dao.AutoMigrate(&data.AIConfig{})
db.Dao.AutoMigrate(&models.BKDict{})
updateMultipleModel()
}