mirror of
https://github.com/enescingoz/awesome-n8n-templates.git
synced 2025-12-17 09:46:03 +00:00
duplicated files are removed
This commit is contained in:
parent
a1346dcce3
commit
683db34625
@ -1,544 +0,0 @@
|
||||
{
|
||||
"id": "itzURpN5wbUNOXOw",
|
||||
"meta": {
|
||||
"instanceId": "205b3bc06c96f2dc835b4f00e1cbf9a937a74eeb3b47c99d0c30b0586dbf85aa"
|
||||
},
|
||||
"name": "[2/2] KNN classifier (lands dataset)",
|
||||
"tags": [
|
||||
{
|
||||
"id": "QN7etptCmdcGIpkS",
|
||||
"name": "classifier",
|
||||
"createdAt": "2024-12-08T22:08:15.968Z",
|
||||
"updatedAt": "2024-12-09T19:25:04.113Z"
|
||||
}
|
||||
],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "33373ccb-164e-431c-8a9a-d68668fc70be",
|
||||
"name": "Embed image",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"position": [
|
||||
-140,
|
||||
-240
|
||||
],
|
||||
"parameters": {
|
||||
"url": "https://api.voyageai.com/v1/multimodalembeddings",
|
||||
"method": "POST",
|
||||
"options": {},
|
||||
"jsonBody": "={{\n{\n \"inputs\": [\n {\n \"content\": [\n {\n \"type\": \"image_url\",\n \"image_url\": $json.imageURL\n }\n ]\n }\n ],\n \"model\": \"voyage-multimodal-3\",\n \"input_type\": \"document\"\n}\n}}",
|
||||
"sendBody": true,
|
||||
"specifyBody": "json",
|
||||
"authentication": "genericCredentialType",
|
||||
"genericAuthType": "httpHeaderAuth"
|
||||
},
|
||||
"credentials": {
|
||||
"httpHeaderAuth": {
|
||||
"id": "Vb0RNVDnIHmgnZOP",
|
||||
"name": "Voyage API"
|
||||
}
|
||||
},
|
||||
"typeVersion": 4.2
|
||||
},
|
||||
{
|
||||
"id": "58adecfa-45c7-4928-b850-053ea6f3b1c5",
|
||||
"name": "Query Qdrant",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"position": [
|
||||
440,
|
||||
-240
|
||||
],
|
||||
"parameters": {
|
||||
"url": "={{ $json.qdrantCloudURL }}/collections/{{ $json.collectionName }}/points/query",
|
||||
"method": "POST",
|
||||
"options": {},
|
||||
"jsonBody": "={{\n{\n \"query\": $json.ImageEmbedding,\n \"using\": \"voyage\",\n \"limit\": $json.limitKNN,\n \"with_payload\": true\n}\n}}",
|
||||
"sendBody": true,
|
||||
"specifyBody": "json",
|
||||
"authentication": "predefinedCredentialType",
|
||||
"nodeCredentialType": "qdrantApi"
|
||||
},
|
||||
"credentials": {
|
||||
"qdrantApi": {
|
||||
"id": "it3j3hP9FICqhgX6",
|
||||
"name": "QdrantApi account"
|
||||
}
|
||||
},
|
||||
"typeVersion": 4.2
|
||||
},
|
||||
{
|
||||
"id": "258026b7-2dda-4165-bfe1-c4163b9caf78",
|
||||
"name": "Majority Vote",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"position": [
|
||||
840,
|
||||
-240
|
||||
],
|
||||
"parameters": {
|
||||
"language": "python",
|
||||
"pythonCode": "from collections import Counter\n\ninput_json = _input.all()[0]\npoints = input_json['json']['result']['points']\nmajority_vote_two_most_common = Counter([point[\"payload\"][\"landscape_name\"] for point in points]).most_common(2)\n\nreturn [{\n \"json\": {\n \"result\": majority_vote_two_most_common \n }\n}]\n"
|
||||
},
|
||||
"typeVersion": 2
|
||||
},
|
||||
{
|
||||
"id": "e83e7a0c-cb36-46d0-8908-86ee1bddf638",
|
||||
"name": "Increase limitKNN",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"position": [
|
||||
1240,
|
||||
-240
|
||||
],
|
||||
"parameters": {
|
||||
"options": {},
|
||||
"assignments": {
|
||||
"assignments": [
|
||||
{
|
||||
"id": "0b5d257b-1b27-48bc-bec2-78649bc844cc",
|
||||
"name": "limitKNN",
|
||||
"type": "number",
|
||||
"value": "={{ $('Propagate loop variables').item.json.limitKNN + 5}}"
|
||||
},
|
||||
{
|
||||
"id": "afee4bb3-f78b-4355-945d-3776e33337a4",
|
||||
"name": "ImageEmbedding",
|
||||
"type": "array",
|
||||
"value": "={{ $('Qdrant variables + embedding + KNN neigbours').first().json.ImageEmbedding }}"
|
||||
},
|
||||
{
|
||||
"id": "701ed7ba-d112-4699-a611-c0c134757a6c",
|
||||
"name": "qdrantCloudURL",
|
||||
"type": "string",
|
||||
"value": "={{ $('Qdrant variables + embedding + KNN neigbours').first().json.qdrantCloudURL }}"
|
||||
},
|
||||
{
|
||||
"id": "f5612f78-e7d8-4124-9c3a-27bd5870c9bf",
|
||||
"name": "collectionName",
|
||||
"type": "string",
|
||||
"value": "={{ $('Qdrant variables + embedding + KNN neigbours').first().json.collectionName }}"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"typeVersion": 3.4
|
||||
},
|
||||
{
|
||||
"id": "8edbff53-cba6-4491-9d5e-bac7ad6db418",
|
||||
"name": "Propagate loop variables",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"position": [
|
||||
640,
|
||||
-240
|
||||
],
|
||||
"parameters": {
|
||||
"options": {},
|
||||
"assignments": {
|
||||
"assignments": [
|
||||
{
|
||||
"id": "880838bf-2be2-4f5f-9417-974b3cbee163",
|
||||
"name": "=limitKNN",
|
||||
"type": "number",
|
||||
"value": "={{ $json.result.points.length}}"
|
||||
},
|
||||
{
|
||||
"id": "5fff2bea-f644-4fd9-ad04-afbecd19a5bc",
|
||||
"name": "result",
|
||||
"type": "object",
|
||||
"value": "={{ $json.result }}"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"typeVersion": 3.4
|
||||
},
|
||||
{
|
||||
"id": "6fad4cc0-f02c-429d-aa4e-0d69ebab9d65",
|
||||
"name": "Image Test URL",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"position": [
|
||||
-320,
|
||||
-240
|
||||
],
|
||||
"parameters": {
|
||||
"options": {},
|
||||
"assignments": {
|
||||
"assignments": [
|
||||
{
|
||||
"id": "46ceba40-fb25-450c-8550-d43d8b8aa94c",
|
||||
"name": "imageURL",
|
||||
"type": "string",
|
||||
"value": "={{ $json.query.imageURL }}"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"typeVersion": 3.4
|
||||
},
|
||||
{
|
||||
"id": "f02e79e2-32c8-4af0-8bf9-281119b23cc0",
|
||||
"name": "Return class",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"position": [
|
||||
1240,
|
||||
0
|
||||
],
|
||||
"parameters": {
|
||||
"options": {},
|
||||
"assignments": {
|
||||
"assignments": [
|
||||
{
|
||||
"id": "bd8ca541-8758-4551-b667-1de373231364",
|
||||
"name": "class",
|
||||
"type": "string",
|
||||
"value": "={{ $json.result[0][0] }}"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"typeVersion": 3.4
|
||||
},
|
||||
{
|
||||
"id": "83ca90fb-d5d5-45f4-8957-4363a4baf8ed",
|
||||
"name": "Check tie",
|
||||
"type": "n8n-nodes-base.if",
|
||||
"position": [
|
||||
1040,
|
||||
-240
|
||||
],
|
||||
"parameters": {
|
||||
"options": {},
|
||||
"conditions": {
|
||||
"options": {
|
||||
"version": 2,
|
||||
"leftValue": "",
|
||||
"caseSensitive": true,
|
||||
"typeValidation": "strict"
|
||||
},
|
||||
"combinator": "and",
|
||||
"conditions": [
|
||||
{
|
||||
"id": "980663f6-9d7d-4e88-87b9-02030882472c",
|
||||
"operator": {
|
||||
"type": "number",
|
||||
"operation": "gt"
|
||||
},
|
||||
"leftValue": "={{ $json.result.length }}",
|
||||
"rightValue": 1
|
||||
},
|
||||
{
|
||||
"id": "9f46fdeb-0f89-4010-99af-624c1c429d6a",
|
||||
"operator": {
|
||||
"type": "number",
|
||||
"operation": "equals"
|
||||
},
|
||||
"leftValue": "={{ $json.result[0][1] }}",
|
||||
"rightValue": "={{ $json.result[1][1] }}"
|
||||
},
|
||||
{
|
||||
"id": "c59bc4fe-6821-4639-8595-fdaf4194c1e1",
|
||||
"operator": {
|
||||
"type": "number",
|
||||
"operation": "lte"
|
||||
},
|
||||
"leftValue": "={{ $('Propagate loop variables').item.json.limitKNN }}",
|
||||
"rightValue": 100
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"typeVersion": 2.2
|
||||
},
|
||||
{
|
||||
"id": "847ced21-4cfd-45d8-98fa-b578adc054d6",
|
||||
"name": "Qdrant variables + embedding + KNN neigbours",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"position": [
|
||||
120,
|
||||
-240
|
||||
],
|
||||
"parameters": {
|
||||
"options": {},
|
||||
"assignments": {
|
||||
"assignments": [
|
||||
{
|
||||
"id": "de66070d-5e74-414e-8af7-d094cbc26f62",
|
||||
"name": "ImageEmbedding",
|
||||
"type": "array",
|
||||
"value": "={{ $json.data[0].embedding }}"
|
||||
},
|
||||
{
|
||||
"id": "58b7384d-fd0c-44aa-9f8e-0306a99be431",
|
||||
"name": "qdrantCloudURL",
|
||||
"type": "string",
|
||||
"value": "=https://152bc6e2-832a-415c-a1aa-fb529f8baf8d.eu-central-1-0.aws.cloud.qdrant.io"
|
||||
},
|
||||
{
|
||||
"id": "e34c4d88-b102-43cc-a09e-e0553f2da23a",
|
||||
"name": "collectionName",
|
||||
"type": "string",
|
||||
"value": "=land-use"
|
||||
},
|
||||
{
|
||||
"id": "db37e18d-340b-4624-84f6-df993af866d6",
|
||||
"name": "limitKNN",
|
||||
"type": "number",
|
||||
"value": "=10"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"typeVersion": 3.4
|
||||
},
|
||||
{
|
||||
"id": "d1bc4edc-37d2-43ac-8d8b-560453e68d1f",
|
||||
"name": "Sticky Note",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
-940,
|
||||
-120
|
||||
],
|
||||
"parameters": {
|
||||
"color": 6,
|
||||
"width": 320,
|
||||
"height": 540,
|
||||
"content": "Here we're classifying existing types of satellite imagery of land types:\n- 'agricultural',\n- 'airplane',\n- 'baseballdiamond',\n- 'beach',\n- 'buildings',\n- 'chaparral',\n- 'denseresidential',\n- 'forest',\n- 'freeway',\n- 'golfcourse',\n- 'harbor',\n- 'intersection',\n- 'mediumresidential',\n- 'mobilehomepark',\n- 'overpass',\n- 'parkinglot',\n- 'river',\n- 'runway',\n- 'sparseresidential',\n- 'storagetanks',\n- 'tenniscourt'\n"
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "13560a31-3c72-43b8-9635-3f9ca11f23c9",
|
||||
"name": "Sticky Note1",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
-520,
|
||||
-460
|
||||
],
|
||||
"parameters": {
|
||||
"color": 6,
|
||||
"content": "I tested this KNN classifier on a whole `test` set of a dataset (it's not a part of the collection, only `validation` + `train` parts). Accuracy of classification on `test` is **93.24%**, no fine-tuning, no metric learning."
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "8c9dcbcb-a1ad-430f-b7dd-e19b5645b0f6",
|
||||
"name": "Execute Workflow Trigger",
|
||||
"type": "n8n-nodes-base.executeWorkflowTrigger",
|
||||
"position": [
|
||||
-520,
|
||||
-240
|
||||
],
|
||||
"parameters": {},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "b36fb270-2101-45e9-bb5c-06c4e07b769c",
|
||||
"name": "Sticky Note2",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
-1080,
|
||||
-520
|
||||
],
|
||||
"parameters": {
|
||||
"width": 460,
|
||||
"height": 380,
|
||||
"content": "## KNN classification workflow-tool\n### This n8n template takes an image URL (as anomaly detection tool does), and as output, it returns a class of the object on the image (out of land types list)\n\n* An image URL is received via the Execute Workflow Trigger, which is then sent to the Voyage.ai Multimodal Embeddings API to fetch its embedding.\n* The image's embedding vector is then used to query Qdrant, returning a set of X similar images with pre-labeled classes.\n* Majority voting is done for classes of neighbouring images.\n* A loop is used to resolve scenarios where there is a tie in Majority Voting (for example, we have 5 \"forest\" and 5 \"beach\"), and we increase the number of neighbours to retrieve.\n* When the loop finally resolves, the identified class is returned to the calling workflow."
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "51ece7fc-fd85-4d20-ae26-4df2d3893251",
|
||||
"name": "Sticky Note3",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
120,
|
||||
-40
|
||||
],
|
||||
"parameters": {
|
||||
"height": 200,
|
||||
"content": "Variables define another Qdrant's collection with landscapes (uploaded similarly as the crops collection, don't forget to switch it with your data) + amount of neighbours **limitKNN** in the database we'll use for an input image classification."
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "7aad5904-eb0b-4389-9d47-cc91780737ba",
|
||||
"name": "Sticky Note4",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
-180,
|
||||
-60
|
||||
],
|
||||
"parameters": {
|
||||
"height": 80,
|
||||
"content": "Similarly to anomaly detection tool, we're embedding input image with the Voyage model"
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "d3702707-ee4a-481f-82ca-d9386f5b7c8a",
|
||||
"name": "Sticky Note5",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
440,
|
||||
-500
|
||||
],
|
||||
"parameters": {
|
||||
"width": 740,
|
||||
"height": 200,
|
||||
"content": "## Tie loop\nHere we're [querying](https://api.qdrant.tech/api-reference/search/query-points) Qdrant, getting **limitKNN** nearest neighbours to our image <*Query Qdrant node*>, parsing their classes from payloads (images were pre-labeled & uploaded with their labels to Qdrant) & calculating the most frequent class name <*Majority Vote node*>. If there is a tie <*check tie node*> in 2 most common classes, for example, we have 5 \"forest\" and 5 \"harbor\", we repeat the procedure with the number of neighbours increased by 5 <*propagate loop variables node* and *increase limitKNN node*>.\nIf there is no tie, or we have already checked 100 neighbours, we exit the loop <*check tie node*> and return the class-answer."
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "d26911bb-0442-4adc-8511-7cec2d232393",
|
||||
"name": "Sticky Note6",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
1240,
|
||||
160
|
||||
],
|
||||
"parameters": {
|
||||
"height": 80,
|
||||
"content": "Here, we extract the name of the input image class decided by the Majority Vote\n"
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "84ffc859-1d5c-4063-9051-3587f30a0017",
|
||||
"name": "Sticky Note10",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
-520,
|
||||
80
|
||||
],
|
||||
"parameters": {
|
||||
"color": 4,
|
||||
"width": 540,
|
||||
"height": 260,
|
||||
"content": "### KNN (k nearest neighbours) classification\n1. The first pipeline is uploading (lands) dataset to Qdrant's collection.\n2. **This is the KNN classifier tool, which takes any image as input and classifies it based on queries to the Qdrant (lands) collection.**\n\n### To recreate it\nYou'll have to upload [lands](https://www.kaggle.com/datasets/apollo2506/landuse-scene-classification) dataset from Kaggle to your own Google Storage bucket, and re-create APIs/connections to [Qdrant Cloud](https://qdrant.tech/documentation/quickstart-cloud/) (you can use **Free Tier** cluster), Voyage AI API & Google Cloud Storage\n\n**In general, pipelines are adaptable to any dataset of images**\n"
|
||||
},
|
||||
"typeVersion": 1
|
||||
}
|
||||
],
|
||||
"active": false,
|
||||
"pinData": {
|
||||
"Execute Workflow Trigger": [
|
||||
{
|
||||
"json": {
|
||||
"query": {
|
||||
"imageURL": "https://storage.googleapis.com/n8n-qdrant-demo/land-use/images_train_test_val/test/buildings/buildings_000323.png"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"versionId": "c8cfe732-fd78-4985-9540-ed8cb2de7ef3",
|
||||
"connections": {
|
||||
"Check tie": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Increase limitKNN",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"node": "Return class",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Embed image": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Qdrant variables + embedding + KNN neigbours",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Query Qdrant": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Propagate loop variables",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Majority Vote": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Check tie",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Image Test URL": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Embed image",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Increase limitKNN": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Query Qdrant",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Execute Workflow Trigger": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Image Test URL",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Propagate loop variables": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Majority Vote",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Qdrant variables + embedding + KNN neigbours": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Query Qdrant",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,177 +0,0 @@
|
||||
{
|
||||
"id": "QnVdtKiTf3nbrNkh",
|
||||
"meta": {
|
||||
"instanceId": "558d88703fb65b2d0e44613bc35916258b0f0bf983c5d4730c00c424b77ca36a",
|
||||
"templateCredsSetupCompleted": true
|
||||
},
|
||||
"name": "Summarize emails with A.I. then send to messenger",
|
||||
"tags": [],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "50e12e63-df28-45ac-9208-48cbf5116d09",
|
||||
"name": "Read emails (IMAP)",
|
||||
"type": "n8n-nodes-base.emailReadImap",
|
||||
"position": [
|
||||
340,
|
||||
260
|
||||
],
|
||||
"parameters": {
|
||||
"options": {},
|
||||
"postProcessAction": "nothing"
|
||||
},
|
||||
"credentials": {
|
||||
"imap": {
|
||||
"id": "gXtdakU9M02LBQc3",
|
||||
"name": "IMAP account"
|
||||
}
|
||||
},
|
||||
"typeVersion": 2
|
||||
},
|
||||
{
|
||||
"id": "6565350b-2269-44e3-8f36-8797f32d3e09",
|
||||
"name": "Send email to A.I. to summarize",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"position": [
|
||||
700,
|
||||
260
|
||||
],
|
||||
"parameters": {
|
||||
"url": "https://openrouter.ai/api/v1/chat/completions",
|
||||
"method": "POST",
|
||||
"options": {},
|
||||
"jsonBody": "={\n \"model\": \"meta-llama/llama-3.1-70b-instruct:free\",\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"I want you to read and summarize all the emails. If it's not rimportant, just give me a short summary with less than 10 words.\\n\\nHighlight as important if it is, add an emoji to indicate it is urgent:\\nFor the relevant content, find any action items and deadlines. Sometimes I need to sign up before a certain date or pay before a certain date, please highlight that in the summary for me.\\n\\nPut the deadline in BOLD at the top. If the email is not important, keep the summary short to 1 sentence only.\\n\\nHere's the email content for you to read:\\nSender email address: {{ encodeURIComponent($json.from) }}\\nSubject: {{ encodeURIComponent($json.subject) }}\\n{{ encodeURIComponent($json.textHtml) }}\"\n }\n ]\n}",
|
||||
"sendBody": true,
|
||||
"specifyBody": "json",
|
||||
"authentication": "genericCredentialType",
|
||||
"genericAuthType": "httpHeaderAuth"
|
||||
},
|
||||
"credentials": {
|
||||
"httpHeaderAuth": {
|
||||
"id": "WY7UkF14ksPKq3S8",
|
||||
"name": "Header Auth account 2"
|
||||
}
|
||||
},
|
||||
"typeVersion": 4.2,
|
||||
"alwaysOutputData": false
|
||||
},
|
||||
{
|
||||
"id": "d04c422a-c000-4e48-82d0-0bf44bcd9fff",
|
||||
"name": "Send summarized content to messenger",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"position": [
|
||||
1100,
|
||||
260
|
||||
],
|
||||
"parameters": {
|
||||
"url": "https://api.line.me/v2/bot/message/push",
|
||||
"method": "POST",
|
||||
"options": {},
|
||||
"jsonBody": "={\n \"to\": \"U3ec262c49811f30cdc2d2f2b0a0df99a\",\n \"messages\": [\n {\n \"type\": \"text\",\n \"text\": \"{{ $json.choices[0].message.content.replace(/\\n/g, \"\\\\n\") }}\"\n }\n ]\n}\n\n\n ",
|
||||
"sendBody": true,
|
||||
"specifyBody": "json",
|
||||
"authentication": "genericCredentialType",
|
||||
"genericAuthType": "httpHeaderAuth"
|
||||
},
|
||||
"credentials": {
|
||||
"httpHeaderAuth": {
|
||||
"id": "SzcKjO9Nn9vZPL2H",
|
||||
"name": "Header Auth account 5"
|
||||
}
|
||||
},
|
||||
"typeVersion": 4.2
|
||||
},
|
||||
{
|
||||
"id": "57a1219c-4f40-407c-855b-86c4c7c468bb",
|
||||
"name": "Sticky Note",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
180,
|
||||
0
|
||||
],
|
||||
"parameters": {
|
||||
"width": 361,
|
||||
"height": 90,
|
||||
"content": "## Summarize emails with A.I.\nYou can find out more about the [use case](https://rumjahn.com/how-a-i-saved-my-kids-school-life-and-my-marriage/)"
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "17686264-56ac-419e-a32b-dc5c75f15f1f",
|
||||
"name": "Sticky Note1",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
283,
|
||||
141
|
||||
],
|
||||
"parameters": {
|
||||
"color": 5,
|
||||
"width": 229,
|
||||
"height": 280,
|
||||
"content": "Find your email server's IMAP Settings. \n- Link for [gmail](https://www.getmailspring.com/setup/access-gmail-via-imap-smtp)"
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "1862abd6-7dca-4c66-90d6-110d4fcf4d99",
|
||||
"name": "Sticky Note2",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
580,
|
||||
0
|
||||
],
|
||||
"parameters": {
|
||||
"color": 6,
|
||||
"width": 365,
|
||||
"height": 442,
|
||||
"content": "For the A.I. you can use Openrouter.ai. \n- Set up a free account\n- The A.I. model selected is FREE to use.\n## Credentials\n- Use header auth\n- Username: Authorization\n- Password: Bearer {insert your API key}.\n- The password is \"Bearer\" space plus your API key."
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "c4a3a76f-539d-4bbf-8f95-d7aaebf39a55",
|
||||
"name": "Sticky Note3",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
1000,
|
||||
0
|
||||
],
|
||||
"parameters": {
|
||||
"color": 4,
|
||||
"width": 307,
|
||||
"height": 439,
|
||||
"content": "Don't use the official Line node. It's outdated.\n## Credentials\n- Use header auth\n- Username: Authorization\n- Password: Bearer {channel access token}\n\nYou can find your channel access token at the [Line API console](https://developers.line.biz/console/). Go to Messaging API and scroll to the bottom."
|
||||
},
|
||||
"typeVersion": 1
|
||||
}
|
||||
],
|
||||
"active": false,
|
||||
"pinData": {},
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"versionId": "81216e6a-2bd8-4215-8a96-376ee520469d",
|
||||
"connections": {
|
||||
"Read emails (IMAP)": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Send email to A.I. to summarize",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Send email to A.I. to summarize": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Send summarized content to messenger",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,224 +0,0 @@
|
||||
{
|
||||
"id": "eXiaTDyKfXpMeyLh",
|
||||
"meta": {
|
||||
"instanceId": "f4f5d195bb2162a0972f737368404b18be694648d365d6c6771d7b4909d28167",
|
||||
"templateCredsSetupCompleted": true
|
||||
},
|
||||
"name": "Dynamically generate HTML page from user request using OpenAI Structured Output",
|
||||
"tags": [],
|
||||
"nodes": [
|
||||
{
|
||||
"id": "b1d9659f-4cd0-4f87-844d-32b2af1dcf13",
|
||||
"name": "Respond to Webhook",
|
||||
"type": "n8n-nodes-base.respondToWebhook",
|
||||
"position": [
|
||||
2160,
|
||||
380
|
||||
],
|
||||
"parameters": {
|
||||
"options": {
|
||||
"responseHeaders": {
|
||||
"entries": [
|
||||
{
|
||||
"name": "Content-Type",
|
||||
"value": "text/html; charset=UTF-8"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"respondWith": "text",
|
||||
"responseBody": "={{ $json.html }}"
|
||||
},
|
||||
"typeVersion": 1.1
|
||||
},
|
||||
{
|
||||
"id": "5ca8ad3e-7702-4f07-af24-d38e94fdc4ec",
|
||||
"name": "Open AI - Using Structured Output",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"position": [
|
||||
1240,
|
||||
380
|
||||
],
|
||||
"parameters": {
|
||||
"url": "https://api.openai.com/v1/chat/completions",
|
||||
"method": "POST",
|
||||
"options": {},
|
||||
"jsonBody": "={\n \"model\": \"gpt-4o-2024-08-06\",\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": \"You are a user interface designer and copy writter. Your job is to help users visualize their website ideas. You design elegant and simple webs, with professional text. You use Tailwind framework\"\n },\n {\n \"role\": \"user\",\n \"content\": \"{{ $json.query.query }}\"\n }\n ],\n \"response_format\":\n{\n \"type\": \"json_schema\",\n \"json_schema\": {\n \"name\": \"ui\",\n \"description\": \"Dynamically generated UI\",\n \"strict\": true,\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"type\": {\n \"type\": \"string\",\n \"description\": \"The type of the UI component\",\n \"enum\": [\n \"div\",\n \"span\",\n \"a\",\n \"p\",\n \"h1\",\n \"h2\",\n \"h3\",\n \"h4\",\n \"h5\",\n \"h6\",\n \"ul\",\n \"ol\",\n \"li\",\n \"img\",\n \"button\",\n \"input\",\n \"textarea\",\n \"select\",\n \"option\",\n \"label\",\n \"form\",\n \"table\",\n \"thead\",\n \"tbody\",\n \"tr\",\n \"th\",\n \"td\",\n \"nav\",\n \"header\",\n \"footer\",\n \"section\",\n \"article\",\n \"aside\",\n \"main\",\n \"figure\",\n \"figcaption\",\n \"blockquote\",\n \"q\",\n \"hr\",\n \"code\",\n \"pre\",\n \"iframe\",\n \"video\",\n \"audio\",\n \"canvas\",\n \"svg\",\n \"path\",\n \"circle\",\n \"rect\",\n \"line\",\n \"polyline\",\n \"polygon\",\n \"g\",\n \"use\",\n \"symbol\"\n]\n },\n \"label\": {\n \"type\": \"string\",\n \"description\": \"The label of the UI component, used for buttons or form fields\"\n },\n \"children\": {\n \"type\": \"array\",\n \"description\": \"Nested UI components\",\n \"items\": {\n \"$ref\": \"#\"\n }\n },\n \"attributes\": {\n \"type\": \"array\",\n \"description\": \"Arbitrary attributes for the UI component, suitable for any element using Tailwind framework\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"description\": \"The name of the attribute, for example onClick or className\"\n },\n \"value\": {\n \"type\": \"string\",\n \"description\": \"The value of the attribute using the Tailwind framework classes\"\n }\n },\n \"additionalProperties\": false,\n \"required\": [\"name\", \"value\"]\n }\n }\n },\n \"required\": [\"type\", \"label\", \"children\", \"attributes\"],\n \"additionalProperties\": false\n }\n }\n}\n}",
|
||||
"sendBody": true,
|
||||
"sendHeaders": true,
|
||||
"specifyBody": "json",
|
||||
"authentication": "predefinedCredentialType",
|
||||
"headerParameters": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "Content-Type",
|
||||
"value": "application/json"
|
||||
}
|
||||
]
|
||||
},
|
||||
"nodeCredentialType": "openAiApi"
|
||||
},
|
||||
"credentials": {
|
||||
"openAiApi": {
|
||||
"id": "WqzqjezKh8VtxdqA",
|
||||
"name": "OpenAi account - Baptiste"
|
||||
}
|
||||
},
|
||||
"typeVersion": 4.2
|
||||
},
|
||||
{
|
||||
"id": "24e5ca73-a3b3-4096-8c66-d84838d89b0c",
|
||||
"name": "OpenAI - JSON to HTML",
|
||||
"type": "@n8n/n8n-nodes-langchain.openAi",
|
||||
"position": [
|
||||
1420,
|
||||
380
|
||||
],
|
||||
"parameters": {
|
||||
"modelId": {
|
||||
"__rl": true,
|
||||
"mode": "list",
|
||||
"value": "gpt-4o-mini",
|
||||
"cachedResultName": "GPT-4O-MINI"
|
||||
},
|
||||
"options": {
|
||||
"temperature": 0.2
|
||||
},
|
||||
"messages": {
|
||||
"values": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "You convert a JSON to HTML. \nThe JSON output has the following fields:\n- html: the page HTML\n- title: the page title"
|
||||
},
|
||||
{
|
||||
"content": "={{ $json.choices[0].message.content }}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"jsonOutput": true
|
||||
},
|
||||
"credentials": {
|
||||
"openAiApi": {
|
||||
"id": "WqzqjezKh8VtxdqA",
|
||||
"name": "OpenAi account - Baptiste"
|
||||
}
|
||||
},
|
||||
"typeVersion": 1.3
|
||||
},
|
||||
{
|
||||
"id": "c50bdc84-ba59-4f30-acf7-496cee25068d",
|
||||
"name": "Format the HTML result",
|
||||
"type": "n8n-nodes-base.html",
|
||||
"position": [
|
||||
1940,
|
||||
380
|
||||
],
|
||||
"parameters": {
|
||||
"html": "<!DOCTYPE html>\n\n<html>\n<head>\n <meta charset=\"UTF-8\" />\n <script src=\"https://cdn.tailwindcss.com\"></script>\n <title>{{ $json.message.content.title }}</title>\n</head>\n<body>\n{{ $json.message.content.html }}\n</body>\n</html>"
|
||||
},
|
||||
"typeVersion": 1.2
|
||||
},
|
||||
{
|
||||
"id": "193093f4-b1ce-4964-ab10-c3208e343c69",
|
||||
"name": "Sticky Note",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
1134,
|
||||
62
|
||||
],
|
||||
"parameters": {
|
||||
"color": 7,
|
||||
"width": 638,
|
||||
"height": 503,
|
||||
"content": "## Generate HTML from user query\n\n**HTTP Request node**\n- Send the user query to OpenAI, with a defined JSON response format - *using HTTP Request node as it has not yet been implemented in the OpenAI nodes*\n- The response format is inspired by the [Structured Output defined in OpenAI Introduction post](https://openai.com/index/introducing-structured-outputs-in-the-api)\n- The output is a JSON containing HTML components and attributed\n\n\n**OpenAI node**\n- Format the response from the previous node from JSON format to HTML format"
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "0371156a-211f-4d92-82b1-f14fe60d4b6b",
|
||||
"name": "Sticky Note1",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
0,
|
||||
60
|
||||
],
|
||||
"parameters": {
|
||||
"color": 7,
|
||||
"width": 768,
|
||||
"height": 503,
|
||||
"content": "## Workflow: Dynamically generate an HTML page from a user request using OpenAI Structured Output\n\n**Overview**\n- This workflow is a experiment to build HTML pages from a user input using the new Structured Output from OpenAI.\n- The Structured Output could be used in a variety of cases. Essentially, it guarantees the output from the GPT will follow a defined structure (JSON object).\n- It uses Tailwind CSS to make it slightly nicer, but any\n\n**How it works**\n- Once active, go to the production URL and add what you'd like to build as the parameter \"query\"\n- Example: https://production_url.com?query=a%20signup%20form\n- OpenAI nodes will first output the UI as a JSON then convert it to HTML\n- Finally, the response is integrated in a HTML container and rendered to the user\n\n**Further thoughts**\n- Results are not yet amazing, it is hard to see the direct value of such an experiment\n- But it showcase the potential of the Structured Output. Being able to guarantee the output format is key to build robust AI applications."
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "06380781-5189-4d99-9ecd-d8913ce40fd5",
|
||||
"name": "Webhook",
|
||||
"type": "n8n-nodes-base.webhook",
|
||||
"position": [
|
||||
820,
|
||||
380
|
||||
],
|
||||
"webhookId": "d962c916-6369-431a-9d80-af6e6a50fdf5",
|
||||
"parameters": {
|
||||
"path": "d962c916-6369-431a-9d80-af6e6a50fdf5",
|
||||
"options": {
|
||||
"allowedOrigins": "*"
|
||||
},
|
||||
"responseMode": "responseNode"
|
||||
},
|
||||
"typeVersion": 2
|
||||
}
|
||||
],
|
||||
"active": true,
|
||||
"pinData": {},
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"versionId": "d2307a2a-5427-4769-94a6-10eab703a788",
|
||||
"connections": {
|
||||
"Webhook": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Open AI - Using Structured Output",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"OpenAI - JSON to HTML": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Format the HTML result",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Format the HTML result": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Respond to Webhook",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Open AI - Using Structured Output": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "OpenAI - JSON to HTML",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,504 +0,0 @@
|
||||
{
|
||||
"meta": {
|
||||
"instanceId": "f4f5d195bb2162a0972f737368404b18be694648d365d6c6771d7b4909d28167"
|
||||
},
|
||||
"nodes": [
|
||||
{
|
||||
"id": "b165115d-5505-4e03-bf41-c21320cb8b09",
|
||||
"name": "Sticky Note1",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
80,
|
||||
40
|
||||
],
|
||||
"parameters": {
|
||||
"color": 7,
|
||||
"width": 681.8337349708484,
|
||||
"height": 843.1482165886073,
|
||||
"content": "## Workflow: Text automations using Apple Shortcuts\n\n**Overview**\n- This workflow answers user requests sent via Apple Shortcuts\n- Several Shortcuts call the same webhook, with a query and a type of query\n- Types of query are:\n - translate to english\n - translate to spanish\n - correct grammar (without changing the actual content)\n - make content shorter\n - make content longer\n\n\n**How it works**\n- Select a text you are writing\n- Launch the shortcut\n- The text is sent to the webhook\n- Depending on the type of request, a different prompt is used\n- Each request is sent to an OpenAI node\n- The workflow responds to the request with the response from GPT\n- Shortcut replace the selected text with the new one\n\n**How to use it**\n- Activate the workflow\n- Download [this Shortcut template](https://drive.usercontent.google.com/u/0/uc?id=16zs5iJX7KeX_4e0SoV49_KfbU7-EF0NE&export=download)\n- Install the shortcut\n- In step 2 of the shortcut, change the url of the Webhook\n- In Shortcut details, \"add Keyboard Shortcut\" with the key you want to use to launch the shortcut\n- Go to settings, advanced, check \"Allow running scripts\"\n- You are ready to use the shortcut. Select a text and hit the keyboard shortcut you just defined\n\n\n**Notes**\n- If you use rich formatting, you'll have to test multiple ways to replace characters in the output. For example, you might use `{{ $json.message.content.output.replaceAll('\\n', \"<br/>\") }}` in the \"Respond to Shortcut\" node depending on the app you use most.\n- This is a basic example that you can extend and modify at your will\n- You can duplicate and modify the example shortcut based on your need, as well as making new automations in this workflow."
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "c45400b8-d3b8-47f7-81c6-d791bce4c266",
|
||||
"name": "Switch",
|
||||
"type": "n8n-nodes-base.switch",
|
||||
"position": [
|
||||
1020,
|
||||
380
|
||||
],
|
||||
"parameters": {
|
||||
"rules": {
|
||||
"values": [
|
||||
{
|
||||
"outputKey": "spanish",
|
||||
"conditions": {
|
||||
"options": {
|
||||
"version": 2,
|
||||
"leftValue": "",
|
||||
"caseSensitive": true,
|
||||
"typeValidation": "strict"
|
||||
},
|
||||
"combinator": "and",
|
||||
"conditions": [
|
||||
{
|
||||
"operator": {
|
||||
"type": "string",
|
||||
"operation": "equals"
|
||||
},
|
||||
"leftValue": "={{ $json.body.type }}",
|
||||
"rightValue": "spanish"
|
||||
}
|
||||
]
|
||||
},
|
||||
"renameOutput": true
|
||||
},
|
||||
{
|
||||
"outputKey": "english",
|
||||
"conditions": {
|
||||
"options": {
|
||||
"version": 2,
|
||||
"leftValue": "",
|
||||
"caseSensitive": true,
|
||||
"typeValidation": "strict"
|
||||
},
|
||||
"combinator": "and",
|
||||
"conditions": [
|
||||
{
|
||||
"id": "bedb302f-646c-4dcd-8246-1fcfecfe3f2e",
|
||||
"operator": {
|
||||
"name": "filter.operator.equals",
|
||||
"type": "string",
|
||||
"operation": "equals"
|
||||
},
|
||||
"leftValue": "={{ $json.body.type }}",
|
||||
"rightValue": "english"
|
||||
}
|
||||
]
|
||||
},
|
||||
"renameOutput": true
|
||||
},
|
||||
{
|
||||
"outputKey": "grammar",
|
||||
"conditions": {
|
||||
"options": {
|
||||
"version": 2,
|
||||
"leftValue": "",
|
||||
"caseSensitive": true,
|
||||
"typeValidation": "strict"
|
||||
},
|
||||
"combinator": "and",
|
||||
"conditions": [
|
||||
{
|
||||
"id": "94e6cf7d-576d-4ad9-85b0-c6b945eb41b7",
|
||||
"operator": {
|
||||
"name": "filter.operator.equals",
|
||||
"type": "string",
|
||||
"operation": "equals"
|
||||
},
|
||||
"leftValue": "={{ $json.body.type }}",
|
||||
"rightValue": "grammar"
|
||||
}
|
||||
]
|
||||
},
|
||||
"renameOutput": true
|
||||
},
|
||||
{
|
||||
"outputKey": "shorter",
|
||||
"conditions": {
|
||||
"options": {
|
||||
"version": 2,
|
||||
"leftValue": "",
|
||||
"caseSensitive": true,
|
||||
"typeValidation": "strict"
|
||||
},
|
||||
"combinator": "and",
|
||||
"conditions": [
|
||||
{
|
||||
"id": "1ed0d1e1-2df0-4f8d-b102-4004a25919ed",
|
||||
"operator": {
|
||||
"name": "filter.operator.equals",
|
||||
"type": "string",
|
||||
"operation": "equals"
|
||||
},
|
||||
"leftValue": "={{ $json.body.type }}",
|
||||
"rightValue": "shorter"
|
||||
}
|
||||
]
|
||||
},
|
||||
"renameOutput": true
|
||||
},
|
||||
{
|
||||
"outputKey": "longer",
|
||||
"conditions": {
|
||||
"options": {
|
||||
"version": 2,
|
||||
"leftValue": "",
|
||||
"caseSensitive": true,
|
||||
"typeValidation": "strict"
|
||||
},
|
||||
"combinator": "and",
|
||||
"conditions": [
|
||||
{
|
||||
"id": "4756df03-7e7c-4e28-9b37-14684326b083",
|
||||
"operator": {
|
||||
"name": "filter.operator.equals",
|
||||
"type": "string",
|
||||
"operation": "equals"
|
||||
},
|
||||
"leftValue": "={{ $json.body.type }}",
|
||||
"rightValue": "longer"
|
||||
}
|
||||
]
|
||||
},
|
||||
"renameOutput": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {}
|
||||
},
|
||||
"typeVersion": 3.2
|
||||
},
|
||||
{
|
||||
"id": "48e0e58e-6293-4e11-a488-ca9943b53484",
|
||||
"name": "Respond to Shortcut",
|
||||
"type": "n8n-nodes-base.respondToWebhook",
|
||||
"position": [
|
||||
1840,
|
||||
400
|
||||
],
|
||||
"parameters": {
|
||||
"options": {},
|
||||
"respondWith": "text",
|
||||
"responseBody": "={{ $json.message.content.output.replaceAll('\\n', '<br/>') }}"
|
||||
},
|
||||
"typeVersion": 1.1
|
||||
},
|
||||
{
|
||||
"id": "2655b782-9538-416c-ae65-35f8c77889c7",
|
||||
"name": "Webhook from Shortcut",
|
||||
"type": "n8n-nodes-base.webhook",
|
||||
"position": [
|
||||
840,
|
||||
400
|
||||
],
|
||||
"webhookId": "e4ddadd2-a127-4690-98ca-e9ee75c1bdd6",
|
||||
"parameters": {
|
||||
"path": "shortcut-global-as",
|
||||
"options": {},
|
||||
"httpMethod": "POST",
|
||||
"responseMode": "responseNode"
|
||||
},
|
||||
"typeVersion": 2
|
||||
},
|
||||
{
|
||||
"id": "880ed4a2-0756-4943-a51f-368678e22273",
|
||||
"name": "OpenAI - Make Shorter",
|
||||
"type": "@n8n/n8n-nodes-langchain.openAi",
|
||||
"position": [
|
||||
1300,
|
||||
540
|
||||
],
|
||||
"parameters": {
|
||||
"modelId": {
|
||||
"__rl": true,
|
||||
"mode": "list",
|
||||
"value": "gpt-4o-mini",
|
||||
"cachedResultName": "GPT-4O-MINI"
|
||||
},
|
||||
"options": {},
|
||||
"messages": {
|
||||
"values": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "Summarize this content a little bit (5% shorter)\nOutput a JSON with a single field: output"
|
||||
},
|
||||
{
|
||||
"content": "={{ $json.body.content }}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"jsonOutput": true
|
||||
},
|
||||
"credentials": {
|
||||
"openAiApi": {
|
||||
"id": "WqzqjezKh8VtxdqA",
|
||||
"name": "OpenAi account - Baptiste"
|
||||
}
|
||||
},
|
||||
"typeVersion": 1.4
|
||||
},
|
||||
{
|
||||
"id": "c6c6d988-7aab-4677-af1f-880d05691ec3",
|
||||
"name": "OpenAI - Make Longer",
|
||||
"type": "@n8n/n8n-nodes-langchain.openAi",
|
||||
"position": [
|
||||
1300,
|
||||
680
|
||||
],
|
||||
"parameters": {
|
||||
"modelId": {
|
||||
"__rl": true,
|
||||
"mode": "list",
|
||||
"value": "gpt-4o-mini",
|
||||
"cachedResultName": "GPT-4O-MINI"
|
||||
},
|
||||
"options": {},
|
||||
"messages": {
|
||||
"values": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "Make this content a little longer (5% longer)\nOutput a JSON with a single field: output"
|
||||
},
|
||||
{
|
||||
"content": "={{ $json.body.content }}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"jsonOutput": true
|
||||
},
|
||||
"credentials": {
|
||||
"openAiApi": {
|
||||
"id": "WqzqjezKh8VtxdqA",
|
||||
"name": "OpenAi account - Baptiste"
|
||||
}
|
||||
},
|
||||
"typeVersion": 1.4
|
||||
},
|
||||
{
|
||||
"id": "8e6de4b7-22c3-45c9-a8d7-d498cf829b6f",
|
||||
"name": "OpenAI - Correct Grammar",
|
||||
"type": "@n8n/n8n-nodes-langchain.openAi",
|
||||
"position": [
|
||||
1300,
|
||||
400
|
||||
],
|
||||
"parameters": {
|
||||
"modelId": {
|
||||
"__rl": true,
|
||||
"mode": "list",
|
||||
"value": "gpt-4o-mini",
|
||||
"cachedResultName": "GPT-4O-MINI"
|
||||
},
|
||||
"options": {},
|
||||
"messages": {
|
||||
"values": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "Correct grammar only, don't change the actual contents.\nOutput a JSON with a single field: output"
|
||||
},
|
||||
{
|
||||
"content": "={{ $json.body.content }}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"jsonOutput": true
|
||||
},
|
||||
"credentials": {
|
||||
"openAiApi": {
|
||||
"id": "WqzqjezKh8VtxdqA",
|
||||
"name": "OpenAi account - Baptiste"
|
||||
}
|
||||
},
|
||||
"typeVersion": 1.4
|
||||
},
|
||||
{
|
||||
"id": "bc006b36-5a96-4c3a-9a28-2778a6c49f10",
|
||||
"name": "OpenAI - To Spanish",
|
||||
"type": "@n8n/n8n-nodes-langchain.openAi",
|
||||
"position": [
|
||||
1300,
|
||||
120
|
||||
],
|
||||
"parameters": {
|
||||
"modelId": {
|
||||
"__rl": true,
|
||||
"mode": "list",
|
||||
"value": "gpt-4o-mini",
|
||||
"cachedResultName": "GPT-4O-MINI"
|
||||
},
|
||||
"options": {},
|
||||
"messages": {
|
||||
"values": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "Translate this message to Spanish.\nOutput a JSON with a single field: output"
|
||||
},
|
||||
{
|
||||
"content": "={{ $json.body.content }}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"jsonOutput": true
|
||||
},
|
||||
"credentials": {
|
||||
"openAiApi": {
|
||||
"id": "WqzqjezKh8VtxdqA",
|
||||
"name": "OpenAi account - Baptiste"
|
||||
}
|
||||
},
|
||||
"typeVersion": 1.4
|
||||
},
|
||||
{
|
||||
"id": "330d2e40-1e52-4517-94e0-ce96226697fa",
|
||||
"name": "OpenAI - To English",
|
||||
"type": "@n8n/n8n-nodes-langchain.openAi",
|
||||
"position": [
|
||||
1300,
|
||||
260
|
||||
],
|
||||
"parameters": {
|
||||
"modelId": {
|
||||
"__rl": true,
|
||||
"mode": "list",
|
||||
"value": "gpt-4o-mini",
|
||||
"cachedResultName": "GPT-4O-MINI"
|
||||
},
|
||||
"options": {},
|
||||
"messages": {
|
||||
"values": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "Translate this message to English.\nOutput a JSON with a single field: output"
|
||||
},
|
||||
{
|
||||
"content": "={{ $json.body.content }}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"jsonOutput": true
|
||||
},
|
||||
"credentials": {
|
||||
"openAiApi": {
|
||||
"id": "WqzqjezKh8VtxdqA",
|
||||
"name": "OpenAi account - Baptiste"
|
||||
}
|
||||
},
|
||||
"typeVersion": 1.4
|
||||
},
|
||||
{
|
||||
"id": "925e4b55-ac26-4c16-941f-66d17b6794ab",
|
||||
"name": "Sticky Note",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
80,
|
||||
900
|
||||
],
|
||||
"parameters": {
|
||||
"color": 7,
|
||||
"width": 469.15174499329123,
|
||||
"height": 341.88919758842485,
|
||||
"content": "### Check these explanations [< 3 min]\n\n[](https://www.loom.com/share/c5b657568af64bb1b50fa8e8a91c45d1?sid=a406be73-55eb-4754-9f51-9ddf49b22d69)"
|
||||
},
|
||||
"typeVersion": 1
|
||||
}
|
||||
],
|
||||
"pinData": {},
|
||||
"connections": {
|
||||
"Switch": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "OpenAI - To Spanish",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"node": "OpenAI - To English",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"node": "OpenAI - Correct Grammar",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"node": "OpenAI - Make Shorter",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"node": "OpenAI - Make Longer",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"OpenAI - To English": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Respond to Shortcut",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"OpenAI - To Spanish": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Respond to Shortcut",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"OpenAI - Make Longer": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Respond to Shortcut",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"OpenAI - Make Shorter": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Respond to Shortcut",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Webhook from Shortcut": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Switch",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"OpenAI - Correct Grammar": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Respond to Shortcut",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,991 +0,0 @@
|
||||
{
|
||||
"meta": {
|
||||
"instanceId": "26ba763460b97c249b82942b23b6384876dfeb9327513332e743c5f6219c2b8e"
|
||||
},
|
||||
"nodes": [
|
||||
{
|
||||
"id": "7076854e-c7e8-45b5-9e5e-16678bffa254",
|
||||
"name": "OpenAI Model",
|
||||
"type": "@n8n/n8n-nodes-langchain.lmOpenAi",
|
||||
"position": [
|
||||
2420,
|
||||
480
|
||||
],
|
||||
"parameters": {
|
||||
"model": {
|
||||
"__rl": true,
|
||||
"mode": "list",
|
||||
"value": "gpt-3.5-turbo-1106",
|
||||
"cachedResultName": "gpt-3.5-turbo-1106"
|
||||
},
|
||||
"options": {
|
||||
"temperature": 0
|
||||
}
|
||||
},
|
||||
"credentials": {
|
||||
"openAiApi": {
|
||||
"id": "8gccIjcuf3gvaoEr",
|
||||
"name": "OpenAi account"
|
||||
}
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "00819f1c-2c60-4b7c-b395-445ec05fd898",
|
||||
"name": "Structured Output Parser",
|
||||
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
|
||||
"position": [
|
||||
2600,
|
||||
480
|
||||
],
|
||||
"parameters": {
|
||||
"jsonSchema": "{\n \"Invoice date\": { \"type\": \"date\" },\n \"invoice number\": { \"type\": \"string\" },\n \"Purchase order number\": { \"type\": \"string\" },\n \"Supplier name\": { \"type\": \"string\" },\n \"Supplier address\": {\n \"type\": \"object\",\n \"properties\": {\n \"address 1\": { \"type\": \"string\" },\n \"address 2\": { \"type\": \"string\" },\n \"city\": { \"type\": \"string\" },\n \"postcode\": { \"type\": \"string\" }\n }\n },\n \"Supplier VAT identification number\": { \"type\": \"string\" },\n \"Customer name\": { \"type\": \"string\" },\n \"Customer address\": {\n \"type\": \"object\",\n \"properties\": {\n \"address 1\": { \"type\": \"string\" },\n \"address 2\": { \"type\": \"string\" },\n \"city\": { \"type\": \"string\" },\n \"postcode\": { \"type\": \"string\" }\n }\n },\n \"Customer VAT identification number\": { \"type\": \"string\" }, \n \"Shipping addresses\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"address 1\": { \"type\": \"string\" },\n \"address 2\": { \"type\": \"string\" },\n \"city\": { \"type\": \"string\" },\n \"postcode\": { \"type\": \"string\" }\n }\n }\n },\n \"Line items\": {\n \"type\": \"array\",\n \"items\": {\n \"name\": \"string\",\n \"description\": \"string\",\n \"price\": \"number\",\n \"discount\": \"number\"\n }\n },\n \"Subtotal without VAT\": { \"type\": \"number\" },\n \"Subtotal with VAT\": { \"type\": \"number\" },\n \"Total price\": { \"type\": \"number\" }\n}"
|
||||
},
|
||||
"typeVersion": 1.1
|
||||
},
|
||||
{
|
||||
"id": "3b40d506-aabc-4105-853a-a318375cea73",
|
||||
"name": "Upload to LlamaParse",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"position": [
|
||||
1620,
|
||||
420
|
||||
],
|
||||
"parameters": {
|
||||
"url": "https://api.cloud.llamaindex.ai/api/parsing/upload",
|
||||
"method": "POST",
|
||||
"options": {},
|
||||
"sendBody": true,
|
||||
"contentType": "multipart-form-data",
|
||||
"sendHeaders": true,
|
||||
"authentication": "genericCredentialType",
|
||||
"bodyParameters": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "file",
|
||||
"parameterType": "formBinaryData",
|
||||
"inputDataFieldName": "=attachment_0"
|
||||
}
|
||||
]
|
||||
},
|
||||
"genericAuthType": "httpHeaderAuth",
|
||||
"headerParameters": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "accept",
|
||||
"value": "application/json"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"credentials": {
|
||||
"httpHeaderAuth": {
|
||||
"id": "pZ4YmwFIkyGnbUC7",
|
||||
"name": "LlamaIndex API"
|
||||
}
|
||||
},
|
||||
"typeVersion": 4.2
|
||||
},
|
||||
{
|
||||
"id": "57a5d331-8838-4d44-8fac-a44dba35fcc4",
|
||||
"name": "Sticky Note",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
1540,
|
||||
140
|
||||
],
|
||||
"parameters": {
|
||||
"color": 7,
|
||||
"width": 785.9525375246163,
|
||||
"height": 623.4951418211454,
|
||||
"content": "## 2. Advanced PDF Processing with LlamaParse\n[Read more about using HTTP Requests](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.httprequest/)\n\nLlamaIndex's LlamaCloud is a cloud-based service that allows you to upload,\nparse, and index document. LlamaParse is a tool offered by LlamaCloud\nto parse for complex PDFs with embedded objects ie PDF Tables and figures.\n\nAt time of writing, you can parse 1000 pdfs/day with LlamaCloud's free plan\nby signing up at [https://cloud.llamaindex.ai/](https://cloud.llamaindex.ai/?ref=n8n.io)."
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "a4504d83-da3b-41bc-891f-f8f9314a6af5",
|
||||
"name": "Receiving Invoices",
|
||||
"type": "n8n-nodes-base.gmailTrigger",
|
||||
"position": [
|
||||
780,
|
||||
400
|
||||
],
|
||||
"parameters": {
|
||||
"simple": false,
|
||||
"filters": {
|
||||
"q": "has:attachment",
|
||||
"sender": "invoices@paypal.com"
|
||||
},
|
||||
"options": {
|
||||
"downloadAttachments": true
|
||||
},
|
||||
"pollTimes": {
|
||||
"item": [
|
||||
{
|
||||
"mode": "everyMinute"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"credentials": {
|
||||
"gmailOAuth2": {
|
||||
"id": "Sf5Gfl9NiFTNXFWb",
|
||||
"name": "Gmail account"
|
||||
}
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "02bd4636-f35b-4a3a-8a5f-9ae7aeed2bf4",
|
||||
"name": "Append to Reconciliation Sheet",
|
||||
"type": "n8n-nodes-base.googleSheets",
|
||||
"position": [
|
||||
2960,
|
||||
320
|
||||
],
|
||||
"parameters": {
|
||||
"columns": {
|
||||
"value": {},
|
||||
"schema": [
|
||||
{
|
||||
"id": "Invoice date",
|
||||
"type": "string",
|
||||
"display": true,
|
||||
"removed": false,
|
||||
"required": false,
|
||||
"displayName": "Invoice date",
|
||||
"defaultMatch": false,
|
||||
"canBeUsedToMatch": true
|
||||
},
|
||||
{
|
||||
"id": "invoice number",
|
||||
"type": "string",
|
||||
"display": true,
|
||||
"removed": false,
|
||||
"required": false,
|
||||
"displayName": "invoice number",
|
||||
"defaultMatch": false,
|
||||
"canBeUsedToMatch": true
|
||||
},
|
||||
{
|
||||
"id": "Purchase order number",
|
||||
"type": "string",
|
||||
"display": true,
|
||||
"removed": false,
|
||||
"required": false,
|
||||
"displayName": "Purchase order number",
|
||||
"defaultMatch": false,
|
||||
"canBeUsedToMatch": true
|
||||
},
|
||||
{
|
||||
"id": "Supplier name",
|
||||
"type": "string",
|
||||
"display": true,
|
||||
"removed": false,
|
||||
"required": false,
|
||||
"displayName": "Supplier name",
|
||||
"defaultMatch": false,
|
||||
"canBeUsedToMatch": true
|
||||
},
|
||||
{
|
||||
"id": "Supplier address",
|
||||
"type": "string",
|
||||
"display": true,
|
||||
"removed": false,
|
||||
"required": false,
|
||||
"displayName": "Supplier address",
|
||||
"defaultMatch": false,
|
||||
"canBeUsedToMatch": true
|
||||
},
|
||||
{
|
||||
"id": "Supplier VAT identification number",
|
||||
"type": "string",
|
||||
"display": true,
|
||||
"removed": false,
|
||||
"required": false,
|
||||
"displayName": "Supplier VAT identification number",
|
||||
"defaultMatch": false,
|
||||
"canBeUsedToMatch": true
|
||||
},
|
||||
{
|
||||
"id": "Customer name",
|
||||
"type": "string",
|
||||
"display": true,
|
||||
"removed": false,
|
||||
"required": false,
|
||||
"displayName": "Customer name",
|
||||
"defaultMatch": false,
|
||||
"canBeUsedToMatch": true
|
||||
},
|
||||
{
|
||||
"id": "Customer address",
|
||||
"type": "string",
|
||||
"display": true,
|
||||
"removed": false,
|
||||
"required": false,
|
||||
"displayName": "Customer address",
|
||||
"defaultMatch": false,
|
||||
"canBeUsedToMatch": true
|
||||
},
|
||||
{
|
||||
"id": "Customer VAT identification number",
|
||||
"type": "string",
|
||||
"display": true,
|
||||
"removed": false,
|
||||
"required": false,
|
||||
"displayName": "Customer VAT identification number",
|
||||
"defaultMatch": false,
|
||||
"canBeUsedToMatch": true
|
||||
},
|
||||
{
|
||||
"id": "Shipping addresses",
|
||||
"type": "string",
|
||||
"display": true,
|
||||
"removed": false,
|
||||
"required": false,
|
||||
"displayName": "Shipping addresses",
|
||||
"defaultMatch": false,
|
||||
"canBeUsedToMatch": true
|
||||
},
|
||||
{
|
||||
"id": "Line items",
|
||||
"type": "string",
|
||||
"display": true,
|
||||
"removed": false,
|
||||
"required": false,
|
||||
"displayName": "Line items",
|
||||
"defaultMatch": false,
|
||||
"canBeUsedToMatch": true
|
||||
},
|
||||
{
|
||||
"id": "Subtotal without VAT",
|
||||
"type": "string",
|
||||
"display": true,
|
||||
"removed": false,
|
||||
"required": false,
|
||||
"displayName": "Subtotal without VAT",
|
||||
"defaultMatch": false,
|
||||
"canBeUsedToMatch": true
|
||||
},
|
||||
{
|
||||
"id": "Subtotal with VAT",
|
||||
"type": "string",
|
||||
"display": true,
|
||||
"removed": false,
|
||||
"required": false,
|
||||
"displayName": "Subtotal with VAT",
|
||||
"defaultMatch": false,
|
||||
"canBeUsedToMatch": true
|
||||
},
|
||||
{
|
||||
"id": "Total price",
|
||||
"type": "string",
|
||||
"display": true,
|
||||
"removed": false,
|
||||
"required": false,
|
||||
"displayName": "Total price",
|
||||
"defaultMatch": false,
|
||||
"canBeUsedToMatch": true
|
||||
}
|
||||
],
|
||||
"mappingMode": "autoMapInputData",
|
||||
"matchingColumns": [
|
||||
"output"
|
||||
]
|
||||
},
|
||||
"options": {},
|
||||
"operation": "append",
|
||||
"sheetName": {
|
||||
"__rl": true,
|
||||
"mode": "id",
|
||||
"value": "gid=0"
|
||||
},
|
||||
"documentId": {
|
||||
"__rl": true,
|
||||
"mode": "list",
|
||||
"value": "1omHDl1jpjHyrtga2ZHBddUkbkdatEr1ga9vHc4fQ1pI",
|
||||
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1omHDl1jpjHyrtga2ZHBddUkbkdatEr1ga9vHc4fQ1pI/edit?usp=drivesdk",
|
||||
"cachedResultName": "Invoice Reconciliation"
|
||||
}
|
||||
},
|
||||
"credentials": {
|
||||
"googleSheetsOAuth2Api": {
|
||||
"id": "XHvC7jIRR8A2TlUl",
|
||||
"name": "Google Sheets account"
|
||||
}
|
||||
},
|
||||
"typeVersion": 4.3
|
||||
},
|
||||
{
|
||||
"id": "cdb0a7ee-068d-465a-b4ae-d5221d5e7400",
|
||||
"name": "Get Processing Status",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"position": [
|
||||
1800,
|
||||
420
|
||||
],
|
||||
"parameters": {
|
||||
"url": "=https://api.cloud.llamaindex.ai/api/parsing/job/{{ $json.id }}",
|
||||
"options": {},
|
||||
"sendHeaders": true,
|
||||
"authentication": "genericCredentialType",
|
||||
"genericAuthType": "httpHeaderAuth",
|
||||
"headerParameters": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "accept",
|
||||
"value": "application/json"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"credentials": {
|
||||
"httpHeaderAuth": {
|
||||
"id": "pZ4YmwFIkyGnbUC7",
|
||||
"name": "LlamaIndex API"
|
||||
}
|
||||
},
|
||||
"typeVersion": 4.2
|
||||
},
|
||||
{
|
||||
"id": "b68a01ab-d8e6-42f4-ab1d-81e746695eef",
|
||||
"name": "Wait to stay within service limits",
|
||||
"type": "n8n-nodes-base.wait",
|
||||
"position": [
|
||||
2120,
|
||||
560
|
||||
],
|
||||
"webhookId": "17a96ed6-b5ff-47bb-a8a2-39c1eb40185a",
|
||||
"parameters": {
|
||||
"amount": 1
|
||||
},
|
||||
"typeVersion": 1.1
|
||||
},
|
||||
{
|
||||
"id": "41bd28d2-665a-4f71-a456-98eeb26b6655",
|
||||
"name": "Is Job Ready?",
|
||||
"type": "n8n-nodes-base.switch",
|
||||
"position": [
|
||||
1960,
|
||||
420
|
||||
],
|
||||
"parameters": {
|
||||
"rules": {
|
||||
"values": [
|
||||
{
|
||||
"outputKey": "SUCCESS",
|
||||
"conditions": {
|
||||
"options": {
|
||||
"leftValue": "",
|
||||
"caseSensitive": true,
|
||||
"typeValidation": "strict"
|
||||
},
|
||||
"combinator": "and",
|
||||
"conditions": [
|
||||
{
|
||||
"id": "300fce8c-b19a-4d0c-86e8-f62853c70ce2",
|
||||
"operator": {
|
||||
"name": "filter.operator.equals",
|
||||
"type": "string",
|
||||
"operation": "equals"
|
||||
},
|
||||
"leftValue": "={{ $json.status }}",
|
||||
"rightValue": "SUCCESS"
|
||||
}
|
||||
]
|
||||
},
|
||||
"renameOutput": true
|
||||
},
|
||||
{
|
||||
"outputKey": "ERROR",
|
||||
"conditions": {
|
||||
"options": {
|
||||
"leftValue": "",
|
||||
"caseSensitive": true,
|
||||
"typeValidation": "strict"
|
||||
},
|
||||
"combinator": "and",
|
||||
"conditions": [
|
||||
{
|
||||
"id": "e6058aa0-a3e2-4ce3-9bed-6ff41a5be052",
|
||||
"operator": {
|
||||
"name": "filter.operator.equals",
|
||||
"type": "string",
|
||||
"operation": "equals"
|
||||
},
|
||||
"leftValue": "={{ $json.status }}",
|
||||
"rightValue": "ERROR"
|
||||
}
|
||||
]
|
||||
},
|
||||
"renameOutput": true
|
||||
},
|
||||
{
|
||||
"outputKey": "CANCELED",
|
||||
"conditions": {
|
||||
"options": {
|
||||
"leftValue": "",
|
||||
"caseSensitive": true,
|
||||
"typeValidation": "strict"
|
||||
},
|
||||
"combinator": "and",
|
||||
"conditions": [
|
||||
{
|
||||
"id": "ceb6338f-4261-40ac-be11-91f61c7302ba",
|
||||
"operator": {
|
||||
"name": "filter.operator.equals",
|
||||
"type": "string",
|
||||
"operation": "equals"
|
||||
},
|
||||
"leftValue": "={{ $json.status }}",
|
||||
"rightValue": "CANCELED"
|
||||
}
|
||||
]
|
||||
},
|
||||
"renameOutput": true
|
||||
},
|
||||
{
|
||||
"outputKey": "PENDING",
|
||||
"conditions": {
|
||||
"options": {
|
||||
"leftValue": "",
|
||||
"caseSensitive": true,
|
||||
"typeValidation": "strict"
|
||||
},
|
||||
"combinator": "and",
|
||||
"conditions": [
|
||||
{
|
||||
"id": "0fa97d86-432a-409a-917e-5f1a002b1ab9",
|
||||
"operator": {
|
||||
"name": "filter.operator.equals",
|
||||
"type": "string",
|
||||
"operation": "equals"
|
||||
},
|
||||
"leftValue": "={{ $json.status }}",
|
||||
"rightValue": "PENDING"
|
||||
}
|
||||
]
|
||||
},
|
||||
"renameOutput": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"allMatchingOutputs": true
|
||||
}
|
||||
},
|
||||
"typeVersion": 3
|
||||
},
|
||||
{
|
||||
"id": "f7157abe-b1ee-46b3-adb2-1be056d9d75d",
|
||||
"name": "Sticky Note1",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
694.0259411218055,
|
||||
139.97202236910687
|
||||
],
|
||||
"parameters": {
|
||||
"color": 7,
|
||||
"width": 808.8727491350096,
|
||||
"height": 709.5781339256318,
|
||||
"content": "## 1. Watch for Invoice Emails\n[Read more about Gmail Triggers](https://docs.n8n.io/integrations/builtin/trigger-nodes/n8n-nodes-base.gmailtrigger)\n\nThe Gmail node can watch for all incoming messages and filter based on a condition. We'll set our Gmail node to wait for:\n* a message from particular email address.\n* having an attachment which should be the invoice PDF\n* not having a label \"invoice synced\", which is what we use to avoid duplicate processing."
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "ff7cb6e4-5a60-4f12-b15e-74e7a4a302ce",
|
||||
"name": "Sticky Note2",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
2360,
|
||||
70.48792658995046
|
||||
],
|
||||
"parameters": {
|
||||
"color": 7,
|
||||
"width": 805.0578351924228,
|
||||
"height": 656.5014186128178,
|
||||
"content": "## 3. Use LLMs to Extract Values from Data\n[Read more about Basic LLM Chain](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.chainllm/)\n\nLarge language models are perfect for data extraction tasks as they can work across a range of document layouts without human intervention. The extracted data can then be sent to a variety of datastores such as spreadsheets, accounting systems and/or CRMs.\n\n**Tip:** The \"Structured Output Parser\" ensures the AI output can be\ninserted to our spreadsheet without additional clean up and/or formatting. "
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "0d510631-440b-41f5-b1aa-9b7279e9c8e3",
|
||||
"name": "Sticky Note3",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
1934,
|
||||
774
|
||||
],
|
||||
"parameters": {
|
||||
"color": 5,
|
||||
"width": 394.15089838126653,
|
||||
"height": 154.49585536070904,
|
||||
"content": "### 🙋♂️ Why not just use the built-in PDF convertor?\nA common issue with PDF-to-text convertors are that they ignore important data structures like tables. These structures can be important for data extraction. For example, being able to distinguish between seperate line items in an invoice."
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "fe7fdb90-3c85-4f29-a7d3-16f927f48682",
|
||||
"name": "Sticky Note4",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
3200,
|
||||
157.65172434465347
|
||||
],
|
||||
"parameters": {
|
||||
"color": 7,
|
||||
"width": 362.3535748101346,
|
||||
"height": 440.3435768155051,
|
||||
"content": "## 4. Add Label to Avoid Duplication\n[Read more about working with Gmail](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.gmail/)\n\nTo finish off the workflow, we'll add the \"invoice synced\" label to the original invoice email to flag that the extraction was successful. This can be useful if working with a shared inbox and for quality control purposes later."
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "1acf2c60-c2b9-4f78-94a4-0711c8bd71ab",
|
||||
"name": "Sticky Note5",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
300,
|
||||
140
|
||||
],
|
||||
"parameters": {
|
||||
"width": 360.0244620907562,
|
||||
"height": 573.2443601155958,
|
||||
"content": "## Try Me Out!\n\n**This workflow does the following:**\n* Waits for email invoices with PDF attachments.\n* Uses the LlamaParse service to convert the invoice PDF into a markdown file.\n* Uses a LLM to extract invoice data from the Markdown file.\n* Exports the extracted data to a Google Sheet.\n\n### Follow along with the blog here\nhttps://blog.n8n.io/how-to-extract-data-from-pdf-to-excel-spreadsheet-advance-parsing-with-n8n-io-and-llamaparse/\n\n### Good to know\n* You'll need to create the label \"invoice synced\" in gmail before using this workflow.\n\n### Need Help?\nJoin the [Discord](https://discord.com/invite/XPKeKXeB7d) or ask in the [Forum](https://community.n8n.io/)!\n\nHappy Hacking!"
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "3802c538-acf9-48d8-b011-bfe2fb817350",
|
||||
"name": "Add \"invoice synced\" Label",
|
||||
"type": "n8n-nodes-base.gmail",
|
||||
"position": [
|
||||
3320,
|
||||
400
|
||||
],
|
||||
"parameters": {
|
||||
"labelIds": [
|
||||
"Label_5511644430826409825"
|
||||
],
|
||||
"messageId": "={{ $('Receiving Invoices').item.json.id }}",
|
||||
"operation": "addLabels"
|
||||
},
|
||||
"credentials": {
|
||||
"gmailOAuth2": {
|
||||
"id": "Sf5Gfl9NiFTNXFWb",
|
||||
"name": "Gmail account"
|
||||
}
|
||||
},
|
||||
"typeVersion": 2.1
|
||||
},
|
||||
{
|
||||
"id": "ffabd8c5-c440-4473-8e44-b849426c70cf",
|
||||
"name": "Get Parsed Invoice Data",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"position": [
|
||||
2160,
|
||||
280
|
||||
],
|
||||
"parameters": {
|
||||
"url": "=https://api.cloud.llamaindex.ai/api/parsing/job/{{ $json.id }}/result/markdown",
|
||||
"options": {
|
||||
"redirect": {
|
||||
"redirect": {}
|
||||
}
|
||||
},
|
||||
"authentication": "genericCredentialType",
|
||||
"genericAuthType": "httpHeaderAuth"
|
||||
},
|
||||
"credentials": {
|
||||
"httpHeaderAuth": {
|
||||
"id": "pZ4YmwFIkyGnbUC7",
|
||||
"name": "LlamaIndex API"
|
||||
}
|
||||
},
|
||||
"typeVersion": 4.2
|
||||
},
|
||||
{
|
||||
"id": "5f9b507f-4dc1-4853-bf71-a64f2f4b55c1",
|
||||
"name": "Map Output",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"position": [
|
||||
2760,
|
||||
320
|
||||
],
|
||||
"parameters": {
|
||||
"mode": "raw",
|
||||
"options": {},
|
||||
"jsonOutput": "={{ $json.output }}"
|
||||
},
|
||||
"typeVersion": 3.3
|
||||
},
|
||||
{
|
||||
"id": "d22744cd-151d-4b92-b4f2-4a5b9ceb4ee7",
|
||||
"name": "Apply Data Extraction Rules",
|
||||
"type": "@n8n/n8n-nodes-langchain.chainLlm",
|
||||
"position": [
|
||||
2420,
|
||||
320
|
||||
],
|
||||
"parameters": {
|
||||
"text": "=Given the following invoice in the <invoice> xml tags, extract the following information as listed below.\nIf you cannot the information for a specific item, then leave blank and skip to the next. \n\n* Invoice date\n* invoice number\n* Purchase order number\n* Supplier name\n* Supplier address\n* Supplier VAT identification number\n* Customer name\n* Customer address\n* Customer VAT identification number\n* Shipping addresses\n* Line items, including a description of the goods or services rendered\n* Price with and without VAT\n* Total price\n\n<invoice>{{ $json.markdown }}</invoice>",
|
||||
"promptType": "define",
|
||||
"hasOutputParser": true
|
||||
},
|
||||
"typeVersion": 1.4
|
||||
},
|
||||
{
|
||||
"id": "3735a124-9fab-4400-8b94-8b5aa9f951fe",
|
||||
"name": "Should Process Email?",
|
||||
"type": "n8n-nodes-base.if",
|
||||
"position": [
|
||||
1340,
|
||||
400
|
||||
],
|
||||
"parameters": {
|
||||
"options": {},
|
||||
"conditions": {
|
||||
"options": {
|
||||
"leftValue": "",
|
||||
"caseSensitive": true,
|
||||
"typeValidation": "strict"
|
||||
},
|
||||
"combinator": "and",
|
||||
"conditions": [
|
||||
{
|
||||
"id": "e5649a2b-6e12-4cc4-8001-4639cc9cc2c2",
|
||||
"operator": {
|
||||
"name": "filter.operator.equals",
|
||||
"type": "string",
|
||||
"operation": "equals"
|
||||
},
|
||||
"leftValue": "={{ $input.item.binary.attachment_0.mimeType }}",
|
||||
"rightValue": "application/pdf"
|
||||
},
|
||||
{
|
||||
"id": "4c57ab9b-b11c-455a-a63d-daf48418b06e",
|
||||
"operator": {
|
||||
"type": "array",
|
||||
"operation": "notContains",
|
||||
"rightType": "any"
|
||||
},
|
||||
"leftValue": "={{ $json.labels }}",
|
||||
"rightValue": "invoice synced"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"typeVersion": 2
|
||||
},
|
||||
{
|
||||
"id": "12a23527-39f3-4f72-8691-3d5cf59f9909",
|
||||
"name": "Split Out Labels",
|
||||
"type": "n8n-nodes-base.splitOut",
|
||||
"position": [
|
||||
980,
|
||||
400
|
||||
],
|
||||
"parameters": {
|
||||
"options": {},
|
||||
"fieldToSplitOut": "labelIds"
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "88ff6e22-d3d3-403d-b0b2-2674487140a7",
|
||||
"name": "Get Labels Names",
|
||||
"type": "n8n-nodes-base.gmail",
|
||||
"position": [
|
||||
980,
|
||||
540
|
||||
],
|
||||
"parameters": {
|
||||
"labelId": "={{ $json.labelIds }}",
|
||||
"resource": "label",
|
||||
"operation": "get"
|
||||
},
|
||||
"credentials": {
|
||||
"gmailOAuth2": {
|
||||
"id": "Sf5Gfl9NiFTNXFWb",
|
||||
"name": "Gmail account"
|
||||
}
|
||||
},
|
||||
"typeVersion": 2.1
|
||||
},
|
||||
{
|
||||
"id": "88accb8e-6531-40be-8d35-1bba594149af",
|
||||
"name": "Combine Label Names",
|
||||
"type": "n8n-nodes-base.aggregate",
|
||||
"position": [
|
||||
980,
|
||||
680
|
||||
],
|
||||
"parameters": {
|
||||
"options": {},
|
||||
"fieldsToAggregate": {
|
||||
"fieldToAggregate": [
|
||||
{
|
||||
"renameField": true,
|
||||
"outputFieldName": "labels",
|
||||
"fieldToAggregate": "name"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "d233ff33-cabf-434e-876d-879693ecaf58",
|
||||
"name": "Email with Label Names",
|
||||
"type": "n8n-nodes-base.merge",
|
||||
"position": [
|
||||
1160,
|
||||
400
|
||||
],
|
||||
"parameters": {
|
||||
"mode": "combine",
|
||||
"options": {},
|
||||
"combinationMode": "multiplex"
|
||||
},
|
||||
"typeVersion": 2.1
|
||||
},
|
||||
{
|
||||
"id": "733fc285-e069-4e4e-b13e-dfc1c259ac12",
|
||||
"name": "Sticky Note6",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
2540,
|
||||
460
|
||||
],
|
||||
"parameters": {
|
||||
"width": 192.26896179623753,
|
||||
"height": 213.73043662572252,
|
||||
"content": "\n\n\n\n\n\n\n\n\n\n\n\n**Need more attributes?**\nChange it here!"
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "83aa6ed0-ce3b-48d7-aded-475c337ae86e",
|
||||
"name": "Sticky Note7",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
2880,
|
||||
300
|
||||
],
|
||||
"parameters": {
|
||||
"width": 258.29345180972877,
|
||||
"height": 397.0641952938746,
|
||||
"content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n🚨**Required**\n* Set Your Google Sheet URL here\n* Set the Name of your Sheet\n\n\n**Don't use GSheets?**\nSwap this for Excel, Airtable or a Database!"
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "720070f6-2d6c-45ef-80c2-e950862a002b",
|
||||
"name": "Sticky Note8",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
740,
|
||||
380
|
||||
],
|
||||
"parameters": {
|
||||
"width": 174.50671517518518,
|
||||
"height": 274.6295678979021,
|
||||
"content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n🚨**Required**\n* Change the email filters here!"
|
||||
},
|
||||
"typeVersion": 1
|
||||
}
|
||||
],
|
||||
"pinData": {},
|
||||
"connections": {
|
||||
"Map Output": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Append to Reconciliation Sheet",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"OpenAI Model": {
|
||||
"ai_languageModel": [
|
||||
[
|
||||
{
|
||||
"node": "Apply Data Extraction Rules",
|
||||
"type": "ai_languageModel",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Is Job Ready?": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Get Parsed Invoice Data",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
null,
|
||||
null,
|
||||
[
|
||||
{
|
||||
"node": "Wait to stay within service limits",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Get Labels Names": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Combine Label Names",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Split Out Labels": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Get Labels Names",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Receiving Invoices": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Split Out Labels",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
},
|
||||
{
|
||||
"node": "Email with Label Names",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Combine Label Names": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Email with Label Names",
|
||||
"type": "main",
|
||||
"index": 1
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Upload to LlamaParse": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Get Processing Status",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Get Processing Status": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Is Job Ready?",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Should Process Email?": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Upload to LlamaParse",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Email with Label Names": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Should Process Email?",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Get Parsed Invoice Data": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Apply Data Extraction Rules",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Structured Output Parser": {
|
||||
"ai_outputParser": [
|
||||
[
|
||||
{
|
||||
"node": "Apply Data Extraction Rules",
|
||||
"type": "ai_outputParser",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Apply Data Extraction Rules": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Map Output",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Append to Reconciliation Sheet": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Add \"invoice synced\" Label",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Wait to stay within service limits": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Get Processing Status",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,697 +0,0 @@
|
||||
{
|
||||
"meta": {
|
||||
"instanceId": "03e9d14e9196363fe7191ce21dc0bb17387a6e755dcc9acc4f5904752919dca8"
|
||||
},
|
||||
"nodes": [
|
||||
{
|
||||
"id": "adfda9cb-1d77-4c54-b3ea-e7bf438a48af",
|
||||
"name": "Parse Webhook",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"position": [
|
||||
760,
|
||||
640
|
||||
],
|
||||
"parameters": {
|
||||
"options": {},
|
||||
"assignments": {
|
||||
"assignments": [
|
||||
{
|
||||
"id": "e63f9299-a19d-4ba1-93b0-59f458769fb2",
|
||||
"name": "response",
|
||||
"type": "object",
|
||||
"value": "={{ $json.body.payload }}"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"typeVersion": 3.3
|
||||
},
|
||||
{
|
||||
"id": "b3e0e490-18e0-44b5-a960-0fdbf8422515",
|
||||
"name": "Qualys Create Report",
|
||||
"type": "n8n-nodes-base.executeWorkflow",
|
||||
"position": [
|
||||
1720,
|
||||
1740
|
||||
],
|
||||
"parameters": {
|
||||
"options": {},
|
||||
"workflowId": "icSLX102kSS9zNdK"
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "80ae074b-bda5-4638-b46f-246a1b9530ae",
|
||||
"name": "Required Report Variables",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"position": [
|
||||
1520,
|
||||
1740
|
||||
],
|
||||
"parameters": {
|
||||
"options": {},
|
||||
"assignments": {
|
||||
"assignments": [
|
||||
{
|
||||
"id": "47cd1502-3039-4661-a6b1-e20a74056550",
|
||||
"name": "report_title",
|
||||
"type": "string",
|
||||
"value": "={{ $json.response.view.state.values.report_title.report_title_input.value }}"
|
||||
},
|
||||
{
|
||||
"id": "6a8a0cbf-bf3e-4702-956e-a35966d8b9c5",
|
||||
"name": "base_url",
|
||||
"type": "string",
|
||||
"value": "https://qualysapi.qg3.apps.qualys.com"
|
||||
},
|
||||
{
|
||||
"id": "9a15f4db-f006-4ad8-a2c0-4002dd3e2655",
|
||||
"name": "output_format",
|
||||
"type": "string",
|
||||
"value": "={{ $json.response.view.state.values.output_format.output_format_select.selected_option.value }}"
|
||||
},
|
||||
{
|
||||
"id": "13978e05-7e7f-42e9-8645-d28803db8cc9",
|
||||
"name": "template_name",
|
||||
"type": "string",
|
||||
"value": "={{ $json.response.view.state.values.report_template.report_template_select.selected_option.text.text }}"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"typeVersion": 3.3
|
||||
},
|
||||
{
|
||||
"id": "b596da86-02c7-4d8e-a267-88933f47ae0c",
|
||||
"name": "Qualys Start Vulnerability Scan",
|
||||
"type": "n8n-nodes-base.executeWorkflow",
|
||||
"position": [
|
||||
1720,
|
||||
1540
|
||||
],
|
||||
"parameters": {
|
||||
"options": {},
|
||||
"workflowId": "pYPh5FlGZgb36xZO"
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "61e39516-6558-46ce-a300-b4cbade7a6f6",
|
||||
"name": "Scan Report Task Modal",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"position": [
|
||||
1620,
|
||||
720
|
||||
],
|
||||
"parameters": {
|
||||
"url": "https://slack.com/api/views.open",
|
||||
"method": "POST",
|
||||
"options": {},
|
||||
"jsonBody": "= {\n \"trigger_id\": \"{{ $('Parse Webhook').item.json['response']['trigger_id'] }}\",\n \"external_id\": \"Scan Report Generator\",\n \"view\": {\n\t\"title\": {\n\t\t\"type\": \"plain_text\",\n\t\t\"text\": \"Scan Report Generator\",\n\t\t\"emoji\": true\n\t},\n\t\"submit\": {\n\t\t\"type\": \"plain_text\",\n\t\t\"text\": \"Generate Report\",\n\t\t\"emoji\": true\n\t},\n\t\"type\": \"modal\",\n\t\"close\": {\n\t\t\"type\": \"plain_text\",\n\t\t\"text\": \"Cancel\",\n\t\t\"emoji\": true\n\t},\n\t\"blocks\": [\n\t\t{\n\t\t\t\"type\": \"image\",\n\t\t\t\"image_url\": \"https://upload.wikimedia.org/wikipedia/commons/thumb/2/26/Logo-Qualys.svg/300px-Logo-Qualys.svg.png\",\n\t\t\t\"alt_text\": \"Qualys Logo\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"section\",\n\t\t\t\"text\": {\n\t\t\t\t\"type\": \"mrkdwn\",\n\t\t\t\t\"text\": \"Select a template and generate a detailed scan report based on the results of your previous scans.\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"type\": \"input\",\n\t\t\t\"block_id\": \"report_template\",\n\t\t\t\"element\": {\n\t\t\t\t\"type\": \"external_select\",\n\t\t\t\t\"placeholder\": {\n\t\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\t\"text\": \"Select a report template\",\n\t\t\t\t\t\"emoji\": true\n\t\t\t\t},\n\t\t\t\t\"action_id\": \"report_template_select\"\n\t\t\t},\n\t\t\t\"label\": {\n\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\"text\": \"Report Template\",\n\t\t\t\t\"emoji\": true\n\t\t\t},\n\t\t\t\"hint\": {\n\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\"text\": \"Choose a report template from your Qualys account to structure the output.\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"type\": \"input\",\n\t\t\t\"block_id\": \"report_title\",\n\t\t\t\"element\": {\n\t\t\t\t\"type\": \"plain_text_input\",\n\t\t\t\t\"action_id\": \"report_title_input\",\n\t\t\t\t\"placeholder\": {\n\t\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\t\"text\": \"Enter a custom title for the report\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"label\": {\n\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\"text\": \"Report Title\",\n\t\t\t\t\"emoji\": true\n\t\t\t},\n\t\t\t\"hint\": {\n\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\"text\": \"Provide a descriptive title for your report. This title will be used in the report header.\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"type\": \"input\",\n\t\t\t\"block_id\": \"output_format\",\n\t\t\t\"element\": {\n\t\t\t\t\"type\": \"static_select\",\n\t\t\t\t\"placeholder\": {\n\t\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\t\"text\": \"Select output format\",\n\t\t\t\t\t\"emoji\": true\n\t\t\t\t},\n\t\t\t\t\"options\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"text\": {\n\t\t\t\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\t\t\t\"text\": \"PDF\",\n\t\t\t\t\t\t\t\"emoji\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"value\": \"pdf\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"text\": {\n\t\t\t\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\t\t\t\"text\": \"HTML\",\n\t\t\t\t\t\t\t\"emoji\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"value\": \"html\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"text\": {\n\t\t\t\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\t\t\t\"text\": \"CSV\",\n\t\t\t\t\t\t\t\"emoji\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"value\": \"csv\"\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\t\"action_id\": \"output_format_select\"\n\t\t\t},\n\t\t\t\"label\": {\n\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\"text\": \"Output Format\",\n\t\t\t\t\"emoji\": true\n\t\t\t},\n\t\t\t\"hint\": {\n\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\"text\": \"Choose the format in which you want the report to be generated.\"\n\t\t\t}\n\t\t}\n\t]\n}\n}",
|
||||
"sendBody": true,
|
||||
"jsonQuery": "{\n \"Content-type\": \"application/json\"\n}",
|
||||
"sendQuery": true,
|
||||
"specifyBody": "json",
|
||||
"specifyQuery": "json",
|
||||
"authentication": "predefinedCredentialType",
|
||||
"nodeCredentialType": "slackApi"
|
||||
},
|
||||
"credentials": {
|
||||
"slackApi": {
|
||||
"id": "DZJDes1ZtGpqClNk",
|
||||
"name": "Qualys Slack App"
|
||||
}
|
||||
},
|
||||
"typeVersion": 4.2
|
||||
},
|
||||
{
|
||||
"id": "29cf716c-9cd6-4bd9-a0f9-c75baca86cc1",
|
||||
"name": "Vuln Scan Modal",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"position": [
|
||||
1620,
|
||||
560
|
||||
],
|
||||
"parameters": {
|
||||
"url": "https://slack.com/api/views.open",
|
||||
"method": "POST",
|
||||
"options": {},
|
||||
"jsonBody": "= {\n \"trigger_id\": \"{{ $('Parse Webhook').item.json['response']['trigger_id'] }}\",\n \"external_id\": \"Scan Report Generator\",\n \"view\": {\n\t\"title\": {\n\t\t\"type\": \"plain_text\",\n\t\t\"text\": \"Vulnerability Scan\",\n\t\t\"emoji\": true\n\t},\n\t\"submit\": {\n\t\t\"type\": \"plain_text\",\n\t\t\"text\": \"Execute Scan\",\n\t\t\"emoji\": true\n\t},\n\t\"type\": \"modal\",\n\t\"close\": {\n\t\t\"type\": \"plain_text\",\n\t\t\"text\": \"Cancel\",\n\t\t\"emoji\": true\n\t},\n\t\"blocks\": [\n\t\t{\n\t\t\t\"type\": \"image\",\n\t\t\t\"image_url\": \"https://upload.wikimedia.org/wikipedia/commons/thumb/2/26/Logo-Qualys.svg/300px-Logo-Qualys.svg.png\",\n\t\t\t\"alt_text\": \"Qualys Logo\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"section\",\n\t\t\t\"text\": {\n\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\"text\": \"Initiate a network-wide scan to detect and assess security vulnerabilities.\",\n\t\t\t\t\"emoji\": true\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"type\": \"input\",\n\t\t\t\"block_id\": \"option_title\",\n\t\t\t\"element\": {\n\t\t\t\t\"type\": \"plain_text_input\",\n\t\t\t\t\"action_id\": \"text_input-action\",\n\t\t\t\t\"initial_value\": \"Initial Options\"\n\t\t\t},\n\t\t\t\"label\": {\n\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\"text\": \"Option Title\",\n\t\t\t\t\"emoji\": true\n\t\t\t},\n\t\t\t\"hint\": {\n\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\"text\": \"Specify the title of the option profile to use for the scan.\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"type\": \"input\",\n\t\t\t\"block_id\": \"scan_title\",\n\t\t\t\"element\": {\n\t\t\t\t\"type\": \"plain_text_input\",\n\t\t\t\t\"action_id\": \"text_input-action\",\n\t\t\t\t\"placeholder\": {\n\t\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\t\"text\": \"Enter your scan title\"\n\t\t\t\t},\n\t\t\t\t\"initial_value\": \"n8n Scan 1\"\n\t\t\t},\n\t\t\t\"label\": {\n\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\"text\": \"Scan Title\",\n\t\t\t\t\"emoji\": true\n\t\t\t},\n\t\t\t\"hint\": {\n\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\"text\": \"Provide a descriptive title for the scan. Up to 2000 characters.\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"type\": \"input\",\n\t\t\t\"block_id\": \"asset_groups\",\n\t\t\t\"element\": {\n\t\t\t\t\"type\": \"plain_text_input\",\n\t\t\t\t\"action_id\": \"text_input-action\",\n\t\t\t\t\"placeholder\": {\n\t\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\t\"text\": \"Enter asset groups\"\n\t\t\t\t},\n\t\t\t\t\"initial_value\": \"Group1\"\n\t\t\t},\n\t\t\t\"label\": {\n\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\"text\": \"Asset Groups\",\n\t\t\t\t\"emoji\": true\n\t\t\t},\n\t\t\t\"hint\": {\n\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\"text\": \"Specify asset group titles for targeting. Multiple titles must be comma-separated.\"\n\t\t\t}\n\t\t}\n\t]\n}\n}",
|
||||
"sendBody": true,
|
||||
"jsonQuery": "{\n \"Content-type\": \"application/json\"\n}",
|
||||
"sendQuery": true,
|
||||
"specifyBody": "json",
|
||||
"specifyQuery": "json",
|
||||
"authentication": "predefinedCredentialType",
|
||||
"nodeCredentialType": "slackApi"
|
||||
},
|
||||
"credentials": {
|
||||
"slackApi": {
|
||||
"id": "DZJDes1ZtGpqClNk",
|
||||
"name": "Qualys Slack App"
|
||||
}
|
||||
},
|
||||
"typeVersion": 4.2
|
||||
},
|
||||
{
|
||||
"id": "a771704d-4191-4e80-b62f-81b41b047a87",
|
||||
"name": "Route Message",
|
||||
"type": "n8n-nodes-base.switch",
|
||||
"position": [
|
||||
940,
|
||||
640
|
||||
],
|
||||
"parameters": {
|
||||
"rules": {
|
||||
"values": [
|
||||
{
|
||||
"outputKey": "Vuln Scan Modal",
|
||||
"conditions": {
|
||||
"options": {
|
||||
"leftValue": "",
|
||||
"caseSensitive": true,
|
||||
"typeValidation": "strict"
|
||||
},
|
||||
"combinator": "and",
|
||||
"conditions": [
|
||||
{
|
||||
"operator": {
|
||||
"type": "string",
|
||||
"operation": "equals"
|
||||
},
|
||||
"leftValue": "={{ $json.response.callback_id }}",
|
||||
"rightValue": "trigger-qualys-vmscan"
|
||||
}
|
||||
]
|
||||
},
|
||||
"renameOutput": true
|
||||
},
|
||||
{
|
||||
"outputKey": "Scan Report Modal",
|
||||
"conditions": {
|
||||
"options": {
|
||||
"leftValue": "",
|
||||
"caseSensitive": true,
|
||||
"typeValidation": "strict"
|
||||
},
|
||||
"combinator": "and",
|
||||
"conditions": [
|
||||
{
|
||||
"id": "02868fd8-2577-4c6d-af5e-a1963cb2f786",
|
||||
"operator": {
|
||||
"name": "filter.operator.equals",
|
||||
"type": "string",
|
||||
"operation": "equals"
|
||||
},
|
||||
"leftValue": "={{ $json.response.callback_id }}",
|
||||
"rightValue": "qualys-scan-report"
|
||||
}
|
||||
]
|
||||
},
|
||||
"renameOutput": true
|
||||
},
|
||||
{
|
||||
"outputKey": "Process Submission",
|
||||
"conditions": {
|
||||
"options": {
|
||||
"leftValue": "",
|
||||
"caseSensitive": true,
|
||||
"typeValidation": "strict"
|
||||
},
|
||||
"combinator": "and",
|
||||
"conditions": [
|
||||
{
|
||||
"id": "c320c8b8-947b-433a-be82-d2aa96594808",
|
||||
"operator": {
|
||||
"name": "filter.operator.equals",
|
||||
"type": "string",
|
||||
"operation": "equals"
|
||||
},
|
||||
"leftValue": "={{ $json.response.type }}",
|
||||
"rightValue": "view_submission"
|
||||
}
|
||||
]
|
||||
},
|
||||
"renameOutput": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"fallbackOutput": "none"
|
||||
}
|
||||
},
|
||||
"typeVersion": 3
|
||||
},
|
||||
{
|
||||
"id": "c8346d57-762a-4bbd-8d2b-f13097cb063d",
|
||||
"name": "Required Scan Variables",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"position": [
|
||||
1520,
|
||||
1540
|
||||
],
|
||||
"parameters": {
|
||||
"options": {},
|
||||
"assignments": {
|
||||
"assignments": [
|
||||
{
|
||||
"id": "096ff32e-356e-4a85-aad2-01001d69dd46",
|
||||
"name": "platformurl",
|
||||
"type": "string",
|
||||
"value": "https://qualysapi.qg3.apps.qualys.com"
|
||||
},
|
||||
{
|
||||
"id": "070178a6-73b0-458b-8657-20ab4ff0485c",
|
||||
"name": "option_title",
|
||||
"type": "string",
|
||||
"value": "={{ $json.response.view.state.values.option_title['text_input-action'].value }}"
|
||||
},
|
||||
{
|
||||
"id": "3605424b-5bfc-44f0-b6e4-e0d6b1130b8e",
|
||||
"name": "scan_title",
|
||||
"type": "string",
|
||||
"value": "={{ $json.response.view.state.values.scan_title['text_input-action'].value }}"
|
||||
},
|
||||
{
|
||||
"id": "2320d966-b834-46fb-b674-be97cc08682e",
|
||||
"name": "asset_groups",
|
||||
"type": "string",
|
||||
"value": "={{ $json.response.view.state.values.asset_groups['text_input-action'].value }}"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"typeVersion": 3.3
|
||||
},
|
||||
{
|
||||
"id": "55589da9-50ce-4d55-a5ff-d62abdf65fa4",
|
||||
"name": "Route Submission",
|
||||
"type": "n8n-nodes-base.switch",
|
||||
"position": [
|
||||
1240,
|
||||
1140
|
||||
],
|
||||
"parameters": {
|
||||
"rules": {
|
||||
"values": [
|
||||
{
|
||||
"outputKey": "Vuln Scan",
|
||||
"conditions": {
|
||||
"options": {
|
||||
"leftValue": "",
|
||||
"caseSensitive": true,
|
||||
"typeValidation": "strict"
|
||||
},
|
||||
"combinator": "and",
|
||||
"conditions": [
|
||||
{
|
||||
"operator": {
|
||||
"type": "string",
|
||||
"operation": "equals"
|
||||
},
|
||||
"leftValue": "={{ $json.response.view.title.text }}",
|
||||
"rightValue": "Vulnerability Scan"
|
||||
}
|
||||
]
|
||||
},
|
||||
"renameOutput": true
|
||||
},
|
||||
{
|
||||
"outputKey": "Scan Report",
|
||||
"conditions": {
|
||||
"options": {
|
||||
"leftValue": "",
|
||||
"caseSensitive": true,
|
||||
"typeValidation": "strict"
|
||||
},
|
||||
"combinator": "and",
|
||||
"conditions": [
|
||||
{
|
||||
"id": "02868fd8-2577-4c6d-af5e-a1963cb2f786",
|
||||
"operator": {
|
||||
"name": "filter.operator.equals",
|
||||
"type": "string",
|
||||
"operation": "equals"
|
||||
},
|
||||
"leftValue": "={{ $json.response.view.title.text }}",
|
||||
"rightValue": "Scan Report Generator"
|
||||
}
|
||||
]
|
||||
},
|
||||
"renameOutput": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"fallbackOutput": "none"
|
||||
}
|
||||
},
|
||||
"typeVersion": 3
|
||||
},
|
||||
{
|
||||
"id": "d0fc264d-0c48-4aa6-aeab-ed605d96f35a",
|
||||
"name": "Sticky Note",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
428.3467548314237,
|
||||
270.6382978723399
|
||||
],
|
||||
"parameters": {
|
||||
"color": 7,
|
||||
"width": 466.8168310000617,
|
||||
"height": 567.6433222116042,
|
||||
"content": "\n## Events Webhook Trigger\nThe first node receives all messages from Slack API via Subscription Events API. You can find more information about setting up the subscription events API by [clicking here](https://api.slack.com/apis/connections/events-api). \n\nThe second node extracts the payload from slack into an object that n8n can understand. "
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "acb3fbdc-1fcb-4763-8529-ea2842607569",
|
||||
"name": "Sticky Note15",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
900,
|
||||
-32.762682645579616
|
||||
],
|
||||
"parameters": {
|
||||
"color": 7,
|
||||
"width": 566.0553219408072,
|
||||
"height": 1390.6748140207737,
|
||||
"content": "\n## Efficient Slack Interaction Handling with n8n\n\nThis section of the workflow is designed to efficiently manage and route messages and submissions from Slack based on specific triggers and conditions. When a Slack interaction occurs—such as a user triggering a vulnerability scan or generating a report through a modal—the workflow intelligently routes the message to the appropriate action:\n\n- **Dynamic Routing**: Uses conditions to determine the nature of the Slack interaction, whether it's a direct command to initiate a scan or a request to generate a report.\n- **Modal Management**: Differentiates actions based on modal titles and `callback_id`s, ensuring that each type of submission is processed according to its context.\n- **Streamlined Responses**: After routing, the workflow promptly handles the necessary responses or actions, including closing modal popups and responding to Slack with appropriate confirmation or data.\n\n**Purpose**: This mechanism ensures that all interactions within Slack are handled quickly and accurately, automating responses and actions in real-time to enhance user experience and workflow efficiency."
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "85f370e8-70d2-466e-8f44-45eaf04a0d95",
|
||||
"name": "Sticky Note11",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
1473.6255461332685,
|
||||
56.17183602125283
|
||||
],
|
||||
"parameters": {
|
||||
"color": 7,
|
||||
"width": 396.6025898621133,
|
||||
"height": 881.1659905894905,
|
||||
"content": "\n## Display Modal Popup\nThis section pops open a modal window that is later used to send data into TheHive. \n\nModals can be customized to perform all sorts of actions. And they are natively mobile! You can see a screenshot of the Slack Modals on the right. \n\nLearn more about them by [clicking here](https://api.slack.com/surfaces/modals)"
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "cae79c1c-47f8-41c0-b1d0-e284359b52a8",
|
||||
"name": "Sticky Note12",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
1480,
|
||||
960
|
||||
],
|
||||
"parameters": {
|
||||
"color": 7,
|
||||
"width": 390.82613196003143,
|
||||
"height": 950.1640646001949,
|
||||
"content": "\n## Modal Submission Payload\nThe data input into the Slack Modal makes its way into these set nodes that then pass that data into the Qualys Sub workflows that handle the heavy lifting. \n\n### Two Trigger Options\n- **Trigger a Vulnerability Scan** in the Slack UI which then sends a slack message to a channel of your choice summarizing and linking to the scan in slack\n- **Trigger report creation** in the Slack UI from the previously generated Vulnerability scan and upload a PDF copy of the report directly in a slack channel of your choice"
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "1017df8b-ff32-47aa-a4c2-a026e6597fa9",
|
||||
"name": "Close Modal Popup",
|
||||
"type": "n8n-nodes-base.respondToWebhook",
|
||||
"position": [
|
||||
1000,
|
||||
1140
|
||||
],
|
||||
"parameters": {
|
||||
"options": {
|
||||
"responseCode": 204
|
||||
},
|
||||
"respondWith": "noData"
|
||||
},
|
||||
"typeVersion": 1.1
|
||||
},
|
||||
{
|
||||
"id": "6b058f2a-2c0c-4326-aa42-08d840e306f7",
|
||||
"name": "Sticky Note8",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
-260,
|
||||
280
|
||||
],
|
||||
"parameters": {
|
||||
"width": 675.1724774900403,
|
||||
"height": 972.8853473866498,
|
||||
"content": "\n## Enhance Security Operations with the Qualys Slack Shortcut Bot!\n\nOur **Qualys Slack Shortcut Bot** is strategically designed to facilitate immediate security operations directly from Slack. This powerful tool allows users to initiate vulnerability scans and generate detailed reports through simple Slack interactions, streamlining the process of managing security assessments.\n\n**Workflow Highlights:**\n- **Interactive Modals**: Utilizes Slack modals to gather user inputs for scan configurations and report generation, providing a user-friendly interface for complex operations.\n- **Dynamic Workflow Execution**: Integrates seamlessly with Qualys to execute vulnerability scans and create reports based on user-specified parameters.\n- **Real-Time Feedback**: Offers instant feedback within Slack, updating users about the status of their requests and delivering reports directly through Slack channels.\n\n\n**Operational Flow:**\n- **Parse Webhook Data**: Captures and parses incoming data from Slack to understand user commands accurately.\n- **Execute Actions**: Depending on the user's selection, the workflow triggers other sub-workflows like 'Qualys Start Vulnerability Scan' or 'Qualys Create Report' for detailed processing.\n- **Respond to Slack**: Ensures that every interaction is acknowledged, maintaining a smooth user experience by managing modal popups and sending appropriate responses.\n\n\n**Setup Instructions:**\n- Verify that Slack and Qualys API integrations are correctly configured for seamless interaction.\n- Customize the modal interfaces to align with your organization's operational protocols and security policies.\n- Test the workflow to ensure that it responds accurately to Slack commands and that the integration with Qualys is functioning as expected.\n\n\n**Need Assistance?**\n- Explore our [Documentation](https://docs.qualys.com) or get help from the [n8n Community](https://community.n8n.io) for more detailed guidance on setup and customization.\n\nDeploy this bot within your Slack environment to significantly enhance the efficiency and responsiveness of your security operations, enabling proactive management of vulnerabilities and streamlined reporting."
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "63b537e8-50c9-479d-96a4-54e621689a23",
|
||||
"name": "Webhook",
|
||||
"type": "n8n-nodes-base.webhook",
|
||||
"position": [
|
||||
520,
|
||||
640
|
||||
],
|
||||
"webhookId": "4f86c00d-ceb4-4890-84c5-850f8e5dec05",
|
||||
"parameters": {
|
||||
"path": "4f86c00d-ceb4-4890-84c5-850f8e5dec05",
|
||||
"options": {},
|
||||
"httpMethod": "POST",
|
||||
"responseMode": "responseNode"
|
||||
},
|
||||
"typeVersion": 2
|
||||
},
|
||||
{
|
||||
"id": "13500444-f2ff-4b77-8f41-8ac52d067ec7",
|
||||
"name": "Respond to Slack Webhook - Vulnerability",
|
||||
"type": "n8n-nodes-base.respondToWebhook",
|
||||
"position": [
|
||||
1280,
|
||||
560
|
||||
],
|
||||
"parameters": {
|
||||
"options": {},
|
||||
"respondWith": "noData"
|
||||
},
|
||||
"typeVersion": 1.1
|
||||
},
|
||||
{
|
||||
"id": "e64cedf0-948c-43c8-a62c-d0ec2916f3b6",
|
||||
"name": "Respond to Slack Webhook - Report",
|
||||
"type": "n8n-nodes-base.respondToWebhook",
|
||||
"position": [
|
||||
1280,
|
||||
720
|
||||
],
|
||||
"parameters": {
|
||||
"options": {
|
||||
"responseCode": 200
|
||||
},
|
||||
"respondWith": "noData"
|
||||
},
|
||||
"typeVersion": 1.1
|
||||
},
|
||||
{
|
||||
"id": "d2e53f7b-090a-4330-949d-d66ac0e5849c",
|
||||
"name": "Sticky Note1",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
1494.8207799250774,
|
||||
1400
|
||||
],
|
||||
"parameters": {
|
||||
"color": 5,
|
||||
"width": 361.46312518523973,
|
||||
"height": 113.6416448104651,
|
||||
"content": "### 🙋 Remember to update your Slack Channels\nDon't forget to update the Slack Channels in the Slack nodes in these two subworkflows. \n"
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "2731f910-288f-497a-a71d-d840a63b2930",
|
||||
"name": "Sticky Note2",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
1480,
|
||||
400
|
||||
],
|
||||
"parameters": {
|
||||
"color": 5,
|
||||
"width": 376.26546828439086,
|
||||
"height": 113.6416448104651,
|
||||
"content": "### 🙋 Don't forget your slack credentials!\nThankfully n8n makes it easy, as long as you've added credentials to a normal slack node, these http nodes are a snap to change via the drop down. "
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "72105959-ee9b-4ce6-a7f8-0f5f112c14d2",
|
||||
"name": "Sticky Note3",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
1880,
|
||||
500
|
||||
],
|
||||
"parameters": {
|
||||
"color": 5,
|
||||
"width": 532.5097590794944,
|
||||
"height": 671.013686767174,
|
||||
"content": ""
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "49b8ce63-cefd-483a-b802-03e3500d807b",
|
||||
"name": "Sticky Note4",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
1880,
|
||||
-200
|
||||
],
|
||||
"parameters": {
|
||||
"color": 5,
|
||||
"width": 535.8333316661616,
|
||||
"height": 658.907292269235,
|
||||
"content": ""
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "3ec8c799-d5a5-4134-891a-59adb3e68e23",
|
||||
"name": "Sticky Note5",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
280,
|
||||
-158.042446016207
|
||||
],
|
||||
"parameters": {
|
||||
"color": 5,
|
||||
"width": 596.6847639718076,
|
||||
"height": 422.00743613240917,
|
||||
"content": "\n### 🤖 Triggering this workflow is as easy as typing a backslash in Slack"
|
||||
},
|
||||
"typeVersion": 1
|
||||
}
|
||||
],
|
||||
"pinData": {},
|
||||
"connections": {
|
||||
"Webhook": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Parse Webhook",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Parse Webhook": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Route Message",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Route Message": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Respond to Slack Webhook - Vulnerability",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"node": "Respond to Slack Webhook - Report",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"node": "Close Modal Popup",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Route Submission": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Required Scan Variables",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"node": "Required Report Variables",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Close Modal Popup": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Route Submission",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Required Scan Variables": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Qualys Start Vulnerability Scan",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Required Report Variables": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Qualys Create Report",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Respond to Slack Webhook - Report": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Scan Report Task Modal",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Respond to Slack Webhook - Vulnerability": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Vuln Scan Modal",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,752 +0,0 @@
|
||||
{
|
||||
"nodes": [
|
||||
{
|
||||
"id": "82fd6023-2cc3-416e-83b7-fda24d07d77a",
|
||||
"name": "Issues to List",
|
||||
"type": "n8n-nodes-base.splitOut",
|
||||
"position": [
|
||||
40,
|
||||
-100
|
||||
],
|
||||
"parameters": {
|
||||
"options": {},
|
||||
"fieldToSplitOut": "data.issues.nodes"
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "9cc77786-e14f-47c6-a3cf-60c2830612e6",
|
||||
"name": "OpenAI Chat Model",
|
||||
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
|
||||
"position": [
|
||||
360,
|
||||
80
|
||||
],
|
||||
"parameters": {
|
||||
"options": {}
|
||||
},
|
||||
"credentials": {
|
||||
"openAiApi": {
|
||||
"id": "8gccIjcuf3gvaoEr",
|
||||
"name": "OpenAi account"
|
||||
}
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "821d4a60-81a4-4915-9c13-3d978cc0114b",
|
||||
"name": "Combine Sentiment Analysis",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"position": [
|
||||
700,
|
||||
-80
|
||||
],
|
||||
"parameters": {
|
||||
"mode": "raw",
|
||||
"options": {},
|
||||
"jsonOutput": "={{\n{\n ...$('Issues to List').item.json,\n ...$json.output\n}\n}}"
|
||||
},
|
||||
"typeVersion": 3.4
|
||||
},
|
||||
{
|
||||
"id": "fe6560f6-2e1b-4442-a2af-bd5a1623f213",
|
||||
"name": "Sentiment over Issue Comments",
|
||||
"type": "@n8n/n8n-nodes-langchain.informationExtractor",
|
||||
"position": [
|
||||
360,
|
||||
-80
|
||||
],
|
||||
"parameters": {
|
||||
"text": "={{\n$json.comments.nodes.map(node => [\n `${node.user.displayName} commented on ${node.createdAt}:`,\n node.body\n].join('\\n')).join('---\\n')\n}}",
|
||||
"options": {},
|
||||
"attributes": {
|
||||
"attributes": [
|
||||
{
|
||||
"name": "sentiment",
|
||||
"required": true,
|
||||
"description": "One of positive, negative or neutral"
|
||||
},
|
||||
{
|
||||
"name": "sentimentSummary",
|
||||
"description": "Describe the sentiment of the conversation"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "4fd0345d-e5bf-426d-8403-e2217e19bbea",
|
||||
"name": "Copy of Issue",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"position": [
|
||||
1200,
|
||||
-60
|
||||
],
|
||||
"parameters": {
|
||||
"mode": "raw",
|
||||
"options": {},
|
||||
"jsonOutput": "={{ $json }}"
|
||||
},
|
||||
"typeVersion": 3.4
|
||||
},
|
||||
{
|
||||
"id": "6d103d67-451e-4780-8f52-f4dba4b42860",
|
||||
"name": "For Each Issue...",
|
||||
"type": "n8n-nodes-base.splitInBatches",
|
||||
"position": [
|
||||
1020,
|
||||
-60
|
||||
],
|
||||
"parameters": {
|
||||
"options": {}
|
||||
},
|
||||
"typeVersion": 3
|
||||
},
|
||||
{
|
||||
"id": "032702d9-27d8-4735-b978-20b55bc1a74f",
|
||||
"name": "Get Existing Sentiment",
|
||||
"type": "n8n-nodes-base.airtable",
|
||||
"position": [
|
||||
1380,
|
||||
-60
|
||||
],
|
||||
"parameters": {
|
||||
"base": {
|
||||
"__rl": true,
|
||||
"mode": "list",
|
||||
"value": "appViDaeaFw4qv9La",
|
||||
"cachedResultUrl": "https://airtable.com/appViDaeaFw4qv9La",
|
||||
"cachedResultName": "Sentiment Analysis over Issue Comments"
|
||||
},
|
||||
"table": {
|
||||
"__rl": true,
|
||||
"mode": "list",
|
||||
"value": "tblhO0sfRhKP6ibS8",
|
||||
"cachedResultUrl": "https://airtable.com/appViDaeaFw4qv9La/tblhO0sfRhKP6ibS8",
|
||||
"cachedResultName": "Table 1"
|
||||
},
|
||||
"options": {
|
||||
"fields": [
|
||||
"Issue ID",
|
||||
"Current Sentiment"
|
||||
]
|
||||
},
|
||||
"operation": "search",
|
||||
"filterByFormula": "={Issue ID} = '{{ $json.identifier || 'XYZ' }}'"
|
||||
},
|
||||
"credentials": {
|
||||
"airtableTokenApi": {
|
||||
"id": "Und0frCQ6SNVX3VV",
|
||||
"name": "Airtable Personal Access Token account"
|
||||
}
|
||||
},
|
||||
"typeVersion": 2.1,
|
||||
"alwaysOutputData": true
|
||||
},
|
||||
{
|
||||
"id": "f2ded6fa-8b0f-4a34-868c-13c19f725c98",
|
||||
"name": "Update Row",
|
||||
"type": "n8n-nodes-base.airtable",
|
||||
"position": [
|
||||
1560,
|
||||
-60
|
||||
],
|
||||
"parameters": {
|
||||
"base": {
|
||||
"__rl": true,
|
||||
"mode": "list",
|
||||
"value": "appViDaeaFw4qv9La",
|
||||
"cachedResultUrl": "https://airtable.com/appViDaeaFw4qv9La",
|
||||
"cachedResultName": "Sentiment Analysis over Issue Comments"
|
||||
},
|
||||
"table": {
|
||||
"__rl": true,
|
||||
"mode": "list",
|
||||
"value": "tblhO0sfRhKP6ibS8",
|
||||
"cachedResultUrl": "https://airtable.com/appViDaeaFw4qv9La/tblhO0sfRhKP6ibS8",
|
||||
"cachedResultName": "Table 1"
|
||||
},
|
||||
"columns": {
|
||||
"value": {
|
||||
"Summary": "={{ $('Copy of Issue').item.json.sentimentSummary || '' }}",
|
||||
"Assigned": "={{ $('Copy of Issue').item.json.assignee.name }}",
|
||||
"Issue ID": "={{ $('Copy of Issue').item.json.identifier }}",
|
||||
"Issue Title": "={{ $('Copy of Issue').item.json.title }}",
|
||||
"Issue Created": "={{ $('Copy of Issue').item.json.createdAt }}",
|
||||
"Issue Updated": "={{ $('Copy of Issue').item.json.updatedAt }}",
|
||||
"Current Sentiment": "={{ $('Copy of Issue').item.json.sentiment.toSentenceCase() }}",
|
||||
"Previous Sentiment": "={{ !$json.isEmpty() ? $json['Current Sentiment'] : 'N/A' }}"
|
||||
},
|
||||
"schema": [
|
||||
{
|
||||
"id": "id",
|
||||
"type": "string",
|
||||
"display": true,
|
||||
"removed": true,
|
||||
"readOnly": true,
|
||||
"required": false,
|
||||
"displayName": "id",
|
||||
"defaultMatch": true
|
||||
},
|
||||
{
|
||||
"id": "Issue ID",
|
||||
"type": "string",
|
||||
"display": true,
|
||||
"removed": false,
|
||||
"readOnly": false,
|
||||
"required": false,
|
||||
"displayName": "Issue ID",
|
||||
"defaultMatch": false,
|
||||
"canBeUsedToMatch": true
|
||||
},
|
||||
{
|
||||
"id": "Previous Sentiment",
|
||||
"type": "options",
|
||||
"display": true,
|
||||
"options": [
|
||||
{
|
||||
"name": "Positive",
|
||||
"value": "Positive"
|
||||
},
|
||||
{
|
||||
"name": "Negative",
|
||||
"value": "Negative"
|
||||
},
|
||||
{
|
||||
"name": "Neutral",
|
||||
"value": "Neutral"
|
||||
},
|
||||
{
|
||||
"name": "N/A",
|
||||
"value": "N/A"
|
||||
}
|
||||
],
|
||||
"removed": false,
|
||||
"readOnly": false,
|
||||
"required": false,
|
||||
"displayName": "Previous Sentiment",
|
||||
"defaultMatch": false,
|
||||
"canBeUsedToMatch": true
|
||||
},
|
||||
{
|
||||
"id": "Current Sentiment",
|
||||
"type": "options",
|
||||
"display": true,
|
||||
"options": [
|
||||
{
|
||||
"name": "Positive",
|
||||
"value": "Positive"
|
||||
},
|
||||
{
|
||||
"name": "Negative",
|
||||
"value": "Negative"
|
||||
},
|
||||
{
|
||||
"name": "Neutral",
|
||||
"value": "Neutral"
|
||||
},
|
||||
{
|
||||
"name": "N/A",
|
||||
"value": "N/A"
|
||||
}
|
||||
],
|
||||
"removed": false,
|
||||
"readOnly": false,
|
||||
"required": false,
|
||||
"displayName": "Current Sentiment",
|
||||
"defaultMatch": false,
|
||||
"canBeUsedToMatch": true
|
||||
},
|
||||
{
|
||||
"id": "Summary",
|
||||
"type": "string",
|
||||
"display": true,
|
||||
"removed": false,
|
||||
"readOnly": false,
|
||||
"required": false,
|
||||
"displayName": "Summary",
|
||||
"defaultMatch": false,
|
||||
"canBeUsedToMatch": true
|
||||
},
|
||||
{
|
||||
"id": "Issue Title",
|
||||
"type": "string",
|
||||
"display": true,
|
||||
"removed": false,
|
||||
"readOnly": false,
|
||||
"required": false,
|
||||
"displayName": "Issue Title",
|
||||
"defaultMatch": false,
|
||||
"canBeUsedToMatch": true
|
||||
},
|
||||
{
|
||||
"id": "Issue Created",
|
||||
"type": "dateTime",
|
||||
"display": true,
|
||||
"removed": false,
|
||||
"readOnly": false,
|
||||
"required": false,
|
||||
"displayName": "Issue Created",
|
||||
"defaultMatch": false,
|
||||
"canBeUsedToMatch": true
|
||||
},
|
||||
{
|
||||
"id": "Issue Updated",
|
||||
"type": "dateTime",
|
||||
"display": true,
|
||||
"removed": false,
|
||||
"readOnly": false,
|
||||
"required": false,
|
||||
"displayName": "Issue Updated",
|
||||
"defaultMatch": false,
|
||||
"canBeUsedToMatch": true
|
||||
},
|
||||
{
|
||||
"id": "Assigned",
|
||||
"type": "string",
|
||||
"display": true,
|
||||
"removed": false,
|
||||
"readOnly": false,
|
||||
"required": false,
|
||||
"displayName": "Assigned",
|
||||
"defaultMatch": false,
|
||||
"canBeUsedToMatch": true
|
||||
},
|
||||
{
|
||||
"id": "Created",
|
||||
"type": "string",
|
||||
"display": true,
|
||||
"removed": true,
|
||||
"readOnly": true,
|
||||
"required": false,
|
||||
"displayName": "Created",
|
||||
"defaultMatch": false,
|
||||
"canBeUsedToMatch": true
|
||||
},
|
||||
{
|
||||
"id": "Last Modified",
|
||||
"type": "string",
|
||||
"display": true,
|
||||
"removed": true,
|
||||
"readOnly": true,
|
||||
"required": false,
|
||||
"displayName": "Last Modified",
|
||||
"defaultMatch": false,
|
||||
"canBeUsedToMatch": true
|
||||
}
|
||||
],
|
||||
"mappingMode": "defineBelow",
|
||||
"matchingColumns": [
|
||||
"Issue ID"
|
||||
]
|
||||
},
|
||||
"options": {},
|
||||
"operation": "upsert"
|
||||
},
|
||||
"credentials": {
|
||||
"airtableTokenApi": {
|
||||
"id": "Und0frCQ6SNVX3VV",
|
||||
"name": "Airtable Personal Access Token account"
|
||||
}
|
||||
},
|
||||
"typeVersion": 2.1
|
||||
},
|
||||
{
|
||||
"id": "e6fb0b8f-2469-4b66-b9e2-f4f3c0a613af",
|
||||
"name": "Airtable Trigger",
|
||||
"type": "n8n-nodes-base.airtableTrigger",
|
||||
"position": [
|
||||
1900,
|
||||
-40
|
||||
],
|
||||
"parameters": {
|
||||
"baseId": {
|
||||
"__rl": true,
|
||||
"mode": "id",
|
||||
"value": "appViDaeaFw4qv9La"
|
||||
},
|
||||
"tableId": {
|
||||
"__rl": true,
|
||||
"mode": "id",
|
||||
"value": "tblhO0sfRhKP6ibS8"
|
||||
},
|
||||
"pollTimes": {
|
||||
"item": [
|
||||
{
|
||||
"mode": "everyHour"
|
||||
}
|
||||
]
|
||||
},
|
||||
"triggerField": "Current Sentiment",
|
||||
"authentication": "airtableTokenApi",
|
||||
"additionalFields": {}
|
||||
},
|
||||
"credentials": {
|
||||
"airtableTokenApi": {
|
||||
"id": "Und0frCQ6SNVX3VV",
|
||||
"name": "Airtable Personal Access Token account"
|
||||
}
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "669762c4-860b-43ad-b677-72d4564e1c29",
|
||||
"name": "Sentiment Transition",
|
||||
"type": "n8n-nodes-base.switch",
|
||||
"position": [
|
||||
2080,
|
||||
-40
|
||||
],
|
||||
"parameters": {
|
||||
"rules": {
|
||||
"values": [
|
||||
{
|
||||
"outputKey": "NON-NEGATIVE to NEGATIVE",
|
||||
"conditions": {
|
||||
"options": {
|
||||
"version": 2,
|
||||
"leftValue": "",
|
||||
"caseSensitive": true,
|
||||
"typeValidation": "strict"
|
||||
},
|
||||
"combinator": "and",
|
||||
"conditions": [
|
||||
{
|
||||
"operator": {
|
||||
"type": "boolean",
|
||||
"operation": "true",
|
||||
"singleValue": true
|
||||
},
|
||||
"leftValue": "={{ $json.fields[\"Previous Sentiment\"] !== 'Negative' && $json.fields[\"Current Sentiment\"] === 'Negative' }}",
|
||||
"rightValue": ""
|
||||
}
|
||||
]
|
||||
},
|
||||
"renameOutput": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"fallbackOutput": "none"
|
||||
}
|
||||
},
|
||||
"typeVersion": 3.2
|
||||
},
|
||||
{
|
||||
"id": "2fbcfbea-3989-459b-8ca7-b65c130a479b",
|
||||
"name": "Fetch Active Linear Issues",
|
||||
"type": "n8n-nodes-base.graphql",
|
||||
"position": [
|
||||
-140,
|
||||
-100
|
||||
],
|
||||
"parameters": {
|
||||
"query": "=query (\n $filter: IssueFilter\n) {\n issues(\n filter: $filter\n ) {\n nodes {\n id\n identifier\n title\n description\n url\n createdAt\n updatedAt\n assignee {\n name\n }\n comments {\n nodes {\n id\n createdAt\n user {\n displayName\n }\n body\n }\n }\n }\n }\n}",
|
||||
"endpoint": "https://api.linear.app/graphql",
|
||||
"variables": "={{\n{\n \"filter\": {\n updatedAt: { gte: $now.minus(30, 'minutes').toISO() }\n }\n}\n}}",
|
||||
"requestFormat": "json",
|
||||
"authentication": "headerAuth"
|
||||
},
|
||||
"credentials": {
|
||||
"httpHeaderAuth": {
|
||||
"id": "XME2Ubkuy9hpPEM5",
|
||||
"name": "Linear.app (heightio)"
|
||||
}
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "aaf1c25e-c398-4715-88bf-bd98daafc10f",
|
||||
"name": "Schedule Trigger",
|
||||
"type": "n8n-nodes-base.scheduleTrigger",
|
||||
"position": [
|
||||
-340,
|
||||
-100
|
||||
],
|
||||
"parameters": {
|
||||
"rule": {
|
||||
"interval": [
|
||||
{
|
||||
"field": "minutes",
|
||||
"minutesInterval": 30
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"typeVersion": 1.2
|
||||
},
|
||||
{
|
||||
"id": "b3e2df39-90ce-4ebf-aa68-05499965ec30",
|
||||
"name": "Deduplicate Notifications",
|
||||
"type": "n8n-nodes-base.removeDuplicates",
|
||||
"position": [
|
||||
2280,
|
||||
-40
|
||||
],
|
||||
"parameters": {
|
||||
"options": {},
|
||||
"operation": "removeItemsSeenInPreviousExecutions",
|
||||
"dedupeValue": "={{ $json.fields[\"Issue ID\"] }}:{{ $json.fields['Last Modified'] }}"
|
||||
},
|
||||
"typeVersion": 2
|
||||
},
|
||||
{
|
||||
"id": "2a116475-32cd-4c9d-bfc1-3bd494f79a49",
|
||||
"name": "Report Issue Negative Transition",
|
||||
"type": "n8n-nodes-base.slack",
|
||||
"position": [
|
||||
2480,
|
||||
-40
|
||||
],
|
||||
"webhookId": "612f1001-3fcc-480b-a835-05f9e2d56a5f",
|
||||
"parameters": {
|
||||
"text": "={{ $('Deduplicate Notifications').all().length }} Issues have transitions to Negative Sentiment",
|
||||
"select": "channel",
|
||||
"blocksUi": "={{\n{\n \"blocks\": [\n {\n \"type\": \"section\",\n \"text\": {\n \"type\": \"mrkdwn\",\n \"text\": \":rotating_light: The following Issues transitioned to Negative Sentiment\"\n }\n },\n {\n \"type\": \"divider\"\n },\n ...($('Deduplicate Notifications').all().map(item => (\n {\n \"type\": \"section\",\n \"text\": {\n \"type\": \"mrkdwn\",\n \"text\": `*<https://linear.app/myOrg/issue/${$json.fields['Issue ID']}|${$json.fields['Issue ID']} ${$json.fields['Issue Title']}>*\\n${$json.fields.Summary}`\n }\n }\n )))\n ]\n}\n}}",
|
||||
"channelId": {
|
||||
"__rl": true,
|
||||
"mode": "list",
|
||||
"value": "C0749JVFERK",
|
||||
"cachedResultName": "n8n-tickets"
|
||||
},
|
||||
"messageType": "block",
|
||||
"otherOptions": {}
|
||||
},
|
||||
"credentials": {
|
||||
"slackApi": {
|
||||
"id": "VfK3js0YdqBdQLGP",
|
||||
"name": "Slack account"
|
||||
}
|
||||
},
|
||||
"executeOnce": true,
|
||||
"typeVersion": 2.3
|
||||
},
|
||||
{
|
||||
"id": "1f3d30b6-de31-45a8-a872-554c339f112f",
|
||||
"name": "Sticky Note",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
-420,
|
||||
-320
|
||||
],
|
||||
"parameters": {
|
||||
"color": 7,
|
||||
"width": 660,
|
||||
"height": 440,
|
||||
"content": "## 1. Continuously Monitor Active Linear Issues\n[Learn more about the GraphQL node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.graphql)\n\nTo keep up with the latest changes in our active Linear tickets, we'll need to use Linear's GraphQL endpoint because filtering is currently unavailable in the official Linear.app node.\n\nFor this demonstration, we'll check for updated tickets every 30mins."
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "9024512d-5cb9-4e9f-b6e1-495d1a32118a",
|
||||
"name": "Sticky Note1",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
260,
|
||||
-320
|
||||
],
|
||||
"parameters": {
|
||||
"color": 7,
|
||||
"width": 640,
|
||||
"height": 560,
|
||||
"content": "## 2. Sentiment Analysis on Current Issue Activity\n[Learn more about the Information Extractor node](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.information-extractor)\n\nWith our recently updated posts, we can use our AI to perform a quick sentiment analysis on the ongoing conversation to check the overall mood of the support issue. This is a great way to check how things are generally going in the support queue; positive should be normal but negative could indicate some uncomfortableness or even frustration."
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "233ebd6d-38cb-4f2d-84b5-29c97d30d77b",
|
||||
"name": "Sticky Note2",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
920,
|
||||
-320
|
||||
],
|
||||
"parameters": {
|
||||
"color": 7,
|
||||
"width": 840,
|
||||
"height": 560,
|
||||
"content": "## 3. Capture and Track Results in Airtable\n[Learn more about the Airtable node](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.airtable)\n\nNext, we can capture this analysis in our insights database as means for human review. When the issue is new, we can create a new row but if the issue exists, we will update it's existing row instead.\n\nWhen updating an existing row, we move its previous \"current sentiment\" value into the \"previous sentiment\" column and replace with our new current sentiment. This gives us a \"sentiment transition\" which will be useful in the next step.\n\nCheck out the Airtable here: https://airtable.com/appViDaeaFw4qv9La/shrq6HgeYzpW6uwXL"
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "a2229225-b580-43cb-b234-4f69cb5924fd",
|
||||
"name": "Sticky Note3",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
1800,
|
||||
-320
|
||||
],
|
||||
"parameters": {
|
||||
"color": 7,
|
||||
"width": 920,
|
||||
"height": 560,
|
||||
"content": "## 4. Get Notified when Sentiment becomes Negative\n[Learn more about the Slack node](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.slack/)\n\nA good use-case for tracking sentiment transitions could be to be alerted if ever an issue moves from a non-negative sentiment to a negative one. This could be a signal of issue handling troubles which may require attention before it escalates.\n\nIn this demonstration, we use the Airtable trigger to catch rows which have their sentiment column updated and check for the non-negative-to-negative sentiment transition using the switch node. For those matching rows, we combine add send a notification via slack. A cool trick is to use the \"remove duplication\" node to prevent repeat notifications for the same updates - here we combine the Linear issue key and the row's last modified date."
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "6f26769e-ec5d-46d0-ae0a-34148b24e6a2",
|
||||
"name": "Sticky Note4",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
-940,
|
||||
-720
|
||||
],
|
||||
"parameters": {
|
||||
"width": 480,
|
||||
"height": 840,
|
||||
"content": "## Try It Out!\n### This n8n template performs continous monitoring on Linear Issue conversations performing sentiment analysis and alerting when the sentiment becomes negative.\nThis is helpful to quickly identify difficult customer support situations early and prioritising them before they get out of hand.\n\n## How it works\n* A scheduled trigger is used to fetch recently updated issues in Linear using the GraphQL node.\n* Each issue's comments thread is passed into a simple Information Extractor node to identify the overall sentiment.\n* The resulting sentiment analysis combined with the some issue details are uploaded to Airtable for review.\n* When the template is re-run at a later date, each issue is re-analysed for sentiment\n* Each issue's new sentiment state is saved to the airtable whilst its previous state is moved to the \"previous sentiment\" column.\n* An Airtable trigger is used to watch for recently updated rows\n* Each matching Airtable row is filtered to check if it has a previous non-negative state but now has a negative state in its current sentiment.\n* The results are sent via notification to a team slack channel for priority.\n\n**Check out the sample Airtable here**: https://airtable.com/appViDaeaFw4qv9La/shrq6HgeYzpW6uwXL\n\n## How to use\n* Modify the GraphQL filter to fetch issues to a relevant issue type, team or person.\n* Update the Slack channel to ensure messages are sent to the correct location.\n\n### Need Help?\nJoin the [Discord](https://discord.com/invite/XPKeKXeB7d) or ask in the [Forum](https://community.n8n.io/)!\n\nHappy Hacking!"
|
||||
},
|
||||
"typeVersion": 1
|
||||
}
|
||||
],
|
||||
"pinData": {},
|
||||
"connections": {
|
||||
"Update Row": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "For Each Issue...",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Copy of Issue": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Get Existing Sentiment",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Issues to List": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Sentiment over Issue Comments",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Airtable Trigger": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Sentiment Transition",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Schedule Trigger": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Fetch Active Linear Issues",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"For Each Issue...": {
|
||||
"main": [
|
||||
[],
|
||||
[
|
||||
{
|
||||
"node": "Copy of Issue",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"OpenAI Chat Model": {
|
||||
"ai_languageModel": [
|
||||
[
|
||||
{
|
||||
"node": "Sentiment over Issue Comments",
|
||||
"type": "ai_languageModel",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Sentiment Transition": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Deduplicate Notifications",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Get Existing Sentiment": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Update Row",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Deduplicate Notifications": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Report Issue Negative Transition",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Combine Sentiment Analysis": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "For Each Issue...",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Fetch Active Linear Issues": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Issues to List",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Sentiment over Issue Comments": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Combine Sentiment Analysis",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,700 +0,0 @@
|
||||
{
|
||||
"meta": {
|
||||
"instanceId": "408f9fb9940c3cb18ffdef0e0150fe342d6e655c3a9fac21f0f644e8bedabcd9"
|
||||
},
|
||||
"nodes": [
|
||||
{
|
||||
"id": "77ee6494-4898-47dc-81d9-35daf6f0beea",
|
||||
"name": "WhatsApp Trigger",
|
||||
"type": "n8n-nodes-base.whatsAppTrigger",
|
||||
"position": [
|
||||
1360,
|
||||
-280
|
||||
],
|
||||
"webhookId": "aaa71f03-f7af-4d18-8d9a-0afb86f1b554",
|
||||
"parameters": {
|
||||
"updates": [
|
||||
"messages"
|
||||
]
|
||||
},
|
||||
"credentials": {
|
||||
"whatsAppTriggerApi": {
|
||||
"id": "H3uYNtpeczKMqtYm",
|
||||
"name": "WhatsApp OAuth account"
|
||||
}
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "57210e27-1f89-465a-98cc-43f890a4bf58",
|
||||
"name": "OpenAI Chat Model",
|
||||
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
|
||||
"position": [
|
||||
1960,
|
||||
-200
|
||||
],
|
||||
"parameters": {
|
||||
"model": "gpt-4o-2024-08-06",
|
||||
"options": {}
|
||||
},
|
||||
"credentials": {
|
||||
"openAiApi": {
|
||||
"id": "8gccIjcuf3gvaoEr",
|
||||
"name": "OpenAi account"
|
||||
}
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "e1053235-0ade-4e36-9ad2-8b29c78fced8",
|
||||
"name": "Window Buffer Memory",
|
||||
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
|
||||
"position": [
|
||||
2080,
|
||||
-200
|
||||
],
|
||||
"parameters": {
|
||||
"sessionKey": "=whatsapp-75-{{ $json.messages[0].from }}",
|
||||
"sessionIdType": "customKey"
|
||||
},
|
||||
"typeVersion": 1.2
|
||||
},
|
||||
{
|
||||
"id": "69f1b78b-7c93-4713-863a-27e04809996f",
|
||||
"name": "Vector Store Tool",
|
||||
"type": "@n8n/n8n-nodes-langchain.toolVectorStore",
|
||||
"position": [
|
||||
2200,
|
||||
-200
|
||||
],
|
||||
"parameters": {
|
||||
"name": "query_product_brochure",
|
||||
"description": "Call this tool to query the product brochure. Valid for the year 2024."
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "170e8f7d-7e14-48dd-9f80-5352cc411fc1",
|
||||
"name": "Embeddings OpenAI",
|
||||
"type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi",
|
||||
"position": [
|
||||
2200,
|
||||
80
|
||||
],
|
||||
"parameters": {
|
||||
"model": "text-embedding-3-small",
|
||||
"options": {}
|
||||
},
|
||||
"credentials": {
|
||||
"openAiApi": {
|
||||
"id": "8gccIjcuf3gvaoEr",
|
||||
"name": "OpenAi account"
|
||||
}
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "ee78320b-d407-49e8-b4b8-417582a44709",
|
||||
"name": "OpenAI Chat Model1",
|
||||
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
|
||||
"position": [
|
||||
2440,
|
||||
-60
|
||||
],
|
||||
"parameters": {
|
||||
"model": "gpt-4o-2024-08-06",
|
||||
"options": {}
|
||||
},
|
||||
"credentials": {
|
||||
"openAiApi": {
|
||||
"id": "8gccIjcuf3gvaoEr",
|
||||
"name": "OpenAi account"
|
||||
}
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "9dd89378-5acf-4ca6-8d84-e6e64254ed02",
|
||||
"name": "When clicking ‘Test workflow’",
|
||||
"type": "n8n-nodes-base.manualTrigger",
|
||||
"position": [
|
||||
0,
|
||||
-240
|
||||
],
|
||||
"parameters": {},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "e68fc137-1bcb-43f0-b597-3ae07f380c15",
|
||||
"name": "Embeddings OpenAI1",
|
||||
"type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi",
|
||||
"position": [
|
||||
760,
|
||||
-20
|
||||
],
|
||||
"parameters": {
|
||||
"model": "text-embedding-3-small",
|
||||
"options": {}
|
||||
},
|
||||
"credentials": {
|
||||
"openAiApi": {
|
||||
"id": "8gccIjcuf3gvaoEr",
|
||||
"name": "OpenAi account"
|
||||
}
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "2d31e92b-18d4-4f6b-8cdb-bed0056d50d7",
|
||||
"name": "Default Data Loader",
|
||||
"type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader",
|
||||
"position": [
|
||||
900,
|
||||
-20
|
||||
],
|
||||
"parameters": {
|
||||
"options": {},
|
||||
"jsonData": "={{ $('Extract from File').item.json.text }}",
|
||||
"jsonMode": "expressionData"
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "ca0c015e-fba2-4dca-b0fe-bac66681725a",
|
||||
"name": "Recursive Character Text Splitter",
|
||||
"type": "@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter",
|
||||
"position": [
|
||||
900,
|
||||
100
|
||||
],
|
||||
"parameters": {
|
||||
"options": {},
|
||||
"chunkSize": 2000,
|
||||
"chunkOverlap": {}
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "63abb6b2-b955-4e65-9c63-3211dca65613",
|
||||
"name": "Extract from File",
|
||||
"type": "n8n-nodes-base.extractFromFile",
|
||||
"position": [
|
||||
360,
|
||||
-240
|
||||
],
|
||||
"parameters": {
|
||||
"options": {},
|
||||
"operation": "pdf"
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "be2add9c-3670-4196-8c38-82742bf4f283",
|
||||
"name": "get Product Brochure",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"position": [
|
||||
180,
|
||||
-240
|
||||
],
|
||||
"parameters": {
|
||||
"url": "https://usa.yamaha.com/files/download/brochure/1/1474881/Yamaha-Powered-Loudspeakers-brochure-2024-en-web.pdf",
|
||||
"options": {}
|
||||
},
|
||||
"typeVersion": 4.2
|
||||
},
|
||||
{
|
||||
"id": "1ae5a311-36d7-4454-ab14-6788d1331780",
|
||||
"name": "Reply To User",
|
||||
"type": "n8n-nodes-base.whatsApp",
|
||||
"position": [
|
||||
2820,
|
||||
-280
|
||||
],
|
||||
"parameters": {
|
||||
"textBody": "={{ $json.output }}",
|
||||
"operation": "send",
|
||||
"phoneNumberId": "477115632141067",
|
||||
"requestOptions": {},
|
||||
"additionalFields": {
|
||||
"previewUrl": false
|
||||
},
|
||||
"recipientPhoneNumber": "={{ $('WhatsApp Trigger').item.json.messages[0].from }}"
|
||||
},
|
||||
"credentials": {
|
||||
"whatsAppApi": {
|
||||
"id": "9SFJPeqrpChOkAmw",
|
||||
"name": "WhatsApp account"
|
||||
}
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "b6efba81-18b0-4378-bb91-51f39ca57f3e",
|
||||
"name": "Reply To User1",
|
||||
"type": "n8n-nodes-base.whatsApp",
|
||||
"position": [
|
||||
1760,
|
||||
80
|
||||
],
|
||||
"parameters": {
|
||||
"textBody": "=I'm unable to process non-text messages. Please send only text messages. Thanks!",
|
||||
"operation": "send",
|
||||
"phoneNumberId": "477115632141067",
|
||||
"requestOptions": {},
|
||||
"additionalFields": {
|
||||
"previewUrl": false
|
||||
},
|
||||
"recipientPhoneNumber": "={{ $('WhatsApp Trigger').item.json.messages[0].from }}"
|
||||
},
|
||||
"credentials": {
|
||||
"whatsAppApi": {
|
||||
"id": "9SFJPeqrpChOkAmw",
|
||||
"name": "WhatsApp account"
|
||||
}
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "52decd86-ac6c-4d91-a938-86f93ec5f822",
|
||||
"name": "Product Catalogue",
|
||||
"type": "@n8n/n8n-nodes-langchain.vectorStoreInMemory",
|
||||
"position": [
|
||||
2200,
|
||||
-60
|
||||
],
|
||||
"parameters": {
|
||||
"memoryKey": "whatsapp-75"
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "6dd5a652-2464-4ab8-8e5f-568529299523",
|
||||
"name": "Sticky Note",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
-88.75,
|
||||
-473.4375
|
||||
],
|
||||
"parameters": {
|
||||
"color": 7,
|
||||
"width": 640.4375,
|
||||
"height": 434.6875,
|
||||
"content": "## 1. Download Product Brochure PDF\n[Read more about the HTTP Request Tool](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.httprequest)\n\nImport your marketing PDF document to build your vector store. This will be used as the knowledgebase by the Sales AI Agent.\n\nFor this demonstration, we'll use the HTTP request node to import the YAMAHA POWERED LOUDSPEAKERS 2024 brochure ([Source](https://usa.yamaha.com/files/download/brochure/1/1474881/Yamaha-Powered-Loudspeakers-brochure-2024-en-web.pdf)) and an Extract from File node to extract the text contents. "
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "116663bc-d8d6-41a5-93dc-b219adbb2235",
|
||||
"name": "Sticky Note1",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
580,
|
||||
-476
|
||||
],
|
||||
"parameters": {
|
||||
"color": 7,
|
||||
"width": 614.6875,
|
||||
"height": 731.1875,
|
||||
"content": "## 2. Create Product Brochure Vector Store\n[Read more about the In-Memory Vector Store](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.vectorstoreinmemory/)\n\nVector stores are powerful databases which serve the purpose of matching a user's questions to relevant parts of a document. By creating a vector store of our product catalog, we'll allow users to query using natural language.\n\nTo keep things simple, we'll use the **In-memory Vector Store** which comes built-in to n8n and doesn't require a separate service. For production deployments, I'd recommend replacing the in-memory vector store with either [Qdrant](https://qdrant.tech) or [Pinecone](https://pinecone.io)."
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "86bd5334-d735-4650-aeff-06230119d705",
|
||||
"name": "Create Product Catalogue",
|
||||
"type": "@n8n/n8n-nodes-langchain.vectorStoreInMemory",
|
||||
"position": [
|
||||
760,
|
||||
-200
|
||||
],
|
||||
"parameters": {
|
||||
"mode": "insert",
|
||||
"memoryKey": "whatsapp-75",
|
||||
"clearStore": true
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "b8078b0d-cbd7-423f-bb30-13902988be38",
|
||||
"name": "Sticky Note2",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
1254,
|
||||
-552
|
||||
],
|
||||
"parameters": {
|
||||
"color": 7,
|
||||
"width": 546.6875,
|
||||
"height": 484.1875,
|
||||
"content": "## 3. Use the WhatsApp Trigger\n[Learn more about the WhatsApp Trigger](https://docs.n8n.io/integrations/builtin/trigger-nodes/n8n-nodes-base.whatsapptrigger/)\n\nThe WhatsApp Trigger allows you to receive incoming WhatsApp messages from customers. It requires a bit of setup so remember to follow the documentation carefully! Once ready however, it's quite easy to build powerful workflows which are easily accessible to users.\n\nNote that WhatsApp can send many message types such as audio and video so in this demonstration, we'll filter them out and just accept the text messages."
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "5bf7ed07-282b-4198-aa90-3e5ae5180404",
|
||||
"name": "Sticky Note3",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
1640,
|
||||
280
|
||||
],
|
||||
"parameters": {
|
||||
"width": 338,
|
||||
"height": 92,
|
||||
"content": "### Want to handle all message types?\nCheck out my other WhatsApp template in my creator page! https://n8n.io/creators/jimleuk/"
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "a3661b59-25d2-446e-8462-32b4d692b69d",
|
||||
"name": "Sticky Note4",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
1640,
|
||||
-40
|
||||
],
|
||||
"parameters": {
|
||||
"color": 7,
|
||||
"width": 337.6875,
|
||||
"height": 311.1875,
|
||||
"content": "### 3a. Handle Unsupported Message Types\nFor non-text messages, we'll just reply with a simple message to inform the sender."
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "ea3c9ee1-505a-40e7-82fe-9169bdbb80af",
|
||||
"name": "Sticky Note5",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
1840,
|
||||
-682.5
|
||||
],
|
||||
"parameters": {
|
||||
"color": 7,
|
||||
"width": 746.6875,
|
||||
"height": 929.1875,
|
||||
"content": "## 4. Sales AI Agent Responds To Customers\n[Learn more about using AI Agents](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.agent/)\n\nn8n's AI agents are powerful nodes which make it incredibly easy to use state-of-the-art AI in your workflows. Not only do they have the ability to remember conversations per individual customer but also tap into resources such as our product catalogue vector store to pull factual information and data for every question.\n\nIn this demonstration, we use an AI agent which is directed to help the user navigate the product brochure. A Chat memory subnode is attached to identify and keep track of the customer session. A Vector store tool is added to allow the Agent to tap into the product catalogue knowledgebase we built earlier."
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "5c72df8d-bca1-4634-b1ed-61ffec8bd103",
|
||||
"name": "Sticky Note6",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
2620,
|
||||
-560
|
||||
],
|
||||
"parameters": {
|
||||
"color": 7,
|
||||
"width": 495.4375,
|
||||
"height": 484.1875,
|
||||
"content": "## 5. Repond to WhatsApp User\n[Learn more about the WhatsApp Node](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.whatsapp/)\n\nThe WhatsApp node is the go-to if you want to interact with WhatsApp users. With this node, you can send text, images, audio and video messages as well as use your WhatsApp message templates.\n\nHere, we'll keep it simple by replying with a text message which is the output of the AI agent."
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "48ec809f-ca0e-4052-b403-9ad7077b3fff",
|
||||
"name": "Sticky Note7",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
-520,
|
||||
-620
|
||||
],
|
||||
"parameters": {
|
||||
"width": 401.25,
|
||||
"height": 582.6283033962263,
|
||||
"content": "## Try It Out!\n\n### This n8n template builds a simple WhatsApp chabot acting as a Sales Agent. The Agent is backed by a product catalog vector store to better answer user's questions.\n\n* This template is in 2 parts: creating the product catalog vector store and building the WhatsApp AI chatbot.\n* A product brochure is imported via HTTP request node and its text contents extracted.\n* The text contents are then uploaded to the in-memory vector store to build a knowledgebase for the chatbot.\n* A WhatsApp trigger is used to capture messages from customers where non-text messages are filtered out.\n* The customer's message is sent to the AI Agent which queries the product catalogue using the vector store tool.\n* The Agent's response is sent back to the user via the WhatsApp node.\n\n### Need Help?\nJoin the [Discord](https://discord.com/invite/XPKeKXeB7d) or ask in the [Forum](https://community.n8n.io/)!"
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "87cf9b41-66de-49a7-aeb0-c8809191b5a0",
|
||||
"name": "Handle Message Types",
|
||||
"type": "n8n-nodes-base.switch",
|
||||
"position": [
|
||||
1560,
|
||||
-280
|
||||
],
|
||||
"parameters": {
|
||||
"rules": {
|
||||
"values": [
|
||||
{
|
||||
"outputKey": "Supported",
|
||||
"conditions": {
|
||||
"options": {
|
||||
"version": 2,
|
||||
"leftValue": "",
|
||||
"caseSensitive": true,
|
||||
"typeValidation": "strict"
|
||||
},
|
||||
"combinator": "and",
|
||||
"conditions": [
|
||||
{
|
||||
"operator": {
|
||||
"type": "string",
|
||||
"operation": "equals"
|
||||
},
|
||||
"leftValue": "={{ $json.messages[0].type }}",
|
||||
"rightValue": "text"
|
||||
}
|
||||
]
|
||||
},
|
||||
"renameOutput": true
|
||||
},
|
||||
{
|
||||
"outputKey": "Not Supported",
|
||||
"conditions": {
|
||||
"options": {
|
||||
"version": 2,
|
||||
"leftValue": "",
|
||||
"caseSensitive": true,
|
||||
"typeValidation": "strict"
|
||||
},
|
||||
"combinator": "and",
|
||||
"conditions": [
|
||||
{
|
||||
"id": "89971d8c-a386-4e77-8f6c-f491a8e84cb6",
|
||||
"operator": {
|
||||
"type": "string",
|
||||
"operation": "notEquals"
|
||||
},
|
||||
"leftValue": "={{ $json.messages[0].type }}",
|
||||
"rightValue": "text"
|
||||
}
|
||||
]
|
||||
},
|
||||
"renameOutput": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {}
|
||||
},
|
||||
"typeVersion": 3.2
|
||||
},
|
||||
{
|
||||
"id": "e52f0a50-0c34-4c4a-b493-4c42ba112277",
|
||||
"name": "Sticky Note8",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
-80,
|
||||
-20
|
||||
],
|
||||
"parameters": {
|
||||
"color": 5,
|
||||
"width": 345.10906976744184,
|
||||
"height": 114.53583720930231,
|
||||
"content": "### You only have to run this part once!\nRun this step to populate our product catalogue vector. Run again if you want to update the vector store with a new version."
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "c1a7d6d1-191e-4343-af9f-f2c9eb4ecf49",
|
||||
"name": "Sticky Note9",
|
||||
"type": "n8n-nodes-base.stickyNote",
|
||||
"position": [
|
||||
1260,
|
||||
-40
|
||||
],
|
||||
"parameters": {
|
||||
"color": 5,
|
||||
"width": 364.6293255813954,
|
||||
"height": 107.02804651162779,
|
||||
"content": "### Activate your workflow to use!\nTo start using the WhatsApp chatbot, you'll need to activate the workflow. If you are self-hosting ensure WhatsApp is able to connect to your server."
|
||||
},
|
||||
"typeVersion": 1
|
||||
},
|
||||
{
|
||||
"id": "a36524d0-22a6-48cc-93fe-b4571cec428a",
|
||||
"name": "AI Sales Agent",
|
||||
"type": "@n8n/n8n-nodes-langchain.agent",
|
||||
"position": [
|
||||
1960,
|
||||
-400
|
||||
],
|
||||
"parameters": {
|
||||
"text": "={{ $json.messages[0].text.body }}",
|
||||
"options": {
|
||||
"systemMessage": "You are an assistant working for a company who sells Yamaha Powered Loudspeakers and helping the user navigate the product catalog for the year 2024. Your goal is not to facilitate a sale but if the user enquires, direct them to the appropriate website, url or contact information.\n\nDo your best to answer any questions factually. If you don't know the answer or unable to obtain the information from the datastore, then tell the user so."
|
||||
},
|
||||
"promptType": "define"
|
||||
},
|
||||
"typeVersion": 1.6
|
||||
}
|
||||
],
|
||||
"pinData": {},
|
||||
"connections": {
|
||||
"AI Sales Agent": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Reply To User",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"WhatsApp Trigger": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Handle Message Types",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Embeddings OpenAI": {
|
||||
"ai_embedding": [
|
||||
[
|
||||
{
|
||||
"node": "Product Catalogue",
|
||||
"type": "ai_embedding",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Extract from File": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Create Product Catalogue",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"OpenAI Chat Model": {
|
||||
"ai_languageModel": [
|
||||
[
|
||||
{
|
||||
"node": "AI Sales Agent",
|
||||
"type": "ai_languageModel",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Product Catalogue": {
|
||||
"ai_vectorStore": [
|
||||
[
|
||||
{
|
||||
"node": "Vector Store Tool",
|
||||
"type": "ai_vectorStore",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Vector Store Tool": {
|
||||
"ai_tool": [
|
||||
[
|
||||
{
|
||||
"node": "AI Sales Agent",
|
||||
"type": "ai_tool",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Embeddings OpenAI1": {
|
||||
"ai_embedding": [
|
||||
[
|
||||
{
|
||||
"node": "Create Product Catalogue",
|
||||
"type": "ai_embedding",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"OpenAI Chat Model1": {
|
||||
"ai_languageModel": [
|
||||
[
|
||||
{
|
||||
"node": "Vector Store Tool",
|
||||
"type": "ai_languageModel",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Default Data Loader": {
|
||||
"ai_document": [
|
||||
[
|
||||
{
|
||||
"node": "Create Product Catalogue",
|
||||
"type": "ai_document",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Handle Message Types": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "AI Sales Agent",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"node": "Reply To User1",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Window Buffer Memory": {
|
||||
"ai_memory": [
|
||||
[
|
||||
{
|
||||
"node": "AI Sales Agent",
|
||||
"type": "ai_memory",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"get Product Brochure": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Extract from File",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Recursive Character Text Splitter": {
|
||||
"ai_textSplitter": [
|
||||
[
|
||||
{
|
||||
"node": "Default Data Loader",
|
||||
"type": "ai_textSplitter",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"When clicking ‘Test workflow’": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "get Product Brochure",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user