@innvisor/conny-ai 9.7.0 → 9.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +66 -0
- package/README.md +17 -1
- package/conny_app.py +9 -3
- package/conny_cli.py +103 -11
- package/conny_core/evolution.py +112 -0
- package/conny_core/first_turn_ops.py +16 -20
- package/conny_core/prompt_ops.py +62 -0
- package/conny_demo_voice.py +1 -1
- package/conny_doctor.py +287 -2
- package/conny_domino.py +2 -2
- package/conny_generator.py +1 -1
- package/conny_i18n.py +81 -2
- package/conny_init.py +254 -41
- package/conny_runtime_ops.py +198 -6
- package/conny_tui.py +7 -0
- package/conny_ultra_config.py +25 -11
- package/conny_utils.py +21 -3
- package/ecosystem.config.js +11 -1
- package/install.sh +78 -22
- package/npm/conny.js +75 -21
- package/package.json +12 -2
- package/run.sh +7 -0
- package/src/conny/admin/dashboard.py +35 -4
- package/src/conny/admin_memory.py +93 -0
- package/src/conny/api/routes.py +26 -9
- package/src/conny/channels/cli.py +30 -9
- package/src/conny/demo/handler.py +23 -23
- package/src/conny/personas/generator.py +1 -1
- package/src/conny/production/domino.py +2 -2
- package/src/conny/production/guard.py +4 -4
- package/src/core/admin_engines.py +51 -48
- package/src/core/globals.py +110 -9
- package/src/core/production_monitor.py +63 -38
- package/src/core/runtime.py +343 -305
- package/src/domain/prompts/prospect_pitch.py +11 -11
- package/src/domain/send_guard.py +4 -4
- package/src/interfaces/web/app.py +91 -27
- package/src/interfaces/web/demo_admin_commands.py +165 -0
- package/src/interfaces/web/demo_handler.py +178 -34
- package/brand-assets/cl-nica-de-las-am-ricas/manifest.json +0 -22
- package/brand-assets/cl-nica-de-las-am-ricas/processed/business-identity.txt +0 -11
- package/brand-assets/cl-nica-de-las-am-ricas/raw/business-identity.txt +0 -11
- package/brand-assets/cl-nica-las-am-ricas/manifest.json +0 -22
- package/brand-assets/cl-nica-las-am-ricas/processed/business-identity.txt +0 -11
- package/brand-assets/cl-nica-las-am-ricas/raw/business-identity.txt +0 -11
- package/brand-assets/conny-demo/manifest.json +0 -22
- package/brand-assets/conny-demo/processed/business-identity.txt +0 -7
- package/brand-assets/conny-demo/raw/business-identity.txt +0 -7
- package/fix_init.py +0 -27
- package/verify_conversation_impl.py +0 -48
|
@@ -127,11 +127,10 @@ class ConnyProduction:
|
|
|
127
127
|
# Load soul knowledge
|
|
128
128
|
soul_context = ""
|
|
129
129
|
try:
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
pass
|
|
130
|
+
from conny_core.prompt_ops import build_business_context
|
|
131
|
+
soul_context = build_business_context(clinic, db, instance_id)
|
|
132
|
+
except Exception as e:
|
|
133
|
+
log.warning(f"[production] error building business context: {e}")
|
|
135
134
|
|
|
136
135
|
tone_instructions = {
|
|
137
136
|
"luxury": "Tono LUXURY: sofisticada, elegante, exclusiva. Usa lenguaje premium. Nunca suenes informal ni uses jerga. Transmite exclusividad en cada palabra.",
|
|
@@ -142,39 +141,55 @@ class ConnyProduction:
|
|
|
142
141
|
}
|
|
143
142
|
tone_instruction = tone_instructions.get(persona_tone, tone_instructions["colombian_warm"])
|
|
144
143
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
-
|
|
177
|
-
-
|
|
144
|
+
# Admin rules injection (things admin said to ask first or forbidden phrases)
|
|
145
|
+
forbidden_txt = ""
|
|
146
|
+
try:
|
|
147
|
+
rules = clinic.get("business_rules", {})
|
|
148
|
+
if isinstance(rules, str):
|
|
149
|
+
import json as _j4
|
|
150
|
+
rules = _j4.loads(rules)
|
|
151
|
+
|
|
152
|
+
forbidden = rules.get("forbidden_phrases", [])
|
|
153
|
+
if forbidden:
|
|
154
|
+
forbidden_txt = "\nREGLAS CRÍTICAS (No usar NUNCA estas frases/palabras):\n" + "\n".join([f"- {p}" for p in forbidden])
|
|
155
|
+
except Exception:
|
|
156
|
+
pass
|
|
157
|
+
|
|
158
|
+
# PROMPT DE PRODUCCIÓN UPGRADED
|
|
159
|
+
sys_prompt = f"""
|
|
160
|
+
Eres Conny, la recepcionista virtual de {clinic_name}. Tu identidad es Innvisor.
|
|
161
|
+
|
|
162
|
+
IDENTIDAD
|
|
163
|
+
No eres un bot. Eres Conny — la persona que atiende este WhatsApp.
|
|
164
|
+
Nunca digas "soy una IA", "soy un asistente virtual" ni "soy un bot" a menos que te lo pregunten directamente.
|
|
165
|
+
Si te preguntan directamente si eres IA, confirmas con naturalidad y sigues adelante.
|
|
166
|
+
|
|
167
|
+
LO QUE SABES DE ESTE NEGOCIO (LEÍDO DE TUS CARPETAS/ARCHIVOS)
|
|
168
|
+
{soul_context}
|
|
169
|
+
{forbidden_txt}
|
|
170
|
+
|
|
171
|
+
LO QUE SABES DE ESTE CLIENTE
|
|
172
|
+
{patient_context}
|
|
173
|
+
|
|
174
|
+
CÓMO HABLAS
|
|
175
|
+
- Responde de manera sumamente humana, natural y empática. Usa buena ortografía y puntuación correcta, pero mantén un tono conversacional (no robótico ni extremadamente formal).
|
|
176
|
+
- Eres cálida y profesional. Transmites confianza.
|
|
177
|
+
- Mensajes cortos. Máximo 2-3 ideas por respuesta. Separa las ideas con ||| (para enviar múltiples burbujas).
|
|
178
|
+
- Sin frases enlatadas o de call center: nada de "con mucho gusto", "en qué le puedo ayudar", "fue un placer". Sé original y auténtica en cada respuesta.
|
|
179
|
+
- TONO: {tone_instruction}
|
|
180
|
+
|
|
181
|
+
LO QUE HACES Y NO HACES
|
|
182
|
+
- Responder preguntas sobre {clinic_name} usando ÚNICAMENTE la información que tienes en "LO QUE SABES DE ESTE NEGOCIO".
|
|
183
|
+
- NUNCA inventes precios, servicios, horarios ni detalles que no conoces con certeza. Si no lo sabes, NO asumas.
|
|
184
|
+
- Si no tienes la información exacta que pide el cliente, detente y dile amablemente: "Permíteme un segundo, voy a validar este detalle exacto con el administrador para darte la información correcta."
|
|
185
|
+
- Si el cliente insiste y sigues sin saberlo, pide disculpas y reitera que estás esperando la respuesta del administrador.
|
|
186
|
+
- Orientar hacia una cita o venta solo cuando estás segura de los datos y el cliente muestra intención.
|
|
187
|
+
|
|
188
|
+
ESCALACIÓN
|
|
189
|
+
Si un cliente pregunta algo que no puedes responder:
|
|
190
|
+
1. Dile al cliente que vas a consultar o confirmar.
|
|
191
|
+
2. Anotas mentalmente que el dueño debe enseñarte eso para que cuando hables con él (el admin), lo presiones para que te enseñe a responder eso.
|
|
192
|
+
"""
|
|
178
193
|
|
|
179
194
|
messages = [{"role": "system", "content": sys_prompt}]
|
|
180
195
|
for m in history[-12:]:
|
|
@@ -308,6 +323,16 @@ REGLAS GENERALES:
|
|
|
308
323
|
try:
|
|
309
324
|
await self.conny._send_message(admin_jid, alert_msg)
|
|
310
325
|
log.info(f"[production] admin alerted: confidence={confidence:.2f} question='{text[:50]}'")
|
|
326
|
+
|
|
327
|
+
# Guardar como pregunta pendiente para el admin
|
|
328
|
+
if not hasattr(self.conny, "_admin_pending"):
|
|
329
|
+
self.conny._admin_pending = {}
|
|
330
|
+
self.conny._admin_pending[admin_jid] = {
|
|
331
|
+
"action": "answer_gap",
|
|
332
|
+
"patient_chat_id": chat_id,
|
|
333
|
+
"original_question": text,
|
|
334
|
+
"ts": time.time()
|
|
335
|
+
}
|
|
311
336
|
except Exception as e:
|
|
312
337
|
log.warning(f"[production] failed to alert admin: {e}")
|
|
313
338
|
|