Motor de análisis generativo que transforma el lenguaje natural en código ejecutable, visualizaciones y reportes PDF profesionales.
Project description
qry-doc
Motor de análisis generativo para consultas en lenguaje natural
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 usuariointernal_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:
- Fork el repositorio
- Crea una rama para tu feature (
git checkout -b feature/nueva-funcionalidad) - Commit tus cambios (
git commit -m 'feat: agregar nueva funcionalidad') - Push a la rama (
git push origin feature/nueva-funcionalidad) - Abre un Pull Request
Licencia
MIT License - ver LICENSE para más detalles.
Hecho con ❤️ por danro-dev
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file qry_doc-0.1.3.tar.gz.
File metadata
- Download URL: qry_doc-0.1.3.tar.gz
- Upload date:
- Size: 88.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.11 {"installer":{"name":"uv","version":"0.9.11"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Linux Mint","version":"22.2","id":"zara","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
64a1e7e24a48b72f8fbe1ede387d812fc809793c3a200d3835fd21e8c23617c7
|
|
| MD5 |
3ac23ebdc9a78579215f4f681e1513ab
|
|
| BLAKE2b-256 |
ec96a4d43490464d29b19ad304af5bd4f1b9301eed913e7650478f30afc57859
|
File details
Details for the file qry_doc-0.1.3-py3-none-any.whl.
File metadata
- Download URL: qry_doc-0.1.3-py3-none-any.whl
- Upload date:
- Size: 92.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.11 {"installer":{"name":"uv","version":"0.9.11"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Linux Mint","version":"22.2","id":"zara","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e59d3b507c1c7287ae6c1a9445db3c9934c47e1f8f3a8587d973f387c6f2cefd
|
|
| MD5 |
6900cd049a330334c35ed0f7f50d58d1
|
|
| BLAKE2b-256 |
18790cafa38512cdf6f0c37664cad78ed457c4b85909213d2d12dbb7eb5e0204
|