mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-09-28 12:26:46 +08:00
fix(reasoning): apply explicit per-call levels without runner config caching
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { hasModelReasoningAbility } from '@/app/home/components/reasoning/model-reasoning';
|
||||
import {
|
||||
DynamicFormItemType,
|
||||
IDynamicFormItemSchema,
|
||||
@@ -193,8 +194,7 @@ export default function DynamicFormItemComponent({
|
||||
{model.abilities?.includes('func_call') && (
|
||||
<Wrench className="h-3 w-3 text-muted-foreground" />
|
||||
)}
|
||||
{(model.reasoning_capabilities?.supported === true ||
|
||||
model.abilities?.includes('reasoning')) && (
|
||||
{hasModelReasoningAbility(model) && (
|
||||
<BrainCircuit
|
||||
className="h-3 w-3 shrink-0 text-muted-foreground"
|
||||
aria-label={t('models.reasoningAbility')}
|
||||
@@ -1260,15 +1260,11 @@ export default function DynamicFormItemComponent({
|
||||
|
||||
const updateModelReasoning = (
|
||||
modelUuid: string,
|
||||
level: ReasoningLevel | undefined,
|
||||
level: ReasoningLevel,
|
||||
) => {
|
||||
if (!modelUuid) return;
|
||||
const updated = { ...modelValue.reasoning };
|
||||
if (level === undefined) {
|
||||
delete updated[modelUuid];
|
||||
} else {
|
||||
updated[modelUuid] = level;
|
||||
}
|
||||
updated[modelUuid] = level;
|
||||
updateValue({ reasoning: updated });
|
||||
};
|
||||
|
||||
@@ -1297,6 +1293,7 @@ export default function DynamicFormItemComponent({
|
||||
const model = llmModels.find(
|
||||
(candidate) => candidate.uuid === modelUuid,
|
||||
);
|
||||
if (!hasModelReasoningAbility(model)) return null;
|
||||
const currentLevel =
|
||||
modelValue.reasoning[modelUuid] || 'provider_default';
|
||||
const availableLevels = model?.reasoning_capabilities?.levels || [
|
||||
@@ -1310,8 +1307,6 @@ export default function DynamicFormItemComponent({
|
||||
<ReasoningLevelPicker
|
||||
value={currentLevel}
|
||||
levels={levels}
|
||||
inherited={!Object.hasOwn(modelValue.reasoning, modelUuid)}
|
||||
onInherit={() => updateModelReasoning(modelUuid, undefined)}
|
||||
onChange={(level) => updateModelReasoning(modelUuid, level)}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { hasModelReasoningAbility } from '../../reasoning/model-reasoning';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Trash2, Eye, Wrench, Check, BrainCircuit } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
@@ -175,8 +176,7 @@ export default function ModelItem({
|
||||
|
||||
const supportsReasoning =
|
||||
modelType === 'llm' &&
|
||||
((model as LLMModel).reasoning_capabilities?.supported === true ||
|
||||
(model as LLMModel).abilities?.includes('reasoning'));
|
||||
hasModelReasoningAbility(model as LLMModel, isLangBotModels);
|
||||
const canSaveModel = !isLangBotModels;
|
||||
|
||||
// Check if popover should be disabled (space models when not logged in)
|
||||
@@ -353,7 +353,11 @@ export default function ModelItem({
|
||||
<div className="flex items-center gap-2">
|
||||
<Checkbox
|
||||
id={`edit-reasoning-${model.uuid}`}
|
||||
checked={editAbilities.includes('reasoning')}
|
||||
checked={
|
||||
isLangBotModels
|
||||
? supportsReasoning
|
||||
: editAbilities.includes('reasoning')
|
||||
}
|
||||
disabled={isLangBotModels}
|
||||
onCheckedChange={(checked) =>
|
||||
toggleAbility('reasoning', checked as boolean)
|
||||
|
||||
@@ -37,8 +37,6 @@ interface ReasoningLevelPickerProps {
|
||||
value: ReasoningLevel;
|
||||
levels: ReasoningLevel[];
|
||||
disabled?: boolean;
|
||||
inherited?: boolean;
|
||||
onInherit?: () => void;
|
||||
onChange: (value: ReasoningLevel) => void;
|
||||
}
|
||||
|
||||
@@ -46,8 +44,6 @@ export default function ReasoningLevelPicker({
|
||||
value,
|
||||
levels,
|
||||
disabled = false,
|
||||
inherited = false,
|
||||
onInherit,
|
||||
onChange,
|
||||
}: ReasoningLevelPickerProps) {
|
||||
const { t } = useTranslation();
|
||||
@@ -56,14 +52,8 @@ export default function ReasoningLevelPicker({
|
||||
const safeValue: ReasoningLevel = safeLevels.includes(value)
|
||||
? value
|
||||
: safeLevels[0];
|
||||
const isInherited = Boolean(onInherit && inherited);
|
||||
const currentLabel = t(
|
||||
isInherited
|
||||
? 'models.reasoningLevels.useModelSetting'
|
||||
: REASONING_LEVEL_LABEL_KEYS[safeValue],
|
||||
);
|
||||
const isExplicit =
|
||||
!isInherited && (Boolean(onInherit) || safeValue !== 'provider_default');
|
||||
const currentLabel = t(REASONING_LEVEL_LABEL_KEYS[safeValue]);
|
||||
const isExplicit = safeValue !== 'provider_default';
|
||||
const currentIndex = Math.max(0, safeLevels.indexOf(safeValue));
|
||||
|
||||
return (
|
||||
@@ -73,9 +63,9 @@ export default function ReasoningLevelPicker({
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
disabled={disabled || (safeLevels.length <= 1 && !onInherit)}
|
||||
disabled={disabled || safeLevels.length <= 1}
|
||||
aria-label={`${t('models.reasoningLevel')}: ${currentLabel}`}
|
||||
className="h-9 w-9 shrink-0 gap-1.5 px-2.5 text-xs font-normal sm:w-auto sm:max-w-36"
|
||||
className="h-9 w-9 shrink-0 gap-1.5 px-2.5 text-xs font-normal sm:w-auto sm:max-w-52"
|
||||
>
|
||||
<BrainCircuit
|
||||
className={`size-4 shrink-0 ${isExplicit ? 'text-primary' : 'text-muted-foreground'}`}
|
||||
@@ -87,29 +77,17 @@ export default function ReasoningLevelPicker({
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent align="end" className="w-[272px] p-4">
|
||||
{onInherit && (
|
||||
<div className="mb-3 flex flex-col gap-1">
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
aria-pressed={isInherited}
|
||||
onClick={onInherit}
|
||||
>
|
||||
{t('models.reasoningLevels.useModelSetting')}
|
||||
</Button>
|
||||
{safeLevels.includes('provider_default') && (
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
aria-pressed={!isInherited && safeValue === 'provider_default'}
|
||||
onClick={() => onChange('provider_default')}
|
||||
>
|
||||
{t(REASONING_LEVEL_LABEL_KEYS.provider_default)}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
{safeLevels.includes('provider_default') && (
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="mb-3 w-full"
|
||||
aria-pressed={safeValue === 'provider_default'}
|
||||
onClick={() => onChange('provider_default')}
|
||||
>
|
||||
{t(REASONING_LEVEL_LABEL_KEYS.provider_default)}
|
||||
</Button>
|
||||
)}
|
||||
<div className="flex h-5 items-center gap-0.5 text-sm text-muted-foreground">
|
||||
<span>{currentLabel}</span>
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { LANGBOT_MODELS_PROVIDER_REQUESTER } from '../models-dialog/types';
|
||||
|
||||
interface ModelReasoningInfo {
|
||||
abilities?: string[];
|
||||
reasoning_capabilities?: { supported?: boolean };
|
||||
provider?: { requester?: string };
|
||||
}
|
||||
|
||||
export function hasModelReasoningAbility(
|
||||
model: ModelReasoningInfo | undefined,
|
||||
isLangBotModels = model?.provider?.requester ===
|
||||
LANGBOT_MODELS_PROVIDER_REQUESTER,
|
||||
): boolean {
|
||||
return Boolean(
|
||||
model?.abilities?.includes('reasoning') ||
|
||||
(isLangBotModels && model?.reasoning_capabilities?.supported === true),
|
||||
);
|
||||
}
|
||||
@@ -264,8 +264,7 @@ const enUS = {
|
||||
reasoningAbility: 'Reasoning',
|
||||
reasoningLevel: 'Reasoning level',
|
||||
reasoningLevels: {
|
||||
useModelSetting: 'Use model setting',
|
||||
providerDefault: 'Provider default',
|
||||
providerDefault: 'Use provider default',
|
||||
disabled: 'Off',
|
||||
enabled: 'On',
|
||||
minimal: 'Minimal',
|
||||
|
||||
@@ -265,8 +265,7 @@ const esES = {
|
||||
reasoningAbility: 'Razonamiento',
|
||||
reasoningLevel: 'Nivel de razonamiento',
|
||||
reasoningLevels: {
|
||||
useModelSetting: 'Usar ajuste del modelo',
|
||||
providerDefault: 'Predeterminado del proveedor',
|
||||
providerDefault: 'Usar valor predeterminado del proveedor',
|
||||
disabled: 'Desactivado',
|
||||
enabled: 'Activado',
|
||||
minimal: 'Mínimo',
|
||||
|
||||
@@ -269,8 +269,7 @@ const jaJP = {
|
||||
reasoningAbility: '推論',
|
||||
reasoningLevel: '推論レベル',
|
||||
reasoningLevels: {
|
||||
useModelSetting: 'モデル設定を使用',
|
||||
providerDefault: 'Provider デフォルト',
|
||||
providerDefault: 'プロバイダーの既定値を使用',
|
||||
disabled: 'オフ',
|
||||
enabled: 'オン',
|
||||
minimal: '最小',
|
||||
|
||||
@@ -261,8 +261,7 @@ const ruRU = {
|
||||
reasoningAbility: 'Рассуждение',
|
||||
reasoningLevel: 'Уровень рассуждений',
|
||||
reasoningLevels: {
|
||||
useModelSetting: 'Настройка модели',
|
||||
providerDefault: 'По умолчанию провайдера',
|
||||
providerDefault: 'Использовать настройки поставщика',
|
||||
disabled: 'Выключено',
|
||||
enabled: 'Включено',
|
||||
minimal: 'Минимальный',
|
||||
|
||||
@@ -256,8 +256,7 @@ const thTH = {
|
||||
reasoningAbility: 'ความสามารถในการให้เหตุผล',
|
||||
reasoningLevel: 'ระดับการให้เหตุผล',
|
||||
reasoningLevels: {
|
||||
useModelSetting: 'ใช้การตั้งค่าโมเดล',
|
||||
providerDefault: 'ค่าเริ่มต้นของผู้ให้บริการ',
|
||||
providerDefault: 'ใช้ค่าเริ่มต้นของผู้ให้บริการ',
|
||||
disabled: 'ปิด',
|
||||
enabled: 'เปิด',
|
||||
minimal: 'ต่ำสุด',
|
||||
|
||||
@@ -260,8 +260,7 @@ const viVN = {
|
||||
reasoningAbility: 'Khả năng suy luận',
|
||||
reasoningLevel: 'Mức độ suy luận',
|
||||
reasoningLevels: {
|
||||
useModelSetting: 'Dùng cài đặt mô hình',
|
||||
providerDefault: 'Mặc định của nhà cung cấp',
|
||||
providerDefault: 'Dùng giá trị mặc định của nhà cung cấp',
|
||||
disabled: 'Tắt',
|
||||
enabled: 'Bật',
|
||||
minimal: 'Tối thiểu',
|
||||
|
||||
@@ -254,8 +254,7 @@ const zhHans = {
|
||||
reasoningAbility: '思考能力',
|
||||
reasoningLevel: '思考档位',
|
||||
reasoningLevels: {
|
||||
useModelSetting: '使用模型设置',
|
||||
providerDefault: 'Provider 默认',
|
||||
providerDefault: '使用供应商默认值',
|
||||
disabled: '关闭',
|
||||
enabled: '开启',
|
||||
minimal: '最低',
|
||||
|
||||
@@ -248,8 +248,7 @@ const zhHant = {
|
||||
reasoningAbility: '思考能力',
|
||||
reasoningLevel: '思考等級',
|
||||
reasoningLevels: {
|
||||
useModelSetting: '使用模型設定',
|
||||
providerDefault: '供應商預設',
|
||||
providerDefault: '使用供應商預設值',
|
||||
disabled: '關閉',
|
||||
enabled: '開啟',
|
||||
minimal: '最低',
|
||||
|
||||
Reference in New Issue
Block a user