n8n-nodes-berget-mk 0.4.13 → 0.4.15
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 +21 -7
- package/dist/nodes/BergetAi/chat.js +20 -2
- package/dist/nodes/BergetAi/speech.js +32 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,10 +4,10 @@ n8n community nodes for [Berget AI](https://berget.ai), packaged as a single ins
|
|
|
4
4
|
|
|
5
5
|
Four nodes:
|
|
6
6
|
|
|
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.)
|
|
7
|
+
- **Berget AI** — multi-resource action node for one-shot calls. Resources: **Chat** (completions, classification, JSON Schema structured output), **Image Analysis** (vision-capable models), **Rerank** (document reranking), and **Speech to Text** (Swedish-tuned KB-Whisper, with optional diarization and word-level alignment). 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
|
|
10
|
+
- **Berget AI Reranker** — sub-node that plugs into Vector Store retrievers via the `AiReranker` connection, reordering candidates by relevance before they reach the agent or chain.
|
|
11
11
|
|
|
12
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.
|
|
13
13
|
|
|
@@ -27,21 +27,35 @@ Then add a **Berget AI API** credential with your API key from [berget.ai](https
|
|
|
27
27
|
|
|
28
28
|
1. Drop **Berget AI** onto the canvas, pick Resource = **Chat**, select a model, add a user message. Execute.
|
|
29
29
|
|
|
30
|
+
For classification or structured extraction tasks, set **Options → Response Format = JSON Schema** and provide a schema. The model is forced to return parseable JSON conforming to your shape — no regex scraping of free-form text.
|
|
31
|
+
|
|
30
32
|
### Agent with tools and memory
|
|
31
33
|
|
|
32
34
|
1. Add n8n's built-in **AI Agent**.
|
|
33
35
|
2. Add **Berget AI Chat Model** and connect it to the Agent's Chat Model socket.
|
|
34
36
|
3. Add Memory and Tool sub-nodes as needed — they work with Berget as the underlying LLM.
|
|
35
37
|
|
|
36
|
-
### RAG
|
|
38
|
+
### RAG with retrieval and reranking
|
|
37
39
|
|
|
38
|
-
1. Add a Vector Store node (
|
|
40
|
+
1. Add a Vector Store node (Qdrant, Supabase, etc.) or a Question and Answer Chain.
|
|
39
41
|
2. Add **Berget AI Embeddings Model** and connect it to the Embedding socket.
|
|
40
|
-
3.
|
|
42
|
+
3. Add **Berget AI Reranker** and connect it to the EmbeddingReranker socket — Vector Store will then retrieve a wider candidate set, the reranker reorders them by relevance, and only the best survive into the answer.
|
|
43
|
+
4. Index documents or query as usual.
|
|
44
|
+
|
|
45
|
+
### Image analysis
|
|
46
|
+
|
|
47
|
+
1. Drop **Berget AI** onto the canvas, pick Resource = **Image Analysis**.
|
|
48
|
+
2. Pick a vision-capable model (the dropdown is filtered automatically).
|
|
49
|
+
3. Choose Input Type = **Binary File** (default — works with Form Trigger uploads, HTTP Request responses, etc.) or **Image URL**, and provide a **Text Input** prompt like `"Describe what you see"`.
|
|
50
|
+
4. Execute.
|
|
41
51
|
|
|
42
|
-
### Swedish speech transcription
|
|
52
|
+
### Swedish speech transcription with speakers
|
|
43
53
|
|
|
44
|
-
1. Drop **Berget AI** onto the canvas, pick Resource = **Speech to Text
|
|
54
|
+
1. Drop **Berget AI** onto the canvas, pick Resource = **Speech to Text**.
|
|
55
|
+
2. Provide the binary input data from a Form Trigger or HTTP Request.
|
|
56
|
+
3. Optional: enable **Options → Diarize (Speaker Identification)** — the response will include a `speaker_transcript` field formatted as readable per-speaker paragraphs (`SPEAKER_00:\n...\n\nSPEAKER_01:\n...`), alongside the raw segment-level timestamps and word-level data.
|
|
57
|
+
4. Optional: enable **Word-Level Alignment** for per-word timestamps useful in subtitle generation.
|
|
58
|
+
5. Optional: add **Hotwords** (comma-separated) for proper nouns and domain vocabulary.
|
|
45
59
|
|
|
46
60
|
## Changelog
|
|
47
61
|
|
|
@@ -84,7 +84,7 @@ exports.chatProperties = [
|
|
|
84
84
|
{ name: 'JSON Schema', value: 'json_schema' },
|
|
85
85
|
],
|
|
86
86
|
default: 'text',
|
|
87
|
-
description: 'Force the model to return a specific response format. "JSON Object" tells the model to return any valid JSON. "JSON Schema" enforces a specific JSON schema you provide — set the schema with the JSON Schema fields below.',
|
|
87
|
+
description: 'Force the model to return a specific response format. "JSON Object" tells the model to return any valid JSON. "JSON Schema" enforces a specific JSON schema you provide — set the schema with the JSON Schema fields below. When either is selected, the parsed JSON is also exposed as a top-level "output" field on the node\'s output so downstream nodes (IF, Set, etc.) can reference its properties directly.',
|
|
88
88
|
},
|
|
89
89
|
{
|
|
90
90
|
displayName: 'JSON Schema Name',
|
|
@@ -131,6 +131,7 @@ exports.chatProperties = [
|
|
|
131
131
|
},
|
|
132
132
|
];
|
|
133
133
|
async function executeChat(context, itemIndex) {
|
|
134
|
+
var _a, _b;
|
|
134
135
|
const credentials = await context.getCredentials('bergetAiApi');
|
|
135
136
|
const model = context.getNodeParameter('chatModel', itemIndex);
|
|
136
137
|
const messages = context.getNodeParameter('chatMessages.values', itemIndex, []);
|
|
@@ -173,5 +174,22 @@ async function executeChat(context, itemIndex) {
|
|
|
173
174
|
if (status !== 200) {
|
|
174
175
|
throw new n8n_workflow_1.NodeOperationError(context.getNode(), (0, shared_1.formatBergetError)('chat', status, data), { itemIndex });
|
|
175
176
|
}
|
|
176
|
-
|
|
177
|
+
const result = data;
|
|
178
|
+
if (responseFormat === 'json_object' || responseFormat === 'json_schema') {
|
|
179
|
+
const choices = result.choices;
|
|
180
|
+
const rawContent = (_b = (_a = choices === null || choices === void 0 ? void 0 : choices[0]) === null || _a === void 0 ? void 0 : _a.message) === null || _b === void 0 ? void 0 : _b.content;
|
|
181
|
+
if (typeof rawContent === 'string' && rawContent.trim().length > 0) {
|
|
182
|
+
try {
|
|
183
|
+
const parsed = JSON.parse(rawContent);
|
|
184
|
+
if (parsed && typeof parsed === 'object') {
|
|
185
|
+
result.output = parsed;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
// Model returned non-JSON despite response_format being set.
|
|
190
|
+
// Leave output absent; raw string stays in choices[0].message.content.
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return result;
|
|
177
195
|
}
|
|
@@ -199,18 +199,42 @@ async function executeSpeech(context, itemIndex) {
|
|
|
199
199
|
// segments and word timestamps. The raw segments/words/timestamps are
|
|
200
200
|
// still preserved on the result object so power users can drill into
|
|
201
201
|
// them when needed.
|
|
202
|
-
if (options.diarize &&
|
|
203
|
-
data
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
data.speaker_transcript = transcript;
|
|
202
|
+
if (options.diarize && data && typeof data === 'object') {
|
|
203
|
+
const segments = extractSegments(data);
|
|
204
|
+
if (segments) {
|
|
205
|
+
const transcript = buildSpeakerTranscript(segments);
|
|
206
|
+
if (transcript) {
|
|
207
|
+
data.speaker_transcript = transcript;
|
|
208
|
+
}
|
|
210
209
|
}
|
|
211
210
|
}
|
|
212
211
|
return data;
|
|
213
212
|
}
|
|
213
|
+
/**
|
|
214
|
+
* Pull the segments array out of Berget's transcription response. Berget has
|
|
215
|
+
* been observed to return the segments in two different shapes:
|
|
216
|
+
*
|
|
217
|
+
* Shape A (flat): { segments: [...], language, text }
|
|
218
|
+
* Shape B (nested): { segments: { segments: [...], ... }, language, text }
|
|
219
|
+
*
|
|
220
|
+
* Shape B is what the API returns for verbose_json with diarize=true (as of
|
|
221
|
+
* 2026-04). We check both so the speaker_transcript builder works regardless
|
|
222
|
+
* of which shape we get, and so future API changes that flatten or re-nest
|
|
223
|
+
* don't silently break the output.
|
|
224
|
+
*/
|
|
225
|
+
function extractSegments(data) {
|
|
226
|
+
const top = data.segments;
|
|
227
|
+
if (Array.isArray(top)) {
|
|
228
|
+
return top;
|
|
229
|
+
}
|
|
230
|
+
if (top && typeof top === 'object') {
|
|
231
|
+
const inner = top.segments;
|
|
232
|
+
if (Array.isArray(inner)) {
|
|
233
|
+
return inner;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return undefined;
|
|
237
|
+
}
|
|
214
238
|
/**
|
|
215
239
|
* Build a "SPEAKER_00:\n...text...\n\nSPEAKER_01:\n..." style transcript
|
|
216
240
|
* by walking the segments array, grouping consecutive segments that share
|
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.15",
|
|
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",
|