feat: External workflow file support with dynamic credential replacement
- Add --workflow-file option to install.sh (default: RAGKI-BotPGVector.json) - Add --ollama-model option (default: ministral-3:3b) - Add --embedding-model option (default: nomic-embed-text:latest) - Update libsupabase.sh to read workflow from external JSON file - Add Python script for dynamic credential ID replacement in workflow - Remove id, versionId, meta, tags, active, pinData from imported workflow - Include RAGKI-BotPGVector.json as default workflow template Tested successfully on container sb-1769180683
This commit is contained in:
323
RAGKI-BotPGVector.json
Normal file
323
RAGKI-BotPGVector.json
Normal file
@@ -0,0 +1,323 @@
|
||||
{
|
||||
"name": "RAG KI-Bot (PGVector)",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {
|
||||
"public": true,
|
||||
"initialMessages": "Hallo! 👋\nMein Name ist Clara (Customer Learning & Answering Reference Assistant)\nWie kann ich behilflich sein?",
|
||||
"options": {
|
||||
"inputPlaceholder": "Hier die Frage eingeben...",
|
||||
"showWelcomeScreen": true,
|
||||
"subtitle": "Die Antworten der AI können fehlerhaft sein.",
|
||||
"title": "Support-Chat 👋",
|
||||
"customCss": ":root {\n /* Colors */\n --chat--color-primary: #e74266;\n --chat--color-primary-shade-50: #db4061;\n --chat--color-primary-shade-100: #cf3c5c;\n --chat--color-secondary: #20b69e;\n --chat--color-secondary-shade-50: #1ca08a;\n --chat--color-white: #ffffff;\n --chat--color-light: #f2f4f8;\n --chat--color-light-shade-50: #e6e9f1;\n --chat--color-light-shade-100: #c2c5cc;\n --chat--color-medium: #d2d4d9;\n --chat--color-dark: #101330;\n --chat--color-disabled: #d2d4d9;\n --chat--color-typing: #404040;\n\n /* Base Layout */\n --chat--spacing: 1rem;\n --chat--border-radius: 0.25rem;\n --chat--transition-duration: 0.15s;\n --chat--font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;\n\n /* Window Dimensions */\n --chat--window--width: 400px;\n --chat--window--height: 600px;\n --chat--window--bottom: var(--chat--spacing);\n --chat--window--right: var(--chat--spacing);\n --chat--window--z-index: 9999;\n --chat--window--border: 1px solid var(--chat--color-light-shade-50);\n --chat--window--border-radius: var(--chat--border-radius);\n --chat--window--margin-bottom: var(--chat--spacing);\n\n /* Header Styles */\n --chat--header-height: auto;\n --chat--header--padding: var(--chat--spacing);\n --chat--header--background: var(--chat--color-dark);\n --chat--header--color: var(--chat--color-light);\n --chat--header--border-top: none;\n --chat--header--border-bottom: none;\n --chat--header--border-left: none;\n --chat--header--border-right: none;\n --chat--heading--font-size: 2em;\n --chat--subtitle--font-size: inherit;\n --chat--subtitle--line-height: 1.8;\n\n /* Message Styles */\n --chat--message--font-size: 1rem;\n --chat--message--padding: var(--chat--spacing);\n --chat--message--border-radius: var(--chat--border-radius);\n --chat--message-line-height: 1.5;\n --chat--message--margin-bottom: calc(var(--chat--spacing) * 1);\n --chat--message--bot--background: var(--chat--color-white);\n --chat--message--bot--color: var(--chat--color-dark);\n --chat--message--bot--border: none;\n --chat--message--user--background: var(--chat--color-secondary);\n --chat--message--user--color: var(--chat--color-white);\n --chat--message--user--border: none;\n --chat--message--pre--background: rgba(0, 0, 0, 0.05);\n --chat--messages-list--padding: var(--chat--spacing);\n\n /* Toggle Button */\n --chat--toggle--size: 64px;\n --chat--toggle--width: var(--chat--toggle--size);\n --chat--toggle--height: var(--chat--toggle--size);\n --chat--toggle--border-radius: 50%;\n --chat--toggle--background: var(--chat--color-primary);\n --chat--toggle--hover--background: var(--chat--color-primary-shade-50);\n --chat--toggle--active--background: var(--chat--color-primary-shade-100);\n --chat--toggle--color: var(--chat--color-white);\n\n /* Input Area */\n --chat--textarea--height: 50px;\n --chat--textarea--max-height: 30rem;\n --chat--input--font-size: inherit;\n --chat--input--border: 0;\n --chat--input--border-radius: 0;\n --chat--input--padding: 0.8rem;\n --chat--input--background: var(--chat--color-white);\n --chat--input--text-color: initial;\n --chat--input--line-height: 1.5;\n --chat--input--placeholder--font-size: var(--chat--input--font-size);\n --chat--input--border-active: 0;\n --chat--input--left--panel--width: 2rem;\n\n /* Button Styles */\n --chat--button--color: var(--chat--color-light);\n --chat--button--background: var(--chat--color-primary);\n --chat--button--padding: calc(var(--chat--spacing) * 1 / 2) var(--chat--spacing);\n --chat--button--border-radius: var(--chat--border-radius);\n --chat--button--hover--color: var(--chat--color-light);\n --chat--button--hover--background: var(--chat--color-primary-shade-50);\n --chat--close--button--color-hover: var(--chat--color-primary);\n\n /* Send and File Buttons */\n --chat--input--send--button--background: var(--chat--color-white);\n --chat--input--send--button--color: var(--chat--color-secondary);\n --chat--input--send--button--background-hover: var(--chat--color-primary-shade-50);\n --chat--input--send--button--color-hover: var(--chat--color-secondary-shade-50);\n --chat--input--file--button--background: var(--chat--color-white);\n --chat--input--file--button--color: var(--chat--color-secondary);\n --chat--input--file--button--background-hover: var(--chat--input--file--button--background);\n --chat--input--file--button--color-hover: var(--chat--color-secondary-shade-50);\n --chat--files-spacing: 0.25rem;\n\n /* Body and Footer */\n --chat--body--background: var(--chat--color-light);\n --chat--footer--background: var(--chat--color-light);\n --chat--footer--color: var(--chat--color-dark);\n}\n\n\n/* You can override any class styles, too. Right-click inspect in Chat UI to find class to override. */\n.chat-message {\n\tmax-width: 50%;\n}",
|
||||
"responseMode": "lastNode"
|
||||
}
|
||||
},
|
||||
"type": "@n8n/n8n-nodes-langchain.chatTrigger",
|
||||
"typeVersion": 1.3,
|
||||
"position": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"id": "chat-trigger-001",
|
||||
"name": "When chat message received",
|
||||
"webhookId": "rag-chat-webhook",
|
||||
"notesInFlow": true,
|
||||
"notes": "Chat URL: /webhook/rag-chat-webhook/chat"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"promptType": "define",
|
||||
"text": "={{ $json.chatInput }}\nAntworte ausschliesslich auf Deutsch und nutze zuerst die Wissensdatenbank.",
|
||||
"options": {}
|
||||
},
|
||||
"type": "@n8n/n8n-nodes-langchain.agent",
|
||||
"typeVersion": 2.2,
|
||||
"position": [
|
||||
208,
|
||||
0
|
||||
],
|
||||
"id": "ai-agent-001",
|
||||
"name": "AI Agent"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"model": "ministral-3:3b",
|
||||
"options": {}
|
||||
},
|
||||
"type": "@n8n/n8n-nodes-langchain.lmChatOllama",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
64,
|
||||
208
|
||||
],
|
||||
"id": "ollama-chat-001",
|
||||
"name": "Ollama Chat Model",
|
||||
"credentials": {
|
||||
"ollamaApi": {
|
||||
"id": "ZmMYzkrY4zMFYJ1J",
|
||||
"name": "Ollama (local)"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {},
|
||||
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
|
||||
"typeVersion": 1.3,
|
||||
"position": [
|
||||
224,
|
||||
208
|
||||
],
|
||||
"id": "memory-001",
|
||||
"name": "Simple Memory"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"mode": "retrieve-as-tool",
|
||||
"toolName": "knowledge_base",
|
||||
"toolDescription": "Verwende dieses Tool für Infos die der Benutzer fragt. Sucht in der Wissensdatenbank nach relevanten Dokumenten.",
|
||||
"tableName": "documents",
|
||||
"options": {}
|
||||
},
|
||||
"type": "@n8n/n8n-nodes-langchain.vectorStorePGVector",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
432,
|
||||
128
|
||||
],
|
||||
"id": "pgvector-retrieve-001",
|
||||
"name": "PGVector Store",
|
||||
"credentials": {
|
||||
"postgres": {
|
||||
"id": "1VVtY5ei866suQdA",
|
||||
"name": "PostgreSQL (local)"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"model": "nomic-embed-text:latest"
|
||||
},
|
||||
"type": "@n8n/n8n-nodes-langchain.embeddingsOllama",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
416,
|
||||
288
|
||||
],
|
||||
"id": "embeddings-retrieve-001",
|
||||
"name": "Embeddings Ollama",
|
||||
"credentials": {
|
||||
"ollamaApi": {
|
||||
"id": "ZmMYzkrY4zMFYJ1J",
|
||||
"name": "Ollama (local)"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"formTitle": "Dokument hochladen",
|
||||
"formDescription": "Laden Sie ein PDF-Dokument hoch, um es in die Wissensdatenbank aufzunehmen.",
|
||||
"formFields": {
|
||||
"values": [
|
||||
{
|
||||
"fieldLabel": "Dokument",
|
||||
"fieldType": "file",
|
||||
"acceptFileTypes": ".pdf"
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {}
|
||||
},
|
||||
"type": "n8n-nodes-base.formTrigger",
|
||||
"typeVersion": 2.3,
|
||||
"position": [
|
||||
768,
|
||||
0
|
||||
],
|
||||
"id": "form-trigger-001",
|
||||
"name": "On form submission",
|
||||
"webhookId": "rag-upload-form"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"operation": "pdf",
|
||||
"binaryPropertyName": "Dokument",
|
||||
"options": {}
|
||||
},
|
||||
"type": "n8n-nodes-base.extractFromFile",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
976,
|
||||
0
|
||||
],
|
||||
"id": "extract-file-001",
|
||||
"name": "Extract from File"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"mode": "insert",
|
||||
"tableName": "documents",
|
||||
"options": {}
|
||||
},
|
||||
"type": "@n8n/n8n-nodes-langchain.vectorStorePGVector",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
1184,
|
||||
0
|
||||
],
|
||||
"id": "pgvector-insert-001",
|
||||
"name": "PGVector Store Insert",
|
||||
"credentials": {
|
||||
"postgres": {
|
||||
"id": "1VVtY5ei866suQdA",
|
||||
"name": "PostgreSQL (local)"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"model": "nomic-embed-text:latest"
|
||||
},
|
||||
"type": "@n8n/n8n-nodes-langchain.embeddingsOllama",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
1168,
|
||||
240
|
||||
],
|
||||
"id": "embeddings-insert-001",
|
||||
"name": "Embeddings Ollama1",
|
||||
"credentials": {
|
||||
"ollamaApi": {
|
||||
"id": "ZmMYzkrY4zMFYJ1J",
|
||||
"name": "Ollama (local)"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"options": {}
|
||||
},
|
||||
"type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader",
|
||||
"typeVersion": 1.1,
|
||||
"position": [
|
||||
1392,
|
||||
240
|
||||
],
|
||||
"id": "data-loader-001",
|
||||
"name": "Default Data Loader"
|
||||
}
|
||||
],
|
||||
"pinData": {},
|
||||
"connections": {
|
||||
"When chat message received": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "AI Agent",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Ollama Chat Model": {
|
||||
"ai_languageModel": [
|
||||
[
|
||||
{
|
||||
"node": "AI Agent",
|
||||
"type": "ai_languageModel",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Simple Memory": {
|
||||
"ai_memory": [
|
||||
[
|
||||
{
|
||||
"node": "AI Agent",
|
||||
"type": "ai_memory",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"PGVector Store": {
|
||||
"ai_tool": [
|
||||
[
|
||||
{
|
||||
"node": "AI Agent",
|
||||
"type": "ai_tool",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Embeddings Ollama": {
|
||||
"ai_embedding": [
|
||||
[
|
||||
{
|
||||
"node": "PGVector Store",
|
||||
"type": "ai_embedding",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"On form submission": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Extract from File",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Extract from File": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "PGVector Store Insert",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Embeddings Ollama1": {
|
||||
"ai_embedding": [
|
||||
[
|
||||
{
|
||||
"node": "PGVector Store Insert",
|
||||
"type": "ai_embedding",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Default Data Loader": {
|
||||
"ai_document": [
|
||||
[
|
||||
{
|
||||
"node": "PGVector Store Insert",
|
||||
"type": "ai_document",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"active": true,
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"versionId": "6ebf0ac8-b8ab-49ee-b6f1-df0b606b3a33",
|
||||
"meta": {
|
||||
"instanceId": "a2179cec0884855b4d650fea20868c0dbbb03f0d0054c803c700fff052afc74c"
|
||||
},
|
||||
"id": "Q9Bm63B9ae8rAj95",
|
||||
"tags": []
|
||||
}
|
||||
24
install.sh
24
install.sh
@@ -61,6 +61,9 @@ Domain / n8n options:
|
||||
--base-domain <domain> (default: userman.de) -> FQDN becomes sb-<unix>.domain
|
||||
--n8n-owner-email <email> (default: admin@<base-domain>)
|
||||
--n8n-owner-pass <pass> Optional. If omitted, generated (policy compliant).
|
||||
--workflow-file <path> Path to n8n workflow JSON file (default: RAGKI-BotPGVector.json)
|
||||
--ollama-model <model> Ollama chat model (default: ministral-3:3b)
|
||||
--embedding-model <model> Ollama embedding model (default: nomic-embed-text:latest)
|
||||
--debug Enable debug mode (show logs on stderr)
|
||||
--help Show help
|
||||
|
||||
@@ -95,11 +98,18 @@ N8N_OWNER_EMAIL=""
|
||||
N8N_OWNER_PASS=""
|
||||
POSTGREST_PORT="3000"
|
||||
|
||||
# Workflow file (default: RAGKI-BotPGVector.json in script directory)
|
||||
WORKFLOW_FILE="${SCRIPT_DIR}/RAGKI-BotPGVector.json"
|
||||
|
||||
# Ollama API settings (hardcoded for local setup)
|
||||
OLLAMA_HOST="192.168.45.3"
|
||||
OLLAMA_PORT="11434"
|
||||
OLLAMA_URL="http://${OLLAMA_HOST}:${OLLAMA_PORT}"
|
||||
|
||||
# Ollama models (can be overridden via CLI)
|
||||
OLLAMA_MODEL="ministral-3:3b"
|
||||
EMBEDDING_MODEL="nomic-embed-text:latest"
|
||||
|
||||
# ---------------------------
|
||||
# Arg parsing
|
||||
# ---------------------------
|
||||
@@ -119,6 +129,9 @@ while [[ $# -gt 0 ]]; do
|
||||
--base-domain) BASE_DOMAIN="${2:-}"; shift 2 ;;
|
||||
--n8n-owner-email) N8N_OWNER_EMAIL="${2:-}"; shift 2 ;;
|
||||
--n8n-owner-pass) N8N_OWNER_PASS="${2:-}"; shift 2 ;;
|
||||
--workflow-file) WORKFLOW_FILE="${2:-}"; shift 2 ;;
|
||||
--ollama-model) OLLAMA_MODEL="${2:-}"; shift 2 ;;
|
||||
--embedding-model) EMBEDDING_MODEL="${2:-}"; shift 2 ;;
|
||||
--postgrest-port) POSTGREST_PORT="${2:-}"; shift 2 ;;
|
||||
--debug) DEBUG="1"; export DEBUG; shift 1 ;;
|
||||
--help|-h) usage; exit 0 ;;
|
||||
@@ -145,8 +158,15 @@ if [[ -n "${APT_PROXY}" ]]; then
|
||||
[[ "${APT_PROXY}" =~ ^http://[^/]+:[0-9]+$ ]] || die "--apt-proxy must look like http://IP:PORT (example: http://192.168.45.2:3142)"
|
||||
fi
|
||||
|
||||
# Validate workflow file exists
|
||||
if [[ ! -f "${WORKFLOW_FILE}" ]]; then
|
||||
die "Workflow file not found: ${WORKFLOW_FILE}"
|
||||
fi
|
||||
|
||||
info "Argument-Parsing OK"
|
||||
info "Workflow file: ${WORKFLOW_FILE}"
|
||||
info "Ollama model: ${OLLAMA_MODEL}"
|
||||
info "Embedding model: ${EMBEDDING_MODEL}"
|
||||
|
||||
if [[ -n "${APT_PROXY}" ]]; then
|
||||
info "APT proxy enabled: ${APT_PROXY}"
|
||||
@@ -602,10 +622,10 @@ info "Chat Webhook URL (intern): ${CHAT_INTERNAL_URL}"
|
||||
info "Step 10: Setting up n8n credentials and importing RAG workflow..."
|
||||
|
||||
# Use the new robust n8n setup function from libsupabase.sh
|
||||
# Parameters: ctid, email, password, pg_host, pg_port, pg_db, pg_user, pg_pass, ollama_url, ollama_model, embedding_model
|
||||
# Parameters: ctid, email, password, pg_host, pg_port, pg_db, pg_user, pg_pass, ollama_url, ollama_model, embedding_model, workflow_file
|
||||
if n8n_setup_rag_workflow "${CTID}" "${N8N_OWNER_EMAIL}" "${N8N_OWNER_PASS}" \
|
||||
"postgres" "5432" "${PG_DB}" "${PG_USER}" "${PG_PASSWORD}" \
|
||||
"${OLLAMA_URL}" "llama3.2:3b" "nomic-embed-text:v1.5"; then
|
||||
"${OLLAMA_URL}" "${OLLAMA_MODEL}" "${EMBEDDING_MODEL}" "${WORKFLOW_FILE}"; then
|
||||
info "Step 10 OK: n8n RAG workflow setup completed successfully"
|
||||
else
|
||||
warn "Step 10: n8n workflow setup failed - manual setup may be required"
|
||||
|
||||
@@ -618,9 +618,9 @@ n8n_api_cleanup() {
|
||||
pct exec "$ctid" -- bash -c "rm -f /tmp/n8n_cookies.txt /tmp/rag_workflow.json" 2>/dev/null || true
|
||||
}
|
||||
|
||||
# Full n8n setup: Create credentials, import workflow, activate
|
||||
# Full n8n setup: Create credentials, import workflow from file, activate
|
||||
# This version runs all API calls in a single shell session to preserve cookies
|
||||
# Usage: n8n_setup_rag_workflow <ctid> <email> <password> <pg_host> <pg_port> <pg_db> <pg_user> <pg_pass> <ollama_url> [ollama_model] [embedding_model]
|
||||
# Usage: n8n_setup_rag_workflow <ctid> <email> <password> <pg_host> <pg_port> <pg_db> <pg_user> <pg_pass> <ollama_url> <ollama_model> <embedding_model> <workflow_file>
|
||||
# Returns: 0 on success, 1 on failure
|
||||
n8n_setup_rag_workflow() {
|
||||
local ctid="$1"
|
||||
@@ -632,11 +632,23 @@ n8n_setup_rag_workflow() {
|
||||
local pg_user="$7"
|
||||
local pg_pass="$8"
|
||||
local ollama_url="$9"
|
||||
local ollama_model="${10:-llama3.2:3b}"
|
||||
local embedding_model="${11:-nomic-embed-text:v1.5}"
|
||||
local ollama_model="${10:-ministral-3:3b}"
|
||||
local embedding_model="${11:-nomic-embed-text:latest}"
|
||||
local workflow_file="${12:-}"
|
||||
|
||||
info "n8n Setup: Starting RAG workflow setup..."
|
||||
|
||||
# Validate workflow file
|
||||
if [[ -z "$workflow_file" ]]; then
|
||||
warn "n8n Setup: No workflow file specified, using built-in template"
|
||||
workflow_file=""
|
||||
elif [[ ! -f "$workflow_file" ]]; then
|
||||
warn "n8n Setup: Workflow file not found: $workflow_file"
|
||||
return 1
|
||||
else
|
||||
info "n8n Setup: Using workflow file: $workflow_file"
|
||||
fi
|
||||
|
||||
# Wait for n8n to be ready
|
||||
info "n8n Setup: Waiting for n8n to be ready..."
|
||||
local i
|
||||
@@ -654,12 +666,20 @@ n8n_setup_rag_workflow() {
|
||||
local escaped_pg_pass
|
||||
escaped_pg_pass=$(echo "$pg_pass" | sed 's/\\/\\\\/g; s/"/\\"/g')
|
||||
|
||||
# Generate workflow JSON with placeholder credential IDs (will be replaced in container)
|
||||
info "n8n Setup: Generating workflow JSON..."
|
||||
# Read workflow from file or generate from template
|
||||
info "n8n Setup: Preparing workflow JSON..."
|
||||
local workflow_json
|
||||
workflow_json=$(n8n_generate_rag_workflow_json "POSTGRES_CRED_ID" "PostgreSQL (local)" "OLLAMA_CRED_ID" "Ollama (local)" "$ollama_model" "$embedding_model")
|
||||
if [[ -n "$workflow_file" && -f "$workflow_file" ]]; then
|
||||
# Read workflow from external file
|
||||
workflow_json=$(cat "$workflow_file")
|
||||
info "n8n Setup: Loaded workflow from file: $workflow_file"
|
||||
else
|
||||
# Generate workflow from built-in template
|
||||
workflow_json=$(n8n_generate_rag_workflow_json "POSTGRES_CRED_ID" "PostgreSQL (local)" "OLLAMA_CRED_ID" "Ollama (local)" "$ollama_model" "$embedding_model")
|
||||
info "n8n Setup: Generated workflow from built-in template"
|
||||
fi
|
||||
|
||||
# Push workflow JSON to container
|
||||
# Push workflow JSON to container (will be processed by setup script)
|
||||
pct_push_text "$ctid" "/tmp/rag_workflow_template.json" "$workflow_json"
|
||||
|
||||
# Create a setup script that runs all API calls in one session
|
||||
@@ -731,9 +751,54 @@ if [ -z "\$OLLAMA_CRED_ID" ]; then
|
||||
fi
|
||||
echo "Ollama credential created: \$OLLAMA_CRED_ID"
|
||||
|
||||
# Replace placeholder IDs in workflow JSON
|
||||
# Process workflow JSON: replace credential IDs and clean up
|
||||
echo "Preparing workflow JSON..."
|
||||
sed -e "s/POSTGRES_CRED_ID/\$PG_CRED_ID/g" -e "s/OLLAMA_CRED_ID/\$OLLAMA_CRED_ID/g" /tmp/rag_workflow_template.json > /tmp/rag_workflow.json
|
||||
|
||||
# Create a Python script to process the workflow JSON
|
||||
cat > /tmp/process_workflow.py << 'PYTHON_SCRIPT'
|
||||
import json
|
||||
import sys
|
||||
|
||||
# Read the workflow template
|
||||
with open('/tmp/rag_workflow_template.json', 'r') as f:
|
||||
workflow = json.load(f)
|
||||
|
||||
# Get credential IDs from environment/arguments
|
||||
pg_cred_id = sys.argv[1]
|
||||
ollama_cred_id = sys.argv[2]
|
||||
|
||||
# Remove fields that should not be in the import
|
||||
fields_to_remove = ['id', 'versionId', 'meta', 'tags', 'active', 'pinData']
|
||||
for field in fields_to_remove:
|
||||
workflow.pop(field, None)
|
||||
|
||||
# Process all nodes and replace credential IDs
|
||||
for node in workflow.get('nodes', []):
|
||||
credentials = node.get('credentials', {})
|
||||
|
||||
# Replace PostgreSQL credential
|
||||
if 'postgres' in credentials:
|
||||
credentials['postgres'] = {
|
||||
'id': pg_cred_id,
|
||||
'name': 'PostgreSQL (local)'
|
||||
}
|
||||
|
||||
# Replace Ollama credential
|
||||
if 'ollamaApi' in credentials:
|
||||
credentials['ollamaApi'] = {
|
||||
'id': ollama_cred_id,
|
||||
'name': 'Ollama (local)'
|
||||
}
|
||||
|
||||
# Write the processed workflow
|
||||
with open('/tmp/rag_workflow.json', 'w') as f:
|
||||
json.dump(workflow, f)
|
||||
|
||||
print("Workflow processed successfully")
|
||||
PYTHON_SCRIPT
|
||||
|
||||
# Run the Python script to process the workflow
|
||||
python3 /tmp/process_workflow.py "\$PG_CRED_ID" "\$OLLAMA_CRED_ID"
|
||||
|
||||
# Import workflow
|
||||
echo "Importing workflow..."
|
||||
|
||||
Reference in New Issue
Block a user