როგორ შევქმენით OWL — ახალი არქიტექტურა ჩვენი ChatGPT‑ზე დაფუძნებული ბრაუზერისთვის, Atlas
ჩვენი ახალი პროცესული არქიტექტურის შიგნით, რომელიც გაძლევთ ვების გამოყენების უფრო სწრაფ და ჭკვიან გზას.
ავტორები: Ken Rockot, ტექნიკური პერსონალის წევრი, და Ben Goodger, ინჟინერიის ხელმძღვანელი, ChatGPT Atlas
გასულ კვირას ჩვენ გავუშვით ChatGPT Atlas — ვებში ნავიგაციის ახალი გზა, როცა ChatGPT თქვენ გვერდითაა. სრულფასოვანი ვებბრაუზერის გარდა, Atlas გვაძლევს მომავალის ხედვას: სამყაროს, სადაც შეგიძლიათ ChatGPT თან წაიყვანოთ მთელ ინტერნეტში, დაუსვათ კითხვები, მიიღოთ შეთავაზებები და შეასრულებინოთ ამოცანები. ამ პოსტში ვხსნით პროდუქტის ერთ-ერთ ყველაზე რთულ საინჟინრო ასპექტს: როგორ ვაქციეთ ChatGPT ბრაუზერად, რომელიც გზაში სულ უფრო სასარგებლო ხდება.
იმისთვის, რომ ChatGPT ვებისთვის ნამდვილ თანამფრენად გვექცია, საჭირო გახდა ბრაუზერის მთელი არქიტექტურის თავიდან გააზრება: Atlas-ის Chromium runtime-ისგან გამიჯვნა. ეს გულისხმობდა Chromium-ის ინტეგრაციის ახალი გზის შექმნას, რომელიც საშუალებას გვაძლევს მივაღწიოთ ჩვენს პროდუქტის მიზნებს: მყისიერი გაშვება, რეაგირება მაშინაც კი, როცა მეტ ჩანართს ხსნით, და აგენტურ გამოყენების შემთხვევებისთვის ძლიერი საფუძვლის შექმნა.

Chromium ბუნებრივი სამშენებლო ბლოკი იყო. ის გვაძლევს უახლესი დონის ვებძრავს ძლიერი უსაფრთხოების მოდელით, დადასტურებული წარმადობით და შეუდარებელი ვებთავსებადობით. უფრო მეტიც, მას ავითარებს გლობალური საზოგადოება, რომელიც მუდმივად აუმჯობესებს მას. ეს თანამედროვე დესკტოპ ვებბრაუზერებისთვის გავრცელებული არჩევანია.
ჩვენს ნიჭიერ დიზაინის გუნდს ჰქონდა ამბიციური მიზნები მომხმარებლის გამოცდილებისთვის, მათ შორის მდიდარი ანიმაციები და ვიზუალური ეფექტები ისეთი ფუნქციებისთვის, როგორიცაა Agent mode. ამისთვის ჩვენს საინჟინრო გუნდს UI-სთვის უნდა გამოეყენებინა ყველაზე თანამედროვე ნატიური ფრეიმवर्कები (SwiftUI, AppKit და Metal) იმის ნაცვლად, რომ უბრალოდ გადაეკეთებინა ღია კოდის Chromium UX. შედეგად, Atlas-ის UI მთელი აპლიკაციის UX-ის სრულყოფილი თავიდან აგებაა.
ასევე გვქონდა სხვა პროდუქტის მიზნებიც, მაგალითად სწრაფი გაშვების დრო და ასობით ჩანართის მხარდაჭერა წარმადობის დაკლების გარეშე. ამ მიზნების მიღწევა რთული იყო Chromium-ის სტანდარტული კონფიგურაციით, რადგან მას მკაფიო პოზიცია აქვს მრავალ დეტალზე — გაშვების თანმიმდევრობიდან, threading model-იდან და tab model-ებიდან. განვიხილავდით ამ მხრივ არსებით ცვლილებებს, მაგრამ გვინდოდა, Chromium-ის მიმართ ჩვენი პაჩების ნაკრები მიზნობრივი დაგვეტოვებინა, რათა ახალი ვერსიების ინტეგრირება სწრაფად შეგვეძლო. იმისთვის, რომ განვითარების სიჩქარე მაქსიმალურად დაგვეჩქარებინა, Chromium runtime-ის ინტეგრაციისა და მართვის განსხვავებული გზა უნდა მოგვეფიქრებინა.
ჩვენი ტექნიკური ინვესტიციის ლაკმუსის ტესტი მხოლოდ ის არ იყო, რომ ის უფრო სწრაფ ექსპერიმენტირებას, იტერაციას და ახალი ფუნქციების მიწოდებას შესაძლებელს გახდიდა — ის ასევე უნდა დახმარებოდა OpenAI-ის საინჟინრო კულტურის ძირითადი ნაწილის შენარჩუნებაში: გამოშვება პირველივე დღეს. ყოველი ახალი ინჟინერი თავის პირველ დღესვე, შუადღის შემდეგ, აკეთებს და აერთიანებს პატარა ცვლილებას. უნდა დაგვერწმუნებინა, რომ ეს შესაძლებელი დარჩებოდა მაშინაც კი, როცა Chromium-ის checkout-სა და build-ს საათები სჭირდება.
ამ გამოწვევებზე ჩვენი პასუხი იყო ახალი არქიტექტურული ფენის შექმნა, რომელსაც ვუწოდებთ OWL: OpenAI’s Web Layer. OWL არის Chromium-ის ჩვენი ინტეგრაცია, რაც გულისხმობს Chromium-ის browser process-ის გაშვებას მთავარი Atlas აპის process-ის გარეთ.
ასე იფიქრეთ: Chromium-მა ბრაუზერები რევოლუციურად შეცვალა იმით, რომ ჩანართები ცალკე პროცესებში გადაიტანა. ჩვენ ამ იდეას კიდევ უფრო ვავითარებთ — თავად Chromium გამოგვაქვს მთავარი აპლიკაციის process-იდან და გადაგვაქვს იზოლირებულ service layer-ში. ეს ცვლილება ბევრ სარგებელს ხსნის:
- უფრო მარტივი, თანამედროვე აპი: Atlas თითქმის მთლიანად SwiftUI-სა და AppKit-შია აგებული. ერთი ენა, ერთი ტექნოლოგიური სტეკი, ერთი სუფთა კოდის ბაზა.
- უფრო სწრაფი გაშვება: Chromium ფონურად, ასინქრონულად იტვირთება. Atlas არ ელოდება — პიქსელები ეკრანზე თითქმის მყისიერად ჩნდება.
- ჩახარვეზებისა და კრაშებისგან იზოლაცია: Chromium ძლიერი და რთული ვებძრავია. თუ მისი მთავარი თრედი გაიჭედა, Atlas არა. თუ ის დაიკრაშა, Atlas მუშაობას აგრძელებს.
- ნაკლები merge-ის სირთულე: რადგან Chromium-ის ღია კოდის UI-ის დიდ ნაწილზე არ ვაშენებთ, upstream Chromium-თან ჩვენი diff ბევრად პატარაა და მოვლაც უფრო მარტივია.
- უფრო სწრაფი იტერაცია: ინჟინრების უმეტესობას Chromium-ის ლოკალურად აგება საერთოდ არ სჭირდება. OWL შიდა გამოყენებისთვის წინასწარ აგებულ ბინარულ ფაილად მიეწოდება, ამიტომ Atlas-ის build-ს საათების ნაცვლად წუთები სჭირდება.
რადგან ჩვენი გუნდის ინჟინრების უმეტესობა Chromium-ს წყაროდან რეგულარულად არ აგებს, განვითარება გაცილებით სწრაფად მიდის — ახალ წევრებსაც კი შეუძლიათ მარტივი ცვლილებების merge თავიანთ პირველივე შუადღეს.
მაღალ დონეზე, Atlas ბრაუზერი არის OWL Client, ხოლო Chromium-ის browser process არის OWL Host. ისინი ურთიერთობენ IPC-ის საშუალებით, კერძოდ Mojo(იხსნება ახალ ფანჯარაში)-ს მეშვეობით — Chromium-ის საკუთარი message-passing სისტემა. ჩვენ Mojo-სთვის დავწერეთ Swift-ის (და TypeScript-ისაც კი) საკუთარი binding-ები, რათა ჩვენს Swift აპს host-ის მხარის ინტერფეისების პირდაპირ გამოძახება შეეძლოს.
OWL client library ავრცელებს მარტივ საჯარო Swift API-ს, რომელიც აბსტრაქტავს host-ის service layer-ის მიერ გამოტანილ რამდენიმე მთავარ კონცეფციას:
- Session: host-ის გლობალურად კონფიგურაცია და კონტროლი
- Profile: ბრაუზერის მდგომარეობის მართვა კონკრეტული მომხმარებლის პროფილისთვის
- WebView: ცალკეული ვებკონტენტის კონტროლი და ჩაშენება (მაგ. რენდერი, შეყვანა, ნავიგაცია, მასშტაბირება და ა.შ.)
- WebContentRenderer: შეყვანის მოვლენების გადაცემა Chromium-ის რენდერის მილსადენში და renderer-ისგან უკუკავშირის მიღება
- LayerHost/Client: UI-სა და Chromium-ს შორის კომპოზიტური ინფორმაციის გაცვლა
არსებობს ასევე service endpoint-ების ფართო სპექტრი მაღალი დონის ფუნქციების სამართავად, როგორიცაა სანიშნები, ჩამოტვირთვები, გაფართოებები და autofill.
WebView-ები, რომლებიც client app-ში ერთმანეთის გამომრიცხავ საპრეზენტაციო სივრცეს იზიარებს, მონაცვლეობით თავსდება საერთო კომპოზიტურ კონტეინერში და იქიდან გამოდის. მაგალითად, ბრაუზერის ფანჯარას ხშირად აქვს ერთი საერთო ხილული კონტეინერი და ჩანართების ზოლში ჩანართის არჩევა ამ ჩანართის WebView-ს კონტეინერში ცვლის. Chromium-ის მხარეს ეს კონტეინერი შეესაბამება gfx::AcceleratedWidget-ს, რომელიც საბოლოოდ CALayer-ზეა დაფუძნებული. ამ layer-ის context ID-ს client-ს ვაძლევთ, სადაც NSView მას კერძო CALayerHost API-ის გამოყენებით აჩაშენებს.
განსაკუთრებული შემთხვევები, როგორიცაა <select> ჩამოსაშლელი მენიუები ან ფერის ამრჩევები, რომლებსაც Chromium ცალკე popup widget-ებში არენდერებს, იმავე მიდგომას იყენებს. მათ არ აქვთ content::WebContents, მაგრამ აქვთ საკუთარი content::RenderWidgetHostView თავისი gfx::AcceleratedWidget-ით, ამიტომ იგივე delegated rendering model აქაც მოქმედებს.
OWL შიგნით view-ის გეომეტრიას Chromium-ის მხარესთან სინქრონში ინახავს, რათა GPU compositor შესაბამისად განახლდეს და ყოველთვის სწორი ზომისა და მოწყობილობის მასშტაბის layer-ის შიგთავსი შექმნას.
ამ ტექნიკას ასევე ვიყენებთ Chromium-ის საკუთარი ნატიური Views UI-ის ელემენტების Atlas-ში შერჩევითად პროეცირებისთვის (ეს ასევე გამოსადეგია ისეთი ფუნქციების სწრაფად ასაწყობად, როგორიცაა permission prompt-ები, მათთვის SwiftUI-ში თავიდანვე ჩანაცვლებების აშენების გარეშე). ეს ტექნიკა დიდწილად ეყრდნობა Chromium-ის უკვე არსებულ ინფრასტრუქტურას macOS-ზე დასაყენებელი ვებაპებისთვის.
Chromium UI პლატფორმის მოვლენებს (მაგალითად, macOS NSEvent-ებს) გარდაქმნის Blink-ის WebInputEvent მოდელად, სანამ მათ renderer-ებს გადაუგზავნის. მაგრამ რადგან OWL Chromium-ს დამალულ პროცესში ამუშავებს, ამ გარდაქმნას ჩვენ თვითონ ვაკეთებთ Swift client library-ში და Chromium-ს უკვე გარდაქმნილ მოვლენებს ვუგზავნით.
ამის შემდეგ, ისინი იმავე სიცოცხლის ციკლს მიჰყვება, რომელსაც ჩვეულებრივ რეალური შეყვანის მოვლენები მიჰყვებოდა ვებკონტენტისთვის. ეს მოიცავს მოვლენების client-ში დაბრუნებასაც, როცა გვერდი მიუთითებს, რომ მოვლენას ვერ დაამუშავა. როცა ეს ხდება, ჩვენ ხელახლა ვასინთეზებთ NSEvent-ს და აპის დანარჩენ ნაწილს შეყვანის დამუშავების შანსს ვაძლევთ.
Atlas-ის აგენტური დათვალიერების ფუნქცია ჩვენს მიდგომებს რენდერის, შეყვანის მოვლენების გადაგზავნისა და მონაცემთა შენახვის მხრივ რამდენიმე უნიკალურ გამოწვევას უქმნის.
ჩვენი კომპიუტერის გამოყენების მოდელი შეყვანად ეკრანის ერთ სურათს ელოდება. მაგრამ ზოგი UI ელემენტი, როგორიცაა <select> ჩამოსაშლელი მენიუები, ჩანართის საზღვრებს გარეთ ცალკე ფანჯრებში რენდერდება. agent mode-ში ამ popup-ებს ისევ მთავარი გვერდის სურათში ვაკომპოზიტებთ სწორ კოორდინატებზე, რათა მოდელმა სრული კონტექსტი ერთ კადრში დაინახოს.
შეყვანისთვის იმავე პრინციპს ვიყენებთ: აგენტის მიერ გენერირებული მოვლენები პირდაპირ renderer-ს მიეწოდება და არასოდეს გადის პრივილეგირებული ბრაუზერის ფენაში. ეს ინარჩუნებს sandbox-ის საზღვარს ავტომატიზებული კონტროლის დროსაც კი. მაგალითად, არ გვინდა, რომ ამ კლასის მოვლენებმა ისეთი კლავიატურის მალსახმობები დაასინთეზოს, რომლებიც ბრაუზერს ვებკონტენტთან დაუკავშირებელ ქმედებებს გააკეთებინებს.
აგენტური დათვალიერება ასევე შეიძლება გაეშვას ეფემერულ „გასული“ კონტექსტში. იმის ნაცვლად, რომ მომხმარებლის არსებული Incognito პროფილი გაგვეზიარებინა, რაც მდგომარეობის გაჟონვას გამოიწვევდა, ვიყენებთ Chromium-ის StoragePartition ინფრასტრუქტურას იზოლირებული, მეხსიერებაში არსებული საცავების ასაწევად. ყოველი აგენტის სესია თავიდან იწყება და დასრულებისას ყველა cookie და საიტის მონაცემი იშლება. შეგიძლიათ რამდენიმე „გასული“ აგენტის სესია გაუშვათ, თითოეული თავის ბრაუზერის ჩანართში და თითოეული სრულად იზოლირებული სხვებისგან.
ეს ყველაფერი შეუძლებელი იქნებოდა Chromium-ის გლობალური საზოგადოების და მათი საოცარი მუშაობის გარეშე, რომლებმაც თანამედროვე ვებისთვის საფუძველი შექმნეს. OWL ამ საფუძველს ახალად იყენებს: ძრავის აპიდან განცალკევებით, მსოფლიო დონის ვებპლატფორმის თანამედროვე ნატიურ ფრეიმवर्कებთან შერწყმით და უფრო სწრაფი, მოქნილი არქიტექტურის გახსნით.
იმის ხელახლა გააზრებით, თუ როგორ იტევს ბრაუზერი Chromium-ს, ჩვენ ვქმნით სივრცეს ახალი ტიპის გამოცდილებებისთვის: უფრო რბილი გაშვება, უფრო მდიდარი UI, OS-ის დანარჩენ ნაწილთან უფრო მჭიდრო ინტეგრაცია და განვითარების ციკლი, რომელიც იდეების სიჩქარით მოძრაობს. თუ ეს თქვენთვის საინტერესო გამოწვევად ჟღერს, გაეცანით ჩვენს ვაკანსიებს Atlas-ზე სამუშაოდ როგორც Software Engineer, Atlas, Software Engineer, iOS და სხვა.
სცადეთ Atlas მისამართზე chatgpt.com/atlas(იხსნება ახალ ფანჯარაში).
მადლობები
განსაკუთრებული მადლობა Darin Fisher-ს და Marie Shin-ს, რომლებმაც წვლილი შეიტანეს ამ პოსტში, ასევე OpenAI-ის მთელ გუნდს, რომელმაც Atlas შექმნა.


