فهرست منبع

feat: add reasoning effort parameter for O-series models in model configuration and settings

Burak Sormageç 4 ماه پیش
والد
کامیت
108be2f8a7

+ 16 - 2
chrome-extension/src/background/agent/helper.ts

@@ -29,7 +29,10 @@ function createOpenAIChatModel(
       // Add other ClientOptions if needed, e.g.?
       // dangerouslyAllowBrowser?: boolean;
     };
-    modelKwargs?: { max_completion_tokens: number };
+    modelKwargs?: {
+      max_completion_tokens: number;
+      reasoning_effort?: 'low' | 'medium' | 'high';
+    };
     topP?: number;
     temperature?: number;
     maxTokens?: number;
@@ -70,6 +73,11 @@ function createOpenAIChatModel(
     args.modelKwargs = {
       max_completion_tokens: maxTokens,
     };
+
+    // Add reasoning_effort parameter for o-series models if specified
+    if (modelConfig.reasoningEffort) {
+      args.modelKwargs.reasoning_effort = modelConfig.reasoningEffort;
+    }
   } else {
     args.topP = (modelConfig.parameters?.topP ?? 0.1) as number;
     args.temperature = (modelConfig.parameters?.temperature ?? 0.1) as number;
@@ -218,7 +226,13 @@ export function createChatModel(providerConfig: ProviderConfig, modelConfig: Mod
         model: deploymentName, // Set model = deployment name to fix Azure requests
         // For O series models, use modelKwargs instead of temperature/topP
         ...(isOSeriesModel
-          ? { modelKwargs: { max_completion_tokens: maxTokens } }
+          ? {
+              modelKwargs: {
+                max_completion_tokens: maxTokens,
+                // Add reasoning_effort parameter for Azure o-series models if specified
+                ...(modelConfig.reasoningEffort ? { reasoning_effort: modelConfig.reasoningEffort } : {}),
+              },
+            }
           : {
               temperature,
               topP,

+ 1 - 0
packages/storage/lib/settings/agentModels.ts

@@ -10,6 +10,7 @@ export interface ModelConfig {
   provider: string;
   modelName: string;
   parameters?: Record<string, unknown>;
+  reasoningEffort?: 'low' | 'medium' | 'high'; // For o-series models (OpenAI and Azure)
 }
 
 // Interface for storing multiple agent model configurations

+ 83 - 0
pages/options/src/components/ModelSettings.tsx

@@ -23,6 +23,11 @@ import {
 // Import chrome for messaging
 const IS_CHROME = typeof chrome !== 'undefined' && typeof chrome.runtime !== 'undefined';
 
+// Helper function to check if a model is an O-series model
+function isOpenAIOModel(modelName: string): boolean {
+  return modelName.startsWith('openai/o') || modelName.startsWith('o');
+}
+
 interface ModelSettingsProps {
   isDarkMode?: boolean; // Controls dark/light theme styling
 }
@@ -41,6 +46,13 @@ export const ModelSettings = ({ isDarkMode = false }: ModelSettingsProps) => {
     [AgentNameEnum.Planner]: { temperature: 0, topP: 0 },
     [AgentNameEnum.Validator]: { temperature: 0, topP: 0 },
   });
+
+  // State for reasoning effort for O-series models
+  const [reasoningEffort, setReasoningEffort] = useState<Record<AgentNameEnum, 'low' | 'medium' | 'high' | undefined>>({
+    [AgentNameEnum.Navigator]: undefined,
+    [AgentNameEnum.Planner]: undefined,
+    [AgentNameEnum.Validator]: undefined,
+  });
   const [newModelInputs, setNewModelInputs] = useState<Record<string, string>>({});
   const [isProviderSelectorOpen, setIsProviderSelectorOpen] = useState(false);
   const newlyAddedProviderRef = useRef<string | null>(null);
@@ -100,6 +112,13 @@ export const ModelSettings = ({ isDarkMode = false }: ModelSettingsProps) => {
                 },
               }));
             }
+            // Also load reasoningEffort if available
+            if (config.reasoningEffort) {
+              setReasoningEffort(prev => ({
+                ...prev,
+                [agent]: config.reasoningEffort as 'low' | 'medium' | 'high',
+              }));
+            }
           }
         }
         setSelectedModels(models);
@@ -521,10 +540,26 @@ export const ModelSettings = ({ isDarkMode = false }: ModelSettingsProps) => {
           console.log(`[handleModelChange] Available deployments:`, providerConfig.azureDeploymentNames || []);
         }
 
+        // Reset reasoning effort if switching models
+        if (isOpenAIOModel(model)) {
+          // Keep existing reasoning effort if already set for O-series models
+          setReasoningEffort(prev => ({
+            ...prev,
+            [agentName]: prev[agentName] || 'medium', // Default to medium if not set
+          }));
+        } else {
+          // Clear reasoning effort for non-O-series models
+          setReasoningEffort(prev => ({
+            ...prev,
+            [agentName]: undefined,
+          }));
+        }
+
         await agentModelStore.setAgentModel(agentName, {
           provider,
           modelName: model,
           parameters: newParameters,
+          reasoningEffort: isOpenAIOModel(model) ? reasoningEffort[agentName] || 'medium' : undefined,
         });
       } else {
         // Reset storage if no model is selected
@@ -535,6 +570,32 @@ export const ModelSettings = ({ isDarkMode = false }: ModelSettingsProps) => {
     }
   };
 
+  const handleReasoningEffortChange = async (agentName: AgentNameEnum, value: 'low' | 'medium' | 'high') => {
+    setReasoningEffort(prev => ({
+      ...prev,
+      [agentName]: value,
+    }));
+
+    // Only update if we have a selected model
+    if (selectedModels[agentName] && isOpenAIOModel(selectedModels[agentName])) {
+      try {
+        // Find provider
+        const provider = getProviderForModel(selectedModels[agentName]);
+
+        if (provider) {
+          await agentModelStore.setAgentModel(agentName, {
+            provider,
+            modelName: selectedModels[agentName],
+            parameters: modelParameters[agentName],
+            reasoningEffort: value,
+          });
+        }
+      } catch (error) {
+        console.error('Error saving reasoning effort:', error);
+      }
+    }
+  };
+
   const handleParameterChange = async (agentName: AgentNameEnum, paramName: 'temperature' | 'topP', value: number) => {
     const newParameters = {
       ...modelParameters[agentName],
@@ -711,6 +772,28 @@ export const ModelSettings = ({ isDarkMode = false }: ModelSettingsProps) => {
             </div>
           </div>
         </div>
+
+        {/* Reasoning Effort Selector (only for O-series models) */}
+        {selectedModels[agentName] && isOpenAIOModel(selectedModels[agentName]) && (
+          <div className="flex items-center">
+            <label
+              htmlFor={`${agentName}-reasoning-effort`}
+              className={`w-24 text-sm font-medium ${isDarkMode ? 'text-gray-300' : 'text-gray-700'}`}>
+              Reasoning
+            </label>
+            <div className="flex flex-1 items-center space-x-2">
+              <select
+                id={`${agentName}-reasoning-effort`}
+                value={reasoningEffort[agentName] || 'medium'}
+                onChange={e => handleReasoningEffortChange(agentName, e.target.value as 'low' | 'medium' | 'high')}
+                className={`flex-1 rounded-md border text-sm ${isDarkMode ? 'border-slate-600 bg-slate-700 text-gray-200' : 'border-gray-300 bg-white text-gray-700'} px-3 py-2`}>
+                <option value="low">Low (Faster)</option>
+                <option value="medium">Medium (Balanced)</option>
+                <option value="high">High (More thorough)</option>
+              </select>
+            </div>
+          </div>
+        )}
       </div>
     </div>
   );