📐 Arquitectura — Caso 12: 🧠 Python (LLM) → 🌉 n8n → ⚡ FastAPI RAG + pgvector#
Emisor Python que reenvía a n8n; el receptor FastAPI embebe cada post e indexa el vector en pgvector, exponiendo búsqueda semántica por similitud coseno (
/search) — el paso retrieval de un pipeline RAG.
🧭 Ficha técnica#
| Atributo | Valor |
|---|---|
| ID | 12 |
| Origen | Python 3.11 — origin/bot.py |
| Puente | n8n — case-12-python-to-rag.json |
| Destino | FastAPI — dest/main.py |
| Persistencia | pgvector (PostgreSQL 16, vector(256)) |
| Puerto (dashboard) | http://localhost:8092 |
| Perfil Docker | case12 |
🗺️ Diagrama de arquitectura#
diagrama mermaid
%%{init: {'theme':'base','themeVariables':{'fontSize':'26px','fontFamily':'Segoe UI, Arial, sans-serif'},'flowchart':{'useMaxWidth':true,'htmlLabels':false,'nodeSpacing':55,'rankSpacing':70,'padding':16,'diagramPadding':16}}%%
flowchart TB
subgraph ORIGIN["ORIGEN - Python"]
B["bot.py"]
end
subgraph BRIDGE["PUENTE - n8n + Guardrails"]
C(["Webhook"]) --> IDEM{"Idempotencia + circuit breaker"}
IDEM -->|nuevo| FWD["HTTP forward + reintentos"]
FWD -.->|error| DLQ["Dead Letter Queue (/errors)"]
end
subgraph DEST["DESTINO - FastAPI RAG"]
FWD --> API["main.py"]
API --> EMB["embed() 256d"]
EMB --> DB[("pgvector")]
DB --> SRCH["/search (coseno <=>)"]
DB --> DASH["Dashboard :8092"]
end
B -->|POST JSON| C
classDef origin fill:#3776AB,stroke:#333,color:#fff
classDef bridge fill:#EA4B71,stroke:#333,color:#fff
classDef dest fill:#009688,stroke:#333,color:#fff
classDef db fill:#336791,stroke:#333,color:#fff
class B origin
class C,IDEM,FWD,DLQ bridge
class API,EMB,SRCH,DASH dest
class DB db🔁 Diagrama de secuencia (ingesta + retrieval)#
diagrama mermaid
%%{init: {'theme':'base','themeVariables':{'fontSize':'24px','fontFamily':'Segoe UI, Arial, sans-serif'},'sequence':{'useMaxWidth':true,'actorFontSize':22,'messageFontSize':20,'noteFontSize':18,'actorMargin':90,'boxMargin':16,'width':180}}}%%
sequenceDiagram
autonumber
participant Bot as bot.py (Python)
participant N8N as n8n
participant API as FastAPI
participant PV as pgvector
Bot->>N8N: POST /webhook (post vencido)
N8N->>N8N: Circuit breaker + idempotencia
N8N->>API: HTTP POST /webhook (reintentos x3)
API->>API: embed(text) -> vector 256d
API->>PV: INSERT ... embedding (ON CONFLICT)
PV-->>API: OK
API-->>N8N: 200 OK
Note over API,PV: GET /search?q=... -> ORDER BY embedding <=> q LIMIT k (retrieval)🧩 Componentes#
🧠 Origen — Python#
origin/bot.pyreenvía los posts vencidos a n8n con la stdlib (urllib), sin dependencias.
🌉 Puente — n8n#
- Guardrails canónicos: fingerprint → circuit breaker → idempotencia → HTTP forward con reintentos → DLQ.
⚡ Destino — FastAPI RAG + pgvector#
dest/main.pyembebe el texto (hashing determinista 256d) y lo indexa en pgvector./searchhace retrieval por coseno;/logslista los últimos posts.- La función de embedding es un punto de extensión aislado (swappable por un modelo real).
▶️ Cómo levantarlo#
bash
docker-compose --profile case12 up -d # pgvector + receptor FastAPIDashboard: http://localhost:8092
🔗 Enlaces#
- 📄 README del caso
- 🗺️ Arquitectura global del laboratorio
- 🛡️ Guardrails de resiliencia
- 🧩 Índice de casos
Diagramas en Mermaid — se renderizan nativamente en GitHub. Parte de Social Bot Scheduler.