This workflow follows the HTTP Request → OpenAI recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "Busca Produtos - Query Expansion + Rerank IA",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "busca-produtos",
"responseMode": "responseNode",
"options": {}
},
"name": "Webhook - Receber Carrinho",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [
240,
300
]
},
{
"parameters": {
"mode": "jsonata",
"jsonataExpression": "carrinho"
},
"name": "Loop Items - Cada Produto",
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 1,
"position": [
460,
300
]
},
{
"parameters": {
"model": "gpt-3.5-turbo",
"messages": {
"values": [
{
"content": "=Voc\u00ea receber\u00e1 um termo de busca e sua tarefa \u00e9 gerar 15 varia\u00e7\u00f5es que se assemelhem \u00e0 linguagem de cat\u00e1logo.\n\nProduto: \"{{ $json.produto }}\"\nMarca: \"{{ $json.marca || 'n\u00e3o fornecida' }}\"\n\nRegras:\n- Gere 15 varia\u00e7\u00f5es por produto\n- Priorize sin\u00f4nimos, abrevia\u00e7\u00f5es e jarg\u00f5es\n Exemplo: \"cotonete\" -> \"HASTES FLEXIVEIS\"\n Exemplo: \"macaxeira\" -> \"AIPIM\", \"MANDIOCA\"\n- Varia\u00e7\u00f5es em MAI\u00daSCULAS\n- N\u00c3O adicione tipos espec\u00edficos\n \u274c Errado: laranja -> LARANJA PERA\n \u2705 Certo: laranja -> FRUTA LARANJA, CITRUS\n- Se marca fornecida, inclua nas varia\u00e7\u00f5es\n\nRetorne APENAS array JSON:\n[\"VARIA\u00c7\u00c3O 1\", \"VARIA\u00c7\u00c3O 2\", ...]"
}
]
},
"options": {
"temperature": 0.7,
"maxTokens": 150
}
},
"name": "OpenAI - Expandir Query",
"type": "n8n-nodes-base.openAi",
"typeVersion": 1,
"position": [
680,
300
],
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"functionCode": "// Parsear resposta OpenAI\nconst resposta = $input.item.json.message?.content || '[]';\nlet queries = [];\n\ntry {\n // Tentar extrair array JSON\n const match = resposta.match(/\\[.*\\]/s);\n if (match) {\n queries = JSON.parse(match[0]);\n }\n} catch (e) {\n // Fallback: usar query original\n queries = [$input.item.json.produto.toUpperCase()];\n}\n\n// Garantir que temos queries\nif (queries.length === 0) {\n queries = [$input.item.json.produto.toUpperCase()];\n}\n\n// Adicionar query original se n\u00e3o estiver na lista\nconst original = $input.item.json.produto.toUpperCase();\nif (!queries.includes(original)) {\n queries.unshift(original);\n}\n\nreturn {\n json: {\n produto_original: $input.item.json.produto,\n marca_original: $input.item.json.marca,\n queries_expandidas: queries\n }\n};"
},
"name": "Code - Parse Expans\u00e3o",
"type": "n8n-nodes-base.function",
"typeVersion": 1,
"position": [
900,
300
]
},
{
"parameters": {
"method": "POST",
"url": "http://localhost:3003/batch-search",
"jsonParameters": true,
"options": {
"timeout": 30000
},
"bodyParametersJson": "={\n \"queries\": {{ $json.queries_expandidas.map(q => ({ query: q, produto_original: $json.produto_original })) }},\n \"loja\": {{ $node[\"Webhook - Receber Carrinho\"].json.loja }},\n \"limit\": 20,\n \"incluir_sem_estoque\": false\n}"
},
"name": "HTTP - Batch Search Qdrant",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 1,
"position": [
1120,
300
]
},
{
"parameters": {
"functionCode": "// Agregar todos os produtos das queries expandidas\nconst resultados = $input.item.json.resultados || [];\nconst produtosUnicos = new Map();\n\n// Coletar todos os produtos\nfor (const resultado of resultados) {\n for (const produto of resultado.produtos || []) {\n // Deduplic por ID, mantendo o de maior score\n const existing = produtosUnicos.get(produto.id);\n if (!existing || produto.score > existing.score) {\n produtosUnicos.set(produto.id, produto);\n }\n }\n}\n\n// Converter para array e ordenar por score\nconst produtosArray = Array.from(produtosUnicos.values());\nprodutosArray.sort((a, b) => b.score - a.score);\n\nreturn {\n json: {\n produto_original: $input.item.json.produto_original,\n marca_original: $input.item.json.marca_original,\n total_candidatos: produtosArray.length,\n candidatos: produtosArray\n }\n};"
},
"name": "Code - Agregar Resultados",
"type": "n8n-nodes-base.function",
"typeVersion": 1,
"position": [
1340,
300
]
},
{
"parameters": {
"model": "gpt-3.5-turbo",
"messages": {
"values": [
{
"content": "=Voc\u00ea receber\u00e1 um produto solicitado e uma lista de op\u00e7\u00f5es. Identifique os 5 produtos mais relevantes.\n\n<pedido do usu\u00e1rio>\nProduto: {{ $json.produto_original }}\n{{ $json.marca_original ? `Marca: ${$json.marca_original}` : '' }}\n</pedido do usu\u00e1rio>\n\n<op\u00e7\u00f5es encontradas>\n{{ $json.candidatos.map((p, i) => `${i+1}. ${p.nome} - ${p.marca || 'Sem marca'} (R$ ${p.preco_final?.toFixed(2) || '?'}, estoque: ${p.estoque_total || 0})`).join('\\n') }}\n</op\u00e7\u00f5es encontradas>\n\nIMPORTANTE:\n- Considere sin\u00f4nimos e varia\u00e7\u00f5es\n- Priorize nome mais pr\u00f3ximo\n- Considere marca se mencionada \n- Priorize mais estoque e menor pre\u00e7o quando relev\u00e2ncia igual\n\nRetorne APENAS array JSON com n\u00fameros dos 5 melhores:\n[1, 5, 8, 12, 15]"
}
]
},
"options": {
"temperature": 0.3,
"maxTokens": 100
}
},
"name": "OpenAI - Rerank com LLM",
"type": "n8n-nodes-base.openAi",
"typeVersion": 1,
"position": [
1560,
300
],
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"functionCode": "// Extrair top 5 usando \u00edndices do LLM\nconst candidatos = $input.item.json.candidatos || [];\nconst respostaLLM = $input.item.json.message?.content || '[]';\n\nlet indices = [];\ntry {\n const match = respostaLLM.match(/\\[(\\d+(?:,\\s*\\d+)*)\\]/);\n if (match) {\n indices = match[1].split(',').map(n => parseInt(n.trim()));\n }\n} catch (e) {\n console.log('Erro parse rerank:', e.message);\n}\n\n// Fallback: se n\u00e3o conseguiu parsear, pegar os 5 primeiros\nif (indices.length === 0) {\n indices = [1, 2, 3, 4, 5];\n}\n\n// Converter \u00edndices (1-based) para produtos\nconst topProdutos = indices\n .slice(0, 5) // Garantir no m\u00e1ximo 5\n .map(idx => candidatos[idx - 1])\n .filter(p => p !== undefined);\n\nreturn {\n json: {\n produto_original: $input.item.json.produto_original,\n marca_original: $input.item.json.marca_original,\n total_encontrados: candidatos.length,\n top_5: topProdutos\n }\n};"
},
"name": "Code - Extrair Top 5",
"type": "n8n-nodes-base.function",
"typeVersion": 1,
"position": [
1780,
300
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ \n {\n success: true,\n loja: $node['Webhook - Receber Carrinho'].json.loja,\n total_itens_carrinho: $node['Webhook - Receber Carrinho'].json.carrinho.length,\n resultados: $items().map(item => item.json)\n }\n}}"
},
"name": "Respond to Webhook",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
2000,
300
]
}
],
"connections": {
"Webhook - Receber Carrinho": {
"main": [
[
{
"node": "Loop Items - Cada Produto",
"type": "main",
"index": 0
}
]
]
},
"Loop Items - Cada Produto": {
"main": [
[
{
"node": "OpenAI - Expandir Query",
"type": "main",
"index": 0
}
]
]
},
"OpenAI - Expandir Query": {
"main": [
[
{
"node": "Code - Parse Expans\u00e3o",
"type": "main",
"index": 0
}
]
]
},
"Code - Parse Expans\u00e3o": {
"main": [
[
{
"node": "HTTP - Batch Search Qdrant",
"type": "main",
"index": 0
}
]
]
},
"HTTP - Batch Search Qdrant": {
"main": [
[
{
"node": "Code - Agregar Resultados",
"type": "main",
"index": 0
}
]
]
},
"Code - Agregar Resultados": {
"main": [
[
{
"node": "OpenAI - Rerank com LLM",
"type": "main",
"index": 0
}
]
]
},
"OpenAI - Rerank com LLM": {
"main": [
[
{
"node": "Code - Extrair Top 5",
"type": "main",
"index": 0
}
]
]
},
"Code - Extrair Top 5": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {},
"staticData": null,
"tags": []
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
openAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Busca Produtos - Query Expansion + Rerank IA. Uses openAi, httpRequest. Webhook trigger; 9 nodes.
Source: https://github.com/PortfoliodoEdu/apioracle/blob/72ebb318f01174772ade0940a640876917b75ef4/embedding-pipeline/n8n-workflow-template.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This powerful n8n automation workflow is designed to execute advanced B2B lead enrichment and hyper-personalization for cold email outreach. By orchestrating a complex chain of data scraping, AI analy
Eu Clara – Funil Kiwify Completo. Uses postgres, openAi, httpRequest, gmail. Webhook trigger; 70 nodes.
This workflow bridges the gap between raw product data and revenue sales tools. It automates the entire Product Qualified Lead (PQL) lifecycle—from real-time intent routing to churn prevention—reducin
Lua Nova - Sistema Completo. Uses postgres, httpRequest, openAi. Webhook trigger; 55 nodes.
User Signup & Verification: The workflow starts when a user signs up. It generates a verification code and sends it via SMS using Twilio. Code Validation: The user replies with the code. The workflow