feat(openai): 添加 OpenAI API 超时设置并调整相关功能

感谢@gnim2600 @XXXiaohuayanGGG 两位提供的帮助和建议
- 在前端和后端添加 OpenAI API 超时设置选项
- 更新 AI 诊断股票功能,支持自定义超时时间
- 优化设置界面布局,提高用户体验
- 为 AI 分析结果添加居中显示样式
This commit is contained in:
spark 2025-02-08 09:14:09 +08:00
parent 6ff1b68f1b
commit 3e13ef007b
5 changed files with 31 additions and 11 deletions

View File

@ -26,6 +26,7 @@ type OpenAi struct {
MaxTokens int `json:"max_tokens"` MaxTokens int `json:"max_tokens"`
Temperature float64 `json:"temperature"` Temperature float64 `json:"temperature"`
Prompt string `json:"prompt"` Prompt string `json:"prompt"`
TimeOut int `json:"time_out"`
} }
func NewDeepSeekOpenAi() *OpenAi { func NewDeepSeekOpenAi() *OpenAi {
@ -37,6 +38,7 @@ func NewDeepSeekOpenAi() *OpenAi {
MaxTokens: config.OpenAiMaxTokens, MaxTokens: config.OpenAiMaxTokens,
Temperature: config.OpenAiTemperature, Temperature: config.OpenAiTemperature,
Prompt: config.Prompt, Prompt: config.Prompt,
TimeOut: config.OpenAiApiTimeOut,
} }
} }
@ -206,7 +208,7 @@ func (o OpenAi) NewChatStream(stock, stockCode string) <-chan string {
client.SetHeader("Authorization", "Bearer "+o.ApiKey) client.SetHeader("Authorization", "Bearer "+o.ApiKey)
client.SetHeader("Content-Type", "application/json") client.SetHeader("Content-Type", "application/json")
client.SetRetryCount(3) client.SetRetryCount(3)
client.SetTimeout(1 * time.Minute) client.SetTimeout(time.Duration(o.TimeOut) * time.Second)
resp, err := client.R(). resp, err := client.R().
SetDoNotParseResponse(true). SetDoNotParseResponse(true).
SetBody(map[string]interface{}{ SetBody(map[string]interface{}{

View File

@ -21,6 +21,7 @@ type Settings struct {
OpenAiModelName string `json:"openAiModelName"` OpenAiModelName string `json:"openAiModelName"`
OpenAiMaxTokens int `json:"openAiMaxTokens"` OpenAiMaxTokens int `json:"openAiMaxTokens"`
OpenAiTemperature float64 `json:"openAiTemperature"` OpenAiTemperature float64 `json:"openAiTemperature"`
OpenAiApiTimeOut int `json:"openAiApiTimeOut"`
Prompt string `json:"prompt"` Prompt string `json:"prompt"`
CheckUpdate bool `json:"checkUpdate"` CheckUpdate bool `json:"checkUpdate"`
} }
@ -57,6 +58,8 @@ func (s SettingsApi) UpdateConfig() string {
"open_ai_temperature": s.Config.OpenAiTemperature, "open_ai_temperature": s.Config.OpenAiTemperature,
"tushare_token": s.Config.TushareToken, "tushare_token": s.Config.TushareToken,
"prompt": s.Config.Prompt, "prompt": s.Config.Prompt,
"check_update": s.Config.CheckUpdate,
"open_ai_api_time_out": s.Config.OpenAiApiTimeOut,
}) })
} else { } else {
logger.SugaredLogger.Infof("未找到配置,创建默认配置:%+v", s.Config) logger.SugaredLogger.Infof("未找到配置,创建默认配置:%+v", s.Config)
@ -74,6 +77,8 @@ func (s SettingsApi) UpdateConfig() string {
OpenAiTemperature: s.Config.OpenAiTemperature, OpenAiTemperature: s.Config.OpenAiTemperature,
TushareToken: s.Config.TushareToken, TushareToken: s.Config.TushareToken,
Prompt: s.Config.Prompt, Prompt: s.Config.Prompt,
CheckUpdate: s.Config.CheckUpdate,
OpenAiApiTimeOut: s.Config.OpenAiApiTimeOut,
}) })
} }
return "保存成功!" return "保存成功!"

View File

@ -27,6 +27,7 @@ const formValue = ref({
temperature: 0.1, temperature: 0.1,
maxTokens: 1024, maxTokens: 1024,
prompt:"", prompt:"",
timeout: 5
}, },
}) })
@ -51,6 +52,7 @@ onMounted(()=>{
temperature:res.openAiTemperature, temperature:res.openAiTemperature,
maxTokens:res.openAiMaxTokens, maxTokens:res.openAiMaxTokens,
prompt:res.prompt, prompt:res.prompt,
timeout:res.openAiApiTimeOut
} }
console.log(res) console.log(res)
}) })
@ -73,7 +75,8 @@ function saveConfig(){
openAiMaxTokens:formValue.value.openAI.maxTokens, openAiMaxTokens:formValue.value.openAI.maxTokens,
openAiTemperature:formValue.value.openAI.temperature, openAiTemperature:formValue.value.openAI.temperature,
tushareToken:formValue.value.tushareToken, tushareToken:formValue.value.tushareToken,
prompt:formValue.value.openAI.prompt prompt:formValue.value.openAI.prompt,
openAiApiTimeOut:formValue.value.openAI.timeout
}) })
//console.log("Settings",config) //console.log("Settings",config)
@ -150,22 +153,25 @@ function sendTestNotice(){
<n-form-item-gi :span="6" label="是否启用AI诊股" path="openAI.enable" > <n-form-item-gi :span="6" label="是否启用AI诊股" path="openAI.enable" >
<n-switch v-model:value="formValue.openAI.enable" /> <n-switch v-model:value="formValue.openAI.enable" />
</n-form-item-gi> </n-form-item-gi>
<n-form-item-gi :span="22" v-if="formValue.openAI.enable" label="openAI 接口地址:" path="openAI.baseUrl"> <n-form-item-gi :span="11" v-if="formValue.openAI.enable" label="openAI 接口地址:" path="openAI.baseUrl">
<n-input type="text" placeholder="AI接口地址" v-model:value="formValue.openAI.baseUrl" clearable /> <n-input type="text" placeholder="AI接口地址" v-model:value="formValue.openAI.baseUrl" clearable />
</n-form-item-gi> </n-form-item-gi>
<n-form-item-gi :span="10" v-if="formValue.openAI.enable" label="openAI apiKey" path="openAI.apiKey"> <n-form-item-gi :span="5" v-if="formValue.openAI.enable" label="请求超时时间(秒)" path="openAI.timeout">
<n-input-number min="1" step="1" placeholder="请求超时时间(秒)" v-model:value="formValue.openAI.timeout" />
</n-form-item-gi>
<n-form-item-gi :span="12" v-if="formValue.openAI.enable" label="openAI 令牌(apiKey)" path="openAI.apiKey">
<n-input type="text" placeholder="apiKey" v-model:value="formValue.openAI.apiKey" clearable /> <n-input type="text" placeholder="apiKey" v-model:value="formValue.openAI.apiKey" clearable />
</n-form-item-gi> </n-form-item-gi>
<n-form-item-gi :span="12" v-if="formValue.openAI.enable" label="AI模型" path="openAI.model"> <n-form-item-gi :span="10" v-if="formValue.openAI.enable" label="AI模型名称" path="openAI.model">
<n-input type="text" placeholder="AI模型" v-model:value="formValue.openAI.model" clearable /> <n-input type="text" placeholder="AI模型名称" v-model:value="formValue.openAI.model" clearable />
</n-form-item-gi> </n-form-item-gi>
<n-form-item-gi :span="12" v-if="formValue.openAI.enable" label="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="maxTokens" path="openAI.maxTokens"> <n-form-item-gi :span="10" 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="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"
:show-count="true" :show-count="true"

View File

@ -611,11 +611,16 @@ function getHeight() {
<n-modal transform-origin="center" v-model:show="modalShow4" preset="card" style="width: 800px;height: 480px" :title="'['+data.name+']AI分析结果'" > <n-modal transform-origin="center" v-model:show="modalShow4" preset="card" style="width: 800px;height: 480px" :title="'['+data.name+']AI分析结果'" >
<n-spin size="small" :show="data.loading"> <n-spin size="small" :show="data.loading">
<MdPreview ref="mdPreviewRef" style="height: 380px" :modelValue="data.airesult" :theme="'dark'"/> <MdPreview ref="mdPreviewRef" style="height: 380px;text-align: left" :modelValue="data.airesult" :theme="'dark'"/>
</n-spin> </n-spin>
</n-modal> </n-modal>
</template> </template>
<style scoped> <style scoped>
h3 {
text-align: center;
}
#总结 {
text-align: center;
}
</style> </style>

View File

@ -73,6 +73,7 @@ export namespace data {
openAiModelName: string; openAiModelName: string;
openAiMaxTokens: number; openAiMaxTokens: number;
openAiTemperature: number; openAiTemperature: number;
openAiApiTimeOut: number;
prompt: string; prompt: string;
checkUpdate: boolean; checkUpdate: boolean;
@ -98,6 +99,7 @@ export namespace data {
this.openAiModelName = source["openAiModelName"]; this.openAiModelName = source["openAiModelName"];
this.openAiMaxTokens = source["openAiMaxTokens"]; this.openAiMaxTokens = source["openAiMaxTokens"];
this.openAiTemperature = source["openAiTemperature"]; this.openAiTemperature = source["openAiTemperature"];
this.openAiApiTimeOut = source["openAiApiTimeOut"];
this.prompt = source["prompt"]; this.prompt = source["prompt"];
this.checkUpdate = source["checkUpdate"]; this.checkUpdate = source["checkUpdate"];
} }