[IMPROVED] Añadir conversión automática a tarifas por hora en rate_update.py

- Detectar período de tiempo mencionado en la respuesta (hora, día, semana, mes, año)
- Aplicar factores de conversión automáticos para estandarizar a tarifa por hora
- Mejorar patrones de búsqueda para detectar valores con comas y diferentes formatos
- Ajustar rangos de validación según el período de tiempo detectado
- Aclarar en el prompt que se necesita específicamente la tarifa POR HORA
- Mejorar la extracción de números con formato miles (1,000.00)

🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Mauro Rosero P. 2025-03-12 11:05:04 -05:00
parent 763a561266
commit 76760ba940
Signed by: mrosero
GPG key ID: 83BD2A5F674B7E26

View file

@ -209,57 +209,129 @@ def query_perplexity(prompt, model="o1"):
content = result.get('choices', [{}])[0].get('message', {}).get('content', '')
logger.info(f"Contenido de la respuesta: {content}")
# Primero, detectar si la respuesta menciona un período de tiempo diferente a hora
period_indicators = {
'hora': 1, # Factor de conversión a hora (1 hora = 1 hora)
'día': 1/8, # Asumiendo jornada de 8 horas
'semana': 1/40, # Asumiendo 40 horas semanales
'mes': 1/160, # Asumiendo ~160 horas mensuales (40 h/sem * 4 sem)
'año': 1/2000, # Asumiendo ~2000 horas anuales
'anual': 1/2000,
'mensual': 1/160,
'semanal': 1/40,
'diario': 1/8,
'por hora': 1,
'por día': 1/8,
'por semana': 1/40,
'por mes': 1/160,
'por año': 1/2000,
'por jornada': 1/8
}
# Detectar el período mencionado en el texto
time_period_factor = 1 # Por defecto asumimos que el valor ya está por hora
for period, factor in period_indicators.items():
if period in content.lower():
time_period_factor = factor
logger.info(f"Detectado período de tiempo: {period} (factor: {factor})")
break
# Estrategia 1: Buscar patrones específicos de dinero (con y sin símbolo de dólar)
# Buscar un patrón como $30.00, 30.00, $30, o 30 USD
money_patterns = [
r'\$(\d+\.\d{2})', # $30.00
r'(\d+\.\d{2})\s*USD', # 30.00 USD
r'(\d+\.\d{2})', # 30.00
r'\$(\d+)', # $30
r'(\d+)\s*USD', # 30 USD
r'(\d+(?:\.\d+)?)' # Cualquier número con o sin decimales
r'\$\s*(\d{1,3}(?:,\d{3})*(?:\.\d{2}))', # $30,000.00 o $30.00
r'(\d{1,3}(?:,\d{3})*(?:\.\d{2}))\s*USD', # 30,000.00 USD o 30.00 USD
r'\$\s*(\d{1,3}(?:,\d{3})*)', # $30,000 o $30
r'(\d{1,3}(?:,\d{3})*)\s*USD', # 30,000 USD o 30 USD
r'\$\s*(\d+\.\d{2})', # $30.00
r'(\d+\.\d{2})\s*USD', # 30.00 USD
r'\$\s*(\d+)', # $30
r'(\d+)\s*USD', # 30 USD
r'(\d+(?:\.\d+)?)' # Cualquier número con o sin decimales
]
for pattern in money_patterns:
match = re.search(pattern, content)
if match:
try:
value = float(match.group(1))
logger.info(f"Valor extraído con patrón {pattern}: {value}")
return round(value, 2) # Asegurar 2 decimales
# Limpiar comas para poder convertir a float
value_str = match.group(1).replace(',', '')
value = float(value_str)
# Convertir a tarifa por hora según el período detectado
hourly_rate = value * time_period_factor
logger.info(f"Valor extraído: {value} (periodo factor: {time_period_factor})")
logger.info(f"Convertido a tarifa por hora: {hourly_rate:.2f}")
return round(hourly_rate, 2) # Asegurar 2 decimales
except (ValueError, IndexError):
continue
# Estrategia 2: Extraer todos los números y elegir el más probable
all_numbers = re.findall(r'\d+(?:\.\d+)?', content)
all_numbers = re.findall(r'\d{1,3}(?:,\d{3})*(?:\.\d+)?|\d+(?:\.\d+)?', content)
if all_numbers:
try:
# Limpiar comas y convertir a float
cleaned_numbers = [float(n.replace(',', '')) for n in all_numbers]
# Si hay varios números, elegir el más probable
# (En este caso, podríamos tomar el promedio o el primero)
if len(all_numbers) > 1:
logger.info(f"Múltiples números encontrados: {all_numbers}")
# Eliminamos valores extremadamente altos o bajos
filtered_numbers = [float(n) for n in all_numbers if 5 <= float(n) <= 500]
if len(cleaned_numbers) > 1:
logger.info(f"Múltiples números encontrados: {cleaned_numbers}")
# Eliminamos valores extremadamente altos o bajos según el período de tiempo
# Definir rangos válidos según el factor de tiempo
min_valid = 5
max_valid = 500
# Ajustar rangos según el período detectado
if time_period_factor == 1/8: # diario
min_valid = 40
max_valid = 4000
elif time_period_factor == 1/40: # semanal
min_valid = 200
max_valid = 20000
elif time_period_factor == 1/160: # mensual
min_valid = 800
max_valid = 80000
elif time_period_factor == 1/2000: # anual
min_valid = 10000
max_valid = 1000000
filtered_numbers = [n for n in cleaned_numbers if min_valid <= n <= max_valid]
if filtered_numbers:
value = sum(filtered_numbers) / len(filtered_numbers)
else:
value = float(all_numbers[0])
# Si no hay valores en el rango, tomar el primer número
value = cleaned_numbers[0]
else:
value = float(all_numbers[0])
value = cleaned_numbers[0]
logger.info(f"Valor final extraído: {value}")
return round(value, 2)
# Aplicar factor de conversión de tiempo
hourly_rate = value * time_period_factor
logger.info(f"Valor extraído: {value} (período factor: {time_period_factor})")
logger.info(f"Convertido a tarifa por hora: {hourly_rate:.2f}")
return round(hourly_rate, 2)
except ValueError:
pass
# Estrategia 3: Último recurso, intentar limpiar el texto y extraer un número
try:
# Eliminar cualquier símbolo de moneda y espacios
# Eliminar cualquier símbolo que no sea dígito o punto
cleaned_content = re.sub(r'[^\d.]', '', content)
if cleaned_content:
value = round(float(cleaned_content), 2)
logger.info(f"Valor limpiado y extraído: {value}")
return value
value = float(cleaned_content)
# Aplicar factor de conversión de tiempo
hourly_rate = value * time_period_factor
logger.info(f"Valor limpiado y extraído: {value} (período factor: {time_period_factor})")
logger.info(f"Convertido a tarifa por hora: {hourly_rate:.2f}")
return round(hourly_rate, 2)
except ValueError:
pass
@ -402,7 +474,13 @@ def generate_prompt(programmer_type, region_code):
# Usamos el año actual para la consulta principal
current_year = time.strftime("%Y")
prompt = f"¿Cuál es la tarifa por hora promedio en dólares estadounidenses (USD) para un {programmer_description} en {region_name} en {current_year}? Si no tienes datos del {current_year}, usa la información más reciente y haz una estimación aproximada. Responde solo con el valor numérico con dos decimales."
prompt = f"""¿Cuál es la tarifa POR HORA promedio en dólares estadounidenses (USD) para un {programmer_description} en {region_name} en {current_year}?
Si no tienes datos del {current_year}, usa la información más reciente y haz una estimación aproximada.
IMPORTANTE: Si encuentras información en otros períodos de tiempo (mensual, anual, etc.), conviértela a tarifa POR HORA.
Responde solo con el valor numérico con dos decimales."""
return prompt