scieee AI-readable full text Open interactive document viewer

El trol versátil

Ballesteros Horcajo, Enrique; Calero Robles, Sergio; Fernández Díaz, Jaime; Mateos Pérez, Ventura

Abstract

Las distintas redes sociales ofrecen cada vez mejores herramientas para la automatización de la interacción de los usuarios. Así el mercado de interacciones en redes sociales es cada vez es más amplio y tiene más competencia. En este contexto se hace necesario el uso de herramientas para la automatización de las interacciones en redes sociales que sean diferenciales. El fin de este trabajo es ofrecer un servicio para la creación de redes de bots que interaccionen automáticamente con cuentas de la red social Twitter de forma configurable y personalizada para cada cliente. La interacción debe ser coherente y difícilmente distinguible de la que realizaría un usuario real.

Full text

EL TROL VERSÁTIL THE VERSATILE TROLL ENRIQUE BALLESTEROS HORCAJO SERGIO CALERO ROBLES JAIME FERNANDEZ DÍAZ VENTURA MATEOS PÉREZ 4ºCURSO. TRABAJO DE FIN DE GRADO. FACULTAD DE INFORMÁTICA UNIVERSIDAD COMPLUTENSE DE MADRID Trabajo Fin de grado del Grado en Ingeniería Informática Fecha 11 de enero de 2022 Profesor Director: MANUEL NÚÑEZ GARCÍA Autorización de difusión Autores Enrique Ballesteros Horcajo Sergio Calero Robles Jaime Fernández Díaz Ventura Mateos Pérez Fecha 11 de enero de 2022 Los arriba firmantes, matriculados en el Grado en Ingeniería Informática de la Facultad de Informática, autorizan a la Universidad Complutense de Madrid (UCM) a difundir y utilizar con fines académicos, no comerciales y mencionando expresamente a su autor el presente Trabajo Fin de Grado: “El Trol Versátil”, realizado durante el curso académico 20212022 bajo la dirección de Manuel Núñez García en el Departamento de Sistemas Informáticos y Computación, y a la Biblioteca de la UCM a depositarlo en el Archivo Institucional EPrints Complutense con el objeto de incrementar la difusión, uso e impacto del trabajo en Internet y garantizar su preservación y acceso a largo plazo. Resumen en castellano Las distintas redes sociales ofrecen cada vez mejores herramientas para la automatización de la interacción de los usuarios. Así el mercado de interacciones en redes sociales es cada vez es más amplio y tiene más competencia. En este contexto se hace necesario el uso de herramientas para la automatización de las interacciones en redes sociales que sean diferenciales. El fin de este trabajo es ofrecer un servicio para la creación de redes de bots que interaccionen automáticamente con cuentas de la red social Twitter de forma configurable y personalizada para cada cliente. La interacción debe ser coherente y difícilmente distinguible de la que realizaría un usuario real. Palabras clave Inteligencia Artificial, Aprendizaje Automático, Bots, Redes Sociales, Twitter, Frontend, Backend Abstract The social networks offer every day better tools for automating user interaction. Therefore, the market of social network interactions is becoming larger and larger each day. In this context it is necessary to use tools for the automation of interactions in social networks that are differential. The purpose of this project is to offer a service for the creation of bot networks that automatically interact with accounts of the social network Twitter in a configurable and personalized way for each client. The interaction must be coherent and hardly distinguishable from what a real user would do. Keywords Artificial Intelligence, Machine Learning, Bots, Social Networks, Twitter, Frontend, Backend Índice general Índice i 1. Introducción 1 1.1. Motivación..................................... 1 1.2. Objetivo...................................... 1 1.3. Estructura de la memoria . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1. Introduction 3 1.1. Motivation..................................... 3 1.2. Objective ..................................... 3 1.3. Memorystructure................................. 4 2. Estado del Arte 5 2.1. Principales empresas web de habla hispana de servicios para redes sociales . 5 2.2. Estado del mercado internacional . . . . . . . . . . . . . . . . . . . . . . . . 7 2.3. Conclusiones sobre el estado del arte . . . . . . . . . . . . . . . . . . . . . . 8 3. Business Plan 9 3.1. Modelodelservicio................................ 10 3.2. Gastos fijos de la empresa . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 3.2.1. Salarios .................................. 11 3.2.2. Coste de los servidores . . . . . . . . . . . . . . . . . . . . . . . . . . 12 3.3. Modelo de negocio sostenible . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 3.4. Plandenegocio.................................. 13 3.4.1. Modelo de negocio sin necesidad de buscar financiación externa . . . 13 3.4.2. Modelo de negocio con inversión externa . . . . . . . . . . . . . . . . 14 3.5. Plandemarketing ................................ 15 3.6. Análisis de debilidades, amenazas, fortalezas y oportunidades . . . . . . . . . 16 3.6.1. Debilidad ................................. 16 3.6.2. Mayor amenaza: mes con balance negativo . . . . . . . . . . . . . . . 17 3.6.3. Fortalezas, amenazas y oportunidades de negocio . . . . . . . . . . . 17 3.7. Conclusiones del plan de negocio . . . . . . . . . . . . . . . . . . . . . . . . 18 4. Propuesta y diseño 19 4.1. Propuesta de interfaz para el usuario . . . . . . . . . . . . . . . . . . . . . . 19 4.2. Modelos de generación de texto . . . . . . . . . . . . . . . . . . . . . . . . . 22 4.2.1. Implementación.............................. 23 i 4.2.2. models.py ................................. 24 4.2.3. responseGeneration.py . . . . . . . . . . . . . . . . . . . . . . . . . . 27 4.3. Análisisdesentimiento.............................. 29 4.4. Bots ........................................ 30 4.4.1. Implementación.............................. 30 4.4.2. Aprendizaje de modelos . . . . . . . . . . . . . . . . . . . . . . . . . 31 4.4.3. Selección de modelo para generar una respuesta . . . . . . . . . . . . 31 4.4.4. Creación e interacción con un Bot . . . . . . . . . . . . . . . . . . . . 31 4.5. FilterParameters................................. 32 4.5.1. Filter Parameters en los scripts . . . . . . . . . . . . . . . . . . . . . 33 4.6. Inferencia de parametros de filtrado . . . . . . . . . . . . . . . . . . . . . . . 33 4.6.1. Inferencia de Positivity Factor ...................... 33 4.6.2. Inferencia de keywords .......................... 34 4.6.3. Inferencia de Slang Factor ........................ 34 4.7. Base de datos de relaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 4.7.1. Implementación.............................. 35 4.7.2. factsGeneration.py ............................ 35 4.8. Unificación de entidades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 4.9. Scripts....................................... 36 4.10.Generadordecorpus ............................... 37 4.11. Setup e instalación de entorno Python . . . . . . . . . . . . . . . . . . . . . 38 5. Arquitectura e Implementación 39 5.1. Arquitectura de la aplicación frontend . . . . . . . . . . . . . . . . . . . . . 39 5.1.1. Consideraciones previas en el desarrollo de una APP . . . . . . . . . 39 5.1.2. Estructurabásica............................. 40 5.1.3. Patrón del flujo de datos . . . . . . . . . . . . . . . . . . . . . . . . . 41 5.1.4. Inicialización de la aplicación frontend . . . . . . . . . . . . . . . . . 43 5.1.5. Diagramas de clases de las Stores y Models . . . . . . . . . . . . . . . 43 5.1.6. Diagramas de clases de los Services . . . . . . . . . . . . . . . . . . . 45 5.2. Arquitectura del servidor de NodeJS . . . . . . . . . . . . . . . . . . . . . . 46 5.2.1. Consideraciones previas . . . . . . . . . . . . . . . . . . . . . . . . . 46 5.2.2. Estructurabásica............................. 46 5.2.3. Flujo de enrutado de las peticiones HTTP . . . . . . . . . . . . . . . 47 5.2.4. Diagramas de clases de los Controllers, Helpers y Models . . . . . . . 49 5.2.5. Diagramas de clases de los Services . . . . . . . . . . . . . . . . . . . 57 5.3. Arquitectura de los scripts de Python para la utilización de Twitter . . . . . 58 5.3.1. Consideraciones previas para la integración de Twitter en Python . . 58 5.3.2. Estructura básica y patrón de datos . . . . . . . . . . . . . . . . . . . 59 5.3.3. Arquitectura de la base de datos de la interacción con Twitter . . . . 59 ii 6. Casos de Estudio 60 6.1. Aplicando la solución en un entorno propuesto . . . . . . . . . . . . . . . . . 60 6.2. Caso de uso: Crear y entrenar una nueva trollnet . . . . . . . . . . . . . . . 61 6.2.1. Fase 1: Frontend Web - procesar el input del usuario . . . . . . . . . 61 6.2.2. Fase 2: Servidor Web - iniciar la creación de la trollnet . . . . . . . . 63 6.2.3. Fase 3: Ejecución Python - creación de un bot . . . . . . . . . . . . . 63 6.2.4. Fase 4: Servidor Web - control y fin de la creación de la trollnet . . . 63 6.2.5. Fase 5: Ejecución Python - vincular cuentas a los bots . . . . . . . . 64 6.2.6. Fase 6: Servidor Web - iniciar proceso de entrenamiento de la trollnet 64 6.2.7. Fase 7: Ejecución Python - entrenamiento de un bot . . . . . . . . . . 65 6.2.8. Fase 8: Servidor Web - control y fin del entrenamiento de la trollnet . 65 6.2.9. Fase 9: Frontend Web - chequeo periódico del progreso . . . . . . . . 66 6.3. Caso de uso: Entrenar un modelo . . . . . . . . . . . . . . . . . . . . . . . . 66 6.3.1. Fase 1: Servidor Web - detección del corpus y comienzo del proceso . 66 6.3.2. Fase 2: Ejecución Python - entrenamiento de un modelo a partir de uncorpus ................................. 67 6.3.3. Fase 3: Servidor Web - actualización de la MDL y control del proceso 68 6.4. Caso de uso: Generar una conversación . . . . . . . . . . . . . . . . . . . . . 68 6.4.1. Fase 1: Frontend Web - procesar el input del usuario . . . . . . . . . 68 6.4.2. Fase 2: Servidor Web - preparación inicial y petición de escucha . . . 69 6.4.3. Fase 3: Ejecución Python - escuchar la próxima publicación de la cuentaobjetivo .............................. 69 6.4.4. Fase 4: Servidor Web - inicio del proceso de conversación . . . . . . . 70 6.4.5. Fase 5: Ejecución Python - generación de respuesta . . . . . . . . . . 70 6.4.6. Fase 6: Servidor Web - recoger respuesta y lanzar flujo de publicación 70 6.4.7. Fase 7: Ejecución Python - publicación de respuesta en Twitter . . . 71 6.4.8. Fase 8: Servidor Web - control y fin del proceso . . . . . . . . . . . . 71 7. Conclusiones 72 7.1. Inteligenciadeunbot............................... 72 7.1.1. Generacióndetexto ........................... 72 7.1.2. Base de datos de relaciones . . . . . . . . . . . . . . . . . . . . . . . 73 7.1.3. Inferencer ................................. 74 7.1.4. Análisis de sentimiento . . . . . . . . . . . . . . . . . . . . . . . . . . 74 7.1.5. Conclusiones de la sección . . . . . . . . . . . . . . . . . . . . . . . . 74 7.2. Conclusionesgenerales .............................. 75 7.2.1. Líneas de trabajo futuro . . . . . . . . . . . . . . . . . . . . . . . . . 76 7. Conclusions 77 7.1. Bot’sintelligence ................................. 77 7.1.1. Textgeneration.............................. 77 7.1.2. Relationships database . . . . . . . . . . . . . . . . . . . . . . . . . . 78 7.1.3. Inferencer ................................. 78 iii 7.1.4. Sentimentanalysis ............................ 79 7.1.5. Sectionconclusions............................ 79 7.2. Mainconclusions ................................. 79 7.2.1. Futurework................................ 80 8. Contribuciones 81 8.1. Enrique Ballesteros Horcajo . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 8.2. SergioCaleroRobles ............................... 83 8.3. JaimeFernándezDíaz .............................. 85 8.4. VenturaMateosPérez .............................. 86 Bibliography 90 A. Imágenes del Estado del Arte y del Business Plan 91 B. Imágenes de la Arquitectura e Implementación y de los Casos de Uso 100 iv Capítulo 1 Introducción En este capítulo se expondrán de forma breve las motivaciones y objetivos del equipo del proyecto a la hora de realizar este Trabajo de Fin de Grado (TFG), así como una pequeña guía sobre la estructura de esta memoria. 1.1. Motivación Las redes sociales continúan creciendo a un ritmo constante y cada vez más personas se adaptan a su uso. Lo que en el pasado podría ser una simple tarjeta con un número de teléfono, hoy es un perfil online con varios enlaces a las distintas cuentas que un usuario tiene en diversas redes sociales. Para muchos, se han convertido hasta en una necesidad, en un medio indispensable para estar al tanto de lo que ocurre a su alrededor, o para comunicarse con los suyos. Y no es sólo eso, también son un gran medio para publicitar multitud de servicios, y compartir opiniones sobre los mismos. Por otro lado, la Inteligencia Artificial ha mejorado mucho en los últimos años, habiéndose desarrollado multitud de técnicas muy potentes y novedosas para, por ejemplo, el Machine Learning, una tecnología de gran utilidad. Y es aquí donde uno se pregunta, ¿por qué no hacer uso de estas revolucionarias herramientas para crear un servicio que aproveche el gran impacto que tienen las redes sociales hoy en día? Esto mismo, junto a una leve curiosidad de ver hasta qué punto se pueden aprovechar estas técnicas, es lo que ha motivado al desarrollo de la aplicación que se presenta en este TFG, mediante la cual cualquier usuario o empresa podrá contratar a unos bots para que discutan y opinen sobre los temas que ellos deseen, generando interacciones en redes sociales (en el caso de este proyecto, en Twitter). 1.2. Objetivo Es esencial, por supuesto, ofrecer un servicio único e innovador, y ese es el principal objetivo de este TFG. Se pretende crear una aplicación que no simplemente genere mensajes que se parezcan a los escritos por un ser humano, sino que hable consigo misma y sus propios mensajes, tenga opiniones positivas o negativas sobre distintos temas, según la cuenta (de 1 un control completo y sencillo sobre lo que se quiere contratar. El precio es de 0,27 euros por comentario positivo automático o de 0,42 euros por comentario redactado por el propio cliente. Resulta muy interesante esta opción de poder elegir qué tipo de comentario puede comprarse, dando una sensación de profesionalidad a la página. Disponen también de una opción más económica que ofrece 100 respuestas por 17,87 euros. Sin embargo, no debe olvidarse que es un servicio en inglés y que se ofrece en dólares, por lo que el precio en euros es al cambio actual (en el momento de la redacción 1 euro equivale a 1,13 dólares) y en un futuro podría variar. Aún así, ninguno de sus paquetes se acerca a los 0,15 euros por interacción. Finalmente queda analizar el primer resultado que coloca Google en su buscador para la compra de comentarios y respuestas en redes, este es la empresa BULKCOMMENTS. Se centra en ofrecer comentarios y respuestas para redes sociales, como puede intuirse por su nombre. Ofrece respuestas interaccionales para Twitter yFacebook por un precio muy competitivo comparado con el resto de ofertas: disponen de cinco paquetes dependiendo del volumen para los que el precio va desde los 0,2 euros hasta los 0,3 euros por respuesta interaccional. Insisten en la calidad de las respuestas y comentarios y garantizan que no utilizan bots, que las interacciones se realizan desde cuentas por todo el mundo y desde diferentes direcciones IPs. En el mercado anglosajón por tanto se encuentra una media de 0,515 euros la interacción en los paquetes más caros del mercado y de 0,35 si se analizan las opciones más económicas. La opción más barata que se ha encontrado es la de PAYSOCIALMEDIA que ofrece un paquete en el que cada interacción se encuentra por un precio de 0,17 euros. 2.3. Conclusiones sobre el estado del arte En el estudio realizado sobre las empresas de habla hispana se han detectado grandes carencias en los servicios, comparándolos con los servicios de las empresas de habla inglesa líderes a nivel mundial es evidente que hay una gran distancia entre ambas. No solo a nivel de precios del servicio, de marketing y colocación de producto. Se ha observado que los productos que ofrecen las empresas angloparlantes son más completos y además ofrecen servicios de valor añadido que las hispano-hablantes no tienen en su catálogo. Destaca especialmente la oferta de respuestas y comentarios en redes sociales, ya que en las empresas de habla hispana no disponen de este servicio, que sin embargo aparece en todas las de habla inglesa. Especialmente destacan las ofertas de respuestas positivas a favor de ciertas publicaciones señaladas por el cliente, un servicio que solo se ofrece en inglés y con precios muy elevados. Se concluye, por tanto, que si bien existe un núcleo de servicios que ofrecen todas las empresas dedicadas a la venta de servicios para la mejora de la tasa de interacción en redes sociales, en la actualidad no hay ninguna empresa líder del mercado que ofrezca respuestas y comentarios a precios competitivos. Parece así que hay una falta clara de oferta de servicios de respuestas interaccionales complejas que generen debate e interacciones adicionales a precios competitivos y sin la necesidad de una participación continua del cliente. 8 Capítulo 3 Business Plan A continuación se presenta el plan de desarrollo del negocio para la empresa de servicios de valor añadido en redes sociales. En este plan de negocio se orientará la oferta de servicios propuesta a interacciones conversacionales en redes sociales, con el objetivo de cubrir la falta de oferta que se ha podido detectar en el análisis del estado del arte presentado en el capítulo 2. El servicio tendrá un precio competitivo y una oferta de servicio de valor añadido que los competidores no tienen: respuestas que generen debate y nuevas interacciones de otros usuarios sobre las conversaciones en las que aparezcan. Se presentará un modelo de servicio al cliente similar al que ofrecen todas las empresas del sector, basado en la compra de paquetes de interacciones. La plantilla de la empresa estará formada por cuatro ingenieros informáticos que trabajarán a jornada completa durante todo el año, en remoto y utilizando sus propios equipos informáticos para reducir los costes todo lo posible. El servicio estará completamente alojado en la nube de Microsoft, en Azure, eliminando así la necesidad de inversión inicial en infraestructuras. En la estrategia de marketing se manejará una opción de búsqueda de capital a través de aceleradoras de Startups españolas, y otra opción alternativa que no requiere de inversión de capital externo. Se analizarán las debilidades y puntos fuertes del negocio y de las estrategias de marketing y financiación que han sido seleccionadas. En el plan de negocio propuesto se plantearán diversas estimaciones de evolución financiera en función de los puntos débiles que han sido detectados. Los objetivos principales serán alcanzar una situación de equilibrio financiero y el retorno completo de la inversión inicial. 9 3.1. Modelo del servicio El modelo de servicio se plantea de forma similar al que ofrecen todas las empresas del sector: el cliente pagará por cada interacción conversacional que reciba su perfil y realizará la contratación de estas interacciones mediante la compra de distintos paquetes predefinidos que le ofrecerán reducciones en el precio dependiendo del volumen de interacciones que contrate: Pack Prueba: es el paquete básico y gratuito que se ofrece a los clientes que quieran probar el servicio. Incluye 10 interacciones conversacionales que podrá utilizar como quiera. Pack Semanal: es el paquete pensado para empresas que contratan por primera vez los servicios y quieran realizar pruebas complejas con el servicio. También está pensado para pequeñas empresas que no quieran realizar una gran inversión inicial. Ofrece el peor coste por interacción, 0,36 euros por respuesta que se emita. Pack Estándar: el paquete pensado para empresas medianas, ofrece 10 interacciones diarias durante un mes a un precio de 300 euros. Se espera que sea la opción contratada inicialmente por los clientes y que posteriormente la mayoría evolucionen a la opción PRO. Pack PRO: el objetivo de la empresa es que todo cliente importante contrate mensualmente este paquete, garantizando así la sostenibilidad de la empresa mediante clientes fieles al servicio. Pack Premium: se ofrecerá a los grandes clientes que excedan las 1.000 interacciones mensuales. Ofrece el precio más competitivo del mercado por interacción conversacional, y se espera que sea un buen reclamo para atraer grandes clientes. Si bien el cliente podrá configurar el número de interacciones que recibirá por publicación, el mínimo de interacciones que se realizarán siempre que el cliente tenga contratado algún paquete será de mínimo 10 por día, 70 semanales o 300 mensuales. Necesario para asegurar que cada mes se cubran los costes que genera cada cliente. Como opción alternativa se ofrecerá un servicio compartido con otros cliente que no garantizará la misma calidad del servicio dedicado pero que dejará libertad en la velocidad del consumo de las interacciones compradas. El objetivo de estos precios es ofrecer un servicio único por un precio competitivo muy complicado de igualar por las empresas existentes que utilizan metodologías manuales o automatizaciones muy elementales. La contratación del paquete Premium será adicional a la contratación del paquete PRO y requerirá de un plan específico aprobado por la empresa. 10 Pack contratado Coste total Interacciones contratadas Coste individual Prueba 0e10 0e Semanal 25e70 0,36e Estándar 100e300 0,33e PRO 1.000e5.000 0,20e Premium 0,15e1 0,15e Cuadro 3.1:Paquetes ofertados a cliente Coste salarios mensuales Coste salarios anual 8.491,47e101.897,6e Cuadro 3.2:Salarios 3.2. Gastos fijos de la empresa En los gastos que la empresa tendrá todos los meses se han incluido los salarios de los trabajadores y el coste de la infraestructura de computación, en este caso servidores virtuales en la nube de Microsoft. 3.2.1. Salarios En una estimación inicial de costes la empresa deberá pagar el salario de los cuatro integrantes del equipo actual (véase figura A.11 del Apéndice A), que percibirán el salario bruto estimado para un ingeniero informático recién egresado. Este salario se ha fijado en 1.400 euros brutos basado en los valores medios que publica la empresa de contratación Jobted 7. Una vez fijado el salario bruto que percibirán los empleados, se añade una estimación de los distintos impuestos que se deberán pagar por estas contrataciones basados en las estimaciones de Marina Camacho en el blog Factorial 2: si bien puede variar según el convenio colectivo, se estima el gasto total por mes en 1.819,6 euros por ingeniero informático. Debe tenerse en cuenta además que la retribución anual será de 14 pagas, por lo que el gasto por ingeniero final será de 25.474,4 euros al año. 11 3.2.2. Coste de los servidores El precio mensual de cada servidor necesario se ha obtenido tomando como referencia los costes aproximados que se indican en la web de Azure en función de los parámetros que requieren los bots, y se han comprobado mediante un piloto de prueba que se ha ejecutado en un servidor contratado utilizando la opción de prueba gratuita del servicio. Los requerimientos de los servidores se han obtenido mediante pruebas de carga en un servidor virtual piloto creado en Azure, junto con las pruebas realizadas en los equipos locales. Los requerimientos en el número de servidores vienen por la necesidad de un servidor central, un servidor para los clientes en prueba y un servidor dedicado para cliente que contrate paquetes no gratuitos. En las pruebas de carga se ha estimado que es suficiente con un servidor dedicado por cliente: Habrá por tanto en todo momento un servidor dedicado a la centralización de la información de los bots, al entrenamiento de estos a partir de los distintos modelos y peticiones de cliente, cuyo requerimiento es un mínimo de 8 GB de memoria RAM de acuerdo a las pruebas de carga realizadas. Con estos parámetros y utilizando la calculadora de Microsoft 8 para máquinas virtuales desplegadas en Azure, se estima un coste de 73,92 euros al mes por máquina(véase figura A.12 del Apéndice A). Se proveerá además otro servidor de las mismas características donde se ejecutarán todos los bots conversacionales de planes gratuitos y donde se ejecutará la web de la propia empresa. Al ser el plan gratuito, las interacciones no serán muy numerosas, por lo que se estima que con uno será suficiente en todo momento. Hay que tener en cuenta que el plan gratuito estará limitado en tiempo para cada cliente. En este servidor adicionalmente podrán correrse bots de aquellos clientes que requieran pocas interacciones diarias, esto es menos de 10 interacciones que no suponen una carga excesiva para el mismo. Adicionalmente, por cada cliente que contrate cualquier otro plan se provisionará una nueva máquina dedicada para el mismo. Esto es con el objetivo de que cualquier prueba, modificación o cambio sobre un cliente no afecte al resto de clientes importantes. 3.3. Modelo de negocio sostenible Teniendo como objetivo principal encontrar un equilibrio económico sostenible para la empresa, la meta es que los ingresos por clientes de paquetes PRO (véase el cuadro 3.1) superen al conjunto de gastos de la empresa. El resto de paquetes tienen como objetivo que el cliente acabe contratando el paquete PRO, por lo que el resto de paquetes no se tendrán en cuenta para el balance contable. Por tanto se estima una necesidad mínima mensual de 10 clientes PRO de acuerdo a las estimaciones que pueden verse en la figura A.13 del Apéndice A. Para dar servicio a este número de clientes se requerirán 12 servidores basados en los test de carga realizados, que junto con los distintos gastos añadidos por personal (véase la figura A.11 del Apéndice A) arrojan los datos finales del balance sostenible: 7.508,53 euros (véase la figura A.13 del Apéndice A). Este es el objetivo mínimo que se plantea conseguir a un año vista de cara a la sosteni12 bilidad futura de la empresa. 3.4. Plan de negocio En el desarrollo del modelo de negocio se plantean dos escenarios posibles: un primer escenario sin necesidad de ninguna inversión de capital externo para el funcionamiento de la empresa (véase sección 3.4.1): para ello será necesario contar con el consenso de todos los integrantes de la empresa y la colaboración de empresas del sector del negocio de la interacción en redes sociales. Un segundo escenario en el que se buscará financiación externa (véase sección 3.4.2): para este escenario contemplaremos la opción de financiarnos a través de aceleradoras o inversores de Startups. 3.4.1. Modelo de negocio sin necesidad de buscar financiación externa Se plantea un modelo de negocio que tiene como objetivo recuperar completamente la inversión inicial a partir del segundo año. Además, como segundo objetivo se plantea no requerir ninguna financiación a partir del mes 13, buscando lograr un balance positivo a partir del mismo. Para la inversión inicial, requerida para cubrir los gastos de los primeros 14 meses, se estima necesario un capital inicial de 61.072 euros. Sin embargo, la primera propuesta para evitarlo es ofrecer a los empleados participaciones en la empresa durante los primeros 14 meses, reduciendo así los gastos previstos para los primeros 14 meses a 17.328 euros (debe tenerse en cuenta que sí deberá pagarse la parte correspondiente a impuestos de los salarios). Estos 17.328 euros podrían solicitarse como préstamo en bancos, sin embargo la primera opción es que se adelante por los mismos empleados de la empresa. De esta forma se ahorraría el pago de comisiones y los gastos derivados de todas la financiación bancaria y no se dependería de capital externo. Con este horizonte en mente se propone un escenario de crecimiento mes a mes, puede verse un ejemplo en la tabla de la figura A.16 del Apéndice A, como objetivo de evolución del negocio. Los dos primeros meses se plantean como toma de contacto con las empresas intermediarias, empresas de marketing, inmersión en el mercado, pruebas de concepto con clientes y contratación de los primeros paquetes Estándar, por lo que no se espera contar con clientes contratando ningún paquete PRO. A partir del tercer mes se espera haber logrado al menos un cliente PRO. Sin embargo, es pasado el cuarto mes cuando será necesario un crecimiento consistente de un cliente importante y fiel cada mes, que contrate el paquete PRO para alcanzar los objetivos de negocio. Para conseguirlo será necesario un producto de calidad que garantice clientes fieles que no se den de baja y que anime a los clientes pequeños a optar por este paquete. Así, a partir del primer año y ya con diez clientes de estas características se alcanzaría el objetivo un balance positivo mensual. Adicionalmente y con el objetivo de recuperar en 24 meses la inversión inicial se requiere mantener este crecimiento 13 hasta finalizar los dos primeros años. A partir del segundo año (mes 13) se comienza a tener un balance contable positivo (puede observarse con facilidad en la tabla de la figura A.16) y tras la finalización de los dos años, nos queda un balance global positivo de 7.508 euros. Una vez alcanzado este objetivo de retorno de la inversión inicial junto con la estabilidad en el balance contable, se comenzará a expandir y generar un conjunto propio de clientes de cara a la independización. Figura 3.1:Gráfica de evolución mensual En cuanto al retorno de la inversión, se puede ver en la gráfica de evolución mensual de la figura 3.1 cómo hasta el mes 24 no se alcanza un balance acumulado positivo. También puede observarse muy claramente cómo a partir del mes 12 los ingresos superan a los gastos, alcanzando un balance mensual positivo a partir de este. Es importante hacer notar ese objetivo de llegar a partir del primer año a un balance positivo mensual, ya que de no ser así el acumulado seguiría descendiendo, agravando la situación económica y retrasando la fecha de recuperación de la inversión. 3.4.2. Modelo de negocio con inversión externa En caso de que no exista consenso entre los integrantes de la empresa para proporcionar el capital inicial y acuerdo para el cobro de los salarios en participaciones, será necesario un mínimo de 61.072 euros de capital inversor inicial para arrancar con unas garantías mínimas el funcionamiento de la empresa. Además, en caso de que no se consiga llegar a un acuerdo con las empresas dominantes del sector hispanohablante de compra de interacciones en redes 14 sociales, será necesaria una inversión adicional en marketing de 13.000 euros mínimo(véase las sección 3.5), que podría subir a los 26.000 euros si quieren adelantarse los dos primeros años en marketing digital. En total se podría llegar a necesitar una inversión superior a los 74.000 euros solo para el primer año de funcionamiento. Existen numerosas formas de conseguir financiación para una empresa nueva6: pedir un crédito al banco, inversores privados, fondos de capital riesgo, subvenciones públicas, financiada a través de los propios trabajadores, mediante campañas de financiación colectiva, colaborando con otras empresas, presentándose a concursos o pidiendo el dinero a amigos o familia, etc. En el primer modelo que se ha definido, el objetivo es financiar la empresa mediante la financiación por los propios trabajadores y ahorrar costes colaborando con empresas asentadas en el sector. Sin embargo, en caso de que esta opción no sea posible, se ha decidido como alternativa buscar inversión externa mediante aceleradoras de Startups. Esta decisión se debe a que este tipo financiación se ajusta perfectamente a las características de la empresa10: trabajadores jóvenes recién egresados, un proyecto ilusionante con gran innovación tecnológica, necesidad de mentorización en la gestión del negocio y gran posibilidad de crecimiento. Conseguir la financiación de una aceleradora de Startups es muy complicado, sin embargo en España existen numerosas aceleradoras11 que buscan proyectos novedosos, para las que la oferta propuesta (que une redes sociales e inteligencia artificial) puede resultar muy interesante. En este modelo se considera presentar el proyecto a la aceleradora Wayra, ya que ofrece un mercado global que permitiría crecer más allá de España. Está financiada por Telefónica, una de las grandes empresas del Ibex 35 de España. La aceleradora Wayra ofrece el capital inversor que se requiere, entre 50.000 euros y 250.000 euros. Además Wayra daría acceso a la oferta de servicios de Telefónica, como el servicio de alojamiento en la nube que permitiría reducir los gastos mensuales (puede verse la figura A.17 del Apéndice Acomo referencia). 3.5. Plan de marketing El mercado de empresas de venta de interacciones en redes sociales está plagado de páginas que ofrecen todo tipo de servicios, sin embargo la opción de interacciones conversacionales de gran calidad que generen debate no está extendida en el mercado internacional. Por ello, la opción para crecer más rápido parece ser ofrecer el servicio a estas empresas que ya están colocadas en el mercado y que tienen un buen banco de clientes, pero que no ofrecen este servicio. Un ejemplo es la empresa COMPRASOCIALMEDIA (véase la figura A.1 en el Apéndice A), la empresa dueña de compra-seguidores.com, una de las empresas más completas según Encarni Arcoya de ActualidadeCommerce 1para la compra de todo tipo de interacciones en Twitter,Facebook y otras redes sociales. El objetivo es realizar una oferta de servicios a estas empresas ya colocadas en el mercado ofreciéndoles un servicio novedoso de gran calidad, permitiendo una inmersión rápida en el 15 mercado desde el inicio, evitando así la necesidad de una inversión de capital inicial en marketing. Se realizará un acercamiento inicial mediante el contacto indicado en sus webs online, buscando una reunión cara a cara para realizar una oferta en la que las empresas ya asentadas en el mercado ofrezcan este servicio a sus clientes a cambio de una comisión fija por cliente. Esto les permitirá completar su oferta ofreciendo un servicio del que no disponían, así como un ingreso extra. A la empresa se le facilitará una base inicial de clientes a partir de la cual crecer de forma sostenible. Esta opción conlleva varios riesgos que se desarrollarán en el apartado 3.6, por lo que alternativamente en caso de que esta estrategia de marketing no surta efecto y no se obtengan los resultados esperados o se deseche por tener suficiente capital inversor inicial, se contemplará la opción de anunciarse en Google Ads. En este caso, será necesario ampliar la inversión inicial en unos 26.000 euros adicionales para garantizar la financiación del marketing los dos primeros años, lo que retrasaría el comienzo de la recuperación de la inversión hasta el mes 26, contando con el mismo crecimiento esperado hasta el mes 24(puede verse en la gráfica de la figura A.15 del Apéndice A). La inversión calculada en este caso en marketing se estima en 1.000 euros mensuales basándose en las estimaciones realizadas por Javier Mir, experto de xplora empresa líder en marketing web, que establece4un coste aproximado de 900 euros al mes. Tomando un margen de 100 euros que se cree necesario para asegurarse estar en las previsiones por encima de la media nacional de inversión en marketing digital14. Toda la gestión del marketing se dejaría a la empresa xplora anteriormente mencionada, ya que no se dispone de un experto en marketing y es la opción que permitiría un crecimiento más rápido. En caso de requerirse esta inversión inicial en marketing se requeriría la opción desarrollada en el modelo de negocio (véase sección 3.4.2) con una inversión inicial de capital externa. 3.6. Análisis de debilidades, amenazas, fortalezas y oportunidades En este plan de negocio se han realizado varios modelos con el objetivo de cubrir distintos escenarios que podrían surgir. En base a estos escenarios, se va a realizar un análisis de los principales elementos del plan: sus debilidades, las amenazas que pueden surgir, las mayores fortalezas del modelo y las oportunidades. 3.6.1. Debilidad Se ha planteado en el plan de negocio un posible escenario en el que este producto se ofrece a compañías ya asentadas en el mercado, por lo que no se incluye ningún gasto en publicidad. Sin embargo, esta estrategia para reducir la necesidad de un gran capital inicial es una de las grandes debilidades. Surge al utilizarla la opción de que ninguna de estas empresas esté dispuesta a aceptar los términos y condiciones propuestos o simplemente no 16 les interese ofrecer esta opción de reventa de servicios. En este caso ya se ha planteado como solución utilizar capital propio o una aceleradora de Startups para cubrir esta necesidad financiera. Esta opción como ya se ha visto llevaría a modificar el balance estimado. 3.6.2. Mayor amenaza: mes con balance negativo Dentro de las mayores amenazas para esta empresa está la incapacidad de obtener clientes fieles que compren los grandes paquetes y que ayuden con un gran volumen de ingresos. Para ilustrarlo se muestra un mes con pocos clientes, en el que para el cálculo de los ingresos se estima que una empresa interesada en este servicio contratará de media un paquete PRO y 1000 iteraciones extra del paquete Premium al mes (véase el cuadro 3.1). Sin embargo, no se cuenta con más volumen de grandes clientes más allá de este. Este escenario, reflejado en la figura A.18 del Apéndice A, ilustra como si esto se prolongase a lo largo del tiempo se acumularían grandes pérdidas, estimadas en este caso en 6.313 euros cada mes, y que pondrían en riesgo la supervivencia a largo plazo de la empresa. 3.6.3. Fortalezas, amenazas y oportunidades de negocio Estas tres aristas de este análisis de negocio giran en torno al mismo punto, que es la escasa oferta actual de interacciones conversacionales automáticas a gran escala. Es claramente la gran fortaleza y oportunidad que ofrece, permitiendo entrar en un mercado con poca competencia en este ámbito, que unido al creciente interés y prospectos de mercado de la inteligencia artificial3hace muy atractiva la oferta de la empresa. Esta falta de oferta sin embargo supone también la mayor amenaza para los prospectos de negocio, ya que los clientes ya asentados pueden no llegar a ver interés en el nuevo servicio que se ofrezca al estar acostumbrados a trabajar con otras opciones de interacción ya conocidas y contratadas previamente. Para evitar esto es importante que el producto sea atractivo, especialmente debe hacerse incapié en la calidad de las técnicas de inteligencia artificial utilizadas. La última de las grandes amenazas son las empresas que actualmente copan el mercado en cuanto a subida de tasa de interacción en redes sociales, a quienes incluso se les propone como una de las opciones del plan de marketing del capítulo 3.5 que sean vendedores intermediarios de estos servicios. Estas empresas una vez se empiece a vender el servicio podrían decidir desarrollar sus propias soluciones para ofrecer a sus clientes. Para evitar esto es muy importante que el producto que se ofrezca sea tanto revolucionario como de gran calidad, de forma que estas empresas no puedan desarrollar el mismo producto. Es importante también ir creando tanto una base de clientes fieles que conozcan este producto y lo compren regularmente como una reputación dentro del mercado. 17 Model management from OpenAI’s official GPT-2 repo (MIT License). Model finetuning from Neil Shepperd’s fork of GPT-2 (MIT License). Text generation output management from textgenrnn (MIT License/also created by me). Sobre este paquete se construyen distintos módulos, que facilitan y adaptan a la aplicación su uso, responseGeneration.py ymodels.py. 4.2.2. models.py Este módulo permite crear una interfaz con el paquete, que en este caso facilite la configuración del entrenamiento de un modelo. Consiste en un único método: trainModel(corpusPath, nameOfModel, num_iterations, _model_version) siendo sus parámetros los siguientes: corpusPath: ruta donde se aloja el corpus. nameOfModel: nombre que se le quiere dar al modelo. num_iterations: número de iteraciones que aplicará el entrenamiento. _model_version: versión del modelo base. Además, este módulo define la clase Model, que contiene todos los datos necesarios para poder utilizar los modelos entrenados más tarde. Estos datos también permiten que el bot pueda hacer una selección adecuada de modelo 4.4.3. Keywords de un corpus Una vez se tiene un modelo entrenado, es necesario un mecanismo que describa el corpus con el cual se ha entrenado este, para permitir seleccionar un modelo que se ajuste a lo deseado cuando existen multitud. Un corpus no es más que, al fin y al cabo, un montón de palabras que de alguna manera tienen relación. Entonces si se seleccionan las n palabras más descriptivas o significativas del corpus, aparece una manera de describir de qué va a hablar el modelo. Estas palabras deben conseguir distinguirse del resto de corpus, por tanto el primer paso debe ser eliminar las palabras que no aportan información sobre el contenido, estas son las llamadas stopwords. Una vez eliminadas estas palabras, hay que establecer una jerarquía sobre las restantes, para poder clasificar las n más descriptivas. Esta jerarquía sobre las palabras, sobretodo cuando se habla de un modelo que genera texto de la misma manera que el corpus está redactado, es lógico que sea el número de veces que aparece la palabra en el corpus. Por ejemplo, si en un corpus aparece muchas veces la palabra política, se puede pensar que es bastante probable que el modelo la introduzca en los textos que genere. Consiguientemente, 24 lo único que se debe hacer es un recuento de todas las palabras (ya filtradas sin stopwords), y seleccionar las n que mas aparecen, y este es el mecanismo que sigue un modelo para generar sus keywords. La implementación del conteo se realiza en C++, debido a que es una tarea potencialmente costosa y se requiere eficiencia, por lo que evitar la naturaleza interpretada de Python, y su gestión automática de memoria es recomendable, además C++ dispone de estructuras de datos optimizadas que serán útiles. El algoritmo es el siguiente, se leen todas las palabras en el texto y se cuentan haciendo uso de un unordered_map, que permite que el coste del conteo sea O(n), aprovechando que el coste mínimo posible para leer las palabras es el mismo. Además, se guardan en una lista no ordenada las claves del mapa, sin repetir. Una vez realizado el conteo, se ordenan las palabras mediante el uso de una cola de prioridad, implementada como Fibonacci Heap. Se recorren todas las claves guardadas en la lista, y se insertan en la cola con coste total en el peor caso de O(n). Por último se lee mveces la cabeza de cola (siendo m el número de palabras que interesa hallar, i.e. las 100 primeras), con un coste de m·log n. Esto da un coste final de n+n+m·log n. Se podría discutir que una mejor solución utiliza inserción ordenada, pero a continuación se describe por qué a partir de m= 100 para tamaños de corpus de unas 30000 palabras y en adelante, esta es una peor solución. Una solución utilizando inserción ordenada, puede ser la siguiente: A medida que se leen las palabras (O(n)), se insertan en una lista enlazada ordenada el elemento. Utilizando búsqueda binaria, se tiene un coste de O(log n)para elementos nuevos. En el caso de un elemento ya presente en la lista (i.e. una palabra que ya se ha encontrado anteriormente), el coste para insertar es como mínimo O(log n)de nuevo: si se guardasen las posiciones de las palabras en la lista en un HashMap, el borrado del elemento sin actualizar en la lista y la correspondiente actualización de punteros tiene un coste de O(1), más su inserción en la lista en la nueva posición O(log n). Despreciando la lectura con coste O(m)posterior, el coste total sería O(n·log n), un coste mayor al encontrado con el método anterior. Una posible mejora a este método, es adaptar el tamaño de la lista a O(m), en vez de O(n). De este modo, solo se guardan en la lista las palabras que más tarde serán leídas, haciendo uso de un HashMap de manera auxiliar que guarda los contadores de todas las palabras. Esto hace que el coste de una inserción en el peor caso (el caso en que esta palabra está entre las m primeras), sea de O(log m), si se sigue el mecanismo anterior, lo que da un coste total de O(n·log m). Aunque se obtiene una mejora muy grande, y un coste muy similar al primer método, este sigue siendo superior a medida que nymse hacen grandes. Models Descriptor List Para que la aplicación pueda guardar los modelos que ya ha entrenado, con todos los datos necesarios para describirlos, se utiliza la Models Descriptor List, que se implementa como una lista de Python que contiene descriptores de modelo (modelos en JSON). Esta lista a su vez se convierte a JSON para que la aplicación pueda guardarla facilmente. 25 Figura 4.6:Negro: n·log nRojo: n+n+m·log npara m= 106 Figura 4.7:Azul: n·log mRojo: n+n+m·log npara m= 110 26 4.2.3. responseGeneration.py Este módulo se encarga de proporcionar una interfaz con el paquete gpt-2-simple, que permita parametrizar y filtrar la salida que se genera. Esta interfaz consiste en un método principal: generateResponse(model, posFactor, slangFactor, keyWords, nchars, number_of_responses, prefix) Estos parametros se pueden dividir en aquellos que se le proporcionan al modelo, y aquellos que se utilizan en el filtrado. Los parametros dirigidos al modelo son: number_of_responses: número de textos candidatos que se generan. prefix: prefijo a partir del cual el modelo generará el texto. Por otra parte, los parámetros dirigidos al filtrado son: posFactor: factor de positividad. slangFactor: factor de informalidad. keyWords: palabras clave. nchars: número máximo de caracteres que debe tener la salida. Filtrado de textos candidatos El modelo se ocupa de generar un número de respuestas, llamados textos candidatos. Todos ellos pasan por el pipeline de filtrado, formado por una serie de funciones de filtrado, que se aplican en orden. Estas pueden ser funciones de puntuación, las cuales puntúan de 0 a 10 al texto candidato según su criterio de filtrado, o bien funciones de modificación, que alteran el contenido de estos textos candidatos, limitando los caracteres o añadiendo expresiones informales. El texto candidato que más puntuación consiga será la salida. Todas las funciones de filtrado deben cumplir una serie de estándares: La entrada es una lista de duplas. Cada dupla está formada por el texto en primer lugar (valor modificado en las funciones de modificación) y la puntuación en segundo lugar (valor modificado en las funciones de puntuación). La salida es una lista de duplas de igual manera. Es recomendable que a esta puntuación se le añada y no asigne, ya que podría machacar puntuaciones aplicadas por otros filtros. Además mantener las puntuaciones de 0 a 10 permite que no haya filtros “overpowered”, que valoren en exceso una característica del texto, haciendo que las puntuaciones del resto de filtros sean insignificantes. Podemos encontrar las siguientes funciones de puntuación, las cuales únicamente alteran la puntuación de los textos candidatos añadiéndoles una puntuación de 0 a 10 cada una. 27 Positividad: Esta función simplemente hace uso del parámetro posFactor para dar mayor puntuación a los textos que tengan una polaridad similar a la del factor dado. Es decir, si el factor es un valor positivo, los textos con un sentimiento igual de positivo recibirán una mayor puntuación que los que tengan un sentimiento demasiado postivo, menos positivo, o directamente un sentimiento negativo. En el mejor de los casos, si ambos valores coinciden, ese texto recibirá 10 puntos. Keywords: esta función hace uso del parámetro keywords, que en el fondo no es más que una lista de palabras clave. Dicho filtro comprueba cuántas de las palabras clave aparecen en cada texto, y luego lo divide entre el número total de palabras clave y lo multiplica por 10. De esta forma se consigue que el filtro siempre otorgue valores entre 0 y 10, cumpliendo así los estándares indicados anteriormente. Por otro lado las funciones de modificación, que utilizan distintos parámetros para modificar ligeramente el texto resultante. Formalidad: se usa para alterar el texto de forma que parezca escrito con más cuidado, si el valor del parámetro es bajo, o escrito de la forma más vulgar de internet, si el valor es alto. En la práctica, se considerarán los textos originales lo más formales posibles, debido a como funcionan los modelos, y a la dificultad que supondría volverlos más formales. Es por ello que los valores bajos del parámetro de informalidad simplemente harán que el texto se modifique menos. Esto se debe a que el filtro toma ciertas medidas para hacer el texto más vulgar, cada una de ellas se ejecuta con una probabilidad que se vuelve más alta según sea más alto el factor. Formato: este filtro formatea el texto de modo que la salida cumpla una longitud máxima determinada. Además elimina anomalías como URLs incompletas, dobles saltos de linea y otras posibles salidas del modelo. Las medidas de informalización empleadas son las siguientes: Abreviar ciertas expresiones en versiones más cortas y muy comunes en el habla de internet. Para ello se hace uso del archivo abbreviations.py, donde se ha creado un diccionario con las expresiones completas como claves, y un par como valor. El par consiste en la expresión abreviada y la probabilidad individual de que se reemplace esa expresión. Estas probabilidades se han predefinido manualmente basadas en la experiencia del equipo usando internet. Por ejemplo, se puede cambiar I don’t know por idk. Añadir ciertas palabras o los conocidos emoticonos al inicio y/o al final de los textos, basados de nuevo en el archivo de abreviaciones, donde se tienen dos diccionarios con expresiones iniciales y finales y sus respectivas probabilidades de aparición. Por ejemplo, se puede añadir :) al final del texto. Eliminar ciertos símbolos de puntuación, en particular el punto, la coma y el apóstrofe (este último se debe a que los textos son en inglés). 28 Cambiar las letras mayúsculas por minúsculas con cierta probabilidad. De nuevo, esta probabilidad depende del factor de informalidad. Añadir pequeños errores de escritura alterando el orden de algunos pares de letras adyacentes en el texto, con una probabilidad muy baja y que sólo ocurre en factores de informalidad superiores a 5. Cabe destacar que todas estas medidas se deben al hecho de que el usuario medio de internet es perezoso y tiende a cometer errores, o acortar frases con tal de enviar su mensaje antes. Por lo que el objetivo es hacer el texto más humano y realista. Este tipo de construcción permite que el escalado y configuración del filtrado sea realmente simple, si se quiere añadir una función de filtrado basta con que cumpla los estándares y se introduzca su llamada en el pipeline. 4.3. Análisis de sentimiento A continuación se describe una herramienta utilizada por distintos elementos de la implementación. Esta herramienta permite analizar textos para sacar información que pueda ser útil en distintos ámbitos, como puede ser el filtrado de textos que se explicará más adelante. Para este propósito se construye funcionalidad sobre el paquete de Python Spacy, que implementa pipelines con distintos propósitos para analizar texto, y conseguir distintas informaciones de este. De la herramienta de análisis de sentimiento se pueden sacar las siguientes propiedades sobre un texto: Nombres propios del texto. Sustantivos del texto. Adjetivos utilizados en el texto. El sujeto de las frases. El objeto de las frases. Puntuación de polaridad del sentimiento, 1 muy positivo y -1 muy negativo. Expresiones que describen la polaridad del texto, con su respectiva puntuación. Puntuación de subjetividad del texto, 1 muy positivo y -1 muy negativo. El texto se separa por frases, y se ordena de mayor polaridad absoluta a menor. La implementación se caracteriza por dos clases Python: Classifier yProperties. Cuando se crea una instancia de la clase Classifier, se puede utilizar para analizar distintos textos a través del método classify(text). Este método recibe un texto text como string y nos devuelve una lista de instancias de la clase Properties. Las instancias de este objeto reúnen los atributos analizados por el Classifier descritos más arriba. 29 4.4. Bots Ahora se debe conseguir crear un ”bot”, entendiendo como bot una entidad capaz de responder o formular un texto, que tenga el mayor sentido posible, dado un contexto (ya sea un comentario en Facebook, un tweet, etc). Además, estos bots deben tener (o simular tener) una personalidad, es decir, que hablen de una serie de temáticas en específico, con actitudes negativas o positivas, que utilicen ciertas expresiones... Para ello se disponen de las herramientas descritas anteriormente, el analisis de sentimiento (véase sección 4.3) y los modelos de generación de texto (véase sección 4.2). En principio, se podría entrenar simplemente un modelo, con un corpus suficientemente grande, que reuniera todos estos comportamientos que se quieren simular en el bot. A priori parece que podría funcionar, pero no es una solución muy práctica ni eficiente, ya que apenas se puede controlar qué va a decir el modelo, y podría responder algo que no tiene sentido en el contexto. Por ejemplo, dado un modelo entrenado con los tweets de Jimmy, que es un chico de 19 años al que le encanta el fútbol y la música clásica. Si se quiere generar una respuesta, simulando la parte músical de la personalidad de Jimmy, para responder a otro usuario, no tendría mucho sentido que el bot respondiera hablando de Cristiano Ronaldo. Por otro lado, está el analisis de sentimiento, que podría ser útil en esta situación. Con los datos que extrae el análisis, se podría solicitar al modelo que genere multiples respuestas, analizar cada una de ellas, y realizar un filtrado de las que más se ajusten a la salida esperada. Ahora se puede esperar que la salida se ajuste más a lo deseado, sin dejar tanto al azar, aunque aún es mejorarable. El siguiente paso lógico, es separar los distintos aspectos de la personalidad de Jimmy en distintos modelos. Entonces por un lado está el Jimmy que habla de fútbol, y el que habla de música. Entonces si el bot consigue discernir, dado un contexto, que ”aspecto de su personalidad” debe seleccionar, con mayor seguridad responderá algo coherente, y que simule un comportamiento humano, que es en última instancia el objetivo. Esta idea, aunque en teoría suena bien, tiene algunas limitaciones prácticas, y es que conseguir corpus suficientemente grandes de cada uno de los aspectos de la personalidad de Jimmy, no es una tarea fácil, ni a veces posible. Una solución posible a todos estos problemas, es buscar un equilibrio entre todas las ideas anteriores. Se puede entrenar un modelo con un corpus gigante en el que solo se hable de fútbol, otro gigante en el que se hable de música, etc. Ahora si se quiere que Jimmy hable de música, basta con seleccionar el modelo entrenado en música, y si se le suma al filtrado, hacer que Jimmy odie a Tchaikovsky, pero hable bien de Brahms parece una tarea más asequible. 4.4.1. Implementación Para condensar en atributos las características que se le quieran dar a un determinado bot, este guardará: 1. Edad. 30 2. Nivel de educación (Desescolarizado, educación obligatoria, estudios superiores). 3. Lista de gustos (likes). 4. Lista de disgustos (dislikes). Siguiendo las ideas expuestas anteriormente, los bots serán capaces de aprender de los modelos que se ajusten a su personalidad, es decir, asociarse a este modelo para más tarde utilizarlo para generar una respuesta. Basta con que el bot sepa seleccionar el modelo adecuado en el contexto dado. Este contexto será normalmente un texto corto, de no más de alrededor de 280 caracteres (límite de Twitter). 4.4.2. Aprendizaje de modelos El escenario de partida es el siguiente, existe un bot, con una serie de gustos y disgustos y se dispone de una serie de modelos, cada uno de ellos con sus keywords (véase sección 4.2.2) asociadas. Además existe una base de datos de relaciones que se verán en la sección 4.7. El objetivo es hacer que el bot sea capaz de asociarse a los modelos que se ajusten a sus gustos, simulando que el bot ”sabe” de esa temática. Por ejemplo, si un bot en sus gustos tiene Kendrick Lamar, y se dispone de un modelo entrenado en hip hop, lo ideal es que este bot sea capaz de asociarse a ese modelo. Con todas estas herramientas, el mecanismo que se sigue es el siguiente, el bot recorre todos sus gustos y disgustos, asi como las keywords de cada modelo, buscando las relaciones que existen entre estos conceptos. Estas relaciones tienen una puntuación asociada, de -1 a 1, que muestra la intensidad (ya sea positiva o negativa) de las relaciones. En el mejor de los casos, todos los likes y dislikes tendrán una fuerte relación con todas las keywords, esto hará que la puntuación final fuese (likes + dislikes) * keywords. Si se mide de manera relativa a este valor las puntuaciones halladas, se puede establecer un umbral porcentual que se quiere superar para considerar que un modelo encaja. 4.4.3. Selección de modelo para generar una respuesta Para esta tarea se utiliza un mecanismo muy similar al anterior, en este caso se comprueba la relación entre los sustantivos comunes y propios que existen en el contexto y sentimentAnalysis encuentra, y las keywords de cada uno de los modelos. En el caso en el que un modelo encajase a la perfección con el contexto, todos los sustantivos tendrían una relación fuerte con cada una de las keywords del corpus. A partir de esto, se calculan los grados de relación de manera relativa a ese número. El modelo que mayor grado de relación consiga es el seleccionado. 4.4.4. Creación e interacción con un Bot Para interactuar con los bots, se encapsula la funcionalidad en la clase BotInstance. Sus métodos se describen a continuación: 31 constructor(age, level\_of\_education, loadModels, likes, dislikes): se crea una instancia del bot con o sin modelos asociados. learn(modelDescriptorList): dada la lista de descriptores de modelo, el bot asocia los modelos que se ajusten a su lista de likes y dislikes. generateResponse(context, filterParams): a partir de un texto de partida context, el Bot genera una respuesta. Esta respuesta se puede filtrar bajo una serie de opciones que se configuran tal y como se explica en la siguiente sección. 4.5. Filter Parameters Debido a la naturaleza incontrolable y aleatoria de la generación de texto, se utilizan una serie de parámetros que permiten filtrar el texto que se genera para conseguir ajustar el resultado buscado. Estos parámetros son: 1. keywords: una lista de palabras que se valoran positivamente a la hora de seleccionar una respuesta. Cuantas más de estas palabras aparezcan en un texto candidato, más puntuación conseguirá. Por defecto, no hay keywords. 2. positivity factor: un número, comprendido entre -1 y 1, siendo 1 muy positivo y -1 muy negativo. Este número se compara con la puntuación que le da el análisis de sentimiento a un texto candidato, y cuanto más cercanos sean estos valores, mayor puntuación conseguirá el texto candidato. Por defecto, no se aplica. 3. number of chars: un entero, mayor que 0. Este número sólo indica el largo máximo del texto, medido en caracteres. Este parametro trunca el texto en la ultima frase acabada en ‘.’ que cumpla que el largo del texto es menor o igual que el number of chars introducido. Por defecto, sin límite. 4. number of responses: un entero, mayor que 0. Especifica el número de textos candidatos que el generador producirá. Cuantos más textos candidatos se generen, más probable es conseguir una respuesta que se ajuste mejor a lo buscado, pero el tiempo de computación también aumentará. 5. slang factor: un entero, entre 0 y 10. El slang se podría denominar en castellano como jerga. Como su nombre indica, se refiere al lenguaje informal, en este caso el usado en internet. Cuanto mayor sea el número, más probabilidad hay de que el texto se modifique para tener un toque más casual. Por defecto, no se aplica. Todos estos parámetros se encapsulan en una clase FilterParams, que es la que se le proporciona al bot a la hora de generar una respuesta. 32 4.5.1. Filter Parameters en los scripts Para especificar los parámetros de filtrado en los comandos, se debe seguir la siguiente sintaxis, especificada en filterParams.txt: -k keyword1,keyword2: keywords (default None). -pf float: positivity factor (default None). -nc int: number of chars (default -1, ”i.e.” no limit). -nor int: number of responses of the model (default 10). -sf float: slang factor (default None, must be between 0 and 10). 4.6. Inferencia de parametros de filtrado Partiendo de tener bots que consiguen generar una respuesta lógica dados unos parametros de filtrado, para lograr que los bots sean independientes y conseguir adaptabilidad a diversas situaciones, se debe lograr que los parametros de filtrado se calculen de manera automatica a partir del contexto antes de generar una respuesta. Este contexto será en este caso un post en una red social, es decir, un texto pequeño (alrededor de 280 caracteres de media) que habla de algo muy concreto. Para cada uno de los parametros de filtrado, se utiliza una función distinta. Se describen a continuacion: 4.6.1. Inferencia de Positivity Factor Encontrar el valor adecuado para este parametro es una tarea bastante compleja, ya que automatizar un método de ”comprensión” del contexto y fusionarlo con la personalidad del bot para que este responda con un factor de positividad acorde es algo dificil. Partiendo de la herramienta de analisis de contexto (véase sección 4.3), que separa el texto en frases ordenadas por mayor positividad absoluta (es decir, la frase que mayor intensidad de sentimiento presenta, se puede asumir que esta frase en general describe bien el carácter y de lo que se habla), se intenta ”entender” de la entidad o tema del que se habla. Como se dispone de una base de datos de relaciones (véase sección 4.7), si se encuentra un ”objeto” que esté emparejado se podrá deducir el resultado. Por tanto, se analizan las frases en busqueda de una palabra (o grupo de palabras) que será utilizada como ”resumen” del contexto dado. Se busca este resumen en el siguiente orden, buscando en el siguiente grupo de palabras si el anterior estaba vacio: 1. Objetos de las frases. 2. Nombres propios. 3. Sustantivos. 33 y herramientas de desarrollo entorno a ello (a menudo habilitadas gracias a IDEs como Visual Studio Code) que en último fin redunda en una mayor escalabilidad. Así, para la lógica de negocio se programará en TypeScript, para los estilos se utilizará SASS y para la maquetación el HTML, que además es precompilado por Ionic y Angular para aprovechar sus herramientas. 5.1.2. Estructura básica La estructura básica de la aplicación frontend puede ser resumida en: 1. Componentes - si se piensa en segmentar o desestructurar una vista o sección de la aplicación, se encontrarán tantos de estos como elementos (potencialmente) repetibles (conocidos como component); servirán para aislar diferentes comportamientos que se vayan a requerir en una vista, y se puede replicar un mismo componente tantas veces como se desee en cualquier parte de la aplicación con diferentes parámetros a cada vez. 2. Vistas o secciones - habitualmente se encuentra un elemento de este tipo por cada vista de la aplicación (conocidos como view otemplate); sirven para cargar, presentar y distribuir la información requerida por dicha vista en la aplicación, y permitir la interacción del usuario con dicha vista, transformando sus acciones en ejecuciones de flujos lógicos que pasan por otros módulos de la aplicación. 3. Módulos de manipulación y gestión de datos - en general se tiene uno por cada estructura de datos de la aplicación (conocidos como store); su objetivo es el de proporcionar vías para otros módulos para obtener, almacenar o modificar elementos del tipo de datos específico de dicha store; ésta es la responsable última de obtenerlos, manipularlos o almacenarlos por cualquier medio existente. 4. Servicios para implementar APIs - pueden servir para interactuar con APIs externas o contra bases de datos locales (conocidos como api provider/service en el primer caso ydatabase service en el segundo); generalmente se tiene uno (de cada tipo) por cada estructura de datos que maneje la aplicación; su cometido es ejecutar las llamadas a sendos servicios con los parámetros requeridos (bien sean APIs REST remotas o bases de datos locales) y controlar las respuestas retornadas. 5. Servicios de utilidades - sirven de herramientas utilizables en cualquier sitio de la aplicación, de forma tan independiente que potencialmente son reutilizables incluso entre aplicaciones que tuvieran características o funcionalidades similares (como si de una librería externa se tratase), (conocidos como service); aportarán utilidades puntuales con un nivel de abstracción suficiente como para que el üsuario"no necesite conocer su funcionamiento a bajo nivel, interactuando contra métodos explícitos, sencillos y convenientes. 40 En el punto actual de la aplicación, sólo se encuentra un tipo de estructura existente, ésta es la red o grupo de trolls, que será conocida como trollnet. Por lo general, se observará que las menciones a diferentes módulos son en su traducción al inglés, lo que conviene por facilidad a la hora de manejarse en el flujo del código programado. 5.1.3. Patrón del flujo de datos A continuación se explican los patrones aplicados en el código de la parte frontend, donde se verá que se ha intentado cumplir los principios de separación de responsabilidades y capas de abstracción. Las vistas existentes en la aplicación presentan datos de un tipo de estructura u otro. El template mostrará la información requerida para la funcionalidad de esta vista, adaptándola o filtrándola según se desee exponer; el template obtiene esa información pidiéndosela a la store. A partir de ese momento se crea una capa de abstracción conveniente ya que, por un lado, no es necesario que el template se preocupe de dónde obtener esa información, delegando esa responsabilidad en la store, de forma que permite que el código de la vista sea más limpio puesto que sólo debe preocuparse por cómo mostrar los datos o atender a la interacción del usuario; por otro, se podrá reaprovechar la misma lógica que ofrece la store para este fin en cualquier vista. La figura B.1 del Apéndice Bes un buen ejemplo para explicar esto. Se puede ver como el template de la vista My Trollnets muestra una lista de todas las trollnets existentes. Tras adquirir el array de trollnets a partir de la store de trollnets, el template se encarga de mostrar un componente por cada trollnet en la lista de trollnets. Puesto que no se conoce la longitud de la lista de antemano, y puede cambiar en cualquier momento, la implementación necesita ajustarse a esa dinámica; Angular trae las herramientas necesarias en este contexto: la directiva ngFor permite generar tantos elementos como existan en el array de trollnets (independientemente de su tipo), pudiendo instanciar así un elemento visual por cada trollnet, cada uno con la información específica de dicha trollnet. Así mismo, la figura permite observar que los servicios son usados tanto por lógicas asociadas a las vistas como por las stores (e incluso por otros servicios también). El LoadingService, como ejemplo de estos servicios, ofrece un spinner de carga junto a un mensaje como feedback para el usuario de que un proceso está cargando. Este servicio independiente es quien se encarga de aportar y ejecutar el código necesario para que dicho spinner se muestre; sin embargo no es quien conoce el estado de la vista, por tanto quien sabe si los datos del template han sido pedidos y están en curso de ser recibidos será quien deba mandar la orden para mostrar el spinner, y ese será el módulo que invoque al LoadingService. De la misma forma, este mismo módulo se encargará de ordenar ocultar el spinner cuando los datos hayan sido finalmente recibidos. La figura B.2 del Apéndice Bmuestra el patrón que se utiliza para la obtención de datos. El flujo más crucial del frontend pasa por la store. Cada vez que una vista, componente u otro módulo desee interacción con un elemento del tipo manejado por la store, por ejemplo cada vez que se pida a una trollnet que genere una conversación entorno a un hilo, se pedirá la información de esa trollnet o se lanzará esa actuación a través de la trollnet store. 41 En ese momento, la store será quien decida de dónde obtener la información requerida de esa trollnet, o a qué externo (API o base de datos local) lanzar la petición para generar la conversación. La store se encarga de hacer las veces de manejador/distribuidor de la información del tipo que maneja. En pro de la separación de responsabilidades, conviene aquí un módulo api provider, un servicio que al estar diseñado específicamente para manejar el mismo tipo de datos que la store, extiende las capacidades de la store permitiendo interactuar con la API remota de este tipo. De este modo, si la trollnet store desea obtener la lista más actualizada real de trollnets existentes y su estado, usará el método público del trollnet service getAllTrollnets; cuando el usuario del frontend quiera añadir una nueva trollnet, así mismo hará uso del método público createTrollnet del trollnet service para lanzarle dicha petición al servidor. Dependiendo de cada petición http lanzada desde este servicio a la API remota, se incluyen diferentes características propias de este protocolo, como el tipo CRUD, los headers, así como características definitorias de la API remota, como la url que atenderá la petición y el contenido del cuerpo de dicha petición; estos detalles intrínsecos a cada petición, al crearse esta nueva capa de abstracción (y no simplemente introducir este código también en la store) permite que este servicio se comporte como una caja negra de cara a la store, que no requiere esos detalles para su finalidad de manipular y distribuir la información, y así simplificar el desarrollo, depuración y escalabilidad de cada módulo por separado por la claridad que supone esta separación de responsabilidades. El requisito que esta capacidad implica es que todos los servicios que contactan con la API remota (se encontrará un por cada endpoint existente en la API remota, en general uno por cada tipo de datos importante), deben heredar de la clase ApiGenericProvider, implementando cada método CRUD existente en la API remota que se quiera aprovechar. La figura B.3 del Apéndice Bexpone, para todas las APIs creadas, el diagrama de clases correspondiente. En paralelo se encontrará también un database service que manejará la misma estructura de datos que la store, que extenderá (de la misma forma independiente y abstracta que el servicio proveedor de la API remota) la capacidad de la store de comunicarse con la base de datos local cuando quiera recuperar o modificar una entrada del tipo de datos específico. Hay varias bases de datos existentes posibles al alcance de un proyecto web como éste; se hará uso de la base de datos IndexedDB, propia del motor web del dispositivo (así como de LocalStorage, como backup). IndexedDB es una base de datos No-SQL, orientada a almacenar datos de entradas de gran tamaño, y no bloquea la entrada-salida del hilo principal. Esto encaja muy bien para tratar con objetos JSON, con posiblemente estructuras y tamaños diferentes entre sí. Se observará que cada database service está creado apuntando específicamente a una tabla y ninguna más, con el mismo nombre del tipo de datos manejado por este database service y su store asociada, reforzando así la separación de responsabilidades y la mantenibilidad y escalabilidad del código. Esta separación es conveniente ya que da la posibilidad de intercambiar el servicio de base de datos utilizado, la codificación o características particulares que requiera cada uno sin afectar al flujo de la store, que delega esa responsabilidad en el database service, y se limita en cualquier caso a interactuar con sus métodos públicos. El database service garantizará la persistencia, inmutabilidad y accesibilidad en cualquier momento a los datos que se le confían. A diferencia de los servicios proveedores 42 de la API externa, no se observará que los database service hereden de un mismo módulo pero todos hacen uso del servicio StorageService independiente para crear utilizar la herramienta Storage de Ionic y Angular, que simplifica mucho la interacción a bajo nivel con las BBDD mencionadas. Se expone la clase que sigue TrollnetDatabaseService en la figura B.4 como ejemplo que abarca los métodos más comunes de interacción con su base de datos. Se encontrarán los diagramas para el resto de database services en el apartado 5.1.4. 5.1.4. Inicialización de la aplicación frontend Cuando se inicia la aplicación, se inicializan los frameworks de Ionic y Angular, y se lanza el módulo base que importa todos los demás módulos implementados antes de ser utilizados por primera vez, app.module.ts. En otras características, en este momento es cuando se utiliza el AppRoutingModule, módulo donde se especifican qué rutas (en la práctica, generalmente una por cada vista) existen y qué modulo debe cargarse en cada una de ellas. Después, se crea el app.component.ts que compone la base visual de la aplicación: se encontrará la lógica correspondiente a un menú lateral con una serie de elementos con un título y descripción que, según sea el seleccionado, se cargará a la derecha el módulo que corresponde a la ruta que invoca. Si se desease añadir funcionalidades a la aplicación, como soporte a sesiones de usuarios, ciertos flujos deberían llevarse a cabo en este momento. Por ejemplo, si se debiera detectar si la aplicación tiene un token válido para mantener iniciada la sesión de un usuario, debería hacerse a esta altura, para decidir a posteriori si se muestra una vista de inicio de sesión o registro, o si por el contrario se puede proceder a mostrar vistas y funcionalidades de la aplicación a las que este usuario sí tenga acceso. 5.1.5. Diagramas de clases de las Stores y Models La trollnet store gestiona todo lo relacionado con la lista de trollnets disponibles, por tanto tiene una importancia que merece una explicación más detallada (véase figura B.5 del Apéndice B). Durante la inicialización de la aplicación, se llama al método privado _synchronizeData para hacer uso del TrollnetService que permite obtener la lista de todas las trollnets mediante getAllTrollnets. Como norma genérica aplicable a cualquiera de las stores, cada vez que se interactúe con la API remota a través de cualquiera de sus métodos, se suele llevar a cabo un flujo común y conveniente: se recibir la información del trollnetService contra la API, se guarda en la trollnetDB con _saveTrollnetsIntoDB, el cuál llama a su vez al método refreshList, que extrae el valor recién actualizado de la trollnetDB y actualizar tanto el array privado _currentTrollnets como el observable _currentTrollnetsObservable con su nuevo valor. Cabe destacar que este último paso es muy importante para el flujo de datos en esta aplicación: se usa el patrón Observer/Subscribe, uno de los patrones reconocidos más útiles de los que hacemos uso en la aplicación frontend. Esta funcionalidad nos viene a través de la librería RXJs y permite que cualquier flujo que desee antes o después acceder a la 43 lista de trollnets, se suscriba al observable _currentTrollnetsObservable mediante el método trollnetsChange de la trollnet store. Así, cada vez que la trollnet store actualice este observable, se notificará dicho cambio dinámicamente a todos los suscriptores de dicho observable en ese instante, enviándoles el nuevo valor para que ejecuten el flujo que necesiten en ese instante. Una vez este proceso inicial dota a la aplicación del estado más reciente de las trollnets, con su método _startPollingStatus se inicia un proceso de actualización periódica: cada 10 segundos, y mientras la aplicación frontend esté en funcionamiento, se llamará a _pollStatus, el cual reúne en una lista los identificadores de aquellas trollnets no completamente entrenadas todavía (discriminando a través de su parámetro trainingStatus) si, las hay, le pasa dicha lista al método getUntrainedStatus del TrollnetService para obtener el último estado de creación y de entrenamiento de cada una de las redes y así ir actualizando periódicamente el progreso de cada una de ellas. De nuevo, se produce el proceso encadenado descrito anteriormente con _saveTrollnetsIntoDB yrefreshList. La trollnet store expone también los métodos createNewTrollnet,deleteTrollnet, renameTrollnet,activateTrollnet ydeactivateTrollnet. Todos ellos son autodescriptivos, interactuan con la API para accionar su cometido y actualizan el frontend según se requiera en cada caso. Si cualquier parte del flujo fallase (ya sea en frontend o backend), se rechazan las partes del flujo que pudieran conllevar datos inconsistentes entre sí y el pretexto es que el backend siempre tiene la información fiable, que se obtendrá de nuevo en cualquier caso con la siguiente petición _synchronizeData. Por tanto, es similar a una transacción, garantizando que los datos de la aplicación son coherentes. Se observará que los diagramas de clase, con el fin de permitir los mecanismos necesarios para cada caso de uso existente, demuestran modelos para cada tipo de datos que son claros y concisos (véase figura B.6 del Apéndice B). 1. Para la clase TrollnetModel, se requiere un id como identificador único de la trollnet, un booleano isActive para describir cuándo la red está activada, un número entero creationStatus que determina el porcentaje de avance en la creación de la trollnet y sus bots (0 al comienzo de la creación, 100 cuando está completado y -1 si se ha abortado por un fallo), un número entero trainingStatus que determina el porcentaje de avance en el entrenamiento de sus bots (0 al comienzo del entrenamiento, 100 cuando está completado, -1 si se ha abortado por un fallo), una fecha lastTrained de cuándo se entrenó a sus bots por última vez, un array de strings botList que contiene todos los identificadores de bots asociados a la trollnet, un campo properties que contiene un objeto que sigue el modelo TrollnetDraftModel (descrito a continuación) y que contiene todas las propiedades que caracterizan a una trollnet y un campo de tipo any error para almacenar el último error que pudo ocurrir en el proceso de creación o de entrenamiento de la trollnet, con fines correctivos. 2. Para la clase TrollnetDraftModel, se requieren una serie de campos que describirán las características tanto de la red en sí como de los bots de dicha red. Así, se requiere un customName como nombre personalizado de dicha trollnet, un genders que contendrá 44 los géneros sexuales posibles, el ageInterval para el intervalo de edades posibles, un campo ethnicity las etnias posibles, un objeto culturalLevel para el intervalo de niveles de educación/niveles culturales posibles, un campo moodLevel para el intervalo de positividad o negatividad posible, un campo keywords para contener una lista de palabras clave genéricas sobre las que aprenderán los bots, dos campos likes y dislikes que contendrán listas de palabras clave sobre las que aprenderán los bots y además asociarán a sentimientos de aprecio o rechazo respectivamente, un campo netsize que describirá el tamaño exacto de la red en número de bots, y por último el campo interactionLevel que será útil para calcular el tamaño de las respuestas que aporten los bots. donde almacenar los cálculos generales extraidos de sus sensores asociados a la room. Salvo el customName y el netsize, el resto de características usará o bien el modelo MultipleStringsModel o bien el NumberIntervalModel, descritos a continuación. 3. La clase MultipleStringsModel es una clase auxiliar que aporta utilidad, tiene un campo values que contiene un array de strings. 4. La clase NumberIntervalModel también es una clase auxiliar de utilidad, ésta tiene un campo values que contiene un objeto con 2 propiedades: lower yupper, conteniendo dos valores enteros que limitan inferior y superiormente un intervalo de números enteros. 5.1.6. Diagramas de clases de los Services A continuación, se describen los servicios a través de sus diagramas (véase figura B.7 del Apéndice B). El alert.service.ts y el toast.service.ts son servicios que aprovechan las funcionalidades de Ionic y Angular de alertas ytoasts respectivamente. En sus constructores se encuentra la configuración por defecto necesaria para generarlos según se prefiera y exponen métodos sencillos para usarlos con diferentes características, showAlert yshowToast respectivamente. El loading.service.ts es otro servicio de la misma categoría que ofrece el típico spinner de carga con mensaje adjunto como feedback al usuario de que un proceso está teniendo lugar y le invita a esperar. Está implementado de forma que sea único por toda la aplicación, y que el módulo que lo puede disipar (con dismiss) sea distinto al que puede instanciarlo (con el método expuesto show) si se determina que tiene mayor autoridad para hacerlo. También se puede modificar su mensaje adjunto sobre la marcha con setContent para poder modificarlo sin tener que volver a instanciarlo. El servicio storage.service.ts se utiliza a lo largo de toda la aplicación desde cada database service existente para crear almacenamientos particulares para cada uno a través de create. Una vez existe dicha base de datos, desde cada database service se interactua con esa base de datos a través de get,set,getAll,remove yremoveAll. Internamente hace uso del servicio de Storage de Ionic y Angular, aprovechando las bases de datos ofrecidas 45 por el motor del navegador, en la mayoría de casos siendo preferentemente IndexedDB y como backup LocalStorage. Se ha añadido una funcionalidad adicional de encriptación de los datos para mayor seguridad con la librería crypto-js, encriptando y desencriptando cada entrada al almacenarla o recuperar respectivamente. 5.2. Arquitectura del servidor de NodeJS En esta sección se expondrá el stack tecnológico sobre el que se apoya el backend, la infraestructura que vertebra y comunica el frontend con las ejecuciones de scripts de Python (tanto para los procesos relacionados con los bots como para los relacionados con las redes sociales en los que publican). Se explican los diferentes elementos que lo componen, así como la finalidad de cada uno y los patrones que los relaciona entre sí. 5.2.1. Consideraciones previas Para desarrollar el proyecto que contiene al servidor se ha elegido el MEAN stack (por sus siglas MongoDB, ExpressJS, Angular y NodeJS). Esto viene justificado por los beneficios que aportan sus herramientas: MongoDB, por ser una base de datos no relacional, permite un desarrollo fluido, escalable y no ajustado a diseños arquitectónicos rígidos, permitiendo almacenar objetos JSON sin modelos fijos que puedan ir variando a lo largo del desarrollo permitiendo convivencia entre datos nuevos y antiguos con diferentes estructuras; ExpressJS facilita enormemente el trabajo de implementar una API REST en NodeJS sin los obstáculos que podría presentar éste a priori (tratamiento de peticiones http con herramientas poco intuitivas); estas elecciones se alinean con Angular en el frontend ya que se desarrolla en un mismo idioma o estilo (JS y TS); y NodeJS aporta la existencia de infinitas librerías de sencillo uso, presentes a lo largo de toda la comunidad de usuarios, altamente probadas y actualizadas, dando muchas herramientas que allanan el terreno para centrarse en las implicaciones directas del desarrollo, y cuyos beneficios se enumerarán más adelante. 5.2.2. Estructura básica En términos generales, se puede describir el proyecto backend compuesto por: 1. Enrutadores, se encontrará uno por cada endpoint de la API REST (se conocerán como routers); cada petición http recibida en el servidor se encaminará a través de ellos dependiendo de su tipo CRUD (GET, POST, PUT o DELETE) y la estructura de la URL para ser atendida por el método específico que debe procesar la petición en cuestión. 2. Controladores, se encontrará al menos uno por cada endpoint de la API REST por lo general habrá uno por cada nombre en la API REST (se conocerán como controllers); 46 en su contexto, se procesan las peticiones que se hayan encaminado hacia ellos, manipulando los datos de la estructura de datos asociada y también interactuando con otros controllers dependiendo de la complejidad de la operación requerida. 3. Modelos, que igual que en el frontend, se encontrará al menos uno por cada estructura de datos existente (se conocerán como models); establecerán la estructura JSON mínima que debe tener un objeto para ser almacenado en una colección de MongoDB. Así mismo se utilizará para generar objetos de ese tipo así como para comprobar que un objeto pertenece a ese tipo gracias a las herramientas de MongoDB. 4. Servicios, que de forma similar a la aplicación frontend, expondrán cómodas APIs para atacar a diferentes servicios como la base de datos de MongoDB, el sistema de archivos del servidor, o la ejecución controlada y sincronizada de scripts de python (se conocerán como providers oservices); su grado de independencia de la aplicación es tan alto que podrían ser copiados y utilizados tal cual en otro proyecto (salvando ligeras modificaciones que están adaptadas a cada proyecto por comodidad). Su existencia separada del resto del código es justificada por la capa de abstracción adicional para delimitar la responsabilidad del módulo que lo invoca y reducir su complejidad, dejando detalles de implementación del servicio en el propio servicio, ocultando su complejidad al invocador. 5. Módulos de soporte, también independientes y por lo general se ocupan de operaciones tediosas de cálculo o manipulación de estructuras de datos que puedan distraer la atención si estuvieran presentes en el código del módulo invocador (se conocerán como helpers); exponen sus métodos a cualquier módulo de la aplicación (por lo general a controllers). 6. Archivos de configuración y de constantes, para centralizar determinados datos relevantes de configuración, para su fácil acceso y modificación. Para entender con más facilidad la alineación del proyecto backend con el frontend y su esquema, se utilizará una similar para cada tipo de datos. 5.2.3. Flujo de enrutado de las peticiones HTTP Como ya se explicó anteriormente, se utiliza ExpressJS para enrutar las peticiones que se dirijan desde cualquier origen a la aplicación frontend. Cuando se inicializa el servidor, a través de ExpressJS se genera un servidor que atiende todas las peticiones recibidas en el puerto (por defecto el 3000) e IP local que se configure mediante el método listen de su objeto app en el server.js. A posteriori, se configura el enrutador con el método setupRouting del módulo router.js. Éste es responsable de, mediante el método use del objeto app importar todos los routers creados y disponer cada uno de ellos de forma vinculada a cada endpoint asociado. De esta forma, cuando se reciba una petición con la ruta /api/trollnet, se redirigirá dicha petición para ser atendida por el router trollnetRouter con 47 use(ROUTER_CONFIG.EP_GLOBAL.TROLLNET, trollnetRouter) Se puede observar esta primera etapa de encaminamiento de peticiones en la figura B.8 del Apéndice B. Tras encaminar una petición al router que debe tratarla, entra en juego la segunda etapa de encaminamiento, en la que dicho router importará el controller asociado a su tipo de datos para encaminar así cada petición según su tipo y su contenido al método del controller que deba atenderla. Gracias a ExpressJS se puede registrar la función del controller a ejecutar para determinadas características, como el tipo CRUD y las características de su url. De esta forma, suponiendo que el trollnet.router.js atiende una petición PUT en la url /api/trollnet/rename/:id, mediante el método put se podrá encaminar dicha petición a ser atendida por el método renameTrollnet del trollnet.controller.js. La figura B.9 del Apéndice Bmuestra este segundo nivel de encaminamiento para cada enrutador, junto a una breve descripción. Para el endpoint /api/trollnet, se asocian 5 entradas atendidas por el trollnet.router.js: 1. En la ruta /api/trollnet/, las peticiones GET serán atendidas por el método getAllTrollnets. 2. En la ruta /api/trollnet/, las peticiones POST serán atendidas por el método addTrollnet. 3. En la ruta /api/trollnet/:id, las peticiones GET serán atendidas por el método getTrollnetById. 4. En la ruta /api/trollnet/:id, las peticiones DELETE serán atendidas por el método deleteTrollnet. 5. En la ruta /api/trollnet/status, las peticiones POST serán atendidas por el método getUntrainedTrollnetsStatus. 6. En la ruta /api/trollnet/rename/:id, las peticiones PUT serán atendidas por el método renameTrollnet. 7. En la ruta /api/trollnet/activate/:id, las peticiones PUT serán atendidas por el método activateTrollnet. 8. En la ruta /api/trollnet/deactivate/:id, las peticiones PUT serán atendidas por el método deactivateTrollnet. Las peticiones que no encajen con algún segmento del primer nivel y del segundo nivel serán automáticamente rechazadas. Se controla de esta manera muy severamente el camino de cualquier petición que atienda el servidor, constituyendo una medida de seguridad importante sobre interacciones externas con esta aplicación, ya que se conoce y controla cualquier posible entrada al servidor por un único camino específico para cada petición y así minimizar brechas de seguridad. 48 5.2.4. Diagramas de clases de los Controllers, Helpers y Models El core.controller.js es un módulo central cuyo cometido es inicializar los procesos demonio de otros controladores una vez la conexión con la MongoDB se ha llevado a cabo, para sincronizar las acciones de dichos controladores con la información existente en la base de datos una vez se ha iniciado el servidor NodeJS y éste haya conectado su cliente de Mongo con la instancia de MongoDB. Al ejecutarse su método público setupCoreMonitors, este módulo lanza _releaseDaemons iniciando los daemons de cada controlador (startTrollnetDaemon del trollnet.controller.js,startCorpusDaemon del corpus.controller.js ystartModelDaemon del model.controller.js). Con esto, finaliza la preparación inicial del servidor. El trollnet.controller.js debe manipular todo entorno a las trollnets, y por ello es quien ejecuta startTrollnetDaemon además de exponer todos sus métodos para atender a la API REST. El startTrollnetDaemon inicia un proceso de comprobación de redes pendientes por entrenar. Para ello, la operación sigue los pasos aquí descritos: 1. Al ser lanzado cuando el servidor está listo, se quiere comprobar qué trollnets están guardadas en la base de datos como creadas pero no totalmente entrenadas, y para ello se accede a la MongoDB con su atributo creationStatus con valor 100 y su atributo trainingStatus con valor inferior a 100. Una vez tiene la lista, llama a _checkUntrainedTrollnets con ella. 2. _checkUntrainedTrollnets une la lista obtenida en la base de datos a cualquier posible trollnet que se hubiera creado entretanto, e inicia el proceso recursivo _followTrollnetTraining para entrenar las redes pendientes de una en una. 3. _followTrollnetTraining en cada nivel (por ser recursivo) irá llamando a _teachTrollnet con una de las trollnets pendientes. Lo primero que hace este método es actualizar en la MongoDB el trainingStatus de esa trollnet con valor 1. Acto seguido, extrae los datos de esa trollnet, de entre los cuales, la lista de bots e invoca al método teachBotArray del botController con ella. Su cometido es entrenar a cada uno de los bots de uno en uno, pero esto se explicará en el apartado del controller de bots. 4. Si devuelve algún fallo, se actualizará en la base de datos la red con trainingStatus -1 así como almacenado el error para ser revisada la causa; si retorna exitosamente, se actualizará en la base de datos la red con trainingStatus 100, y será indicador de que la red ha sido entrenada exitosamente. 5. Al acabar, _followTrollnetTraining vuelve a invocarse a sí mismo para ejecutarse de nuevo con la siguiente trollnet, hasta que no queden más por entrenar. En ese momento, vuelve a _checkUntrainedTrollnets que se encarga de configurar un temporizador para volver a repetir estos mismos pasos más tarde, en caso de que se hayan creado nuevas trollnets. El método getAllTrollnets extrae de la MongoDB la lista de trollnets existentes, y si funciona y las hay resuelve la petición http asociada con un código 200 y la lista de trollnets 49 3. El método getIntervalPortion sirve para obtener la proporción de un valor dentro de un intervalo. 4. El método randomElementFromArray sirve para obtener un elemento aleatorio de entre los elementos de un array. 5. El método splitRandomlyByCoef sirve para separar aleatoriamente los elementos de un array en dos arrays diferentes y según una proporción determinada, de forma que pueda hablar más en un array que en el otro, dependiendo de la proporción especificada por parámetro. 6. El método _shuffleArray es utilizado en el splitRandomlyByCoef para reordenar aleatoriamente el array antes de separarlo. 7. El método stringToAscii sirve para codificar todos los caracteres de un string a codificación ASCII. 8. El método asciiToString sirve para decodificar un texto en ASCII a su texto original. Los modelos de datos manejados en el servidor se han diseñado como modelos para ser usados por MongoDB. Por eso, se utiliza los métodos Schema ymodel de la librería de npm mongoose para crearlos y registrarlos. Para los modelos Trollnet y TrollnetDraft, puesto que se comparten con el frontend, se sigue el mismo esquema con el fin de reforzar la mantenibilidad de código, y allanar el terreno al comunicar cliente y servidor. Encontramos otros modelos como: 1. Bot utilizado para almacenar información de bots creados. Tendrán un string identificador id, una fecha de creación creationDate, un string como nombre botName, un objeto de propiedades que le describen properties, el objeto descriptor AIObject que genera y utiliza Python en su creación y enseñanza respectivamente y una fecha lastTrained para indicar cuándo se entrenó por última vez. 2. BotUser utilizado para almacenar la asociación de un bot a una cuenta de Twitter. Tendrán un string identificador del bot botname, y la cuenta asociada en un string twitteruser. 3. Corpus contendrá información acerca de un archivo de corpus. Tiene un string identificador id, un string de su ruta de localización fileName y un booleano isNewCorpus indicando si es un corpus procesado o no. 4. Conversation servirá para crear y almacenar conversaciones, descritas por la fecha de creación creationDate, el identificador de la trollnet que generó la conversación trollnetId, el hilo original utilizado para generarla topic y el array de mensajes (con emisor, destinatario y contenido) generados en el campo conversation. 56 5. PythonFiles se utiliza para almacenar aquellos objetos que los scripts de python requieran frecuentemente. Por el momento, se almacena la model descriptor list en el campo modelDescriptorList, además de una fecha de creación en creationDate y un valor de versión version como campos auxiliares útiles para el desarrollo y control de versiones de datos. 5.2.5. Diagramas de clases de los Services El servicio mongo.db.js, gracias a la librería de npm mongoose, permite establecer una conexión entre el cliente utilizado en la aplicación servidor y la base de datos de MongoDB. El servicio creado expone públicamente un método _connect para este fin, y una vez se le proporciona la URL de MongoDB y las opciones deseadas para la conexión (constantes extraídas del archivo de configuración server.config.js), avisará de si la conexión ha tenido éxito para poder operar contra la base de datos con garantía de funcionamiento y disponibilidad, así como de si se producen futuros errores en las operaciones contra la MongoDB. El servicio python.service.js tiene la capacidad de ejecutar scripts de python y atender a su respuesta. Se debe especificar la ruta del sistema de archivos del servidor donde está el ejecutable de Python que se debe usar; así como la ruta del script que se quiere lanzar. En el caso de este proyecto, se ejecutará desde dos carpetas distintas, por razones de distribución del trabajo en el proyecto. Por un lado el script scripts.py situado en C:/Proyectos/etv-tfg/ETV-models-and-bots/ETV; por otro, los siguientes scripts assign_accounts_to_bots.py,listener_twitter.py yscript_publisher.py situados en C:/Proyectos/etv-tfg/bot_publisher. Los parámetros de los métodos deben ir en formato texto; y además, en el caso de algunos parámetros de alguno de los métodos (cuando contienen objetos JSON pasados a texto), es requisito del script que se codifique la entrada a ASCII, y así mismo se decodifique cuando la ejecución de los scripts de Python retornen valores de las mismas características. Además, para todos ellos, es necesario filtrar la salida del script pues puede devolver un array con varios elementos de log de información, pero en todos los casos la respuesta que interesa es el último elemento del array y esa es la que habrá que procesar. Este servicio expone los siguientes métodos: 1. createBot: ejecuta el script scripts.py con la orden create y varios parámetros de un bot como la edad, nivel de educación, likes y dislikes para devolver un objeto que describe a un bot. 2. trainModel: ejecuta el script scripts.py con la orden trainModel y varios parámetros como el identificador de un modelo, el nombre del archivo, la modelDescriptorList explicada en la sección 5.2.4 y el número de iteraciones para refinar el modelo. Devuelve la modelDescriptorList actualizada con la información asociada al último modelo entrenado. 3. teachBot: ejecuta el script scripts.py con la orden trainBot, el objeto descriptor del bot y la modelDescriptorList. 57 4. answerThread: ejecuta el script scripts.py con la orden getResponse, el objeto descriptor del bot, el mensaje a responder, los parámetros de filtrado y devuelve el mensaje generado por el bot. 5. linkAccountsToBots: ejecuta el script assign_accounts_to_bots.py con una lista de identificadores de bots como único parámetro. Devuelve la lista de los bots a los que se les ha asignado una cuenta. 6. listenToTwitterAccount: ejecuta el script listener_twitter.py con un nombre de perfil de Twitter. El script sigue ejecutándose hasta que dicha cuenta publique un mensaje, en cuyo momento retornará con el identificador de ese mensaje y su contenido. Ambos datos serán lo que devuelva finalmente este método al proceso invocador. 7. publishMessage: ejecuta el script script_publisher.py con el identificador del mensaje al que responder, el contenido de la respuesta que se va a publicar y el identificador del bot que la va a publicar. Una vez se ha publicado, devuelve el identificador del mensaje que se publicó. El servicio filesystem.service.js, gracias a la librería chokidar y al módulo de NodeJS fs, es capaz de detectar qué archivos hay en la ruta que se desee y atender a cambios en dichos archivos o carpetas. Acepta también expresiones regulares o strings que determinen rutas o nombres de archivo para los cuales se desee pasar por alto la detección. Para su usabilidad desde módulos que lo quieran invocar, expone los métodos scanFolder para detectar los elementos existentes en una determinada ruta y onNewFileAdded para detectar genéricamente los cambios que ocurran en una ruta. 5.3. Arquitectura de los scripts de Python para la utilización de Twitter La interacción del servidor central con la red social Twitter se ha centralizado en una serie de scripts de Python agrupados por funcionalidades: publicar respuestas de bots en Twitter, recoger publicaciones de los clientes, asginar usuarios disponibles a los bots y autorizar a la APP de Twitter a publicar en nombre de los usuarios. Para la integración de Twitter con Python, se utilizará la API oficial de Twiter junto con la biblioteca de Python tweepy, que facilita el la utilización de la misma. Así mismo, se ha utilizado la base de datos central para almacenar la información de las cuentas de Twitter y de las asignaciones de usuarios a bots. 5.3.1. Consideraciones previas para la integración de Twitter en Python Para utilizar la API oficial de Twitter es necesario cumplir una serie de requisitos15, el más importante es disponer de una cuenta de desarrollador de Twitter. Una cuenta de 58 dessarrollador se obtiene completando un complejo formulario sobre el uso que se hará de la misma, tras la aprobación de Twitter. Una vez se dispone de una cuenta de desarrollador, se debe crear una APP de Twitter. Al crear esta APP se generarán las claves de autorización que serán necesarias para interactuar desde Python con la API de Twitter. Sin embargo, aún no se podrá publicar en nombre de los usuarios que se quiera. Para publicar en Twitter utilizando la APP creada deben en todo momento cumplirse las políticas de Twitter para desarrolladores13 y además cada usuario debe autorizar a la aplicación para que publique en su nombre. Esta autorización solo debe realizarse una vez y nunca caduca, por lo que una vez hecho se dispondrá de la cuenta para publicar y responder en nombre de los bots. Para la integración se ha desarrollado un script específico que automáticamente almacena los tokens generados en la base de datos principal. Puede verse el diagrama del flujo en la figura B.10 del Apéndice B. 5.3.2. Estructura básica y patrón de datos El core de la interacción está dividido en dos scripts de Python principales: el script dedicado a realizar publicaciones en Twitter y el script dedicado a permanecer en espera para recoger las publicaciones que realicen los clientes. Para la interacción con Twitter, el servidor central llama a los distintos scripts disponibles, que centalizan la interacción. Estos scripts interaccionan con Twitter utilizando su API oficial. Para el almacenamiento de las claves y tokens de autorización, de los usuarios disponibles y otros elementos de interés se utiliza la base de datos central. Puede verse un diagrama simplificado en la figura B.11 del Apéndice B. 5.3.3. Arquitectura de la base de datos de la interacción con Twitter La base de datos de MongoDB que utilizan los scripts de Python para la interacción con Twitter está formada por dos Collections:bot users ytwitter accounts. Puede verse la estructura básica en la figura B.12 del Apéndice B. La Collection bot users almacena todos los bots y la cuenta de usuario de Twitter que se le ha asignado a cada uno. La Collection twitter accounts almacena todas las cuentas de Twitter disponibles para utilizar por el servidor central junto con los token de autorización para que la APP publique por ellos. 59 Capítulo 6 Casos de Estudio En el presente capítulo se propone un entorno ficticio en el que aplicar nuestra solución para que el lector lo utilice de escenario en el que figurar las explicaciones de los siguientes casos de uso que prosiguen. Para cada uno de los casos de uso, que vendrán acompañados de diagramas explicativos, se dividirá su proceso en tantas fases como separaciones haya entre el frontend web, el servidor web y los scripts de Python, en un intento de visualizar la intervención de cada una de estas capas en cada caso de uso. 6.1. Aplicando la solución en un entorno propuesto Para atraer la atención en sus redes sociales, el recién contratado Social Media Manager de un incipiente diario online de política busca una forma de ampliar el alcance de sus noticias en las redes, y busca una forma de aumentar la interacción de los usuarios en sus perfiles de Twitter, Instagram, Facebook, etc. En la era moderna, toma mucha importancia la cantidad y contenido llamativo (no tanto la calidad o veracidad del mismo) para que los motores de búsqueda y de sugerencias de las redes sociales destaquen ciertos perfiles por encima de otros. Por ello, este empleado que recién ha conocido las capacidades del producto de El Trol Versátil, desea probar qué tal funciona en su caso, esto es: necesita usuarios (aunque sean bots) que se adhieran rápidamente en sus publicaciones, y a ser posible que generen debate y polémica por los comentarios que añadan. Puede bastarle con una veintena de bots de diferentes edades y perfiles sociales, que puedan hablar de temas relacionados con la política (con más o menos inclinaciones políticas en diferentes ámbitos) y que den sus opiniones (más o menos controvertidas) en cada publicación que él haga. Nuestra solución le permite conseguir su propósito: necesita acceder a nuestra aplicación web, crear una red de trolls con esas características, y una vez nuestro servicio haya creado y entrenado esa red, tendrá a su alcance que los bots generen conversaciones sobre cada una de las publicaciones del perfil en Twitter de su diario, o sobre las publicaciones de cualquier otro perfil que introduzca. A continuación, se profundizará en cada uno de los casos de uso que intervienen en este 60 escenario. 6.2. Caso de uso: Crear y entrenar una nueva trollnet El usuario previamente ha accedido a la aplicación web y ha seleccionado la pantalla de ’New trollnet’. A continuación se describe el proceso por el que el usuario elige las características de la trollnet que desea crear y procede aceptar la creación, que lleva a cabo el servidor para crear tanto la trollnet como cada uno de los bots que van asociados a ella, así como lo que ejecutan los scripts de Python que crean cada uno de los bots. Cuando ese proceso finaliza, a través de otro script de Python se llevará a cabo una vinculación uno a uno de cada bot de la trollnet con una de las cuentas disponibles (previamente creadas por los administradores de este producto) del servicio que vamos a utilizar para publicar los mensajes, Twitter; tras esto, empezará a entrenar la trollnet, en un proceso similar a la creación, entrenando uno por uno los bots apoyándose en los scripts de Python para dicho entrenamiento. Una vez esto finalice, se guardará la trollnet y cada uno de los bots actualizados en la MongoDB. En paralelo, el frontend irá solicitando el estado del progreso al backend y será informado del porcentaje de compleción del mismo, y se le mostrará al usuario. La figura B.13 del Apéndice Bservirá de apoyo para la explicación de este caso de uso. 6.2.1. Fase 1: Frontend Web - procesar el input del usuario 1. Una vez el usuario haya accedido a la pestaña ’New trollnet’, observará en el lado derecho de la aplicación una serie de componentes parametrizables para moldear las características de la trollnet que desea crear. Cada vez que modifique uno de estos parámetros, el componente que lo rige modificará esa característica en la plantilla para la trollnet. Así, tiene a su alcance la modificación de las siguientes propiedades: a) El nombre de la trollnet, modificará la propiedad customName. Este parámetro es, de momento, sólo estético, pero le permitirá identificar la trollnet de entre su lista de trollnets. b) El rango de edades, a través del componente age-selector.component.ts, modificará la propiedad ageInterval. Este parámetro es, de momento, sólo estético. c) Los géneros posibles, a través del componente gender-selector.component.ts, modificará la propiedad genders. Este parámetro es, de momento, sólo estético. d) Las etnias posibles, a través del componente ethnicity-selector.component.ts, modificará la propiedad ethnicity. Este parámetro es, de momento, sólo estético. e) El rango de educación o formalidad del habla, que se da a través del componente cultural-level.component.ts, modificará la propiedad culturalLevel. Este parámetro influye en el nivel de formalidad de la respuesta de los bots. 61 f) El rango del nivel de positividad del bot en el habla, a través del componente mood-selector.component.ts, modificará la propiedad moodLevel. Este parámetro influye en la proporción relativa entre likes ydislikes (explicados más adelante), de forma que cuanto más bajo sea el nivel de positividad, más tenderá a quejarse de aquello que no le gusta, y al contrario, cuaanto más alto, más tenderá a hablar de aquello que le gusta. g) El tamaño de la trollnet en número de bots, que se puede fijar a través del componente net-size.component.ts, modificará la propiedad netsize. Pueden ser valores entre 5 y 50, a inervalos de 5. h) El intervalo del nivel de interacción, definido por medio del componente llamado interaction-level.component.ts, modificará la propiedad interactionLevel. Esto influirá en el tamaño de las respuestas del bot. i) La inclusión de una serie de palabras clave, utilizando el componente llamado keywords.component.ts, modificará la propiedad keywords. Los bots aprenderán diferentes combinaciones de estos temas, y dependiendo del moodLevel se distribuirán como likes olikes del bot. j) La inclusión de una serie de gustos o likes, a través del componente keywords.component.ts, modificará la propiedad likes. Los bots expresarán más afección por estos temas que por otros, teniendo cada bot una combinación diferente de estos temas. k) De formal similar, la inclusión de una serie de odios o dislikes, a través del componente keywords.component.ts, modificará la propiedad dislikes. Los bots expresarán más desafección por estos temas que por otros, teniendo cada bot una combinación diferente de estos temas. 2. Al modificar los parámetros a su alcance, cada componente modificará su propiedad en la plantilla almacenada en la lógica de esta pantalla, create.page.ts, de tipo TrollnetDraftModel. Cuando esté listo, seleccionará el botón ’CREATE TROLLNET’ en la parte inferior de la pantalla, de forma que el flujo alcanzará a la trollnet.store.ts a través de createNewTrollnet con la plantilla como parámetro. 3. A su vez, la store redirigirá el flujo a trollnetService para acceder a través de él a la API remota del backend con una petición POST en el endpoint /api/trollnet, con la plantilla de la trollnet como payload. Los últimos pasos de la fase están ligados entre sí con promesas (Objetos Promise del ECMASCRIPT 6). Cuando se reciba la respuesta del servidor en la fase 2 del caso de uso, las promesas irán resolviéndose sucesivamente, y se observará en el frontend una trollnet creada. En la fase 9 de este caso de uso se explica lo pertinente a observar el progreso de creación y entrenamiento de la trollnet. 62 6.2.2. Fase 2: Servidor Web - iniciar la creación de la trollnet 1. En el servidor, el router router.js procesará la petición en el endpoint /api/trollnet y la redirigirá hacia el trollnet.router.js. Al detectar que es una petición tipo POST, la redirige al método addTrollnet del trollnet.controller.js. 2. Éste invocará al createBotArray del bot.controller.js para iniciar la creación de los bots asociados a la trollnet, almacenará en la MongoDB un nuevo objeto Trollnet con la información de esta trollnet y resolverá la petición del frontend como éxito, confirmándole que se inicia el proceso de creación de la trollnet. 3. El bot.controller.js iniciará una operación recursiva a través de _followBotCreation, que se llamará a sí misma tantas veces como bots se deba crear. Ese método se encarga de, en primer lugar, calcular mediante _getRandomParams una configuración de parámetros aleatoria dentro de los intervalos específicos establecidos por los parámetros de la trollnet, elegidos por el usuario. Esa configuración será la asignada al bot que se esté creando en ese punto. En segundo lugar, llamará a _createBot. 4. _createBot usará el servicio PythonService con los parámetros adecuados para la creación del bot, el cual se encargará de realizar la llamada al script de Python con los parámetros en el formato adecuado, y de recoger y procesar su respuesta en la fase 4 de este caso de uso. 6.2.3. Fase 3: Ejecución Python - creación de un bot Para esta fase, véase figura B.14 del Apéndice B. 1. Cuando Scripts.py recibe un comando a ejecutar, primero analiza los parametros en busca de opciones generales especificadas (véase sección 4.9)), si se encuentran se levantan los flags pertinentes. Después se identifica el comando ”create” y se hace una validación de los parámetros introducidos. 2. Se solicita la creación de una instancia de Bot con parámetros introducidos y se transforma a JSON. 3. Se devuelve el resultado por la salida específicada. 6.2.4. Fase 4: Servidor Web - control y fin de la creación de la trollnet 1. Cuando finalice el script de Python, PythonService recogerá su output, filtrará en busca del objeto bot creado y lo devolverá a bot.controller.js, que se encargará de almacenar la respuesta dentro del campo AIObject de este nuevo bot creado en la MongoDB. 63 2. En este momento, se calcula la proporción de bots creados sobre los totales por crear y se actualiza la trollnet en la MongoDB con el campo creationStatus a dicho porcentaje (sobre 100). 3. Si faltan más bots por ser creados, _followBotCreation será invocado de nuevo para volver a realizar los pasos previos. Si no, el flujo será devuelto al invocador en trollnet.controller.js que, si no registra ningún fallo del proceso, actualizará la trollnet en la MongoDB con la lista de identificadores de los bots. 4. Se requerirá un último paso antes de dar por finalizada la creación: vincular cuentas de Twitter a cada uno de los bots. Para ello, se invoca al linkAccountsToBots del PythonService, que invocará al script de Python con la lista de bots que deben recibir la asignación de una cuenta. 6.2.5. Fase 5: Ejecución Python - vincular cuentas a los bots 1. El script de Python recibirá una lista de nombres de bots. Esta lista debe contener todos los nombres de bots para los que se quiere que se les asigne un usuario disponible de Twitter para publicar los tuits que se generen para él. 2. Una vez recibida la lista se ejecutará assign_accounts, que primero cargará de la base de datos ETV la lista de usuarios de Twitter disponibles y después asignará a cada bot un usuario de Twitter mientras queden. 3. Finalmente se almacenará en la base de datos ETV las asignaciones que se han realizado y devolverá al script un json con la lista de los bots a los que se les ha asignado un usuario de Twitter y otra lista con los que no se les haya podido asignar. El script remitirá esta información y finalizará. Puede verse el flujo de vinculación en la figura B.15 del apéndice B. 6.2.6. Fase 6: Servidor Web - iniciar proceso de entrenamiento de la trollnet 1. Cuando finalice el script de Python, PythonService notificará la compleción al controlador trollnet.controller.js que, si ha funcionado bien, guardará en la MongoDB la trollnet con el campo creationStatus a 100. Además, apuntará la trollnet a la lista volátil de trollnets sin entrenar con _addUntrainedTrollnet. 2. El demonio del trollnet.controller.js que realiza chequeos periódicamente con _checkUntrainedTrollnets detectará una nueva trollnet por entrenar, e iniciará la operación recursiva _followTrollnetTraining. Según el mismo principio que sigue _followBotCreation, que se llamará a sí misma tantas veces como trollnets se deba entrenar. A cada nivel de la misma, llamará a _teachTrollnet, que actualizará primero el trainingStatus de la trollnet en la MongoDB a 1; después llamará a teachBotArray del botController con la lista de bots de la trollnet. 64 3. teachBotArray se encarga de iniciar el entrenamiento de los bots asociados a la trollnet, pero para ello primero debe extraer un dato importante para los scripts de Python, la model descriptor list, y lo hace llamando al método getModelDescriptorListFromDB del ModelController. Cuando lo tiene, invoca la operación recursiva _followBotTeaching, que se llamará a sí misma tantas veces como bots se deba entrenar. 4. En cada nivel, invocará a _teachBot que extrae la información del bot de la MongoDB, y junto a la model descriptor list, los utiliza como parámetros en la llamada al método teachBot del servicio PythonService, el cual se encargará de realizar la llamada al script de Python con los parámetros en el formato adecuado, y de recoger y procesar su respuesta en la fase 8 de este caso de uso. 6.2.7. Fase 7: Ejecución Python - entrenamiento de un bot Para esta fase, véase figura B.16 del Apéndice B. 1. Cuando Scripts.py recibe un comando a ejecutar, primero analiza los parametros en busca de opciones generales especificadas 4.9, si se encuentran se levantan los flags pertinentes. Después se identifica el comando "trainBot 2 se hace una validación de los parámetros introducidos. 2. Se carga la instancia del bot. 3. Se carga la instancia de la MDL. 4. Se llama a learn en el bot cargado con la MDL cargada. 5. El bot consulta en la BD las relaciones entre sus gustos y las keywords de cada modelo en la MDL. 6. Asocia los modelos que encajan. 7. Se devuelve instancia del bot actualizada. 8. scripts.py devuelve al bot actualizado. 6.2.8. Fase 8: Servidor Web - control y fin del entrenamiento de la trollnet 1. Cuando finalice el script de Python, PythonService recogerá su output, filtrará en busca del objeto del bot entrenado y lo devolverá a bot.controller.js, que se encargará de actualizar el campo AIObject del bot con la respuesta en la MongoDB. 65 Capítulo 7 Conclusiones En este capítulo se tratan aquellas dificultades encontradas durante el desarrollo de este TFG y se comentan brevemente algunos aspectos que podrían mejorarse en el futuro. 7.1. Inteligencia de un bot Cuando se habla de un bot se tratan muchas partes distintas del sistema que, trabajando de manera conjunta, se abstraen en forma de bot. Cada una de ellas está bien definida y tiene su problematica asociada, aunque en conclusión es la idea de estas piezas trabajando de manera conjunta la que hace que el sistema sea como es. Esta organización y distribución de roles propone un producto con un potencial muy grande, ya que un hipotetico sistema en el que estas piezas estuvieran altamente refinadas, lograría crear personalidades, algo mucho más allá del alcance de los productos en la competencia. La abstracción y separación de estos elementos facilita también el desarrollo y refactorización si así fuera necesario, logrando focalizar en una tarea muy clara cada una de estas piezas. Este ha sido uno de los problemas que se encontró al plantear el sistema, bajo la premisa de crear un bot con un comportamiento individual y humano, separar este objetivo en distintos engranajes más simples (y programables). A pesar de que este objetivo se ha conseguido llevar a cabo, las distintas piezas que lo forman plantean otros retos, que aunque mejor definidos, carecen de simpleza. A continuación se plantean los diversos problemas y posibles soluciones que se encuentran en cada módulo. 7.1.1. Generación de texto Generador La implementación de este rol se ha llevado a cabo con GPT-2, a pesar de que GPT-3 existe desde que el desarrollo comenzó. Esto se debe a que GPT-3 permite el finetuning bajo pago, dependiendo de sus servidores. La libreria de GPT-2 utilizada permite que se haga el finetuning alla donde se quiera alojar. El finetuning es un pilar fundamental del 72 sistema para alcanzar los bots con personalidad, y esta barrera económica es la que hace que se descarte GPT-3. Con mayor presupuesto disponible, se pasaría a utilizar GPT-3. Esto no solo incrementaria de forma considerable la calidad de las respuestas, sino que además descargaría requerimientos por parte del equipo, ya que el finetuning se realiza en los servidores de OpenAI. Por otro lado, el tiempo que se tarda en entrenar un modelo es un aspecto a mejorar con urgencia, ya que para modelos relativamente pequeños, se han encontrado tiempos de espera de 4 a 8 horas. Con corpus más grandes este tiempo crece de manera pronunciada. Una de las opciones, es preparar una máquina dedicada a tiempo completo a este trabajo, y que además los entrenamientos corran sobre una GPU. Esto último requeriría un ajuste en las librerías a instalar y el código, pero lo realmente costoso es poseer y mantener una máquina con estas características. Otro problema hayado es la obtención de corpus. Actualmente los corpus se obtienen manualmente con un script que recopila tweets de twitter a partir de una o varias palabras clave. El propio script puede mejorar un poco, ya que actualmente hay que ejecutarlo varias veces por corpus si se quieren incluir varias palabras clave. Aunque, aun así, está lejos de ser una solución perfecta, pues el script hace llamadas a la API de Twitter, las cuales tienen un límite cada 15 minutos, por lo que el script a menudo se detiene y tarda bastante en obtener los corpus. Por tanto, o bien se podría buscar una alternativa para la obtención de corpus que no involucre recopilar mensajes de Twitter, o bien adaptar mejor el script en torno a la limitación de los 15 minutos y aumentar el nivel de automatización del mismo, que por ahora no llegó a ser muy necesario. Pipeline de filtrado El pipeline de filtrado es una herramienta con alto potencial de desarrollo y fácil ampliación. La extensión con otras características podría permitir un filtrado por personalidad más fino, en el que se pudieran tener en cuenta otros factores que definen una personalidad, como la etnia, la edad, etc. También se podrían añadir otras funciones modificadoras que estilizasen en mayor medida los textos resultantes, ajustandose así más a distintos perfiles de personalidad. Otro factor a explotar en este elemento es el orden de las funciones de filtrado, el orden en el que se ejecuten podría cambiar el resultado, ya que si se ejecutan funciones modificadoras las siguientes funciones evaluadoras leerán esos cambios. Esto con un volumen de funciones alto podría tener un amplio impacto, pudiendo llegar a merecer la pena soportar una interfaz que permita manjear este orden, ya sea de manera automática o para el usuario. 7.1.2. Base de datos de relaciones Aunque en la implementación se ha optado por utilizar Prolog, bajo unas reglas relativamente sencillas, se podría decidir proseguir el desarrollo en otra dirección, o en esta misma ampliando la lógica de estas reglas. El objetivo de esta base de datos es condensar en un único parametro (un número de -1 a 1) como están relacionados dos conceptos en el mundo 73 que conocemos, por tanto cualquier servicio que cumpliera esta condición sería suficiente. Un posible camino, es utilizar otra red neuronal, que reciba como entrada estos dos conceptos y devuelva el número acorde. Esto conllevaría su dificultad asociada, ya que no solo hay que conseguir esta tecnología, si no que además hay que alimentarla con un catálogo de corpus acomodado a este requerimiento, y la automatización de la propia creación del corpus sería no trivial. 7.1.3. Inferencer Esta herramienta, que se apoya fuertemente en la base de datos de relaciones y la cual configura como se aplica el pipeline de filtrado, tiene un ambito de desarrollo tan grande como el propio pipeline de filtrado (o incluso más). A su vez cada parámetro tiene su propio cálculo independiente, con tanto desarrollo y complejidad como se le quiera dar. Las dificultades encontradas se asocian a cada uno de los parámetros de filtrado. Los algoritmos utilizados podrían mejorarse ampliamente, aunque el buen funcionamiento de esta pieza depende en gran medida de la base de datos de relaciones. Una posible mejora (y aunque se comente en este apartado podría extrapolarse a otras partes) es hacer que el bot tenga en cuenta no solo el contexto inmediato, si no crear un contexto más complejo compuesto por los tweets que ese mismo bot haya escrito ese día (lo que podría ir definiendo de qué humor está), todos los tweets del hilo en el que se responda e incluso datos del usuario al que se responde como la descripción del perfil. Con todos estos datos se podrían refinar en gran medida los parámetros que se calculan, aunque esto tiene una problemática asociada, y es el crecimiento en ámbito y complejidad de los algoritmos, que cada vez deban tener mas factores en cuenta, haciendo que acaben siendo insostenibles de cara a la depuración y refinación. Es de vital importancia que cada una de los parámetros (al igual que su cálculo) esté bien definido y acotado. 7.1.4. Análisis de sentimiento El desarrollo de este módulo se ha basado en las demandas requeridas por el resto del sistema, haciendo de wrapper de la librería utilizada Spacy. Uno de los problemas (o ventajas, según como se mire) es la cantidad de cosas que calcula, lo cual lo hace muy lento. Esto se ve reflejado claramente en el filtrado de textos generados o en la generación de relaciones en la base de datos. Aunque para esta aplicación, no se necesitan bajos tiempos de respuesta, si se suman los costes de los distintos módulos sin control podría llegar a ser excesivo. Por ello Spacy tiene aún un gran potencial por ser explotado, pero podría ser demasiado potente para lo necesario en el sistema, se debe considerar (en una supuesta continuación del desarrollo) si utilizar herramientas más ligeras o sacar mayor partido a las funcionalidades que propone. 7.1.5. Conclusiones de la sección El hecho de que todas estas herramientas estén bien definidas y delimitadas, podría permitir que una empresa asignara cada una de ellas a un grupo de personas distinto, que 74 se especialicen en ese campo y puedan llevar el desarrollo a niveles más altos. 7.2. Conclusiones generales En este TFG se ha desarrollado un servicio completo de generación de interacciones automáticas inteligentes en Twitter. En concreto se ha realizado: el análisis del mercado actual, el diseño del plan de negocio, el desarrollo completo de la interfaz de usuario, la herramienta para el entrenamiento de los distintos algoritmos de generación de bots, el servidor central para la configuración, generación de las redes de bots especializados y la sincronización de las diferentes ejecuciones de Python, la implementación de la base de datos central y el módulo para publicación en la red social Twitter. Por tanto, se ofrece un servicio que permite al cliente configurar una red de bots con las características deseadas para interactuar con perfiles de Twitter mediante una interfaz amigable. El servidor coordinará a los bots de la red para participar e interactuar con los mensajes publicados por la cuenta indicada. El usuario decidirá qué bots responden al mensaje principal y qué bots participan en conversaciones derivadas y se responden entre sí. Los perfiles operativos de Twitter se almacenan en la base de datos central, donde se habrán creado en el momento en el que el cliente haya contratado el servicio. El proceso de inclusión de usuarios en la base de datos requiere autorizar previamente a nuestra aplicación a publicar mediante otro de los módulos desarrollados. En el análisis del mercado y el plan de negocio se ha elaborado una estrategia para la implementación de una empresa que desarrolle y ofrezca el servicio. Si bien para encontrar financiación no se ha obtenido una opción segura y definitiva, se han ofrecido distintas opciones de las cuales se han analizado y ofrecido soluciones para los principales problemas que podrían surgir. Mediante el plan de marketing se han propuesto soluciones para la salida rápida al mercado, con un bajo interés y coste de financiación. La interfaz web de usuario permite al cliente configurar las redes de bots que ineractuarán con sus perfiles de Twitter de forma fácil y rápida. Esta opción de configurarse su propia red también facilitará al equipo la creación de redes propias en caso de que el cliente no desee configurarlas él mismo. La gran cantidad de opciones parametrizables en la web permite la creación de bots con personalidades complejas y muy cercanas a la caracterización de cualquier usuario real. Los mensajes y respuestas que se generan son de gran calidad y originalidad, siendo prácticamente indistinguibles de los publicados por un usuario real. Esto es el resultado de un proceso complejo de recopilación de conjuntos de datos, desarrollo de algoritmos apropiados y largos entrenamientos de redes de bots. Si bien el entrenamiento se ha visto que es costoso en tiempo y cómputo, esto no afecta a la experiencia del usuario ya que solo se realiza para la creación de las redes de bots especializados. Una vez se crea la red de bots con las distintas características, la interacción real con Twitter ofrece una gran esperiencia de usuario. La interacción con los mensajes publicados se produce prácticamente en tiempo real, con el delay que se esperaría para la interacción de un usuario real. 75 7.2.1. Líneas de trabajo futuro El desarrollo se ha centrado en el uso de Twitter pero la modularidad de la arquitectura permite integrar el servicio con otras redes sociales, una mejora que ampliaría el mercado en el que se podría ofrecer el servicio. La publicación actualmente se realiza exclusivamente en inglés, por lo que uno de los siguientes pasos a dar es desarrollar el servicio en castellano, lo que aumentaría el número potencial de clientes. La generación de perfiles reales junto con la autorización a nuestra aplicación para publicar en Twitter no ha podido automatizarse al completo debido a las estrictas normas de uso de Twitter. Si bien se ha desarrollado un script para facilitar al máximo esta tarea, en un futuro sería interesante desarrollar una interfaz gráfica web para facilitarla aún más. El alto tiempo de entrenamiento para los algoritmos se debe al coste en cómputo y memoria de estos. Este tiempo actualmente es demasiado alto debido a la falta de medios técnicos por el alto coste de grandes equipos de cómputo. Si bien como primera mejora ya se ha empleado una GPU, se vuelve necesario para los siguientes pasos utilizar equipos más potentes. 76 Capítulo 7 Conclusions In this chapter are described the difficulties found during the development, and some features that could be improved in the future. 7.1. Bot’s intelligence When talking about a bot, lots of different parts of the system are involved, which work together to abstract themselves as a bot. Each one of them is well defined and has its problems associated, but in the end the idea of these pieces working together is what makes the system be as it is. This role distribution proposes a product with lots of potential. A hypothetical system with these pieces greatly refined could create personalities, something that is far ahead from the competitors in the market. This splitted model also allows the development or refactorization in case it was needed, setting clearly the objective of each piece. This was one of the main problems found, having the objective of creating individual and "human-behavioural"bots, splitting the system into small codable modules. Despite this was actually achieved, the different parts bring new problems that are not simple although they are better defined. This will be described and discussed in the following sections. 7.1.1. Text generation Generator Despite of GPT-3 being on the market since the beginning of the development, the implementation was made with GPT-2. This was caused by the fact that GPT-3 only allows fine-tuning through real payments and in their servers. The GPT-2 library allows fine tuning in any place. Fine tuning is a key element of the system to reach the bots with personality goal, and this economic breach is what makes GPT-3 not to be considered. With a bigger budget access, GPT-3 would be the choice. The usage of this tool would increase significantly the quality of the responses, as well as it would ignore team equipment limitations, due to hosting the fine-tuning on OpenAI servers. 77 Another thing to improve urgently is the time required to train a model, since right now this takes from 4 to 8 hours using a relatively small sized corpus. This time would strongly increase with bigger corpus. One option to solve this would be having a machine dedicated strictly to this purpose, with a GPU to run the training on. The GPU usage requires some adjustments in the libraries and in the code, but the biggest issue comes from having and maintaining a machine with those characteristics. Last but not least, the other problem found was the attainment of a new corpus. This task is made right now manually with a script that collect tweets from Twitter using some keywords. This script could be improved, due to the need of running it multiple times for every corpus if it is desired to use different keywords. The script is far from being a good solution, since it calls the Twitter API every 15 min (a time limit established by Twitter) so most of the time the script is waiting. A solution could be gathering tweets from other sources, or enhancing it around the 15 minute limitation, using better automation that wasn’t necessary for the moment. Filter pipeline The filter pipeline is a tool with lots of room for improvement, and easy development. This, along with other characteristics could allow better filtering, that could consider other features of a human, such as age, or other modifiers that would customize more the responses based on the profile of the bot. Another thing to consider is the order in which the functions are applied. This could change the result because, if some modifiers are executed before the evaluators, the final punctuation could be different since this changes are later read and evaluated. With a big volume of functions the order could have a big impact on the final result, leading to the consideration of having an interface to manage this, automatically or by the user. 7.1.2. Relationships database In the implementation it was decided to use Prolog, with some simple rules. The development could follow this path improving the rules, or just take a completely different path. The objective of the database is to condense the relationship between two entities in a single parameter (a number from -1 to 1), therefore any service that provides this could be useful. An option is to use a neural network, that takes these two elements as the input and returns the number. To achieve this, not only would we need the technology, but also for it to be fed with the corresponding corpus, and the automation and adjustment of the corpus would not be trivial. 7.1.3. Inferencer This tool, that leans strongly on the relationships database and configures how the filter pipeline is applied, has a development scope as big as the filter pipeline. Each parameter has its own algorithm, that could be developed and improved as much as desired. The obstacles 78 that came across are associated with each one of the parameters. The algorithms can be improved, but the good performance of this element depends strongly on the relationship database. A possible improvement (and this can be applied to other parts of the system) is to make the bot take in consideration more things apart from the immediate context, such as the tweets the bot has written, other tweets from the thread or even the profile description of the user it is responding to. With all this data the parameters could be greatly improved, but this has an associated problem, the scope growth and algorithm complexity, making the inference not viable to debug and enhance. It is mandatory that each one of the parameters (and their calculation) is well defined. 7.1.4. Sentiment analysis This module has been developed around the requirements demanded by the rest of the system, working as a wrapper for Spacy, the dependency used. One of the disadvantages (or advantages, depending on how it is seen) is the amount of processing that it does, which makes it slow. This is clearly shown in the filtering of generated texts or in the generation of relationships inside of the database. Even though this application does not really require low response times, the result of adding the cost of all modules without control could end up being excessive. That is why Spacy still has room for improvement. It could, however, be too much for what the system needs, so using lighter tools should be considered (in case the development is continued), or improving the usage of the options that it provides. 7.1.5. Section conclusions The fact that all these tools are properly defined and delimited could let a company easily assign a specialized group of people to each one, allowing a higher level development. 7.2. Main conclusions In this Final Degree Project, a service for the generation of automatic interactions on Twitter has been developed. The following steps were carried out: the analysis of the current market, the design of the business plan, the development of the user interface, the tool for training the different bot algorithms, the central server for configuration, generation of the botnets and synchronization of different Python executions, the implementation of the central database and the module for publication in the social network Twitter. Therefore, a service is offered that allows the client to configure a botnet with the desired characteristics to interact with Twitter profiles through a friendly interface. The server will coordinate the bots of the network to participate and interact with the messages published by the account that has been selected. The user will decide which bots respond to the main message and which bots participate in secondary conversations and interact between each other. The operational profiles of Twitter are stored in the central database, where they have been created when the client has contracted the service. The process of adding users into the 79 database requires to previously authorize our application to publish through another of the developed modules. In the market analysis and the business plan, a feasible strategy has been developed for the real implementation of a company that creates and offers the service. Although a fully safe and definitive strategy does not exist to find the initial funding, different options have been offered. These options have been analyzed and the main problems that could arise have been solved. Through the marketing plan, different solutions have been proposed for a quick integration in the market of services for social networks. The web user interface allows the client to configure the botnets that will interact with their Twitter profiles both easily and quickly. This option to configure your own network will also make it easier for the team to create their own networks in case the client does not want to configure them himself. The large number of configurable options on the web allows the creation of bots with complex personalities and very close to the characterization of any possible real user. The messages and answers that are generated are of great quality and originality, being practically indistinguishable from those published by a real user. This is the result of a complex process of collecting data sets, developing appropriate algorithms, and a thorough botnet training. Although training has been seen to be costly in terms of time and computation, this does not affect the user experience since it is done only for the creation of specialized botnets. Once the botnet with various features is created, the actual interaction with Twitter offers a great user experience. The interaction with the published messages occurs practically in real time, with the delay that is expected from the interaction of a real user. 7.2.1. Future work Development has focused on the use of Twitter, but the modular architecture allows the service to be integrated with other social networks, an improvement that would expand the market in which the service can be offered. The publication is currently carried out exclusively in English, so one of the next steps to take is to develop the service in the Spanish language, which would increase the potential number of clients to whom the service can be offered. The actual Twitter profiling generation, along with the authorization for the posting to Twitter could not be fully automated due to strict Twitter usage rules. Although a script has been developed to make this task as easy as possible, it would be interesting to develop a graphical web interface to make it even easier in the future. The lengthy training time for the algorithms is due to their computational and memory cost. This time is currently too high due to the lack of technical means because of the high cost of a large computer equipment. Although a GPU has already been used as a first improvement, it becomes necessary to get more powerful equipment in the following steps. 80 Capítulo 8 Contribuciones A continuación exponemos las contribuciones de cada integrante del proyecto, así como los principales obstáculos a los que han tenido que enfrentarse. 8.1. Enrique Ballesteros Horcajo Mi contribución se ha centrado principalmente en tres áreas: el desarrollo del estado del arte, la creación del business plan y la programación y diseño de la interacción con la red social Twitter. Las dos primeras partes en una fase inicial se realizaron conjuntamente entre todos los integrantes del equipo y fueron desarrolladas en profundidad por mí una vez se tuvo una aproximación consensuada. Para la interacción con la red social Twitter primero he realizado un análisis de las distintas opciones ya desarrolladas y finalmente he decidido crear un desarrollo propio buscando la mejor integración con la API de Twitter del resto módulos del proyecto. En la creación del análisis del estado del arte se han desarrollado dos líneas principales de investigación: una centrada en herramientas y empresas de habla hispana y otra para todo el mercado internacional. Los prinicpales puntos de análisis en ambos casos han sido los siguientes: La red social Twitter, foco principal del estudio por su interés al ser una red social centrada en la interacción mediante mensajes de texto escrito. La red social Facebook, por su opción de comentarios tanto para perfiles de usuario como páginas de empresa. Estos comentarios centran la interacción y también están compuestos en su mayor parte por texto. Los precios que ofrecen las distintas empresas online para la compra de interacciones en ambas redes sociales, con el objetivo de tener un análisis completo de los costes medios. El principal obstáculo en el análisis de las distintas empresas analizadas ha sido parametrizar cada uno de los indicadores que querían representarse y estandarizarlos para poder 81 completo este sistema y convirtiendolo en una ”caja negra”. Esto junto a otro módulo de utils permite que el sistema tenga un sistema de loggeo, contención de errores y otras funcionalidades que facilitasen tanto el desarrollo como la solución de problemas que surgen durante el desarrollo. 88 Bibliografía [1] E. Arcoya. 5 herramientas para comprar seguidores en twitter, (2020). https://www.actualidadecommerce.com/comprar-seguidores-twitter. [2] M. Camacho. El coste de un trabajador para la empresa, (2021). https://factorialhr.es/blog/coste-empresa-trabajador/. [3] A. Cossío. Realidad y perspectivas de la inteligencia artificial en españa, (2018). https://www.pwc.es/es/publicaciones/tecnologia/assets/pwc-ia-en-espana-2018.pdf. [4] J. Mir de xplora. Google ads, ¿qué precio, tarifas y cuánto cuesta la gestión de publicidad?, (2020). https://www.xplora.eu/precio-google-ads/. [5] Statista Research Department. Redes sociales a nivel mundial con más usuarios activos, (2021). https://www.statista.com/statistics/272014/global-social-networks-ranked-bynumber-of-users/. [6] A. Durán. 11 formas de financiar un proyecto, (2021). https://www.bbva.com/es/11formas-de-financiar-un-proyecto/. [7] Jobted. Sueldo del ingeniero informático en españa, (2021). https://www.jobted.es/salario/ingeniero-informático. [8] Microsoft. Calculadora de precios, (2021). https://azure.microsoft.com/eses/pricing/calculator. [9] J. Quaglia. Celebridades y políticos compran seguidores para obtener falsa popularidad, (2013). https://www.huffingtonpost.es/juan-quaglia/celebridades-y-politicos_b_3069721.html. [10] A. Reyna. ¿qué es una aceleradora de ’startups’?, (2019). https://www.bbva.com/es/que-es-una-aceleradora-de-startups/. [11] Startupxplore. Principales aceleradoras de españa, (2021). https://startupxplore.com/es/blog/aceleradoras-espana-principales-como-funcionandemasiadas/. [12] E. Tornos. Tasa de interacción en twitter, (2021). https://eduardotornos.com/tasa-deinteraccion-engagement-twitter/. [13] Inc. Twitter. Política de desarrolladores de twitter, (2020). https://developer.twitter.com/es/developer-terms/agreement-and-policy. 89 [14] Inc. Twitter. Cuánto cuesta un servicio de marketing digital en zaask, (2021). https://www.zaask.es/cuanto-cuesta/marketing-digital. [15] Inc. Twitter. Políticas y reglas de la api de twitter, (2021). https://help.twitter.com/es/rules-and-policies/twitter-api. 90 Apéndice A Imágenes del Estado del Arte y del Business Plan Se incluyen en este apéndice las capturas, imágenes y tablas referenciadas en los capítulos del Estado del Arte (capítulo 2) y del Business Plan (capítulo 3). Figura A.1:Web compra-seguidores.com 91 Figura A.2:Compra de Me Gusta para Facebook Figura A.3:Interacciones ofrecidas por FollowersYA 92 Figura A.4:Interacciones ofrecidas por FollowersYA Figura A.5:Compra de seguidores ofrecida por compraseguidores.com 93 Figura A.6:Compra de seguidores ofrecida por compraseguidores.com Figura A.7:Compra de respuestas personalizadas de Socialforming 94 Figura A.8:Compra de respuestas de Buyviewslikes Figura A.9:Compra de respuestas de Paysocialmedia 95 Figura A.10:Compra de respuestas de Bulkcomments Figura A.11:Salarios por ingeniero informático Figura A.12:Coste estimado de un servidor de Microsoft Azure 96 Figura A.13:Balance mínimo sostenible por clientes PRO Figura A.14:Coste de un servicio de marketing, media nacional 97 Figura B.7:Services Class Diagram 104 Figura B.8:Base API Entry Schema 105 Figura B.9:Trollnet API Schema 106 Figura B.10:Diagrama de autorización a la APP de un usuario de Twitter Figura B.11:Arquitectura básica de interacción con Twitter 107 Figura B.12:Arquitectura de la base de datos de interacción con Twitter 108 Figura B.13:Diagrama de comunicación entre frontend, backend y lado Python para crear y entrenar una nueva trollnet 109 Figura B.14:Diagrama de creación de un bot en entorno de Python Figura B.15:Diagrama de vinculación de un usuario de Twitter a un bot 110 Figura B.16:Diagrama de entrenamiento de un bot en entorno de Python 111 Figura B.17:Diagrama de comunicación entre backend y el lado Python para entrenar un modelo a partir de un corpus 112 Figura B.18:Diagrama de entrenamiento de un modelo en entorno de Python 113