Como construimos un asistente de movilidad IA para una plataforma de fleetmanagement

20 de febrero de 202615 min readJonathan Kramer
Como construimos un asistente de movilidad IA para una plataforma de fleetmanagement

Construimos un asistente IA para una plataforma de fleetmanagement que gestiona politicas de movilidad para empresas: coches de leasing, bicicletas, tarjetas de transporte publico, coches compartidos, compensaciones por teletrabajo. A traves del asistente, los empleados pueden hacer preguntas sobre su politica de movilidad personal. Preguntas personales, datos en vivo, respuestas en tiempo real.

Esto es un relato tecnico de como lo construi. Los patrones que use, las decisiones de diseno que tome, y donde estuvo realmente la complejidad.

Function calling como patron central

El corazon del asistente es function calling. Es el patron donde un modelo de IA no solo genera texto, sino que tambien puede usar herramientas. Le das al modelo una lista de funciones con nombres, descripciones y definiciones de parametros. En cada mensaje del usuario, el modelo decide por si mismo si necesita llamar a una funcion, cual y con que argumentos.

En la practica: un empleado escribe "Cuanto presupuesto de bicicleta me queda?" El modelo analiza la pregunta, reconoce que es una consulta de presupuesto para la modalidad bicicleta, y llama a una funcion que obtiene el presupuesto restante a traves de la API interna de la plataforma. La API devuelve datos estructurados. El modelo lee esos datos y formula una respuesta clara.

La diferencia con un chatbot tradicional: el modelo elige la funcion, no el desarrollador. En un chatbot clasico programas cada ruta tu mismo. Si el usuario dice X, haz Y. Eso no escala. Con function calling describes lo que hacen tus funciones, y el modelo determina cuando cual funcion es adecuada. Nuevos tipos de preguntas que caen dentro del dominio de tus funciones existentes funcionan automaticamente. Cero codigo necesario.

El diseno de las funciones

Esta es la parte donde inveteri mas trabajo de diseno. No la implementacion. El diseno.

Cada funcion que el asistente puede llamar es un contrato. El nombre dice lo que hace la funcion. La description le dice al modelo cuando usarla y cuando no. Los parametros estan estrictamente tipados con enums donde es posible.

Un ejemplo simplificado (no la implementacion exacta de produccion, pero el patron es correcto):

{
  "name": "get_mobility_budget",
  "description": "Obtener el presupuesto de movilidad
    actual para un empleado y una modalidad especifica.
    Usar para preguntas sobre presupuesto restante,
    gastos o monto disponible por tipo de transporte.
    No usar para preguntas genericas de politica
    sin componente personal.",
  "parameters": {
    "modality": {
      "type": "string",
      "enum": ["car", "bike", "public_transport",
               "shared_car", "wfh"]
    }
  }
}

Esa description es prompt engineering disfrazado. El modelo lee ese texto en cada turno para decidir si esta funcion se ajusta a la pregunta. Si la description es demasiado vaga, el modelo elige la funcion equivocada. Demasiado estricta, y no se atreve a usarla cuando deberia.

Pase mas horas calibrando esas descripciones que construyendo las integraciones de API. No exagero. La diferencia entre "funciona en la demo" y "funciona de forma fiable en produccion" esta en un 80% en lo bien escritas que estan las descripciones de funciones.

Multi-step reasoning

Las preguntas simples son triviales. Una funcion, una respuesta. Pero los empleados tambien preguntan cosas complejas. "Estoy pensando en cambiar mi coche de leasing por una e-bike y una tarjeta de transporte publico. Es posible con mi politica y que significaria financieramente?"

Eso requiere multiples pasos. El modelo necesita obtener la politica actual. Verificar el contrato de leasing. Calcular como seria el presupuesto con un cambio de modalidad. Y presentar la comparacion. Cuatro llamadas a funciones en secuencia. Function calling soporta esto nativamente.

Por que function calling y no RAG

Para el asistente, RAG no funciona. Las politicas de movilidad son dinamicas y personales. Un documento que dice "el presupuesto maximo de bicicleta es 1.500 euros" es inutil si no sabes cuanto de eso ya se gasto. Ese estado actual no esta en un documento. Esta en un sistema en vivo.

Function calling resuelve esto fundamentalmente diferente. En lugar de buscar en documentos, el modelo consulta la fuente de verdad: los datos en vivo de la plataforma. Para preguntas genericas de politica hay una knowledge base como respaldo. Pero el peso esta en function calling.

La arquitectura de seguridad

El asistente tiene acceso a datos de empleados. Presupuestos, detalles de contratos, politicas. Construi cuatro capas de seguridad independientes.

Capa 1: alcance de solo lectura. El asistente solo puede leer. Todas las funciones hacen exclusivamente requests GET. No existe ninguna funcion para modificar datos, cancelar contratos o iniciar pagos.

Capa 2: scoping de identidad. Cada sesion esta vinculada a un usuario autenticado. Las funciones solo pueden consultar datos de ese usuario especifico. El ID de usuario se inyecta del lado del servidor, no lo determina el modelo. Inmutable, siempre sobrescrito por el servidor.

Capa 3: sanitizacion de output. Antes de que un resultado de funcion llegue al modelo, se eliminan los campos innecesarios. Minimizacion de datos por diseno.

Capa 4: prevencion de prompt injection. La entrada del usuario se valida. El system prompt contiene limites explicitos. Y aunque alguien manipulara el modelo: la capa 2 bloquea cualquier request fuera del alcance de la sesion.

Un detalle importante: el modelo de IA en si nunca tiene acceso directo a los datos de los usuarios. Todos los datos permanecen dentro de la infraestructura de la plataforma. El modelo solo puede solicitar puntos de datos especificos y predefinidos a traves de la capa de funciones, e incluso entonces, los resultados se filtran antes de que el modelo los vea. Sin acceso masivo, sin consultas a la base de datos, sin exportacion de datos. El modelo trabaja con el minimo que necesita para responder la pregunta, nada mas.

Defense in depth. Cuatro muros independientes, no uno.

Optimizaciones despues de v1

Temperature en 0. Determinismo en lugar de creatividad. La misma pregunta con los mismos datos da la misma respuesta.

Descripciones de funciones versionadas. Cada cambio en una description es rastreable. Cuando aparece un edge case, puedo rastrear exactamente que version estaba activa.

Observability. Cada paso se registra: que funcion considero el modelo, cual eligio, latencia de la API, tamano del resultado. Sin estos logs se depura a ciegas.

Contexto compacto. Menos tokens por turno significa respuestas mas rapidas y precisas. System prompt compacto. Resultados de funciones reducidos al minimo.

La imagen mas amplia

Function calling como capa de abstraccion entre un modelo de IA y APIs existentes es uno de los patrones mas poderosos que existen ahora mismo. Cualquier sistema con datos internos sobre los que la gente tiene preguntas puede usar este patron.

Lo que lo hace dificil no es la IA. Lo que lo hace dificil es la ingenieria alrededor. Limitar el alcance. Validar el output. Probar los edge cases. Calibrar las descripciones de funciones. Asegurar que el modelo sea honesto sobre lo que no sabe. Eso es ingenieria de software. No magia de IA.

Ready to automate?

Let us show you what AI automation can do for your business.

Get in touch