N8N-Projekt-Drogosch.Dominic
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,240 @@
|
||||
# Projekt-Dokumentation – *N8N-MailSummarizer*
|
||||
|
||||
## Inhaltsverzeichnis
|
||||
|
||||
1. [Projektübersicht](#projektübersicht)
|
||||
2. [Systemarchitektur](#systemarchitektur)
|
||||
3. [Workflow Übersicht](#workflow-übersicht)
|
||||
4. [Workflow Beschreibung (JSON erklärt)](#workflow-beschreibung-json-erklärt)
|
||||
5. [Node-Beschreibungen](#node-beschreibungen)
|
||||
6. [Docker aufsetzen](#docker-aufsetzen)
|
||||
7. [N8N aufsetzen](#n8n-aufsetzen)
|
||||
8. [Ollama installieren](#ollama-installieren)
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
# Projektübersicht
|
||||
|
||||
**N8N-MailSummarizer** automatisiert die Verarbeitung eingehender E-Mails.
|
||||
Es liest E-Mails per IMAP ein, bereitet die Inhalte auf, lässt die Inhalte durch das KI-Modell *llama3.2* (über Ollama) zusammenfassen, extrahiert strukturierte Informationen und sendet anschließend eine formatierte Zusammenfassung per E-Mail zurück.
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
|
||||
# Systemarchitektur
|
||||
|
||||
```
|
||||
N8N → Email Trigger (IMAP) → Set Node Parsing → AI Summarization (Ollama) → Code Node (Funktion Node) → E-Mail Versand
|
||||
|
||||
```
|
||||
|
||||
**Verwendete Systeme:**
|
||||
* **Docker**
|
||||
* **N8N** (als Automationsplattform)
|
||||
* **Ollama** (lokale KI-Inferenz)
|
||||
* **llama3.2** Modell
|
||||
* **SMTP/IMAP E-Mail Konten**
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
# Workflow Übersicht
|
||||
|
||||
Der Workflow führt folgende Schritte aus:
|
||||
|
||||
1. **IMAP Email Trigger**
|
||||
→ neue E-Mail wird erkannt
|
||||
2. **Set Node**
|
||||
→ extrahiert Rohdaten (Absender, Betreff, Datum, Text)
|
||||
3. **Summarization Chain (LangChain)**
|
||||
→ Übergibt Text in Chunks an das Ollama Modell
|
||||
4. **Ollama Chat Model**
|
||||
→ erstellt strukturierte JSON-Zusammenfassung
|
||||
5. **Code Node**
|
||||
→ extrahiert JSON aus dem KI-Output
|
||||
6. **Send Email**
|
||||
→ sendet schöne Zusammenfassung als Rückmeldung
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
# Workflow Beschreibung (JSON erklärt)
|
||||
|
||||
Das von dir bereitgestellte JSON repräsentiert einen vollständigen **N8N Workflow Export**.
|
||||
|
||||
### Wichtige Komponenten:
|
||||
|
||||
| Schlüssel | Beschreibung |
|
||||
| ------------- | ------------------------------------------------------- |
|
||||
| `nodes` | Enthält alle Prozessschritte |
|
||||
| `connections` | Definiert die Reihenfolge der Nodes |
|
||||
| `settings` | Workflow-Einstellungen |
|
||||
| `credentials` | Referenzen auf Zugangsdaten (werden in N8N gespeichert) |
|
||||
| `active` | Workflow aktiv / inaktiv
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
|
||||
# Node-Beschreibungen
|
||||
|
||||
## 1. Email Trigger (IMAP)
|
||||
|
||||
Liest eingehende E-Mails:
|
||||
|
||||
* E-Mail Inhalt
|
||||
* Metadaten
|
||||
* Absender/Empfänger
|
||||
* Datum/Uhrzeit
|
||||
|
||||
→ Output wird weitergegeben.
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
## 2. Edit Fields (Set Node)
|
||||
|
||||
Transformiert das E-Mail Objekt in folgendes Format:
|
||||
|
||||
```json
|
||||
{
|
||||
"absender": {{$json.from}},
|
||||
"betreff": {{$json.subject}},
|
||||
"datum": {{ JSON.stringify($json.date) }},
|
||||
"inhalt": {{ JSON.stringify($json.textPlain) }}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
## 3. Email Summarization Chain
|
||||
|
||||
Funktion:
|
||||
|
||||
* Teilt die E-Mail in Chunks
|
||||
* Übergibt alles an **llama3.2**
|
||||
* Nutzt spezielle Prompts zur Extraktion:
|
||||
|
||||
* Absendername / E-Mail
|
||||
* Empfängername / E-Mail
|
||||
* Betreff
|
||||
* Datum/Uhrzeit
|
||||
* Wichtige Inhalte
|
||||
* Todos
|
||||
* Termine
|
||||
* Rückruf nötig?
|
||||
* Strenge JSON-Formatierung
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
## 4. Ollama Chat Model
|
||||
|
||||
Verwendet:
|
||||
**Modell:** `llama3.2:latest`
|
||||
|
||||
Ollama Modell erzeugt eine strukturierte Analyse.
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
## 5. Code Node
|
||||
|
||||
Extrahiert JSON aus Ollama-Output:
|
||||
|
||||
* erkennt `json … ` Codeblöcke
|
||||
* parsed JSON
|
||||
* validiert es
|
||||
* gibt die Felder einzeln aus
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
## 6. Send Email
|
||||
|
||||
Versendet eine professionell formatierte Rückmeldung:
|
||||
|
||||
* Zusammenfassung
|
||||
* Absender/Empfänger
|
||||
* Kontext
|
||||
* Termine
|
||||
* Todos
|
||||
* Rückruf-Status
|
||||
|
||||
SMTP Zugangsdaten werden im Credentials Manager verwaltet.
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
# Docker aufsetzen
|
||||
|
||||
1. Gehen Sie auf die Docker Webseite:
|
||||
[https://www.docker.com/](https://www.docker.com/)
|
||||
2. Docker-Konto erstellen.
|
||||
3. Docker herunterladen.
|
||||
4. Docker installieren und einrichten.
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
# Docker Netzwerk erstellen
|
||||
|
||||
|
||||
1. Öffnen Sie **PowerShell** oder **CMD**.
|
||||
2. Geben sie diesen Code ein.
|
||||
|
||||
```bash
|
||||
Docker network create n8n-network
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
# N8N aufsetzen
|
||||
|
||||
1. Öffnen Sie **PowerShell** oder **CMD**.
|
||||
2. Kopieren Sie diesen Code und führen Sie ihn aus:
|
||||
|
||||
<br>
|
||||
|
||||
```bash
|
||||
docker run -e N8N_BASIC_AUTH_ACTIVE=true -e N8N_BASIC_AUTH_USER=admin -e N8N_BASIC_AUTH_PASSWORD=supersecret -e N8N_HOST=0.0.0.0 --name n8n-container -p 5678:5678 -d n8nio/n8n
|
||||
```
|
||||
|
||||
3. Jetzt wurde ein Container mit **n8n** angelegt.
|
||||
4. Sie können über **localhost** und den Port darauf zugreifen:
|
||||
[http://localhost:5678](http://localhost:5678)
|
||||
5. Melden Sie sich mit den im Code definierten Zugangsdaten an.
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
# Ollama installieren
|
||||
|
||||
1. Öffnen Sie **PowerShell** oder **CMD**.
|
||||
2. Kopieren Sie diesen Code und führen Sie ihn aus:
|
||||
|
||||
```bash
|
||||
docker run -d --name ollama --network n8n-network -p 11434:11434 -v ollama:/root/.ollama ollama/ollama
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
## Modell in Ollama installieren (z. B. llama3.2)
|
||||
|
||||
```bash
|
||||
docker exec -it ollama ollama pull llama3.2
|
||||
```
|
||||
<br>
|
||||
|
||||
|
||||
## Prüfen, ob Model geladen wurde
|
||||
|
||||
```bash
|
||||
docker exec -it ollama-local ollama list
|
||||
```
|
||||
@@ -0,0 +1,222 @@
|
||||
{
|
||||
"name": "myProject",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {
|
||||
"fromEmail": "=",
|
||||
"toEmail": "={{ $('Email Trigger (IMAP)').item.json.metadata['delivered-to'] }}",
|
||||
"subject": "Übersichtliche Zusammenfassung",
|
||||
"emailFormat": "text",
|
||||
"text": "= 📨 Neue E-Mail Zusammenfassung\n\n📧 Absender: {{ $json.sender_email }}\n👤 Absender Name: {{ $json.sender_name }}\n\n🕒 Gesendet Am: {{ $json.date_sent }}\n👥 Gesendet An: {{ $('Email Trigger (IMAP)').item.json.metadata['delivered-to'] }}\n\n\n📌 Betreff:\n{{ $json.context }}\n\n⚠️ Wichtige Inhalte:\n{{ $json.important_content }}\n\n📅 Termin:\n{{ $json.Termin_Date }}, {{ $json.Termin_Time }}\n\n☎️ Rückruf erforderlich: {{ $json.callback_needed }}",
|
||||
"options": {}
|
||||
},
|
||||
"type": "n8n-nodes-base.emailSend",
|
||||
"typeVersion": 2.1,
|
||||
"position": [
|
||||
656,
|
||||
-576
|
||||
],
|
||||
"id": "221417b8-ff66-4c17-80f2-3b67bb809755",
|
||||
"name": "Send email",
|
||||
"webhookId": "e61483b3-1b35-49b1-843f-88e08a83b069",
|
||||
"credentials": {
|
||||
"smtp": {
|
||||
"id": "QV9RLh6CctQW2oah",
|
||||
"name": "SMTP account"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"model": "llama3.2:latest",
|
||||
"options": {}
|
||||
},
|
||||
"type": "@n8n/n8n-nodes-langchain.lmChatOllama",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
32,
|
||||
-432
|
||||
],
|
||||
"id": "dee4455c-069a-4561-a439-fd8a3c2871e3",
|
||||
"name": "Ollama Chat Model",
|
||||
"credentials": {
|
||||
"ollamaApi": {
|
||||
"id": "PdcHmENVe6yKtSSE",
|
||||
"name": "Ollama account"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"options": {}
|
||||
},
|
||||
"type": "n8n-nodes-base.emailReadImap",
|
||||
"typeVersion": 2.1,
|
||||
"position": [
|
||||
-384,
|
||||
-656
|
||||
],
|
||||
"id": "33b5ae64-2b92-4f76-824c-baacb288bcd9",
|
||||
"name": "Email Trigger (IMAP)",
|
||||
"credentials": {
|
||||
"imap": {
|
||||
"id": "OKyCJelEArgUpW4P",
|
||||
"name": "IMAP account"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"mode": "raw",
|
||||
"jsonOutput": "={\n \"absender\": \"{{$json.from}}\",\n \"betreff\": \"{{$json.subject}}\",\n \"datum\": {{ JSON.stringify($json.date) }},\n \"inhalt\": {{ JSON.stringify($json.textPlain) }}\n}",
|
||||
"options": {
|
||||
"dotNotation": false
|
||||
}
|
||||
},
|
||||
"type": "n8n-nodes-base.set",
|
||||
"typeVersion": 3.4,
|
||||
"position": [
|
||||
-176,
|
||||
-656
|
||||
],
|
||||
"id": "6286a39c-3d2a-403c-8e31-3ad71b0c9178",
|
||||
"name": "Edit Fields1",
|
||||
"alwaysOutputData": false,
|
||||
"executeOnce": false
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"chunkSize": 3000,
|
||||
"chunkOverlap": 300,
|
||||
"options": {
|
||||
"summarizationMethodAndPrompts": {
|
||||
"values": {
|
||||
"combineMapPrompt": "=Du bist ein professioneller E-Mail Assistent.\n\nDu bekommst die E-Mail-Daten (oder einen Ausschnitt davon) als Text:\n\n\"{text}\"\n\nAnalysiere diesen Ausschnitt und fasse ihn kurz zusammen.\n\nKonzentriere dich auf:\n- Absender E-Mail und Name (vom Absender, nicht vom Empfänger)\n- Betreff\n- Datum, wann die E-Mail gesendet wurde\n- Thema / Kontext der Nachricht\n- Wichtige Inhalte, Termine\n\nAntworte nur mit einer kurzen, klaren Zusammenfassung dieses Ausschnitts.\n",
|
||||
"prompt": "=Du bist ein professioneller E-Mail Assistent.\n\nDu bekommst die E-Mail-Daten als JSON (aus vorherigen Schritten in der Chain verarbeitet):\n\n\"{text}\"\n\nAnalysiere die Inhalte und erstelle eine klar strukturierte Zusammenfassung im \"JSON-Format\" mit In UTF-8.\n\nRegeln:\n- Extrahiere alle relevanten Informationen:\n - \"sender_name\": Name des Absenders\n - \"sender_email\": E-Mail des Absenders\n - \"recipient_name\": Name des Empfängers\n - \"recipient_email\": E-Mail des Empfängers\n - \"subject\": Betreff der E-Mail\n - \"date_sent\": Datum und Uhrzeit der E-Mail\n - \"context\": Thema oder Kontext der Nachricht\n - \"important_content\": Wichtige Inhalte \n - \"Termin_Date\": Termin Datum\n - \"Termin_Time\": Termin Urzeit, \n - \"callback_needed\": true/false (entscheide, ob ein Rückruf nötig ist)\n\n- Erkenne Datum und Uhrzeit automatisch aus dem Inhalt.\n- Beurteile aus dem Text, ob ein Rückruf erforderlich ist, und setze \"callback_needed\" entsprechend.\n- Gib ausschließlich valid JSON zurück, ohne zusätzlichen Text, Erklärungen oder Formatierungen.\n\n **Gib ausschließlich einen einzigen JSON-Codeblock zurück.** \n **Kein zusätzlicher Text vor oder nach dem Codeblock.** \n **Keine Erklärungen.** \n\n Das Format MUSS in JSON sein ähnlich wie:\n\n \"sender_name\": \"\",\n \"sender_email\": \"\",\n \"recipient_name\": \"\",\n \"recipient_email\": \"\",\n \"subject\": \"\",\n \"date_sent\": \"\",\n \"context\": \"\",\n \"important_content\": \"\",\n \"Termin_Date\": \"\", \n \"Termin_Time\": \"\", \n \"callback_needed\": false/True\n\n**Schreibe wirklich nur den JSON-Codeblock.**"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "74666097-a7ca-4fe2-adaa-f84dc3088844",
|
||||
"name": "Email Summarization Chain",
|
||||
"type": "@n8n/n8n-nodes-langchain.chainSummarization",
|
||||
"position": [
|
||||
32,
|
||||
-656
|
||||
],
|
||||
"typeVersion": 2
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const rawText = items[0].json.response.text;\n\n// Erst versuchen, JSON-Codeblock zu finden\nlet match = rawText.match(/```(?:json)?\\s*([\\s\\S]*?)```/i);\nlet cleanJson = \"\";\n\nif (match) {\n // JSON aus Codeblock\n cleanJson = match[1].trim();\n} else {\n // Falls kein Codeblock vorhanden: versuchen, den Text direkt als JSON zu parsen\n try {\n cleanJson = rawText.trim();\n // JSON strings like \"{\\\"a\\\":1}\" → erst ent-escapen\n if (cleanJson.startsWith('\"') && cleanJson.endsWith('\"')) {\n cleanJson = JSON.parse(cleanJson); \n }\n } catch (e) {\n throw new Error(\n \"Kein JSON-Codeblock gefunden und Text ist kein gültiges JSON.\\nOriginal Text:\\n\" + rawText\n );\n }\n}\n\nlet parsed;\ntry {\n parsed = JSON.parse(cleanJson);\n} catch (err) {\n throw new Error(\n \"Fehler beim JSON parsen: \" + err.message + \"\\nOriginal JSON:\\n\" + cleanJson\n );\n}\n\n// Felder auslesen\nreturn [\n {\n json: {\n sender_name: parsed.sender_name,\n sender_email: parsed.sender_email,\n recipient_name: parsed.recipient_name,\n recipient_email: parsed.recipient_email,\n subject: parsed.subject,\n date_sent: parsed.date_sent,\n context: parsed.context,\n important_content: parsed.important_content,\n Termin_Date: parsed.Termin_Date,\n Termin_Time: parsed.Termin_Time,\n callback_needed: parsed.callback_needed\n }\n }\n];\n"
|
||||
},
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
400,
|
||||
-576
|
||||
],
|
||||
"id": "b9041d27-1c52-4730-9b6f-755deea8e1ea",
|
||||
"name": "Code"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"operation": "executeQuery",
|
||||
"query": "INSERT INTO Termin (Termin_Date, Termin_Time, Bezeichnung, [E-Mail])\nVALUES ('{{ $json.Termin_Date }}', '{{ $json.Termin_Time }}', '{{ $json.important_content }}', '{{ $json.sender_email }}')"
|
||||
},
|
||||
"type": "n8n-nodes-base.microsoftSql",
|
||||
"typeVersion": 1.1,
|
||||
"position": [
|
||||
592,
|
||||
-384
|
||||
],
|
||||
"id": "24933fc1-85c2-4f9e-b919-9001ee53e0c5",
|
||||
"name": "Microsoft SQL",
|
||||
"credentials": {
|
||||
"microsoftSql": {
|
||||
"id": "djdfLzBSpOyGbd5J",
|
||||
"name": "Microsoft SQL account"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"pinData": {},
|
||||
"connections": {
|
||||
"Ollama Chat Model": {
|
||||
"ai_languageModel": [
|
||||
[
|
||||
{
|
||||
"node": "Email Summarization Chain",
|
||||
"type": "ai_languageModel",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Email Trigger (IMAP)": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Edit Fields1",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Edit Fields1": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Email Summarization Chain",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Email Summarization Chain": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Code",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Code": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Send email",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
},
|
||||
{
|
||||
"node": "Microsoft SQL",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Send email": {
|
||||
"main": [
|
||||
[]
|
||||
]
|
||||
}
|
||||
},
|
||||
"active": false,
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"versionId": "10fda10c-5c62-4a6e-a3d3-2b2081722028",
|
||||
"meta": {
|
||||
"templateCredsSetupCompleted": true,
|
||||
"instanceId": "b7269067285ce522731ca81186ba09707a0ea125a4dea42e18c518a85012a790"
|
||||
},
|
||||
"id": "i229inRVlUCmagOy",
|
||||
"tags": []
|
||||
}
|
||||
Reference in New Issue
Block a user