1 puntos por GN⁺ 2023-06-26 | 2 comentarios | Compartir por WhatsApp
  • WinGPT es un proyecto que busca ejecutar un chatbot basado en la API de OpenAI incluso en Windows 3.1, con enfoque en llamar servicios modernos de IA desde PCs antiguas como una 386
  • La implementación está basada en C y la API estándar de Windows, y gracias a Open Watcom v2 es posible compilar para Windows de 16 bits incluso desde Windows 11
  • Se conecta directamente al servidor de la API de OpenAI con TLS 1.3 sin proxy, aunque se aclara que esta implementación de TLS no es segura
  • Como los controles de UI básicos de Windows 3.1 son limitados, hubo que implementar directamente elementos como la barra de estado o modificar código antiguo de dominio público
  • Debido a las limitaciones de memoria, solicita respuestas cortas y no envía los turnos previos de la conversación, por lo que no puede mantener el contexto conversacional

Un experimento para llamar la API de OpenAI desde Windows 3.1

  • WinGPT es un asistente de IA para Windows 3.1 que propone usos como preguntas y respuestas, chistes, y redacción de borradores de documentos y hojas de cálculo mediante la API de OpenAI
    • En una nota al pie se aclara que esta descripción es satírica y que no se debe depender de él, ya que no puede realizar esas funciones de forma confiable
  • La implementación está basada en C y en la API estándar de Windows
    • El compilador usado es Open Watcom v2
    • Open Watcom v2 permite compilación cruzada para Windows de 16 bits incluso desde Windows 11
  • Se conecta directamente al servidor de la API de OpenAI mediante TLS 1.3
    • No requiere un proxy que termine TLS en una máquina moderna
    • En “Modern TLS on 16-bit Windows” se explican el método de implementación y las dificultades, y se indica explícitamente que esta implementación de TLS no es segura

Dificultades de UI causadas por una API de Windows anticuada

  • En Windows 3.1, usar solo la API básica de Windows ofrece capacidades muy limitadas para construir la UI
    • La mayor parte de la UI se creó directamente en código C, y también se escribió lógica de redimensionamiento para que cada componente conserve el tamaño correcto al cambiar el tamaño de la ventana
    • Los controles estándar se limitan más o menos a push button, check box, radio button y edit box
  • Las limitaciones de Windows 3.1 se notan especialmente al implementar una barra de estado
    • File Manager y Control Panel tienen barra de estado, pero Microsoft no la puso ampliamente a disposición de desarrolladores de aplicaciones generales hasta Windows 95
    • Al preguntarle a ChatGPT cómo usar una barra de estado, mostró archivos de encabezado que solo existen en versiones posteriores de Windows y, al insistir, inventó el nombre de una biblioteca de UI que aparentemente no existe
    • Al final se usó la implementación de barra de estado de Philip J. Erdelsky de 1997, modificándola para que se pareciera más, píxel por píxel, a la barra de estado de los programas de Microsoft
  • Los íconos se crearon con Borland Image Editor
    • Los íconos de programa de Windows 3.1 son de 32x32 y se muestran en Program Manager y en el selector de tareas
    • También se crearon por separado íconos de 16x16 para mostrarlos en versiones posteriores de Windows

Restricciones de memoria y condiciones de ejecución

  • Debido a las limitaciones de memoria de una máquina con Windows 3.1, fue necesario reducir el uso de memoria en las solicitudes a la API y en el procesamiento de respuestas
    • Las respuestas JSON de las APIs modernas no están optimizadas para tamaño, y la API de OpenAI no es la excepción
    • Para mantener pequeñas las respuestas, se le pide al modelo que responda de forma breve
    • Como no se incluye el texto de turnos previos en las llamadas a la API, no se puede aprovechar el contexto previo de la conversación
  • WinGPT tiene licencia GNU GPL v2
    • Funciona en Windows de 16 o 32 bits posteriores a Windows 3.1
    • Requiere una implementación de Winsock, y fue probado en Windows 3.11 for Workgroups con Microsoft TCP/IP-32 3.11b instalado y en un Windows 2000 base
    • No funciona en Windows de 64 bits, pero sí puede ejecutarse en Wine
    • Para comunicarse con OpenAI se necesita una clave de API de OpenAI, que se ingresa después de ejecutar el programa en File | Options...
    • Descarga: Binaries for 16-bit and 32-bit Windows
    • El código fuente está incluido en modified WolfSSL source code y su ubicación es watcom16/wingpt

2 comentarios

 
cosine20 2023-06-28

jajajajajajajajajajaja

 
GN⁺ 2023-06-26
Opiniones de Hacker News
  • Quedaría bien incluso integrado en la versión de MS Office de esa época
    Incluso podrían convertirlo en un personaje antropomórfico con estilo skeuomórfico basado en artículos reales de oficina de entonces, como una liga… o… algo como un clip…

    • Buena idea :) aunque Clippy apareció después de Office 97, así que quizá haría falta una versión que encaje más con la estética de Windows 95/98 o Windows Me
    • Microsoft Bob también le quedaría muy bien: https://en.m.wikipedia.org/wiki/Microsoft_Bob
    • Del clip de papel al paperclip maximizer, la IA realmente dio la vuelta completa
  • Hay una parte aparte donde lograron hacer funcionar TLS 1.2 y 1.3 en Windows 3.1 para que WinGPT se conecte directamente a los servidores de OpenAI sin depender de la terminación TLS de una máquina moderna: https://www.dialup.net/wingpt/tls.html
    Vale mucho la pena leerlo. En entornos embebidos muy profundos como IoT, e incluso en CPUs de 8 bits que usan bank switching, muchas veces sí hay soporte para TLS 1.2, así que sorprende que haya sido difícil meter una implementación TLS dentro de 64KB de código y datos

    • Qué gusto ver que hay alguien trabajando en TLS 1.3 para Windows 3.1
      Es un poco triste que los sistemas operativos viejos tengan problemas para acceder a internet
    • Algunos de esos chips podrían tener soporte de hardware criptográfico
  • Extraño muchísimo la era de Windows 3.1, 95 y 98. Siento que la interfaz solo ha empeorado desde entonces
    Cada vez que enciendo un 386 o un Pentium me sorprende lo limpia y poco estresante que era la GUI. Ya me cansé del infierno de pop-ups de bajo contraste al estilo Apple/Google

    • Vale la pena leer las Windows Interface Guidelines de 1995: https://www.ics.uci.edu/~kobsa/courses/ICS104/course-notes/M...
    • ¿Recuerdan que en esa época realmente podías redimensionar los elementos? Cosas como barras laterales y barras de herramientas
      Ahora, si localizas la interfaz, la mitad del UI termina con etiquetas como "Tap to....". Con todas estas grandes herramientas modernas de UI y desarrolladores estrella que las usan, muchas veces ni siquiera logran hacer una sola barra lateral arrastrable
  • Si quieres intercambiar espacio por tiempo de CPU, puedes usar parsing estilo SAX
    El parsing estilo SAX recorre el árbol de arriba hacia abajo y dispara eventos al visitar cada nodo. Comparado con parsear JSON completo, la memoria necesaria es casi despreciable, y tampoco parece muy difícil escribir un parser SAX personalizado para JSON. También hay parsers JSON estilo SAX ya existentes que pueden servir de referencia
    [1]: https://en.wikipedia.org/wiki/Simple_API_for_XML
    [2]: https://rapidjson.org/md_doc_sax.html

    • Exacto. Estoy usando JSMN(https://github.com/zserge/jsmn), que es un parser en streaming que visita cada token en secuencia, así que solo existe una copia de la respuesta JSON en memoria
      También evito al máximo nuevas asignaciones intermedias de memoria. Por ejemplo, al deshacer los escapes con barra invertida en una cadena JSON, uso un bucle destructivo que mueve los caracteres sin barra invertida hacia el frente de la memoria y adelanta el terminador nulo para recortar la cadena. Hoy en día casi nadie lo haría así, pero como dijiste, se puede gastar un poco más de tiempo de CPU para ahorrar algo de espacio :)

      void DestructivelyUnescapeStr(LPSTR lpInput) {
      int offset = 0;
      int i = 0;
      while (lpInput[i] != '\0') {
      if (lpInput[i] == '\') {
      offset++;
      } else {
      lpInput[i - offset] = lpInput[i];
      }
      i++;
      }
      lpInput[i - offset] = '\0';
      }

  • Es muy probable que la infraestructura de soporte del control de cuadro de texto en el que estoy escribiendo ahora mismo consuma más recursos del sistema que todo WinGPT
    Eso muestra que estamos desperdiciando literalmente varios órdenes de magnitud de memoria para aumentar un poco la productividad del desarrollador. Programar controles puros de Windows claro que era difícil, pero también se puede argumentar que Delphi o VB en Win95 eran mucho más productivos que los toolkits modernos de UI, y las aplicaciones resultantes usaban muchísimos menos recursos. Lo principal que faltaba era soporte móvil y conciencia de DPI

    • Sinceramente, la frase "una pequeña ganancia en productividad del desarrollador" me parece quedarse corta
      Las cosas que de niño sufría para hacer en código nativo ahora prácticamente cualquiera las puede hacer con librerías y herramientas ya hechas orientadas al navegador web. Eso en sí es un logro impresionante y no es algo malo. Lo más triste es que el navegador, al volverse en general la opción "mejor", está matando a las apps nativas

      Hoy en día, las empresas de software dan por hecho que tienen que ofrecer acceso web a sus servicios de red, así que primero hacen la versión web. Después quieren soportar iPhone, Windows, Android, macOS y Linux. Hay opciones que cubren parcialmente cada plataforma, pero para ese punto ya existe al menos una prueba de concepto en el navegador, y con una instalación de NPM puedes empacarla para ejecutarse en una ventana aparte con instalador y sistema de distribución incluidos. No será grandioso, pero sí es posible

      Si existiera un framework GUI nativo eficiente y de calidad de producción capaz de apuntar de forma eficiente al DOM y a las UI nativas de Windows, macOS, Android e iPhone, con entrada de texto nativa que soporte IME y la semántica propia de cada plataforma, accesibilidad integrada con lectores de pantalla, cambios responsivos de UI para distintos tamaños de pantalla, y elementos visuales robustos, rápidos e independientes de DPI que manejen correctamente escalas fraccionales, el problema sería menor. Seguro sería fácil, ¿no?

Pero no hay nada así. Me gustan Delphi VCL y Win32 puro, pero tampoco cumplen con la mayoría de los requisitos. Dar soporte a todas estas plataformas es muy difícil. El navegador hace bastante bien este trabajo y además es una de las mejores fuentes de código de ejemplo para consultar al escribir código profundo y específico de cada plataforma. Encima, como de todos modos casi todo apunta a la web y el motor del navegador también es "código nativo", es mucho más fácil distribuir un navegador o al menos un motor de JS junto con una plataforma que ya ejecuta código nativo, que crear una solución de código nativo isomórfico que también funcione en el entorno del navegador

Al final mejorará algún día, pero antes de mejorar es muy probable que empeore más
  • ¿Podrías desarrollar un poco más la parte de "también se podría decir que era mucho más productivo"?

  • El concepto de despliegue también tiene que formar parte de la productividad. En esa época, Delphi/VB ignoraban por completo esa cuestión según el estándar del momento
    Si era una utilidad simple en zip, bastaba con copiar un único EXE en algún montaje de red dentro de una LAN detrás del firewall. Windows incluía una especie de sistema de archivos dentro del binario para cargar iconos y cadenas, y con eso alcanzaba. Si era una app más compleja que necesitaba DLL y entradas del registro, había que pagar cientos de dólares por InstallShield y aprender InstallScript. Antes de que aparecieran MSI y WiX, no había punto medio, y hasta mediados de los años 90 Microsoft veía internet como una moda exótica y consideraba poco práctico distribuir software por red debido al bajo ancho de banda. El software era para CD-ROM, y despachar realmente significaba enviarlo en barco

    El problema es que a la gente le importaba casi por encima de todo la velocidad de iteración, incluso más que la productividad pura. El mundo cambiaba más rápido que Delphi. Borland pudo haberse dado cuenta de que la tendencia de forzar al navegador a comportarse como una app representaba una necesidad fundamental no verbalizada y quizá haber creado algo como un intérprete de Object Pascal. Por ejemplo, si hubieran hecho algo como "Delphi Browser", probablemente se habría adoptado, pero su base de código estaba orientada de raíz a producir apps nativas de Windows, así que una transición así habría sido difícil. Además, Borland era más bien un invitado en la plataforma Windows y tendía a seguir la dirección marcada por Microsoft. Microsoft impulsó ActiveX como forma de conectar el mundo web con el de Windows, y Borland se dio cuenta demasiado tarde de que ActiveX no iba a cubrir lo que la gente necesitaba. Al principio no vio la web como competidor; después la vio como un simple medio de transporte para apps Delphi; más tarde empujó el uso de Delphi para servidores web, pero esa no era su fortaleza

    La lección aquí es la importancia de las preferencias no verbalizadas, que se aprenden observando lo que la gente realmente hace y no lo que dice, y la importancia abrumadora del despliegue. El despliegue sigue siendo un punto ciego incluso para la mayoría de los competidores de la web hoy en día. Hasta el año pasado casi no había plataformas tipo Delphi con un despliegue al estilo web que se refrescara siempre al ejecutar la app. Ni siquiera Electron ofrece más que actualizaciones de escritorio totalmente asíncronas. Yo dirijo una pequeña empresa que hace un producto para arreglar el despliegue de apps de escritorio dentro de las limitaciones de las plataformas nativas, y añadimos un modo de despliegue estilo web llamado aggressive updates (https://hydraulic.dev/). En este modo se buscan actualizaciones en cada ejecución, así que si puedes lograr que el usuario reinicie la app de vez en cuando o forzar un reinicio en el momento apropiado, puedes iterar muy rápido. No es muy distinto de pedir en una SPA que cierren la pestaña y vuelvan a cargar

    Por eso no estoy de acuerdo con que lo que faltaba eran los móviles y el DPI. Delphi, VB, GTK, Cocoa y demás ya habían perdido el escritorio antes de que los smartphones se volvieran importantes. No tenían un buen sistema de despliegue y actualizaciones, y la capacidad de empujar correcciones y cambios de inmediato era más importante que todas las demás funciones juntas

  • Parece que el ritmo del progreso tecnológico se ha acelerado tanto que estamos empezando a sufrir un choque cultural originado en nuestra propia cultura, es decir, un choque con el futuro. Ese ritmo se acelerará aún más dentro de nuestras vidas
    Está bueno volver a ver software de Windows 3.1. Dejo esto también para los fanáticos de lo retro: https://www.xfce-look.org/p/1016410

  • La parte más impresionante es el TLS nativo
    Recuerdo haber oído que la criptografía moderna no podía usarse en CPUs antiguas por la cantidad de cálculo numérico difícil de optimizar. Algo como que algunas etapas del algoritmo de intercambio de claves tardaban tanto que el servidor podía agotar el tiempo de espera. Pero aparentemente en un 386 viejo y lento no es problema, ¿o sí?

    • Si consideras cuántos dispositivos embebidos siguen en uso, y que una parte importante de ellos son microcontroladores de 8 bits con RAM mínima, diseñar sistemas de esa manera es irresponsable
      Tal vez pueda ser así en sistemas sin uso embebido, como el cifrado de video en tiempo real, pero no todo el mundo se conecta a internet desde el iPhone más reciente
  • Está realmente genial. Puede que lo pruebe en una de mis máquinas reales con Windows 3.1 :)
    Como sugerencia, estaría bueno permitir personalizar el prompt del sistema en el cuadro de diálogo Options. La configuración de 1992 es divertida, pero algo limitada. Si estás tratando de resolver un problema en una computadora retro, usar esto en vez de sacar una computadora moderna o un smartphone hasta podría tener cierto sentido

  • Si usas Win32s en Windows 3.1, no tienes que preocuparte por el modelo de memoria segmentada, y además puede funcionar en Windows de 64 bits

    • Cierto, pero cosas como Win32s o WinG se sienten como conocimiento transmitido oralmente que solo recuerdan los veteranos que compraban revistas de programación antiguas con regularidad