WinGPT ผู้ช่วย AI สำหรับ Windows 3.1
(dialup.net)- WinGPT เป็นโปรเจกต์ที่พยายามรันแชตบอตบนพื้นฐาน OpenAI API ได้แม้บน Windows 3.1 โดยมุ่งเน้นการเรียกใช้บริการ AI สมัยใหม่จากพีซีเก่าอย่างเครื่อง 386
- การพัฒนาทำบนพื้นฐาน C และ Windows API มาตรฐาน และด้วย Open Watcom v2 จึงสามารถบิลด์สำหรับ Windows แบบ 16 บิตได้แม้บน Windows 11
- เชื่อมต่อกับเซิร์ฟเวอร์ OpenAI API โดยตรงผ่าน TLS 1.3 โดยไม่ใช้พร็อกซี แต่ระบุไว้อย่างชัดเจนว่าการใช้งาน TLS นี้ไม่ใช่การใช้งานที่ปลอดภัย
- คอนโทรล UI พื้นฐานของ Windows 3.1 มีข้อจำกัดมาก จึงต้องสร้างองค์ประกอบอย่างแถบสถานะเอง หรือปรับแก้โค้ด public domain เก่า
- เนื่องจากข้อจำกัดด้านหน่วยความจำ จึงขอให้ตอบกลับแบบสั้นและไม่ส่งรอบสนทนาก่อนหน้าไปด้วย ทำให้ไม่สามารถรักษา บริบทการสนทนา ได้
การทดลองเรียก OpenAI API บน Windows 3.1
- WinGPT เป็นผู้ช่วย AI สำหรับ Windows 3.1 ที่นำเสนอการใช้งานอย่างการถามตอบผ่าน OpenAI API, เล่าเรื่องตลก, และร่างเอกสารหรือสเปรดชีต
- ในเชิงอรรถระบุว่าคำอธิบายนี้เป็น การเสียดสี และไม่ควรพึ่งพาฟีเจอร์เหล่านี้ เพราะไม่สามารถทำได้อย่างเชื่อถือได้
- การพัฒนาทำบนพื้นฐาน C และ Windows API มาตรฐาน
- ใช้คอมไพเลอร์ Open Watcom v2
- Open Watcom v2 สามารถ cross-compile สำหรับ Windows แบบ 16 บิตได้แม้บน Windows 11
- เชื่อมต่อกับเซิร์ฟเวอร์ OpenAI API โดยตรงผ่าน TLS 1.3
- ไม่จำเป็นต้องมีพร็อกซีที่ terminate TLS บนเครื่องสมัยใหม่
- ใน “Modern TLS on 16-bit Windows” กล่าวถึงวิธีการพัฒนาและความยากลำบาก พร้อมระบุชัดเจนว่าการใช้งาน TLS นี้ไม่ปลอดภัย
ความยากในการพัฒนา UI จาก Windows API รุ่นเก่า
- หากใช้เฉพาะ Windows API พื้นฐานบน Windows 3.1 ความสามารถในการ สร้าง UI จะจำกัดมาก
- UI ส่วนใหญ่ถูกสร้างขึ้นโดยตรงในโค้ด C และยังต้องเขียนลอจิก resize เพื่อให้แต่ละคอมโพเนนต์คงขนาดที่ถูกต้องเมื่อปรับขนาดหน้าต่าง
- คอนโทรลมาตรฐานจำกัดอยู่ประมาณ push button, check box, radio button และ edit box
- ข้อจำกัดของ Windows 3.1 เห็นได้ชัดเป็นพิเศษในการทำ แถบสถานะ
- File Manager และ Control Panel มีแถบสถานะ แต่ Microsoft ไม่ได้เปิดให้ผู้พัฒนาแอปทั่วไปใช้อย่างแพร่หลายจนกว่าจะถึง Windows 95
- เมื่อถาม ChatGPT ถึงวิธีใช้แถบสถานะ มันเสนอไฟล์ header ที่มีเฉพาะใน Windows เวอร์ชันถัดมา และเมื่อถามซ้ำก็สร้างชื่อไลบรารี UI ที่ดูเหมือนไม่มีอยู่จริงขึ้นมา
- สุดท้ายจึงใช้ status bar implementation ของ Philip J. Erdelsky ในปี 1997 และปรับแก้ให้ใกล้เคียงกับแถบสถานะของโปรแกรม Microsoft มากขึ้นในระดับพิกเซล
- ไอคอนสร้างด้วย Borland Image Editor
- ไอคอนโปรแกรมของ Windows 3.1 มีขนาด 32x32 และแสดงใน Program Manager กับตัวสลับงาน
- ยังสร้างไอคอน 16x16 แยกต่างหากสำหรับแสดงใน Windows เวอร์ชันถัดมา
ข้อจำกัดด้านหน่วยความจำและเงื่อนไขการรัน
- เนื่องจาก ข้อจำกัดด้านหน่วยความจำ ของเครื่อง Windows 3.1 จึงต้องลดการใช้หน่วยความจำในการส่งคำขอ API และประมวลผลคำตอบ
- การตอบกลับ JSON ของ API สมัยใหม่ไม่ได้ถูกปรับให้มีขนาดเล็ก และ OpenAI API ก็ไม่ใช่ข้อยกเว้น
- เพื่อให้คำตอบมีขนาดเล็ก จึงขอให้โมเดลตอบแบบสั้น
- เนื่องจากไม่ได้รวมข้อความจากรอบสนทนาก่อนหน้าในการเรียก API จึงไม่สามารถใช้บริบทการสนทนาก่อนหน้าได้
- WinGPT ใช้ไลเซนส์ GNU GPL v2
- ทำงานได้บน Windows แบบ 16 บิตหรือ 32 บิตหลัง Windows 3.1
- ต้องมีการใช้งาน Winsock และทดสอบแล้วบน Windows 3.11 for Workgroups ที่ติดตั้ง Microsoft TCP/IP-32 3.11b และบน Windows 2000 แบบพื้นฐาน
- ไม่ทำงานบน Windows 64 บิต แต่สามารถรันบน Wine ได้
- หากต้องการสื่อสารกับ OpenAI ต้องมี OpenAI API key และหลังรันโปรแกรมให้กรอก secret key ที่
File | Options... - ดาวน์โหลด: Binaries for 16-bit and 32-bit Windows
- ซอร์สรวมอยู่ใน modified WolfSSL source code โดยอยู่ที่
watcom16/wingpt
2 ความคิดเห็น
55555555555555555555
ความเห็นจาก Hacker News
น่าจะเอาไปใส่ใน MS Office เวอร์ชันยุคนั้นได้เหมือนกัน
ตอนนั้นอาจทำเป็นตัวละครสคิวมอร์ฟิกที่ทำให้เครื่องใช้สำนักงานจริงดูเหมือนมีชีวิตก็ได้ เช่น ยางลบ… หรือว่า… คลิปหนีบกระดาษอะไรแบบนั้น…
มีงานอีกส่วนหนึ่งที่ทำให้ TLS 1.2 และ 1.3 ใช้งานบน Windows 3.1 ได้ เพื่อให้ WinGPT เชื่อมต่อกับเซิร์ฟเวอร์ OpenAI ได้โดยตรงโดยไม่ต้องพึ่งการปิดปลายทาง TLS บนเครื่องสมัยใหม่: https://www.dialup.net/wingpt/tls.html
น่าอ่านมากทีเดียว หลายครั้งในสภาพแวดล้อมฝังตัวลึกแบบ IoT หรือแม้แต่บน CPU 8 บิตที่ใช้ bank switching ก็ยังรองรับ TLS 1.2 กันได้อยู่ เลยค่อนข้างน่าแปลกใจที่การยัด implementation ของ TLS ลงในโค้ดและข้อมูลแค่ 64KB จะยากขนาดนั้น
มันน่าเศร้านิด ๆ ที่ระบบปฏิบัติการเก่า ๆ เข้าถึงอินเทอร์เน็ตได้ยาก
คิดถึงยุค Windows 3.1, 95, 98 มาก อินเทอร์เฟซหลังจากนั้นเหมือนจะแย่ลงเรื่อย ๆ
ทุกครั้งที่เปิด 386 หรือ Pentium ขึ้นมาก็ยังทึ่งว่า GUI มันสะอาดตาและกดดันน้อยแค่ไหน เบื่อเต็มทีกับ นรกป๊อปอัปคอนทราสต์ต่ำ แบบ Apple/Google
ทุกวันนี้พอทำ localization แล้ว UI ครึ่งจอกลับมีป้ายอย่าง "Tap to...." โผล่มา แปลกดีที่เครื่องมือ UI สุดล้ำสมัยกับเหล่านักพัฒนาระดับดาวเด่นจำนวนมากยังทำ sidebar ที่ลากปรับได้สักอันไม่ได้
ถ้าจะแลกพื้นที่กับเวลา CPU ก็ใช้ การ parse แบบ SAX ได้
การ parse แบบ SAX จะไล่ต้นไม้จากบนลงล่างและยิง event ตอนเจอแต่ละโหนด หน่วยความจำที่ต้องใช้แทบไม่มีนัยสำคัญเมื่อเทียบกับการ parse JSON แบบเต็มรูป และการเขียน parser JSON แบบ SAX เองก็ดูไม่น่ายากมากนัก ยังมี parser JSON แบบ SAX ที่มีอยู่แล้วให้อ้างอิงได้ด้วย
[1]: https://en.wikipedia.org/wiki/Simple_API_for_XML
[2]: https://rapidjson.org/md_doc_sax.html
ใช่เลย ตอนนี้ใช้ JSMN(https://github.com/zserge/jsmn) อยู่ ซึ่งเป็น streaming parser ที่ไล่ดูแต่ละ token ตามลำดับ ทำให้มีสำเนา JSON response อยู่ในหน่วยความจำเพียงชุดเดียว
พยายามหลีกเลี่ยงการจัดสรรหน่วยความจำชั่วคราวใหม่ให้มากที่สุดด้วย เช่น เวลา unescape backslash escape ในสตริง JSON ก็ใช้ ลูปแบบทำลายข้อมูลเดิม โดยย้ายอักขระที่ไม่ใช่ backslash มาทางด้านหน้าของหน่วยความจำ แล้วเลื่อน null terminator เข้ามาด้านหน้าเพื่อตัดสตริง วิธีแบบนี้ในปัจจุบันแทบไม่ค่อยทำกันแล้ว แต่ก็อย่างที่ว่า คือยอมใช้เวลา CPU เพื่อประหยัดพื้นที่ได้อีกนิด :)
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';
}
เป็นไปได้สูงว่าโครงสร้างพื้นฐานที่รองรับ text box control ที่ฉันกำลังพิมพ์อยู่นี้ตอนนี้ จะกินทรัพยากรระบบมากกว่า WinGPT ทั้งตัว เสียอีก
มันชี้ให้เห็นว่าเราเผาหน่วยความจำกันแบบคนละหลักเพียงเพื่อเพิ่ม productivity ของนักพัฒนาเล็กน้อย การเขียนโปรแกรมด้วย Windows controls ล้วน ๆ นั้นยากก็จริง แต่ Delphi หรือ VB บน Win95 ก็อาจถือว่า productive กว่า UI toolkit สมัยใหม่มาก และแอปที่ได้ก็ใช้ทรัพยากรน้อยกว่ามาก สิ่งที่ขาดจริง ๆ มีแค่การรองรับมือถือกับการรับรู้ DPI เท่านั้น
คำว่า "เพิ่ม productivity ของนักพัฒนาเล็กน้อย" นี่พูดน้อยไปมากถ้าพูดกันตรง ๆ
สิ่งที่เมื่อก่อนตอนเด็ก ๆ ต้องลำบากเขียนด้วย native code เดี๋ยวนี้แทบใครก็ทำได้ด้วยไลบรารีและเครื่องมือสำเร็จรูปที่เจาะเว็บเบราว์เซอร์โดยเฉพาะ ซึ่งในตัวมันเองก็เป็นความสำเร็จที่น่าทึ่งและไม่ใช่เรื่องแย่ สิ่งที่น่าเสียดายที่สุดคือเมื่อเบราว์เซอร์กลายเป็นตัวเลือกที่ "ดีกว่า" โดยรวม มันก็กำลังฆ่า native app ไปด้วย
ทุกวันนี้บริษัทซอฟต์แวร์มองเป็นเรื่องปกติว่าต้องเปิดให้เข้าถึงบริการเครือข่ายผ่านเว็บ จึงเริ่มทำเว็บก่อน แล้วค่อยพยายามรองรับ iPhone, Windows, Android, macOS และ Linux ต่อ แม้จะมีตัวเลือกที่ช่วยครอบคลุมหลายแพลตฟอร์มได้บ้าง แต่พอถึงจุดนั้นก็มี proof of concept บนเบราว์เซอร์อยู่แล้ว และแค่ติดตั้ง NPM ครั้งเดียวก็แพ็กส่งเป็นแอปหน้าต่างแยกพร้อมตัวติดตั้งและระบบแจกจ่ายได้ ถึงจะไม่ยอดเยี่ยม แต่ก็พอทำได้
ถ้ามี เฟรมเวิร์ก GUI แบบเนทีฟที่มีประสิทธิภาพและคุณภาพระดับ production ซึ่งสามารถรองรับ DOM และ native UI ของ Windows, macOS, Android, iPhone ได้อย่างมีประสิทธิผล พร้อมรองรับการป้อนข้อความแบบเนทีฟที่มี IME และความหมายเชิงแพลตฟอร์มเฉพาะ การเข้าถึงร่วมกับ screen reader การปรับ UI แบบ responsive ตามขนาดหน้าจอที่หลากหลาย และองค์ประกอบภาพที่เป็นอิสระจาก DPI ซึ่งทั้งแข็งแรงและเร็ว รวมถึงจัดการสเกลแบบเศษส่วนได้อย่างถูกต้อง ปัญหาก็คงน้อยกว่านี้มาก งานง่ายเลยเนอะ?
แต่ก็ไม่มีอะไรแบบนั้น ผมชอบ Delphi VCL หรือ Win32 ล้วน ๆ แต่นั่นก็ยังตอบโจทย์ได้ไม่ครบเป็นส่วนใหญ่ การรองรับทุกแพลตฟอร์มเหล่านี้เป็นเรื่องยากมาก เบราว์เซอร์ทำเรื่องนี้ได้ค่อนข้างดี และยังเป็นหนึ่งในแหล่งโค้ดตัวอย่างที่ดีที่สุดสำหรับใช้อ้างอิงเวลาเขียนโค้ดเชิงลึกเฉพาะแพลตฟอร์มด้วย อีกอย่าง ไม่ว่าอย่างไรเป้าหมายส่วนใหญ่ก็ยังเป็นเว็บอยู่ดี และเอนจินเบราว์เซอร์ก็เป็น "native code" ด้วย ดังนั้นแทนที่จะสร้างวิธีแก้แบบ native code ที่เป็นเนื้อเดียวกันและรันได้ในสภาพแวดล้อมเบราว์เซอร์ การแจกจ่ายเบราว์เซอร์หรืออย่างน้อยเอนจิน JS ไปพร้อมกับแพลตฟอร์มที่รัน native code ได้อยู่แล้วจึงง่ายกว่ามาก
ช่วยขยายความส่วนที่ว่า "อาจมองได้ว่ามีประสิทธิภาพมากกว่ามาก" ได้ไหม?
แนวคิดเรื่อง การแจกจ่ายซอฟต์แวร์ ก็ควรถูกรวมอยู่ในคำว่าประสิทธิภาพด้วย ในยุคนั้น Delphi/VB เพิกเฉยต่อคำถามนี้ไปอย่างสิ้นเชิงตามมาตรฐานของยุคนั้น
ถ้าเป็นยูทิลิตี zip ง่าย ๆ ก็แค่คัดลอก EXE ไฟล์เดียวไปไว้ที่ไหนสักแห่งบน network mount ใน LAN หลังไฟร์วอลล์ก็จบแล้ว Windows มีระบบคล้ายไฟล์ซิสเต็มอยู่ในไบนารีสำหรับโหลดไอคอนและสตริง และนั่นก็เพียงพอแล้ว แต่ถ้าเป็นแอปที่ซับซ้อนกว่านั้นซึ่งต้องใช้ DLL และรายการในรีจิสทรี คุณต้องจ่ายหลายร้อยดอลลาร์เพื่อซื้อ InstallShield และไปเรียน InstallScript ไม่มีทางสายกลางจนกว่า MSI และ WiX จะออกมา และจนถึงกลางทศวรรษ 1990 Microsoft ก็ยังมองอินเทอร์เน็ตเป็นเหมือนกระแสแปลกใหม่จากแดนไกล และคิดว่าการแจกจ่ายซอฟต์แวร์ผ่านเครือข่ายไม่ใช่เรื่องใช้การได้จริงเพราะแบนด์วิดท์ต่ำ ซอฟต์แวร์มีไว้สำหรับ CD-ROM และการส่งมอบคือการขนส่งกันจริง ๆ
ปัญหาคือผู้คนให้ความสำคัญกับ ความเร็วของการวนซ้ำ มากกว่าประสิทธิภาพล้วน ๆ แทบจะเหนือทุกอย่าง โลกเปลี่ยนเร็วกว่า Delphi เสียอีก Borland อาจสังเกตได้ว่ากระแสการฝืนใช้เบราว์เซอร์ให้เป็นแอปนั้นสะท้อนความต้องการพื้นฐานที่ผู้ใช้ไม่ได้พูดออกมาตรง ๆ และอาจสร้างอะไรอย่างอินเทอร์พรีเตอร์ Object Pascal ขึ้นมาได้ เช่น ถ้าทำ "Delphi Browser" ออกมา มันก็น่าจะถูกนำไปใช้ แต่โค้ดเบสของมันถูกออกแบบมาเพื่อการผลิตแอป Windows แบบ native โดยพื้นฐาน ทำให้การเปลี่ยนทิศทางแบบนั้นทำได้ยาก อีกทั้ง Borland ก็อยู่ในสถานะคล้ายแขกบนแพลตฟอร์ม Windows และมักเดินตามทิศทางของ Microsoft ฝั่ง Microsoft ผลักดัน ActiveX ให้เป็นสะพานเชื่อมโลกเว็บกับโลก Windows และ Borland ก็ตระหนักช้าเกินไปว่า ActiveX จะไม่ตอบโจทย์สิ่งที่ผู้คนต้องการ ตอนแรกพวกเขาไม่ได้มองเว็บเป็นคู่แข่ง ต่อมามองว่าเป็นเพียงพาหะขนส่งสำหรับแอป Delphi และหลังจากนั้นก็ผลักดันให้ใช้ Delphi ทำเว็บเซิร์ฟเวอร์ ทั้งที่จุดแข็งของมันไม่ได้อยู่ตรงนั้น
บทเรียนที่ได้จากเรื่องนี้คือ ความชอบที่ไม่ได้ถูกพูดออกมา ซึ่งต้องเรียนรู้จากการดูว่าผู้คนทำอะไรจริง ไม่ใช่ฟังว่าเขาพูดอะไร และคือความสำคัญอย่างท่วมท้นของการแจกจ่ายซอฟต์แวร์ การแจกจ่ายยังคงเป็นจุดบอดของคู่แข่งฝั่งเว็บส่วนใหญ่ในปัจจุบันด้วย จนถึงปีที่แล้ว แทบไม่มีแพลตฟอร์มที่คล้าย Delphi ซึ่งมีการแจกจ่ายแบบเว็บที่รีเฟรชทุกครั้งที่รันแอป แม้แต่ Electron ก็ยังให้เพียงการอัปเดตแบบเดสก์ท็อปที่ไม่เป็น synchronous อย่างสมบูรณ์ ผมบริหารบริษัทเล็ก ๆ ที่ทำผลิตภัณฑ์เพื่อแก้ปัญหาการแจกจ่ายแอปเดสก์ท็อปภายใต้ข้อจำกัดของแพลตฟอร์ม native และได้เพิ่มโหมดการแจกจ่ายแบบเว็บชื่อ aggressive updates (https://hydraulic.dev/) ในโหมดนี้จะตรวจสอบอัปเดตทุกครั้งที่รัน จึงทำให้วนซ้ำได้เร็วมาก หากคุณสามารถให้ผู้ใช้รีสตาร์ตแอปเป็นครั้งคราว หรือบังคับรีสตาร์ตในเวลาที่เหมาะสมได้ มันไม่ต่างจากการบอกให้ปิดแท็บแล้วโหลดใหม่ใน SPA
เพราะอย่างนั้นผมจึงไม่เห็นด้วยว่าหัวใจสำคัญที่ขาดไปคือมือถือกับ DPI เพราะ Delphi, VB, GTK, Cocoa และอื่น ๆ แพ้บนเดสก์ท็อปไปก่อนแล้วตั้งแต่ก่อนที่สมาร์ตโฟนจะสำคัญเสียอีก พวกมันไม่มีระบบแจกจ่ายและอัปเดตที่ดี และความสามารถในการผลักการแก้ไขและการเปลี่ยนแปลงออกไปได้ทันทีนั้นสำคัญกว่าฟีเจอร์อื่นทั้งหมดรวมกัน
ความก้าวหน้าทางเทคโนโลยีกำลังเร็วขึ้นมาก จนดูเหมือนว่าเราเริ่มเผชิญ culture shock ที่เกิดจากวัฒนธรรมของเราเอง หรือก็คือ future shock แล้ว ความเร็วนี้จะยิ่งเพิ่มขึ้นอีกในช่วงชีวิตของเรา
กลับมาดูซอฟต์แวร์ Windows 3.1 แล้วรู้สึกดีมาก สำหรับคนชอบของย้อนยุค ขอแปะอันนี้ไว้ด้วย: https://www.xfce-look.org/p/1016410
ส่วนที่น่าประทับใจที่สุดคือ native TLS
จำได้ว่าเคยได้ยินว่าระบบเข้ารหัสสมัยใหม่ใช้กับ CPU เก่า ๆ ไม่ได้ เพราะปริมาณการคำนวณตัวเลขที่ปรับแต่งประสิทธิภาพได้ยาก มีประมาณว่าบางขั้นตอนของอัลกอริทึมแลกเปลี่ยนกุญแจใช้เวลานานเกินไปจนเซิร์ฟเวอร์ timeout ได้ แต่ดูเหมือนบน 386 เก่าและช้ากลับไม่เป็นปัญหา?
สำหรับระบบที่ไม่มีงานแบบฝังตัว เช่น การเข้ารหัสวิดีโอแบบเรียลไทม์ อาจจะเป็นอีกเรื่อง แต่ไม่ใช่ทุกคนจะเชื่อมต่ออินเทอร์เน็ตด้วย iPhone รุ่นล่าสุด
เจ๋งมาก เดี๋ยวคงลองกับเครื่อง Windows 3.1 จริงสักเครื่องที่ผมมีอยู่ :)
ขอเสนอว่า ถ้าในกล่องโต้ตอบ Options สามารถปรับแต่ง system prompt ได้ก็น่าจะดี การตั้งค่าแบบปี 1992 สนุกดีแต่ก็จำกัดพอสมควร ถ้าคุณกำลังพยายามแก้ปัญหาบนคอมพิวเตอร์ย้อนยุค การใช้สิ่งนี้แทนการหยิบคอมพิวเตอร์สมัยใหม่หรือสมาร์ตโฟนขึ้นมา ก็อาจจะพอมีเหตุผลอยู่บ้าง
ถ้าใช้ Win32s บน Windows 3.1 คุณก็ไม่ต้องกังวลกับ segmented memory model และยังสามารถทำให้มันทำงานบน Windows 64 บิตได้