This workflow follows the Documentdefaultdataloader → OpenAI Embeddings recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"updatedAt": "2026-03-29T18:51:59.159Z",
"createdAt": "2026-03-29T15:11:57.978Z",
"id": "mBfJwOXiWDsfjE37",
"name": "FPCVectorStoreIngestion",
"active": false,
"isArchived": false,
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
0,
0
],
"id": "e6dd256d-2ad1-4210-bbd2-c0a89afb6c1e",
"name": "Start"
},
{
"parameters": {
"jsCode": "// FPC Samples Splitter - Teilt FPCSamplesV2.md in einzelne Chunks\n// Jeder Chunk ist ein eigenstaendiges FPC-Beispiel mit Metadaten\n\nconst samples = [\n {\n title: \"AND-Verknuepfung zweier Inputs\",\n category: \"Grundlagen\",\n level: \"Einfach\",\n tags: [\"AND\", \"Logik\", \"Grundlagen\"],\n commands: [\"GET\", \"AND\", \"MOV\"],\n content: \"AND-Verknuepfung: Output 0 = Input 0 AND Input 1. Grundlegende binaere Verknuepfung zweier Eingangssignale. Push-Push-Operate-Pop-Fluss.\\n\\nCode:\\nGET I 0\\nGET I 1\\nAND\\nMOV O 0\\n\\nStack-Fluss: [] -> [I0] -> [I0,I1] -> [I0&&I1] -> []\"\n },\n {\n title: \"OR-Verknuepfung (Logisches ODER)\",\n category: \"Grundlagen\",\n level: \"Einfach\",\n tags: [\"OR\", \"Logik\", \"Grundlagen\", \"Parallelschaltung\"],\n commands: [\"GET\", \"OR\", \"MOV\"],\n content: \"OR-Verknuepfung: Output 0 = Input 0 OR Input 1. Output ist AN wenn mindestens ein Input AN ist. Anwendung: Mehrere Taster fuer eine Funktion, Parallelschaltung.\\n\\nCode:\\nGET I 0\\nGET I 1\\nOR\\nMOV O 0\\n\\nStack-Fluss: [] -> [I0] -> [I0,I1] -> [I0||I1] -> []\"\n },\n {\n title: \"Negation eines Inputs\",\n category: \"Grundlagen\",\n level: \"Einfach\",\n tags: [\"NOT\", \"Invertierung\", \"Grundlagen\"],\n commands: [\"GET\", \"NOT\", \"MOV\"],\n content: \"Invertierung: Output 0 = NOT Input 0. Verwendung eines unaeren logischen Operators auf dem Stack.\\n\\nCode:\\nGET I 0\\nNOT\\nMOV O 0\\n\\nStack-Fluss: [] -> [I0] -> [!I0] -> []\"\n },\n {\n title: \"XOR-Verknuepfung (Exklusiv-ODER)\",\n category: \"Grundlagen\",\n level: \"Einfach\",\n tags: [\"XOR\", \"Wechselschaltung\", \"Grundlagen\"],\n commands: [\"GET\", \"XOR\", \"MOV\"],\n content: \"XOR-Verknuepfung: Output 0 = Input 0 XOR Input 1. Output ist AN wenn genau ein Input AN ist. Anwendung: Wechselschaltung (Licht), Zustandsaenderungserkennung.\\n\\nCode:\\nGET I 0\\nGET I 1\\nXOR\\nMOV O 0\\n\\nStack-Fluss: [] -> [I0] -> [I0,I1] -> [I0^I1] -> []\"\n },\n {\n title: \"NAND-Verknuepfung (Negiertes UND)\",\n category: \"Grundlagen\",\n level: \"Einfach\",\n tags: [\"NAND\", \"Logik\", \"Grundlagen\"],\n commands: [\"GET\", \"AND\", \"NOT\", \"MOV\"],\n content: \"NAND-Verknuepfung: Output 0 = NOT (Input 0 AND Input 1). Output ist AUS nur wenn beide Inputs AN sind. Basis fuer komplexe Logik.\\n\\nCode:\\nGET I 0\\nGET I 1\\nAND\\nNOT\\nMOV O 0\\n\\nStack-Fluss: [] -> [I0] -> [I0,I1] -> [I0&&I1] -> [!(I0&&I1)] -> []\"\n },\n {\n title: \"NOR-Verknuepfung (Negiertes ODER)\",\n category: \"Grundlagen\",\n level: \"Einfach\",\n tags: [\"NOR\", \"Logik\", \"Grundlagen\", \"Stoerung\"],\n commands: [\"GET\", \"OR\", \"NOT\", \"MOV\"],\n content: \"NOR-Verknuepfung: Output 0 = NOT (Input 0 OR Input 1). Output ist AN nur wenn beide Inputs AUS sind. Anwendung: Ruhe-/Stoerungszustand.\\n\\nCode:\\nGET I 0\\nGET I 1\\nOR\\nNOT\\nMOV O 0\\n\\nStack-Fluss: [] -> [I0] -> [I0,I1] -> [I0||I1] -> [!(I0||I1)] -> []\"\n },\n {\n title: \"Drei-Input AND-Verknuepfung\",\n category: \"Grundlagen\",\n level: \"Einfach\",\n tags: [\"AND\", \"Drei-Input\", \"Mehrfachbedingung\"],\n commands: [\"GET\", \"AND\", \"MOV\"],\n content: \"Drei-Input AND: Output 0 = Input 0 AND Input 1 AND Input 2. Output nur AN wenn alle drei Inputs AN sind. Anwendung: Drei-Hand-Bedienung, Mehrfachbedingung.\\n\\nCode:\\nGET I 0\\nGET I 1\\nAND\\nGET I 2\\nAND\\nMOV O 0\\n\\nStack-Fluss: [] -> [I0] -> [I0,I1] -> [I0&&I1] -> [I0&&I1,I2] -> [I0&&I1&&I2] -> []\"\n },\n {\n title: \"Bedingtes Setzen eines Outputs (CMOV)\",\n category: \"Grundlagen\",\n level: \"Einfach\",\n tags: [\"CMOV\", \"bedingt\", \"Grundlagen\"],\n commands: [\"GET\", \"CMOV\"],\n content: \"Bedingtes Setzen: Wenn I0 true dann O1 = 1. Bedingte Ausfuehrung einer Aktion auf Basis des obersten Stack-Wertes. CMOV poppt den Stack-Wert und fuehrt die Aktion nur bei true aus.\\n\\nCode:\\nGET I 0\\nCMOV O 1 1\\n\\nStack-Fluss: [] -> [I0] -> [] (O1 wird nur gesetzt wenn I0=true)\"\n },\n {\n title: \"Bedingtes Setzen eines Timers (CSET)\",\n category: \"Grundlagen\",\n level: \"Einfach\",\n tags: [\"CSET\", \"Timer\", \"bedingt\"],\n commands: [\"GET\", \"CSET\"],\n content: \"Bedingtes Timer-Setzen: Wenn I0 true dann Timer 0 mit 500ms starten. CSET poppt den Stack-Wert und startet den Timer nur bei true.\\n\\nCode:\\nGET I 0\\nCSET T 0 500\\n\\nStack-Fluss: [] -> [I0] -> [] (Timer wird nur gestartet wenn I0=true)\\n\\nWICHTIG: CSET darf nicht zyklisch in einem dauerhaft true-Zweig verwendet werden, da dies den Timer staendig neu triggert.\"\n },\n {\n title: \"Einfacher Blinker (1 Hz)\",\n category: \"Timer und Blinker\",\n level: \"Mittel\",\n tags: [\"Timer\", \"Blinker\", \"1Hz\", \"Statusanzeige\"],\n commands: [\"GETNOT\", \"DUP\", \"CSET\", \"CMOV\", \"GET\", \"MOV\"],\n content: \"Einfacher Blinker mit 1 Hz (500ms an/aus). Memory 0 verhindert Timer-Neustart. Timer wird nur beim ersten Zyklus gestartet (einmalige Initialisierung mit Memory-Flag).\\n\\nCode:\\n# Blinker mit 1 Hz\\nGETNOT M 0\\nDUP\\nCSET T 0 500\\nCMOV M 0 1\\nGET T 0\\nMOV O 0\\n\\nStack-Fluss:\\nGETNOT M 0: [] -> [!M0]\\nDUP: [!M0] -> [!M0, !M0]\\nCSET T 0 500: [!M0, !M0] -> [!M0] (startet Timer nur beim ersten Zyklus)\\nCMOV M 0 1: [!M0] -> [] (setzt Flag)\\nGET T 0: [] -> [T0]\\nMOV O 0: [T0] -> []\\n\\nWICHTIG: Das GETNOT+DUP+CSET+CMOV Pattern ist das verbindliche Muster fuer einmalige Timer-Initialisierung.\"\n },\n {\n title: \"Eingangsgesteuerter Blinker (1 Hz nur bei I0)\",\n category: \"Timer und Blinker\",\n level: \"Mittel\",\n tags: [\"Timer\", \"Blinker\", \"Gating\", \"eingangsgesteuert\"],\n commands: [\"GETNOT\", \"DUP\", \"CSET\", \"CMOV\", \"GET\", \"AND\", \"MOV\"],\n content: \"Eingangsgesteuerter Blinker: Output 0 blinkt mit 1 Hz, aber nur solange Input 0 aktiv ist. Zweiphasen-Muster: 1) Timer einmalig initialisieren 2) Ausgabe ueber Logik-Gating.\\n\\nCode:\\n# Timer einmalig initialisieren\\nGETNOT M 0\\nDUP\\nCSET T 0 500\\nCMOV M 0 1\\n# Blinksignal mit Freigabe I0 verbinden\\nGET I 0\\nGET T 0\\nAND\\nMOV O 0\\n\\nWICHTIG: Kein CSET im laufenden I/O-Gating-Teil! Timer wird einmalig gestartet und laeuft dauerhaft. Die Ausgabe wird nur durch AND mit I0 gesteuert.\\n\\nAnti-Pattern: CSET T 0 500 im Eingangspfad fuehrt zu staendigem Retrigger und verhindert stabiles Blinken.\"\n },\n {\n title: \"Schneller Blinker (5 Hz)\",\n category: \"Timer und Blinker\",\n level: \"Mittel\",\n tags: [\"Timer\", \"Blinker\", \"5Hz\", \"Alarm\"],\n commands: [\"GETNOT\", \"DUP\", \"CSET\", \"CMOV\", \"GET\", \"MOV\"],\n content: \"Schneller Blinker mit 5 Hz (100ms an/aus). Anwendung: Alarmanzeige, Aufmerksamkeitssignal.\\n\\nCode:\\nGETNOT M 0\\nDUP\\nCSET T 0 100\\nCMOV M 0 1\\nGET T 0\\nMOV O 0\\n\\nGleiche Struktur wie 1Hz-Blinker, nur mit 100ms statt 500ms Periode.\"\n },\n {\n title: \"Timer stoppen\",\n category: \"Timer und Blinker\",\n level: \"Einfach\",\n tags: [\"Timer\", \"stoppen\", \"deaktivieren\"],\n commands: [\"GET\", \"CSET\"],\n content: \"Timer-Deaktivierung: Stoppe Timer 0 wenn I0 true. Setzt Timer-Wert auf 0, was den Timer stoppt.\\n\\nCode:\\nGET I 0\\nCSET T 0 0\\n\\nCSET T n 0 stoppt den pulsierenden Timer n.\"\n },\n {\n title: \"Einschaltverzoegerung mit Timer\",\n category: \"Timer und Blinker\",\n level: \"Mittel\",\n tags: [\"Timer\", \"Verzoegerung\", \"Einschaltverzoegerung\", \"TON\"],\n commands: [\"GETNOT\", \"DUP\", \"CMOV\", \"GET\", \"AND\", \"CSET\", \"MOV\"],\n content: \"Einschaltverzoegerung: Ausgang 1 wird nach 5 Sekunden gesetzt, wenn Eingang 1 aktiv ist. Timer wird gestartet wenn Eingang 1 aktiv wird.\\n\\nCode:\\n# Zuruecksetzen wenn I1 inaktiv\\nGETNOT I 1\\nDUP\\nCMOV M 0 0\\nCMOV M 1 0\\n# Timer starten bei steigender Flanke\\nGET I 1\\nGETNOT M 0\\nAND\\nDUP\\nCMOV M 0 1\\nCSET T 0 5000\\n# Nach Ablauf Merker setzen\\nGET M 0\\nGETNOT T 0\\nAND\\nCMOV M 1 1\\n# Ausgang setzen\\nGET M 1\\nMOV O 1\\n\\nPrinzip: Timer laeuft als Puls (5s true, 5s false). Wenn Timer-Wert false wird (nach 5s), wird der Ausgang gesetzt.\"\n },\n {\n title: \"Ausschaltverzoegerung mit Timer\",\n category: \"Timer und Blinker\",\n level: \"Mittel\",\n tags: [\"Timer\", \"Verzoegerung\", \"Ausschaltverzoegerung\", \"TOF\"],\n commands: [\"GET\", \"GETNOT\", \"AND\", \"DUP\", \"CMOV\", \"CSET\", \"OR\", \"MOV\"],\n content: \"Ausschaltverzoegerung: Ausgang bleibt nach Abschalten von Eingang noch 5 Sekunden aktiv.\\n\\nCode:\\nGET I 1\\nCMOV M 0 1\\nGETNOT M 0\\nGETNOT T 0\\nAND\\nCSET T 0 0\\nGETNOT I 1\\nGET M 0\\nAND\\nDUP\\nCMOV M 0 0\\nCSET T 0 5000\\nGET I 1\\nGET T 0\\nOR\\nMOV O 1\\n\\nPrinzip: Wenn Eingang abfaellt, wird Timer gestartet. Ausgang = Eingang OR Timer.\"\n },\n {\n title: \"Counter inkrementieren bei Bedingung\",\n category: \"Counter Operationen\",\n level: \"Mittel\",\n tags: [\"Counter\", \"CINC\", \"Zaehler\", \"Ereignis\"],\n commands: [\"GET\", \"CINC\"],\n content: \"Counter inkrementieren: Wenn I0 true dann Counter 0 wird um 1 erhoeht. Ereignisbasierte Erhoehung eines Counters mittels bedingter Ausfuehrung.\\n\\nCode:\\nGET I 0\\nCINC C 0\\n\\nWICHTIG: CINC wird bei JEDEM Zyklus ausgefuehrt wenn I0 true ist! Fuer flankensensitive Zaehlung muss zusaetzlich eine Flankenerkennung implementiert werden.\"\n },\n {\n title: \"Vergleich eines Counters\",\n category: \"Counter Operationen\",\n level: \"Mittel\",\n tags: [\"Counter\", \"CMP\", \"Vergleich\", \"Schwellenwert\"],\n commands: [\"CMP\", \"MOV\"],\n content: \"Counter-Vergleich: Wenn Counter 0 == 5 dann O2 = true. Zustandspruefung eines Counters.\\n\\nCode:\\nCMP C 0 5\\nMOV O 2\\n\\nVergleichs-Semantik:\\n- CMP C n v -> true bei C[n] == v (exakter Vergleich)\\n- GT C n v -> true bei C[n] >= v+1 (groesser als v)\\n- LE C n v -> true bei C[n] <= v-1 (kleiner als v)\"\n },\n {\n title: \"Toggle-Logik mit Memory\",\n category: \"Toggle-Logik\",\n level: \"Mittel\",\n tags: [\"Toggle\", \"Memory\", \"Zustandsumschaltung\"],\n commands: [\"GET\", \"NOT\", \"CMOV\"],\n content: \"Toggle-Logik: Umschalten von M0 wenn I0 true. Einfache Zustandsumschaltung unter Verwendung eines Memory-Flags.\\n\\nCode:\\nGET I 0\\nGET M 0\\nNOT\\nCMOV M 0 1\\n\\nWICHTIG: Dieses Muster toggelt bei JEDEM Zyklus wenn I0 true ist! Fuer einmaliges Toggeln pro Tastendruck ist eine Flankenerkennung noetig.\"\n },\n {\n title: \"Sicherheitsabschaltung (Not-Aus Vorrang)\",\n category: \"Toggle-Logik\",\n level: \"Mittel\",\n tags: [\"Sicherheit\", \"Not-Aus\", \"Fail-Safe\", \"Vorrang\"],\n commands: [\"GET\", \"GETNOT\", \"AND\", \"MOV\"],\n content: \"Sicherheitsabschaltung: O0 nur aktiv wenn I0 AND NOT I1. I1 ist der Not-Aus-Schalter mit Vorrang. Einfache Fail-Safe-Logik.\\n\\nCode:\\nGET I 0\\nGETNOT I 1\\nAND\\nMOV O 0\\n\\nI1 = Not-Aus (bei true wird O0 sofort abgeschaltet, unabhaengig von I0)\"\n },\n {\n title: \"Anti-Pattern: Timer-Initialisierung ohne DUP (Stack-Fehler)\",\n category: \"Pattern\",\n level: \"Mittel\",\n tags: [\"Anti-Pattern\", \"Stack-Fehler\", \"Timer\", \"DUP\"],\n commands: [\"GETNOT\", \"CSET\", \"CMOV\"],\n content: \"ANTI-PATTERN - FALSCHER Code:\\nGETNOT M 0\\nCSET T 0 500\\nCMOV M 0 1\\n\\nProblem: CSET poppt den Stack-Wert. Fuer CMOV ist kein Wert mehr vorhanden. Stack-Unterlauf!\\n\\nKORREKTER Code (mit DUP):\\nGETNOT M 0\\nDUP\\nCSET T 0 500\\nCMOV M 0 1\\n\\nDUP dupliziert den Wert, so dass sowohl CSET als auch CMOV jeweils einen Wert haben.\"\n },\n {\n title: \"Korrekte Timer-Initialisierung mit Flag\",\n category: \"Pattern\",\n level: \"Mittel\",\n tags: [\"Pattern\", \"Timer\", \"DUP\", \"Initialisierung\", \"Best-Practice\"],\n commands: [\"GETNOT\", \"DUP\", \"CSET\", \"CMOV\"],\n content: \"VERBINDLICHES MUSTER fuer einmalige Timer-Initialisierung:\\n\\nGETNOT M 0\\nDUP\\nCSET T 0 500\\nCMOV M 0 1\\n\\nStack-Fluss:\\n1. GETNOT M 0: prueft ob noch nicht initialisiert -> [!M0]\\n2. DUP: erhaelt den Wert fuer zwei Operationen -> [!M0, !M0]\\n3. CSET T 0 500: startet Timer (poppt einen Wert) -> [!M0]\\n4. CMOV M 0 1: setzt Initialisierungs-Flag (poppt letzten Wert) -> []\\n\\nNach dem ersten Zyklus ist M0=true, GETNOT M 0 liefert false, und weder CSET noch CMOV werden ausgefuehrt.\\n\\nTimer-Definition: SET/CSET T n v bedeutet v ms TRUE, dann v ms FALSE. Gesamtperiode = 2*v ms.\"\n },\n {\n title: \"FPC Sprachregeln und Stack-Disziplin\",\n category: \"Referenz\",\n level: \"Einfach\",\n tags: [\"Referenz\", \"Regeln\", \"Stack\", \"Befehle\"],\n commands: [],\n content: \"FPC Sprachregeln:\\n\\nErlaubte Befehle: GET, GETNOT, DUP, NOT, AND, OR, XOR, MOV, CMOV, SET, CSET, CINC, CDEC, CMP, GT, LE\\n\\nStack-Aenderungen:\\n- GET, GETNOT, CMP, GT, LE: +1 (push)\\n- DUP: +1 (benoetigt mind. 1 Wert)\\n- NOT: 0 (benoetigt 1 Wert, ersetzt ihn)\\n- AND, OR, XOR: -1 (poppt 2, pusht 1)\\n- MOV, CMOV, CSET: -1 (poppt 1)\\n- SET, CINC, CDEC: 0 (kein Stack-Effekt)\\n\\nRessourcen: I 0-63, O 0-63, M 0-1023, T 0-127, C 0-127\\nKommentare: Nur eigene Zeilen mit #, keine Inline-Kommentare\\nStack muss am Programmende leer sein (depth=0)\"\n },\n {\n title: \"FPC Timer-Semantik\",\n category: \"Referenz\",\n level: \"Einfach\",\n tags: [\"Referenz\", \"Timer\", \"Pulsierend\", \"Semantik\"],\n commands: [\"SET\", \"CSET\", \"GET\"],\n content: \"FPC Timer-Semantik:\\n\\nTimer sind PULSIEREND (nicht einmalig!)\\n- SET T n v: startet Timer mit Periode 2*v ms\\n - v ms TRUE, dann v ms FALSE, dann v ms TRUE, ...\\n- CSET T n v: wie SET, aber nur bei true am Stack-Top (poppt Wert)\\n- SET T n 0 / CSET T n 0: stoppt den Timer\\n- GET T n: aktueller Zustand (true/false)\\n\\nBeispiel 500ms: 500ms AN, 500ms AUS, 500ms AN, ...\\n\\nVERBINDLICH: Timer immer einmalig initialisieren (GETNOT M + DUP + CSET + CMOV Pattern).\\nNIE CSET im dauerhaft-true Pfad verwenden (verhindert stabiles Blinken durch Retrigger).\"\n },\n {\n title: \"FPC Counter-Semantik\",\n category: \"Referenz\",\n level: \"Einfach\",\n tags: [\"Referenz\", \"Counter\", \"Vergleich\", \"Semantik\"],\n commands: [\"SET\", \"CINC\", \"CDEC\", \"CMP\", \"GT\", \"LE\"],\n content: \"FPC Counter-Semantik:\\n\\nCounter sind Integer-Werte (C 0 bis C 127).\\n\\nBefehle:\\n- SET C n v: Counter n auf Wert v setzen\\n- CSET C n v: Counter n auf v setzen, nur bei true am Stack\\n- CINC C n [v]: Counter n um v erhoehen (default v=1), nur bei true am Stack\\n- CDEC C n [v]: Counter n um v verringern (default v=1), nur bei true am Stack\\n\\nVergleiche (pushen Ergebnis auf Stack):\\n- CMP C n v: true wenn C[n] == v (exakt gleich)\\n- GT C n v: true wenn C[n] > v (ACHTUNG: strikt groesser, also >= v+1)\\n- LE C n v: true wenn C[n] < v (ACHTUNG: strikt kleiner, also <= v-1)\\n\\nWICHTIG: CINC/CDEC werden bei JEDEM Zyklus ausgefuehrt wenn Bedingung true ist!\"\n }\n];\n\n// Output als einzelne Items fuer Vector Store Ingestion\nreturn samples.map((sample, index) => ({\n json: {\n pageContent: sample.content,\n metadata: {\n id: `fpc_sample_${index + 1}`,\n number: index + 1,\n title: sample.title,\n category: sample.category,\n level: sample.level,\n tags: sample.tags.join(', '),\n commands: sample.commands.join(', ')\n }\n }\n}));"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
256,
0
],
"id": "40823e61-1534-43cc-9c60-7ff9de35fbcf",
"name": "FPC Samples Splitter"
},
{
"parameters": {
"mode": "insert",
"tableName": "fpc_doc_vectors",
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.vectorStorePGVector",
"typeVersion": 1.3,
"position": [
512,
0
],
"id": "53415e5a-f892-4633-a217-492c43e2fe47",
"name": "VectorStore Insert",
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"model": "text-embedding-3-large",
"options": {
"dimensions": 3072
}
},
"type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi",
"typeVersion": 1.2,
"position": [
512,
208
],
"id": "b7f189c7-5d16-46f7-9471-7a754db0173c",
"name": "Embeddings",
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsonMode": "expressionData",
"jsonData": "={{ $json.pageContent }}",
"options": {
"metadata": {
"metadataValues": [
{
"name": "title",
"value": "={{ $json.metadata.title }}"
},
{
"name": "category",
"value": "={{ $json.metadata.category }}"
},
{
"name": "level",
"value": "={{ $json.metadata.level }}"
},
{
"name": "tags",
"value": "={{ $json.metadata.tags }}"
},
{
"name": "commands",
"value": "={{ $json.metadata.commands }}"
},
{
"name": "id",
"value": "={{ $json.metadata.id }}"
}
]
}
}
},
"type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader",
"typeVersion": 1,
"position": [
512,
400
],
"id": "a3ad608c-cb96-4cf1-ba00-9ebc5c6f7f6c",
"name": "Document Loader"
},
{
"parameters": {},
"type": "@n8n/n8n-nodes-langchain.textSplitterCharacterTextSplitter",
"typeVersion": 1,
"position": [
608,
608
],
"id": "4460692a-b8dc-41f2-af13-8bf3209b7766",
"name": "Character Text Splitter"
}
],
"connections": {
"Start": {
"main": [
[
{
"node": "FPC Samples Splitter",
"type": "main",
"index": 0
}
]
]
},
"FPC Samples Splitter": {
"main": [
[
{
"node": "VectorStore Insert",
"type": "main",
"index": 0
}
]
]
},
"Embeddings": {
"ai_embedding": [
[
{
"node": "VectorStore Insert",
"type": "ai_embedding",
"index": 0
}
]
]
},
"Document Loader": {
"ai_document": [
[
{
"node": "VectorStore Insert",
"type": "ai_document",
"index": 0
}
]
]
},
"Character Text Splitter": {
"ai_textSplitter": [
[
{
"node": "Document Loader",
"type": "ai_textSplitter",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1",
"binaryMode": "separate"
},
"staticData": null,
"meta": null,
"versionId": "60550e79-5d7d-4104-a1b4-3bbde04c0865",
"activeVersionId": null,
"triggerCount": 0,
"shared": [
{
"updatedAt": "2026-03-29T15:11:57.980Z",
"createdAt": "2026-03-29T15:11:57.980Z",
"role": "workflow:owner",
"workflowId": "mBfJwOXiWDsfjE37",
"projectId": "NGVmW0kzxTFQBNsK"
}
],
"activeVersion": null,
"tags": []
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
openAiApipostgres
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
FPCVectorStoreIngestion. Uses vectorStorePGVector, embeddingsOpenAi, documentDefaultDataLoader, textSplitterCharacterTextSplitter. Event-driven trigger; 6 nodes.
Source: https://github.com/leoggehrer/FreelyProgrammableControl/blob/cb5c293d7e112aaf6c85cecd39ea3efa11866d36/FPCVectorStoreIngestion.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Alfred (funcional). Uses gmailTool, googleCalendarTool, gmail, embeddingsOpenAi. Event-driven trigger; 83 nodes.
RAG AI Agent Template V5. Uses lmChatOpenAi, documentDefaultDataLoader, embeddingsOpenAi, googleDrive. Event-driven trigger; 56 nodes.
My workflow 2529. Uses lmChatOpenAi, documentDefaultDataLoader, embeddingsOpenAi, googleDrive. Event-driven trigger; 54 nodes.
05. Base_To_Copy. Uses lmChatOpenAi, documentDefaultDataLoader, embeddingsOpenAi, googleDrive. Event-driven trigger; 54 nodes.
OIL Rag. Uses lmChatOpenAi, embeddingsOpenAi, agent, telegramTrigger. Event-driven trigger; 53 nodes.