n8n-nodes-berget-mk 0.4.7 → 0.4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/nodes/BergetAi/rerank.js +2 -2
- package/dist/nodes/BergetAiEmbeddingsModel/BergetAiEmbeddingsModel.node.js +12 -4
- package/dist/nodes/BergetAiReranker/BergetAiReranker.node.d.ts +10 -0
- package/dist/nodes/BergetAiReranker/BergetAiReranker.node.js +160 -0
- package/dist/nodes/BergetAiReranker/bergetai.svg +3 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
n8n community nodes for [Berget AI](https://berget.ai), packaged as a single installable module. Maintained by Micke Kring.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Four nodes:
|
|
6
6
|
|
|
7
|
-
- **Berget AI** — multi-resource action node for one-shot calls: **Chat** (completions, classification), **Rerank** (document reranking), and **Speech to Text** (Swedish-tuned KB-Whisper). Can also be exposed as a tool to an AI Agent. (OCR is temporarily hidden — see [CHANGELOG.md](CHANGELOG.md) for `0.4.4` for details.)
|
|
7
|
+
- **Berget AI** — multi-resource action node for one-shot calls: **Chat** (completions, classification), **Image Analysis** (vision models), **Rerank** (document reranking), and **Speech to Text** (Swedish-tuned KB-Whisper). Can also be exposed as a tool to an AI Agent. (OCR is temporarily hidden — see [CHANGELOG.md](CHANGELOG.md) for `0.4.4` for details.)
|
|
8
8
|
- **Berget AI Chat Model** — sub-node that plugs into n8n's built-in **AI Agent**, **Basic LLM Chain**, and other LangChain-based nodes. Exposes `reasoning_effort` and the full standard LLM parameter set.
|
|
9
9
|
- **Berget AI Embeddings Model** — sub-node that plugs into n8n's **Vector Store** nodes (Supabase, Qdrant, Pinecone, PGVector, etc.) and **Question and Answer Chain**.
|
|
10
|
+
- **Berget AI Reranker** — sub-node that plugs into Vector Store retrievers to reorder candidate documents by relevance before handing them to the chain or agent.
|
|
10
11
|
|
|
11
12
|
> ⚠️ **Experimental — actively developed.** This package is pre-1.0 and may break between minor releases. Pin a specific version in production workflows until `1.0.0`. See [CHANGELOG.md](CHANGELOG.md) for breaking changes.
|
|
12
13
|
|
|
@@ -63,9 +63,9 @@ class BergetAiEmbeddingsModel {
|
|
|
63
63
|
displayName: 'Dimensions',
|
|
64
64
|
name: 'dimensions',
|
|
65
65
|
type: 'number',
|
|
66
|
-
typeOptions: { minValue:
|
|
67
|
-
default:
|
|
68
|
-
description: "
|
|
66
|
+
typeOptions: { minValue: 0 },
|
|
67
|
+
default: 0,
|
|
68
|
+
description: "⚠️ CURRENTLY BROKEN ON BERGET'S API. Leave at 0 (default) to omit the parameter entirely — this is the only reliable mode as of 2026-04. Setting any positive value causes Berget to return HTTP 503 EMBEDDING_CREATION_ERROR for every request, even when the value matches the model's native dimension (e.g. 1024 for intfloat/multilingual-e5-large-instruct). Berget's OpenAPI spec documents the dimensions parameter but the backend currently rejects it for all embedding models we've tested. The field is kept here so that when Berget fixes their backend, you can set a dimension without a package update. Default behaviour (dimensions=0) returns the model's native vector size.",
|
|
69
69
|
},
|
|
70
70
|
{
|
|
71
71
|
displayName: 'Strip New Lines',
|
|
@@ -114,6 +114,12 @@ class BergetAiEmbeddingsModel {
|
|
|
114
114
|
const credentials = await this.getCredentials('bergetAiApi');
|
|
115
115
|
const modelName = this.getNodeParameter('model', itemIndex);
|
|
116
116
|
const options = this.getNodeParameter('options', itemIndex, {});
|
|
117
|
+
// Dimensions is intentionally only passed through when > 0. Berget's
|
|
118
|
+
// backend currently returns HTTP 503 EMBEDDING_CREATION_ERROR for any
|
|
119
|
+
// request that includes the dimensions field (verified 2026-04-11),
|
|
120
|
+
// despite their OpenAPI spec documenting it. The field is kept in the
|
|
121
|
+
// UI so users can opt in once Berget fixes the backend without a
|
|
122
|
+
// package update. See CHANGELOG 0.4.8 for details.
|
|
117
123
|
const embeddings = new openai_1.OpenAIEmbeddings({
|
|
118
124
|
apiKey: credentials.apiKey,
|
|
119
125
|
model: modelName,
|
|
@@ -123,7 +129,9 @@ class BergetAiEmbeddingsModel {
|
|
|
123
129
|
batchSize: (_a = options.batchSize) !== null && _a !== void 0 ? _a : 512,
|
|
124
130
|
stripNewLines: (_b = options.stripNewLines) !== null && _b !== void 0 ? _b : true,
|
|
125
131
|
timeout: (_c = options.timeout) !== null && _c !== void 0 ? _c : 60000,
|
|
126
|
-
...(options.dimensions
|
|
132
|
+
...(options.dimensions && options.dimensions > 0
|
|
133
|
+
? { dimensions: options.dimensions }
|
|
134
|
+
: {}),
|
|
127
135
|
});
|
|
128
136
|
return { response: embeddings };
|
|
129
137
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ILoadOptionsFunctions, type INodePropertyOptions, type INodeType, type INodeTypeDescription, type ISupplyDataFunctions, type SupplyData } from 'n8n-workflow';
|
|
2
|
+
export declare class BergetAiReranker implements INodeType {
|
|
3
|
+
description: INodeTypeDescription;
|
|
4
|
+
methods: {
|
|
5
|
+
loadOptions: {
|
|
6
|
+
getRerankModels(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
supplyData(this: ISupplyDataFunctions, itemIndex: number): Promise<SupplyData>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.BergetAiReranker = void 0;
|
|
7
|
+
const documents_1 = require("@langchain/core/documents");
|
|
8
|
+
const document_compressors_1 = require("@langchain/core/retrievers/document_compressors");
|
|
9
|
+
const axios_1 = __importDefault(require("axios"));
|
|
10
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
11
|
+
const BERGET_API_BASE_URL = 'https://api.berget.ai/v1';
|
|
12
|
+
/**
|
|
13
|
+
* LangChain-compatible document compressor that calls Berget AI's `/v1/rerank`
|
|
14
|
+
* endpoint to reorder a list of documents by relevance to a query. Plugs into
|
|
15
|
+
* any n8n node that accepts an AiReranker connection type (Vector Store
|
|
16
|
+
* retrievers, QA Chain, etc.).
|
|
17
|
+
*
|
|
18
|
+
* Berget's API returns results with 0-based indices into the input documents
|
|
19
|
+
* array. We preserve the original LangChain Document metadata across the round
|
|
20
|
+
* trip so downstream consumers don't lose pageContent source references.
|
|
21
|
+
*/
|
|
22
|
+
class BergetReranker extends document_compressors_1.BaseDocumentCompressor {
|
|
23
|
+
constructor(params) {
|
|
24
|
+
super();
|
|
25
|
+
this.apiKey = params.apiKey;
|
|
26
|
+
this.model = params.model;
|
|
27
|
+
this.topN = params.topN;
|
|
28
|
+
this.timeoutMs = params.timeoutMs;
|
|
29
|
+
}
|
|
30
|
+
async compressDocuments(documents, query, _callbacks) {
|
|
31
|
+
var _a, _b;
|
|
32
|
+
if (documents.length === 0)
|
|
33
|
+
return [];
|
|
34
|
+
const documentStrings = documents.map((d) => d.pageContent);
|
|
35
|
+
const response = await axios_1.default.post(`${BERGET_API_BASE_URL}/rerank`, {
|
|
36
|
+
model: this.model,
|
|
37
|
+
query,
|
|
38
|
+
documents: documentStrings,
|
|
39
|
+
top_n: Math.min(this.topN, documents.length),
|
|
40
|
+
return_documents: false,
|
|
41
|
+
}, {
|
|
42
|
+
headers: {
|
|
43
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
44
|
+
'Content-Type': 'application/json',
|
|
45
|
+
},
|
|
46
|
+
timeout: this.timeoutMs,
|
|
47
|
+
});
|
|
48
|
+
const results = (_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.data) !== null && _b !== void 0 ? _b : [];
|
|
49
|
+
return results.map((result) => {
|
|
50
|
+
var _a, _b, _c;
|
|
51
|
+
const original = documents[result.index];
|
|
52
|
+
return new documents_1.Document({
|
|
53
|
+
pageContent: (_b = (_a = original === null || original === void 0 ? void 0 : original.pageContent) !== null && _a !== void 0 ? _a : result.document) !== null && _b !== void 0 ? _b : '',
|
|
54
|
+
metadata: {
|
|
55
|
+
...((_c = original === null || original === void 0 ? void 0 : original.metadata) !== null && _c !== void 0 ? _c : {}),
|
|
56
|
+
relevance_score: result.relevance_score,
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
class BergetAiReranker {
|
|
63
|
+
constructor() {
|
|
64
|
+
this.description = {
|
|
65
|
+
displayName: 'Berget AI Reranker',
|
|
66
|
+
name: 'bergetAiReranker',
|
|
67
|
+
icon: 'file:bergetai.svg',
|
|
68
|
+
group: ['transform'],
|
|
69
|
+
version: 1,
|
|
70
|
+
description: 'Rerank documents retrieved from a Vector Store using a Berget AI reranker model. Plugs into Vector Store retrievers and other nodes that accept an AiReranker connection.',
|
|
71
|
+
defaults: { name: 'Berget AI Reranker' },
|
|
72
|
+
codex: {
|
|
73
|
+
categories: ['AI'],
|
|
74
|
+
subcategories: {
|
|
75
|
+
AI: ['Rerankers'],
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
credentials: [{ name: 'bergetAiApi', required: true }],
|
|
79
|
+
inputs: [],
|
|
80
|
+
outputs: [n8n_workflow_1.NodeConnectionTypes.AiReranker],
|
|
81
|
+
outputNames: ['Reranker'],
|
|
82
|
+
properties: [
|
|
83
|
+
{
|
|
84
|
+
displayName: 'This node must be connected to a Vector Store retriever or a similar parent node that accepts a reranker. It cannot be executed on its own.',
|
|
85
|
+
name: 'notice',
|
|
86
|
+
type: 'notice',
|
|
87
|
+
default: '',
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
displayName: 'Model',
|
|
91
|
+
name: 'model',
|
|
92
|
+
type: 'options',
|
|
93
|
+
typeOptions: { loadOptionsMethod: 'getRerankModels' },
|
|
94
|
+
default: '',
|
|
95
|
+
required: true,
|
|
96
|
+
description: 'The Berget AI reranker model to use. Fetched live from the Berget API.',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
displayName: 'Top N',
|
|
100
|
+
name: 'topN',
|
|
101
|
+
type: 'number',
|
|
102
|
+
typeOptions: { minValue: 1 },
|
|
103
|
+
default: 3,
|
|
104
|
+
description: 'Maximum number of documents to keep after reranking. The parent node still passes the reranker a larger candidate set; this controls how many survive the rerank step.',
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
displayName: 'Options',
|
|
108
|
+
name: 'options',
|
|
109
|
+
type: 'collection',
|
|
110
|
+
placeholder: 'Add Option',
|
|
111
|
+
default: {},
|
|
112
|
+
options: [
|
|
113
|
+
{
|
|
114
|
+
displayName: 'Timeout (Ms)',
|
|
115
|
+
name: 'timeout',
|
|
116
|
+
type: 'number',
|
|
117
|
+
typeOptions: { minValue: 1 },
|
|
118
|
+
default: 60000,
|
|
119
|
+
description: 'Maximum time in milliseconds to wait for the rerank API',
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
};
|
|
125
|
+
this.methods = {
|
|
126
|
+
loadOptions: {
|
|
127
|
+
async getRerankModels() {
|
|
128
|
+
var _a, _b;
|
|
129
|
+
const credentials = await this.getCredentials('bergetAiApi');
|
|
130
|
+
const response = await axios_1.default.get(`${BERGET_API_BASE_URL}/models`, {
|
|
131
|
+
headers: {
|
|
132
|
+
Authorization: `Bearer ${credentials.apiKey}`,
|
|
133
|
+
'Content-Type': 'application/json',
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
const models = (_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.data) !== null && _b !== void 0 ? _b : [];
|
|
137
|
+
return models
|
|
138
|
+
.filter((m) => m.model_type === 'rerank')
|
|
139
|
+
.map((m) => ({ name: m.id, value: m.id }))
|
|
140
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
async supplyData(itemIndex) {
|
|
146
|
+
var _a;
|
|
147
|
+
const credentials = await this.getCredentials('bergetAiApi');
|
|
148
|
+
const model = this.getNodeParameter('model', itemIndex);
|
|
149
|
+
const topN = this.getNodeParameter('topN', itemIndex, 3);
|
|
150
|
+
const options = this.getNodeParameter('options', itemIndex, {});
|
|
151
|
+
const reranker = new BergetReranker({
|
|
152
|
+
apiKey: credentials.apiKey,
|
|
153
|
+
model,
|
|
154
|
+
topN,
|
|
155
|
+
timeoutMs: (_a = options.timeout) !== null && _a !== void 0 ? _a : 60000,
|
|
156
|
+
});
|
|
157
|
+
return { response: reranker };
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
exports.BergetAiReranker = BergetAiReranker;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-berget-mk",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.9",
|
|
4
4
|
"description": "n8n community node for Berget AI. Multi-resource action node (chat, OCR, rerank, speech-to-text) plus Chat Model and Embeddings Model sub-nodes that plug into n8n's built-in AI Agent and Vector Store nodes.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"n8n-community-node-package",
|
|
@@ -63,7 +63,8 @@
|
|
|
63
63
|
"nodes": [
|
|
64
64
|
"dist/nodes/BergetAi/BergetAi.node.js",
|
|
65
65
|
"dist/nodes/BergetAiChatModel/BergetAiChatModel.node.js",
|
|
66
|
-
"dist/nodes/BergetAiEmbeddingsModel/BergetAiEmbeddingsModel.node.js"
|
|
66
|
+
"dist/nodes/BergetAiEmbeddingsModel/BergetAiEmbeddingsModel.node.js",
|
|
67
|
+
"dist/nodes/BergetAiReranker/BergetAiReranker.node.js"
|
|
67
68
|
]
|
|
68
69
|
}
|
|
69
70
|
}
|