fix: Fix ollama node url path and thinking tokens (#23963)

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: Dimitri Lavrenük <20122620+dlavrenuek@users.noreply.github.com>
Co-authored-by: Dimitri Lavrenük <dimitri.lavrenuek@n8n.io>
This commit is contained in:
Julian van der Horst 2026-04-29 14:30:03 +02:00 committed by GitHub
parent ec2e2f11dc
commit 4ea1153dfb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 43 additions and 32 deletions

View File

@ -1,4 +1,4 @@
import { Ollama } from '@langchain/ollama';
import { Ollama, type OllamaInput } from '@langchain/ollama';
import {
NodeConnectionTypes,
type INodeType,
@ -57,7 +57,7 @@ export class LmOllama implements INodeType {
const credentials = await this.getCredentials('ollamaApi');
const modelName = this.getNodeParameter('model', itemIndex) as string;
const options = this.getNodeParameter('options', itemIndex, {}) as object;
const options = this.getNodeParameter('options', itemIndex, {}) as OllamaInput;
const headers = credentials.apiKey
? {
Authorization: `Bearer ${credentials.apiKey as string}`,

View File

@ -70,6 +70,14 @@ export const ollamaOptions: INodeProperties = {
type: 'collection',
default: {},
options: [
{
displayName: 'Enable Thinking',
name: 'think',
type: 'boolean',
default: true,
description:
"Whether to enable (default) thinking mode for supported models. When enabled, the model's thinking process is separated from the output. When disabled, the model outputs content directly (only for supported models).",
},
{
displayName: 'Sampling Temperature',
name: 'temperature',

View File

@ -98,6 +98,14 @@ const properties: INodeProperties[] = [
},
description: 'Controls randomness in responses. Lower values make output more focused.',
},
{
displayName: 'Thinking',
name: 'think',
type: 'boolean',
default: true,
description:
"Whether to enable (default) thinking mode for supported models. When enabled, the model's thinking process is separated from the output. When disabled, the model outputs content directly (only for supported models).",
},
{
displayName: 'Output Randomness (Top P)',
name: 'top_p',
@ -336,6 +344,7 @@ const properties: INodeProperties[] = [
interface MessageOptions {
system?: string;
temperature?: number;
think?: boolean;
top_p?: number;
top_k?: number;
num_predict?: number;
@ -374,7 +383,7 @@ export async function execute(this: IExecuteFunctions, i: number): Promise<INode
const inputType = this.getNodeParameter('inputType', i, 'binary') as string;
const text = this.getNodeParameter('text', i, '') as string;
const simplify = this.getNodeParameter('simplify', i, true) as boolean;
const options = this.getNodeParameter('options', i, {}) as MessageOptions;
const { think, ...options } = this.getNodeParameter('options', i, {}) as MessageOptions;
let images: string[];
@ -432,6 +441,7 @@ export async function execute(this: IExecuteFunctions, i: number): Promise<INode
messages,
stream: false,
options: processedOptions,
think,
};
const response: OllamaChatResponse = await apiRequest.call(this, 'POST', '/api/chat', {

View File

@ -97,6 +97,14 @@ const properties: INodeProperties[] = [
},
description: 'Controls randomness in responses. Lower values make output more focused.',
},
{
displayName: 'Thinking',
name: 'think',
type: 'boolean',
default: true,
description:
"Whether to enable (default) thinking mode for supported models. When enabled, the model's thinking process is separated from the output. When disabled, the model outputs content directly (only for supported models).",
},
{
displayName: 'Output Randomness (Top P)',
name: 'top_p',
@ -335,6 +343,7 @@ const properties: INodeProperties[] = [
interface MessageOptions {
system?: string;
temperature?: number;
think?: boolean;
top_p?: number;
top_k?: number;
num_predict?: number;
@ -372,18 +381,16 @@ export async function execute(this: IExecuteFunctions, i: number): Promise<INode
const model = this.getNodeParameter('modelId', i, '', { extractValue: true }) as string;
const messages = this.getNodeParameter('messages.values', i, []) as OllamaMessage[];
const simplify = this.getNodeParameter('simplify', i, true) as boolean;
const options = this.getNodeParameter('options', i, {}) as MessageOptions;
const { think, system, ...options } = this.getNodeParameter('options', i, {}) as MessageOptions;
const { tools, connectedTools } = await getTools.call(this);
if (options.system) {
if (system) {
messages.unshift({
role: 'system',
content: options.system,
content: system,
});
}
delete options.system;
const processedOptions = { ...options };
if (processedOptions.stop && typeof processedOptions.stop === 'string') {
processedOptions.stop = processedOptions.stop
@ -398,6 +405,7 @@ export async function execute(this: IExecuteFunctions, i: number): Promise<INode
stream: false,
tools,
options: processedOptions,
think,
};
let response: OllamaChatResponse = await apiRequest.call(this, 'POST', '/api/chat', {

View File

@ -29,8 +29,7 @@ export async function apiRequest(
throw new Error('API key must be a string');
}
const url = new URL(endpoint, credentials.baseUrl).toString();
const url = `${credentials.baseUrl.replace(/\/$/, '')}${endpoint}`;
const headers = parameters?.headers ?? {};
if (apiKey) {
headers.Authorization = `Bearer ${apiKey}`;

View File

@ -236,7 +236,7 @@
"@langchain/groq": "1.0.2",
"@langchain/mistralai": "1.0.1",
"@langchain/mongodb": "1.0.1",
"@langchain/ollama": "1.0.3",
"@langchain/ollama": "1.2.6",
"@langchain/openai": "catalog:",
"@langchain/pinecone": "1.0.1",
"@langchain/qdrant": "1.0.1",

View File

@ -1972,8 +1972,8 @@ importers:
specifier: 1.0.1
version: 1.0.1(@aws-sdk/credential-providers@3.808.0)(@langchain/core@1.1.41(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.213.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(openai@6.34.0(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67))(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(gcp-metadata@5.3.0)(socks@2.8.3)
'@langchain/ollama':
specifier: 1.0.3
version: 1.0.3(@langchain/core@1.1.41(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.213.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(openai@6.34.0(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67))(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)))
specifier: 1.2.6
version: 1.2.6(@langchain/core@1.1.41(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.213.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(openai@6.34.0(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67))(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)))
'@langchain/openai':
specifier: 'catalog:'
version: 1.4.4(@langchain/core@1.1.41(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.213.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(openai@6.34.0(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67))(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))
@ -7852,8 +7852,8 @@ packages:
peerDependencies:
'@langchain/core': ^1.0.0
'@langchain/ollama@1.0.3':
resolution: {integrity: sha512-tG9DqIVzWE6xTzqI4519QdLn5NWvs3EnU2gSttwTlnCM+OEdkGxpgRFSs2pgtyV4Hn2tPOj32JbtXE1qsthHHA==}
'@langchain/ollama@1.2.6':
resolution: {integrity: sha512-wEfjRjyB20SMduqjriIBEalXZf1twbfaNTxxLIjKCVrufHPtKJKGy1a0tQHqa+27HwektNNXlcMre7MTuaS5Rw==}
engines: {node: '>=20'}
peerDependencies:
'@langchain/core': ^1.0.0
@ -21369,14 +21369,6 @@ packages:
unique-slug@2.0.2:
resolution: {integrity: sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==}
unique-slug@3.0.0:
resolution: {integrity: sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==}
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
unique-slug@5.0.0:
resolution: {integrity: sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==}
engines: {node: ^18.17.0 || >=20.5.0}
unist-util-is@6.0.1:
resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==}
@ -21388,6 +21380,7 @@ packages:
unist-util-visit@5.1.0:
resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==}
universal-user-agent@6.0.1:
resolution: {integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==}
@ -27385,7 +27378,7 @@ snapshots:
- snappy
- socks
'@langchain/ollama@1.0.3(@langchain/core@1.1.41(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.213.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(openai@6.34.0(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67))(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)))':
'@langchain/ollama@1.2.6(@langchain/core@1.1.41(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.213.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(openai@6.34.0(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67))(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)))':
dependencies:
'@langchain/core': 1.1.41(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.213.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(openai@6.34.0(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67))(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))
ollama: 0.6.3
@ -44252,14 +44245,6 @@ snapshots:
imurmurhash: 0.1.4
optional: true
unique-slug@3.0.0:
dependencies:
imurmurhash: 0.1.4
unique-slug@5.0.0:
dependencies:
imurmurhash: 0.1.4
unist-util-is@6.0.1:
dependencies:
'@types/unist': 3.0.3
@ -44278,6 +44263,7 @@ snapshots:
'@types/unist': 3.0.3
unist-util-is: 6.0.1
unist-util-visit-parents: 6.0.2
universal-user-agent@6.0.1: {}
universalify@0.1.2: {}