✨ feat: Add ChannelOtherSettings to manage additional channel configurations
This commit is contained in:
@@ -22,6 +22,7 @@ const (
|
|||||||
ContextKeyChannelBaseUrl ContextKey = "base_url"
|
ContextKeyChannelBaseUrl ContextKey = "base_url"
|
||||||
ContextKeyChannelType ContextKey = "channel_type"
|
ContextKeyChannelType ContextKey = "channel_type"
|
||||||
ContextKeyChannelSetting ContextKey = "channel_setting"
|
ContextKeyChannelSetting ContextKey = "channel_setting"
|
||||||
|
ContextKeyChannelOtherSetting ContextKey = "channel_other_setting"
|
||||||
ContextKeyChannelParamOverride ContextKey = "param_override"
|
ContextKeyChannelParamOverride ContextKey = "param_override"
|
||||||
ContextKeyChannelOrganization ContextKey = "channel_organization"
|
ContextKeyChannelOrganization ContextKey = "channel_organization"
|
||||||
ContextKeyChannelAutoBan ContextKey = "auto_ban"
|
ContextKeyChannelAutoBan ContextKey = "auto_ban"
|
||||||
|
|||||||
@@ -8,3 +8,7 @@ type ChannelSettings struct {
|
|||||||
SystemPrompt string `json:"system_prompt,omitempty"`
|
SystemPrompt string `json:"system_prompt,omitempty"`
|
||||||
SystemPromptOverride bool `json:"system_prompt_override,omitempty"`
|
SystemPromptOverride bool `json:"system_prompt_override,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ChannelOtherSettings struct {
|
||||||
|
AzureResponsesVersion string `json:"azure_responses_version,omitempty"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -244,6 +244,7 @@ func SetupContextForSelectedChannel(c *gin.Context, channel *model.Channel, mode
|
|||||||
common.SetContextKey(c, constant.ContextKeyChannelType, channel.Type)
|
common.SetContextKey(c, constant.ContextKeyChannelType, channel.Type)
|
||||||
common.SetContextKey(c, constant.ContextKeyChannelCreateTime, channel.CreatedTime)
|
common.SetContextKey(c, constant.ContextKeyChannelCreateTime, channel.CreatedTime)
|
||||||
common.SetContextKey(c, constant.ContextKeyChannelSetting, channel.GetSetting())
|
common.SetContextKey(c, constant.ContextKeyChannelSetting, channel.GetSetting())
|
||||||
|
common.SetContextKey(c, constant.ContextKeyChannelOtherSetting, channel.GetOtherSettings())
|
||||||
common.SetContextKey(c, constant.ContextKeyChannelParamOverride, channel.GetParamOverride())
|
common.SetContextKey(c, constant.ContextKeyChannelParamOverride, channel.GetParamOverride())
|
||||||
if nil != channel.OpenAIOrganization && *channel.OpenAIOrganization != "" {
|
if nil != channel.OpenAIOrganization && *channel.OpenAIOrganization != "" {
|
||||||
common.SetContextKey(c, constant.ContextKeyChannelOrganization, *channel.OpenAIOrganization)
|
common.SetContextKey(c, constant.ContextKeyChannelOrganization, *channel.OpenAIOrganization)
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ type Channel struct {
|
|||||||
Priority *int64 `json:"priority" gorm:"bigint;default:0"`
|
Priority *int64 `json:"priority" gorm:"bigint;default:0"`
|
||||||
AutoBan *int `json:"auto_ban" gorm:"default:1"`
|
AutoBan *int `json:"auto_ban" gorm:"default:1"`
|
||||||
OtherInfo string `json:"other_info"`
|
OtherInfo string `json:"other_info"`
|
||||||
Settings string `json:"settings"`
|
OtherSettings string `json:"settings" gorm:"column:settings"` // 其他设置
|
||||||
Tag *string `json:"tag" gorm:"index"`
|
Tag *string `json:"tag" gorm:"index"`
|
||||||
Setting *string `json:"setting" gorm:"type:text"` // 渠道额外设置
|
Setting *string `json:"setting" gorm:"type:text"` // 渠道额外设置
|
||||||
ParamOverride *string `json:"param_override" gorm:"type:text"`
|
ParamOverride *string `json:"param_override" gorm:"type:text"`
|
||||||
@@ -838,6 +838,28 @@ func (channel *Channel) SetSetting(setting dto.ChannelSettings) {
|
|||||||
channel.Setting = common.GetPointer[string](string(settingBytes))
|
channel.Setting = common.GetPointer[string](string(settingBytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (channel *Channel) GetOtherSettings() dto.ChannelOtherSettings {
|
||||||
|
setting := dto.ChannelOtherSettings{}
|
||||||
|
if channel.OtherSettings != "" {
|
||||||
|
err := common.UnmarshalJsonStr(channel.OtherSettings, &setting)
|
||||||
|
if err != nil {
|
||||||
|
common.SysError("failed to unmarshal setting: " + err.Error())
|
||||||
|
channel.OtherSettings = "{}" // 清空设置以避免后续错误
|
||||||
|
_ = channel.Save() // 保存修改
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return setting
|
||||||
|
}
|
||||||
|
|
||||||
|
func (channel *Channel) SetOtherSettings(setting dto.ChannelOtherSettings) {
|
||||||
|
settingBytes, err := common.Marshal(setting)
|
||||||
|
if err != nil {
|
||||||
|
common.SysError("failed to marshal setting: " + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
channel.OtherSettings = string(settingBytes)
|
||||||
|
}
|
||||||
|
|
||||||
func (channel *Channel) GetParamOverride() map[string]interface{} {
|
func (channel *Channel) GetParamOverride() map[string]interface{} {
|
||||||
paramOverride := make(map[string]interface{})
|
paramOverride := make(map[string]interface{})
|
||||||
if channel.ParamOverride != nil && *channel.ParamOverride != "" {
|
if channel.ParamOverride != nil && *channel.ParamOverride != "" {
|
||||||
|
|||||||
@@ -128,7 +128,11 @@ func (a *Adaptor) GetRequestURL(info *relaycommon.RelayInfo) (string, error) {
|
|||||||
|
|
||||||
// 特殊处理 responses API
|
// 特殊处理 responses API
|
||||||
if info.RelayMode == relayconstant.RelayModeResponses {
|
if info.RelayMode == relayconstant.RelayModeResponses {
|
||||||
requestURL = fmt.Sprintf("/openai/v1/responses?api-version=preview")
|
responsesApiVersion := "preview"
|
||||||
|
if info.ChannelOtherSettings.AzureResponsesVersion != "" {
|
||||||
|
responsesApiVersion = info.ChannelOtherSettings.AzureResponsesVersion
|
||||||
|
}
|
||||||
|
requestURL = fmt.Sprintf("/openai/v1/responses?api-version=%s", responsesApiVersion)
|
||||||
return relaycommon.GetFullRequestURL(info.BaseUrl, requestURL, info.ChannelType), nil
|
return relaycommon.GetFullRequestURL(info.BaseUrl, requestURL, info.ChannelType), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ type RelayInfo struct {
|
|||||||
AudioUsage bool
|
AudioUsage bool
|
||||||
ReasoningEffort string
|
ReasoningEffort string
|
||||||
ChannelSetting dto.ChannelSettings
|
ChannelSetting dto.ChannelSettings
|
||||||
|
ChannelOtherSettings dto.ChannelOtherSettings
|
||||||
ParamOverride map[string]interface{}
|
ParamOverride map[string]interface{}
|
||||||
UserSetting dto.UserSetting
|
UserSetting dto.UserSetting
|
||||||
UserEmail string
|
UserEmail string
|
||||||
@@ -292,6 +293,12 @@ func GenRelayInfo(c *gin.Context) *RelayInfo {
|
|||||||
if ok {
|
if ok {
|
||||||
info.ChannelSetting = channelSetting
|
info.ChannelSetting = channelSetting
|
||||||
}
|
}
|
||||||
|
|
||||||
|
channelOtherSettings, ok := common.GetContextKeyType[dto.ChannelOtherSettings](c, constant.ContextKeyChannelOtherSetting)
|
||||||
|
if ok {
|
||||||
|
info.ChannelOtherSettings = channelOtherSettings
|
||||||
|
}
|
||||||
|
|
||||||
userSetting, ok := common.GetContextKeyType[dto.UserSetting](c, constant.ContextKeyUserSetting)
|
userSetting, ok := common.GetContextKeyType[dto.UserSetting](c, constant.ContextKeyUserSetting)
|
||||||
if ok {
|
if ok {
|
||||||
info.UserSetting = userSetting
|
info.UserSetting = userSetting
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ const EditChannelModal = (props) => {
|
|||||||
pass_through_body_enabled: false,
|
pass_through_body_enabled: false,
|
||||||
system_prompt: '',
|
system_prompt: '',
|
||||||
system_prompt_override: false,
|
system_prompt_override: false,
|
||||||
|
settings: '',
|
||||||
};
|
};
|
||||||
const [batch, setBatch] = useState(false);
|
const [batch, setBatch] = useState(false);
|
||||||
const [multiToSingle, setMultiToSingle] = useState(false);
|
const [multiToSingle, setMultiToSingle] = useState(false);
|
||||||
@@ -187,38 +188,31 @@ const EditChannelModal = (props) => {
|
|||||||
handleInputChange('setting', settingsJson);
|
handleInputChange('setting', settingsJson);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 解析渠道设置JSON为单独的状态
|
const handleChannelOtherSettingsChange = (key, value) => {
|
||||||
const parseChannelSettings = (settingJson) => {
|
// 更新内部状态
|
||||||
|
setChannelSettings(prev => ({ ...prev, [key]: value }));
|
||||||
|
|
||||||
|
// 同步更新到表单字段
|
||||||
|
if (formApiRef.current) {
|
||||||
|
formApiRef.current.setValue(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 同步更新inputs状态
|
||||||
|
setInputs(prev => ({ ...prev, [key]: value }));
|
||||||
|
|
||||||
|
// 需要更新settings,是一个json,例如{"azure_responses_version": "preview"}
|
||||||
|
let settings = {};
|
||||||
|
if (inputs.settings) {
|
||||||
try {
|
try {
|
||||||
if (settingJson && settingJson.trim()) {
|
settings = JSON.parse(inputs.settings);
|
||||||
const parsed = JSON.parse(settingJson);
|
|
||||||
setChannelSettings({
|
|
||||||
force_format: parsed.force_format || false,
|
|
||||||
thinking_to_content: parsed.thinking_to_content || false,
|
|
||||||
proxy: parsed.proxy || '',
|
|
||||||
pass_through_body_enabled: parsed.pass_through_body_enabled || false,
|
|
||||||
system_prompt: parsed.system_prompt || '',
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setChannelSettings({
|
|
||||||
force_format: false,
|
|
||||||
thinking_to_content: false,
|
|
||||||
proxy: '',
|
|
||||||
pass_through_body_enabled: false,
|
|
||||||
system_prompt: '',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('解析渠道设置失败:', error);
|
console.error('解析设置失败:', error);
|
||||||
setChannelSettings({
|
}
|
||||||
force_format: false,
|
}
|
||||||
thinking_to_content: false,
|
settings[key] = value;
|
||||||
proxy: '',
|
const settingsJson = JSON.stringify(settings);
|
||||||
pass_through_body_enabled: false,
|
handleInputChange('settings', settingsJson);
|
||||||
system_prompt: '',
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
const handleInputChange = (name, value) => {
|
const handleInputChange = (name, value) => {
|
||||||
if (formApiRef.current) {
|
if (formApiRef.current) {
|
||||||
@@ -360,6 +354,17 @@ const EditChannelModal = (props) => {
|
|||||||
data.system_prompt_override = false;
|
data.system_prompt_override = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.settings) {
|
||||||
|
try {
|
||||||
|
const parsedSettings = JSON.parse(data.settings);
|
||||||
|
data.azure_responses_version = parsedSettings.azure_responses_version || '';
|
||||||
|
} catch (error) {
|
||||||
|
console.error('解析其他设置失败:', error);
|
||||||
|
data.azure_responses_version = '';
|
||||||
|
data.region = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setInputs(data);
|
setInputs(data);
|
||||||
if (formApiRef.current) {
|
if (formApiRef.current) {
|
||||||
formApiRef.current.setValues(data);
|
formApiRef.current.setValues(data);
|
||||||
@@ -1377,6 +1382,15 @@ const EditChannelModal = (props) => {
|
|||||||
showClear
|
showClear
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<Form.Input
|
||||||
|
field='azure_responses_version'
|
||||||
|
label={t('默认 Responses API 版本,为空则使用上方版本')}
|
||||||
|
placeholder={t('例如:preview')}
|
||||||
|
onChange={(value) => handleChannelOtherSettingsChange('azure_responses_version', value)}
|
||||||
|
showClear
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user