MarianaCodebase commited on
Commit
66e9b6f
·
verified ·
1 Parent(s): b2d4035

Upload 9 files

Browse files
Files changed (9) hide show
  1. .dockerignore +9 -0
  2. .env +24 -0
  3. .env.example +57 -0
  4. .gitignore +10 -0
  5. Dockerfile +28 -0
  6. README.md +215 -7
  7. requirements.txt +7 -0
  8. server.py +13 -0
  9. sid.tmp +1 -0
.dockerignore ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ .env
2
+ .env.example
3
+ .git
4
+ __pycache__/
5
+ *.pyc
6
+ var/
7
+ *.db
8
+ data/reference/
9
+ README.md
.env ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # === Configuración local (NO se sube a git) ===
2
+
3
+ # --- Gemini (proveedor de LLM) ---
4
+ # Clave creada en https://aistudio.google.com/apikey
5
+ # PEGA AQUÍ TU CLAVE COMPLETA (empieza por AQ. o AIza)
6
+ GEMINI_API_KEY=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
7
+ GEMINI_MODEL=gemini-2.0-flash
8
+ ANTHROPIC_MODEL=claude-opus-4-8
9
+ LLM_TEMPERATURE=0.4
10
+ LLM_TIMEOUT=60
11
+
12
+ # --- Servidor ---
13
+ APP_ENV=development
14
+ PORT=8000
15
+ LOG_LEVEL=INFO
16
+ PUBLIC_BASE_URL=http://localhost:8000
17
+ SESSION_TTL_HOURS=24
18
+
19
+ # --- Correo (SMTP) para entrega real del PDF (opcional; si falta, se simula) ---
20
+ SMTP_HOST=
21
+ SMTP_PORT=587
22
+ SMTP_USER=
23
+ SMTP_PASS=
24
+ SMTP_FROM=Clara - Colsubsidio Seguros <no-reply@colsubsidio.demo>
.env.example ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copia este archivo como .env y completa los valores.
2
+ # NUNCA subas el .env real a git ni al hosting (usa secrets del entorno).
3
+
4
+ # --- Proveedor de LLM ---
5
+ # Vacío => se detecta por el prefijo de la clave (AIza=Gemini, sk-ant-=Claude).
6
+ # ollama => modelo servido por endpoint compatible con OpenAI (ver más abajo).
7
+ LLM_PROVIDER=
8
+
9
+ # --- Gemini ---
10
+ # Crea tu clave en https://aistudio.google.com/apikey
11
+ GEMINI_API_KEY=
12
+ GEMINI_MODEL=gemini-2.0-flash
13
+ LLM_TEMPERATURE=0.4
14
+ # Sube a 120 con modelos locales: la primera petición carga el modelo en memoria.
15
+ LLM_TIMEOUT=60
16
+
17
+ # --- Modelo por endpoint compatible con OpenAI (LLM_PROVIDER=ollama) ---
18
+ # Dos despliegues con el mismo código:
19
+ #
20
+ # 1) Local con Ollama (el dato no sale de la máquina):
21
+ # OLLAMA_BASE_URL=http://localhost:11434/v1
22
+ # OLLAMA_MODEL=qwen3:4b
23
+ #
24
+ # 2) Alojado en Hugging Face (no requiere GPU propia):
25
+ # OLLAMA_BASE_URL=https://router.huggingface.co/v1
26
+ # OLLAMA_MODEL=<id del modelo en el Hub>
27
+ # HF_TOKEN=hf_...
28
+ OLLAMA_BASE_URL=http://localhost:11434/v1
29
+ OLLAMA_MODEL=qwen3:4b
30
+ HF_TOKEN=
31
+
32
+ # --- Servidor ---
33
+ # development | production
34
+ APP_ENV=development
35
+ PORT=8000
36
+ LOG_LEVEL=INFO
37
+
38
+ # URL pública base para enlaces (pago y PDFs).
39
+ # Local: http://localhost:8000 · En Hugging Face Spaces se detecta sola (SPACE_HOST).
40
+ PUBLIC_BASE_URL=http://localhost:8000
41
+
42
+ # Horas de inactividad tras las cuales se purga una sesión persistida.
43
+ SESSION_TTL_HOURS=24
44
+
45
+ # --- Correo (SMTP) para entrega real del PDF (opcional; si falta, se simula) ---
46
+ # Gmail: activa verificación en 2 pasos y crea una "Contraseña de aplicación".
47
+ SMTP_HOST=
48
+ SMTP_PORT=587
49
+ SMTP_USER=
50
+ SMTP_PASS=
51
+ SMTP_FROM=Clara - Colsubsidio Seguros <no-reply@colsubsidio.demo>
52
+
53
+ # --- Twilio (opcional, WhatsApp/SMS) ---
54
+ TWILIO_ACCOUNT_SID=
55
+ TWILIO_AUTH_TOKEN=
56
+ TWILIO_WHATSAPP_FROM=whatsapp:+14155238886
57
+ TWILIO_SMS_FROM=
.gitignore ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ .env
2
+ __pycache__/
3
+ *.pyc
4
+ var/
5
+ *.db
6
+ *.db-wal
7
+ *.db-shm
8
+ sid.tmp
9
+ *.tmp
10
+ .DS_Store
Dockerfile ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Imagen de producción (compatible con Hugging Face Spaces, SDK: docker).
2
+ # El cerebro es la API de Gemini: configura GEMINI_API_KEY como secret.
3
+ FROM python:3.12-slim
4
+
5
+ # Usuario sin privilegios
6
+ RUN useradd -m -u 1000 clara
7
+ WORKDIR /app
8
+
9
+ COPY requirements.txt .
10
+ RUN pip install --no-cache-dir -r requirements.txt
11
+
12
+ COPY app ./app
13
+ COPY static ./static
14
+ COPY server.py .
15
+
16
+ # Carpeta de trabajo escribible (PDFs generados + SQLite)
17
+ RUN mkdir -p /app/var/docs && chown -R clara:clara /app/var
18
+
19
+ ENV APP_ENV=production
20
+ ENV PORT=7860
21
+
22
+ USER clara
23
+ EXPOSE 7860
24
+
25
+ HEALTHCHECK --interval=30s --timeout=5s --start-period=10s \
26
+ CMD python -c "import urllib.request,os;urllib.request.urlopen(f'http://localhost:{os.environ.get(\"PORT\",7860)}/api/health')" || exit 1
27
+
28
+ CMD ["sh", "-c", "uvicorn app.main:app --host 0.0.0.0 --port ${PORT:-7860} --workers 1"]
README.md CHANGED
@@ -1,12 +1,220 @@
1
  ---
2
- title: ClaraSeguros
3
- emoji: 💻
4
- colorFrom: blue
5
- colorTo: green
6
  sdk: docker
 
7
  pinned: false
8
- license: mit
9
- short_description: LLM CLARA
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: Clara - Seguros Colsubsidio
3
+ emoji: 🛡️
4
+ colorFrom: green
5
+ colorTo: blue
6
  sdk: docker
7
+ app_port: 7860
8
  pinned: false
9
+ short_description: Agente conversacional de venta de seguros (Reto 2 - 30X)
 
10
  ---
11
 
12
+ # Clara Venta automatizada de seguros 🛡️
13
+
14
+ **Reto 2 · Venta automatizada de seguros** — [Hackathon Colsubsidio × 30X](https://innovacion.colsubsidio.com/)
15
+ · 22–26 de julio de 2026 · Club La Colina, Bogotá.
16
+
17
+ Repositorio: [github.com/Mariana-Codebase/AgenteSeguros](https://github.com/Mariana-Codebase/AgenteSeguros)
18
+
19
+ > **El reto:** hoy adquirir un seguro en Colsubsidio depende de un asesor que
20
+ > identifique la necesidad, cotice, explique y cierre. Ese modelo no escala, no
21
+ > opera 24/7 y depende del equipo comercial. **Clara lleva al afiliado desde
22
+ > _"no sé qué seguro necesito"_ hasta _"ya quedé asegurado"_ sin un solo humano
23
+ > en el medio.**
24
+
25
+ ---
26
+
27
+ ## Qué es Clara
28
+
29
+ Clara es una **asesora digital de seguros** que conversa en lenguaje natural, en
30
+ español colombiano. En una sola conversación:
31
+
32
+ 1. **Diagnostica** la vida del afiliado con preguntas abiertas (con quién vive, si
33
+ tiene carro, moto, mascota, viajes, dependientes…).
34
+ 2. **Recomienda** el mejor producto de **todo el portafolio Colsubsidio** (14
35
+ productos), explicando por qué encaja, qué cubre y **qué NO cubre**.
36
+ 3. **Contrata**: reúne los datos, genera el **contrato en PDF**, captura la
37
+ **firma electrónica** y entrega un **enlace de pago** (checkout tipo Wompi).
38
+ 4. **Emite** la **póliza en PDF** en el instante en que el pago se aprueba y hace
39
+ post-venta (número de póliza, cómo usarla, encuesta de satisfacción).
40
+
41
+ Todo el recorrido queda en un **registro de auditoría** persistente. La demo web
42
+ muestra, en vivo y al lado del chat, **cada decisión, herramienta y escritura en
43
+ base de datos** que ocurre detrás — para que un juez vea que no hay magia: hay
44
+ arquitectura.
45
+
46
+ ---
47
+
48
+ ## Por qué Clara gana: una arquitectura en la que se puede confiar
49
+
50
+ Vender seguros con un LLM tiene un riesgo mortal: **que el modelo alucine una
51
+ cobertura, un precio o una condición**. En seguros eso no es un bug, es una
52
+ **responsabilidad legal y financiera**. Clara está diseñada, de raíz, para que
53
+ eso **no pueda pasar**:
54
+
55
+ | Principio | Cómo lo garantiza Clara |
56
+ |-----------|-------------------------|
57
+ | **El LLM solo conversa** | Gemini nunca calcula ni inventa. Solo dialoga y **llama herramientas** (function-calling). Toda la lógica dura vive en el backend. |
58
+ | **Coberturas ⇒ base de conocimiento (RAG)** | Cada afirmación de amparo/exclusión/condición sale de `consultar_coberturas`, **con cita de la fuente** (cláusula de las condiciones). |
59
+ | **Precios ⇒ motor de reglas determinístico** | Ninguna cifra la produce el modelo: salen de un motor auditable (`cotizar`) con factores por edad y dependientes. |
60
+ | **Emisión ⇒ backend, no el modelo** | Contrato, firma, pago y póliza los ejecuta el código de forma determinística; el modelo solo confirma en lenguaje natural. |
61
+ | **Guardrail de salida** | Una capa basada en reglas revisa cada respuesta: si menciona cobertura o precio sin respaldo en el turno, lo marca en la auditoría. |
62
+ | **Cumplimiento por diseño** | Aviso de tratamiento de datos (**Ley 1581 de 2012**) desde el saludo; el prompt rechaza temas fuera de alcance y resiste intentos de jailbreak. |
63
+ | **Trazabilidad total** | Cada perfil, cotización, contrato, pago y póliza se registra en SQLite y se muestra en vivo en la interfaz. |
64
+
65
+ > En una frase: **el modelo pone las palabras, el sistema pone la verdad.**
66
+
67
+ ---
68
+
69
+ ## El recorrido del afiliado
70
+
71
+ ```
72
+ Afiliado Clara (Gemini) Backend determinístico
73
+ │ │ │
74
+ │ "no sé qué necesito" │ │
75
+ ├────────────────────────▶│ diagnóstico (preguntas │
76
+ │ │ abiertas, escucha activa) │
77
+ │ ├─ registrar_perfil ──────────▶│ SQLite (perfil)
78
+ │ │ │
79
+ │ ├─ recomendar ────────────────▶│ RAG + motor de reglas
80
+ │◀── opciones con precio │◀─ coberturas + precio real ──┤
81
+ │ y exclusiones reales │ │
82
+ │ ├─ consultar_coberturas ──────▶│ RAG (cita fuente)
83
+ │ "quiero ese" │ │
84
+ │ ├─ registrar_datos ───────────▶│ SQLite (contratante)
85
+ │ ├─ generar_contrato ──────────▶│ PDF contrato
86
+ │ [ firma con botón ] ───┼─────────────────────────────▶│ firma + enlace de pago
87
+ │ [ paga en checkout ] ──┼─────────────────────────────▶│ webhook aprobado
88
+ │◀── "ya quedaste │◀─ emisión determinística ────┤ PDF póliza + auditoría
89
+ │ asegurado 🎉" │ │
90
+ ```
91
+
92
+ Estados de la sesión: `DIAGNOSTICO → RECOMENDACION → DUDAS → CIERRE → EMITIDA`.
93
+ La conversación soporta un **atajo**: si el afiliado ya sabe lo que quiere
94
+ ("solo quiero seguro de viaje"), Clara no lo interroga — va directo al producto.
95
+
96
+ ---
97
+
98
+ ## Portafolio cubierto (14 productos reales de Colsubsidio)
99
+
100
+ Vida · Vida y Ahorro · Plan Complementario de Salud · Asistencias Médicas
101
+ Familiares · Accidentes Personales · Exequial · Accidentes + Exequial · Asesorías
102
+ Jurídicas · Asistencias Múltiples (hogar, vehículo, salud y mascotas 24/7) ·
103
+ Asistencia Médica en Viajes · Hogar · Autos · Moto · Mascotas.
104
+
105
+ Cada uno con sus amparos, exclusiones, condiciones, fuente citable y prima base
106
+ en `app/knowledge.py`. El recomendador **rankea por ajuste al perfil, no por
107
+ precio**, y no se limita a vida o mascotas: considera todo el portafolio.
108
+
109
+ ---
110
+
111
+ ## Probar la demo en 2 minutos
112
+
113
+ ```powershell
114
+ python -m pip install -r requirements.txt
115
+ copy .env.example .env # y pega tu GEMINI_API_KEY (gratis, sin tarjeta)
116
+ python server.py
117
+ ```
118
+
119
+ → Abre **http://localhost:8000** y entra a la pestaña **Demo interactiva**.
120
+
121
+ Guion sugerido para el jurado:
122
+ 1. *"Hola, no sé qué seguro necesito."* → deja que Clara diagnostique.
123
+ 2. Cuéntale algo real: *"vivo con mi pareja y tengo un gato"* → mira cómo aparece
124
+ el seguro de mascotas en la recomendación.
125
+ 3. Elige un producto, da tus datos, **firma** con el botón y **paga** con la
126
+ tarjeta de prueba `4242 4242 4242 4242` (la `4111…` simula rechazo).
127
+ 4. Observa cómo se **emite la póliza en PDF** y todo queda en el panel de auditoría.
128
+
129
+ > **Clave Gemini:** usa una de **Google AI Studio** (`AIza...`,
130
+ > [aistudio.google.com/apikey](https://aistudio.google.com/apikey)), gratis y sin
131
+ > tarjeta. Evita claves Vertex (`AQ.`) salvo que tengas facturación en Google Cloud.
132
+
133
+ ---
134
+
135
+ ## Estado de ejecución (honestidad de ingeniería)
136
+
137
+ Esto es un **MVP demostrable** para la hackathon, no un producto en producción.
138
+ El flujo principal se recorre completo en local; algunas piezas son
139
+ **simulaciones** conscientes que se dejan listas para evolucionar.
140
+
141
+ | Área | Estado | Notas |
142
+ |------|--------|-------|
143
+ | **Conversación con Gemini** | ✅ Funcional | Function-calling, escucha activa, manejo de peticiones directas. |
144
+ | **Flujo end-to-end** | ✅ Funcional | Diagnóstico → recomendación → contrato → firma → pago → emisión, cableado y recorrible. |
145
+ | **Frontend (chat + paneles)** | ✅ Funcional | Chat, estado, perfil y auditoría en vivo. |
146
+ | **PDFs (resumen/contrato/póliza)** | ✅ Funcional | Generación real con `fpdf2`, descarga por `/docs/{archivo}`. |
147
+ | **Persistencia** | ✅ Funcional | Sesiones y auditoría en SQLite; sobrevive reinicios. |
148
+ | **Pago (Wompi)** | 🟡 Simulación | Checkout con tarjetas de prueba y validación Luhn. **No** es la API real de Wompi (webhooks firmados, producción). |
149
+ | **Correo / WhatsApp** | 🟡 Simulación | Sin `SMTP_*`/Twilio, la entrega se registra como `[SIMULADO]`. Con credenciales, envía de verdad. |
150
+ | **Despliegue** | 🟡 Preparado | Dockerfile + variables de entorno listos; falta hardening cloud. |
151
+
152
+ ---
153
+
154
+ ## Roadmap corto
155
+
156
+ - **Agente:** pulir tono, consistencia de fases y edge cases de peticiones directas.
157
+ - **Pago:** integración real con Wompi (referencias, estados, reintentos, webhook firmado).
158
+ - **Entrega:** envío real de PDF por SMTP y WhatsApp (Twilio) con pruebas end-to-end.
159
+ - **RAG / catálogo:** enriquecer condiciones desde fuentes oficiales (`data/reference/`).
160
+ - **Calidad:** tests automatizados + CI, y observabilidad (métricas de sesión, errores LLM, latencias).
161
+
162
+ ---
163
+
164
+ ## Arquitectura y estructura
165
+
166
+ ```
167
+ ├── server.py # Punto de entrada (python server.py)
168
+ ├── app/ # Backend (paquete Python)
169
+ │ ├── main.py # API FastAPI + checkout de pago
170
+ │ ├── config.py # Configuración central (.env)
171
+ │ ├── agent.py # Sesión, herramientas y bucle de tool-calling + guardrail
172
+ │ ├── llm.py # Cliente Gemini (AI Studio + Vertex Express)
173
+ │ ├── extraction.py # Captura de datos: regex + responseSchema (Gemini)
174
+ │ ├── knowledge.py # Catálogo, RAG y motor de cotización (fuente de verdad)
175
+ │ ├── payments.py # Pasarela simulada (tarjetas de prueba, Luhn)
176
+ │ ├── pdfgen.py # PDFs de resumen, contrato y póliza (fpdf2)
177
+ │ ├── notify.py # Entrega por correo SMTP / WhatsApp Twilio (opcional)
178
+ │ └── store.py # SQLite (sesiones + auditoría)
179
+ ├── static/ # Frontend (chat + paneles de estado/perfil/auditoría)
180
+ │ ├── index.html · css/styles.css · js/app.js · img/
181
+ ├── data/reference/ # Documentos de referencia del reto (política de datos, workflow)
182
+ ├── var/ # Runtime: PDFs y DB (ignorado en git)
183
+ ├── Dockerfile · requirements.txt
184
+ ```
185
+
186
+ **Stack:** Python · FastAPI · Gemini (function-calling) · fpdf2 · SQLite · Docker.
187
+
188
+ ---
189
+
190
+ ## Desplegar (Docker / Hugging Face Space)
191
+
192
+ ```powershell
193
+ docker build -t clara .
194
+ docker run -p 7860:7860 -e GEMINI_API_KEY=AIza... clara
195
+ ```
196
+
197
+ En un **Space** (SDK Docker): define `GEMINI_API_KEY` como *secret*. **Nunca**
198
+ subas el `.env` real al repo ni al hosting.
199
+
200
+ ### Variables de entorno
201
+
202
+ | Variable | Por defecto | Descripción |
203
+ |----------|-------------|-------------|
204
+ | `GEMINI_API_KEY` | — | **Obligatoria.** Preferir clave AI Studio (`AIza...`). |
205
+ | `GEMINI_MODEL` | `gemini-2.0-flash` | Modelo Gemini. |
206
+ | `APP_ENV` | `development` | `production` desactiva docs OpenAPI y autoreload. |
207
+ | `PORT` | `8000` / `7860` (Docker) | Puerto HTTP. |
208
+ | `PUBLIC_BASE_URL` | auto | Base para enlaces de pago y PDFs (en Spaces se autodetecta). |
209
+ | `SMTP_*` | — | Correo real con PDF adjunto (opcional). |
210
+ | `TWILIO_*` | — | WhatsApp/SMS (opcional). |
211
+
212
+ ---
213
+
214
+ ## Autora
215
+
216
+ **Mariana Sinisterra** · [@MarianaCodebase](https://github.com/MarianaCodebase)
217
+
218
+ Prototipo para el **Reto 2 · Venta automatizada de seguros** —
219
+ Hackathon [Colsubsidio × 30X](https://innovacion.colsubsidio.com/).
220
+ </content>
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ fastapi==0.115.6
2
+ uvicorn[standard]==0.34.0
3
+ requests==2.32.3
4
+ pydantic==2.10.4
5
+ python-multipart==0.0.20
6
+ python-dotenv==1.0.1
7
+ fpdf2==2.8.2
server.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Punto de entrada: python server.py"""
2
+
3
+ import uvicorn
4
+
5
+ from app.config import settings
6
+
7
+ if __name__ == "__main__":
8
+ uvicorn.run(
9
+ "app.main:app",
10
+ host="0.0.0.0",
11
+ port=settings.PORT,
12
+ reload=not settings.is_production,
13
+ )
sid.tmp ADDED
@@ -0,0 +1 @@
 
 
1
+ 934b3bd63a0d