Skip to content
danro-devPublic

About

Motor de análisis generativo que transforma el lenguaje natural en código ejecutable, visualizaciones y reportes PDF profesionales. Simplificación radical de la interacción con CSVs y SQL.

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

qry-doc

qry-doc

Motor de análisis generativo para consultas en lenguaje natural

Instalación

Inicio Rápido

Características

Ejemplos

API

Contribuir


qry-doc transforma el lenguaje natural en código ejecutable, visualizaciones y reportes PDF profesionales. Simplifica radicalmente la interacción con archivos CSV y bases de datos SQL.

from qry_doc import QryDoc, ReportTemplate
import pandasai as pai
from pandasai_openai import OpenAI

# Configurar LLM
llm = OpenAI()
pai.config.set({"llm": llm})

qry = QryDoc("ventas.csv", llm=llm)

# Pregunta en español
respuesta = qry.ask("¿Cuál fue el producto más vendido en 2024?")
print(respuesta)  # "El producto más vendido fue 'Laptop Pro' con 1,234 unidades"

# Exporta resultados a CSV
qry.extract_to_csv("Top 10 clientes por ingresos", "top_clientes.csv")

# Genera reporte PDF profesional
qry.generate_report("Análisis trimestral de ventas", "reporte_q4.pdf")

Características

  • 🗣️ Consultas en lenguaje natural - Pregunta sobre tus datos como si hablaras con un analista
  • 📊 Visualizaciones automáticas - Genera gráficos relevantes sin escribir código
  • 📄 Reportes PDF profesionales - Crea documentos con tablas, gráficos y resúmenes
  • 📁 Exportación CSV - Extrae resultados tabulares con encoding Excel-compatible
  • 🎨 Templates personalizables - Adapta el estilo de reportes a tu marca
  • 🖼️ Portadas personalizadas - Añade imágenes de portada a tus reportes
  • 🏷️ Logo en pie de página - Logo por defecto o personalizado con posición configurable
  • ✏️ Fuentes personalizadas - Soporte para fuentes TTF/OTF
  • 📑 Sistema de secciones - Controla el orden y contenido de las secciones del reporte
  • 🔒 Sanitización de errores - Protege información sensible en mensajes de error
  • 🐍 Python 3.11+ - Type hints completos y código moderno

Instalación

Con uv (recomendado)

# Instalación básica
uv add qry-doc

# Con soporte para OpenAI
uv add "qry-doc[openai]"

# Con soporte para múltiples proveedores
uv add "qry-doc[litellm]"

# Con todos los proveedores
uv add "qry-doc[all]"

Con pip

# Instalación básica
pip install qry-doc

# Con soporte para OpenAI
pip install "qry-doc[openai]"

# Con soporte para múltiples proveedores
pip install "qry-doc[litellm]"

# Con todos los proveedores
pip install "qry-doc[all]"

Desde código fuente

git clone https://github.com/danro-dev/qry-doc.git
cd qry-doc
uv sync

Inicio Rápido

1. Configura tu LLM

qry-doc utiliza PandasAI como motor de IA. Instala con el extra que necesites:

# Para OpenAI
pip install "qry-doc[openai]"

# Para múltiples proveedores
pip install "qry-doc[litellm]"
import pandasai as pai
from pandasai_openai import OpenAI

# Opción 1: API key como variable de entorno OPENAI_API_KEY
llm = OpenAI()

# Opción 2: Pasar el API key directamente
llm = OpenAI(api_token="sk-...")

# Configurar PandasAI
pai.config.set({"llm": llm})

Proveedores soportados vía LiteLLM:

  • OpenAI (GPT-4, GPT-3.5)
  • Anthropic (Claude)
  • Google (Gemini)
  • Azure OpenAI
  • Ollama (modelos locales)
  • Y muchos más...

2. Carga tus datos

from qry_doc import QryDoc
import pandas as pd

# Desde archivo CSV
qry = QryDoc("datos.csv", llm=llm)

# Desde DataFrame
df = pd.read_excel("datos.xlsx")
qry = QryDoc(df, llm=llm)

# Desde SQL (próximamente)
# qry = QryDoc("postgresql://user:pass@host/db", llm=llm)

3. Haz preguntas

# Preguntas simples
total = qry.ask("¿Cuál es el total de ventas?")

# Análisis complejos
tendencia = qry.ask("¿Cómo han evolucionado las ventas mes a mes en 2024?")

# Comparaciones
comparacion = qry.ask("Compara las ventas de Q1 vs Q2 por región")

Ejemplos

Exportar datos a CSV

from qry_doc import QryDoc
import pandasai as pai
from pandasai_openai import OpenAI

llm = OpenAI()
pai.config.set({"llm": llm})
qry = QryDoc("clientes.csv", llm=llm)

# Extrae datos filtrados
qry.extract_to_csv(
    "Clientes con más de 10 compras en el último año",
    "clientes_frecuentes.csv"
)

# Extrae agregaciones
qry.extract_to_csv(
    "Ventas totales por categoría de producto",
    "ventas_por_categoria.csv"
)

# Incluir índice si es necesario
qry.extract_to_csv(
    "Ranking de vendedores por comisión",
    "ranking.csv",
    include_index=True
)

Generar reportes PDF

from qry_doc import QryDoc, ReportTemplate
import pandasai as pai
from pandasai_openai import OpenAI

llm = OpenAI()
pai.config.set({"llm": llm})
qry = QryDoc("ventas_2024.csv", llm=llm)

# Reporte con template por defecto
qry.generate_report(
    "Análisis de rendimiento del equipo de ventas",
    "reporte_ventas.pdf"
)

# Reporte con template personalizado
template = ReportTemplate(
    logo_path="mi_logo.png",
    primary_color="#003366",
    title_font="Helvetica-Bold",
    body_font="Helvetica"
)

qry.generate_report(
    "Resumen ejecutivo Q4 2024",
    "resumen_q4.pdf",
    title="Informe Trimestral de Ventas",
    template=template
)

Reportes con portada personalizada

from qry_doc import ReportTemplate
from pathlib import Path

# Template con imagen de portada
template = ReportTemplate(
    cover_image_path=Path("mi_portada.png"),  # Imagen a página completa
    logo_path="mi_logo.png",
    primary_color="#003366"
)

qry.generate_report(
    "Análisis anual de ventas",
    "reporte_anual.pdf",
    title="Informe Anual 2024",
    template=template
)

Personalización del logo en pie de página

from qry_doc import ReportTemplate, LogoPosition

# Logo personalizado en posición específica
template = ReportTemplate(
    footer_logo_path=Path("mi_marca.png"),     # Logo personalizado (None = logo por defecto)
    footer_logo_enabled=True,                   # Activar/desactivar logo
    footer_logo_position=LogoPosition.BOTTOM_LEFT,  # BOTTOM_RIGHT, BOTTOM_LEFT, BOTTOM_CENTER
    footer_logo_width=50.0,                     # Ancho en puntos
    footer_logo_height=25.0                     # Alto en puntos
)

# Desactivar el logo del pie de página
template_sin_logo = ReportTemplate(
    footer_logo_enabled=False
)

Fuentes personalizadas (TTF/OTF)

from qry_doc import ReportTemplate
from pathlib import Path

# Usar fuentes personalizadas
template = ReportTemplate(
    custom_title_font_path=Path("fonts/Montserrat-Bold.ttf"),
    custom_body_font_path=Path("fonts/OpenSans-Regular.ttf"),
    primary_color="#1a1a2e"
)

# Si la fuente no existe o es inválida, se usa Helvetica automáticamente

Sistema de secciones personalizadas

from qry_doc import ReportTemplate, SectionType, SectionConfig

# Definir orden y contenido de secciones
sections = [
    SectionConfig(SectionType.COVER),           # Portada
    SectionConfig(SectionType.SUMMARY),         # Resumen ejecutivo
    SectionConfig(SectionType.CHART),           # Gráficos
    SectionConfig(SectionType.DATA),            # Tabla de datos
    SectionConfig(                              # Sección personalizada
        SectionType.CUSTOM,
        custom_content="Este es contenido adicional personalizado."
    ),
]

template = ReportTemplate(
    cover_image_path=Path("portada.png"),
    sections=sections
)

# Desactivar una sección específica
sections_sin_datos = [
    SectionConfig(SectionType.SUMMARY),
    SectionConfig(SectionType.CHART),
    SectionConfig(SectionType.DATA, enabled=False),  # No mostrar tabla
]

Templates predefinidos

from qry_doc import (
    DEFAULT_TEMPLATE,    # Estilo profesional estándar
    CORPORATE_TEMPLATE,  # Azul corporativo
    MINIMAL_TEMPLATE,    # Minimalista
    A4_TEMPLATE,         # Tamaño A4 (europeo)
)

qry.generate_report(
    "Análisis de mercado",
    "analisis.pdf",
    template=CORPORATE_TEMPLATE
)

Uso como context manager

from qry_doc import QryDoc
import pandasai as pai
from pandasai_openai import OpenAI

llm = OpenAI()
pai.config.set({"llm": llm})

# Limpieza automática de archivos temporales
with QryDoc("datos.csv", llm=llm) as qry:
    respuesta = qry.ask("¿Cuántos registros hay?")
    qry.generate_report("Resumen de datos", "resumen.pdf")
# Los archivos temporales se eliminan automáticamente

Acceso a datos subyacentes

import pandasai as pai
from pandasai_openai import OpenAI

llm = OpenAI()
pai.config.set({"llm": llm})
qry = QryDoc("datos.csv", llm=llm)

# Obtener el DataFrame
df = qry.dataframe

# Ver columnas disponibles
print(qry.columns)  # ['fecha', 'producto', 'cantidad', 'precio']

# Ver dimensiones
print(qry.shape)  # (1000, 4)

API

QryDoc

Clase principal que actúa como punto de entrada (Facade) para toda la funcionalidad.

QryDoc(
    data_source: str | Path | DataFrame,  # Fuente de datos
    llm: Any,                              # Proveedor LLM
    api_key: str | None = None             # API key opcional
)

Métodos:

Método Descripción Retorno
ask(query) Pregunta en lenguaje natural str
extract_to_csv(query, path, include_index=False) Exporta resultado a CSV str
generate_report(query, path, title, template) Genera reporte PDF str

Propiedades:

Propiedad Descripción Tipo
dataframe DataFrame subyacente pd.DataFrame
columns Nombres de columnas list[str]
shape Dimensiones (filas, columnas) tuple[int, int]

ReportTemplate

Configuración para personalizar el estilo de reportes PDF.

ReportTemplate(
    # Configuración básica
    logo_path: Path | None = None,      # Ruta al logo del header
    primary_color: str = "#1a1a2e",     # Color principal (hex)
    title_font: str = "Helvetica-Bold", # Fuente de títulos
    body_font: str = "Helvetica",       # Fuente de cuerpo
    page_size: tuple = letter,          # Tamaño de página
    margin_top: float = 72.0,           # Margen superior (puntos)
    margin_bottom: float = 72.0,        # Margen inferior
    margin_left: float = 72.0,          # Margen izquierdo
    margin_right: float = 72.0,         # Margen derecho
    
    # Portada (v0.2.3+)
    cover_image_path: Path | None = None,  # Imagen de portada a página completa
    
    # Logo en pie de página (v0.2.3+)
    footer_logo_path: Path | None = None,  # Logo personalizado (None = default)
    footer_logo_enabled: bool = True,      # Activar/desactivar logo
    footer_logo_position: LogoPosition = LogoPosition.BOTTOM_RIGHT,
    footer_logo_width: float = 40.0,       # Ancho en puntos
    footer_logo_height: float = 20.0,      # Alto en puntos
    
    # Fuentes personalizadas (v0.2.3+)
    custom_title_font_path: Path | None = None,  # Fuente TTF/OTF para títulos
    custom_body_font_path: Path | None = None,   # Fuente TTF/OTF para cuerpo
    
    # Secciones (v0.2.3+)
    sections: list[SectionConfig] = [],    # Lista de secciones del reporte
)

SectionType (v0.2.3+)

Enum para tipos de secciones disponibles en un reporte.

Valor Descripción
COVER Portada con imagen a página completa
SUMMARY Sección de resumen ejecutivo
DATA DataFrame renderizado como tabla
CHART Imagen de gráfico/visualización
CUSTOM Contenido personalizado arbitrario

SectionConfig (v0.2.3+)

Configuración para una sección del reporte.

SectionConfig(
    section_type: SectionType,           # Tipo de sección
    enabled: bool = True,                # Si la sección está activa
    custom_content: str | None = None,   # Contenido para secciones CUSTOM
)

LogoPosition (v0.2.3+)

Enum para posiciones del logo en el pie de página.

Valor Descripción
BOTTOM_RIGHT Esquina inferior derecha (default)
BOTTOM_LEFT Esquina inferior izquierda
BOTTOM_CENTER Centro inferior

AssetManager (v0.2.3+)

Clase para gestión de assets del paquete (uso avanzado).

from qry_doc import AssetManager

# Obtener ruta al logo por defecto del paquete
default_logo = AssetManager.get_default_logo_path()

# Validar rutas de imágenes
is_valid, error = AssetManager.validate_image_path(Path("imagen.png"))

# Validar rutas de fuentes
is_valid, error = AssetManager.validate_font_path(Path("fuente.ttf"))

Excepciones

Excepción Descripción
QryDocError Excepción base para todos los errores
QueryError Error al interpretar o ejecutar consulta
ExportError Error al exportar datos
ReportError Error al generar reporte PDF
DataSourceError Error al cargar fuente de datos
ValidationError Error de validación de salidas

Todas las excepciones incluyen:

  • user_message: Mensaje amigable para mostrar al usuario
  • internal_error: Excepción original para debugging
from qry_doc import QryDoc, QueryError

try:
    respuesta = qry.ask("consulta ambigua")
except QueryError as e:
    print(f"Error: {e.user_message}")
    # Logging interno: e.internal_error

Configuración avanzada

Variables de entorno

Variable Descripción
OPENAI_API_KEY API key de OpenAI (fallback)

Encoding de archivos

Por defecto, los CSV se exportan con encoding utf-8-sig (BOM) para compatibilidad con Excel. Esto asegura que caracteres especiales (ñ, acentos, etc.) se muestren correctamente.

Desarrollo

Requisitos

  • Python 3.11+
  • uv (gestor de paquetes)

Setup

git clone https://github.com/danro-dev/qry-doc.git
cd qry-doc
uv sync --all-extras

Tests

# Ejecutar todos los tests
uv run pytest

# Con cobertura
uv run pytest --cov=src/qry_doc --cov-report=html

# Tests específicos
uv run pytest tests/property/test_qrydoc.py -v

Estructura del proyecto

qry-doc/
├── src/qry_doc/
│   ├── __init__.py          # Exports públicos
│   ├── core.py              # QryDoc (Facade)
│   ├── ai_adapter.py        # PandasAI adapter
│   ├── data_source.py       # Carga de datos
│   ├── csv_exporter.py      # Exportación CSV
│   ├── report_generator.py  # Generación PDF
│   ├── report_template.py   # Templates de reportes
│   ├── chart_manager.py     # Gestión de gráficos
│   ├── asset_manager.py     # Gestión de assets (v0.2.3+)
│   ├── validators.py        # Validación y sanitización
│   ├── exceptions.py        # Jerarquía de excepciones
│   └── assets/              # Assets del paquete (v0.2.3+)
│       └── default_logo.png # Logo por defecto
├── tests/
│   ├── conftest.py          # Fixtures compartidos
│   └── property/            # Property-based tests
├── docs/                    # Documentación adicional
├── pyproject.toml
└── README.md

Roadmap

  • Soporte para conexiones SQL (PostgreSQL, MySQL, SQLite)
  • Caché de consultas para mejorar rendimiento
  • Exportación a Excel (.xlsx)
  • Más templates predefinidos
  • CLI para uso desde terminal
  • Integración con Jupyter notebooks

Contribuir

¡Las contribuciones son bienvenidas! Por favor:

  1. Fork el repositorio
  2. Crea una rama para tu feature (git checkout -b feature/nueva-funcionalidad)
  3. Commit tus cambios (git commit -m 'feat: agregar nueva funcionalidad')
  4. Push a la rama (git push origin feature/nueva-funcionalidad)
  5. Abre un Pull Request

Licencia

GPL-3.0 License - ver LICENSE para más detalles.


Hecho con ❤️ por danro-dev

About

Motor de análisis generativo que transforma el lenguaje natural en código ejecutable, visualizaciones y reportes PDF profesionales. Simplificación radical de la interacción con CSVs y SQL.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages