Observable Framework में दिखे दिलचस्प आइडिया
(simonwillison.net)- Observable Framework एक open source टूल है, जो अस्थायी data exploration में मजबूत notebook model से आगे जाकर तेज़ी से load होने वाले data apps, dashboards और reports को static sites के रूप में deploy करने के लिए है
- Markdown के अंदर
jscode blocks और inline expressions browser में execute होते हैं, औरnowजैसे reactive values बदलने पर संबंधित display भी अपने-आप update हो जाता है - Framework, Observable Notebooks की reactivity बनाए रखते हुए भी single Markdown file, standard JavaScript और Git-friendly workflow देता है
Inputs,d3,Plotजैसी libraries development के दौरान lazy-loaded होती हैं, और build/deploy के समय केवल referenced code ही jsdelivr CDN से अपने-आप load होता है- Data loader का उपयोग करने पर build time पर किसी भी भाषा में data तैयार कर उसे JSON·CSV जैसे static files के रूप में bundle किया जा सकता है, जिससे backend dependency कम करते हुए dashboards deploy करना संभव होता है
Data apps के लिए static site generator
- Observable Framework एक static site generator है, जो Markdown, JavaScript और ज़रूरत पड़ने पर अन्य भाषाओं को मिलाकर interactive pages में compile करता है
- इसमें पूरी क्षमता वाला hot reloading server शामिल है, इसलिए editor में file बदलकर save करते ही browser में बदलाव तुरंत दिखते हैं
- काम पूरा होने पर build command से static files का set बनाया जा सकता है
- इस file को server पर deploy किया जा सकता है
npm run deployसे Observable के authenticated sharing platform पर सीधे deploy भी किया जा सकता है
Markdown के अंदर चलने वाला JavaScript
- Framework का core design Markdown document के अंदर JavaScript डालकर interactive document बनाने का तरीका है
jsसे tagged Markdown code blocks user के browser में JavaScript के रूप में execute होते हैं- Inline expressions भी इस्तेमाल किए जा सकते हैं, और
${new Date(now)}की तरह current time को string के रूप में दिखाया जा सकता है nowएक special variable है, जो epoch के बाद से milliseconds में current time देता है और लगातार update होता रहता हैnowबदलने पर उसे reference करने वाले cells और inline expressions भी साथ में update होते हैं
- Observable Notebooks में code और Markdown अलग-अलग cells में लिखे जाते हैं, लेकिन Framework में दोनों एक ही text document के अंदर होते हैं
- Inline expressions और
jsblocks का display तरीका अलग हो सकता है- Inline expressions JavaScript object की default string representation का उपयोग करते हैं
jsblocks Observable केdisplay()function का उपयोग करते हैं, और display rules inspect/src/inspect.js में हैं
Reactive execution model बरकरार
- Observable Notebooks की core capability यानी reactivity Framework के JavaScript Markdown documents में भी बनी रहती है
- कोई cell बदलने पर उस cell पर निर्भर अन्य cells अपने-आप फिर से evaluate होते हैं
- यह तरीका Jupyter notebooks से बड़ा फर्क है, और Python notebook tool marimo की भी प्रमुख capability है
- Form inputs के साथ इस्तेमाल करने पर इसका असर बड़ा होता है
- Page में input जोड़कर उसके value को document के दूसरे हिस्सों में reference करने से real-time interaction आसानी से बनाया जा सकता है
PyPI downloads dashboard का उदाहरण
- Example dashboard Python package के अनुसार PyPI download statistics दिखाता है, और Observable Framework version 57-line Markdown document से बना है
- User
Inputs.select()सेpackagesarray में से package चुनता हैInputs.select()Framework में शामिल method है और Observable Inputs documentation में देखा जा सकता हैview()function Framework में नया जोड़ा गया feature है, जिससे input selection में बदलाव document के दूसरे code blocks में reflect होता है
packageNameकोconstके रूप में define किया गया है और page के अन्यjsblocks में इस्तेमाल किया जा सकता है- Data
d3.json()से लाया जाता है- Framework में पूरा D3 इस्तेमाल किया जा सकता है
- URL में selected package name शामिल होता है
- Data source Datasette का JSON API है
- SQLite table datasette.io/content/stats पर है, और latest PyPI package statistics के साथ दिन में एक बार update होती है
- संबंधित GitHub Actions workflow पहले के baked data लेख में cover किया गया था
- URL में
.jsonजोड़ने पर JSON return होता है- केवल specific package rows मांगी जाती हैं
- Date descending order में sort किया जाता है
- अधिकतम 1,000 rows object array के रूप में मिलती हैं
- SQLite string dates को
d3.timeParse("%Y-%m-%d")से JavaScriptDateobjects में convert किया जाता है - Chart को Framework के साथ packaged Observable Plot से render किया जाता है
- Package list Datasette के
/contentdatabase पर सीधे SQL query चलाकर लाई जाती है- Query है
select package from stats group by package order by max(downloads) desc _shape=arrayfirstresult rows के पहले column को JSON array के रूप में पाने का shortcut है
- Query है
केवल इस्तेमाल हो रहा code शामिल
- Example dashboard
Inputs,d3,Plotजैसी additional libraries इस्तेमाल करता है - Development mode में lazy loading लागू होती है
- Code केवल तब load होता है जब पहली बार किसी cell में उसे इस्तेमाल करने की कोशिश होती है
- Application build और deploy करने पर Framework केवल referenced library code को jsdelivr CDN से अपने-आप load करता है
Build time data caching
- Framework का Data loader dashboard data को build time पर तैयार करने की capability है
- Framework dashboards runtime पर
fetch()या उसके wrapper का उपयोग करके कहीं से भी data ला सकते हैं- Observable Notebooks भी इसी तरीके से काम करते हैं
- इस तरीके में dashboard performance जुड़े हुए backend पर निर्भर होती है
- Framework deployment time पर dashboard के लिए data बनाने और केवल ज़रूरी data subset को static files के रूप में bundle करने का pattern सुझाता है
- Static data files dashboard code के समान static hosting से तेज़ी से serve की जा सकती हैं
- Data loader किसी भी programming language में लिखा गया script होता है
- Build के समय Framework script execute करता है
- Script के standard output result को file के रूप में save करता है
- उदाहरण में
quakes.json.shfile मेंcurl https://earthquake.usgs.gov/earthquakes/feed/…डालने का तरीका है- Build के समय filename Framework को बताता है कि destination file
quakes.jsonहै और execute किया जाने वाला loader.shहै
- Build के समय filename Framework को बताता है कि destination file
- अगर standard output पर JSON, CSV या कोई उपयोगी format output किया जा सकता है, तो data किसी भी technology से लाया जा सकता है
Observable Notebooks से फर्क
- Observable Framework, Observable Notebooks के कई ideas और code reuse करता है, लेकिन file format और execution environment में बड़ा फर्क है
- Existing Observable Notebooks की Jupyter Notebooks की तुलना में ये विशेषताएं हैं
- Python नहीं, JavaScript इस्तेमाल करता है
- Notebook editor खुद open source नहीं है और observablehq.com पर उपलब्ध hosted product है
- Notebook को static file के रूप में export करके कहीं भी चलाया जा सकता है, लेकिन editor proprietary product है
- Cells reactive होते हैं, और कोई cell बदलने पर उस cell पर निर्भर दूसरे cells Excel की तरह अपने-आप re-evaluate होते हैं
- Reactivity model को support करने के लिए
viewofनाम का custom keyword बनाया गया, इसलिए JavaScript syntax पूरी तरह standard नहीं है - Editable notebooks complex proprietary file format हैं और Git जैसे tools के साथ अच्छी तरह fit नहीं होते, इसलिए Observable ने अपना version management और collaboration system implement किया है
- Observable Framework इस model को अधिक simple file format और open source execution environment में लाता है
- Document JavaScript blocks वाली single Markdown file है
- यह अब भी reactive है, लेकिन किसी भी text editor से edit किया जा सकता है और Git में रखा जा सकता है
- पूरा stack ISC license वाला open source है, और पूरा editing stack local machine पर चलाया जा सकता है
- Custom syntax के बिना केवल standard JavaScript इस्तेमाल करता है
Observable की दिशा में बदलाव
- Observable Framework, Observable के मौजूदा proprietary Observable Notebook editor-केंद्रित collaboration tool से developer tools की ओर अधिक झुके बदलाव जैसा दिखता है
- Observable का Twitter intro text है “The end-to-end solution for developers who want to build and host dashboards that don’t suck”
- 3 अक्टूबर 2023 की Internet Archive copy में “Build data visualizations, dashboards, and data apps that impact your business — faster.” लिखा था
- Observable Notebooks का उपयोग platform की proprietary nature और free account की limitations, खासकर free private notebooks न होने की वजह से कुछ सीमित हो सकता है
- Observable Plot जैसी open source libraries को पहले से सक्रिय रूप से इस्तेमाल की जा सकने वाली technology माना जाता है
- Observable Framework उन ideas को, जिन्होंने Observable Notebooks को आकर्षक बनाया था, open source, standard JavaScript, single text file और static deployment model के रूप में फिर से implement करता है
1 टिप्पणियां
Hacker News की राय
कुछ मायनों में Observable Framework, Mike Bostock cinematic universe का Avengers: Endgame जैसा है
d3, Observable, Observable Plot, HTL को एक साथ लाता है, और ऊपर से काफ़ी नए ideas भी जोड़ता है
Observable में पहले से AI integration है, और यह ऐसा wrapper लगता है जिससे AI चीज़ों को ज़्यादा आसानी से जोड़कर इस्तेमाल कर सके। AI के बिना strategy का मूल्यांकन वाला हिस्सा थोड़ा अटपटा लगा
आज static Jupyter Notebook को host करने या WASM के ज़रिए interactive रूप में चलाने के तरीके देखने शुरू किए, लेकिन लगता है कि ज़्यादातर use cases के लिए Observable Framework ज़्यादा ठीक बैठेगा
Observable की दिक्कत यह है कि यह d3 examples की gallery जैसा दिखता है, फिर भी उसका code उसी framework के भीतर चलने के लिए design किया गया है, इसलिए बस copy-paste नहीं किया जा सकता
d3 वैसे भी examples के बिना इस्तेमाल करने में आसान नहीं है, और खासकर versions के बीच breaking changes भी अक्सर होते हैं। फिर भी site पर कई कमाल के graphics हैं
[0] https://observablehq.com/@d3/gallery
यह मूल भाषा के इतना करीब है कि graphics दिखाने के लिए API थोड़ा जोड़कर बस JavaScript ही इस्तेमाल की जा सकती थी
इसमें ज़्यादातर top-level cell definitions को फिर से लिखना होता है
[0]: https://observablehq.com/@bumbeishvili/convert-observable-co...
ObservableHQ notebooks में यह शिकायत खास तौर पर ज़्यादा थी। वे शानदार examples होते हुए भी practically useless material बन जाते हैं। हालांकि इस बार Framework वाला हिस्सा कुछ ज़्यादा open लगता है, और कम-से-कम self-hosting संभव है, इसलिए देख रहा हूँ
ऊपर से यह लेख नए Observable Framework के बारे में है, जिसने पुराने Observable notebooks की कुछ समस्याएँ हटाई हैं, इसलिए यह comment लेख से थोड़ा हटकर है। अब तो बात ऐसी है कि “सब कुछ standard JavaScript है, custom syntax नहीं”
Framework को GitHub Pages पर deploy करना भी बहुत आसान है
steps और sample GitHub Action यहाँ लिख रखे हैं: https://notes.billmill.org/programming/observable_framework/...
लेखक ने Framework के बारे में बिल्कुल सही पकड़ा है
Observable Framework का इस्तेमाल करके एक छोटा interactive plot बनाया था(https://github.com/willmeyers/observable-ssta), और setup करने व data plot करने की प्रक्रिया अविश्वसनीय रूप से आसान थी। मेरी एकमात्र शिकायत यह है कि काश Python data loader को virtualenv इस्तेमाल करने के लिए configure किया जा सकता
Python project बनाने के बाद development server शुरू करते समय
yarn run devकी जगहpoetry run yarn run devचलाएँ, तो Python virtualenv के अंदर execute होता है। यह setup data loader में reusable और unit-testable code को custom Python package के रूप में define करने देता है, फिर*.json.pyfiles में import करके उन्हें बहुत simple रखा जा सकता हैnode और npm/yarn जैसे tools, और JavaScript तक, venv के अंदर साथ में रहते हैं
.shdata loader में shebang डालकर उसे virtual environment directory के अंदर मौजूदbin/pythonके full path की ओर point नहीं कराया जा सकता?हाल ही में Observable notebook से अपना पहला “real-world” project पूरा किया
इसमें Observable Plot, Arquero सीखना, JavaScript के कुछ हिस्से फिर से सीखना, और data generation process यानी Rust-based simulator के साथ integration शामिल था। ईमानदारी से कहूँ तो यह सचमुच शानदार था। tools सीखने में काफ़ी energy लगी और data generator को parameterize करने की capability अभी भी थोड़ी कम लगती है, लेकिन final notebook खूबसूरत है और अच्छी तरह काम करता है
Markdown और reactivity इस्तेमाल करने पर ऐसे notebooks सच में उपयोगी लगते हैं। Jupyter का custom format version control को बहुत मुश्किल बना देता है, और reactivity न हो तो iteratively design किया गया notebook आसानी से ऐसा state-based mess बन जाता है जिसे लिखना आसान पर पढ़ना मुश्किल होता है। Quarto और उसके Observable integration से भी कोशिश की, लेकिन वह जुगाड़ के टुकड़े जोड़ने जैसा लगा
सच में, यह पहला अनुभव था जब notebook लिखना और दूसरों के साथ share करना मज़ेदार और उत्साहजनक लगा। आगे भी sharp edges होंगे, लेकिन इस project के बाद notebook tools में मेरी पहली पसंद यही है
[0]: https://living-papers.vercel.app/
अगर आप ब्राउज़र में Framework को जल्दी से आज़माना और उससे खेलना चाहते हैं, तो Node और Python environment को अपने-आप configure करने वाला Codespace devcontainer बनाया गया है
[0]: https://github.com/dleeftink/observable-codespace
क्या Jupyter Notebook से Observable पर शिफ्ट होना चाहिए? या दोनों को इस तरह अलग-अलग बांटना ही गलत framing है?
पोस्ट की बात को दूसरे शब्दों में कहें तो,
jscontent hint वाले code block के अंदर की हर चीज़ user के browser में तुरंत execute होती हैcode दिखाने के लिए
js echohint इस्तेमाल करना पड़ता है। backward compatibility को देखते हुए इसका उलटा बेहतर नहीं होता? मसलन, user के browser में चलने वाले code कोjs execजैसे opt-in hint के रूप में रखा जाता, और व्यापक रूप से इस्तेमाल होने वालाjshint जैसा है वैसा ही रहता। मौजूदा संरचना में उस renderer को किसी existing app में integrate करते समय अलग से manage करना पड़ता है कि कहाँ execution allow करनी हैयह page-by-page front matter में किया जा सकेगा, या project settings से पूरे project पर लागू किया जा सकेगा। तब
js run=falseको default बनाया जा सकता है, और जहाँ चाहें केवल वहाँjs runसे live code चालू किया जा सकता है। हालांकि हमारा मुख्य use case live code है, इसलिए हमने इसे default के रूप में चुनाअब language annotation हटाए बिना Mermaid code block को सिर्फ दिखाना संभव नहीं रह गया है
Observable Framework में डूबकर एक रात बिताई, और यह बहुत अच्छा लगा
लगभग कोई friction नहीं था, और मैं Google Maps history को विस्तार से visualize और explore कर सका। data loader environment से जुड़ा हिस्सा बहुत clear नहीं था, लेकिन Python को poetry environment में चलाने से समाधान हो गया
मुझे Kotlin पसंद है, इसलिए Kotlin scripts के लिए data loader बनाने की भी कोशिश की, लेकिन कुछ rough edges थे। Kotlin script file का नाम
foo.main.ktsहोने की अपेक्षा करता है, जबकि Observable executable shebang loader के लिएfoo.exeextension expect करता है। इसलिए मैंने Kotlin script को call करने वाला proxy exe script बनाया, लेकिन तब data का automatic reload trigger नहीं होताmarimo या Jupyter की तुलना में एक हल्की असुविधा data loader और notebook के बीच variables इस्तेमाल करने में है। उदाहरण के लिए, मैं date selection view component से loader द्वारा लाई जाने वाली data range बदलना चाहता हूँ, लेकिन यह साफ़ नहीं है कि ऐसा कैसे करना है। इसलिए exploratory analysis थोड़ा धीमा हो जाता है। मुझे पता है कि यह paradigm के खिलाफ है, लेकिन इसे mention करना चाहता था। नतीजतन, explore करते समय data wrangling का काफी हिस्सा notebook में shift हो सकता है, जो performance के लिहाज़ से ideal नहीं है
आखिर में, अच्छा होगा अगर data loader को inline define किया जा सके। मुझे single file पसंद है, इसलिए अगर Python code block जोड़ने पर Framework उसे file में extract कर दे, तो यह छोटी-सी quality-of-life improvement होगी। अभी शुरुआती दौर है, लेकिन Framework promising लगता है। उम्मीद है कि अपनी सारी Markdown notes यहाँ डालकर, full Emacs तक गए बिना org-mode जैसा environment बनाया जा सकेगा
.shया.exeसे workaround किए बिना नए interpreters को ज़्यादा आसानी से register करने के लिए एक PR खुला हैइससे किसी खास file extension से जुड़े interpreter को specify किया जा सकेगा। उदाहरण के लिए Kotlin के लिए
.ktsसंभव होगा। https://github.com/observablehq/framework/pull/935input values से data loader चलाने का तरीका Framework के static data snapshots को prefer करने से थोड़ा अलग दिशा में है। मकसद यह है कि built site self-contained और performant हो। फिर भी एक अच्छी तरह काम करने वाली technique यह है कि data loader में जिस data से interact करना है उसका superset Parquet file के रूप में generate किया जाए, और client-side पर DuckDB/SQL से visualization के लिए subset निकाला जाए। आम तौर पर performance अच्छी रहती है, लेकिन जाहिर है यह उस superset के size पर निर्भर करता है जिसे आप handle करना चाहते हैं
Observable, REST API के ज़रिए ClickHouse के साथ बहुत अच्छी तरह integrate होता है
example यहाँ है: https://observablehq.com/@stas-sl/github-issues-survival-ana...
नया Observable Framework अभी इस्तेमाल नहीं किया है, लेकिन database को real time में query करने वाले similar examples देखना दिलचस्प होगा। उम्मीद है कि इसकी structure ऐसी नहीं है कि सिर्फ सारे data को पहले से load और cache करना ही possible हो। ऐसे apps interactive होने चाहिए, इसलिए ideally SQL को live edit करने के लिए expose किया जाना चाहिए
यह demo runtime पर
fetch()से data load करता है: https://simonw.github.io/observable-framework-experiments/pa...