Skip to content

Commit c734742

Browse files
Rework failover agent invocation selection for agent and ephemmeral agent (#2515)
* Rework failover agent invocation selection for agent and ephemmeral agent * update order of check * update order of check * lint
1 parent 11b7ccd commit c734742

File tree

2 files changed

+90
-52
lines changed

2 files changed

+90
-52
lines changed

server/utils/agents/ephemeral.js

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -99,30 +99,69 @@ class EphemeralAgentHandler extends AgentHandler {
9999
}
100100
}
101101

102+
/**
103+
* Attempts to find a fallback provider and model to use if the workspace
104+
* does not have an explicit `agentProvider` and `agentModel` set.
105+
* 1. Fallback to the workspace `chatProvider` and `chatModel` if they exist.
106+
* 2. Fallback to the system `LLM_PROVIDER` and try to load the the associated default model via ENV params or a base available model.
107+
* 3. Otherwise, return null - will likely throw an error the user can act on.
108+
* @returns {object|null} - An object with provider and model keys.
109+
*/
110+
#getFallbackProvider() {
111+
// First, fallback to the workspace chat provider and model if they exist
112+
if (this.#workspace.chatProvider && this.#workspace.chatModel) {
113+
return {
114+
provider: this.#workspace.chatProvider,
115+
model: this.#workspace.chatModel,
116+
};
117+
}
118+
119+
// If workspace does not have chat provider and model fallback
120+
// to system provider and try to load provider default model
121+
const systemProvider = process.env.LLM_PROVIDER;
122+
const systemModel = this.providerDefault(systemProvider);
123+
if (systemProvider && systemModel) {
124+
return {
125+
provider: systemProvider,
126+
model: systemModel,
127+
};
128+
}
129+
130+
return null;
131+
}
132+
102133
/**
103134
* Finds or assumes the model preference value to use for API calls.
104135
* If multi-model loading is supported, we use their agent model selection of the workspace
105136
* If not supported, we attempt to fallback to the system provider value for the LLM preference
106137
* and if that fails - we assume a reasonable base model to exist.
107-
* @returns {string} the model preference value to use in API calls
138+
* @returns {string|null} the model preference value to use in API calls
108139
*/
109140
#fetchModel() {
110-
if (!Object.keys(this.noProviderModelDefault).includes(this.provider))
111-
return this.#workspace.agentModel || this.providerDefault();
141+
// Provider was not explicitly set for workspace, so we are going to run our fallback logic
142+
// that will set a provider and model for us to use.
143+
if (!this.provider) {
144+
const fallback = this.#getFallbackProvider();
145+
if (!fallback) throw new Error("No valid provider found for the agent.");
146+
this.provider = fallback.provider; // re-set the provider to the fallback provider so it is not null.
147+
return fallback.model; // set its defined model based on fallback logic.
148+
}
112149

113-
// Provider has no reliable default (cant load many models) - so we need to look at system
114-
// for the model param.
115-
const sysModelKey = this.noProviderModelDefault[this.provider];
116-
if (!!sysModelKey)
117-
return process.env[sysModelKey] ?? this.providerDefault();
150+
// The provider was explicitly set, so check if the workspace has an agent model set.
151+
if (this.invocation.workspace.agentModel)
152+
return this.invocation.workspace.agentModel;
118153

119-
// If all else fails - look at the provider default list
154+
// Otherwise, we have no model to use - so guess a default model to use via the provider
155+
// and it's system ENV params and if that fails - we return either a base model or null.
120156
return this.providerDefault();
121157
}
122158

123159
#providerSetupAndCheck() {
124-
this.provider = this.#workspace.agentProvider;
160+
this.provider = this.#workspace.agentProvider ?? null;
125161
this.model = this.#fetchModel();
162+
163+
if (!this.provider)
164+
throw new Error("No valid provider found for the agent.");
126165
this.log(`Start ${this.#invocationUUID}::${this.provider}:${this.model}`);
127166
this.checkSetup();
128167
}

server/utils/agents/index.js

Lines changed: 41 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,6 @@ const ImportedPlugin = require("./imported");
1111
class AgentHandler {
1212
#invocationUUID;
1313
#funcsToLoad = [];
14-
noProviderModelDefault = {
15-
azure: "OPEN_MODEL_PREF",
16-
lmstudio: "LMSTUDIO_MODEL_PREF",
17-
textgenwebui: null, // does not even use `model` in API req
18-
"generic-openai": "GENERIC_OPEN_AI_MODEL_PREF",
19-
bedrock: "AWS_BEDROCK_LLM_MODEL_PREFERENCE",
20-
};
2114
invocation = null;
2215
aibitat = null;
2316
channel = null;
@@ -184,53 +177,70 @@ class AgentHandler {
184177
}
185178
}
186179

180+
/**
181+
* Finds the default model for a given provider. If no default model is set for it's associated ENV then
182+
* it will return a reasonable base model for the provider if one exists.
183+
* @param {string} provider - The provider to find the default model for.
184+
* @returns {string|null} The default model for the provider.
185+
*/
187186
providerDefault(provider = this.provider) {
188187
switch (provider) {
189188
case "openai":
190-
return "gpt-4o";
189+
return process.env.OPEN_MODEL_PREF ?? "gpt-4o";
191190
case "anthropic":
192-
return "claude-3-sonnet-20240229";
191+
return process.env.ANTHROPIC_MODEL_PREF ?? "claude-3-sonnet-20240229";
193192
case "lmstudio":
194-
return "server-default";
193+
return process.env.LMSTUDIO_MODEL_PREF ?? "server-default";
195194
case "ollama":
196-
return "llama3:latest";
195+
return process.env.OLLAMA_MODEL_PREF ?? "llama3:latest";
197196
case "groq":
198-
return "llama3-70b-8192";
197+
return process.env.GROQ_MODEL_PREF ?? "llama3-70b-8192";
199198
case "togetherai":
200-
return "mistralai/Mixtral-8x7B-Instruct-v0.1";
199+
return (
200+
process.env.TOGETHER_AI_MODEL_PREF ??
201+
"mistralai/Mixtral-8x7B-Instruct-v0.1"
202+
);
201203
case "azure":
202-
return "gpt-3.5-turbo";
203-
case "koboldcpp":
204204
return null;
205+
case "koboldcpp":
206+
return process.env.KOBOLD_CPP_MODEL_PREF ?? null;
205207
case "gemini":
206-
return "gemini-pro";
208+
return process.env.GEMINI_MODEL_PREF ?? "gemini-pro";
207209
case "localai":
208-
return null;
210+
return process.env.LOCAL_AI_MODEL_PREF ?? null;
209211
case "openrouter":
210-
return "openrouter/auto";
212+
return process.env.OPENROUTER_MODEL_PREF ?? "openrouter/auto";
211213
case "mistral":
212-
return "mistral-medium";
214+
return process.env.MISTRAL_MODEL_PREF ?? "mistral-medium";
213215
case "generic-openai":
214-
return null;
216+
return process.env.GENERIC_OPEN_AI_MODEL_PREF ?? null;
215217
case "perplexity":
216-
return "sonar-small-online";
218+
return process.env.PERPLEXITY_MODEL_PREF ?? "sonar-small-online";
217219
case "textgenwebui":
218220
return null;
219221
case "bedrock":
220-
return null;
222+
return process.env.AWS_BEDROCK_LLM_MODEL_PREFERENCE ?? null;
221223
case "fireworksai":
222-
return null;
224+
return process.env.FIREWORKS_AI_LLM_MODEL_PREF ?? null;
223225
case "deepseek":
224-
return "deepseek-chat";
226+
return process.env.DEEPSEEK_MODEL_PREF ?? "deepseek-chat";
225227
case "litellm":
226-
return null;
228+
return process.env.LITE_LLM_MODEL_PREF ?? null;
227229
case "apipie":
228-
return null;
230+
return process.env.APIPIE_LLM_MODEL_PREF ?? null;
229231
default:
230-
return "unknown";
232+
return null;
231233
}
232234
}
233235

236+
/**
237+
* Attempts to find a fallback provider and model to use if the workspace
238+
* does not have an explicit `agentProvider` and `agentModel` set.
239+
* 1. Fallback to the workspace `chatProvider` and `chatModel` if they exist.
240+
* 2. Fallback to the system `LLM_PROVIDER` and try to load the the associated default model via ENV params or a base available model.
241+
* 3. Otherwise, return null - will likely throw an error the user can act on.
242+
* @returns {object|null} - An object with provider and model keys.
243+
*/
234244
#getFallbackProvider() {
235245
// First, fallback to the workspace chat provider and model if they exist
236246
if (
@@ -262,7 +272,7 @@ class AgentHandler {
262272
* If multi-model loading is supported, we use their agent model selection of the workspace
263273
* If not supported, we attempt to fallback to the system provider value for the LLM preference
264274
* and if that fails - we assume a reasonable base model to exist.
265-
* @returns {string} the model preference value to use in API calls
275+
* @returns {string|null} the model preference value to use in API calls
266276
*/
267277
#fetchModel() {
268278
// Provider was not explicitly set for workspace, so we are going to run our fallback logic
@@ -275,21 +285,11 @@ class AgentHandler {
275285
}
276286

277287
// The provider was explicitly set, so check if the workspace has an agent model set.
278-
if (this.invocation.workspace.agentModel) {
288+
if (this.invocation.workspace.agentModel)
279289
return this.invocation.workspace.agentModel;
280-
}
281290

282-
// If the provider we are using is not supported or does not support multi-model loading
283-
// then we use the default model for the provider.
284-
if (!Object.keys(this.noProviderModelDefault).includes(this.provider)) {
285-
return this.providerDefault();
286-
}
287-
288-
// Load the model from the system environment variable for providers with no multi-model loading.
289-
const sysModelKey = this.noProviderModelDefault[this.provider];
290-
if (sysModelKey) return process.env[sysModelKey] ?? this.providerDefault();
291-
292-
// Otherwise, we have no model to use - so guess a default model to use.
291+
// Otherwise, we have no model to use - so guess a default model to use via the provider
292+
// and it's system ENV params and if that fails - we return either a base model or null.
293293
return this.providerDefault();
294294
}
295295

@@ -299,7 +299,6 @@ class AgentHandler {
299299

300300
if (!this.provider)
301301
throw new Error("No valid provider found for the agent.");
302-
303302
this.log(`Start ${this.#invocationUUID}::${this.provider}:${this.model}`);
304303
this.checkSetup();
305304
}

0 commit comments

Comments
 (0)