[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:
parent
763a561266
commit
76760ba940
1 changed files with 102 additions and 24 deletions
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue