Autocompletado con IA para filtros de búsqueda de empleo basado en datos
Los buscadores de empleo suelen tener problemas con los filtros en sitios como HeadHunter, SuperJob, Zarplata.ru y TrudVsem. Los análisis muestran que los usuarios abren el panel de filtros, introducen datos al azar, obtienen resultados irrelevantes —desde miles de ofertas de conserje hasta listas vacías— y abandonan la página. Soluciones como avisos, campos obligatorios y resaltados fallaron: las conversiones bajaron porque los usuarios se intimidaban o escribían tonterías como "trabajo".
Idea clave: la complejidad. Cada plataforma usa IDs únicos para ciudades (HeadHunter tiene 1.600 con IDs, SuperJob los suyos), especializaciones, niveles de experiencia. Volcar diccionarios completos en un LLM implica 140.000 tokens por consulta (25-40 RUB), alucinaciones o quiebra.
Arquitectura de la tubería de IA basada en datos
La solución aprovecha una base de datos existente con tablas job_filters, job_filter_options, job_service_filters, city_master y city_source_map. Estas mapean valores canónicos a IDs específicos de la plataforma (p. ej., Moscú: HeadHunter=1, SuperJob=4).
El sistema autocategoriza filtros marcados con is_ai_eligible = true:
- Diccionarios pequeños (≤30 opciones): experiencia (
noExperience,between1And3), tipo de empleo (FULL,PART). Se envían al prompt (~400 tokens). - Diccionarios grandes (>30): ciudades, roles. El LLM genera texto ("Moscú"), el código resuelve IDs desde la BD.
- Texto libre: consultas como "desarrollador backend Python".
- Números: salario del currículum o del LLM.
Los prompts se generan dinámicamente desde la BD. Ejemplo:
== FILTROS DE OPCIONES MÚLTIPLES ==
experience: noExperience="Sin experiencia", between1And3="1-3 años"
employment_form: FULL="Tiempo completo"
== CAMPOS DE DICCIONARIO ==
city_name: "Moscú"
== CAMPOS DE TEXTO ==
text: 2-8 palabras
Entrada: resumen del currículum (habilidades, experiencia), rol deseado, sitios objetivo. Salida: JSON sin IDs:
{
"text": "desarrollador backend Python",
"area_name": "Moscú",
"experience": "between1And3",
"salary": {"from": 250000}
}
Fases de procesamiento y resolución
Fase 1: Generación de prompt y llamada al LLM
BuildSearchFiltersPromptTask arma la instrucción. El LLM (GigaChat) interpreta la intención del usuario, elige de diccionarios pequeños, nombra los grandes.
Fase 2: Postprocesamiento en código
- Resolución:
SearchCitiesActionbusca "Moscú" encity_master, mapea a IDs víacity_source_map. - Adaptación: convierte
between1And3al formato de API de la plataforma. - Ensamblado:
unified_filters+filter_labelspara el frontend.
Resultado: filtros prellenados para todos los sitios. Los usuarios revisan y guardan.
Escalabilidad: nuevo sitio/filtro —solo agregar datos a la BD; el prompt y la tubería se adaptan automáticamente.
Métricas de rendimiento
| Enfoque | Tokens | Costo por consulta | Precisión |
|---------|--------|--------------------|-----------|
| Naïve (diccionarios completos) | 140.000 | 25–40 RUB | Baja (alucinaciones) |
| Basado en datos | 850 + 150 | 0,1 RUB | Alta (resolución en BD) |
Ahorros: 150x. La tasa de abandono en búsquedas bajó, los ingresos medios por usuario de funciones premium subieron.
Lecciones clave
- Separación de roles: el LLM maneja semántica, la BD hace mapeo de IDs —reduce tokens y errores.
- Autoclasificación: umbral de 30 opciones es dinámico; nuevos filtros se integran sin código.
- Salida JSON: formato estricto del LLM simplifica el parseo.
- Escala: soporta miles de usuarios sin picos de costo.
- UX: autocompletado baja barreras de entrada.
— Editorial Team
Aún no hay comentarios.