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
+3
View File
@@ -0,0 +1,3 @@
.DS_Store
~$*
*.tmp
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 youlinhsieh
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+159
View File
@@ -0,0 +1,159 @@
# n8n 版 LLM Wiki
> Andrej Karpathy 的「LLM Wiki」概念,用 **n8n + Google Docs + Google Sheets** 重新實作的可下載版本。
> 不需要 Obsidian、不需要向量資料庫,人人都有的 Google 工具就能玩這套「新 RAG」。
感謝 [Andrej Karpathy](https://github.com/karpathy) 提出這個觀念。原文(gist):
<https://gist.github.com/karpathy/442a6bf555914893e9891c11ac484894>
---
## 這是什麼?
傳統 RAG 把文件丟進嵌入模型「碎紙化」存進向量庫,查詢時抽幾條碎紙給 LLM,LLM 只看得到那幾條、看不到全局。
Karpathy 的 **LLM Wiki** 用的是另一套思路 — **pre-compile(預編譯)**
把所有原始資料交給 LLM,讓它像「維基百科總編輯」一樣,把內容**整理、改寫、互相連結**後寫進一個結構化的知識庫。你問問題時,它先查**目錄(index)**,再讀對應的 wiki 條目來回答 — 有全局觀,知道來龍去脈,而不是靠碎紙拼湊。
| | 傳統向量 RAG | LLM Wiki(本專案) |
|---|---|---|
| 入庫方式 | 切塊 → 嵌入 → 存向量 | LLM 閱讀 → 整理改寫 → 寫成 wiki 條目 |
| 找資料方式 | 向量相似度 | 查**目錄**(像人查索引) |
| 資料成長 | 無限增加(知識**倉庫**) | 結構性整理、更新而非堆疊(知識**庫**) |
| 原稿角色 | 直接被切碎 | 單一事實來源(SSOT),有爭議時回查 |
| 成本 | 嵌入便宜 | Token 燒得較兇,但整理品質高 |
> **更新而非新增**:給它 1 萬份文件,它不會生成 1 萬篇 wiki,而是整理成一本結構化的「教科書」。內容相近就**更新**既有條目,差很多才**新增**。
---
## 為什麼用 Google Docs + Sheets
- **Obsidian 沒有網路版**,不一定人人習慣 — 重點是觀念,工具不重要。
- **Google Docs** 當 wiki 條目本體,電腦手機通用、人人都有。
- **Google Sheets** 當**目錄(index**:結構化、乾淨、搜尋飛快,n8n 又能直接讀成 JSON。目錄裡不只篇名,還有 `keywords``summary``last_updated`,讓 AI 好找。
---
## 倉庫內容
```
.
├── workflows/
│ ├── LLM_wiki.json # 主工作流(入庫 + 查詢兩條流程)
│ └── create_wiki_page.json # 子工作流:建立 Google Doc 並移到指定資料夾
├── index.xlsx # 目錄範本(上傳 Google Drive 後轉成 Google Sheets
├── wiki/
│ └── RAG 檢索增強生成(RAG.docx # 一篇 wiki 條目範例(轉成 Google Docs
└── README.md
```
> ⚠️ 這是**零件包**,你需要自己組裝(接上自己的 Google 帳號與 LLM 金鑰)。
### 為什麼下載的是 `.xlsx` 和 `.docx`
這個專案產生的 wiki 原本放在 **Google Drive 的 Docs / Sheets**。為了方便在 GitHub 上發佈下載,匯出成 Office 格式(`.xlsx` / `.docx`)。
**👉 你下載後,要把它們上傳到自己的 Google Drive,並轉回 Google 原生格式才能被 n8n 呼叫:**
| 下載到的檔案 | 上傳後請轉成 | 用途 |
|---|---|---|
| `index.xlsx` | **Google Sheets** | 目錄(index |
| `wiki/*.docx` | **Google Docs** | wiki 條目(範例,可刪) |
轉換方式(任一即可):
- 在 Google Drive 直接用 Google Sheets / Google Docs **開啟** `.xlsx` / `.docx`,再「檔案 → 另存為 Google 試算表 / Google 文件」。
- 或在 Drive 設定中開啟「上傳時自動轉換為 Google 文件格式」,再上傳。
---
## 目錄(index)欄位
`index.xlsx` 是 wiki 的目錄,AI 靠它找資料。欄位:
| 欄位 | 說明 |
|---|---|
| `topic` | 主題名稱(也是 wiki 條目的標題) |
| `doc_id` | 對應 Google Doc 的 ID |
| `keywords` | 關鍵字,幫 AI 比對問題 |
| `summary` | 摘要,幫 AI 判斷相關性 |
| `last_updated` | 最後更新日期 |
---
## 運作原理(兩條流程)
主工作流 `LLM_wiki.json` 內含兩條獨立流程。
### 1️⃣ 資料入庫(寫入)
`On form submission`(上傳 `.md` / `.txt`)→ `Extract from File`**`AI Agent`(知識寫入助手)**
寫入 Agent 的邏輯:
1. **先讀目錄** `get_indexs`(鐵律:沒讀過 index 不准做任何事)。
2. 把上傳文件拆成一個或多個主題。
3. 逐一判斷:
- **主題已存在** → `write_wiki`Append 到既有 Doc+ `update_wiki`(更新該條目的 keywords / summary)。
- **主題不存在** → `create_wiki_page`(建新 Doc,呼叫子工作流)+ `write_wiki`(寫入初始內容)+ `write_index`(在目錄新增一行)。
4. 確認每個主題都完成最後一步(更新過 index)才回報結果。
### 2️⃣ 資料查詢(讀取)
`When chat message received`**`AI Agent1`(知識查詢助手)**
查詢 Agent 的邏輯:
1. `get_indexs` 讀目錄,瀏覽所有 keywords / summary。
2. 判斷哪個(些)`doc_id` 與問題最相關。
3. `read_wiki` 讀取對應 Doc 全文。
4. 根據讀到的內容回答(只讀不寫;目錄裡找不到就老實說「Wiki 尚未收錄此主題」)。
### 子工作流 `create_wiki_page.json`
因為 Google Docs 節點**無法直接在指定資料夾建立文件**,所以拆成子工作流:用 Webhook 觸發 → `Create a document``Move file`(移到指定 wiki 資料夾)→ 回傳 `doc_id`。主工作流用 HTTP Request 節點呼叫它。
---
## 安裝與設定
### 需求
- 一個可用的 **n8n** 實例(自架或雲端)。
- **Google 帳號**Docs / Sheets / Drive 權限)。
- 一個 **LLM**。本專案範例用 **Google Gemini**`lmChatGoogleGemini` 節點),可自行換成其他 LLM 節點。
### 步驟
1. **匯入工作流**:在 n8n 中匯入 `workflows/LLM_wiki.json``workflows/create_wiki_page.json`
2. **準備 Google 檔案**
-`index.xlsx` 上傳 Google Drive 並**轉成 Google Sheets**。
- 在 Drive 建一個資料夾放 wiki 條目(例:`wiki/`)。
- (可選)把 `wiki/*.docx` 上傳並**轉成 Google Docs** 當範例,或直接刪掉從零開始。
3. **接憑證**:在每個 Google Sheets / Docs / Drive 節點接上你的 Google OAuth 憑證;LLM 節點接上你的金鑰。
4. **指定目標**
-`get_indexs` / `get_indexs1` / `write_index` 指向你的 index Google Sheet。
-`create_wiki_page` 子工作流的「建立文件」與「Move file」指向你的 wiki 資料夾。
- 主工作流的 `create_wiki_page` HTTP 節點 URL 改成**你自己 n8n 的 webhook 網址**(範本內是作者的網址,務必替換)。
5. **啟用並測試**
- 用表單上傳一份 `.md` / `.txt` → 看 index 是否新增、wiki 資料夾是否多出 Doc。
- 在 chat 觸發器問一個問題 → 看它是否查目錄、讀 Doc、回答。
---
## 注意事項
- **Token 燒得較兇**:因為是讓 LLM 真的去「讀、整理、改寫」資料,比向量法耗 token。處理大量文件前先評估成本。
- **範本內含作者的 webhook 網址**,請替換成自己的。
- 這套設計**重整理輕堆疊** — 它整理出來的是一個「知識**庫**」,而不是無限長大的「知識**倉庫**」。
---
## 致謝
觀念來自 **Andrej Karpathy** 的 LLM Wiki[原文 gist](https://gist.github.com/karpathy/442a6bf555914893e9891c11ac484894))。本專案只是把同一個觀念換成人人都有的 Google 工具,方便教學與實際使用。
## 授權
MIT License,詳見 [LICENSE](LICENSE)。
BIN
View File
Binary file not shown.
Binary file not shown.
+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": []
}