mirror of
https://github.com/abhinavxd/libredesk.git
synced 2026-10-14 00:50:36 +00:00
add reasoning effort setting for providers
Add a reasoning effort field to the completion provider config, sent as-is to the model. Reasoning models such as GPT-5.x need it set to "none" to use tools. Also switch to max_completion_tokens.
This commit is contained in:
@@ -79,6 +79,17 @@
|
||||
</FormItem>
|
||||
</FormField>
|
||||
|
||||
<FormField v-slot="{ componentField }" name="reasoning_effort">
|
||||
<FormItem>
|
||||
<FormLabel>{{ t('admin.ai.reasoningEffort') }}</FormLabel>
|
||||
<FormControl>
|
||||
<Input type="text" placeholder="none" v-bind="componentField" />
|
||||
</FormControl>
|
||||
<FormDescription>{{ t('admin.ai.reasoningEffortHint') }}</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
|
||||
<FormField v-slot="{ componentField }" name="instructions">
|
||||
<FormItem class="md:col-span-2">
|
||||
<FormLabel>{{ t('admin.ai.instructions') }}</FormLabel>
|
||||
@@ -264,6 +275,7 @@ const form = useForm({
|
||||
base_url: z.string().optional(),
|
||||
api_key: z.string().optional(),
|
||||
instructions: z.string().optional(),
|
||||
reasoning_effort: z.string().optional(),
|
||||
temperature: numberField().refine((v) => isBlank(v) || inRange(v, 0, 2), {
|
||||
message: t('admin.ai.temperatureRange')
|
||||
}),
|
||||
@@ -281,6 +293,7 @@ const form = useForm({
|
||||
base_url: '',
|
||||
api_key: '',
|
||||
instructions: '',
|
||||
reasoning_effort: '',
|
||||
temperature: fieldDefaults.temperature,
|
||||
max_tokens: fieldDefaults.maxTokens,
|
||||
dimensions: fieldDefaults.dimensions,
|
||||
@@ -298,6 +311,7 @@ onMounted(async () => {
|
||||
base_url: data.base_url || '',
|
||||
api_key: data.api_key || '',
|
||||
instructions: data.instructions || '',
|
||||
reasoning_effort: data.reasoning_effort || '',
|
||||
// Fall back to sensible defaults when the provider has nothing saved (0/absent).
|
||||
temperature: data.temperature != null ? String(data.temperature) : fieldDefaults.temperature,
|
||||
max_tokens: data.max_tokens ? String(data.max_tokens) : fieldDefaults.maxTokens,
|
||||
@@ -321,6 +335,7 @@ const onSubmit = form.handleSubmit(async (values) => {
|
||||
if (props.showCompletionFields) {
|
||||
payload.instructions = values.instructions || ''
|
||||
payload.vision = !!values.vision
|
||||
payload.reasoning_effort = (values.reasoning_effort || '').trim()
|
||||
if (values.temperature !== '' && values.temperature != null)
|
||||
payload.temperature = Number(values.temperature)
|
||||
if (values.max_tokens !== '' && values.max_tokens != null)
|
||||
|
||||
@@ -130,6 +130,8 @@
|
||||
"admin.ai.temperatureRange": "Temperature must be a number between 0 and 2.",
|
||||
"admin.ai.positiveNumber": "Enter a whole number greater than 0.",
|
||||
"admin.ai.maxTokens": "Max tokens",
|
||||
"admin.ai.reasoningEffort": "Reasoning effort",
|
||||
"admin.ai.reasoningEffortHint": "Leave blank for most models. Reasoning models such as GPT-5.x require 'none' to use tools; other values are 'low', 'medium' or 'high'.",
|
||||
"admin.ai.instructions": "Custom instructions",
|
||||
"admin.ai.instructionsHint": "Added to every Copilot and reply-draft prompt. Use it to set tone and format, e.g. keep replies under 3 sentences, match the brand voice, always reply in the customer's language.",
|
||||
"admin.ai.vision": "Model supports image input",
|
||||
|
||||
+10
-9
@@ -218,15 +218,16 @@ func (m *Manager) UpdateProviderConfig(providerType string, in models.ProviderCo
|
||||
}
|
||||
|
||||
cfg := models.ProviderConfig{
|
||||
Provider: "openai",
|
||||
BaseURL: in.BaseURL,
|
||||
APIKey: apiKey,
|
||||
Model: in.Model,
|
||||
Temperature: in.Temperature,
|
||||
MaxTokens: in.MaxTokens,
|
||||
Dimensions: in.Dimensions,
|
||||
Instructions: in.Instructions,
|
||||
Vision: in.Vision,
|
||||
Provider: "openai",
|
||||
BaseURL: in.BaseURL,
|
||||
APIKey: apiKey,
|
||||
Model: in.Model,
|
||||
Temperature: in.Temperature,
|
||||
MaxTokens: in.MaxTokens,
|
||||
Dimensions: in.Dimensions,
|
||||
Instructions: in.Instructions,
|
||||
Vision: in.Vision,
|
||||
ReasoningEffort: in.ReasoningEffort,
|
||||
}
|
||||
b, err := json.Marshal(cfg)
|
||||
if err != nil {
|
||||
|
||||
@@ -45,6 +45,9 @@ type ProviderConfig struct {
|
||||
MaxTokens int `json:"max_tokens"`
|
||||
Dimensions int `json:"dimensions"`
|
||||
Instructions string `json:"instructions"`
|
||||
// ReasoningEffort, when set, is sent as-is. Reasoning models (e.g. GPT-5.x) need "none" to use
|
||||
// tools on /chat/completions; leave blank for models that reject the param.
|
||||
ReasoningEffort string `json:"reasoning_effort,omitempty"`
|
||||
// Vision marks the completion model as accepting image input; when false the harness drops image parts.
|
||||
Vision bool `json:"vision"`
|
||||
}
|
||||
|
||||
@@ -84,13 +84,19 @@ func (o *OpenAIClient) SendChatCompletion(payload models.ChatCompletionPayload)
|
||||
o.lo.Debug("chat completion request", "model", model, "messages", len(messages), "images", sentImages, "vision", o.cfg.Vision, "tools", len(payload.Tools))
|
||||
|
||||
body := map[string]any{
|
||||
"model": model,
|
||||
"messages": messages,
|
||||
"max_tokens": maxTokens,
|
||||
"model": model,
|
||||
"messages": messages,
|
||||
"max_completion_tokens": maxTokens,
|
||||
}
|
||||
// Only send optional params the admin set. Reasoning models (e.g. GPT-5.x) reject a non-default
|
||||
// temperature and require reasoning_effort "none" to use tools on /chat/completions; leave
|
||||
// temperature blank and set reasoning_effort accordingly for those.
|
||||
if o.cfg.Temperature != nil {
|
||||
body["temperature"] = *o.cfg.Temperature
|
||||
}
|
||||
if o.cfg.ReasoningEffort != "" {
|
||||
body["reasoning_effort"] = o.cfg.ReasoningEffort
|
||||
}
|
||||
if len(payload.Tools) > 0 {
|
||||
body["tools"] = payload.Tools
|
||||
body["tool_choice"] = "auto"
|
||||
|
||||
Reference in New Issue
Block a user