-
-
-
- Ollama Base URL
-
- {loading ? (
-
- ) : (
- <>
- {!basePathValue.value && (
-
- Auto-Detect
-
- )}
- >
- )}
+
+
+
+
+
+ Ollama Base URL
+
+ {loading ? (
+
+ ) : (
+ <>
+ {!basePathValue.value && (
+
+ Auto-Detect
+
+ )}
+ >
+ )}
+
+
+
+ Enter the URL where Ollama is running.
+
-
-
- Enter the URL where Ollama is running.
-
-
-
-
-
-
-
- Performance Mode
-
-
-
setPerformanceMode(e.target.value)}
- >
- Base (Default)
- Maximum
-
-
- Choose the performance mode for the Ollama model.
-
-
-
- Note: Be careful with the Maximum mode. It may
- increase resource usage significantly.
+ Base (Default)
+ Maximum
+
+
+ Choose the performance mode for the Ollama model.
-
-
- Base: Ollama automatically limits the context
- to 2048 tokens, keeping resources usage low while maintaining
- good performance. Suitable for most users and models.
+
+
+ Note: Be careful with the Maximum mode. It
+ may increase resource usage significantly.
+
+
+
+ Base: Ollama automatically limits the context
+ to 2048 tokens, keeping resources usage low while maintaining
+ good performance. Suitable for most users and models.
+
+
+
+ Maximum: Uses the full context window (up to
+ Max Tokens). Will result in increased resource usage but
+ allows for larger context conversations.
+
+ This is not recommended for most users.
+
+
+
+
+
+ Ollama Keep Alive
+
+
+ No cache
+ 5 minutes
+ 1 hour
+ Forever
+
+
+ Choose how long Ollama should keep your model in memory before
+ unloading.
+
+ {" "}
+ Learn more →
+
-
-
- Maximum: Uses the full context window (up to
- Max Tokens). Will result in increased resource usage but allows
- for larger context conversations.
+
+
+
+
+
+ Auth Token
+
+
+ Enter a Bearer Auth Token for interacting with your
+ Ollama server.
- This is not recommended for most users.
+ Used only if running Ollama behind an authentication
+ server.
-
+
+
@@ -194,7 +224,11 @@ export default function OllamaLLMOptions({ settings }) {
);
}
-function OllamaLLMModelSelection({ settings, basePath = null }) {
+function OllamaLLMModelSelection({
+ settings,
+ basePath = null,
+ authToken = null,
+}) {
const [customModels, setCustomModels] = useState([]);
const [loading, setLoading] = useState(true);
@@ -207,7 +241,11 @@ function OllamaLLMModelSelection({ settings, basePath = null }) {
}
setLoading(true);
try {
- const { models } = await System.customModels("ollama", null, basePath);
+ const { models } = await System.customModels(
+ "ollama",
+ authToken,
+ basePath
+ );
setCustomModels(models || []);
} catch (error) {
console.error("Failed to fetch custom models:", error);
@@ -216,7 +254,7 @@ function OllamaLLMModelSelection({ settings, basePath = null }) {
setLoading(false);
}
findCustomModels();
- }, [basePath]);
+ }, [basePath, authToken]);
if (loading || customModels.length == 0) {
return (
diff --git a/frontend/src/hooks/useProviderEndpointAutoDiscovery.js b/frontend/src/hooks/useProviderEndpointAutoDiscovery.js
index 956b0907593..aff13d30084 100644
--- a/frontend/src/hooks/useProviderEndpointAutoDiscovery.js
+++ b/frontend/src/hooks/useProviderEndpointAutoDiscovery.js
@@ -5,11 +5,15 @@ import showToast from "@/utils/toast";
export default function useProviderEndpointAutoDiscovery({
provider = null,
initialBasePath = "",
+ initialAuthToken = null,
ENDPOINTS = [],
}) {
const [loading, setLoading] = useState(false);
const [basePath, setBasePath] = useState(initialBasePath);
const [basePathValue, setBasePathValue] = useState(initialBasePath);
+
+ const [authToken, setAuthToken] = useState(initialAuthToken);
+ const [authTokenValue, setAuthTokenValue] = useState(initialAuthToken);
const [autoDetectAttempted, setAutoDetectAttempted] = useState(false);
const [showAdvancedControls, setShowAdvancedControls] = useState(true);
@@ -20,7 +24,7 @@ export default function useProviderEndpointAutoDiscovery({
ENDPOINTS.forEach((endpoint) => {
possibleEndpoints.push(
new Promise((resolve, reject) => {
- System.customModels(provider, null, endpoint, 2_000)
+ System.customModels(provider, authTokenValue, endpoint, 2_000)
.then((results) => {
if (!results?.models || results.models.length === 0)
throw new Error("No models");
@@ -74,9 +78,18 @@ export default function useProviderEndpointAutoDiscovery({
setBasePath(basePathValue);
}
+ function handleAuthTokenChange(e) {
+ const value = e.target.value;
+ setAuthTokenValue(value);
+ }
+
+ function handleAuthTokenBlur() {
+ setAuthToken(authTokenValue);
+ }
+
useEffect(() => {
if (!initialBasePath && !autoDetectAttempted) autoDetect(true);
- }, [initialBasePath, autoDetectAttempted]);
+ }, [initialBasePath, initialAuthToken, autoDetectAttempted]);
return {
autoDetecting: loading,
@@ -93,6 +106,16 @@ export default function useProviderEndpointAutoDiscovery({
value: basePathValue,
set: setBasePathValue,
},
+ authToken: {
+ value: authToken,
+ set: setAuthTokenValue,
+ onChange: handleAuthTokenChange,
+ onBlur: handleAuthTokenBlur,
+ },
+ authTokenValue: {
+ value: authTokenValue,
+ set: setAuthTokenValue,
+ },
handleAutoDetectClick,
runAutoDetect: autoDetect,
};
diff --git a/server/.env.example b/server/.env.example
index 6ae9d8e6371..1975ada8bba 100644
--- a/server/.env.example
+++ b/server/.env.example
@@ -39,6 +39,7 @@ SIG_SALT='salt' # Please generate random string at least 32 chars long.
# OLLAMA_BASE_PATH='http://host.docker.internal:11434'
# OLLAMA_MODEL_PREF='llama2'
# OLLAMA_MODEL_TOKEN_LIMIT=4096
+# OLLAMA_AUTH_TOKEN='your-ollama-auth-token-here (optional, only for ollama running behind auth - Bearer token)'
# LLM_PROVIDER='togetherai'
# TOGETHER_AI_API_KEY='my-together-ai-key'
diff --git a/server/models/systemSettings.js b/server/models/systemSettings.js
index 7f7d0ea34de..58087f7b78a 100644
--- a/server/models/systemSettings.js
+++ b/server/models/systemSettings.js
@@ -471,6 +471,7 @@ const SystemSettings = {
OllamaLLMTokenLimit: process.env.OLLAMA_MODEL_TOKEN_LIMIT,
OllamaLLMKeepAliveSeconds: process.env.OLLAMA_KEEP_ALIVE_TIMEOUT ?? 300,
OllamaLLMPerformanceMode: process.env.OLLAMA_PERFORMANCE_MODE ?? "base",
+ OllamaLLMAuthToken: process.env.OLLAMA_AUTH_TOKEN ?? null,
// Novita LLM Keys
NovitaLLMApiKey: !!process.env.NOVITA_LLM_API_KEY,
diff --git a/server/package.json b/server/package.json
index 497a0d00a2a..25753ad11b0 100644
--- a/server/package.json
+++ b/server/package.json
@@ -63,7 +63,7 @@
"mssql": "^10.0.2",
"multer": "^1.4.5-lts.1",
"mysql2": "^3.9.8",
- "ollama": "^0.5.0",
+ "ollama": "^0.5.10",
"openai": "4.38.5",
"pg": "^8.11.5",
"pinecone-client": "^1.1.0",
@@ -97,4 +97,4 @@
"nodemon": "^2.0.22",
"prettier": "^3.0.3"
}
-}
+}
\ No newline at end of file
diff --git a/server/storage/models/.gitignore b/server/storage/models/.gitignore
index 037663a35aa..12436b21f38 100644
--- a/server/storage/models/.gitignore
+++ b/server/storage/models/.gitignore
@@ -7,4 +7,5 @@ novita
mixedbread-ai*
gemini
togetherAi
-tesseract
\ No newline at end of file
+tesseract
+ppio
\ No newline at end of file
diff --git a/server/utils/AiProviders/ollama/index.js b/server/utils/AiProviders/ollama/index.js
index 5c53dd5f4b3..25ea07e1c90 100644
--- a/server/utils/AiProviders/ollama/index.js
+++ b/server/utils/AiProviders/ollama/index.js
@@ -15,6 +15,7 @@ class OllamaAILLM {
if (!process.env.OLLAMA_BASE_PATH)
throw new Error("No Ollama Base Path was set.");
+ this.authToken = process.env.OLLAMA_AUTH_TOKEN;
this.basePath = process.env.OLLAMA_BASE_PATH;
this.model = modelPreference || process.env.OLLAMA_MODEL_PREF;
this.performanceMode = process.env.OLLAMA_PERFORMANCE_MODE || "base";
@@ -27,7 +28,10 @@ class OllamaAILLM {
user: this.promptWindowLimit() * 0.7,
};
- this.client = new Ollama({ host: this.basePath });
+ const headers = this.authToken
+ ? { Authorization: `Bearer ${this.authToken}` }
+ : {};
+ this.client = new Ollama({ host: this.basePath, headers: headers });
this.embedder = embedder ?? new NativeEmbedder();
this.defaultTemp = 0.7;
this.#log(
@@ -273,9 +277,8 @@ class OllamaAILLM {
type: "textResponseChunk",
textResponse: "",
close: true,
- error: `Ollama:streaming - could not stream chat. ${
- error?.cause ?? error.message
- }`,
+ error: `Ollama:streaming - could not stream chat. ${error?.cause ?? error.message
+ }`,
});
response.removeListener("close", handleAbort);
stream?.endMeasurement(usage);
diff --git a/server/utils/agents/aibitat/providers/ollama.js b/server/utils/agents/aibitat/providers/ollama.js
index 5cb529e51b3..5261c5b7eff 100644
--- a/server/utils/agents/aibitat/providers/ollama.js
+++ b/server/utils/agents/aibitat/providers/ollama.js
@@ -16,7 +16,13 @@ class OllamaProvider extends InheritMultiple([Provider, UnTooled]) {
} = config;
super();
- this._client = new Ollama({ host: process.env.OLLAMA_BASE_PATH });
+ const headers = process.env.OLLAMA_AUTH_TOKEN
+ ? { Authorization: `Bearer ${process.env.OLLAMA_AUTH_TOKEN}` }
+ : {};
+ this._client = new Ollama({
+ host: process.env.OLLAMA_BASE_PATH,
+ headers: headers,
+ });
this.model = model;
this.verbose = true;
}
diff --git a/server/utils/helpers/customModels.js b/server/utils/helpers/customModels.js
index 3f211d43102..32cb977d56b 100644
--- a/server/utils/helpers/customModels.js
+++ b/server/utils/helpers/customModels.js
@@ -41,7 +41,7 @@ async function getCustomModels(provider = "", apiKey = null, basePath = null) {
case "localai":
return await localAIModels(basePath, apiKey);
case "ollama":
- return await ollamaAIModels(basePath);
+ return await ollamaAIModels(basePath, apiKey);
case "togetherai":
return await getTogetherAiModels(apiKey);
case "fireworksai":
@@ -292,7 +292,7 @@ async function getKoboldCPPModels(basePath = null) {
}
}
-async function ollamaAIModels(basePath = null) {
+async function ollamaAIModels(basePath = null, _authToken = null) {
let url;
try {
let urlPath = basePath ?? process.env.OLLAMA_BASE_PATH;
@@ -304,7 +304,9 @@ async function ollamaAIModels(basePath = null) {
return { models: [], error: "Not a valid URL." };
}
- const models = await fetch(`${url}/api/tags`)
+ const authToken = _authToken || process.env.OLLAMA_AUTH_TOKEN || null;
+ const headers = authToken ? { Authorization: `Bearer ${authToken}` } : {};
+ const models = await fetch(`${url}/api/tags`, { headers: headers })
.then((res) => {
if (!res.ok)
throw new Error(`Could not reach Ollama server! ${res.status}`);
@@ -321,6 +323,9 @@ async function ollamaAIModels(basePath = null) {
return [];
});
+ // Api Key was successful so lets save it for future uses
+ if (models.length > 0 && !!authToken)
+ process.env.OLLAMA_AUTH_TOKEN = authToken;
return { models, error: null };
}
diff --git a/server/utils/helpers/updateENV.js b/server/utils/helpers/updateENV.js
index e3c1b91403d..d0c50a8c0f4 100644
--- a/server/utils/helpers/updateENV.js
+++ b/server/utils/helpers/updateENV.js
@@ -120,6 +120,10 @@ const KEY_MAPPING = {
envKey: "OLLAMA_KEEP_ALIVE_TIMEOUT",
checks: [isInteger],
},
+ OllamaLLMAuthToken: {
+ envKey: "OLLAMA_AUTH_TOKEN",
+ checks: [],
+ },
// Mistral AI API Settings
MistralApiKey: {
diff --git a/server/yarn.lock b/server/yarn.lock
index 90e5e5749f9..a070488b01c 100644
--- a/server/yarn.lock
+++ b/server/yarn.lock
@@ -5198,10 +5198,10 @@ object.values@^1.1.6, object.values@^1.1.7:
define-properties "^1.2.1"
es-object-atoms "^1.0.0"
-ollama@^0.5.0:
- version "0.5.0"
- resolved "https://registry.yarnpkg.com/ollama/-/ollama-0.5.0.tgz#cb9bc709d4d3278c9f484f751b0d9b98b06f4859"
- integrity sha512-CRtRzsho210EGdK52GrUMohA2pU+7NbgEaBG3DcYeRmvQthDO7E2LHOkLlUUeaYUlNmEd8icbjC02ug9meSYnw==
+ollama@^0.5.10:
+ version "0.5.12"
+ resolved "https://registry.yarnpkg.com/ollama/-/ollama-0.5.12.tgz#d8aadfaff076b2852cf826d928a03d9a40f308b9"
+ integrity sha512-flVH1fn1c9NF7VV3bW9kSu0E+bYc40b4DxL/gS2Debhao35osJFRDiPOj9sIWTMvcyj78Paw1OuhfIe7uhDWfQ==
dependencies:
whatwg-fetch "^3.6.20"