[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', '')
|
content = result.get('choices', [{}])[0].get('message', {}).get('content', '')
|
||||||
logger.info(f"Contenido de la respuesta: {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)
|
# 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
|
# Buscar un patrón como $30.00, 30.00, $30, o 30 USD
|
||||||
money_patterns = [
|
money_patterns = [
|
||||||
r'\$(\d+\.\d{2})', # $30.00
|
r'\$\s*(\d{1,3}(?:,\d{3})*(?:\.\d{2}))', # $30,000.00 o $30.00
|
||||||
r'(\d+\.\d{2})\s*USD', # 30.00 USD
|
r'(\d{1,3}(?:,\d{3})*(?:\.\d{2}))\s*USD', # 30,000.00 USD o 30.00 USD
|
||||||
r'(\d+\.\d{2})', # 30.00
|
r'\$\s*(\d{1,3}(?:,\d{3})*)', # $30,000 o $30
|
||||||
r'\$(\d+)', # $30
|
r'(\d{1,3}(?:,\d{3})*)\s*USD', # 30,000 USD o 30 USD
|
||||||
r'(\d+)\s*USD', # 30 USD
|
r'\$\s*(\d+\.\d{2})', # $30.00
|
||||||
r'(\d+(?:\.\d+)?)' # Cualquier número con o sin decimales
|
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:
|
for pattern in money_patterns:
|
||||||
match = re.search(pattern, content)
|
match = re.search(pattern, content)
|
||||||
if match:
|
if match:
|
||||||
try:
|
try:
|
||||||
value = float(match.group(1))
|
# Limpiar comas para poder convertir a float
|
||||||
logger.info(f"Valor extraído con patrón {pattern}: {value}")
|
value_str = match.group(1).replace(',', '')
|
||||||
return round(value, 2) # Asegurar 2 decimales
|
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):
|
except (ValueError, IndexError):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Estrategia 2: Extraer todos los números y elegir el más probable
|
# 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:
|
if all_numbers:
|
||||||
try:
|
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
|
# Si hay varios números, elegir el más probable
|
||||||
# (En este caso, podríamos tomar el promedio o el primero)
|
if len(cleaned_numbers) > 1:
|
||||||
if len(all_numbers) > 1:
|
logger.info(f"Múltiples números encontrados: {cleaned_numbers}")
|
||||||
logger.info(f"Múltiples números encontrados: {all_numbers}")
|
# Eliminamos valores extremadamente altos o bajos según el período de tiempo
|
||||||
# Eliminamos valores extremadamente altos o bajos
|
|
||||||
filtered_numbers = [float(n) for n in all_numbers if 5 <= float(n) <= 500]
|
# 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:
|
if filtered_numbers:
|
||||||
value = sum(filtered_numbers) / len(filtered_numbers)
|
value = sum(filtered_numbers) / len(filtered_numbers)
|
||||||
else:
|
else:
|
||||||
value = float(all_numbers[0])
|
# Si no hay valores en el rango, tomar el primer número
|
||||||
|
value = cleaned_numbers[0]
|
||||||
else:
|
else:
|
||||||
value = float(all_numbers[0])
|
value = cleaned_numbers[0]
|
||||||
|
|
||||||
|
# Aplicar factor de conversión de tiempo
|
||||||
|
hourly_rate = value * time_period_factor
|
||||||
|
|
||||||
logger.info(f"Valor final extraído: {value}")
|
logger.info(f"Valor extraído: {value} (período factor: {time_period_factor})")
|
||||||
return round(value, 2)
|
logger.info(f"Convertido a tarifa por hora: {hourly_rate:.2f}")
|
||||||
|
|
||||||
|
return round(hourly_rate, 2)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Estrategia 3: Último recurso, intentar limpiar el texto y extraer un número
|
# Estrategia 3: Último recurso, intentar limpiar el texto y extraer un número
|
||||||
try:
|
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)
|
cleaned_content = re.sub(r'[^\d.]', '', content)
|
||||||
if cleaned_content:
|
if cleaned_content:
|
||||||
value = round(float(cleaned_content), 2)
|
value = float(cleaned_content)
|
||||||
logger.info(f"Valor limpiado y extraído: {value}")
|
|
||||||
return value
|
# 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:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -402,7 +474,13 @@ def generate_prompt(programmer_type, region_code):
|
||||||
|
|
||||||
# Usamos el año actual para la consulta principal
|
# Usamos el año actual para la consulta principal
|
||||||
current_year = time.strftime("%Y")
|
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
|
return prompt
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue