feat(frontend/backend):添加日K线数据天数设置功能

- 在前端设置页面添加日 K 线数据天数配置选项
- 在后端 OpenAI 配置中添加 KDays 字段
- 调整股票数据分析时的历史数据时间范围
This commit is contained in:
spark 2025-02-18 12:32:34 +08:00
parent 17a234f679
commit e21ba1b800
5 changed files with 32 additions and 3 deletions

View File

@ -33,6 +33,7 @@ type OpenAi struct {
TimeOut int `json:"time_out"` TimeOut int `json:"time_out"`
QuestionTemplate string `json:"question_template"` QuestionTemplate string `json:"question_template"`
CrawlTimeOut int64 `json:"crawl_time_out"` CrawlTimeOut int64 `json:"crawl_time_out"`
KDays int64 `json:"kDays"`
} }
func NewDeepSeekOpenAi(ctx context.Context) *OpenAi { func NewDeepSeekOpenAi(ctx context.Context) *OpenAi {
@ -44,6 +45,9 @@ func NewDeepSeekOpenAi(ctx context.Context) *OpenAi {
if config.CrawlTimeOut <= 0 { if config.CrawlTimeOut <= 0 {
config.CrawlTimeOut = 60 config.CrawlTimeOut = 60
} }
if config.KDays < 30 {
config.KDays = 30
}
} }
return &OpenAi{ return &OpenAi{
ctx: ctx, ctx: ctx,
@ -56,6 +60,7 @@ func NewDeepSeekOpenAi(ctx context.Context) *OpenAi {
TimeOut: config.OpenAiApiTimeOut, TimeOut: config.OpenAiApiTimeOut,
QuestionTemplate: config.QuestionTemplate, QuestionTemplate: config.QuestionTemplate,
CrawlTimeOut: config.CrawlTimeOut, CrawlTimeOut: config.CrawlTimeOut,
KDays: config.KDays,
} }
} }
@ -146,7 +151,7 @@ func (o OpenAi) NewChatStream(stock, stockCode, userQuestion string) <-chan map[
go func() { go func() {
defer wg.Done() defer wg.Done()
endDate := time.Now().Format("20060102") endDate := time.Now().Format("20060102")
startDate := time.Now().Add(-time.Hour * 24 * 365).Format("20060102") startDate := time.Now().Add(-time.Hour * time.Duration(24*o.KDays)).Format("20060102")
K := NewTushareApi(getConfig()).GetDaily(ConvertStockCodeToTushareCode(stockCode), startDate, endDate, o.CrawlTimeOut) K := NewTushareApi(getConfig()).GetDaily(ConvertStockCodeToTushareCode(stockCode), startDate, endDate, o.CrawlTimeOut)
msg = append(msg, map[string]interface{}{ msg = append(msg, map[string]interface{}{
"role": "assistant", "role": "assistant",

View File

@ -27,6 +27,7 @@ type Settings struct {
CheckUpdate bool `json:"checkUpdate"` CheckUpdate bool `json:"checkUpdate"`
QuestionTemplate string `json:"questionTemplate"` QuestionTemplate string `json:"questionTemplate"`
CrawlTimeOut int64 `json:"crawlTimeOut"` CrawlTimeOut int64 `json:"crawlTimeOut"`
KDays int64 `json:"kDays"`
} }
func (receiver Settings) TableName() string { func (receiver Settings) TableName() string {
@ -65,6 +66,7 @@ func (s SettingsApi) UpdateConfig() string {
"open_ai_api_time_out": s.Config.OpenAiApiTimeOut, "open_ai_api_time_out": s.Config.OpenAiApiTimeOut,
"question_template": s.Config.QuestionTemplate, "question_template": s.Config.QuestionTemplate,
"crawl_time_out": s.Config.CrawlTimeOut, "crawl_time_out": s.Config.CrawlTimeOut,
"k_days": s.Config.KDays,
}) })
} else { } else {
logger.SugaredLogger.Infof("未找到配置,创建默认配置:%+v", s.Config) logger.SugaredLogger.Infof("未找到配置,创建默认配置:%+v", s.Config)
@ -86,6 +88,7 @@ func (s SettingsApi) UpdateConfig() string {
OpenAiApiTimeOut: s.Config.OpenAiApiTimeOut, OpenAiApiTimeOut: s.Config.OpenAiApiTimeOut,
QuestionTemplate: s.Config.QuestionTemplate, QuestionTemplate: s.Config.QuestionTemplate,
CrawlTimeOut: s.Config.CrawlTimeOut, CrawlTimeOut: s.Config.CrawlTimeOut,
KDays: s.Config.KDays,
}) })
} }
return "保存成功!" return "保存成功!"
@ -93,6 +96,18 @@ func (s SettingsApi) UpdateConfig() string {
func (s SettingsApi) GetConfig() *Settings { func (s SettingsApi) GetConfig() *Settings {
var settings Settings var settings Settings
db.Dao.Model(&Settings{}).First(&settings) db.Dao.Model(&Settings{}).First(&settings)
if settings.OpenAiEnable {
if settings.OpenAiApiTimeOut <= 0 {
settings.OpenAiApiTimeOut = 60 * 5
}
if settings.CrawlTimeOut <= 0 {
settings.CrawlTimeOut = 60
}
if settings.KDays < 30 {
settings.KDays = 30
}
}
return &settings return &settings
} }

View File

@ -31,6 +31,7 @@ const formValue = ref({
timeout: 5, timeout: 5,
questionTemplate: "{{stockName}}分析和总结", questionTemplate: "{{stockName}}分析和总结",
crawlTimeOut:30, crawlTimeOut:30,
kDays:30,
} }
}) })
@ -58,6 +59,7 @@ onMounted(()=>{
timeout:res.openAiApiTimeOut, timeout:res.openAiApiTimeOut,
questionTemplate:res.questionTemplate?res.questionTemplate:'{{stockName}}分析和总结', questionTemplate:res.questionTemplate?res.questionTemplate:'{{stockName}}分析和总结',
crawlTimeOut:res.crawlTimeOut, crawlTimeOut:res.crawlTimeOut,
kDays:res.kDays,
} }
console.log(res) console.log(res)
}) })
@ -84,6 +86,7 @@ function saveConfig(){
openAiApiTimeOut:formValue.value.openAI.timeout, openAiApiTimeOut:formValue.value.openAI.timeout,
questionTemplate:formValue.value.openAI.questionTemplate, questionTemplate:formValue.value.openAI.questionTemplate,
crawlTimeOut:formValue.value.openAI.crawlTimeOut, crawlTimeOut:formValue.value.openAI.crawlTimeOut,
kDays:formValue.value.openAI.kDays
}) })
//console.log("Settings",config) //console.log("Settings",config)
@ -152,6 +155,7 @@ function importConfig(){
timeout:config.openAiApiTimeOut, timeout:config.openAiApiTimeOut,
questionTemplate:config.questionTemplate, questionTemplate:config.questionTemplate,
crawlTimeOut:config.crawlTimeOut, crawlTimeOut:config.crawlTimeOut,
kDays:config.kDays
} }
// formRef.value.resetFields() // formRef.value.resetFields()
}; };
@ -240,9 +244,12 @@ window.onerror = function (event, source, lineno, colno, error) {
<n-form-item-gi :span="12" v-if="formValue.openAI.enable" label="openAI temperature" path="openAI.temperature" > <n-form-item-gi :span="12" v-if="formValue.openAI.enable" label="openAI temperature" path="openAI.temperature" >
<n-input-number placeholder="temperature" v-model:value="formValue.openAI.temperature"/> <n-input-number placeholder="temperature" v-model:value="formValue.openAI.temperature"/>
</n-form-item-gi> </n-form-item-gi>
<n-form-item-gi :span="10" v-if="formValue.openAI.enable" label="openAI maxTokens" path="openAI.maxTokens"> <n-form-item-gi :span="5" v-if="formValue.openAI.enable" label="openAI maxTokens" path="openAI.maxTokens">
<n-input-number placeholder="maxTokens" v-model:value="formValue.openAI.maxTokens"/> <n-input-number placeholder="maxTokens" v-model:value="formValue.openAI.maxTokens"/>
</n-form-item-gi> </n-form-item-gi>
<n-form-item-gi :span="5" v-if="formValue.openAI.enable" title="天数越多消耗tokens越多" label="日K线数据(天)" path="openAI.maxTokens">
<n-input-number min="30" step="1" max="365" placeholder="日K线数据(天)" title="天数越多消耗tokens越多" v-model:value="formValue.openAI.kDays"/>
</n-form-item-gi>
<n-form-item-gi :span="22" v-if="formValue.openAI.enable" label="模型系统 Prompt" path="openAI.prompt"> <n-form-item-gi :span="22" v-if="formValue.openAI.enable" label="模型系统 Prompt" path="openAI.prompt">
<n-input v-model:value="formValue.openAI.prompt" <n-input v-model:value="formValue.openAI.prompt"
type="textarea" type="textarea"

View File

@ -772,7 +772,7 @@ function saveAsMarkdown() {
<template #action> <template #action>
<n-flex justify="right"> <n-flex justify="right">
<n-input v-model:value="data.question" <n-input v-model:value="data.question" style="text-align: left"
type="textarea" type="textarea"
:show-count="true" :show-count="true"
placeholder="请输入您的问题:例如{{stockName}}[{{stockCode}}]分析和总结" placeholder="请输入您的问题:例如{{stockName}}[{{stockCode}}]分析和总结"

View File

@ -78,6 +78,7 @@ export namespace data {
checkUpdate: boolean; checkUpdate: boolean;
questionTemplate: string; questionTemplate: string;
crawlTimeOut: number; crawlTimeOut: number;
kDays: number;
static createFrom(source: any = {}) { static createFrom(source: any = {}) {
return new Settings(source); return new Settings(source);
@ -106,6 +107,7 @@ export namespace data {
this.checkUpdate = source["checkUpdate"]; this.checkUpdate = source["checkUpdate"];
this.questionTemplate = source["questionTemplate"]; this.questionTemplate = source["questionTemplate"];
this.crawlTimeOut = source["crawlTimeOut"]; this.crawlTimeOut = source["crawlTimeOut"];
this.kDays = source["kDays"];
} }
convertValues(a: any, classs: any, asMap: boolean = false): any { convertValues(a: any, classs: any, asMap: boolean = false): any {