Initial commit: n8n 版 LLM Wiki

Karpathy 的 LLM Wiki 觀念,用 n8n + Google Docs + Google Sheets 實作。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-17 18:21:44 +08:00
commit 3f2db62850
7 changed files with 939 additions and 0 deletions
+614
View File
@@ -0,0 +1,614 @@
{
"name": "LLM_wiki",
"nodes": [
{
"parameters": {
"formTitle": "上傳文件",
"formDescription": "上傳你的知識文件",
"formFields": {
"values": [
{
"fieldLabel": "文件",
"fieldType": "file",
"fieldName": "doc",
"acceptFileTypes": ".md, .txt"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.formTrigger",
"typeVersion": 2.5,
"position": [
0,
112
],
"id": "57e78e69-c698-4fbe-963a-1e43d3e1dc81",
"name": "On form submission",
"webhookId": "75dd9d9f-182b-44a7-8295-ef33d55aa4d2"
},
{
"parameters": {
"promptType": "define",
"text": "=以下是用戶上傳的文件內容,請整理後寫入 Wiki\n{{ $json.doc }}",
"options": {
"systemMessage": "你是 Wiki 知識寫入助手。\n你的唯一任務是將收到的文件內容整理後,完整寫入 Wiki 知識庫。\n\n## 工具說明\n\n- get_indexs:讀取 index sheet,回傳所有條目的 topic、doc_id、keywords、summary\n- create_wiki_page:新建 Wiki Doc,輸入 topic 名稱,回傳 doc_id\n- write_wiki:在 Wiki Doc 末尾 Append 新內容,輸入 doc_id + content\n- write_index:在 index sheet 新增一行,用於全新條目,輸入 topic、doc_id、keywords、summary\n- update_wiki:更新 index sheet 既有條目的 keywords 和 summary,輸入 topic + 新值\n\n## 執行流程\n\n### 第一步:讀取 index(必須)\n呼叫 get_indexs,取得所有現有條目。\n在做任何其他動作之前,必須先完成這一步。\n\n### 第二步:分析文件\n將文件內容拆解為一個或多個主題。\n每個主題獨立處理。\n\n### 第三步:對每個主題執行以下判斷\n\n**如果主題已存在於 index**\n1. 呼叫 write_wiki(帶入既有 doc_id),將新知識 Append 到文件末尾\n2. 呼叫 update_wiki,更新該條目的 keywords 和 summary\n→ update_wiki 是這個分支的最後一步,未呼叫代表此主題尚未完成\n\n**如果主題不存在於 index**\n1. 呼叫 create_wiki_page(輸入 topic),取得新 doc_id\n2. 呼叫 write_wiki(帶入新 doc_id),寫入初始內容\n3. 呼叫 write_index,將新條目寫入 index sheet\n→ write_index 是這個分支的最後一步,未呼叫代表此主題尚未完成\n\n### 第四步:確認收尾(必須)\n在回報任何結果給用戶之前,檢查每個主題是否都已完成最後一步:\n- 既有主題:update_wiki 已呼叫 ✓\n- 新主題:write_index 已呼叫 ✓\n\n如果有任何主題還沒完成最後一步,必須先補完,才能回報結果。\n\n### 第五步:回報結果\n格式如下:\n\n✅ 已更新的主題:[topic 名稱]doc_id: xxx\n🆕 已新建的頁面:[topic 名稱]doc_id: xxx\n\n## 寫入格式規範\n\n- 語言:繁體中文\n- 結構:條列核心概念,每點一行\n- 末尾固定附上:來源:上傳文件|日期:{{$now}}\n- 模式:Append,絕對不刪除或覆蓋舊內容\n\n## 鐵律\n\n- 沒有呼叫 get_indexs 之前,不得執行任何其他工具\n- 沒有更新 index 之前,不得回報任務完成\n- write_wiki 永遠不是最後一步\n你必須透過工具呼叫(function call)執行所有操作。\n絕對不可以用文字描述「我將要呼叫 XXX」或「Calling XXX with input」。\n描述行動不等於執行行動。只有實際呼叫工具才算完成任務。"
}
},
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 3.1,
"position": [
704,
0
],
"id": "1a52474b-dc56-409f-b9f5-76655dd842f5",
"name": "AI Agent"
},
{
"parameters": {
"operation": "text",
"binaryPropertyName": "doc",
"destinationKey": "doc",
"options": {}
},
"type": "n8n-nodes-base.extractFromFile",
"typeVersion": 1.1,
"position": [
224,
112
],
"id": "b35641d7-1830-4951-9007-f1d5870fc223",
"name": "Extract from File"
},
{
"parameters": {
"descriptionType": "manual",
"toolDescription": "讀取 Wiki index sheet,取得所有現有條目。\n\n回傳每筆條目的:topic、doc_id、keywords、summary、last_updated\n\n這是每次流程的第一步,必須先呼叫才能判斷主題是否已存在。",
"authentication": "serviceAccount",
"documentId": {
"__rl": true,
"value": "1Zgs3o1sJxzWdpN_JbDHCcPECXvrxlj7QnYZKcu5u0ho",
"mode": "list",
"cachedResultName": "index",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Zgs3o1sJxzWdpN_JbDHCcPECXvrxlj7QnYZKcu5u0ho/edit?usp=drivesdk"
},
"sheetName": {
"__rl": true,
"value": "gid=0",
"mode": "list",
"cachedResultName": "工作表1",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Zgs3o1sJxzWdpN_JbDHCcPECXvrxlj7QnYZKcu5u0ho/edit#gid=0"
},
"options": {}
},
"type": "n8n-nodes-base.googleSheetsTool",
"typeVersion": 4.7,
"position": [
576,
224
],
"id": "71b93dc0-d918-42dd-88ca-30a75b807130",
"name": "get_indexs",
"credentials": {
"googleApi": {
"id": "jiemOwKMFTLhtSli",
"name": "Service_Account_Richblack"
}
}
},
{
"parameters": {
"toolDescription": "=建立一個新的 Google Docs Wiki 頁面。\n\n輸入:\n- doc_title:頁面標題(主題名稱)\n\n回傳:\n- doc_id:新建頁面的 Google Doc ID(後續 write_wiki 和 write_index 都需要這個值)\n\n注意:建立後必須繼續呼叫 write_wiki 寫入內容,再呼叫 write_index 更新索引,任務才算完成。",
"method": "POST",
"url": "https://YOUR-N8N-HOST/webhook/YOUR-CREATE-WIKI-PAGE-WEBHOOK-ID",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "doc_title",
"value": "={{ $fromAI('doc_title') }}"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.httpRequestTool",
"typeVersion": 4.4,
"position": [
704,
224
],
"id": "8e9efcaa-e434-444a-98bc-347fc0c9b989",
"name": "create_wiki_page"
},
{
"parameters": {
"modelName": "models/gemini-flash-latest",
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"typeVersion": 1.1,
"position": [
448,
224
],
"id": "7cb78f89-1c14-435d-90aa-1f2dcb3bd07d",
"name": "Gemini",
"credentials": {
"googlePalmApi": {
"id": "kT9HBbdgSzqMyxem",
"name": "Google Gemini Leo 自家用"
}
}
},
{
"parameters": {
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.chatTrigger",
"typeVersion": 1.4,
"position": [
240,
464
],
"id": "d437ecd9-f215-4e9e-850b-9f041ef9168e",
"name": "When chat message received",
"webhookId": "2215100f-da5f-4c4d-a25c-c5e480d8c54c"
},
{
"parameters": {
"descriptionType": "manual",
"toolDescription": "讀取指定 Wiki Google Doc 的完整內容。\n\n輸入:\n- doc_id:目標 Google Doc 的 ID(從 get_indexs 取得)\n\n回傳:該頁面的全文內容,用於回答用戶問題。",
"operation": "get",
"documentURL": "={{ $fromAI('doc_id') }}"
},
"type": "n8n-nodes-base.googleDocsTool",
"typeVersion": 2,
"position": [
720,
688
],
"id": "bc9be3ed-9db6-4efa-b517-ea06c56b0c8d",
"name": "read_wiki",
"credentials": {
"googleDocsOAuth2Api": {
"id": "pgd50DD52VYwX6IC",
"name": "Leo_personal_n8n_test"
}
}
},
{
"parameters": {
"options": {
"systemMessage": "你是 Wiki 知識查詢助手。\n你的任務是根據用戶的問題,從 Wiki 知識庫找到答案後回答。\n\n工具說明:\n- get_indexs:讀取 index sheet,回傳所有條目的 topic、doc_id、keywords、summary\n- read_wiki:讀取指定 Wiki Doc 的內容,輸入 doc_id,回傳全文\n\n執行順序:\n1. 呼叫 get_indexs,瀏覽所有條目的 keywords 和 summary\n2. 判斷哪個(或哪幾個)doc_id 與問題最相關\n3. 呼叫 read_wiki(帶入 doc_id)讀取內容\n4. 根據讀到的內容回答用戶\n\n注意:\n- 只讀不寫,不要修改任何 Wiki 內容\n- 如果 index 裡找不到相關主題,直接告知用戶「Wiki 尚未收錄此主題」\n- 回答要根據 Wiki 內容,不要自己發明答案"
}
},
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 3.1,
"position": [
592,
464
],
"id": "2b77a40c-e0b7-477f-aac1-50d80fe4deec",
"name": "AI Agent1"
},
{
"parameters": {
"modelName": "models/gemma-4-31b-it",
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"typeVersion": 1.1,
"position": [
464,
688
],
"id": "e32a353a-adb9-4821-8308-784af0c93129",
"name": "Gemini1",
"credentials": {
"googlePalmApi": {
"id": "kT9HBbdgSzqMyxem",
"name": "Google Gemini Leo 自家用"
}
}
},
{
"parameters": {
"descriptionType": "manual",
"toolDescription": "在 index sheet 新增或更新一筆條目。這是每次寫入流程的最後一步,沒有呼叫這個工具代表任務尚未完成。\n\n輸入:\n- topic:主題名稱\n- doc_id:對應的 Google Doc ID(從 create_wiki_page 取得,或從 get_indexs 讀出)\n- keywords:逗號分隔的關鍵詞列表\n- summary:這篇 Wiki 目前涵蓋內容的一句話摘要\n- last_updated:今天日期,格式 YYYY-MM-DD\n\n行為:doc_id 已存在則更新該行,不存在則新增一行。",
"authentication": "serviceAccount",
"operation": "appendOrUpdate",
"documentId": {
"__rl": true,
"value": "1Zgs3o1sJxzWdpN_JbDHCcPECXvrxlj7QnYZKcu5u0ho",
"mode": "list",
"cachedResultName": "index",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Zgs3o1sJxzWdpN_JbDHCcPECXvrxlj7QnYZKcu5u0ho/edit?usp=drivesdk"
},
"sheetName": {
"__rl": true,
"value": "gid=0",
"mode": "list",
"cachedResultName": "工作表1",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Zgs3o1sJxzWdpN_JbDHCcPECXvrxlj7QnYZKcu5u0ho/edit#gid=0"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"doc_id": "={{ $fromAI('doc_id') }}",
"topic": "={{ $fromAI('topic') }}",
"keywords": "={{ $fromAI('keywords') }}",
"summary": "={{ $fromAI('summary') }}",
"last_updated": "={{ $fromAI('last_updated') }}"
},
"matchingColumns": [
"doc_id"
],
"schema": [
{
"id": "topic",
"displayName": "topic",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "doc_id",
"displayName": "doc_id",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "keywords",
"displayName": "keywords",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "summary",
"displayName": "summary",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "last_updated",
"displayName": "last_updated",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.googleSheetsTool",
"typeVersion": 4.7,
"position": [
832,
224
],
"id": "6091001d-c6e3-478d-bdbd-6ab4afededc2",
"name": "write_index",
"credentials": {
"googleApi": {
"id": "jiemOwKMFTLhtSli",
"name": "Service_Account_Richblack"
}
}
},
{
"parameters": {
"descriptionType": "manual",
"toolDescription": "讀取指定 Wiki Google Doc 的完整內容。\n\n輸入:\n- doc_id:目標 Google Doc 的 ID(從 get_indexs 取得)\n\n回傳:該頁面的全文內容,用於回答用戶問題。",
"authentication": "serviceAccount",
"documentId": {
"__rl": true,
"value": "1Zgs3o1sJxzWdpN_JbDHCcPECXvrxlj7QnYZKcu5u0ho",
"mode": "list",
"cachedResultName": "index",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Zgs3o1sJxzWdpN_JbDHCcPECXvrxlj7QnYZKcu5u0ho/edit?usp=drivesdk"
},
"sheetName": {
"__rl": true,
"value": "gid=0",
"mode": "list",
"cachedResultName": "工作表1",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Zgs3o1sJxzWdpN_JbDHCcPECXvrxlj7QnYZKcu5u0ho/edit#gid=0"
},
"options": {}
},
"type": "n8n-nodes-base.googleSheetsTool",
"typeVersion": 4.7,
"position": [
848,
688
],
"id": "d9edd457-07a4-46d6-810b-c1c988ac9525",
"name": "get_indexs1",
"credentials": {
"googleApi": {
"id": "jiemOwKMFTLhtSli",
"name": "Service_Account_Richblack"
}
}
},
{
"parameters": {},
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"typeVersion": 1.4,
"position": [
592,
688
],
"id": "48c22e61-9260-4c77-b782-cf3cd049e371",
"name": "Simple Memory"
},
{
"parameters": {
"descriptionType": "manual",
"toolDescription": "取代指定 Wiki Google Doc 中的特定文字段落。用於修改或更正既有頁面中的內容。\n\n輸入:\n- doc_id:目標 Google Doc 的 ID\n- old_text:要被取代的原始文字\n- new_text:取代後的新文字\n\n注意:呼叫完畢後必須繼續呼叫 write_index 更新索引中的 keywords 和 summary。",
"operation": "update",
"documentURL": "={{ $fromAI('doc_id') }}",
"actionsUi": {
"actionFields": [
{
"action": "replaceAll",
"text": "={{ $fromAI('old_text') }}",
"replaceText": "={{ $fromAI('new_text') }}"
}
]
}
},
"type": "n8n-nodes-base.googleDocsTool",
"typeVersion": 2,
"position": [
960,
224
],
"id": "811d333c-2d32-4238-a03a-bf35e2d7bd82",
"name": "update_wiki",
"credentials": {
"googleDocsOAuth2Api": {
"id": "pgd50DD52VYwX6IC",
"name": "Leo_personal_n8n_test"
}
}
},
{
"parameters": {
"descriptionType": "manual",
"toolDescription": "將新內容 Append(插入)到指定的 Wiki Google Doc 末尾。用於寫入全新頁面的初始內容,或在既有頁面末尾新增知識。\n\n輸入:\n- doc_id:目標 Google Doc 的 ID\n- text:要寫入的內容\n\n注意:這是新增內容,不會刪除原有內容。呼叫完畢後必須繼續呼叫 write_index 更新索引。",
"operation": "update",
"documentURL": "={{ $fromAI('doc_id') }}",
"actionsUi": {
"actionFields": [
{
"action": "insert",
"text": "={{ $fromAI('text') }}"
}
]
}
},
"type": "n8n-nodes-base.googleDocsTool",
"typeVersion": 2,
"position": [
1088,
224
],
"id": "64891a23-95d7-4d9f-a8ff-a0e74798737e",
"name": "write_wiki",
"credentials": {
"googleDocsOAuth2Api": {
"id": "pgd50DD52VYwX6IC",
"name": "Leo_personal_n8n_test"
}
}
},
{
"parameters": {
"content": "## 1. 資料入庫",
"height": 448,
"width": 1328,
"color": 2
},
"type": "n8n-nodes-base.stickyNote",
"position": [
-96,
-80
],
"typeVersion": 1,
"id": "e6626b8e-1717-40f1-9094-e95d3455eec8",
"name": "Sticky Note"
},
{
"parameters": {
"content": "## 2. 資料查詢",
"height": 448,
"width": 1328,
"color": 4
},
"type": "n8n-nodes-base.stickyNote",
"position": [
-96,
384
],
"typeVersion": 1,
"id": "35370a11-27e8-4b58-97db-725cf7af1319",
"name": "Sticky Note1"
}
],
"pinData": {},
"connections": {
"On form submission": {
"main": [
[
{
"node": "Extract from File",
"type": "main",
"index": 0
}
]
]
},
"Extract from File": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
]
]
},
"get_indexs": {
"ai_tool": [
[
{
"node": "AI Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"create_wiki_page": {
"ai_tool": [
[
{
"node": "AI Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Gemini": {
"ai_languageModel": [
[
{
"node": "AI Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"When chat message received": {
"main": [
[
{
"node": "AI Agent1",
"type": "main",
"index": 0
}
]
]
},
"read_wiki": {
"ai_tool": [
[
{
"node": "AI Agent1",
"type": "ai_tool",
"index": 0
}
]
]
},
"Gemini1": {
"ai_languageModel": [
[
{
"node": "AI Agent1",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"write_index": {
"ai_tool": [
[
{
"node": "AI Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"get_indexs1": {
"ai_tool": [
[
{
"node": "AI Agent1",
"type": "ai_tool",
"index": 0
}
]
]
},
"Simple Memory": {
"ai_memory": [
[
{
"node": "AI Agent1",
"type": "ai_memory",
"index": 0
}
]
]
},
"update_wiki": {
"ai_tool": [
[
{
"node": "AI Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"write_wiki": {
"ai_tool": [
[
{
"node": "AI Agent",
"type": "ai_tool",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1",
"binaryMode": "separate"
},
"versionId": "e749498e-7a54-4cf8-95da-11b5a53cdd29",
"meta": {
"templateCredsSetupCompleted": true,
"instanceId": "4b0d44081b86641724941387a3a04b51a305f7e1a5c57b8feea64b401216b1f0"
},
"id": "eIbQFUBI8Q8bRRPn",
"tags": []
}
+142
View File
@@ -0,0 +1,142 @@
{
"name": "create_wiki_page",
"nodes": [
{
"parameters": {
"folderId": "14vxRl7a9DZLG1ykMTdPCi1AzeQX79usZ",
"title": "={{ $json.body.doc_title }}"
},
"type": "n8n-nodes-base.googleDocs",
"typeVersion": 2,
"position": [
208,
-128
],
"id": "317e8285-f374-493d-acf0-33175e883755",
"name": "Create a document",
"credentials": {
"googleDocsOAuth2Api": {
"id": "pgd50DD52VYwX6IC",
"name": "Leo_personal_n8n_test"
}
}
},
{
"parameters": {
"operation": "move",
"fileId": {
"__rl": true,
"value": "={{ $json.id }}",
"mode": "id"
},
"driveId": {
"__rl": true,
"value": "My Drive",
"mode": "list",
"cachedResultName": "My Drive",
"cachedResultUrl": "https://drive.google.com/drive/my-drive"
},
"folderId": {
"__rl": true,
"value": "1cpyZ8P3uIDq6ImgwO9K47AsXyfSy3KU3",
"mode": "list",
"cachedResultName": "wiki",
"cachedResultUrl": "https://drive.google.com/drive/folders/1cpyZ8P3uIDq6ImgwO9K47AsXyfSy3KU3"
}
},
"type": "n8n-nodes-base.googleDrive",
"typeVersion": 3,
"position": [
432,
-128
],
"id": "59a77840-bca4-4680-8532-e841fb23817a",
"name": "Move file",
"credentials": {
"googleDriveOAuth2Api": {
"id": "QRyA20Y3eqGs35SL",
"name": "Google Drive account"
}
}
},
{
"parameters": {
"httpMethod": "POST",
"path": "38c09cd0-cc9f-44f0-b99c-4009f3a3e3a0",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
-16,
-128
],
"id": "e93dc02f-546e-4836-9e2f-6afb64344565",
"name": "Webhook",
"webhookId": "38c09cd0-cc9f-44f0-b99c-4009f3a3e3a0"
},
{
"parameters": {
"respondWith": "allIncomingItems",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.5,
"position": [
640,
-128
],
"id": "9485ee0d-dea6-40a2-b439-ad947d03f4a6",
"name": "Respond to Webhook"
}
],
"pinData": {},
"connections": {
"Create a document": {
"main": [
[
{
"node": "Move file",
"type": "main",
"index": 0
}
]
]
},
"Webhook": {
"main": [
[
{
"node": "Create a document",
"type": "main",
"index": 0
}
]
]
},
"Move file": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
}
},
"active": true,
"settings": {
"executionOrder": "v1",
"binaryMode": "separate"
},
"versionId": "b86e5488-b977-4ed5-813c-4bea3a8b080a",
"meta": {
"templateCredsSetupCompleted": true,
"instanceId": "4b0d44081b86641724941387a3a04b51a305f7e1a5c57b8feea64b401216b1f0"
},
"id": "5AhXVFwD2xRkSJXH",
"tags": []
}