feat(frontend/backend):增加自定义用户提问模板功能

- 在 Settings 模型中添加 questionTemplate 字段
- 在 OpenAi 结构体中添加 QuestionTemplate 字段
- 更新前端设置组件,增加用户 prompt 配置选项
- 修改后端 API调用,支持使用自定义用户 prompt
This commit is contained in:
spark 2025-02-12 14:47:50 +08:00
parent a3b718c149
commit 1f78cc3589
4 changed files with 51 additions and 23 deletions

View File

@ -23,27 +23,29 @@ import (
// @Desc
// -----------------------------------------------------------------------------------
type OpenAi struct {
ctx context.Context
BaseUrl string `json:"base_url"`
ApiKey string `json:"api_key"`
Model string `json:"model"`
MaxTokens int `json:"max_tokens"`
Temperature float64 `json:"temperature"`
Prompt string `json:"prompt"`
TimeOut int `json:"time_out"`
ctx context.Context
BaseUrl string `json:"base_url"`
ApiKey string `json:"api_key"`
Model string `json:"model"`
MaxTokens int `json:"max_tokens"`
Temperature float64 `json:"temperature"`
Prompt string `json:"prompt"`
TimeOut int `json:"time_out"`
QuestionTemplate string `json:"question_template"`
}
func NewDeepSeekOpenAi(ctx context.Context) *OpenAi {
config := getConfig()
return &OpenAi{
ctx: ctx,
BaseUrl: config.OpenAiBaseUrl,
ApiKey: config.OpenAiApiKey,
Model: config.OpenAiModelName,
MaxTokens: config.OpenAiMaxTokens,
Temperature: config.OpenAiTemperature,
Prompt: config.Prompt,
TimeOut: config.OpenAiApiTimeOut,
ctx: ctx,
BaseUrl: config.OpenAiBaseUrl,
ApiKey: config.OpenAiApiKey,
Model: config.OpenAiModelName,
MaxTokens: config.OpenAiMaxTokens,
Temperature: config.OpenAiTemperature,
Prompt: config.Prompt,
TimeOut: config.OpenAiApiTimeOut,
QuestionTemplate: config.QuestionTemplate,
}
}
@ -102,7 +104,14 @@ func (o OpenAi) NewChatStream(stock, stockCode string) <-chan string {
"content": o.Prompt,
},
}
question := strutil.ReplaceWithMap(o.QuestionTemplate, map[string]string{
"{{stockName}}": strutil.RemoveNonPrintable(stock),
"{{stockCode}}": strutil.RemoveNonPrintable(stockCode),
})
logger.SugaredLogger.Infof("NewChatStream stock:%s stockCode:%s", stock, stockCode)
logger.SugaredLogger.Infof("Prompt%s", o.Prompt)
logger.SugaredLogger.Infof("User Prompt config:%v", o.QuestionTemplate)
logger.SugaredLogger.Infof("User question:%s", question)
wg := &sync.WaitGroup{}
wg.Add(5)
@ -207,7 +216,7 @@ func (o OpenAi) NewChatStream(stock, stockCode string) <-chan string {
wg.Wait()
msg = append(msg, map[string]interface{}{
"role": "user",
"content": stock + "分析和总结",
"content": question,
})
client := resty.New()
client.SetBaseURL(o.BaseUrl)

View File

@ -25,6 +25,7 @@ type Settings struct {
OpenAiApiTimeOut int `json:"openAiApiTimeOut"`
Prompt string `json:"prompt"`
CheckUpdate bool `json:"checkUpdate"`
QuestionTemplate string `json:"questionTemplate"`
}
func (receiver Settings) TableName() string {
@ -61,6 +62,7 @@ func (s SettingsApi) UpdateConfig() string {
"prompt": s.Config.Prompt,
"check_update": s.Config.CheckUpdate,
"open_ai_api_time_out": s.Config.OpenAiApiTimeOut,
"question_template": s.Config.QuestionTemplate,
})
} else {
logger.SugaredLogger.Infof("未找到配置,创建默认配置:%+v", s.Config)
@ -80,6 +82,7 @@ func (s SettingsApi) UpdateConfig() string {
Prompt: s.Config.Prompt,
CheckUpdate: s.Config.CheckUpdate,
OpenAiApiTimeOut: s.Config.OpenAiApiTimeOut,
QuestionTemplate: s.Config.QuestionTemplate,
})
}
return "保存成功!"

View File

@ -28,8 +28,9 @@ const formValue = ref({
temperature: 0.1,
maxTokens: 1024,
prompt:"",
timeout: 5
},
timeout: 5,
questionTemplate: "{{stockName}}分析和总结"
}
})
onMounted(()=>{
@ -53,7 +54,8 @@ onMounted(()=>{
temperature:res.openAiTemperature,
maxTokens:res.openAiMaxTokens,
prompt:res.prompt,
timeout:res.openAiApiTimeOut
timeout:res.openAiApiTimeOut,
questionTemplate:res.questionTemplate?res.questionTemplate:'{{stockName}}分析和总结',
}
console.log(res)
})
@ -77,7 +79,8 @@ function saveConfig(){
openAiTemperature:formValue.value.openAI.temperature,
tushareToken:formValue.value.tushareToken,
prompt:formValue.value.openAI.prompt,
openAiApiTimeOut:formValue.value.openAI.timeout
openAiApiTimeOut:formValue.value.openAI.timeout,
questionTemplate:formValue.value.openAI.questionTemplate
})
//console.log("Settings",config)
@ -143,7 +146,8 @@ function importConfig(){
temperature:config.openAiTemperature,
maxTokens:config.openAiMaxTokens,
prompt:config.prompt,
timeout:config.openAiApiTimeOut
timeout:config.openAiApiTimeOut,
questionTemplate:config.questionTemplate,
}
// formRef.value.resetFields()
};
@ -243,8 +247,18 @@ window.onerror = function (event, source, lineno, colno, error) {
}"
/>
</n-form-item-gi>
<n-form-item-gi :span="22" v-if="formValue.openAI.enable" label="模型用户 Prompt" path="openAI.questionTemplate">
<n-input v-model:value="formValue.openAI.questionTemplate"
type="textarea"
:show-count="true"
placeholder="请输入用户prompt:例如{{stockName}}[{{stockCode}}]分析和总结"
:autosize="{
minRows: 5,
maxRows: 8
}"
/>
</n-form-item-gi>
</n-grid>
<n-gi :span="24">
<div style="display: flex; justify-content: center">
<n-space>

View File

@ -76,6 +76,7 @@ export namespace data {
openAiApiTimeOut: number;
prompt: string;
checkUpdate: boolean;
questionTemplate: string;
static createFrom(source: any = {}) {
return new Settings(source);
@ -102,6 +103,7 @@ export namespace data {
this.openAiApiTimeOut = source["openAiApiTimeOut"];
this.prompt = source["prompt"];
this.checkUpdate = source["checkUpdate"];
this.questionTemplate = source["questionTemplate"];
}
convertValues(a: any, classs: any, asMap: boolean = false): any {