Skip to content

Latest commit

 

History

History
85 lines (52 loc) · 5.22 KB

File metadata and controls

85 lines (52 loc) · 5.22 KB

secop-intel

Inteligencia de contratación pública colombiana. Filtra, mide y resume los contratos del Estado por sector y región, desde la API abierta de datos.gov.co, y entrega un brief listo para un equipo comercial.


La necesidad

Una empresa que le vende al Estado vive de una pregunta: ¿qué se está contratando en mi sector y mi región, por cuánto, y quién lo está ganando?

Hoy esa respuesta está en SECOP, el sistema de contratación pública. Los datos son abiertos, pero el portal está hecho para consultar un contrato a la vez, no para leer un mercado. Un equipo comercial que quiera saber "cómo viene la contratación de salud en Córdoba este trimestre" tiene que:

  • entrar a buscar contrato por contrato,
  • copiar valores a una hoja de cálculo,
  • intentar sacar totales, promedios y quién repite como proveedor,
  • y hacerlo de nuevo la semana siguiente porque la data cambió.

Es trabajo manual, lento y se hace mal. El resultado: la empresa se entera tarde de las licitaciones y no tiene una lectura de precios de referencia para cotizar. El dolor no es la falta de datos. Es que los datos crudos no son inteligencia.

Por qué esta solución

La data ya existe y es pública. Lo que falta es la capa que la convierte en una lectura accionable. Por eso secop-intel no es otra base de datos ni otro dashboard genérico: es un agente de lectura que toma la pregunta del comercial (sector, región, fecha) y devuelve las cifras que importan más un brief en lenguaje natural.

Decisiones que definen el alcance:

  • No reemplazamos a SECOP, lo leemos. Consumimos su API, no copiamos su data. La fuente sigue siendo la oficial.
  • Cifras primero, narrativa después. El valor para el comercial son los números correctos. La prosa solo los explica.
  • CLI antes que UI. El primer usuario corre esto en su terminal o en un cron a las 7am. Una interfaz web es peso muerto hasta validar que el brief sirve.

Por qué esta arquitectura

El diseño responde a un riesgo concreto: un brief comercial con un número inventado es peor que no tener brief. Si el equipo cotiza sobre una cifra alucinada, pierde plata. Toda la arquitectura se ordena alrededor de evitar eso.

SECOP API (SODA)  →  client  →  models  →  analytics  →  brief  →  CLI
 datos.gov.co      consulta    tipado     cifras       narra     entrega
                               y limpia   (código)     (LLM)

Separación dura entre el número y la palabra. Las cifras (totales, promedios, mediana, proveedor dominante, contratos atípicos) se calculan en analytics.py, código determinista y testeado. El LLM en brief.py recibe esas cifras ya calculadas y tiene una sola tarea: redactarlas. La regla está en el prompt y en el diseño: usa solo los números que te paso, no inventes ninguna cifra. El LLM narra, no calcula. Así una alucinación no puede cambiar un valor de contrato.

El LLM es opcional. Sin OPENAI_API_KEY el comando funciona igual y entrega las cifras en plantilla. La inteligencia base es determinista; la IA es una capa de comodidad, no el núcleo. Esto también hace el CI verde sin secretos.

El prompt vive en un archivo de texto, no en el código. prompts/brief_es.txt se edita sin tocar Python, y SECOP_BRIEF_PROMPT_PATH permite apuntar a otro. El comportamiento del narrador es un parámetro, no una constante compilada.

Por capas pequeñas y aburridas. client solo habla con la API. models solo tipa y limpia la fila cruda (los valores vienen como string, las pyme como "Si"/"No"). analytics solo calcula sobre objetos limpios, sin red, por eso se testea en milisegundos. Cada pieza se entiende y se reemplaza sola.

Trade-offs asumidos

  • Snapshot, no streaming. Cada corrida es una foto del momento. Para alertas se programa el comando watch en cron; no montamos infraestructura de eventos para un primer usuario.
  • Detección de atípicos simple (z-score). Un contrato con valor muy por encima del promedio se marca. No es detección de fraude, es una señal para mirar. Suficiente para un brief, honesto sobre lo que es.
  • Filtro por texto sobre la API. Filtramos con like sobre departamento/sector. La data del Estado tiene inconsistencias de mayúsculas y tildes; por eso normalizamos con upper(). No prometemos exactitud perfecta sobre data sucia ajena.

Instalación

pip install -e ".[dev]"

Uso

# Brief de un sector y región
secop-intel brief --departamento Córdoba --sector salud --since 2026-01-01

# Filtrar por categoría UNSPSC
secop-intel brief --categoria V1.80111600 --limit 500

# Contratos nuevos desde una fecha (para cron)
secop-intel watch 2026-06-01 --departamento Córdoba

El brief usa OPENAI_API_KEY si está presente; sin ella, entrega las cifras en plantilla. Para narrar con otro prompt: edita prompts/brief_es.txt o exporta SECOP_BRIEF_PROMPT_PATH.

Stack

Python 3.12 · httpx · Pydantic v2 · typer + rich · pytest · ruff · GitHub Actions. Los tests son deterministas y no tocan la red.

Fuente

SECOP II, contratos electrónicos — datos.gov.co (Socrata Open Data API).

Autor

Jotive · dev.jotive.com.co