feat: add optional API key support for Lemonade provider (#5281)
* add API key param to Lemonade LLM Provider and Embedding Provider * add LEMONADE_LLM_API_KEY to .env.example * add api key to aibitat provider * fix api key from being sent to frontend * fix tooltip id * add null fallback for `apiKey` * remove console log * add missing api keys --------- Co-authored-by: Timothy Carambat <rambat1010@gmail.com>
This commit is contained in:
parent
3f9eaa1a76
commit
0bfd27c6df
@ -62,6 +62,31 @@ export default function LemonadeEmbeddingOptions({ settings }) {
|
|||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex flex-col w-60">
|
||||||
|
<div
|
||||||
|
data-tooltip-place="top"
|
||||||
|
data-tooltip-id="lemonade-embedding-api-key"
|
||||||
|
className="flex gap-x-1 items-center mb-3"
|
||||||
|
>
|
||||||
|
<label className="text-white text-sm font-semibold block">
|
||||||
|
API Key (optional)
|
||||||
|
</label>
|
||||||
|
<Info
|
||||||
|
size={16}
|
||||||
|
className="text-theme-text-secondary cursor-pointer"
|
||||||
|
/>
|
||||||
|
<Tooltip id="lemonade-embedding-api-key">
|
||||||
|
The API key for your Lemonade instance
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
name="LemonadeLLMApiKey"
|
||||||
|
defaultValue={settings?.LemonadeLLMApiKey ? "*".repeat(20) : ""}
|
||||||
|
className="border-none bg-theme-settings-input-bg text-white placeholder:text-theme-settings-input-placeholder text-sm rounded-lg focus:outline-primary-button active:outline-primary-button outline-none block w-full p-2.5"
|
||||||
|
autoComplete="off"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-start mt-4">
|
<div className="flex justify-start mt-4">
|
||||||
<button
|
<button
|
||||||
|
|||||||
@ -159,6 +159,43 @@ export default function LemonadeOptions({ settings }) {
|
|||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex flex-col w-60">
|
||||||
|
<div className="flex items-center gap-1 mb-3">
|
||||||
|
<label className="text-white text-sm font-semibold block">
|
||||||
|
API Key (optional)
|
||||||
|
</label>
|
||||||
|
<Tooltip
|
||||||
|
id="lemonade-api-key"
|
||||||
|
place="top"
|
||||||
|
delayShow={300}
|
||||||
|
delayHide={800}
|
||||||
|
clickable={true}
|
||||||
|
className="tooltip !text-xs !opacity-100 z-99"
|
||||||
|
style={{
|
||||||
|
maxWidth: "350px",
|
||||||
|
whiteSpace: "normal",
|
||||||
|
wordWrap: "break-word",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
The API key for your Lemonade server
|
||||||
|
</Tooltip>
|
||||||
|
<div
|
||||||
|
className="text-theme-text-secondary cursor-pointer hover:bg-theme-bg-primary flex items-center justify-center rounded-full"
|
||||||
|
data-tooltip-id="lemonade-api-key"
|
||||||
|
data-tooltip-place="top"
|
||||||
|
data-tooltip-delay-hide={800}
|
||||||
|
>
|
||||||
|
<Info size={18} className="text-theme-text-secondary" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
name="LemonadeLLMApiKey"
|
||||||
|
defaultValue={settings?.LemonadeLLMApiKey ? "*".repeat(20) : ""}
|
||||||
|
className="border-none bg-theme-settings-input-bg text-white placeholder:text-theme-settings-input-placeholder text-sm rounded-lg focus:outline-primary-button active:outline-primary-button outline-none block w-full p-2.5"
|
||||||
|
autoComplete="off"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<LemonadeModelSelection
|
<LemonadeModelSelection
|
||||||
selectedModelId={selectedModelId}
|
selectedModelId={selectedModelId}
|
||||||
setSelectedModelId={setSelectedModelId}
|
setSelectedModelId={setSelectedModelId}
|
||||||
|
|||||||
@ -180,6 +180,7 @@ SIG_SALT='salt' # Please generate random string at least 32 chars long.
|
|||||||
# LEMONADE_LLM_BASE_PATH='http://127.0.0.1:8000'
|
# LEMONADE_LLM_BASE_PATH='http://127.0.0.1:8000'
|
||||||
# LEMONADE_LLM_MODEL_PREF='Llama-3.2-1B-Instruct-GGUF'
|
# LEMONADE_LLM_MODEL_PREF='Llama-3.2-1B-Instruct-GGUF'
|
||||||
# LEMONADE_LLM_MODEL_TOKEN_LIMIT=8192
|
# LEMONADE_LLM_MODEL_TOKEN_LIMIT=8192
|
||||||
|
# LEMONADE_LLM_API_KEY=
|
||||||
|
|
||||||
###########################################
|
###########################################
|
||||||
######## Embedding API SElECTION ##########
|
######## Embedding API SElECTION ##########
|
||||||
@ -452,4 +453,4 @@ TTS_PROVIDER="native"
|
|||||||
# Set to "true" to enable. This can reduce token costs by 80% when you have
|
# Set to "true" to enable. This can reduce token costs by 80% when you have
|
||||||
# many tools/MCP servers enabled.
|
# many tools/MCP servers enabled.
|
||||||
# AGENT_SKILL_RERANKER_ENABLED="true"
|
# AGENT_SKILL_RERANKER_ENABLED="true"
|
||||||
# AGENT_SKILL_RERANKER_TOP_N=15 # (optional) Number of top tools to keep after reranking (default: 15)
|
# AGENT_SKILL_RERANKER_TOP_N=15 # (optional) Number of top tools to keep after reranking (default: 15)
|
||||||
|
|||||||
@ -34,6 +34,9 @@ function lemonadeUtilsEndpoints(app) {
|
|||||||
const lemonadeResponse = await fetch(lemonadeUrl.toString(), {
|
const lemonadeResponse = await fetch(lemonadeUrl.toString(), {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
|
...(!!process.env.LEMONADE_LLM_API_KEY
|
||||||
|
? { Authorization: `Bearer ${process.env.LEMONADE_LLM_API_KEY}` }
|
||||||
|
: {}),
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
@ -129,6 +132,9 @@ function lemonadeUtilsEndpoints(app) {
|
|||||||
const lemonadeResponse = await fetch(lemonadeUrl.toString(), {
|
const lemonadeResponse = await fetch(lemonadeUrl.toString(), {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
|
...(!!process.env.LEMONADE_LLM_API_KEY
|
||||||
|
? { Authorization: `Bearer ${process.env.LEMONADE_LLM_API_KEY}` }
|
||||||
|
: {}),
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
|
|||||||
@ -714,6 +714,7 @@ const SystemSettings = {
|
|||||||
|
|
||||||
// Lemonade Keys
|
// Lemonade Keys
|
||||||
LemonadeLLMBasePath: process.env.LEMONADE_LLM_BASE_PATH,
|
LemonadeLLMBasePath: process.env.LEMONADE_LLM_BASE_PATH,
|
||||||
|
LemonadeLLMApiKey: !!process.env.LEMONADE_LLM_API_KEY,
|
||||||
LemonadeLLMModelPref: process.env.LEMONADE_LLM_MODEL_PREF,
|
LemonadeLLMModelPref: process.env.LEMONADE_LLM_MODEL_PREF,
|
||||||
LemonadeLLMModelTokenLimit:
|
LemonadeLLMModelTokenLimit:
|
||||||
process.env.LEMONADE_LLM_MODEL_TOKEN_LIMIT || 8192,
|
process.env.LEMONADE_LLM_MODEL_TOKEN_LIMIT || 8192,
|
||||||
|
|||||||
@ -22,7 +22,7 @@ class LemonadeLLM {
|
|||||||
process.env.LEMONADE_LLM_BASE_PATH,
|
process.env.LEMONADE_LLM_BASE_PATH,
|
||||||
"openai"
|
"openai"
|
||||||
),
|
),
|
||||||
apiKey: null,
|
apiKey: process.env.LEMONADE_LLM_API_KEY ?? null,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.model = modelPreference || process.env.LEMONADE_LLM_MODEL_PREF;
|
this.model = modelPreference || process.env.LEMONADE_LLM_MODEL_PREF;
|
||||||
@ -202,7 +202,7 @@ class LemonadeLLM {
|
|||||||
process.env.LEMONADE_LLM_BASE_PATH,
|
process.env.LEMONADE_LLM_BASE_PATH,
|
||||||
"openai"
|
"openai"
|
||||||
),
|
),
|
||||||
apiKey: null,
|
apiKey: process.env.LEMONADE_LLM_API_KEY ?? null,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { labels = [] } = await client.models.retrieve(this.model);
|
const { labels = [] } = await client.models.retrieve(this.model);
|
||||||
@ -233,14 +233,17 @@ class LemonadeLLM {
|
|||||||
const endpoint = new URL(parseLemonadeServerEndpoint(basePath, "openai"));
|
const endpoint = new URL(parseLemonadeServerEndpoint(basePath, "openai"));
|
||||||
endpoint.pathname += "/load";
|
endpoint.pathname += "/load";
|
||||||
|
|
||||||
console.log(endpoint.toString());
|
|
||||||
|
|
||||||
LemonadeLLM.slog(
|
LemonadeLLM.slog(
|
||||||
`Loading model ${model} with context size ${this.promptWindowLimit()}`
|
`Loading model ${model} with context size ${this.promptWindowLimit()}`
|
||||||
);
|
);
|
||||||
await fetch(endpoint.toString(), {
|
await fetch(endpoint.toString(), {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: {
|
||||||
|
...(process.env.LEMONADE_LLM_API_KEY
|
||||||
|
? { Authorization: `Bearer ${process.env.LEMONADE_LLM_API_KEY}` }
|
||||||
|
: {}),
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
model_name: String(model),
|
model_name: String(model),
|
||||||
ctx_size: Number(this.promptWindowLimit()),
|
ctx_size: Number(this.promptWindowLimit()),
|
||||||
@ -343,7 +346,14 @@ async function getAllLemonadeModels(basePath = null, task = "chat") {
|
|||||||
);
|
);
|
||||||
lemonadeUrl.pathname += "/models";
|
lemonadeUrl.pathname += "/models";
|
||||||
lemonadeUrl.searchParams.append("show_all", "true");
|
lemonadeUrl.searchParams.append("show_all", "true");
|
||||||
await fetch(lemonadeUrl.toString())
|
|
||||||
|
await fetch(lemonadeUrl.toString(), {
|
||||||
|
headers: {
|
||||||
|
...(!!process.env.LEMONADE_LLM_API_KEY
|
||||||
|
? { Authorization: `Bearer ${process.env.LEMONADE_LLM_API_KEY}` }
|
||||||
|
: {}),
|
||||||
|
},
|
||||||
|
})
|
||||||
.then((res) => res.json())
|
.then((res) => res.json())
|
||||||
.then(({ data }) => {
|
.then(({ data }) => {
|
||||||
data?.forEach((model) => {
|
data?.forEach((model) => {
|
||||||
|
|||||||
@ -13,7 +13,7 @@ class LemonadeEmbedder {
|
|||||||
process.env.EMBEDDING_BASE_PATH,
|
process.env.EMBEDDING_BASE_PATH,
|
||||||
"openai"
|
"openai"
|
||||||
),
|
),
|
||||||
apiKey: null,
|
apiKey: process.env.LEMONADE_LLM_API_KEY ?? null,
|
||||||
});
|
});
|
||||||
this.model = process.env.EMBEDDING_MODEL_PREF;
|
this.model = process.env.EMBEDDING_MODEL_PREF;
|
||||||
|
|
||||||
|
|||||||
@ -402,7 +402,7 @@ class Provider {
|
|||||||
configuration: {
|
configuration: {
|
||||||
baseURL: process.env.LEMONADE_LLM_BASE_PATH,
|
baseURL: process.env.LEMONADE_LLM_BASE_PATH,
|
||||||
},
|
},
|
||||||
apiKey: null,
|
apiKey: process.env.LEMONADE_LLM_API_KEY ?? null,
|
||||||
...config,
|
...config,
|
||||||
});
|
});
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -27,7 +27,7 @@ class LemonadeProvider extends InheritMultiple([Provider, UnTooled]) {
|
|||||||
process.env.LEMONADE_LLM_BASE_PATH,
|
process.env.LEMONADE_LLM_BASE_PATH,
|
||||||
"openai"
|
"openai"
|
||||||
),
|
),
|
||||||
apiKey: null,
|
apiKey: process.env.LEMONADE_LLM_API_KEY ?? null,
|
||||||
maxRetries: 3,
|
maxRetries: 3,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -829,6 +829,10 @@ const KEY_MAPPING = {
|
|||||||
envKey: "LEMONADE_LLM_BASE_PATH",
|
envKey: "LEMONADE_LLM_BASE_PATH",
|
||||||
checks: [isValidURL],
|
checks: [isValidURL],
|
||||||
},
|
},
|
||||||
|
LemonadeLLMApiKey: {
|
||||||
|
envKey: "LEMONADE_LLM_API_KEY",
|
||||||
|
checks: [],
|
||||||
|
},
|
||||||
LemonadeLLMModelPref: {
|
LemonadeLLMModelPref: {
|
||||||
envKey: "LEMONADE_LLM_MODEL_PREF",
|
envKey: "LEMONADE_LLM_MODEL_PREF",
|
||||||
checks: [isNotEmpty],
|
checks: [isNotEmpty],
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user