Benutzer ein einzelnes Feld (z. B. "Client") ändert, gehen andere grundlegende Felder (z. B.
"Datum", "Autor" usw.) verloren, und einige Daten wie "Themen" und "Risiken" sind
duplizieren. Der Kontext behält die Daten zwischen Modifikationen nicht korrekt bei. < /p>
Code: Select all
Problema específico:
Al modificar un campo (ej: cliente:gsbat), se pierden otros campos básicos
Los arrays como "temas" y "riesgos" se duplican
El deepcopy no parece estar preservando correctamente el estado anterior
< /code>
** < /p>
"""def create_empty_context():
return {
'cliente': None,
'fecha': None,
'hora': None,
'duracion': None,
'autor': None,
'nombre': None,
'asistentes': [],
'orden_dia': [],
'temas': [],
'riesgos': [],
'comentarios': [],
'tareas': [],
'pasos': []
}
context = create_empty_context()
def is_complete_summary(text):
required_fields = ['cliente', 'fecha', 'duracion', 'autor', 'nombre']
text_lower = text.lower()
if any(f"{field}:" in text_lower for field in required_fields):
return True
patterns = [
r'(cliente|empresa|contratante)[:\s]',
r'(fecha|día|reunión el|reunión\s*\d+)',
r'(duracion|duró|tiempo)[:\s]',
r'(autor|escrita\s*por|responsable)[:\s]',
r'(proyecto|nombre\s*del\s*proyecto)[:\s]'
]
return sum(1 for pattern in patterns if re.search(pattern, text_lower)) >= 3
def extract_field_from_text(field, text):
patterns = {
'cliente': r'(cliente|empresa|contratante)[:\s]([^\n,;]+)',
'fecha': r'(fecha|día|reunión el|el\s\d+)[:\s]([^\n,;]+)',
'hora': r'(hora|comenzó a las|a las)[:\s]([^\n,;]+)',
'duracion': r'(duracion|duró|tiempo)[:\s]([^\n,;]+)',
'autor': r'(autor|escrita por|responsable)[:\s]([^\n,;]+)',
'nombre': r'(proyecto|nombre del proyecto)[:\s]*([^\n,;]+)'
}
if field in patterns:
match = re.search(patterns[field], text, re.IGNORECASE)
return match.group(2).strip() if match else None
return None
def get_missing_fields():
required_fields = ['cliente', 'fecha', 'duracion', 'autor', 'nombre']
return [field for field in required_fields if not context.get(field)]
def handle_field_update(field, value, is_add_mode=False):
global context
if field in ['cliente', 'fecha', 'hora', 'duracion', 'autor', 'nombre']:
context[field] = value
return
if field in ['orden_dia', 'comentarios', 'pasos']:
if isinstance(value, str):
items = [item.strip() for item in value.split(',') if item.strip()]
if is_add_mode:
context[field].extend(items)
else:
context[field] = items
return
if field == 'asistentes':
if isinstance(value, str):
new_names = [name.strip() for name in value.split(',') if name.strip()]
if is_add_mode:
for name in new_names:
context['asistentes'].append({
'nombre': name,
'organizacion': 'No especificada',
'estado': 'Presente'
})
else:
context['asistentes'] = [{
'nombre': name,
'organizacion': 'No especificada',
'estado': 'Presente'
} for name in new_names]
return
if field == 'temas':
if isinstance(value, str):
new_titles = [title.strip() for title in value.split(',') if title.strip()]
if is_add_mode:
for title in new_titles:
context['temas'].append({
'titulo': title,
'puntos': [],
'decisiones': []
})
else:
context['temas'] = [{
'titulo': title,
'puntos': [],
'decisiones': []
} for title in new_titles]
return
if field == 'riesgos':
if isinstance(value, str):
new_titles = [title.strip() for title in value.split(',') if title.strip()]
if is_add_mode:
for title in new_titles:
context['riesgos'].append({
'titulo': title,
'problema': '',
'asociado': '',
'mitigaciones': []
})
else:
context['riesgos'] = [{
'titulo': title,
'problema': '',
'asociado': '',
'mitigaciones': []
} for title in new_titles]
return
if field == 'tareas':
if isinstance(value, str):
new_tasks = [task.strip() for task in value.split(',') if task.strip()]
if is_add_mode:
for task in new_tasks:
context['tareas'].append({
'tarea': task,
'responsable': '',
'fecha': '',
'estado': ''
})
else:
context['tareas'] = [{
'tarea': task,
'responsable': '',
'fecha': '',
'estado': ''
} for task in new_tasks]
return
def ensure_default_values(context):
"""Asegura valores por defecto solo para campos vacíos"""
if not context.get('temas'):
context['temas'] = [{
'titulo': 'Temas no especificados',
'puntos': ['No se registraron puntos clave'],
'decisiones': ['No se registraron decisiones']
}]
if not context.get('riesgos'):
context['riesgos'] = [{
'titulo': 'No se identificaron riesgos',
'problema': 'No aplica',
'asociado': 'No aplica',
'mitigaciones': ['No aplica']
}]
if not context.get('tareas'):
context['tareas'] = [{
'tarea': 'No se registraron tareas',
'responsable': 'No aplica',
'fecha': 'No aplica',
'estado': 'N/A'
}]
if not context.get('asistentes'):
context['asistentes'] = [{
'nombre': 'No se especificaron asistentes',
'organizacion': 'No especificada',
'estado': 'No especificado'
}]
if not context.get('orden_dia'):
context['orden_dia'] = ['No se especificó el orden del día']
if not context.get('comentarios'):
context['comentarios'] = ['No hay comentarios registrados']
if not context.get('pasos'):
context['pasos'] = ['No se definieron próximos pasos']
return context
def generate_draft_response(with_options=False):
try:
template_path = 'plantilla_acta2.docx'
safe_cliente = re.sub(r'[^\w\s-]', '', context.get('cliente', '
acta')).strip().replace(' ', '')[:30]
safe_fecha = re.sub(r'[^\w\s-]', '', context.get('fecha', '')).strip().replace(' ',
'')[:10]
filename = f"acta_{safe_cliente}_{safe_fecha}.docx"
output_path = f'output/{filename}'
os.makedirs('output', exist_ok=True)
final_context = copy.deepcopy(context)
final_context = ensure_default_values(final_context)
if render_docx_template(template_path, final_context, output_path):
preview_html = render_template('preview.html', context=final_context)
if with_options:
return (
f"📄 Borrador del acta generado:\n"
f"{preview_html}\n"
f""
f"Opciones disponibles:"
f"1. [url=/download/{filename}]Descargar acta[/url]"
f"2. Enviar por correo"
f"3. Modificar
campos"
f"4. Cerrar"
f""
f""
f"function sendAction(action) {{"
f" fetch('/send_message', {{"
f" method: 'POST',"
f" headers: {{'Content-Type': 'application/json'}},"
f" body: JSON.stringify({{message: action}})"
f" }}).then(response => response.json())"
f" .then(data => {{"
f" if(data.action === 'reload') location.reload();"
f" else alert(data.response || 'Acción completada');"
f" }});"
f"}}"
f"document.getElementById('downloadLink').addEventListener('click',
function() {{"
f" fetch('/prepare_download/{filename}')"
f" .then(response => response.json())"
f" .then(data => {{"
f" if(data.redirect) window.location.href = data.redirect;"
f" }});"
f"}});"
f""
)
return preview_html
return "❌ Error al generar el documento"
except Exception as e:
return f"❌ Error al generar el documento: {str(e)}"
@app.route('/', methods=['GET', 'POST'])
def chat():
return render_template('chat.html')
@app.route('/send_message', methods=['POST'])
def send_message():
global context
data = request.json
user_message = data.get('message', '').strip()
user_message_lower = user_message.lower()
if user_message_lower == 'cerrar':
context = create_empty_context()
return jsonify({
'response': "✅ El proceso ha sido cerrado. Puedes comenzar de nuevo enviando
otro resumen.",
'context': context
})
if user_message_lower in ['modificar', 'modificar campos'] and not
data.get('modifying'):
return jsonify({
'response': ( "✏️ Modo edición activado. Elige una opción:\n"
"1. Para MODIFICAR un campo existente (sobrescribe):\n"
"'campo: valor'\n"
"2. Para AÑADIR información (mantiene lo existente):\n"
"'++campo: valor'\n"
"Ejemplos:\n"
f"'autor: Francisco López' (modifica el autor)\n"
f"'asistentes: Carlos Ruiz' (sobrescribe asistentes)\n"
f"'++asistentes: Carlos Ruiz' (añade asistente)\n"
"Campos disponibles:\n"
f"{', '.join(context.keys())}\n"
"Escribe 'listo' para finalizar"
),
'context': context,
'modifying': True
})
if data.get('modifying'):
if user_message_lower == 'listo':
missing_fields = get_missing_fields()
if missing_fields:
return jsonify({
'response': (
f"⚠️ Faltan campos obligatorios: {', '.join(missing_fields)}\n"
"¿Deseas completarlos ahora? (responde 'si' para continuar editando
o 'no' para generar el acta igualmente)"
),
'context': context,
'confirming_missing': True
})
else:
return jsonify({
'response': generate_draft_response(with_options=True),
'context': context,
'show_options': True
})
elif data.get('confirming_missing'):
if user_message_lower in ['si', 'sí']:
return jsonify({
'response': "Continúa modificando los campos faltantes usando 'campo:
valor' o '++campo: valor' para añadir",
'context': context,
'modifying': True
})
elif user_message_lower == 'no':
return jsonify({
'response': generate_draft_response(with_options=True),
'context': context,
'show_options': True
})
elif ':' in user_message:
field_part, value_part = user_message.split(':', 1)
is_add_mode = field_part.startswith('++')
field = field_part.replace('++', '').strip().lower()
value = value_part.strip()
field_aliases = {
'proyecto': 'nombre',
'dia': 'fecha',
'tiempo': 'duracion',
'responsable': 'autor'
}
field = field_aliases.get(field, field)
if field in context:
try:
current_context = copy.deepcopy(context)
if field in ['cliente', 'fecha', 'hora', 'duracion', 'autor',
'nombre']:
context[field] = value
else:
handle_field_update(field, value, is_add_mode)
for basic_field in ['cliente', 'fecha', 'hora', 'duracion', 'autor',
'nombre']:
if basic_field != field and current_context.get(basic_field):
context[basic_field] = current_context[basic_field]
return jsonify({
'response': f"✅ '{field}' actualizado. Continúa modificando o
escribe 'listo'",
'context': context,
'modifying': True
})
except Exception as e:
print(f"Error al procesar modificación: {str(e)}")
return jsonify({
'response': f"❌ Error al procesar '{field}'. Inténtalo de nuevo.",
'context': context,
'modifying': True
})
else:
return jsonify({
'response': f"❌ Campo '{field}' no válido. Campos disponibles:\n{', '.join(context.keys())}",
'context': context,
'modifying': True
})
if is_complete_summary(user_message):
try:
parsed_data = parse_meeting_summary(user_message)
basic_fields = ['cliente', 'fecha', 'hora', 'duracion', 'autor', 'nombre']
for field in basic_fields:
if parsed_data.get(field):
context[field] = parsed_data[field]
for key, value in parsed_data.items():
if key not in basic_fields and value and (not isinstance(value, list) or
len(value) > 0):
if isinstance(context[key], list) and isinstance(value, list):
context[key].extend(value)
else:
context[key] = value
missing_fields = get_missing_fields()
if missing_fields:
return jsonify({
'response': (
f"✅ Información recibida. Faltan campos obligatorios:\n"
f"{', '.join(missing_fields)}\n"
f"Por favor completa estos campos o escribe 'generar' para continuar."
),
'context': context,
'awaiting_fields': True
})
return jsonify({
'response': generate_draft_response(with_options=True),
'context': context,
'show_options': True
})
except Exception as e:
print(f"Error en el servidor: {str(e)}")
return jsonify({
'response': "❌ Error al procesar el acta. Por favor, verifica el formato e
intenta nuevamente.",
'context': context
})"""