<p align="center">
  <img src="docs/img/1.png" alt="qry-doc" width="600">
</p>

# qry-doc

<p align="center">
  <strong>Motor de análisis generativo para consultas en lenguaje natural</strong>
</p>

<p align="center">
  <a href="#instalación">Instalación</a> •
  <a href="#inicio-rápido">Inicio Rápido</a> •
  <a href="#características">Características</a> •
  <a href="#ejemplos">Ejemplos</a> •
  <a href="#api">API</a> •
  <a href="#contribuir">Contribuir</a>
</p>

---

**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.

```python
from qry_doc import QryDoc
from pandasai.llm import OpenAI

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

# 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
- 🔒 **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)

```bash
uv add qry-doc
```

### Con pip

```bash
pip install qry-doc
```

### Desde código fuente

```bash
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](https://pandas-ai.com/) como motor de IA. Necesitas configurar un proveedor LLM:

```python
from pandasai.llm import OpenAI

# Opción 1: API key como parámetro
llm = OpenAI(api_token="sk-...")

# Opción 2: Variable de entorno OPENAI_API_KEY
llm = OpenAI()
```

**Proveedores soportados:**
- OpenAI (GPT-4, GPT-3.5)
- Anthropic (Claude)
- Google (Gemini)
- Azure OpenAI
- LiteLLM (cualquier modelo)

### 2. Carga tus datos

```python
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

```python
# 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

```python
from qry_doc import QryDoc
from pandasai.llm import OpenAI

qry = QryDoc("clientes.csv", llm=OpenAI())

# 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

```python
from qry_doc import QryDoc, ReportTemplate
from pandasai.llm import OpenAI

qry = QryDoc("ventas_2024.csv", llm=OpenAI())

# 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
)
```

### Templates predefinidos

```python
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

```python
from qry_doc import QryDoc
from pandasai.llm import OpenAI

# Limpieza automática de archivos temporales
with QryDoc("datos.csv", llm=OpenAI()) 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

```python
qry = QryDoc("datos.csv", llm=OpenAI())

# 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.

```python
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.

```python
ReportTemplate(
    logo_path: Path | None = None,      # Ruta al logo
    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
)
```

### 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

```python
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](https://docs.astral.sh/uv/) (gestor de paquetes)

### Setup

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

### Tests

```bash
# 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
│   ├── validators.py        # Validación y sanitización
│   └── exceptions.py        # Jerarquía de excepciones
├── 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

MIT License - ver [LICENSE](LICENSE) para más detalles.

---

<p align="center">
  Hecho con ❤️ por <a href="https://github.com/danro-dev">danro-dev</a>
</p>
