WinGPT, trợ lý AI cho Windows 3.1
(dialup.net)- WinGPT là một dự án nhằm thử chạy chatbot dựa trên OpenAI API ngay cả trên Windows 3.1, tập trung vào việc gọi các dịch vụ AI hiện đại từ những PC cũ như 386
- Việc triển khai dựa trên C và Windows API tiêu chuẩn, và nhờ Open Watcom v2 nên có thể build cho Windows 16-bit ngay cả trên Windows 11
- Kết nối trực tiếp tới máy chủ OpenAI API bằng TLS 1.3 mà không cần proxy, nhưng có nêu rõ rằng phần triển khai TLS này không an toàn
- Do các control UI mặc định của Windows 3.1 bị hạn chế, những thành phần như thanh trạng thái cũng phải tự triển khai hoặc chỉnh sửa mã public domain cũ
- Vì giới hạn bộ nhớ, dự án yêu cầu phản hồi ngắn và không gửi các lượt hội thoại trước đó, nên không thể duy trì ngữ cảnh hội thoại
Thử nghiệm gọi OpenAI API trên Windows 3.1
- WinGPT là một trợ lý AI cho Windows 3.1, quảng bá các mục đích như hỏi đáp, kể chuyện cười, viết nháp tài liệu và bảng tính thông qua OpenAI API
- Phần chú thích cho biết mô tả này mang tính châm biếm, và khuyên không nên phụ thuộc vào nó vì không thể thực hiện các chức năng đó một cách đáng tin cậy
- Việc triển khai dựa trên C và Windows API tiêu chuẩn
- Trình biên dịch sử dụng Open Watcom v2
- Open Watcom v2 có thể cross-compile cho Windows 16-bit ngay cả trên Windows 11
- Kết nối trực tiếp tới máy chủ OpenAI API bằng TLS 1.3
- Không cần proxy kết thúc TLS trên máy hiện đại
- Bài “Modern TLS on 16-bit Windows” đề cập đến cách triển khai và những khó khăn, đồng thời nêu rõ rằng phần triển khai TLS này không an toàn
Những khó khăn khi triển khai UI do Windows API cũ kỹ tạo ra
- Trên Windows 3.1, nếu chỉ dùng Windows API mặc định thì khả năng xây dựng UI rất hạn chế
- Phần lớn UI được tạo trực tiếp trong mã C, và cũng phải viết logic thay đổi kích thước để mỗi thành phần giữ đúng kích thước khi cửa sổ được resize
- Các control tiêu chuẩn bị giới hạn ở push button, check box, radio button và edit box
- Giới hạn của Windows 3.1 đặc biệt nổi bật khi triển khai thanh trạng thái
- File Manager và Control Panel có thanh trạng thái, nhưng Microsoft không phổ biến rộng rãi nó cho nhà phát triển ứng dụng nói chung cho đến trước Windows 95
- Khi hỏi ChatGPT cách dùng thanh trạng thái, nó đưa ra các header file chỉ có ở các phiên bản Windows sau này, và khi hỏi lại thì còn bịa ra tên một thư viện UI dường như không tồn tại
- Cuối cùng, dự án đã dùng status bar implementation năm 1997 của Philip J. Erdelsky và chỉnh sửa để giống thanh trạng thái trong các chương trình Microsoft hơn tới từng pixel
- Biểu tượng được tạo bằng Borland Image Editor
- Biểu tượng chương trình của Windows 3.1 là 32x32 và được hiển thị trong Program Manager và trình chuyển tác vụ
- Biểu tượng 16x16 hiển thị ở các phiên bản Windows sau này cũng được làm riêng
Giới hạn bộ nhớ và điều kiện chạy
- Do giới hạn bộ nhớ của máy Windows 3.1, cần giảm lượng bộ nhớ dùng trong xử lý yêu cầu và phản hồi API
- Phản hồi JSON của các API hiện đại không được tối ưu về kích thước, và OpenAI API cũng không ngoại lệ
- Để giữ phản hồi nhỏ, dự án yêu cầu model trả lời ngắn
- Vì không đưa văn bản của các lượt hội thoại trước vào lời gọi API, nên không thể tận dụng ngữ cảnh hội thoại trước đó
- WinGPT được cấp phép theo GNU GPL v2
- Chạy trên Windows 16-bit hoặc 32-bit từ sau Windows 3.1
- Cần có triển khai Winsock, và đã được thử nghiệm trên Windows 3.11 for Workgroups cài Microsoft TCP/IP-32 3.11b và Windows 2000 mặc định
- Không chạy được trên Windows 64-bit nhưng có thể chạy trong Wine
- Để giao tiếp với OpenAI, cần có khóa OpenAI API, và sau khi chạy thì nhập secret key trong
File | Options... - Tải xuống: Binaries for 16-bit and 32-bit Windows
- Mã nguồn được bao gồm trong modified WolfSSL source code và nằm tại
watcom16/wingpt
2 bình luận
kkkkkkkkkkkkkkkkkkkkkkkk
Ý kiến trên Hacker News
Có vẻ cũng hợp để đưa vào các phiên bản MS Office thời đó
Khi ấy thậm chí có thể biến nó thành một nhân vật được nhân cách hóa theo kiểu skeuomorphic từ đồ dùng văn phòng thật, ví dụ như dây chun… hoặc… một cái kẹp giấy gì đó…
Có hẳn một phần riêng nói về việc làm cho TLS 1.2 và 1.3 chạy được trên Windows 3.1 để WinGPT có thể kết nối trực tiếp tới máy chủ OpenAI mà không phụ thuộc vào việc chấm dứt TLS trên máy hiện đại: https://www.dialup.net/wingpt/tls.html
Rất đáng đọc. Trong các môi trường nhúng sâu như IoT, thậm chí cả CPU 8-bit dùng bank switching, việc hỗ trợ TLS 1.2 khá phổ biến, nên việc khó nhét được một triển khai TLS vào trong 64KB mã và dữ liệu lại tạo cảm giác khá bất ngờ
Việc các hệ điều hành hơi cũ gặp khó khăn khi truy cập Internet quả là điều buồn
Thật sự rất nhớ thời Windows 3.1, 95, 98. Giao diện dường như chỉ tệ đi kể từ sau đó
Mỗi lần bật một máy 386 hay Pentium, tôi lại ngạc nhiên vì GUI ngày ấy gọn gàng và ít gây căng thẳng đến mức nào. Tôi thật sự chán ngấy kiểu địa ngục popup tương phản thấp của Apple/Google
Giờ thì chỉ cần bản địa hóa là nửa cái UI hiện ra mấy nhãn kiểu "Tap to....". Những công cụ UI hiện đại tuyệt vời cùng các ngôi sao lập trình dùng chúng mà nhiều khi còn chẳng làm nổi một sidebar kéo được
Nếu muốn đổi không gian lấy thời gian CPU thì có thể dùng phân tích cú pháp kiểu SAX
Phân tích cú pháp kiểu SAX sẽ duyệt cây từ trên xuống dưới và phát sinh sự kiện khi ghé từng nút. So với việc phân tích đầy đủ JSON thì bộ nhớ cần dùng gần như không đáng kể, và việc tự viết một bộ phân tích cú pháp JSON kiểu SAX có lẽ cũng không quá khó. Cũng có sẵn các bộ phân tích cú pháp JSON kiểu SAX đáng tham khảo
[1]: https://en.wikipedia.org/wiki/Simple_API_for_XML
[2]: https://rapidjson.org/md_doc_sax.html
Đúng vậy. Tôi đang dùng JSMN(https://github.com/zserge/jsmn), một bộ phân tích cú pháp streaming đi tuần tự qua từng token, nên chỉ có một bản sao của phản hồi JSON nằm trong bộ nhớ
Tôi cũng tránh cấp phát thêm bộ nhớ trung gian mới bất cứ khi nào có thể. Ví dụ, khi bỏ escape backslash trong chuỗi JSON, tôi dùng một vòng lặp phá hủy tại chỗ để dồn các ký tự không có backslash về phía trước trong bộ nhớ và kéo ký tự kết thúc null lên trước để cắt chuỗi. Đây gần như không phải kiểu người ta làm trong môi trường ngày nay, nhưng đúng như bạn nói, có thể đổi chút thời gian CPU để tiết kiệm chút không gian :)
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';
}
Có khả năng phần hạ tầng hỗ trợ cho ô textbox mà tôi đang gõ vào lúc này còn ngốn nhiều tài nguyên hệ thống hơn toàn bộ WinGPT
Điều đó cho thấy chúng ta lãng phí bộ nhớ tới đúng nghĩa là hơn vài bậc độ lớn chỉ để tăng nhẹ năng suất lập trình viên. Lập trình thuần bằng Windows control tất nhiên là khó, nhưng cũng có thể nói Delphi hay VB thời Win95 còn năng suất hơn nhiều toolkit UI hiện đại, trong khi ứng dụng tạo ra dùng ít tài nguyên hơn hẳn. Điểm còn thiếu chủ yếu chỉ là hỗ trợ di động và nhận biết DPI
Cụm từ "một chút lợi ích về năng suất lập trình viên" thành thật mà nói còn là nói giảm đi
Những thứ mà hồi nhỏ tôi từng phải vật lộn viết bằng mã native giờ gần như ai cũng có thể làm được bằng thư viện và công cụ có sẵn nhắm tới trình duyệt web. Bản thân điều đó là một thành tựu đáng kinh ngạc và không hề xấu. Điều đáng tiếc nhất là khi trình duyệt trở thành lựa chọn tổng thể "tốt hơn", nó đang giết chết ứng dụng native
Các công ty phần mềm ngày nay mặc nhiên cho rằng phải cung cấp truy cập web cho dịch vụ mạng, nên họ làm web trước. Sau đó họ muốn hỗ trợ iPhone, Windows, Android, macOS, Linux. Có những lựa chọn bao phủ được phần nào các nền tảng đó, nhưng đến lúc ấy thì thường đã có sẵn một bản proof-of-concept trong trình duyệt rồi, và chỉ cần cài NPM một lần là có thể đóng gói nó vào cửa sổ riêng, kèm cả trình cài đặt và hệ thống phân phối để phát hành. Không tuyệt vời, nhưng làm được
Nếu có một framework GUI native hiệu quả, chất lượng production có thể nhắm mục tiêu hiệu quả tới DOM và UI native trên Windows, macOS, Android, iPhone, đồng thời hỗ trợ nhập văn bản native với IME và ngữ nghĩa đặc thù của từng nền tảng, khả năng truy cập tích hợp với screen reader, thay đổi UI phản hồi theo nhiều kích thước màn hình khác nhau, và các thành phần hiển thị độc lập DPI vừa chắc chắn vừa nhanh xử lý đúng cả tỷ lệ scale lẻ, thì vấn đề đã đỡ hơn. Dễ làm nhỉ?
Nhưng không có thứ như vậy. Tôi thích Delphi VCL hoặc Win32 thuần, nhưng ngay cả chúng cũng không đáp ứng được phần lớn yêu cầu. Hỗ trợ tất cả các nền tảng này là cực kỳ khó. Trình duyệt làm việc này khá tốt, đồng thời cũng là một trong những nguồn mã ví dụ tốt nhất để tham khảo khi viết mã chuyên sâu theo từng nền tảng. Hơn nữa, dù sao thì phần lớn cũng hướng đến web và bản thân engine trình duyệt cũng là "native code", nên thay vì tạo ra một giải pháp native code đồng hình chạy được cả trong môi trường trình duyệt, sẽ dễ hơn rất nhiều nếu phân phối trình duyệt hoặc ít nhất là engine JS cùng với nền tảng vốn đã chạy native code.
Có thể giải thích thêm ý "cũng có thể xem là năng suất hơn rất nhiều" không?
Khái niệm năng suất cũng phải bao gồm cả triển khai. Theo chuẩn mực của thời đó, Delphi/VB đã hoàn toàn phớt lờ câu hỏi này.
Nếu chỉ là một tiện ích zip đơn giản thì chỉ cần chép một file EXE duy nhất vào đâu đó trên network mount trong LAN phía sau firewall là xong. Windows có một kiểu pseudo-filesystem trong binary để tải icon và chuỗi, như vậy là đủ. Với ứng dụng phức tạp hơn cần DLL và mục registry, bạn phải bỏ ra vài trăm đô để mua InstallShield rồi học InstallScript. Trước khi MSI và WiX xuất hiện thì không có gì ở giữa, và cho đến tận giữa thập niên 1990 Microsoft vẫn xem Internet như một mốt lạ từ phương xa, cho rằng do băng thông thấp nên phân phối phần mềm qua mạng là không thực tế. Phần mềm là để phát hành trên CD-ROM, và "shipping" theo nghĩa đen là chở hàng bằng tàu.
Vấn đề là mọi người coi trọng tốc độ lặp lại gần như hơn bất cứ điều gì, còn hơn cả năng suất thuần túy. Thế giới thay đổi nhanh hơn Delphi. Borland lẽ ra có thể nhận ra rằng xu hướng cố dùng trình duyệt như ứng dụng phản ánh một nhu cầu nền tảng không được nói ra thành lời, và có thể tạo ra thứ gì đó như trình thông dịch Object Pascal. Ví dụ, nếu họ làm một "Delphi Browser" thì có lẽ đã được chấp nhận, nhưng codebase của họ về căn bản được tối ưu cho việc tạo ứng dụng Windows native nên rất khó xoay chuyển theo hướng đó. Thêm vào đó, Borland gần như là khách trên nền tảng Windows và có xu hướng đi theo định hướng của Microsoft. Microsoft thúc đẩy ActiveX như cách nối liền thế giới web và Windows, còn Borland thì nhận ra quá muộn rằng ActiveX sẽ không đáp ứng được nhu cầu của mọi người. Ban đầu họ không xem web là đối thủ, sau đó xem nó như phương tiện vận chuyển đơn thuần cho ứng dụng Delphi, rồi về sau lại thúc đẩy dùng Delphi cho web server, nhưng thế mạnh của Delphi không nằm ở đó.
Bài học rút ra ở đây là phải học từ những sở thích không được nói ra thành lời bằng cách quan sát những gì mọi người thực sự làm, chứ không phải những gì họ nói, cùng với tầm quan trọng áp đảo của việc triển khai. Triển khai đến nay vẫn là điểm mù của phần lớn các đối thủ cạnh tranh với web. Ngay cả đến năm ngoái cũng hầu như không có nền tảng kiểu Delphi nào có được kiểu triển khai như web, nơi ứng dụng luôn được làm mới mỗi lần chạy. Ngay cả Electron cũng chỉ cung cấp cập nhật kiểu desktop hoàn toàn bất đồng bộ. Tôi đang điều hành một công ty nhỏ làm sản phẩm để sửa bài toán triển khai ứng dụng desktop trong các ràng buộc của nền tảng native, và đã thêm chế độ triển khai kiểu web gọi là aggressive updates (https://hydraulic.dev/). Ở chế độ này, mỗi lần chạy đều kiểm tra cập nhật, nên nếu người dùng thỉnh thoảng khởi động lại ứng dụng, hoặc có thể bị buộc khởi động lại vào thời điểm phù hợp, thì bạn có thể lặp rất nhanh. Điều đó không khác gì việc yêu cầu đóng tab và tải lại trong SPA.
Vì vậy tôi không đồng ý rằng điều cốt lõi bị thiếu là di động và DPI. Delphi, VB, GTK, Cocoa v.v. đã mất desktop từ trước khi smartphone trở nên quan trọng. Chúng không có hệ thống triển khai/cập nhật tốt, và khả năng đẩy bản sửa lỗi cùng thay đổi ngay lập tức quan trọng hơn tất cả các tính năng khác cộng lại.
Có vẻ như tốc độ phát triển công nghệ đã tăng nhanh đến mức chúng ta bắt đầu trải qua cú sốc văn hóa đến từ chính nền văn hóa của mình, tức là cú sốc tương lai. Tốc độ này sẽ còn tăng nhanh hơn trong quãng đời của chúng ta.
Thật thú vị khi xem lại phần mềm Windows 3.1. Cũng để lại cái này cho những người thích retro: https://www.xfce-look.org/p/1016410
Phần ấn tượng nhất là TLS native.
Tôi nhớ là từng nghe nói crypto hiện đại không dùng được trên CPU cũ vì lượng tính toán số học khó tối ưu hóa. Đại loại là một số bước trong thuật toán trao đổi khóa mất quá lâu nên server có thể timeout. Nhưng có vẻ trên chiếc 386 cũ và chậm thì lại không thành vấn đề?
Có thể đúng với các hệ thống không có use case nhúng, như mã hóa video thời gian thực, nhưng không phải ai cũng kết nối Internet bằng chiếc iPhone mới nhất.
Thật sự rất ngầu. Có lẽ tôi sẽ thử trên một trong những máy Windows 3.1 thật mà tôi có :)
Xin đề xuất là nên cho phép tùy biến system prompt trong hộp thoại Options. Thiết lập năm 1992 thì vui thật, nhưng hơi hạn chế. Nếu đang cố xử lý vấn đề trên máy retro, thì dùng cái này thay vì lôi máy tính hiện đại hay smartphone ra có thể cũng phần nào hợp lý.
Dùng Win32s trên Windows 3.1 thì không cần bận tâm đến mô hình bộ nhớ phân đoạn, và còn có thể chạy trên Windows 64-bit.