mirror of
https://github.com/farcasclaudiu/openclaw.git
synced 2026-06-28 15:01:41 +03:00
refactor(commands): share vllm setup
This commit is contained in:
@@ -1,16 +1,6 @@
|
|||||||
import type { OpenClawConfig } from "../config/config.js";
|
import type { OpenClawConfig } from "../config/config.js";
|
||||||
import type { ApplyAuthChoiceParams, ApplyAuthChoiceResult } from "./auth-choice.apply.js";
|
import type { ApplyAuthChoiceParams, ApplyAuthChoiceResult } from "./auth-choice.apply.js";
|
||||||
import { upsertAuthProfileWithLock } from "../agents/auth-profiles.js";
|
import { promptAndConfigureVllm } from "./vllm-setup.js";
|
||||||
|
|
||||||
const VLLM_DEFAULT_BASE_URL = "http://127.0.0.1:8000/v1";
|
|
||||||
const VLLM_DEFAULT_CONTEXT_WINDOW = 128000;
|
|
||||||
const VLLM_DEFAULT_MAX_TOKENS = 8192;
|
|
||||||
const VLLM_DEFAULT_COST = {
|
|
||||||
input: 0,
|
|
||||||
output: 0,
|
|
||||||
cacheRead: 0,
|
|
||||||
cacheWrite: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
function applyVllmDefaultModel(cfg: OpenClawConfig, modelRef: string): OpenClawConfig {
|
function applyVllmDefaultModel(cfg: OpenClawConfig, modelRef: string): OpenClawConfig {
|
||||||
const existingModel = cfg.agents?.defaults?.model;
|
const existingModel = cfg.agents?.defaults?.model;
|
||||||
@@ -41,63 +31,12 @@ export async function applyAuthChoiceVllm(
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const baseUrlRaw = await params.prompter.text({
|
const { config: nextConfig, modelRef } = await promptAndConfigureVllm({
|
||||||
message: "vLLM base URL",
|
cfg: params.config,
|
||||||
initialValue: VLLM_DEFAULT_BASE_URL,
|
prompter: params.prompter,
|
||||||
placeholder: VLLM_DEFAULT_BASE_URL,
|
|
||||||
validate: (value) => (value?.trim() ? undefined : "Required"),
|
|
||||||
});
|
|
||||||
const apiKeyRaw = await params.prompter.text({
|
|
||||||
message: "vLLM API key",
|
|
||||||
placeholder: "sk-... (or any non-empty string)",
|
|
||||||
validate: (value) => (value?.trim() ? undefined : "Required"),
|
|
||||||
});
|
|
||||||
const modelIdRaw = await params.prompter.text({
|
|
||||||
message: "vLLM model",
|
|
||||||
placeholder: "meta-llama/Meta-Llama-3-8B-Instruct",
|
|
||||||
validate: (value) => (value?.trim() ? undefined : "Required"),
|
|
||||||
});
|
|
||||||
|
|
||||||
const baseUrl = String(baseUrlRaw ?? "")
|
|
||||||
.trim()
|
|
||||||
.replace(/\/+$/, "");
|
|
||||||
const apiKey = String(apiKeyRaw ?? "").trim();
|
|
||||||
const modelId = String(modelIdRaw ?? "").trim();
|
|
||||||
const modelRef = `vllm/${modelId}`;
|
|
||||||
|
|
||||||
await upsertAuthProfileWithLock({
|
|
||||||
profileId: "vllm:default",
|
|
||||||
credential: { type: "api_key", provider: "vllm", key: apiKey },
|
|
||||||
agentDir: params.agentDir,
|
agentDir: params.agentDir,
|
||||||
});
|
});
|
||||||
|
|
||||||
const nextConfig: OpenClawConfig = {
|
|
||||||
...params.config,
|
|
||||||
models: {
|
|
||||||
...params.config.models,
|
|
||||||
mode: params.config.models?.mode ?? "merge",
|
|
||||||
providers: {
|
|
||||||
...params.config.models?.providers,
|
|
||||||
vllm: {
|
|
||||||
baseUrl,
|
|
||||||
api: "openai-completions",
|
|
||||||
apiKey: "VLLM_API_KEY",
|
|
||||||
models: [
|
|
||||||
{
|
|
||||||
id: modelId,
|
|
||||||
name: modelId,
|
|
||||||
reasoning: false,
|
|
||||||
input: ["text"],
|
|
||||||
cost: VLLM_DEFAULT_COST,
|
|
||||||
contextWindow: VLLM_DEFAULT_CONTEXT_WINDOW,
|
|
||||||
maxTokens: VLLM_DEFAULT_MAX_TOKENS,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!params.setDefaultModel) {
|
if (!params.setDefaultModel) {
|
||||||
return { config: nextConfig, agentModelOverride: modelRef };
|
return { config: nextConfig, agentModelOverride: modelRef };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
import type { OpenClawConfig } from "../config/config.js";
|
import type { OpenClawConfig } from "../config/config.js";
|
||||||
import type { WizardPrompter, WizardSelectOption } from "../wizard/prompts.js";
|
import type { WizardPrompter, WizardSelectOption } from "../wizard/prompts.js";
|
||||||
import {
|
import { ensureAuthProfileStore, listProfilesForProvider } from "../agents/auth-profiles.js";
|
||||||
ensureAuthProfileStore,
|
|
||||||
listProfilesForProvider,
|
|
||||||
upsertAuthProfileWithLock,
|
|
||||||
} from "../agents/auth-profiles.js";
|
|
||||||
import { DEFAULT_MODEL, DEFAULT_PROVIDER } from "../agents/defaults.js";
|
import { DEFAULT_MODEL, DEFAULT_PROVIDER } from "../agents/defaults.js";
|
||||||
import { getCustomProviderApiKey, resolveEnvApiKey } from "../agents/model-auth.js";
|
import { getCustomProviderApiKey, resolveEnvApiKey } from "../agents/model-auth.js";
|
||||||
import { loadModelCatalog } from "../agents/model-catalog.js";
|
import { loadModelCatalog } from "../agents/model-catalog.js";
|
||||||
@@ -17,20 +13,12 @@ import {
|
|||||||
} from "../agents/model-selection.js";
|
} from "../agents/model-selection.js";
|
||||||
import { formatTokenK } from "./models/shared.js";
|
import { formatTokenK } from "./models/shared.js";
|
||||||
import { OPENAI_CODEX_DEFAULT_MODEL } from "./openai-codex-model-default.js";
|
import { OPENAI_CODEX_DEFAULT_MODEL } from "./openai-codex-model-default.js";
|
||||||
|
import { promptAndConfigureVllm } from "./vllm-setup.js";
|
||||||
|
|
||||||
const KEEP_VALUE = "__keep__";
|
const KEEP_VALUE = "__keep__";
|
||||||
const MANUAL_VALUE = "__manual__";
|
const MANUAL_VALUE = "__manual__";
|
||||||
const VLLM_VALUE = "__vllm__";
|
const VLLM_VALUE = "__vllm__";
|
||||||
const PROVIDER_FILTER_THRESHOLD = 30;
|
const PROVIDER_FILTER_THRESHOLD = 30;
|
||||||
const VLLM_DEFAULT_BASE_URL = "http://127.0.0.1:8000/v1";
|
|
||||||
const VLLM_DEFAULT_CONTEXT_WINDOW = 128000;
|
|
||||||
const VLLM_DEFAULT_MAX_TOKENS = 8192;
|
|
||||||
const VLLM_DEFAULT_COST = {
|
|
||||||
input: 0,
|
|
||||||
output: 0,
|
|
||||||
cacheRead: 0,
|
|
||||||
cacheWrite: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Models that are internal routing features and should not be shown in selection lists.
|
// Models that are internal routing features and should not be shown in selection lists.
|
||||||
// These may be valid as defaults (e.g., set automatically during auth flow) but are not
|
// These may be valid as defaults (e.g., set automatically during auth flow) but are not
|
||||||
@@ -327,63 +315,13 @@ export async function promptDefaultModel(
|
|||||||
);
|
);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
const baseUrlRaw = await params.prompter.text({
|
const { config: nextConfig, modelRef } = await promptAndConfigureVllm({
|
||||||
message: "vLLM base URL",
|
cfg,
|
||||||
initialValue: VLLM_DEFAULT_BASE_URL,
|
prompter: params.prompter,
|
||||||
placeholder: VLLM_DEFAULT_BASE_URL,
|
|
||||||
validate: (value) => (value?.trim() ? undefined : "Required"),
|
|
||||||
});
|
|
||||||
const apiKeyRaw = await params.prompter.text({
|
|
||||||
message: "vLLM API key",
|
|
||||||
placeholder: "sk-... (or any non-empty string)",
|
|
||||||
validate: (value) => (value?.trim() ? undefined : "Required"),
|
|
||||||
});
|
|
||||||
const modelIdRaw = await params.prompter.text({
|
|
||||||
message: "vLLM model",
|
|
||||||
placeholder: "meta-llama/Meta-Llama-3-8B-Instruct",
|
|
||||||
validate: (value) => (value?.trim() ? undefined : "Required"),
|
|
||||||
});
|
|
||||||
|
|
||||||
const baseUrl = String(baseUrlRaw ?? "")
|
|
||||||
.trim()
|
|
||||||
.replace(/\/+$/, "");
|
|
||||||
const apiKey = String(apiKeyRaw ?? "").trim();
|
|
||||||
const modelId = String(modelIdRaw ?? "").trim();
|
|
||||||
|
|
||||||
await upsertAuthProfileWithLock({
|
|
||||||
profileId: "vllm:default",
|
|
||||||
credential: { type: "api_key", provider: "vllm", key: apiKey },
|
|
||||||
agentDir,
|
agentDir,
|
||||||
});
|
});
|
||||||
|
|
||||||
const nextConfig: OpenClawConfig = {
|
return { model: modelRef, config: nextConfig };
|
||||||
...cfg,
|
|
||||||
models: {
|
|
||||||
...cfg.models,
|
|
||||||
mode: cfg.models?.mode ?? "merge",
|
|
||||||
providers: {
|
|
||||||
...cfg.models?.providers,
|
|
||||||
vllm: {
|
|
||||||
baseUrl,
|
|
||||||
api: "openai-completions",
|
|
||||||
apiKey: "VLLM_API_KEY",
|
|
||||||
models: [
|
|
||||||
{
|
|
||||||
id: modelId,
|
|
||||||
name: modelId,
|
|
||||||
reasoning: false,
|
|
||||||
input: ["text"],
|
|
||||||
cost: VLLM_DEFAULT_COST,
|
|
||||||
contextWindow: VLLM_DEFAULT_CONTEXT_WINDOW,
|
|
||||||
maxTokens: VLLM_DEFAULT_MAX_TOKENS,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return { model: `vllm/${modelId}`, config: nextConfig };
|
|
||||||
}
|
}
|
||||||
return { model: String(selection) };
|
return { model: String(selection) };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import type { OpenClawConfig } from "../config/config.js";
|
||||||
|
import type { WizardPrompter } from "../wizard/prompts.js";
|
||||||
|
import { upsertAuthProfileWithLock } from "../agents/auth-profiles.js";
|
||||||
|
|
||||||
|
export const VLLM_DEFAULT_BASE_URL = "http://127.0.0.1:8000/v1";
|
||||||
|
export const VLLM_DEFAULT_CONTEXT_WINDOW = 128000;
|
||||||
|
export const VLLM_DEFAULT_MAX_TOKENS = 8192;
|
||||||
|
export const VLLM_DEFAULT_COST = {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function promptAndConfigureVllm(params: {
|
||||||
|
cfg: OpenClawConfig;
|
||||||
|
prompter: WizardPrompter;
|
||||||
|
agentDir?: string;
|
||||||
|
}): Promise<{ config: OpenClawConfig; modelId: string; modelRef: string }> {
|
||||||
|
const baseUrlRaw = await params.prompter.text({
|
||||||
|
message: "vLLM base URL",
|
||||||
|
initialValue: VLLM_DEFAULT_BASE_URL,
|
||||||
|
placeholder: VLLM_DEFAULT_BASE_URL,
|
||||||
|
validate: (value) => (value?.trim() ? undefined : "Required"),
|
||||||
|
});
|
||||||
|
const apiKeyRaw = await params.prompter.text({
|
||||||
|
message: "vLLM API key",
|
||||||
|
placeholder: "sk-... (or any non-empty string)",
|
||||||
|
validate: (value) => (value?.trim() ? undefined : "Required"),
|
||||||
|
});
|
||||||
|
const modelIdRaw = await params.prompter.text({
|
||||||
|
message: "vLLM model",
|
||||||
|
placeholder: "meta-llama/Meta-Llama-3-8B-Instruct",
|
||||||
|
validate: (value) => (value?.trim() ? undefined : "Required"),
|
||||||
|
});
|
||||||
|
|
||||||
|
const baseUrl = String(baseUrlRaw ?? "")
|
||||||
|
.trim()
|
||||||
|
.replace(/\/+$/, "");
|
||||||
|
const apiKey = String(apiKeyRaw ?? "").trim();
|
||||||
|
const modelId = String(modelIdRaw ?? "").trim();
|
||||||
|
const modelRef = `vllm/${modelId}`;
|
||||||
|
|
||||||
|
await upsertAuthProfileWithLock({
|
||||||
|
profileId: "vllm:default",
|
||||||
|
credential: { type: "api_key", provider: "vllm", key: apiKey },
|
||||||
|
agentDir: params.agentDir,
|
||||||
|
});
|
||||||
|
|
||||||
|
const nextConfig: OpenClawConfig = {
|
||||||
|
...params.cfg,
|
||||||
|
models: {
|
||||||
|
...params.cfg.models,
|
||||||
|
mode: params.cfg.models?.mode ?? "merge",
|
||||||
|
providers: {
|
||||||
|
...params.cfg.models?.providers,
|
||||||
|
vllm: {
|
||||||
|
baseUrl,
|
||||||
|
api: "openai-completions",
|
||||||
|
apiKey: "VLLM_API_KEY",
|
||||||
|
models: [
|
||||||
|
{
|
||||||
|
id: modelId,
|
||||||
|
name: modelId,
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: VLLM_DEFAULT_COST,
|
||||||
|
contextWindow: VLLM_DEFAULT_CONTEXT_WINDOW,
|
||||||
|
maxTokens: VLLM_DEFAULT_MAX_TOKENS,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return { config: nextConfig, modelId, modelRef };
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user