logo

midulive


Transcribed podcasts: 746
Time transcribed: 15d 5h 20m 39s

This graph shows how many times the word ______ has been mentioned throughout the history of the program.

Hoy vamos a estar desarrollando un proyecto de JavaScript, porque ya sabéis que tenemos una página web que es javascript100proyectos, javascript100.dev, donde aquí, de vez en cuando, me gustaría hacer más, pero de vez en cuando, hacemos proyectos que los podéis ver, por ejemplo este que hicimos, como lo del Tinder, todo con JavaScript desde cero, desde cero, todo con JavaScript desde cero, JavaScript puro y duro, también hicimos el juego de Arkano y todo con JavaScript desde cero, el reto de mecanografía, que esto es un juego muy famoso, ¿vale?
Para ver si estás escribiendo bien o escribes mal, ¿ves? Si escribes mal, puedes ir para atrás, pues este también lo hicimos con JavaScript y hoy vamos a hacer un cuarto proyecto y el cuarto proyecto que vamos a hacer es un chat GPT, pero un chat GPT muy especial, porque se va a ejecutar todo 100% en el navegador, sin backend, sin utilizar APIs, sin coste, gratuito 100%, 100% privado, todo ejecutándose en local, todo en tu máquina y me parece muy interesante por diferentes motivos.
Uno, porque es una inteligencia artificial que vais a poder llevar a webs que queráis utilizar en vuestra empresa, es una idea muy potente, muy interesante, porque tiene cero coste, se ejecuta todo en la parte del usuario, en la parte del cliente, no en el servidor, no necesitamos servidor.
Así que está muy interesante por eso y hay tecnologías que vamos a utilizar que hacen que tenga todo el sentido del mundo que la metamos aquí.
Primero, por debajo, utiliza WebGPU. ¿Cómo que sé que ha ido el página? Página funciona perfectamente. Utiliza WebGPU. Nosotros no vamos a ver cómo utiliza WebGPU, pero sí que lo vamos a explicar, que es WebGPU, porque es interesante y todo esto, pero sí que vamos a ver una tecnología que no se suele ver, que aunque sea poco lo que vayamos a ver, aunque parece que es poquito, vamos a ver WebWorkers.
Pero lo más interesante de esta tecnología es, uno, que no la conoce ni el tato, pero dos, es muy interesante y muy potente para mejorar el rendimiento de nuestras aplicaciones, porque tres, te muestra una forma de hacer programación multi-hilo en JavaScript.
Y es que JavaScript ya sabes que es monohilo, que solo funciona todo en un thread principal, pero los WebWorkers lo que te permite es delegar trabajo a otro hilo y comunicarte con él y vamos a ver cómo es eso que es tan interesante y cómo nos va a mejorar el rendimiento con este chat GPT local que vamos a hacer nosotros.
Así que vais a ver que está muy bien. Tato es quien queráis que sea. O sea, Tato es cualquier persona, básicamente. Cuando dicen no conoce el tato es que no conoce nadie, pero el tato no es que es una persona que exista.
Es una persona que no existe, tiene un nombre indeterminado. Es una expresión muy española. Pero bueno, que no os preocupéis, que el tato no es que nos va a perseguir aquí o nos va a hacer algo.
Casos de uso también darás. A ver, es que casos de uso son infinitos los casos de uso. Mira, lo podéis utilizar en vuestro portafolio. Por ejemplo, tener un modelo de inteligencia artificial que funcione en local, que se le puedan hacer preguntas sin backend ni nada.
Pero en cualquier página web, imaginad la posibilidad de que tengáis, yo que sé, un CMS como WordPress. Con esta inteligencia artificial puedas corregirle errores en el texto o darle una puntuación o escribir automáticamente el extract.
Por ejemplo, es que hay cualquier cosa que se te ocurra que lo puedas hacer en local, en el cliente, sin backend. Tiene coste gratuito 100%. Es que me parece que es impresionante.
Para extensiones de Chrome. Y además nadie te va a poder atacar porque se estaría atacando a sí mismo. No tiene muchos en todo. Tiene mil millones de casos de uso.
No creo que lo pueda hacer cualquiera. No, hombre. Es que eso es lo mejor. Vamos a utilizar una dependencia. Vamos a utilizar la dependencia de WebLLM.
Esta dependencia, la que nos va a permitir, es que vamos a aprender cosas muy interesantes que no son difíciles.
Pero vamos a ver también el sistema de módulos de JavaScript. Es que vamos a ver un montón de cosas que tienen que ver con JavaScript puro y duro.
El sistema de módulos de JavaScript, que muchas veces creemos que esto es de empaquetadores como Bit, Webpack y todo esto.
Y nada de eso. Lo vamos a ver totalmente con un proyecto de JavaScript sin empaquetadores.
Luego, vamos a ver también los WebWorkers. Vamos a ver que muy fácilmente vamos a poder utilizar inteligencia artificial de forma local.
O sea, es que un montón de cosas. Está muy chulo. Está muy chulo. Total, vamos a utilizar esta dependencia de WebLLM,
que lo que hace es poder utilizar modelos de inteligencia artificial, que ya están entrenados, directamente en tu navegador.
Y esto, aquí ellos tienen una demo, que es esta, ¿ves? Que yo he estado utilizando, haciendo unas preguntitas.
Ellos tienen como este chat GPT, mucho más trabajado, en el que le puedes escribir lo que quieras.
Lo que quieras. ¿Por qué dividir entre cero no se puede? ¿Vale? ¿Por qué dividir entre cero no se puede? ¿Vale?
Le preguntas. Entonces, ¿veis? Aquí carga el modelo de forma local. O sea, se está cargando el modelo de forma local.
Y una vez que tiene el modelo, ya funciona inmediatamente. Esto en este caso es porque se lo ha tenido que descargar la primera vez.
Pero, ¿veis? Ya está escribiendo. Y ahora, una pregunta clásica y muy interesante.
¿La razón por la que no se puede dividir? ¿Se encuentra entre cero y tal?
Vale, pues esto lo vamos a hacer y vamos a mejorarle el rendimiento a creando WebWorkers y todo esto.
Le podemos seguir escribiendo, no sé qué. Buena explicación nos está dando.
Pero esto que estáis viendo aquí, para que lo entendáis, esto que estamos viendo ahora mismo,
no está utilizando ningún backend. Todo se está ejecutando en el navegador.
Todo, todo, todo lo que veis. O sea, no hay ningún tipo de API. No hay nada.
Eso es lo que lo hace todavía más interesante. Mira, para que os lo creáis, fijaos.
Voy a mirar aquí la network. Vamos a darle aquí. Voy a decirle, dime un problema matemático interesante.
¿Vale? Le voy a dar a enviar y fijaos que me va a contestar y aquí no va a haber ninguna petición nueva.
No va a pasar absolutamente nada. No va a pasar. ¿Veis? No ha hecho la petición a ningún sitio.
Está funcionando totalmente todo el local. Eso es lo que vamos a hacer hoy.
Y os voy a explicar esto, cómo funciona realmente y tal.
Con imágenes. A ver, creo que no funcionan con imágenes, pero no tardarán en hacer que funcione con imágenes.
O sea, sí que es Oyama. Me lo lía. Que no es Oyama. Que no es Oyama.
A ver, tú lo que llamas Oyama, Oyama es una cosa diferente. ¿Vale?
Oyama es una aplicación que tú tienes que tener ejecutada en tu máquina para que funcione.
Esto es Oyama. ¿Vale? Oyama. Oyama es una aplicación que tú tienes que...
Que están para Macos, Linux y Windows.
Y la tienes que tener ejecutada en tu ordenador para que funcione.
Eso es Oyama.
Ahora, el modelo es Oyama 3. Eso es el modelo.
Oyama es una aplicación y Oyama es un modelo.
Y hay un montón de modelos que son totalmente de código abierto.
Como por ejemplo, Oyama 3. Fee. Fee, por ejemplo, es de Microsoft.
Mistral, que es de una empresa francesa.
Gema, que es de Google.
Todos estos son modelos de... ¿Ves? Este es de Microsoft.
Mistral es de una empresa aquí europea.
Gema es de Google.
Todos estos sí que los vais a poder utilizar.
Pero ojo, que esto es lo interesante.
Que no vais a necesitar instalar ninguna aplicación.
Que no vais a necesitar hacer nada.
No necesitáis Oyama. ¿Vale?
O sea, no necesitáis Oyama.
Solo funciona en web o se puede implementar en otros lados.
Así no sea una API.
A ver, solo funciona... Solo funciona en web.
Lo que vamos a ver hoy solo funciona en web.
Con JavaScript y tal, ¿eh?
No lo vais a poder utilizar, por ejemplo, con React Native.
Al menos por ahora.
¿De dónde saca los datos?
Esto no es que de dónde saque los datos.
Es que los datos ya los tiene preentrenados.
Pensemos un poco cómo es la cosa.
Estos son modelos que ya han entrenado, ¿vale?
Ya, digamos, que los han comprimido y han creado el modelo
para que tú lo puedas utilizar y ya está.
Entonces, ahí es donde estarían los datos.
Y ahora veremos cómo los descargan.
Al principio habréis visto que ha tardado un poquito y ya está, ¿no?
Ha tardado un poco porque tiene que descargar el modelo.
El modelo sí que lo descarga, aunque luego lo tiene cacheado
y ya no tiene que hacer absolutamente nada, ¿eh?
¿Funcionaría con Electron?
Con Electron yo creo que sí que funcionaría.
¿Y cuántos recursos consume?
Ahora de eso también hablaremos, ¿vale?
También comentaremos de eso.
¿Cómo se entrena un modelo?
Madre mía.
Eso no es tan sencillo.
El cómo se entrena un modelo es básicamente enviándole muchos datos.
Tú tienes que enviarle datos, explicarle datos y los nutres de datos.
Y así lo que estás haciendo es generar esas conexiones
donde transforma esos datos en tokens.
Y entonces empieza como a aprender realmente como si fuese una red neuronal
donde va asociando cada uno de los tokens,
que son datos realmente, los que le has pasado y ya está.
Pero eso ya nosotros no vamos a verlo hoy.
Vamos a tener los modelos ya entrenados.
Nosotros no vamos a tener que preocuparnos para nada de esto.
Vamos a darle cañita porque hay mucha tela que cortar.
Tenemos aquí el JavaScript 100 proyectos.
Y voy a crear una nueva carpeta que le vamos a llamar 04-CHGPT-Local.
Le llamamos CHGPT-Local, ¿vale?
Y fijaos que vamos a empezar con un index.html.
Pues aquí vamos a empezar con nuestro proyectito.
Y le vamos a...
Yo tengo este truquillo.
Bueno, es una abrevación de emet.
No sé si utilizaréis.
Pero esto aquí le dais y ¡pum!
Ya te enseña todo esto.
Podéis hacer o este, el de una exclamación, o el de tres,
que el de tres es la corta.
Pero con uno, pues tenéis esto.
Y lo bueno es que ya podéis aquí poner el CHGPT-Local,
100% privado, gratis y maravilloso.
Y aquí es donde vamos a crear nuestro CHGPT.
No va a ser el más bonito del mundo, pero al menos que funcione.
¿No vas a usar Astro?
No, porque utilizamos aquí nuestro proyecto JavaScript 100.
Son proyectos que están hechos 100% vanilla.
O sea, sin frameworks, sin nada.
Entonces lo hacemos con JavaScript plano.
HTML, CSS y JavaScript.
Todo plano totalmente.
Así que no, no vamos a utilizar Astro tampoco.
Ni vamos a utilizar Bit.
Todo es plano.
O sea, es un archivo HTML.
Plano, normal y corriente.
Sí, amigos, parece mentira.
Sé que os puede volar la cabeza.
Pero todavía existe el desarrollo web sin ninguna dependencia.
Y lo vamos a ver.
Y creo que es lo interesante para que también lo que aprendamos
sea lo más cercano a la plataforma.
Lo cual está súper bien.
Pero podemos usar Tailwind.
Podríais usar Tailwind si queréis,
pero yo no voy a usar ni Tailwind ni nada.
Sí, voy a instalar, mirad.
Voy a instalar las dependencias, ¿vale?
Mira, las dependencias que hoy vamos a instalar.
Vamos a instalar HTML, CSS y JavaScript.
JavaScript, ¿vale?
Eso es lo que vamos a instalar.
¿Os parece?
Venga, vamos a instalarlas y ya está.
Instaladas, punto.
Instaladas.
Ya hemos instalado todo lo que necesitamos hoy, punto.
Bueno, no, ahora en serio, que no vamos a necesitar nada.
HTML, CSS y JavaScript.
No necesitáis saber nada más.
Es lo más sencillo del universo, ¿eh?
¿Cuánto pesan?
Cero.
Cero cas.
Encima gratis.
Pues venga, vamos a empezar con el HTML.
Yo tengo una extensión.
Siempre os la digo porque es que si no, la gente se me vuelve loca.
Microsoft tiene una extensión que se llama Live Preview.
Es mi favorita para trabajar con este tipo de cositas.
¿Ves?
Live Preview.
Y esto lo que hace es levantarte como un entorno de desarrollo para tu HTML.
También tenéis Live Server.
A mí me gusta más Live Preview, pero bueno, cada uno que utilice el que le dé la gana.
Y lo único que tenéis que hacer es Live Preview, iniciar el servidor y os aparece aquí.
Ah, claro.
Aquí.
Claro.
Vale, vale.
Pues no, no puedo hacerlo así.
Voy a hacer otra cosa.
Voy a entrar directamente en el 0.4 chat gpt.
Voy a entrar aquí en la carpeta y ahora sí que funcionará, ¿vale?
Para que no me dé problemas.
Para que no me dé problemas, ahora sí.
Live Preview.
Ahí he tenido que entrar directamente en la carpeta, iniciar aquí el servidor.
Y ahora sí, porque está vacío, no pasa nada.
Ahora veremos alguna cosa.
Live Preview.
Vale, quitamos esto.
Y esta es la previsualización.
Así que aquí ponemos chat gpt, ¿ves?
Y ya ponemos aquí.
Lo que me gusta mucho de Live Preview es que conforme tú vas escribiendo, ¿ves?
Te lo va refrescando en tiempo real.
No tienes que guardar, no tienes que hacer nada.
Directamente te lo refresca y ya está.
Pues aquí vamos a poner el HTML directamente y vamos a por ella.
Vamos a crear la estructura básica.
Tampoco nos vamos a volver muy locos.
Pero vamos a imaginarnos que vamos a tener un elemento main donde vamos a tener la lista de mensajes.
La lista de mensajes le vamos a poner unas clases, ¿vale?
Donde vamos a tener los que son los del bot.
Y dentro vamos a tener un spam donde veremos quién ha sido.
Voy a poner gpt como que podría haber puesto otra cosa.
Y otro spam que sería, bueno, esta es la respuesta del bot.
Y esto mismo lo vamos a tener, pero no os preocupéis que hará lo estilo, ¿eh?
Vamos a tener el del usuario, que aquí en lugar de esto vamos a poner tú.
Y aquí vamos a poner esta es la respuesta del usuario.
Y así ahora cuando ponga los estilos, pues al menos lo veré bien.
Voy a poner otro solo para asegurarme que se ve bien esta respuesta del usuario.
Y es una respuesta muy larga para ver que no se rompe nada, ¿vale?
Esto sería un poco el main, pero vamos a necesitar también un formulario.
Un formulario donde vamos a escribirle a nuestra inteligencia artificial.
Escribe tu mensaje.
Bueno, el type, mira, vais a aprender algo de HTML que está interesante.
No sé si lo sabíais, pero el tipo text, el tipo text es opcional.
No sé si lo sabéis, pero es opcional.
Lo podéis quitar.
Los inputs que son type text, el type text es por defecto.
Entonces, si no lo ponéis, pues va a aparecer exactamente igual.
Y mira, está bien porque así, pues eso que os agarráis un poquito más corto.
Yo muchas veces lo hago, que lo quito y ya está.
Y el nombre no lo vamos a necesitar tampoco.
Así que vamos a poner esto.
Vamos a poner, escribe tu mensaje aquí, ¿vale?
Aquí.
Y aquí vamos a tener un botón que sea enviar, ¿vale?
Enviar, ya está.
Vale.
Y aquí al final vamos a tener...
Esto sería todo lo visual que vamos a necesitar.
Lo que pasa es que será escribiendo.
Pero hoy también vamos a aprender una etiqueta que quizá no conoces.
Es que hoy vamos a aprender muchas cosas, ¿eh?
Vamos a aprender un montón de cosas.
Mira, web workers, ahora estoy pensando los templates, que es una cosa que mucha gente no conoce y es una etiqueta de HTML que está bastante bien.
Así que no sé si sabéis lo que es esto, ¿vale?
La etiqueta template.
La etiqueta template es una etiqueta que realmente no se renderiza, pero te permite introducir HTML como fragmentos de HTML que luego puedes utilizar ya sea para JavaScript o para cualquier HTML dinámico que vayas a generar.
Lo cual está súper, súper bien y es bastante útil para no tener que generarlo dentro de JavaScript, ¿vale?
Entonces, por ejemplo, fijaos aquí que tenemos una tabla y tenemos un template donde podemos tener ya el HTML generado para cada una de las filas que vamos a tener dentro del cuerpo.
Y así podemos recuperar este template y lo que haríamos es dentro meter la información.
Pues es un poco lo mismo que vamos a hacer nosotros.
¿Por qué?
Porque fijaos que aquí tenemos estos mensajes y estos mensajes nosotros los vamos a querer generar.
Hacerlo con JavaScript es una pérdida de tiempo porque lo mejor es hacerlo con HTML, tener las bases e introducir la información que queremos.
Entonces, vamos a utilizar la etiqueta template, le vamos a dar una ID como cualquier elemento.
Vamos a decir que esto es un message template y dentro, pues exactamente esto.
Vamos a hacer como si fuese este li.
Lo que pasa es que vacío lo vamos a hacer.
Vamos a quitar este de bot porque no sabremos si es un bot o es del usuario.
Vamos a tener el primer span, esto lo vamos a quitar por aquí y lo repetimos.
¿Por qué?
Porque queremos esta misma estructura, la queremos aquí, la queremos replicar y luego poder recuperarla.
Recuperaremos este template y le diremos, cloname este HTML que lo quiero reutilizar y le diremos,
méteme aquí esta información, aquí esta información y este HTML resultante, pues me lo tienes que poner acá.
Y así tendremos este template aquí.
Podéis tener tantos templates como queráis y con el identificador vais a poder reutilizarlos tantas veces como queráis,
donde queráis y lo que sea.
Vale, pues esto sería un poco el HTML que necesitamos.
A ver, yo creo que ya está bien.
O sea, no necesitamos nada más.
¿La etiqueta template es nueva en HTML?
No, mira, la etiqueta template es más vieja que el caminar hacia adelante.
O sea, la etiqueta template nació más o menos entre los dinosaurios y los, vamos, entre los homínidos.
O sea, madre mía, no tiene tiempo, no tiene tiempo la etiqueta template.
Es vieja pero a rabiar la etiqueta template.
Estaba el tato y todo.
Sí, sí, no, en serio.
La etiqueta template tiene muchos años.
Tiene muchos años, de verdad.
No es nueva para nada.
De hecho, a ver, si veis la compatibilidad, pues vais a ver que es infinita.
Template, a ver si aparece.
Template HTML y template.
Bueno, 97,62.
Pero fijaos que...
Bueno, espérate, porque esto es HTML templates, que este no es ni siquiera.
Este creo que ni siquiera es.
¿Puede ser que este no sea?
Porque una cosa es la etiqueta, que la etiqueta al final existía de hace tiempo.
Bueno, pues igual sí que es esto, igual sí que es esto.
Nada, pero ya hace mucho, mucho, mucho tiempo.
Mucho, mucho tiempo.
Fijaos.
Ah, pues sí que es este.
Pero nada, que tiene un 97% de compatibilidad, que ya está por todos los sitios.
Es verdad que en Internet Explorer no tiene soporte, pero una cosa que se podía hacer con Internet Explorer...
A ver, Internet Explorer...
Yo no sé todavía ni quién utiliza Internet Explorer.
Pero en Internet Explorer es muy fácil hacer que no se vea.
Que le pongas display none y ya está.
Ya te olvidas y ya está.
Pero no, hace ya muchos, muchos años, de verdad, que se utiliza la etiqueta template, así que no os preocupéis.
¿Qué es IE?
Ya, ya, no.
Tú ríete, pero hay gente lo suficientemente joven que no tiene ni puñetera idea que es Internet Explorer, ¿eh?
Eso nos reímos, pero no nos riamos tanto porque...
El otro día estuve dando una charla y dije, claro, es que esto es del 2003.
Y hay alguien que, digo, todos lo sabéis, ¿no?
Me dice, perdón, yo es que no había nacido todavía en el 2003.
¡Claro!
Es que hay gente que tiene 20 años que en el 2003 no existía.
Madre mía.
Y yo en la universidad, ¿sabes?
Estos niños de hoy en día.
Se ve muy feo.
Tienes razón.
Seguro que estás pensando eso.
No te preocupes.
Hemos venido también aquí a hacer los estilos rápidamente.
Vamos a poner PhoneFamily.
Yo utilizo System UI, que son las fuentes del sistema.
Esto es lo que hace es utilizarte las tuyas del sistema de Mac, de Windows, de Linux, la que sea.
Si no tiene la de Mac, utiliza...
Esto es un fallback.
Va de izquierda a derecha.
Pero, ojo, mira, voy a explicar una que es muy interesante, que es esta.
La primera, System UI.
Fíjate que se ve exactamente igual.
Esta System UI, esto que ves aquí, esto es una variable de CSS, también un poco conocida,
que lo que hace es priorizar por defecto la familia, la fuente del sistema operativo.
Entonces, esto en realidad tú lo utilizas ya de una y ya debería funcionar.
¿Veis que ya funciona y ya se ve aquí el PhoneFamily correcto?
Si yo lo quito esto, fíjate, yo quito esto, ¿veis?
Se ve otra, que creo que es la Times New Roman.
Por defecto se ve la Times New Roman.
Pero solo con esta, System UI ya lo hace.
¿Por qué entonces se pone todo lo demás?
¿Por qué se pone todo lo demás?
Porque resulta que por temas de retrocompatibilidad
y porque la variable de System UI en algunos navegadores no funciona del todo bien.
Entonces, por cosas antiguas, históricas, se utiliza como toda la lista,
pero que sepas que lo podríamos dejar así
y quedaría ya perfecto.
Lo podemos hacer perfectamente.
Pues vamos ahí, PhoneFamily, System UI, perfecto.
Vamos a poner un background.
Tampoco nada, yo que sé, F0, F0, un grisecito ahí.
Display Grid, Place Content Center, para centrarlo todo.
La altura.
Vamos a utilizar el DVH, que parece...
DVH me encanta porque parece una enfermedad.
Oye, 100 DVH, parece que te ha dado un cáncer o algo.
DVH.
DVH es Dynamic Viewport High.
¿Cuál es la diferencia entre DVH?
¿Cuál es la diferencia entre DVH?
¿DVH?
¿VH?
¿Vale?
¿Cuál es la diferencia entre estas dos?
La diferencia entre estas dos,
esta es Dynamic Viewport High y esta es Viewport High.
La diferencia es poca, pero notoria e importante.
Y tiene que ver mucho con los dispositivos móviles.
Mira, ¿cuál es el problema?
El problema es que el de toda la vida, el de 100 VH,
el problema es que, fíjate que ocuparía también la barra
que tienes aquí de herramientas.
O incluso si aparece el teclado o ves la barra de direcciones.
Entonces, el problema de 100 VH es que siempre es el mismo
y por lo tanto puede quedar un poco raro
o te puede hacer un scroll y cosas así.
En cambio, el Dynamic Viewport High lo que hace es que detecta
dinámicamente si está mostrando la barra de tareas o no
y se ajusta, se adapta al tamaño del Viewport
en la posibilidad de cuando es el más pequeño o el más grande.
Entonces, normalmente este, normalmente, no siempre,
no tiene por qué siempre ser así,
pero normalmente, sobre todo si hablamos del contenido de tu web,
normalmente vas a querer utilizar este.
Entonces, una cosa que puedes hacer para que lo sepáis
es que, claro, este es bastante nuevo,
entonces el soporte no será del 100%.
A ver si así lo podemos encontrar.
Vale, 88%.
Está bastante bien.
88%.
No, 23%.
No, 23%.
Joder, bueno, está de lujo.
Pero si por lo que sea todavía tenéis algún problema,
una cosa que podéis hacer es, sería esta.
Podéis poner primero esta y luego la otra.
¿Vale?
¿Por qué?
Porque si esta no la soporta, la ignorará y utilizará esta.
Y ya está.
Así funciona CSS muchas veces.
Ahora utilizaré DVH hasta en mi vida.
No, la verdad es que si podéis, pues tiene mucho sentido.
Si no, otra cosa que hay, hay mucho.
Claro, si utilizas post CSS, esto te lo transforma y te hace mil historias.
Así que no os tenéis que preocupar.
¿Vale?
Muy bien.
Vale, pues ya tenemos unos pocos estilos.
Va, voy a adelantar un poco estilos porque si no...
Vale, vamos a poner que el main tenga esto con el 100%.
Lo vamos...
A ver, no son clases de CSS.
Por lo tanto, de CSS no esperéis que me ponga yo aquí a explicaros todo el CSS.
Ya os voy explicando.
Pero que voy a intentar hacer algo que quede más o menos bonito.
Pero que tampoco espero que sea responsive, que todo funcione perfecto.
Lo importante va a ser la parte de JavaScript que vamos a hacer en un momento.
¿Vale?
Voy a separar la parte de abajo un poco.
¿Vale?
Y aquí vamos a hacer que tenga un overflow del scroll o auto.
Vamos a poner auto.
¿Vale?
Bueno, ahora no se ve el overflow, pero ya se verá.
Vamos a estilar ahora la lista de mensajes.
Entonces, le ponemos un display flex, column.
Vamos a hacer que vaya todo.
Le vamos a quitar la lista esta.
List style none.
Y vamos a hacer que el padding se ponga cero para que tenga bien ahí la separación.
Creo que habíamos puesto una clase para los mensajes.
Message.
Vale.
Pues vamos a estirar los mensajes.
Y mira, otra cosa que vamos a aprender aquí a utilizar el parent...
Bueno, el parent selector no.
El nested.
Nested selector, que está bastante bien.
Vale.
Display flex.
Siempre el display flex para todos los sitios.
Column.
¿Vale?
Porque queremos que quede...
O encima...
O sea, vamos a hacer que...
Ahora lo veréis más claro.
Pero hacemos que la persona quede arriba y el mensaje abajo.
Y ahora le ponemos también una separación.
¿Vale?
Para que tenga una separación.
Y de cada mensaje vamos a hacer que esté mejor separado.
Martin no.
Margin.
¿Vale?
Y le vamos a poner un padding.
¿Vale?
También para que estén mejor separados todos los mensajes.
Y ahora lo que haremos también...
Voy a poner...
Bueno, el borde radio lo arreglamos ahora.
¿Vale?
El primer span...
Ya veis que no estoy utilizando muchas clases porque no tengo ganas de poner nombres a las cosas.
¿Vale?
Por eso, aquí voy este lee, que es el mensaje.
El primer span es la parte de esta.
Y el segundo span, que es el mensaje, lo tengo abajo.
Entonces, no quiero poner clases, no tengo ganas de perder tiempo en eso.
Y como os digo, lo importante va a ser el JavaScript.
Entonces, lo que estoy diciendo es, en el mensaje, el primer hijo que sea span, entonces, pues vamos a poner aquí que tenga algo, ¿no?
Vamos a poner el primer hijo, vamos a hacer que sea una redonda.
Vamos a ponerlo ahí como una redonda.
Vamos a poner por ahora que tenga un background cualquiera.
Yo que sé.
Solo para ver que...
Vale.
Y así veré que lo estoy haciendo bien.
Vamos a hacer que esto sea un poquito más pequeño.
Vamos a poner que sea semi-volt.
No sé si poner volt o algo así.
Y lo vamos a centrar.
¿Vale?
Flex, justify, justify content center, center.
¿Vale?
Y le hacemos que esto sea un borde radius 99999 para que quede redondo.
Bueno, no está mal, no está mal.
Poco a poco, poco a poco.
Esto sería para las cosas estas que son los primeros hijos.
¿Vale?
Y ahora, el mensaje sería lo mismo, pero el último hijo.
Ahora, el último hijo, que es el mensaje, pues vamos a ponerle un poquito de separación y vamos a...
Vale.
Por ahora lo vamos a dejar así.
Ya está.
Un poquito de separación.
Porque ahora lo que quiero es que cada uno, por ejemplo, si es el usuario...
Los usuarios vamos a hacer que se peguen a la derecha.
¿Vale?
Entonces, vamos a hacer que align self sea flex end.
¿Vale?
¿Veis?
Así se va a la derecha y así...
Como que queda mejor.
Es tipo chat.
Un tipo chat.
Y también vamos a poner los items al final para que quede pegado esto también aquí.
Y ya esto...
Este es el usuario.
Pues vamos a ponerle un color a los background...
No sé qué color ponerle.
Orange.
Orange queda un poco...
Vamos a ponerle blue, pero un blue más flojito.
¿Vale?
Le ponemos blue, pero ahora con esto, pues ponemos esto por aquí, esto por acá.
Esto...
Así.
Así me parece bien.
Algo así.
¿Vale?
Y ya estoy viendo que aquí este last child...
Vamos a ponerle el border radius a 4 píxeles.
Algo así.
Para que quede así.
Y esto mismo, pero para el bot, vamos a hacer que el span tenga un background.
La verdad es que aquí podríamos haber hecho esto del background de otra forma.
Pero bueno, no pasa nada.
Este orange...
No, orange no.
Vamos a poner que sea...
¡Ah, Dios mío!
A ver.
Que sea verde.
Ponemos verde.
Algo así.
¿Qué os parecen?
A ver, no son los mejores colores del mundo.
Pero un momentito.
¿Vale?
Más o menos.
Para arreglar...
Claro, para arreglar esto, porque veis que esto llega hasta el final.
No sé si se ve.
Sí.
¿Veis que esto llega aquí hasta el final?
Esto lo podríamos arreglar...
Creo que si la ponemos en la line self...
Flex start...
¿Veis?
Ahora ya queda bien.
Vale, perfecto.
Ya está.
Pues así lo tenemos.
Vale.
También podríamos hacer lo del...
With content y todo esto.
Porque he puesto el 999...
Es verdad que me he pasado.
Me he pasado.
No me he pasado.
Es verdad que he puesto esto.
Esto lo he puesto más que nada por no pensar.
¿Vale?
Esto lo he puesto por no pensar.
El mensaje no debería ser una P.
Tenéis razón.
Debería ser una P.
Pero...
Bueno, venga.
Vamos a hacer que sea una P.
Me fastidiáis un poco todos los asuntos.
Porque había puesto spam ya para no pensar mucho.
Pero vamos a hacer que sea una P.
Y así también simplificamos un poco el tema este.
¿Vale?
Me habéis fastidiado aquí todo el asunto.
Pero vamos a hacerlo bien.
Vamos a hacerlo bien.
Vamos a hacerlo bien.
Va.
Vamos a hacerlo bien.
Entonces decimos que si esto es una P y esto es una spam.
Y así también se simplifica.
Perdonad.
Perdonad.
¿Vale?
¿Veis?
Ahora me lo habéis liado.
Me lo habéis liado porque...
¿Por qué no me pillan los estilos?
¿Por qué no me pillan este estilo?
¿Por qué no me pillan este estilo?
¿Por qué no me pillan este estilo?
¿Dónde hemos cambiado esto que no lo ha cambiado bien?
Esta P, esta P...
¿Ves?
Me lo habéis liado.
Me lo habéis liado.
En un momento.
En un momento.
Os he hecho caso y ya la hemos liado.
No, pero en serio.
¿Qué es lo que he hecho?
A ver.
Este spam está bien.
Aquí está pillando bien.
Dentro de message tendríamos la P.
La P...
El...
Ah.
Porque...
Vale, vale.
Ya está, ya está.
Vale, vale.
Vale, vale.
También podríamos utilizar una custom property.
También lo digo, ¿eh?
También podríamos hacer una custom property.
Vale, ya está.
Ahora sí, ahora sí, ahora sí.
Esto ahora está bien.
Ahora está bien.
Eh...
El last child.
No, no, no.
El last child.
Eso está bien.
Pues nada, nos faltan los estilos un poco del formulario.
En un momentito.
Oh, chin, chan, chin, chan.
Y ya está.
Y ya lo tendríamos.
¿Vale?
Así que vamos con los estilos del formulario.
Tampoco nada fancy.
Con que se vea un poquito.
Y así empezamos ya con nuestro querido...
Con nuestro...
JavaScript.
Display Flex.
Estamos utilizando, por cierto,
el nested selector, que está bastante bien.
O sea, esto lo que quiere decir...
Tú utilizas aquí una etiqueta
y aquí dentro pones otra etiqueta
y esto sería como si escribieses esto.
Form input.
¿Vale?
Es como si escribieses esto.
O sea, esto que yo voy a poner aquí dentro del input,
por ejemplo, border radius,
que he puesto lo del 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 píxeles.
Ahora os explico esto, ¿vale?
Vamos a poner crezca todo, border 0,
porque seno se ve raro.
Border 0.
Padding, 12 píxeles.
Bueno, 12 píxeles es demasiado mejor.
8 píxeles.
¿Vale?
8 píxeles.
Margin, 8 píxeles.
Para que tenga un poquito de separación.
le ponemos un borde así un poquito
chiquitito, ¿vale? para que se vea
más o menos, ¿vale? pues esto
que hemos hecho aquí es como si
hiciésemos esto de aquí, ¿vale?
a esto se llama nested selector
y hombre, está bastante bien, es una cosa que hace mucho
tiempo que tenía SAS, SSSS
y todo esto, pero te facilita
y te permite agrupar los
elementos que estás estilando y queda bastante
bien, y dentro de input podríamos
volver a hacer, por ejemplo, dentro del
bueno, el botón, como va a tener
joven, lo vas a ver, el botón, pues ponemos
el botón, un background, yo que sé
algo así, border 0
color white
¿vale? vamos a ponerle también border
radius, no tan exagerado
cursor pointer
esto es polémico, lo sé, pero bueno
yo lo voy a hacer porque como estamos muy acostumbrados
ponemos un padding
de 8
bueno, no veis el botón, no estáis viendo como
estoy estirando el botón, pero os lo voy a enseñar
un momento para que nadie se asuste
este es el botón, ¿vale? está quedando así, más o menos
tampoco nada del otro mundo, ya es nativo de CSS
sí, sí, es nativo de CSS, pero bueno
este es el botón como está quedando
solo nos faltaría el hover, y esto es lo que os decía
que podéis estar constantemente
anidando, y aquí
como para reutilizar el mismo
parent, o sea, el padre, le tenéis
que poner este ampersand, y aquí
le estamos diciendo como si pusiéramos aquí este
nos referimos al botón, por lo tanto ponemos
el ampersand, esto ya os digo que en SAS
pues es muy, muy típico
o en stylus
y todo esto, vamos a hacer que sea un poco más
oscuro, y ya está
ponemos una transition del background
y ya está
y con esto, pues ya tenemos
ahí nuestro botoncito, con una pequeña animación
nada del otro mundo, pero bueno, ya estaría
esto es toda la parte de CSS, no os preocupéis
que no vamos a tocar más CSS
igual un poquito más, pero no mucho más
¿vale? pero muy poquito, muy poquito
alguien ya me está diciendo que hay mucho gap
entre no sé qué, no sé cuánto, a ver, que no espero
ser aquí Leonardo Da Vinci
dibujando la yokanda, ¿eh? o sea, he hecho un estilo
bastante simple, entonces no esperéis aquí
que voy a hacer unos estilos
impresionantes, voy a quitar
voy a quitar el gap, por ejemplo
y aquí margin 0
¿por qué tiene tanta
separación esto? en algún sitio
este margin, este no será por el margin
y por el padding tampoco es, no sé
aquí por qué hay tanta separación
podría hacer, o sea, es que no
tengo ganas de perder mucho
tiempo en esto, ¿eh? pero
no sé por qué hay tanta separación
entre estos dos, display flex
flex direction, porque este no tiene
el gap, bueno, no tengo ni idea, ¿qué más da?
¿qué más da? ¿qué más da?
es que te veo la gsconf, hostia, que me he
enterado por Twitter que la gsconf de Chile
lo van a cambiar, ¿eh? lo van a cambiar
¡ah! ya sé lo que es, claro, es que
antes no quedaba tanto porque
el párrafo seguramente
tiene un margen por defecto
claro, como no hemos utilizado un reset
vale, ya está, ¿vale? por eso ha tenido
tanto, ¿eh? ese es el tema
que como no estábamos teniendo aquí
no estaba teniendo en cuenta los estilos
por defecto, ¿vale? pero
¿ahora mejor? ¿algo así? ¿mejor?
¿sí? pues así más o menos
vamos a, ya está, ¿eh? se acabó el CSS
tiene más separación que la extóxica
¡qué malo sois!
sois la leche
vamos con scripts, ¿vale? vamos a hacer el
javascript, vamos a hacer el javascript
amigos, y sí, tenía que haber utilizado
mi CSS reset, voy a tener que hacer mi CSS reset
vale, vamos con javascript
esto es muy interesante porque os voy a
explicar algo que os va a llamar la atención
vale, normalmente
y es que esto está interesante
porque, a ver, podríamos poner el script
aquí arriba, ¿vale? y de hecho lo podemos
poner justo después de los estilos
vamos a poner los estilos
porque son más críticos y luego ponemos
los, el javascript
el javascript lo vamos a poner en línea
porque lo hacemos siempre así con estos
proyectos que son vanilla
pero lo podemos poner en un archivo
pero en este caso lo vamos a hacer aquí
y entonces ahora podríamos recuperar
por ejemplo el formulario, ¿vale?
entonces hacemos document.queryselectorform
voy a poner, pongo delante de la variable
un símbolo de dólar
para indicar que es un
elemento del DOM, ¿vale?
por eso lo hago
y sí, tiene que ver con jQuery y todo esto
pero lo hago para que sepa que este
esta variable tiene un elemento del DOM
es una cosa que hacía antiguamente
por eso lo hago
entonces, ¿qué pasa con esto?
que si nosotros ponemos el script ahí
fijaos que
ah, pues no me da ningún problema
vale, perfecto
pensaba que me iba a dar un problema
al ponerlo aquí
a ver si hacemos console.log
ah, claro, no me va a dar ningún problema
pero porque no estoy haciendo nada con él
porque fijaos que
si yo pongo arriba el javascript
es que esto quiero que lo entendáis
porque muy poca gente entiende realmente esto
y vais a ver la razón
por la que javascript
los scripts en línea
se ponen o con defer
o se ponen abajo
vale, imaginad que yo digo
lo pongo aquí arriba
digo, vale, script
voy a recuperar el formulario
querySelector
y hago un console.log del formulario
o peor todavía
que es lo que queríamos hacer
hago form.atblistener
cuando hago un submit
pues vamos a ver aquí
vamos a hacer un event.preventDefault
porque no queremos que haga su comportamiento
por defecto
¿no?
y aquí pues hacemos
hacemos más cosas
¿vale?
guardamos los cambios
y fijaos en una cosita
que nos da un pete
nos da un pete
porque este elemento
que estamos intentando recuperar
en esta línea
todavía no existe
y es que como se ejecuta
javascript por defecto
así en línea
es que paraliza la página
lo evalúa
y lo ejecuta
¿y qué pasa?
que este elemento
el formulario
no se crea
hasta que no es después
que es aquí
¿vale?
entonces por eso no lo ve
entonces
algo tan fácil como esto
¿cómo lo podemos arreglar?
de dos formas
uno
podemos mover el script
aquí abajo
¿vale?
lo movemos aquí abajo
y ahora vais a ver
que
bueno quito esto
y vais a ver que no hay ningún error
¿vale?
ya está
ya funciona
¿por qué?
porque ahora este elemento
sí que existe
lo tenemos aquí
entonces lo ha creado
y luego evalúa
el javascript
otra forma de arreglar esto
es dejarlo donde estaba
y ponerle
el atributo
defer
que además
es la mejor forma
y ahora te explicaré por qué
¿vale?
le ponemos el atributo
defer
y el atributo
defer
lo que le indica
es
oye
quiero que
ah
espérate
porque
me ha dejado fatal
me ha dejado fatal
me ha dejado fatal
porque fijaos
me está dando
el mismo pete
me está dando el mismo pete
o sea
me está dando
me ha dejado fatal
me ha dejado fatal
¿puede ser que sea
que el defer
le tenemos que poner
true?
puede ser
como hace tiempo
que no lo pongo a mano
no
a ver
script
defer
no pero sí
estoy seguro que era así
aaaaa
ahora
qué bueno es esto
ahora vais a entender por qué
ahora entiendo
es que claro
en mi cabeza
sonaba espectacular
pero
es que el tema
mira mira
qué bueno
qué bueno
no acordaba de esto
el tema
es que el defer
no funciona
con los scripts en línea
cierto
el defer
no funciona
con los scripts en línea
es verdad
es verdad
no funciona
no podéis hacer esto
no se puede hacer un defer
vale
porque el javascript
está en line
y por lo tanto
no puedo hacer un defer
vale
defer
¿qué es lo que hace?
lo que hace el defer
es que le indica
al navegador
que quieres cargar
el javascript
pero evaluarlo
ejecutarlo
solo cuando ha terminado
de cargar todo el html
y claro
con un archivo en línea
o sea
con el código en línea
no funciona
pero
hay otra forma
de solucionar esto
que es
utilizando el documentonload
cuando
a documentatvlistener
que cuando has hecho
el doncontentloaded
entonces ejecutar
todo este código
y aquí meterías
todo este código
y esto sí que funcionaría
harías como las dos cosas
que lo cargaría arriba
y tal vez
ahora no puede
no habría ningún problema
entonces
hay una tercera
forma de hacerlo
una tercera
que es la más interesante
y la de que
yo a partir de ahora
os recomendaría
y que además
la vamos a necesitar
y es utilizando
un setTimeout
no es broma
te imaginas
esto fuera
vale
esto no es necesario
no hay que hacerlo
ya a día de hoy
lo que hay que hacer ahora
es utilizar
el de tipo módulo
vale
le decimos
que es que
este script
es de type module
y esto va a hacer
que podamos utilizar
aquí dentro
import
o export
por ejemplo
vale
vamos a poder hacer esto
import y export
los import y export
de toda la vida
vale
y este type module
va a funcionar
como si fuese
un defer
o sea esto
aunque lo pongamos arriba
fijaos que ahora
no me está dando
ningún tipo de problema
vale
y este type module
esto es algo
nativo de javascript
vale
vamos a poner aquí
module
para que lo veáis
module
y vais a ver
que el module
lo ves
lo tengo aquí
me ha cargado el module
ha funcionado correctamente
y lo más interesante
es que esto
lo ha cargado
pero no lo ha evaluado
hasta que no ha terminado
de cargar toda la página
y luego vamos a ver
que esto es importante
el type module
porque vamos a tener
que hacer un import
pero bueno
solo para que veáis
todas las opciones
que teníais
vale
el tipo módulo
esto si que es algo
más o menos moderno
pero es una cosa
que podéis utilizar
en cualquier página
html
sin ningún tipo de problema
así que tenedlo en cuenta
que el type module
es la mejor opción
a día de hoy
la mejor
la mejor
que podéis utilizar
porque al final
aparte de que la forma moderna
de cargar javascript
también funciona
para javascript en línea
también para los archivos
te va a hacer el defer
automáticamente
vale
así que si tenéis que hacer
javascript
vanila
lo mejor que podéis utilizar
el type module
a no ser que tengas
que soportar un
yo que sé
un navegador
que eres en blanco y negro
y todo esto
pero bueno
ponemos el type module
y ya lo teníamos
incluso sin usar import
yo aunque no tenga que usar import
lo intentaría utilizar
vale
porque otra cosa es que
por lo que sea
no sea compatible
con lo que estáis haciendo
pero es que
es mucho más interesante
utilizar el type module
porque es la forma moderna
y como os digo
ya vais a tener
arreglado totalmente
el tema de la carga
es totalmente asíncrono
está súper bien
venga
formulario
vamos a recuperar
todos los elementos
que necesitamos
necesitamos el input
también
vale
como ya veo
un poco esto
del query selector
para la gente
que le gusta jQuery
vamos a crear
nuestro jQuery
con una línea de código
vale
ya tenemos jQuery
ala ya está
ya hemos creado jQuery
con una línea de código
hemos creado jQuery
y así no tengo que escribir
todo el rato
ahí no sé qué
vamos a recuperar
el template
vale
que hemos creado antes
vamos a crear
también los mensajes
vamos a tener
el container
también
y el botón
también me lo voy a traer
para desactivarlo
cuando hagamos
lo de enviar
vale
esto básicamente
es un método
que podéis utilizar
el dólar
para crear el método
y le pasamos
por parámetro
el elemento
que queremos recuperar
y hacemos un document
.Query
selector
con el elemento
y ya está
y así podemos hacer esto
que queda un poco mejor
que tener que estar repitiendo
todo el rato lo mismo
entonces
funcionalidad básica
que necesitamos
es que cuando el usuario
escriba
y envíe un mensaje
pues obviamente
lo vamos a querer mostrar
lo primero que habría que hacer
habría que hacer muchas cosas
pero vamos a limpiar un poco
el mensaje del usuario
y para eso vamos a hacerle un trim
un trim es eliminar los espacios
de la lente y de atrás
y ya está
tampoco es nada del otro mundo
pero al menos así nos aseguramos
que podemos recuperar
podemos mirar
vamos a poner message
message text
vale
para asegurarnos
que no nos confundimos con nada
que si es diferente
a un stream vacío
pues vamos a añadir
añadimos el mensaje
en el DOM
vale
y luego lo que hacemos
es resetear el input
y le ponemos el valor
así
con esto
solo con esto
ya cuando
cuando yo escribo aquí
y le doy al enter
debería
vale
resetearse
no aparece
porque todavía aquí no tenemos
la forma de añadir el mensaje
pero lo añadimos ahora
vamos a crear aquí una función
add message
donde vamos a tener
por un lado
el mensaje
bueno
vamos a ponerle text
y la persona que lo envía
porque
pensad que tenemos
tanto al usuario
como al bot
primero
clonar el template
para esto lo hemos creado
el template
que es este
esto que tenemos aquí
vale
esto es un elemento
HTML
que no se renderiza
en el DOM
y nos permite crear
construcciones HTML
que vamos a poder
recuperar en JavaScript
para generar
HTML dinámico
y justo aquí
lo estamos recuperando
ves
template
message template
pues esto
vamos a clonarlo
vamos a tener el
clon
HTML
por ejemplo
o clon
template
y aquí
tenemos el template
quiero que el contenido
me hagas
un clon
y le pasamos
true
que es este true
este true
lo que estamos diciendo
es que tiene que hacer
una clonación
profunda
porque si no
lo que va a hacer
es que nos hace una clonación
superficial
y los elementos
que tenemos dentro del template
los estaríamos modificando
entonces lo que queremos
es que nos haga una copia
profunda
de todo lo que tenemos
dentro del template
y así podremos reutilizar
sin miedo
constantemente
este HTML
¿vale?
así que este true
que no se te olvide
porque si no
la puedes liar
pardísima
luego
aquí tendríamos
el new message
vamos a tener que recuperar
el template
que hemos clonado
hemos creado
este HTML
lo hemos clonado
pero este HTML
ahora digamos
que está en memoria
no está en ningún sitio
así que este
clone template
vamos a tener que
recuperar
con el query selector
vamos a tener que
recuperar
el mensaje
¿vale?
el mensaje
vamos a hacer esto
un poco más pequeño
para que quepa esto
porque fijaos que en el template
dentro tenemos la clase message
¿vale?
hemos clonado todo esto
y ahora lo que quiero
es recuperar esta parte
de message
entonces así ya teníamos
el mensaje
¿vale?
ya teníamos el elemento mensaje
y ahora en este mensaje
vamos a recuperar
por un lado
el who
¿vale?
el who sería
new message
.query selector
el span
¿no?
porque hemos dicho
que tendríamos
en el span
y aquí tendríamos
en el texto
para el párrafo
porque fíjate
que en el span
te dice
quién ha sido
y el párrafo
te dice el texto
tendríamos estos dos elementos
pues ahora ya simplemente
teníamos que decirle
el text.textcontent
le pasamos el texto
le pasamos por parámetro
y en el who
.textcontent
aquí tenemos que hacer
un poquito
a ver
es que estoy pensando
bueno
si le vamos a poner sender
y ya está
¿quién lo está enviando?
que será gpt
o será tú
o ya está
¿qué más tendríamos
que hacer por aquí?
tendríamos que indicar
si es el usuario
o si es el bot
¿vale?
entonces
este new message
fijaos que aquí
habíamos puesto
una clase
bot o user
entonces
este new message
que es el mensaje completo
vamos a añadirle
una class list
le vamos a añadir
el sender
claro
en el sender
ya veo que le vamos a pasar
bot o user
¿vale?
podemos hacer una cosa
si sender
es bot
vamos a poner aquí
gpt
esto lo he puesto al revés
¿eh?
y si no
vamos a poner aquí

¿vale?
y aquí le pondremos
la clase sender
y aquí en sender
le pasaremos
si es bot
o user directamente
y creo que con esto
yo creo que con esto
ya está
tendríamos que ver aquí
de actualizar el scroll
para ir bajando
eso lo haremos después
¿vale?
que debe ser un momento
y una vez que ya tenemos
todo esto
claro
necesitamos
todo este html
que hemos creado
que hemos clonado
lo hemos clonado
primero
hemos recuperado
el mensaje
luego los elementos internos
hemos
hemos escrito
la información
pero todavía nos falta
un detalle importante
que es
meterlo en el DOM
entonces
en la lista de mensajes
que lo hemos recuperado
aquí
¿ves?
este message
que es ul
que es la lista desordenada
que hemos creado
tenemos que hacer
un append child
y este nuevo mensaje
lo vamos a añadir
al html
que tendríamos
entonces
en este huele
se va a añadir
el elemento
li
que estamos creando
y para terminar
vamos a devolver
bueno
no vamos a devolver nada
vamos a hacer esto
aquí
add message
add message
vamos a poner aquí
el mensaje
sería el message text
y esto sería el user
y con todo esto
que hemos hecho
se supone
¿vale?
fíjate
hola
vale
ya estamos aquí
añadiendo cositas
pero fijaos
que voy escribiendo
y no hace
hay que hacer el scroll manualmente
bueno
no pasa nada
para situar esto correctamente
lo que podemos hacer
es
mirar donde tenemos el overflow
o sea
donde tenemos el scroll
el scroll
lo he puesto por aquí
el overflow
en el main
¿vale?
veis que aquí en el main
he puesto overflow
y auto
el auto significa
que va a enseñar el scroll
la barra de dirección
si necesitas
el contenido no cabe
y por lo tanto
el usuario
tiene que hacer scroll
para llegar a él
entonces está oculto
y solo puedes llegar a él
haciendo scroll
pues como es el main
aquí hemos recuperado el main
en el container
¿veis?
aquí hemos recuperado el elemento main
pues este container
lo que vamos a hacer aquí
en el container
appendChain lo vamos a hacer
vamos a decirle
que el scroll top
sea igual
al container
punto scroll height
lo que estamos diciéndole es
oye
quiero que me sitúes
la posición del scroll
¿vale?
el scroll vertical
por eso es el scroll top
¿vale?
quiero que me lo sitúes
a la altura
que tiene el scroll total
¿vale?
el scroll height
lo que hace es
es una propiedad
que te dice
el scroll total
que tiene una ventana
no confundir con la altura
una cosa es el
client height
que esto sería
la altura
que tiene la caja
visible
pero si tú lo que quieres saber
es lo que ocupa
todo el scroll
incluso lo que no se ve
tendríamos que hacer
el scroll height
¿vale?
y con esto
ahora
si escribo
no lo hace
no lo hace
ah sí
sí que lo ha hecho
pero tarde
ah
porque lo he puesto al revés
¿vale?
primero tendríamos que poner esto
y luego actualizar el scroll
ahora sí
vale
bien
vamos
vale
¿veis?
ahora se está moviendo constantemente
para mejorar un poco esto
una cosa que podéis hacer
esto es opcional totalmente
podéis cambiar aquí
el scroll behavior
y le ponéis smooth
y esto va a crear
una pequeña animación
que va a hacer que sea un poquito más
más sutil
¿no?
entonces ahora
ahora cuando escribas
¿vale?
ves que hace
una animación
y queda
súper bien
con una línea
de CSS
y queda súper natural
¿vale?
así que vale
ahí lo tenemos
ahora que ya tenemos todo esto
nos faltaría simular
un poco la respuesta
vamos con
está bien porque mira
justo ahora
una hora
y vamos ya
con la parte
más interesante
del stream
yo creo
porque todo esto
al final
seguro que lo podías haber hecho
aquí
una cosa podríamos hacer
es que
vamos a poner
vamos a desactivar
por ahora el botón
cuando le dé
y voy a simular
y esto es lo que vamos a hacer ahora
el utilizar la inteligencia artificial
vamos a simular aquí
la respuesta
un poco del
de la inteligencia artificial
y para eso
vamos a poner
add message
hola como estás
como si fuese el bot
entonces se supone que
yo escribo aquí
¿vale?
no sé por qué
no me
ah
pensaba que no me había desactivado
el botón
pero es porque esto
no le hemos puesto aquí
un disabled
disabled
¿vale?
vamos a poner aquí
al disabled
esto es para que
si tienes el atributo
disabled
vamos a ponerle
opacidad
0.6
algo así
y ahora
a ver
ahora
vale ¿veis?
ahora sí
y al rato
¿ves?
me contesta
esto lo estoy simulando
pero bueno
al menos para que podamos ver aquí
¿vale?
hola como estás
y tal
y encima aquí el hover
tendríamos que poner
background
tendríamos que ponerle
exactamente el mismo background
ah no
claro
es que
hover tendría que ser exactamente
el mismo este
¿vale?
a ver
para que no me haga
o ponerle un pointer events
none
y ya está
pointer events none
y ya nos olvidamos de todo esto
vale
ya está
vale
y entonces te responde
chagpt y tal
ahora lo interesante
porque obviamente
no vamos a hacer esto
de que lo simule chagpt
lo que vamos a hacer
es tener un chagpt de verdad
¿ok?
¿cómo vamos a hacer esto?
venga
paso a paso
primero
vamos a ver la librería
que vamos a cargar
vamos a cargar una biblioteca
que se llama
web LLM
que es una biblioteca
de alto rendimiento
que te permite
utilizar modelos
directamente
en tu navegador
¿esto qué quiere decir?
pues que hay
modelos de inteligencia artificial
que sin necesidad
de utilizar un backend
sin necesidad de tener
ningún tipo de llamada
a una API externa
todo de forma local
privada
gratuita
desde tu navegador
vas a poder utilizar
algunos modelos
además
tiene cosas muy interesantes
primero
el rendimiento es buenísimo
porque utiliza
web GPU
que luego te explicaré
un poquito más
de esta tecnología
pero ves
lo pone aquí
web GPU
para aceleración por hardware
esto quiere decir
que va a utilizar
tu tarjeta gráfica
¿vale?
va a utilizar tu tarjeta gráfica
para todo el tema
de inteligencia artificial
y esto
si tienes un ordenador
bueno
vas a ver
que va muy rápido
pero muy rápido
es espectacularmente rápido
luego
lo segundo
lo segundo
es que
la API
que vamos a estar utilizando
o sea
no la API
sino que
el contrato
es totalmente compatible
con el contrato
de OpenAI
esto no quiere decir
que vamos a utilizar
la API externa
externa de OpenAI
nada de eso
lo que quiere decir
es que el código
que vas a ver
te lo vas a poder llevar
muy fácil
si quieres
si quisieras
si lo necesitases
a OpenAI
porque sería exactamente igual
y lo vas a ver
si has hecho algo
¿vale?
luego
tenemos más de un modelo
¿vale?
más de un modelo disponible
tenemos una lista entera
para cositas que podemos utilizar
tenemos la posibilidad
de crear nuestros propios modelos
si queremos
tenemos una
una integración
facilísima
que no hace falta
ni utilizar
NPM
lo vais a ver ahora
y también
podemos tener respuestas
en streaming
y en tiempo real
lo cual es espectacular
y lo mejor de todo
soporte a WebWorkers
y ServiceWorkers
también
que no lo vamos a ver hoy
lo de ServiceWorkers
vamos a ver lo de WebWorkers
porque me parece muy interesante
la parte de WebWorkers
y lo mejor
para terminar
es que también tienes soporte
para extensiones de Chrome
o sea
lo que vamos a ver hoy
te lo podrías llevar
a una extensión de Chrome
si quisieras
y utilizarlo
sin ningún tipo de problema
¿sirve para Apple Silicon?

porque yo lo tengo
¿utiliza WebAssembly?
no
no utiliza WebAssembly
utiliza WebGPU
¿vale?
que es todavía más interesante
para este caso
y funciona
en todos los sitios
lo único malo que puede tener
es que no te funcione bien
en rendimiento
pero funciona
aquí tenemos algunos
de los modelos
que tenemos disponibles
de Llama
tenemos Llama 3
Llama 2
Hermes
tal
Fi
que es el modelo
de inteligencia artificial
de código abierto
de Microsoft
Fi 3
Fi 2
1.5
Gemma
que es el de Google
tenemos Mistral
y tenemos también uno chino
que se llama Cuen
la lista correcta
la tenemos aquí
¿vale?
la lista correcta
digo porque es que hay
un montón de modelos
muy específicos
según la cantidad
de datos
que se han utilizado
para entrenarlo
el contexto
el número
el contexto
que queremos que tenga
tanto de output
como de input
¿veis?
aquí tenemos
Context Windows Size
1024
obviamente
aunque muchos
hay algunos de estos modelos
que son tan potentes
como ChatGPT
dice
no tiene los de OpenAI
bueno
no tiene los de OpenAI
porque obviamente
OpenAI
se llama Open
pero no tiene ningún modelo
que sea Open
no hay ninguno de código abierto
en cambio
todos estos
sí que son todos
de código abierto
y de nuevo
todos estos
son privados
o sea
lo vas a utilizar
en local
¿se puede utilizar comercialmente?
que yo sepa

que yo sepa
sí que se puede utilizar
comercialmente
todo se puede utilizar
comercialmente
vale
vamos con esto
creo que los de Yama
tienen alguna cosa
que tengo dudas
que según la empresa
lo puedas utilizar
comercialmente
¿cómo lo vamos a utilizar?
¿vale?
¿cómo vamos a utilizar
esta biblioteca?
lo primero
es cargar la biblioteca
en nuestro proyecto
lo interesante
que tenemos
es que estamos
utilizando módulos
fíjate que aquí
en el script
he puesto que sea
de tipo módulo
y ahora vas a ver
lo mejor
que tiene
los Enmascript Modules
los módulos
de JavaScript
que muchas veces
se nos olvida
porque como utilizamos
bit
utilizamos tal
fijaos que aquí pone
package manager
y pone npm install
no sé qué
pero ¿sabes qué?
que no necesitamos
nada de esto
podemos utilizar
directamente
esta URL
y traernos
el paquete
podemos hacer aquí
un import
directamente
de esto
y de aquí
lo que vamos a querer
traernos
es algo en concreto
vamos a poder traernos
create
mlc
engine
¿vale?
y con esto
vamos a poder
traer este método
de esta URL
no estamos utilizando
ningún empaquetador
ningún framework
nada
esto es vanilla
html
y javascript
¿vale?
luego le vamos a indicar
aquí cuál es el
selected model
voy a utilizar un modelo
que es bastante
podríamos utilizar
de gema
a ver
os voy a explicar
un poco los modelos
los que hay
aquí tenéis la lista
veis aquí que dice
la lista
puedes acceder aquí
le dais aquí
y aquí tenéis la lista
de modelos
veis que pone
model
model ID
tenéis que utilizar
el model ID
en el model ID
tenéis un montón
pero ojo cuidado con esto
porque hay unos
que utilizan más recursos
y otros
pues hay de menos
y de más
pero dependiendo
de eso
pues también
obviamente
vais a necesitar
más memoria RAM
en el caso de llama
que suele ser
el que mejor funciona
este necesita
5.000
o sea 5 GB
pero por ejemplo
los de FI
son bastante chiquititos
¿ves?
FI 3 mini
este es de 3,5
pero hay incluso
alguno que
ves 2,5 GB
hay alguno
que incluso
llega a ser
bastante pequeño
el de GEMA
también creo que
es bastante pequeñito
entonces podéis mirar
porque dependiendo
de lo que queráis hacer
voy a ver
cuál es el más pequeñito
este es 1,5 GB
GEMA
es bastante pequeño
lo malo que es
pues que aquí hay que ver
el que mejor te funcione
en tu caso
y en el que
o sea
que funcione bien
pero que no consuma
la información
o sea
que consuma los recursos
de forma innecesaria
entonces
este sería uno
muy pequeño
que funciona
porque tiene muy pocos recursos
pero por otro lado
a lo mejor las respuestas
no son tan buenas
¿no?
entonces
vamos a hacer este
vamos a añadir este mismo
por probarlo
a ver cómo responde
o bueno
vamos a poner este
este que es un poquito mejor
y ya está
entonces aquí en Selected Model
vamos a utilizar el de GEMA
y tal
ahora vamos a crear
el motor
¿vale?
Consengin
y aquí le decimos
esto tiene que ser
asíncrono
así que tenemos que esperar
Create MLC Engine
y le decimos
que utilice
el modelo que hemos seleccionado
y aquí le podemos pasar
un montón de configuración
temperatura
lo típico de los modelos
si queremos que sea
más original
más creativo
bueno
esto se lo podemos poner aquí
por eso
no lo vamos a ver hoy
pero sí que hay uno
que es muy interesante
que es Limit Progress Callback
donde te va a estar informando
constantemente
cómo va la carga
de este modelo
porque estos modelos
se los va a descargar
de internet
los va a guardar
de forma local
en el navegador
o sea
no en el navegador
del usuario
pero digamos que
en el ordenador
del usuario
¿vale?
lo va a almacenar
de forma local
no lo tiene que guardar
en un servidor ni nada
no
sino que cada usuario
de forma local
lo tendrá guardado
¿vale?
aquí voy a poner un console log
solo para que veamos
ahí la información
y para que esto
lo veamos bien
ahora lo voy a probar
para que lo veamos
a ver si lo he hecho bien
vámonos aquí
vale
fijaos
como ya está cargando
veis aquí
que tiene un tanto por ciento
está cargando el modelo
¿vale?
aquí teníamos el callback
¿vale?
aquí no sé
que se ha quejado
de alguna cosa
this is only a 4G
using default
vale
esto no sé
qué problema tiene con esto
me parece gaso a lo interno
pero vale
¿qué ha pasado aquí?
aquí lo que ha pasado
es que ha empezado
a descargar los parámetros
ha estado descargando
todo el modelo
de forma local
te está poniendo aquí
como el progreso
con un tanto por ciento
para que tú vayas viendo
finalmente
ha llegado un momento
que ha terminado
carga el modelo
desde la caché
¿vale?
1,3 gigas
que ocupa este modelo
que lo está descargando local
no está en ningún servidor
ni nada
ahora lo tengo local
y esto
una vez que llega aquí
ya lo tenemos
dispuesto para utilizar
fijaos que aquí dice
he terminado de cargarlo
en el web GPU
¿vale?
y me ha detectado
la GPU
que es la de Apple
ahora
la web GPU
¿qué es esto de web GPU?
web GPU
es una nueva API
que tiene los navegadores
que lo que permite
es acceder a toda la potencia
de tu tarjeta gráfica
desde
el navegador
lo cual es
impresionante
porque hasta hace poco
sí que teníamos
web GL
que no estaba mal
pero no funcionaba
al cien por cien
esta nueva API
es mucho más potente
y te permite hacer cosas
mucho más avanzadas
y en este caso
imagínate esto
que nos va a permitir
utilizar un modelo
de forma totalmente local
alguien preguntaba
¿se puede utilizar
sin internet?

se podría utilizar
sin ningún tipo de internet
sin internet
podrías utilizar esto
siempre y cuando
ya tuvieses el modelo
descargado
claro
porque el modelo
necesita descargarlo
entonces
para saber si tu navegador
o si tu ordenador
tiene soporte
una cosa que podéis hacer
es utilizar
la API
que es
navigator
punto
GPU
¿vale?
si hacéis esto
deberíais ver
que os aparece algo
esto debería
si no os aparece algo
significa
que vuestro navegador
no tiene soporte
por ejemplo
Safari
Safari
si vosotros vais aquí
y buscáis
en el
inspeccionar elemento
y os vais a la consola
y ponéis
navigator.gpu
undefined
entonces no tiene soporte
si vais al navegador
que navigator.gpu
es undefined
tenéis que actualizar
normalmente
a día de hoy
tiene soporte
en Chrome
y en Edge
y en Safari
creo que hay
no
en Firefox
en Safari no
en Firefox
hay soporte
pero está todavía
debajo de un flag
pero lo van a añadir
o sea que poco a poco
no os preocupéis
que va a llegar a todos sitios
luego si hacéis
navigator.gpu
punto
get devices
creo que era
ah no me acuerdo
devices
no
navigator.gpu
ah no me acuerdo
no me acuerdo
como es
pero
se puede llegar a saber
get devices
a ver si encuentro
GPO property
request device
request device
hola midu
que tal
tal vez la pregunta
pueda ser redudante
pero entonces
lo puedo entrenar
con diferentes documentaciones
actualizadas
a la fecha actual
como next
15
larabel 11
nuxt 3.9
etc
le vas a poder
embeder cualquier documentación
de hecho eso
se puede hacer
con cualquier modelo
así que sí
una vez
de hecho lo pone
en la documentación
aquí
veréis que se le pueden
se le puedan ir
un montón de cosas
y tal
y lo podéis llevar
mucho más allá
o sea no hacer
las típicas preguntas
sino que le podéis utilizar
con vectores
y eso
y eso lo podríais hacer
sin ningún problema
no me acuerdo
como es
pero se puede
navigator.gpu
get devices
no me acuerdo
como se puede
pero
ah no me acuerdo
ah request adapter
mira
o request device
ahí está
request device
este sería el tema
este sería el tema
este sería
y con eso
deberíais tener
la información
de vuestro
gpu
vale
de vuestra gpu
en el caso
de que
veis
device
pues aquí tendríamos
toda la información
la feature
los límites que tiene
veis aquí tendrías
toda la máxima memoria
que puede tener
está bastante bien
porque ahí tenéis
toda la información
si no os aparece
esto
si os da algún problema
significará
que no tenéis soporte
vale
para que simplemente
lo sepáis
y que no os asustéis
pero bueno
ya sea por vuestro navegador
pues lo actualizáis
y si no
pues ya está
si tienes una gpu
no tan potente
puedes cargar parte
del modelo de la gpu
y la rama
al menos es así
con otras herramientas
lo que puede ser
es que os funcione
mucho peor
o sea no hace falta
que tengáis una mega gpu
sino que simplemente
a veces os funcionará
peor y ya está
bueno
entonces ya veis
que ahora nada más entrar
ya tenemos la información
de cómo se está cargando
como quiero que esta información
no quiero entrar
todo el rato
en la consola
para tener que ver
esto del progress callback
y todo esto
voy a hacer una pequeña cosa
si os parece
vale
voy a meter un small
aquí debajo
debajo de todo
aquí
vamos a poner un small
le voy a poner un espacio vacío
para que no me haga un salto
cuando se ponga la información
y aquí
en los estilos
vamos a poner este small
aquí
lo estilo un momento
vale
y así que aparezca ahí
toda esa información
de cómo se está cargando
ponemos aquí un font size
bastante pequeño
un color
un gris
position fix
el bottom
cero
left cero
right cero
margin auto
bueno
esto vamos a poner
que está un poco más separado
y yo creo que con esto
ya está
bueno
vamos a ponerle una separación máxima
así
un ancho máximo
y así
este callback
que habíamos hecho aquí
con el info
vamos a poner
que en el small
vamos a poner
tu tu tu tu tu tu
vale
esto
que lo habíamos hecho aquí
vamos a hacerlo más abajo
una vez que hemos recuperado
los elementos
y así utilizaremos
el elemento
que acabo de crear
para ir mostrando
la información
vale
entonces aquí este small
vale
vamos a poner aquí
que en info
text content
más que progress
que el progress
no me interesa tanto
a ver
cómo
cómo se crea esto
creo que sale al rato
y ahora veréis por qué
vale
text
vale el text
vamos a mostrar el text
directamente
vale
y ahora sí
deberíamos
tu tu tu
vale
veis aquí
no sé si se ve
pero ahora aquí abajo
tengo la información
y así pues perfecto
tengo ahí la información
y al menos
lo podemos ver rápidamente
sin necesidad de entrar
en la consola
y todo esto
ya tenemos
todo lo que sería
el callback
ya tenemos todo esto
no está mal
otra cosa que podemos hacer
es deshabilitar
el botón
para que no nos envíen
preguntas
hasta que no lo tengamos
entonces vamos a mirar
que en la información
fijaos
bueno
ahora porque lo he roto
pero teníamos el progress
que si el progress
llega a uno
significa
que ya
podemos tener
ya tenemos el engine
lo tenemos preparado
entonces vamos a hacer esto
vamos a remove attribute disable
y vamos a hacer que el botón
por defecto
esté desactivado
vale
entonces vamos a la html
vamos a poner aquí
el botón disable
y así
mientras se está cargando
al principio
a ver si
vale
pues que aparezca así
en enviar
y cuando empiece a cargar
y termine de cargar
pues ya
se active
el botón
vale
al menos ya teníamos esto
y ahora vamos a utilizar
por fin
para que nos dé
respuestas
nuestra inteligencia artificial
esto que habíamos puesto aquí
de un timeout
y todo esto
vamos a hacer algo
vamos a tener
vamos a tener aquí un
messages
let messages
que va a ser un array
vale
y aquí
vamos
en lugar del timeout
vamos a
a preguntarle
a nuestro modelo
sobre lo que sea
no
vamos a tener aquí
la reply
que va a ser la contestación
de nuestro modelo
y hacemos
await
porque esto es asíncrono
le decimos que al engine
del chat
queremos crear
completions
esto es exactamente igual
a la API de OpenAI
vale
pero no estamos utilizando OpenAI
y aquí le utilizamos
con el create
le pasamos los mensajes
que en este caso
los mensajes que tenemos
ahora mismo están vacíos
pero bueno
ahora veremos
ahora lo arreglaremos
esto un poco
aquí se me queja
que el await
no está disponible
porque no es una función asíncrona
así que tenemos que poner
que esto es async
vale
y ahora que tenemos aquí el reply
tenemos que ver
que nos devuelve
el reply
entonces
en messages
claro
le tengo que pasar algo
aunque sea lo mínimo
por ahora voy a pasarle
todos los mensajes
que ya tenía
que son los que hemos guardado aquí
aquí
¿veis este messages?
vale
se lo vamos a pasar
y además
vamos a añadir uno más
donde el usuario
le va a pasar de contenido
el message text
vale
y ahora sí
si volvemos aquí
vale
empieza a cargar
esto lo tiene que cargar
de la caché
siempre que refresca
ahora ya estaría disponible
y le decimos
¿cuál es la capital de Francia?
le damos al enter
vale
y me ha dado la respuesta
no la estoy mostrando
pero fijaos
que me ha dado aquí
una respuesta
me ha dicho
choices
0
finish reason
el message
content
la capital de Francia
es París
vale
me ha estado dando
más información
vamos a tener que recuperar
esa respuesta
ya vamos a ver
un poco como entra
estaría en reply
choices
0
punto
message
así que
esta información
es la que vamos a querer
con un send message
vamos a poner
este
es que ha puesto
punto content
y ahora tengo dudas
si el content
iba o no iba
vale
vamos a decir
que send message
del bot
ah no
send message no
add message
vale
esto
vamos a poner
bot message
lo recuperamos así
para que se entienda mejor
lo ponemos aquí
le decimos que eso
lo escribe el bot
y volvemos aquí
vale
y ahora vamos a ver
si va
si va el content
vale vale
pues ahora
ahora lo arreglo
vale
vamos a ver
entonces
volvemos
cual es
cual es
la capital
de Francia
le damos al enter
y
vale
me he equivocado
porque si que iba el content
vale
porque
ay
encima lo he escrito mal
lo he escrito mal
lo he escrito mal
lo he escrito mal
lo he escrito mal
repli.choice0message
vale
igualmente
voy a intentar asegurarme
cual es la capital
de Francia
así mientras escribo
vale
vale
object object
o sea que si que va el content
perfecto
si que va el content
veis que está aquí
content
lo interesante
es que
aquí si quería el content
pero
aquí tenemos que hacer
message.push
bot message
vale
porque este mensaje
este mensaje
que me estaba devolviendo
lo tenemos que
lo tenemos que guardar
en la lista
vale
entonces
también antes
de enviarle el mensaje
este
este mensaje
que estamos enviando aquí
también lo tenemos que guardar
o sea que vamos a hacer
user message
vamos a crear aquí
con el rol
user
content message text
messages.push
user message
vale
esto lo guardamos
y así no necesitamos
hacer esto
y ya podríamos hacer
que este message
sea exactamente
el mismo que le estamos enviando
vale
esto por aquí
esto por aquí
esto por acá
o sea ya estamos
básicamente aquí
guardamos
en la lista de mensajes
el del usuario
y una vez que tenemos aquí
la respuesta
lo también lo guardamos
el del bot
y aquí el que tenemos
que mostrar
en el html
es el contenido
del mensaje
vale
vamos a probar ahora
vale
cuál es la capital
de Francia
ahora veréis
porque hay un problema
de rendimiento
que no os estáis dando cuenta
pero bastante grave
y lo vamos a arreglar
con web workers
vale
cuál es la capital
de Francia
vale
la capital de Francia
es París
es la ciudad
más grande del país
con estatus político
económico
cultural y político
importante
ya tenemos
ya tenemos aquí
no sé
resuelve
bueno
cuál es la potencia
de 22
de 3
yo que sé
ah espérate
porque fijaos
que no he desactivado
no he vuelto a activar
el botón
aquí
que hemos hecho
el button
vale
aquí he puesto esto
que esto no es necesario
como tal
vale
tenemos que volver a activarlo
una vez que tenemos
el mensaje del
del bot
así que esto
vamos a hacer un remove
attribute
disable
vale
estas respuestas
que habíamos hecho
al principio
no las necesitamos
o sea que esto
lo podemos eliminar
del html
para que quede
mucho más limpio
esto lo había puesto
más que nada
para empezar
a revisar
y tal
entonces ahora
ya podría quedar así
directamente
pero hay un problema
de rendimiento
hay dos problemas
de rendimiento
uno
cuando nada más entrar
fijaos que nada más entrar
si yo intento darle click
aquí
fijaos que se queda penchado
esto
no sé si lo habéis visto
pero se queda
se queda como
congelada la página
la página se queda congelada
no responde
estoy dando click
no responde
y hasta que no pasa un rato
no empieza a responder
y esto
lo podemos ver
muy claramente
si utilizamos
esta herramienta
de performance
fijaos que
si recargamos la página
y que ahora
no funciona
hasta que no pasa
un rato
no funciona
este profiling
nos va a decir
que
mirad
mirad esta parte
de aquí
run microtash
durante 1,5 segundos
la página
se ha quedado
congelada
congelada
porque
fijaos
esto amarillo
que veis aquí
esto sería
javascript
¿vale?
javascript puro
que
ha bloqueado
el thread principal
de la página
y no ha permitido
que hiciéramos
absolutamente nada
y por eso
la página
ni siquiera responde
no puedo escribir
no puedo hacer nada
esto lo vamos a arreglar
después
¿vale?
y de hecho
lo podríamos ver
no sé si se pueden
aquí
screenshots
aquí con las screenshots
lo podemos ver
mucho más claro
pero fijaos
que yo le doy click
le doy click
no funciona
y es por culpa
de este
este run microtash
todo lo que veis aquí
esto al final
es javascript
que está ejecutando
nuestro modelo
y que está bloqueando
la página
pero por suerte
todo este trabajo
lo vamos a poder hacer
en otro thread
diferente al principal
para que nuestra página
sea totalmente
mucho mejor de rendimiento
tenga mejor experiencia
de usuario
y responda a los clicks
que es lo que queremos
lo vamos a hacer después
pero antes
tenemos otro problema
y es que fijaos
que si yo le digo
¿sabes qué es el principito?
¿vale?
¿sabes qué es el principito?
no tengo la capacidad
de saber qué es el principito
no tengo una conciencia
o percepción
pero conoces
pero conoces
el cuento
de el principito
tampoco
igual es un poco tonto
¿qué te gustaría saber?
cuéntame
cuéntame
la historia
a ver si
tiene un poco de contexto
de lo que le acabo de decir
vale
ya podéis ver
que tarda bastante
en responder
¿no?
estamos viendo
que
tarda en responder
en darme la respuesta
la historia del principito
es un cuento infantil
de escribir el viaje
¿qué te gusta
de esta historia en particular?
me gusta
me gusta
que se parece
un poco
a un chico
que se llama
Midudep
va a flipar
la prueba
de ingeniería artificial
¿eh?
en realidad
el principito
es un cuento infantil
que se refiere
a una criatura
folilar
¿folilar?
¿qué es folilar?
el principito
es un personaje divertido
ingenuo
que aprende cosas nuevas
y tal
pues como
Midudep
pues como
Midudep
es un personaje divertido
ingenuo
espero que pueda
volver a encontrarlo
en el bosque
yo también
yo también
vale
está flipando
entonces

dice
Nico Sub
dice que
Gema
y el resto
de modelos pequeños
son medio tontos
luego veremos
que hay otros modelos
un poquito más grandes
que son mejores
¿vale?
que son bastante mejores
pero
una cosa que hemos visto
es que
fíjate que
si le digo
cuéntame la historia
del principito
se queda como
unos cuantos segundos
ahí como pensando
y el problema
es que
lo que estamos haciendo aquí
es que
esperamos
a que haga
toda la respuesta
fíjate
aquí
aquí
¿vale?
aquí lo que estamos esperando
es
oye
espera
toda la respuesta
y entonces
dibujo la respuesta
y esto
como ya sabéis
esto es un error
común
que no se comete
en chatGPT
y como queremos
que lo nuestro
sea tan genial
como chatGPT
lo que vamos a hacer
es cambiar un poco esto
con una forma muy sencilla
vamos a añadir
otro
parámetro
que se llama
stream
y el stream
lo que va a hacer es
mientras va generando
la respuesta
lo va a ir devolviendo
va a ir devolviendo
la respuesta
mientras la va pensando
y nosotros vamos a ir
dibujando
la respuesta
entonces en lugar de tener aquí
el reply
como la respuesta
lo que vamos a tener aquí
en realidad
son los chunks
los chunks serían
las partes
de la respuesta
y vamos a tener que crear
una variable
que se llama reply
donde vamos a ir guardando
y generando
la respuesta
correcta
completa
a partir de esos trocitos
que nos va dando
y como vamos a ir generando
esos trocitos
bueno pues nosotros vamos a esperar
que nos vaya dando los trocitos
y por lo tanto
esto va a ser asíncrono
tenemos que hacer un for await
donde vamos a esperar
cada uno de esos trocitos
de la respuesta
y cuando los tengamos
vamos a decir
vale
pues ya tendríamos aquí
cada uno de los trocitos
y vamos a ver
como nos llegan
vale
voy a hacer un console log
del chunk choices
aquí por ahora
voy a
voy a poner esto
más que nada
para que veamos esto
vale
porque esto no va a funcionar
esto tampoco funcionará
vale
por ahora voy a hacer
un console log
para ver como se va devolviendo
la respuesta
vamos a ver ahora
como funciona
explícame
el cuento
de el principito
vamos a abrir
la herramienta
vamos a darle a enviar
vale
fijaos como me está devolviendo
la respuesta
trozo a trozo
y que rápido ha sido
fijaos que le he dado
al enter
y ya me está dando
constantemente
me está dando
un montón de
de letras
el cuento
o sea
la experiencia de usuario
es otra cosa
vamos a ver
como funcionaría
está aquí
como en el array
delta
y content
vale
pues tendríamos
que ir recuperando
en choices
tendríamos aquí
voy a ir recuperarlo
paso a paso
vale
aquí tenemos
choice
y chunk
punto choices
aquí esto sería lo mismo
que hacer esto
choice
chunk choices
es lo mismo
vale
la línea de arriba
es igual a la de abajo
pero esto lo que está haciendo
es una desestructuración
de forma que
recupero el primer elemento
y lo meto
en la variable
choice
bueno
en esta casa
una constante
yo personalmente
muchas veces me gusta más
trabajar así
de izquierda a derecha
que no de derecha a izquierda
o sea
no me gusta
normalmente poner
el cero
como que me parece
un poco más feo
pero no pasa nada
o sea
lo podéis utilizar
esto soy yo
utilizando esto
pero si os gusta más este
utilizad este
el que os dé la gana
luego teníamos el contenido
que era
choice
punto delta
punto content
y vamos a poner
pues un
contenido por defecto
en el caso de que sea
null o undefined
vamos a poner una cadena de texto
por vacía
estamos utilizando
el nullish
collection operator
porque solo en el caso
que este choice delta content
de hecho aquí vamos a poner
el optional chaining
vale
vamos a poner
el optional chaining
en el caso
que algo de aquí
de la izquierda
sea null o undefined
entonces le podemos
la cadena de texto
por vacía
pero si content
ya es una cadena de texto
vacía
pues la dejamos
vale
no tiene mucho sentido
que hagamos más
más de eso
y mientras
vamos a ir
acumulando
ese contenido
que nos estaba devolviendo
en la variable reply
y este reply
es donde vamos a
este
new message
vale
tenemos que ir
grabando en el html
y como vamos a hacer esto
pues
veis que aquí
estamos haciendo
un add message
no se que no se cuanto
esto
lo vamos a hacer ahora
desde el principio
vale
vamos a escribir aquí
el contenido
pero vamos a escribir
el contenido
vacío realmente
o sea porque al principio
no tenemos nada
así que primero
vamos a hacer un add message
con una cadena de texto vacía
y le vamos a decir
que ahí va a empezar
a escribir el bot
y en esta
esta función
de add message
aquí
ahora no estábamos
devolviendo nada
pero una cosa
que podemos hacer
es devolver
el text
vale
el text
es el elemento
del párrafo
es donde estábamos
escribiendo la respuesta
que antes la estábamos
escribiendo
cuando teníamos
la respuesta completa
pero ahora
lo que vamos a hacer
es que vamos a devolver
el elemento
y así aquí
aquí dentro
vamos a poder
guardar
el
bot
text
bot text
vale
o bot
message
bueno
bot text
vale
bot text
voy a poner message
es que como
como pone aquí
add message
voy a ponerle message
y aquí
este elemento
del DOM
lo vamos a poder
actualizar aquí
vale
bot message
punto text content
y le vamos poniendo
el content
ahora
no vale mucho
la pena
aquí alguien podría decir
pues podríamos hacer esto
y aquí ir acumulando
el reply
no vale mucho la pena
la verdad
porque el text content
es lo suficientemente rápido
y nosotros visualmente
no vamos a anotar nada
y
pero bueno
lo podéis probar
si queréis
por un tema de rendimiento
aunque yo creo que no va a haber
ningún problema
aquí
entonces ya tenemos
el bot message
text content
le ponemos el content
ahí lo vamos actualizando
quitaríamos
una vez que termina
ya el botón
lo desactivamos
y lo que sí que es importante
que no se nos olvide
es que
tenemos que
pushear
este mensaje
lo que pasa es que ahora
tenemos que crear nosotros
tenemos que poner
role
assistant
y el mensaje
no sé si es mensaje
o content
lo que va devolviendo aquí
creo que es content
porque a mí me está diciendo content
ahora no me acuerdo
si es message o content
vamos a poner que es content
y vamos a poner aquí
reply
vale
vamos a ponerle reply
en el content
el reply es porque tiene
toda la respuesta
de nuestra inteligencia artificial
y con esto
ahora
si
ponemos aquí
vale
y le digo
cuéntame
el cuento
del
principito
vale
error
error
pero va bastante rápido
al menos vemos que va bastante rápido
esto es porque la he liado
en alguna cosa
porque he puesto aquí content
y aquí quería decir reply
vale
justo os he dicho eso
vale
ahora sí
ahora sí
mira
tiene el error ese
cuéntame
el cuento
del
principito
fijaos la diferencia
lo rápido
que es
o sea
fijaos
lo rápido
que responde
una vez que está cargado
el modelo
de forma local
totalmente
fijaos
lo rápido
que ha sido
o sea
es impresionante
que
personajes
salen
o sea
es impresionante
lo rápido
que va
un oso oso
me encanta
un oso oso
una araña
una mariposa
oso oso
chaco
no es muy listo
no es muy listo
de hecho
seguramente lo que podemos hacer
es probar
otro modelo
este modelo
que estamos utilizando
creo que era el de Gema
voy a decir algo
un poco polémico
pero
el modelo de Gema
suele ser el peor
el de Gema
es el de Google
y
aún siendo uno de los primeros
que han hecho
no suele funcionar muy bien
pero
el mejor
suele ser Yama
Yama es el mejor
el que mejor responde
pero suele ser el más grande
y
Fee
sería el intermedio
entonces
lo malo de Yama
pues claro
Yama
vais a ver que
funciona bastante bien
pero
ocupa más
va a tardar más en cargar
va a necesitar más
más
más tiempo
necesitará más
más
más memoria
también
todo
ahora se lo tiene que descargar
fijaos que ahora
primero lo descarga
lo primero que hace es descargarlo
y luego lo guarda en local
entonces lo vamos a dejar aquí un momento
mientras
pero veis
este
este es bastante más grande
pero este funciona
muy bien
este funciona
súper bien
ahora cuando veréis un poco
la respuesta lo vais a ver
que funcionan bastante bien
el único problema
es eso
que deben ser unos 5 gigas
más o menos
tarda un rato
pero una vez que ya lo ha descargado
y al final aquí
le podéis decir al usuario
esto tiene que cargar
y le podéis mostrar la carga
y todo esto
no habría ningún tipo de problema
¿de dónde se descarga esta información?
esta información
estos modelos
lo está guardando
no se puede guardar en caché
o algo para que cuando refresque
no descargue de nuevo
es que no lo descarga de nuevo
lo guarda en caché
de hecho ahora lo vais a ver
¿veis?
ahora lo está
como podéis ver
ahora lo está descargando
luego lo que hace
es que lo
lo tiene en la caché
y tiene que inicializarlo
pero eso todavía
tarda unos segundos
porque pensad que es un modelo
que tiene gigas
son gigas
entonces puede tardar unos segundos
la primera vez
puede tardarte un minuto
en descargar el modelo
porque son 5 gigas
son 4 o 5 gigas
es bastante bestia
pero una vez que lo tiene
ya lo tiene cacheado
y no lo vuelve a descargar
ahora ya veréis
por ejemplo
cómo lo hace
o sea fijaos que ahora
mira son casi 5 gigas
no llega
4 gigas y algo
pero veis
este es mucho más potente
ahora es que carga el modelo
desde la caché
y esto es mucho mucho más rápido
estos son unos pocos segundos
pero veis que esto
al final
lo ha dejado
lo ha descargado
ahora lo carga
y ahora ya lo podríamos utilizar
esto habría que enseñarle al usuario
aquí sí que tiene sentido
enseñarle una carga
y darle la información
y ahora vamos a decir
explícame
el principito
el cuento
el cuento
del principito
¿vale?
y a ver qué
el principito
es un libro de aventuras
de reflexión
escrito
¿ves?
este es mucho mejor
que el otro
como podéis ver
la respuesta que está dando
es mucho mejor
está como
mejor explicado
y todo
así que ahí tenéis
el principito
es un joven príncipe
no sé cuánto
y seguramente
pues va a poder tener
la posibilidad
también de
principitos de la cuenta
joder
está dándole bastante caña
bastante caña
¿cuál es el mejor
cuál es el mejor
personaje
del principito?
vamos a ver
¿cuál es el mejor personaje
del principito?
hostia hostia
que sigue
que sigue
que sigue
no sé
no veas
no veas
¿tienes alguna pregunta?
¿cuál es el mejor personaje?
cada personaje
tiene su propio carácter
pero veáis
este
este de llama
es más parecido a HGPT
de hecho
según las pruebas
es muy parecido a HGPT
en cuanto a calidad
para que lo sepáis
ahí lo tenéis
ahora
veo que hay una cosita
que me da un poco de rabia
que es que cuando se pone a escribir
fijaos que
luego
no
hay que volver a bajarlo
¿no?
entonces
esto que hemos hecho aquí
también lo podríamos hacer
para que cuando termine
vuelva abajo
¿vale?
para poder tener esa información
pero mira
ahora
por ejemplo
lo está
lo está pillando de la caché
y esto tarda un poquito
pero fijaos que
mientras
cuando empieza
no responde la página
tiene un problema ahí
de la página
que no responde
entonces
vamos a utilizar
una cosa
que son los
web workers
¿vale?
los web workers
en javascript
durante mucho tiempo
y sigue siendo verdad
javascript es
mono hilo
esto quiere decir
que solo
se ejecuta
en un thread principal
que es el mítico
thread principal
entonces
si tú lo bloqueas
si tú haces algo
que sea demasiado
bestia
o tiene mucha computación
tu página
no responde
no responde
porque lo que ocurre
es que
está evaluando
el javascript
y no le da espacio
por ejemplo
a leer los eventos
de click
o hacer absolutamente nada
entonces
hace tiempo
que existen
los web workers
que son
un hilo
totalmente
separado
al principal
desde el que
puedes ejecutar
scripts
en un segundo plano
y con el que
te puedes comunicar
y esto
que te permite
enviar mensajes
para cuando tú
le envías mensajes
para decirle
oye
haz esta tarea
o cuando el web worker
haya terminado la tarea
volver de vuelta
con ese mensaje
lo que te permite
es liberar
ese trabajo
del thread principal
para hacerlo
en un hilo secundario
¿vale?
y esto está muy interesante
por temas de seguridad
¿vale?
porque por un tema de seguridad
quizás quieres
que sea en el web worker
que se ejecute
cierta carga
por un tema de rendimiento
obviamente
porque así puedes
desbloquear
toda la potencia
de tu thread principal
para cosas tan importantes
como la interacción
del usuario
y hacer otras cosas
que pueden ser
mucho más intensivas
en este web worker
puede ser
un cálculo
que tengas que hacer
muy bestia
puede ser
se puede utilizar
también en notes
se puede utilizar
en diferentes sitios
¿vale?
y en este caso
encaja perfectamente
porque como podéis ver
el problema
que estamos teniendo
es que la carga
del modelo
al inicio
es muy potente
aquí en el performance
si lo veis
que aquí además
veis que al principio
no
como que no responde
tarda en enseñar
la información
podemos ver
que tenemos
un montón
pero un montón
de información
que veis
aquí
esta parte
básicamente
es toda esta parte
veis aquí
hay un montón
de
pues mira
alguien decía
si utiliza WebAssembly
y si que utiliza WebAssembly
porque fijaos
que pone Wasp
así que si utiliza WebAssembly
aunque vosotros
no necesitáis utilizar
nada de WebAssembly
pero hay un montón
de cosas de JavaScript
que está utilizando aquí
que está haciendo
y que tardan
un montón en responder
para arreglar esto
lo que vamos a hacer
es utilizar WebWorkers
y como podemos utilizar
los WebWorkers
a ver
normalmente
para utilizar
un WebWorker
lo más sencillo
lo más fácil
es crear
un archivo
Worker
.js
y aquí
haríamos
lo que queramos
por ejemplo
podríamos hacer
hola
me llamo
aaron
te saludo
desde México
estoy aprendiendo
mucho
en este directo
quería preguntarte
si es posible
usarlo
desde el móvil
tengo un iPhone 15
no sé
qué limitaciones
tenga
o si es preferible
dejarlo solo a web
o si se puede publicar
para mostrarlo
a mis amigos
se puede utilizar
un iPhone
yo creo que sí
yo creo que sí
que se puede utilizar
un iPhone
porque al final
también tiene
tiene el procesador
con inteligencia artificial
tienes una buena GPU
o sea creo que no va a haber
ningún tipo de problema
así que yo creo que sí
yo creo que sí
no lo he probado
pruébalo
y nos cuentas
a ver si funciona
o no funciona
ya está
vale
pues venga
vamos con el ejemplo
vamos con el ejemplo
del Worker
vale
para crear un Worker
lo primero que tenéis que hacer
es crear un archivo Worker
vale
que haga algo
porque necesitáis
tener un archivo
totalmente separado
no puedes tener un Worker
en vuestra misma página
siempre tiene que estar
de una forma separada
vale
y en este Worker
vamos a tener
sí o sí
que tener un OnMessage
el OnMessage
que es lo que significa
es cuando recibe
un mensaje
nuestro Worker
que es lo que tiene que hacer
o sea que
va a recibir un evento
lo podemos poner aquí
en la E
pero voy a decir
Log
Worker
Message
Receive
from
Main Thread
vale
y aquí pues podremos tener
bueno
vamos a mirar la consola
y ya está
vamos a hacer solo esto
que responda
simplemente a los mensajes
esto es lo que tendría que hacer
nuestro Worker
aquí dentro
podríamos hacer
todo lo que queramos
que sea tan importante
puedes importar también
scripts de terceros
aquí puedes hacer un import
sin ningún problema
puedes hacer import
bla bla bla
lo que tú quieras
la dependencia
como hemos hecho
en HTML con nuestro
import aquí
de hecho lo vamos a tener que hacer
vamos a tener que hacer
un import
lo veréis
este import
lo podéis hacer en el Worker
ahora lo veréis
y luego
lo que vamos a tener aquí
que hacer es cargar
nuestro Worker
a ver
para cargar un Worker
vamos a
lo primero que podríais hacer
es mirar si existen
los Worker
vale
podéis hacer esto
aunque a día de hoy
los Web Workers
check
los Web Workers
ya existen
o sea ya existen
en todas las páginas
o sea en todos los navegadores
que yo sepa
vamos a ver
pero yo creo que es una tecnología
que ya
ah no
Share Web Workers
ah no
pero esto es para
diferentes scripts
98%
esto es otro
digo hostia 47%
estoy flipando
no no
los Web Workers
para que os hagáis una idea
es una tecnología
que soporta hasta Internet Explorer
o sea que imagínate
98% de soporte
o sea imagínate
va sobrado
no te tienes que preocupar
así que yo esto
a ver
lo podéis hacer
por si os queréis quedar a gusto
luego tenéis que cargar
el Worker
entonces ponemos Worker
y aquí le tenemos que crear
un nuevo Worker
e indicarle
donde está el Worker
así que hacemos Worker.js
aquí pues tendrías que poner
la ruta completa
nosotros lo tenemos exactamente
en el mismo sitio
entonces no vamos a tener
ningún problema
pero si es un problema
de según la ruta
y por ejemplo
que estéis en una ruta
en un path y tal
pues tened en cuenta
que tenéis que poner la barra
que tenéis que poner
temas relativos
que tendréis que crear
la ruta relativa
dependiendo de diferentes cosas
lo que sea
vale
entonces una vez que tenéis esto
ya lo que podemos hacer
es enviarle un mensaje
del Worker
le podemos enviar
un mensaje
hello from the Worker
vale
le podemos enviar el mensaje
que queramos
y lo que sea
y también
aquí
nosotros podemos enviar
un mensaje de vuelta
por ahora vamos a hacer
solo esto
para ver cómo funciona
y vámonos
aquí a la página
hostia
no sé por qué
la página
dónde he dejado la página
vámonos a la consola
claro
lo malo de la consola
es que ahora tenemos
lo del init progress callback
voy a quitarlo
para que no nos
este console.log
lo quito
vale
y así nos enteraremos
de este
fijaos
Worker
ha recibido un mensaje
desde el main thread
y aquí tendríamos el evento
fijaos
es un evento
como si fuese un click
y tendríamos la data
hello from the Worker
vale
bueno
he puesto hello from the Worker
pero no tiene mucho sentido
que hagamos el hello from the Worker
no aquí
aquí en realidad
es hello from the Worker
teníamos que poner
hello from the main thread
de main thread
pero podríais pasarle
otras cosas diferentes
por ejemplo
podríais pasarle
yo que sé
vamos a pasarle un objeto
vale
hello
y vamos a ver aquí
vamos a ver aquí
y aquí vamos a poner
if e.data.name
eh
punto name
¿he puesto name?

name
le ponemos que es igual a hello
entonces
vamos
vamos a poner hello back
¿ves?
podemos hacer aquí un post message
y esto lo que va a hacer
es que el Worker
se va a comunicar
con este de aquí
así que vamos a poder escuchar
cada vez que el Worker
nos devuelva
un mensaje
de vuelta
¿vale?
y aquí lo teníamos
vamos a poner
console.log
vamos a quitar este
message receive from
from worker
¿vale?
y aquí vamos a poner main thread
main thread
y ya está
entonces ya estaríamos
ya se están comunicando
fíjate
el Worker recibió el mensaje
del month thread
y el Worker envía un mensaje
al main thread
el main thread
ha recibido el mensaje
y el mensaje
lo que está diciendo es
hello back
o sea que ya estamos
haciendo totalmente
la comunicación
entre el main thread
y el hilo
totalmente secundario
o sea que ya podemos
enviarle información
para que haga
todo lo que tenga que hacer
este Web Worker
por nosotros
para que nosotros
no nos tengamos que preocupar
de ninguna cosa
entonces
ahora que ya tenemos claro
esto de los Web Workers
que aquí
dependerá totalmente
lo que queráis hacer
pero lo bueno
es que la gente
de Web
LLM
tiene soporte nativo
para Web Workers
y esto lo que nos permite
es que podemos importar
en el Web Worker
un método especial
¿vale?
esto lo vamos a cargar
desde la URL
del CDN
que tenemos aquí
este CDN
¿vale?
este CDN
lo cargamos aquí
y vamos a poder crear
sin ningún tipo de problema
aquí
un engine
ya no necesitamos
el on message
porque esto de forma interna
ya se va a preocupar
vamos a crear el engine
creamos
MLC engine
¿vale?
y ahora vamos a crear
el handler
que esto lo que va a hacer
es el on message
que hemos visto
vamos a crear
new MLC engine
worker handler
pasándole el engine
y lo que habéis visto
del on message
pues aquí vamos a recibir
el mensaje
y cada mensaje
que recibamos
este handler
que hemos creado
vamos a hacer
un on message
message
o sea
este handler
ya está haciendo
internamente
todo lo que
nosotros antes
hemos hecho
lo que está haciendo
es recuperar
esa información
del engine
en el worker
y directamente
tratarlo
automáticamente
cuando reciba
esa información
ya lo hará
en este worker
totalmente separado
y ya está
y ahora nosotros
todavía tenemos que hacer
algo por nuestra parte
no es que esto
creamos el worker
y ya está
aquí habíamos creado
un create
MLC engine
claro
esto funcionaba
bien
pero ahora que queremos
utilizar un worker
tenemos que cambiar
un poco esto
para eso
tenemos que utilizar
el create
no me acuerdo
como se llama
create
web worker
MLC engine
es muy parecido
de hecho
el contrato
es exactamente
el mismo
excepto
porque
voy a quitar esto
que esto ya no necesitamos
veis que antes
hacemos el selected model
todo esto
aquí utilizamos
el create
MLC engine
que era el de antes
ahora
utilizando el de web worker
tenemos que cambiar
una cosita
y es que tenemos
que indicarle
como primer parámetro
cual es el web worker
que queremos utilizar
entonces utilizamos
new worker
porque este es el worker
que queremos utilizar
worker.js
y hay otro detalle
que necesitamos
vale
o sea
parece así
pero hay otro detalle
que nos va a dar un problema
y ahora verás cuáles
si volvemos a nuestra página
vale
fíjate que nos da un problema
no puedes utilizar
un import
fuera de un módulo
¿por qué?
porque aquí en el worker
estoy utilizando este import
y te he dicho
que esto se podía hacer
pero claro
necesitas un detalle
para que esto funcione
y es que aquí
en el new worker
que hemos creado
tenemos que pasarle
un segundo parámetro
que serán las opciones
e indicarle
que este web worker
es del tipo módulo
y esto lo que hace
igual que hemos hecho
aquí en el script
que hemos puesto
type module
esto lo que hace
es informarle
que este web worker
también va a utilizar
los exma script modules
y vamos a poder utilizar
imports y exports
como queramos
esto es lo que le hace
como decir
oye
que voy a utilizar
los imports
ahora
tenlo en cuenta
cuando cargues esto
para que lo cargues correctamente
y ahora si
cuando entramos
pues fijaos
que ya lo tenemos ahí
funcionando
parece ser que funciona
correctamente
y fíjate que ahora
si que me responde
desde el principio
veis que ahora
si que haciendo click
responde totalmente
aunque no esté cargando esto
¿por qué ha pasado esto?
bueno pues esto lo podemos ver
muy fácilmente
si hacemos un profiling
desde el principio
antes habíamos visto
que había mucho amarillo
ahí
en la carga del modelo
y todo esto
y fijaos ahora
la diferencia
fijaos en el main
esto sería
el thread principal
el thread principal
es que
ha desaparecido
casi todo
fijaos
que aunque si
que aparece ahí
algunas cosas
amarillo
en rojo
y tal
pero es que
casi casi
ya no hay nada
en cambio
el worker
que es el otro hilo
fijaos donde está
toda la carga
de trabajo
del javascript
todo esto
que antes teníamos
en el thread principal
es que ha desaparecido
ahora el thread principal
está
está no haciendo
casi nada
y en cambio
el worker
que todos los workers
que tengáis
porque puedes tener
más de un worker
puedes tener
infinito workers
pues fijaos
que todo esto
que estaba bloqueando
el thread
por más de un segundo
porque estos son
700 milisegundos
y aquí otros
580 milisegundos
esto lo ha hecho
en un hilo secundario
y en cambio
el thread principal
ha quedado limpísimo
lo que hace que esto
si ahora
no
cuéntame
el principito
vale
esto sigue funcionando
perfectamente
lo que pasa
es que toda
la inicialización
del módulo
del modelo
todo
todo el trabajo
inicial
que bloqueaba
nuestra página
ahora lo estamos
extrayendo
a un hilo secundario
para dejar libre
nuestro thread principal
así que
espero que
que no está mal
no está mal
no está mal
la cosa
la respuesta del modelo
pasa en el thread principal
o en el worker también
yo creo que
seguramente
pasa en el worker
o sea
creo que
todo pasa en el worker
porque
porque
como está aquí
en el on message
a ver
es verdad que
no sé si aquí
no hay un post message
como tal
aquí no hay un post message
entonces tengo la duda
pero no sé si internamente
aquí
realmente sí que está haciendo
el post message
y todo esto
y no lo vemos
podríamos intentar mirar
podríamos intentar mirar
entrando en el código
y tal
pero yo creo que sí
que seguramente
lo está haciendo
en el worker
porque tendría sentido
al final es trabajo
que también
ayuda
a que lo quites
del thread principal
no tenía mucho sentido
que solo una parte
la extraigas
y lo demás
te lo que dejes así
entonces
addcode04
vamos a añadir
todo este código
os recuerdo
que esto es parte
de los 100 proyectos
de javascript
llevábamos 3
este es el cuarto
que lo añadiré aquí
para que lo tengas
en cada uno
tenéis todo el código
todos los vídeos
que antes alguien me ha dicho
pero no veo los vídeos
pues aquí tienes
el botón del vídeo
le das al vídeo
y entonces tienes
el vídeo
donde explicamos
cómo lo estamos haciendo
igual que el de hoy
lo voy a subir
con el vídeo
con el código
y también la demo
de cada uno
para que podáis ver la demo
podáis ver el vídeo
de cómo lo hicimos
y que también tengáis
todo el código disponible
para revisarlo
y este
el que acabamos de hacer
pues ya tenéis aquí
el código disponible
en el proyecto
de javascript 100 proyectos
de github
vale
para que podáis
toquetearlo
revisarlo
echarle un vistazo
hacer lo que queráis
pero ya tenemos
cuatro proyectos
seguramente después
lo añadiré aquí también
el cuarto
porque todavía no me ha dado tiempo
y lo haremos ahí después
pero espero y deseo
que os haya gustado mucho
la clase
son dos horas
pero hemos hecho
un montón de cosas
porque has aprendido
temas de los módulos
de gmascript
obviamente todo el tema
de los eventos
del formulario
generación con templates
de DOM dinámico
hemos aprendido
qué son los web workers
porque es importante
cuándo te puede ayudar
cómo puedes revisar
en el rendimiento
si está habiendo
una afectación
y algo que puedas sacar
a un web worker
no sé
creo que ha sido
muy interesante
y además
cómo puedes ejecutar
inteligencia artificial
de forma totalmente local
privada y gratuita
en el navegador
lo cual es bastante tremendo
porque creo que puede tener
un montón de casos de uso
lo que comentamos
una página
de viajes
que pasándole
ciertas cosas
pues te haga un itinerario
muy rápidamente
o que te revise
o que te responda
a dudas
de la ciudad
a la que vas
por ejemplo
oye
cuál es la capital de Francia
cuánta gente vive en Francia
cuál es un barrio
bastante interesante
de Francia
y además
el hecho de tenerlo
directamente
en tu página
creo que le da
le da un toque
bastante diferente
¿sabes?
así que
no sé
ahí lo tenemos
voy a poner esto
por ejemplo
yo me voy a Japón
la semana que viene
no sé lo sabéis
la semana que viene
me voy a Japón
entonces le podéis preguntar
¿qué barrio
me recomiendas
visitar
en Japón
para ver?
pues mira
le podemos preguntar
hola Japón es un país
con la gran vela
aquí te presento a algunos
a Sakuza
bueno
habría que hacer
que la respuesta
esté bien formateada
y tal
pero ya está
Sakuza
Shibuya
Shibuya es uno de los barrios
más populares
o sea
imaginaos estas cosas
es increíble
o sea
el límite es tu imaginación
¡Gracias!
¡Gracias!