n8n-nodes-berget-mk 0.3.0 → 0.4.0
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 +28 -15
- package/dist/nodes/BergetAi/BergetAi.node.d.ts +0 -1
- package/dist/nodes/BergetAi/BergetAi.node.js +4 -16
- package/dist/nodes/BergetAiEmbeddingsModel/BergetAiEmbeddingsModel.node.d.ts +10 -0
- package/dist/nodes/BergetAiEmbeddingsModel/BergetAiEmbeddingsModel.node.js +122 -0
- package/dist/nodes/BergetAiEmbeddingsModel/bergetai.svg +3 -0
- package/package.json +4 -3
- package/dist/nodes/BergetAi/embeddings.d.ts +0 -3
- package/dist/nodes/BergetAi/embeddings.js +0 -71
package/README.md
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
# n8n-nodes-berget-mk
|
|
2
2
|
|
|
3
|
-
n8n community
|
|
3
|
+
n8n community nodes for [Berget AI](https://berget.ai), packaged as a single installable module. Maintained by Micke Kring.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Three nodes:
|
|
6
6
|
|
|
7
|
-
- **Berget AI** —
|
|
8
|
-
- **Berget AI Chat Model** —
|
|
7
|
+
- **Berget AI** — multi-resource action node for one-shot calls: **Chat** (completions, classification), **OCR** (document text extraction), **Rerank** (document reranking), and **Speech to Text** (Swedish-tuned KB-Whisper). Can also be exposed as a tool to an AI Agent.
|
|
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
|
+
- **Berget AI Embeddings Model** — sub-node that plugs into n8n's **Vector Store** nodes (Supabase, Qdrant, Pinecone, PGVector, etc.) and **Question and Answer Chain**.
|
|
9
10
|
|
|
10
|
-
> ⚠️ **Experimental — actively developed.** This package is pre-1.0 and
|
|
11
|
+
> ⚠️ **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.
|
|
11
12
|
|
|
12
13
|
## Install
|
|
13
14
|
|
|
@@ -19,19 +20,31 @@ n8n-nodes-berget-mk
|
|
|
19
20
|
|
|
20
21
|
Then add a **Berget AI API** credential with your API key from [berget.ai](https://berget.ai).
|
|
21
22
|
|
|
22
|
-
##
|
|
23
|
+
## Typical workflows
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
2. Select a **Resource** (Chat, Embeddings, OCR, Rerank, or Speech to Text).
|
|
26
|
-
3. Fill in the resource-specific fields (model, input, options).
|
|
27
|
-
4. Execute.
|
|
25
|
+
### One-shot chat / classification
|
|
28
26
|
|
|
29
|
-
|
|
27
|
+
1. Drop **Berget AI** onto the canvas, pick Resource = **Chat**, select a model, add a user message. Execute.
|
|
30
28
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
### Agent with tools and memory
|
|
30
|
+
|
|
31
|
+
1. Add n8n's built-in **AI Agent**.
|
|
32
|
+
2. Add **Berget AI Chat Model** and connect it to the Agent's Chat Model socket.
|
|
33
|
+
3. Add Memory and Tool sub-nodes as needed — they work with Berget as the underlying LLM.
|
|
34
|
+
|
|
35
|
+
### RAG / vector search
|
|
36
|
+
|
|
37
|
+
1. Add a Vector Store node (Supabase, Qdrant, etc.) or a Question and Answer Chain.
|
|
38
|
+
2. Add **Berget AI Embeddings Model** and connect it to the Embedding socket.
|
|
39
|
+
3. Index documents or query as usual.
|
|
40
|
+
|
|
41
|
+
### Document extraction
|
|
42
|
+
|
|
43
|
+
1. Drop **Berget AI** onto the canvas, pick Resource = **OCR**, provide a document URL or base64 data, and pick your output format (Markdown or JSON).
|
|
44
|
+
|
|
45
|
+
### Swedish speech transcription
|
|
46
|
+
|
|
47
|
+
1. Drop **Berget AI** onto the canvas, pick Resource = **Speech to Text**, pick a model (defaults to `KB-Whisper-Large`), and point at an audio file.
|
|
35
48
|
|
|
36
49
|
## Changelog
|
|
37
50
|
|
|
@@ -4,7 +4,6 @@ export declare class BergetAi implements INodeType {
|
|
|
4
4
|
methods: {
|
|
5
5
|
loadOptions: {
|
|
6
6
|
getChatModels(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
|
|
7
|
-
getEmbeddingsModels(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
|
|
8
7
|
getRerankModels(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
|
|
9
8
|
getSpeechModels(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
|
|
10
9
|
};
|
|
@@ -4,7 +4,6 @@ exports.BergetAi = void 0;
|
|
|
4
4
|
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
5
|
const n8n_workflow_2 = require("n8n-workflow");
|
|
6
6
|
const chat_1 = require("./chat");
|
|
7
|
-
const embeddings_1 = require("./embeddings");
|
|
8
7
|
const ocr_1 = require("./ocr");
|
|
9
8
|
const rerank_1 = require("./rerank");
|
|
10
9
|
const speech_1 = require("./speech");
|
|
@@ -18,14 +17,15 @@ class BergetAi {
|
|
|
18
17
|
group: ['transform'],
|
|
19
18
|
version: 1,
|
|
20
19
|
subtitle: '={{$parameter["resource"]}}',
|
|
21
|
-
description: 'Use Berget AI for chat completions,
|
|
20
|
+
description: 'Use Berget AI for chat completions, document OCR, speech-to-text, and document reranking',
|
|
22
21
|
defaults: { name: 'Berget AI' },
|
|
22
|
+
usableAsTool: true,
|
|
23
23
|
codex: {
|
|
24
|
+
alias: ['Berget', 'Berget AI', 'Swedish AI', 'LLM', 'KB-Whisper'],
|
|
24
25
|
categories: ['AI'],
|
|
25
26
|
subcategories: {
|
|
26
|
-
AI: ['Miscellaneous'],
|
|
27
|
+
AI: ['Agents', 'Miscellaneous', 'Root Nodes'],
|
|
27
28
|
},
|
|
28
|
-
alias: ['Berget', 'Berget AI', 'Swedish AI', 'LLM'],
|
|
29
29
|
},
|
|
30
30
|
credentials: [
|
|
31
31
|
{
|
|
@@ -48,11 +48,6 @@ class BergetAi {
|
|
|
48
48
|
value: 'chat',
|
|
49
49
|
description: 'Create a chat completion',
|
|
50
50
|
},
|
|
51
|
-
{
|
|
52
|
-
name: 'Embeddings',
|
|
53
|
-
value: 'embeddings',
|
|
54
|
-
description: 'Generate vector embeddings from text',
|
|
55
|
-
},
|
|
56
51
|
{
|
|
57
52
|
name: 'OCR',
|
|
58
53
|
value: 'ocr',
|
|
@@ -71,7 +66,6 @@ class BergetAi {
|
|
|
71
66
|
],
|
|
72
67
|
},
|
|
73
68
|
...chat_1.chatProperties,
|
|
74
|
-
...embeddings_1.embeddingsProperties,
|
|
75
69
|
...ocr_1.ocrProperties,
|
|
76
70
|
...rerank_1.rerankProperties,
|
|
77
71
|
...speech_1.speechProperties,
|
|
@@ -82,9 +76,6 @@ class BergetAi {
|
|
|
82
76
|
async getChatModels() {
|
|
83
77
|
return (0, shared_1.loadModelOptions)(this, (m) => m.model_type === 'text' || m.model_type === 'ocr');
|
|
84
78
|
},
|
|
85
|
-
async getEmbeddingsModels() {
|
|
86
|
-
return (0, shared_1.loadModelOptions)(this, (m) => m.model_type === 'embedding');
|
|
87
|
-
},
|
|
88
79
|
async getRerankModels() {
|
|
89
80
|
return (0, shared_1.loadModelOptions)(this, (m) => m.model_type === 'rerank');
|
|
90
81
|
},
|
|
@@ -105,9 +96,6 @@ class BergetAi {
|
|
|
105
96
|
case 'chat':
|
|
106
97
|
result = await (0, chat_1.executeChat)(this, i);
|
|
107
98
|
break;
|
|
108
|
-
case 'embeddings':
|
|
109
|
-
result = await (0, embeddings_1.executeEmbeddings)(this, i);
|
|
110
|
-
break;
|
|
111
99
|
case 'ocr':
|
|
112
100
|
result = await (0, ocr_1.executeOcr)(this, i);
|
|
113
101
|
break;
|
|
@@ -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 BergetAiEmbeddingsModel implements INodeType {
|
|
3
|
+
description: INodeTypeDescription;
|
|
4
|
+
methods: {
|
|
5
|
+
loadOptions: {
|
|
6
|
+
getEmbeddingsModels(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
supplyData(this: ISupplyDataFunctions, itemIndex: number): Promise<SupplyData>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
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.BergetAiEmbeddingsModel = void 0;
|
|
7
|
+
const openai_1 = require("@langchain/openai");
|
|
8
|
+
const axios_1 = __importDefault(require("axios"));
|
|
9
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
10
|
+
const BERGET_API_BASE_URL = 'https://api.berget.ai/v1';
|
|
11
|
+
class BergetAiEmbeddingsModel {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.description = {
|
|
14
|
+
displayName: 'Berget AI Embeddings Model',
|
|
15
|
+
name: 'bergetAiEmbeddingsModel',
|
|
16
|
+
icon: 'file:bergetai.svg',
|
|
17
|
+
group: ['transform'],
|
|
18
|
+
version: 1,
|
|
19
|
+
description: 'Use a Berget AI embedding model with Vector Store, Question and Answer Chain, or other LangChain nodes',
|
|
20
|
+
defaults: { name: 'Berget AI Embeddings Model' },
|
|
21
|
+
codex: {
|
|
22
|
+
categories: ['AI'],
|
|
23
|
+
subcategories: {
|
|
24
|
+
AI: ['Embeddings'],
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
credentials: [{ name: 'bergetAiApi', required: true }],
|
|
28
|
+
inputs: [],
|
|
29
|
+
outputs: [n8n_workflow_1.NodeConnectionTypes.AiEmbedding],
|
|
30
|
+
outputNames: ['Embeddings'],
|
|
31
|
+
properties: [
|
|
32
|
+
{
|
|
33
|
+
displayName: 'This node must be connected to a Vector Store or QA Chain, not executed on its own.',
|
|
34
|
+
name: 'notice',
|
|
35
|
+
type: 'notice',
|
|
36
|
+
default: '',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
displayName: 'Model',
|
|
40
|
+
name: 'model',
|
|
41
|
+
type: 'options',
|
|
42
|
+
typeOptions: { loadOptionsMethod: 'getEmbeddingsModels' },
|
|
43
|
+
default: '',
|
|
44
|
+
required: true,
|
|
45
|
+
description: 'The Berget AI embedding model to use. Fetched live from the Berget API.',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
displayName: 'Options',
|
|
49
|
+
name: 'options',
|
|
50
|
+
type: 'collection',
|
|
51
|
+
placeholder: 'Add Option',
|
|
52
|
+
default: {},
|
|
53
|
+
options: [
|
|
54
|
+
{
|
|
55
|
+
displayName: 'Batch Size',
|
|
56
|
+
name: 'batchSize',
|
|
57
|
+
type: 'number',
|
|
58
|
+
typeOptions: { minValue: 1 },
|
|
59
|
+
default: 512,
|
|
60
|
+
description: 'Number of documents to embed per API request',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
displayName: 'Strip New Lines',
|
|
64
|
+
name: 'stripNewLines',
|
|
65
|
+
type: 'boolean',
|
|
66
|
+
default: true,
|
|
67
|
+
description: 'Whether to strip newlines from input text before embedding',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
displayName: 'Timeout (Ms)',
|
|
71
|
+
name: 'timeout',
|
|
72
|
+
type: 'number',
|
|
73
|
+
typeOptions: { minValue: 1 },
|
|
74
|
+
default: 60000,
|
|
75
|
+
description: 'Maximum time in milliseconds to wait for the embeddings API',
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
};
|
|
81
|
+
this.methods = {
|
|
82
|
+
loadOptions: {
|
|
83
|
+
async getEmbeddingsModels() {
|
|
84
|
+
var _a, _b;
|
|
85
|
+
const credentials = await this.getCredentials('bergetAiApi');
|
|
86
|
+
const response = await axios_1.default.get(`${BERGET_API_BASE_URL}/models`, {
|
|
87
|
+
headers: {
|
|
88
|
+
Authorization: `Bearer ${credentials.apiKey}`,
|
|
89
|
+
'Content-Type': 'application/json',
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
const models = (_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.data) !== null && _b !== void 0 ? _b : [];
|
|
93
|
+
return models
|
|
94
|
+
.filter((m) => m.model_type === 'embedding')
|
|
95
|
+
.map((m) => ({
|
|
96
|
+
name: m.id,
|
|
97
|
+
value: m.id,
|
|
98
|
+
}))
|
|
99
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
async supplyData(itemIndex) {
|
|
105
|
+
var _a, _b, _c;
|
|
106
|
+
const credentials = await this.getCredentials('bergetAiApi');
|
|
107
|
+
const modelName = this.getNodeParameter('model', itemIndex);
|
|
108
|
+
const options = this.getNodeParameter('options', itemIndex, {});
|
|
109
|
+
const embeddings = new openai_1.OpenAIEmbeddings({
|
|
110
|
+
apiKey: credentials.apiKey,
|
|
111
|
+
model: modelName,
|
|
112
|
+
configuration: {
|
|
113
|
+
baseURL: BERGET_API_BASE_URL,
|
|
114
|
+
},
|
|
115
|
+
batchSize: (_a = options.batchSize) !== null && _a !== void 0 ? _a : 512,
|
|
116
|
+
stripNewLines: (_b = options.stripNewLines) !== null && _b !== void 0 ? _b : true,
|
|
117
|
+
timeout: (_c = options.timeout) !== null && _c !== void 0 ? _c : 60000,
|
|
118
|
+
});
|
|
119
|
+
return { response: embeddings };
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
exports.BergetAiEmbeddingsModel = BergetAiEmbeddingsModel;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-berget-mk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "n8n community node for Berget AI.
|
|
3
|
+
"version": "0.4.0",
|
|
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",
|
|
7
7
|
"n8n",
|
|
@@ -62,7 +62,8 @@
|
|
|
62
62
|
],
|
|
63
63
|
"nodes": [
|
|
64
64
|
"dist/nodes/BergetAi/BergetAi.node.js",
|
|
65
|
-
"dist/nodes/BergetAiChatModel/BergetAiChatModel.node.js"
|
|
65
|
+
"dist/nodes/BergetAiChatModel/BergetAiChatModel.node.js",
|
|
66
|
+
"dist/nodes/BergetAiEmbeddingsModel/BergetAiEmbeddingsModel.node.js"
|
|
66
67
|
]
|
|
67
68
|
}
|
|
68
69
|
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.embeddingsProperties = void 0;
|
|
4
|
-
exports.executeEmbeddings = executeEmbeddings;
|
|
5
|
-
const n8n_workflow_1 = require("n8n-workflow");
|
|
6
|
-
const shared_1 = require("./shared");
|
|
7
|
-
const showForEmbeddings = {
|
|
8
|
-
displayOptions: {
|
|
9
|
-
show: {
|
|
10
|
-
resource: ['embeddings'],
|
|
11
|
-
},
|
|
12
|
-
},
|
|
13
|
-
};
|
|
14
|
-
exports.embeddingsProperties = [
|
|
15
|
-
{
|
|
16
|
-
displayName: 'Model',
|
|
17
|
-
name: 'embeddingsModel',
|
|
18
|
-
type: 'options',
|
|
19
|
-
typeOptions: { loadOptionsMethod: 'getEmbeddingsModels' },
|
|
20
|
-
default: '',
|
|
21
|
-
required: true,
|
|
22
|
-
description: 'The Berget AI embedding model to use',
|
|
23
|
-
...showForEmbeddings,
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
displayName: 'Input Text',
|
|
27
|
-
name: 'embeddingsInput',
|
|
28
|
-
type: 'string',
|
|
29
|
-
typeOptions: { rows: 4 },
|
|
30
|
-
default: '',
|
|
31
|
-
required: true,
|
|
32
|
-
description: 'Text to convert into an embedding vector',
|
|
33
|
-
...showForEmbeddings,
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
displayName: 'Options',
|
|
37
|
-
name: 'embeddingsOptions',
|
|
38
|
-
type: 'collection',
|
|
39
|
-
placeholder: 'Add Option',
|
|
40
|
-
default: {},
|
|
41
|
-
options: [
|
|
42
|
-
{
|
|
43
|
-
displayName: 'Encoding Format',
|
|
44
|
-
name: 'encoding_format',
|
|
45
|
-
type: 'options',
|
|
46
|
-
options: [
|
|
47
|
-
{ name: 'Float', value: 'float' },
|
|
48
|
-
{ name: 'Base64', value: 'base64' },
|
|
49
|
-
],
|
|
50
|
-
default: 'float',
|
|
51
|
-
description: 'Format of the returned embedding data',
|
|
52
|
-
},
|
|
53
|
-
],
|
|
54
|
-
...showForEmbeddings,
|
|
55
|
-
},
|
|
56
|
-
];
|
|
57
|
-
async function executeEmbeddings(context, itemIndex) {
|
|
58
|
-
var _a, _b;
|
|
59
|
-
const credentials = await context.getCredentials('bergetAiApi');
|
|
60
|
-
const model = context.getNodeParameter('embeddingsModel', itemIndex);
|
|
61
|
-
const input = context.getNodeParameter('embeddingsInput', itemIndex);
|
|
62
|
-
const options = context.getNodeParameter('embeddingsOptions', itemIndex, {});
|
|
63
|
-
const { status, data } = await (0, shared_1.bergetRequest)(credentials.apiKey, 'POST', '/embeddings', { model, input, ...options });
|
|
64
|
-
if (status !== 200) {
|
|
65
|
-
const message = (_b = (_a = data === null || data === void 0 ? void 0 : data.error) === null || _a === void 0 ? void 0 : _a.message) !== null && _b !== void 0 ? _b : `HTTP ${status}`;
|
|
66
|
-
throw new n8n_workflow_1.NodeOperationError(context.getNode(), `Berget AI embeddings error: ${message}`, {
|
|
67
|
-
itemIndex,
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
return data;
|
|
71
|
-
}
|