✨ feat: Add ChannelOtherSettings to manage additional channel configurations
This commit is contained in:
@@ -22,6 +22,7 @@ const (
|
||||
ContextKeyChannelBaseUrl ContextKey = "base_url"
|
||||
ContextKeyChannelType ContextKey = "channel_type"
|
||||
ContextKeyChannelSetting ContextKey = "channel_setting"
|
||||
ContextKeyChannelOtherSetting ContextKey = "channel_other_setting"
|
||||
ContextKeyChannelParamOverride ContextKey = "param_override"
|
||||
ContextKeyChannelOrganization ContextKey = "channel_organization"
|
||||
ContextKeyChannelAutoBan ContextKey = "auto_ban"
|
||||
|
||||
@@ -8,3 +8,7 @@ type ChannelSettings struct {
|
||||
SystemPrompt string `json:"system_prompt,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.ContextKeyChannelCreateTime, channel.CreatedTime)
|
||||
common.SetContextKey(c, constant.ContextKeyChannelSetting, channel.GetSetting())
|
||||
common.SetContextKey(c, constant.ContextKeyChannelOtherSetting, channel.GetOtherSettings())
|
||||
common.SetContextKey(c, constant.ContextKeyChannelParamOverride, channel.GetParamOverride())
|
||||
if nil != channel.OpenAIOrganization && *channel.OpenAIOrganization != "" {
|
||||
common.SetContextKey(c, constant.ContextKeyChannelOrganization, *channel.OpenAIOrganization)
|
||||
|
||||
@@ -42,7 +42,7 @@ type Channel struct {
|
||||
Priority *int64 `json:"priority" gorm:"bigint;default:0"`
|
||||
AutoBan *int `json:"auto_ban" gorm:"default:1"`
|
||||
OtherInfo string `json:"other_info"`
|
||||
Settings string `json:"settings"`
|
||||
OtherSettings string `json:"settings" gorm:"column:settings"` // 其他设置
|
||||
Tag *string `json:"tag" gorm:"index"`
|
||||
Setting *string `json:"setting" 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))
|
||||
}
|
||||
|
||||
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{} {
|
||||
paramOverride := make(map[string]interface{})
|
||||
if channel.ParamOverride != nil && *channel.ParamOverride != "" {
|
||||
|
||||
@@ -128,7 +128,11 @@ func (a *Adaptor) GetRequestURL(info *relaycommon.RelayInfo) (string, error) {
|
||||
|
||||
// 特殊处理 responses API
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -102,6 +102,7 @@ type RelayInfo struct {
|
||||
AudioUsage bool
|
||||
ReasoningEffort string
|
||||
ChannelSetting dto.ChannelSettings
|
||||
ChannelOtherSettings dto.ChannelOtherSettings
|
||||
ParamOverride map[string]interface{}
|
||||
UserSetting dto.UserSetting
|
||||
UserEmail string
|
||||
@@ -292,6 +293,12 @@ func GenRelayInfo(c *gin.Context) *RelayInfo {
|
||||
if ok {
|
||||
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)
|
||||
if ok {
|
||||
info.UserSetting = userSetting
|
||||
|
||||
@@ -132,6 +132,7 @@ const EditChannelModal = (props) => {
|
||||
pass_through_body_enabled: false,
|
||||
system_prompt: '',
|
||||
system_prompt_override: false,
|
||||
settings: '',
|
||||
};
|
||||
const [batch, setBatch] = useState(false);
|
||||
const [multiToSingle, setMultiToSingle] = useState(false);
|
||||
@@ -187,38 +188,31 @@ const EditChannelModal = (props) => {
|
||||
handleInputChange('setting', settingsJson);
|
||||
};
|
||||
|
||||
// 解析渠道设置JSON为单独的状态
|
||||
const parseChannelSettings = (settingJson) => {
|
||||
const handleChannelOtherSettingsChange = (key, value) => {
|
||||
// 更新内部状态
|
||||
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 {
|
||||
if (settingJson && settingJson.trim()) {
|
||||
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: '',
|
||||
});
|
||||
}
|
||||
settings = JSON.parse(inputs.settings);
|
||||
} catch (error) {
|
||||
console.error('解析渠道设置失败:', error);
|
||||
setChannelSettings({
|
||||
force_format: false,
|
||||
thinking_to_content: false,
|
||||
proxy: '',
|
||||
pass_through_body_enabled: false,
|
||||
system_prompt: '',
|
||||
});
|
||||
console.error('解析设置失败:', error);
|
||||
}
|
||||
}
|
||||
settings[key] = value;
|
||||
const settingsJson = JSON.stringify(settings);
|
||||
handleInputChange('settings', settingsJson);
|
||||
}
|
||||
};
|
||||
|
||||
const handleInputChange = (name, value) => {
|
||||
if (formApiRef.current) {
|
||||
@@ -360,6 +354,17 @@ const EditChannelModal = (props) => {
|
||||
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);
|
||||
if (formApiRef.current) {
|
||||
formApiRef.current.setValues(data);
|
||||
@@ -1377,6 +1382,15 @@ const EditChannelModal = (props) => {
|
||||
showClear
|
||||
/>
|
||||
</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