CultivaBase β€” Xata Serverless

Base de conocimiento IA de CULTIVA IA Β· PostgreSQL + Elasticsearch + Vectores en una sola API

βœ“ ProducciΓ³n
Capacidades activas
πŸ—„οΈ CRUD Tipado (TypeScript)
🧠 Búsqueda Vectorial (1536 dims)
πŸ€– RAG integrado (.ask())
🌿 Branching de Esquemas (tipo git)
Schema Xata β€” .xata/schema.json

πŸ“‹ tabla: skills

titlestring
contenttext
serviciolink β†’ servicios
tagsmultiple
publishedbool
publishedAtdatetime
embeddingvector[1536]
coverfile

❓ tabla: faqs

questionstring
answertext
categoriastring
helpfulbool
createdAtdatetime
embeddingvector[1536]

tabla: servicios
namestring
slugstring
colorstring
CRUD Tipado β€” src/lib/cultivabase.ts
src/lib/cultivabase.ts TypeScript
// CultivaBase β€” Cliente Xata para gestiΓ³n del catΓ‘logo de skills
import { getXataClient } from "./xata";

const xata = getXataClient();

// ─────────────────────────────────────────────────────────────
// CRUD β€” Crear / Leer / Actualizar / Eliminar skills
// ─────────────────────────────────────────────────────────────

export async function createSkill(data: {
  title: string;
  content: string;
  servicioId: string;
  tags: string[];
  embedding: number[];   // generado con OpenAI text-embedding-3-small
}) {
  return await xata.db.skills.create({
    title:     data.title,
    content:   data.content,
    servicio:  data.servicioId,   // enlace a tabla servicios
    tags:      data.tags,
    embedding: data.embedding,
    published: false,
  });
}

export async function getPublishedSkills(page = 1) {
  const results = await xata.db.skills
    .filter({ published: true })
    .sort("publishedAt", "desc")
    .select(["title", "tags", "publishedAt", "servicio.name"])
    .getPaginated({ pagination: { size: 20, offset: (page - 1) * 20 } });

  return {
    skills:   results.records,
    hasMore:  results.hasNextPage(),
    total:    results.totalCount,
  };
}

export async function publishSkill(id: string) {
  await xata.db.skills.update(id, {
    published:   true,
    publishedAt: new Date(),
  });
}
src/lib/search.ts TypeScript
// ─────────────────────────────────────────────────────────────
// BÚSQUEDA FULL-TEXT con highlight (dashboard buscador)
// ─────────────────────────────────────────────────────────────

export async function searchSkills(query: string, servicio?: string) {
  const results = await xata.db.skills.search(query, {
    target:     ["title", "content"],
    fuzziness:  1,               // tolerar 1 typo
    prefix:     "phrase",        // autocomplete
    filter:     {
      published: true,
      ...(servicio && { "servicio.name": servicio }),
    },
    highlight:  { enabled: true },
    page:       { size: 10 },
  });

  return results.records.map((r) => ({
    id:       r.id,
    title:    r.title,
    snippet:  r.getMetadata().highlight?.content ?? r.content?.slice(0, 200),
    score:    r.getMetadata().score,
    tags:     r.tags,
  }));
}

// ─────────────────────────────────────────────────────────────
// BÚSQUEDA VECTORIAL β€” "Skills parecidas" / Recomendaciones
// ─────────────────────────────────────────────────────────────

export async function findSimilarSkills(skillId: string, top = 5) {
  const skill = await xata.db.skills.read(skillId);
  if (!skill?.embedding) return [];

  const similar = await xata.db.skills.vectorSearch(
    "embedding",
    skill.embedding,
    {
      size:   top,
      filter: {
        published: true,
        id: { $isNot: skillId },
      },
    }
  );

  return similar.records;
}

// ─────────────────────────────────────────────────────────────
// RAG INTEGRADO β€” Chatbot "ΒΏQuΓ© skill necesito?"
// ─────────────────────────────────────────────────────────────

export async function askSkill(question: string) {
  const result = await xata.db.skills.ask(question, {
    searchType: "hybrid",         // keyword + vector a la vez
    rules: [
      "Responde sΓ³lo con skills del catΓ‘logo CULTIVA IA",
      "Indica el servicio al que pertenece cada skill",
      "Si hay varias opciones, lista las 3 mΓ‘s relevantes",
      "Responde en espaΓ±ol y en menos de 4 oraciones",
    ],
  });

  return {
    answer:  result.answer,
    sources: result.records.map((r) => ({ id: r.id, title: r.title })),
  };
}
Demo β€” Resultados de bΓΊsqueda: "automatizacion email"
β†’ xata.db.skills.search("automatizacion email", { target: ["title","content"], fuzziness: 1, highlight: { enabled: true } })
0.97 Secuencias de email con automatizacion y IA β€” workflows de nurturing para agencias AutomatizaciΓ³n
0.89 Cold email B2B: estructura, personalizaciΓ³n con datos y envΓ­o automatizado Marketing
0.82 Churn prevention: emails de retenciΓ³n disparados por eventos de comportamiento AutomatizaciΓ³n
0.74 Newsletter strategy: calendario editorial, segmentaciΓ³n y mΓ©tricas de apertura Contenido
0.68 Shopify email flows: abandoned cart, post-compra y reactivaciΓ³n automΓ‘tica Web
Demo β€” Chatbot RAG: askSkill("ΒΏcΓ³mo puedo generar leads con contenido?")
Respuesta generada por .ask() β€” hybrid search + LLM RAG Output
πŸ’¬ Pregunta:  ΒΏcΓ³mo puedo generar leads con contenido?

πŸ€– Respuesta: Para generar leads con contenido en CULTIVA IA hay tres skills clave:
   (1) lead-magnets (Marketing) β€” crea recursos descargables de alto valor para capturar emails;
   (2) free-tool-strategy (Marketing) β€” herramientas gratuitas que posicionan y convierten;
   (3) content-strategy (Contenido) β€” estrategia editorial alineada con el buyer journey.
   Combina las tres para un funnel de atracciΓ³n completo.

πŸ“š Fuentes usadas:
   β€’ rec_xyz001 β€” "Lead Magnets: recursos de valor para captura de emails"
   β€’ rec_xyz002 β€” "Free Tool Strategy: herramientas gratuitas como canal de adquisiciΓ³n"
   β€’ rec_xyz003 β€” "Content Strategy: editorial alineada con el funnel de ventas"
Branching de esquemas β€” flujo git-style
🌿
main
esquema estable
β†’
πŸ”€
branch create
staging
β†’
πŸ› οΈ
schema edit
aΓ±adir "views"
β†’
βœ…
test en staging
sin romper prod
β†’
πŸš€
branch merge
β†’ main
main ── v1.0 (skills + faqs + servicios)
staging ── + columna "views" en skills
main ── v1.1 (merge staging: views aΓ±adidas)