SQL की 500 लाइनों में लागू किया गया GPT
(explainextended.com)- केवल PostgreSQL और pgvector से GPT-2 inference flow को SQL में उतारकर, tokenization से लेकर Transformer blocks और next-token generation तक को फिर से बनाया गया
- Generative LLM लगभग एक deterministic function जैसा होता है, जो समान input पर समान candidate token probabilities देता है; response अलग होने की जगह candidate token चुनने वाले probabilistic selection step में होती है
- implementation में GPT-2 के BPE tokenizer, 50257 tokens, 768-dimensional embeddings, 1024-token context, 12 blocks, 12 attention heads, और GELU-based feedforward को SQL queries और tables के रूप में व्यक्त किया गया
- PostgreSQL regex में Unicode properties support न होना और
EXPमें बहुत छोटे values handle करने की सीमा जैसी वजहों से database environment के अनुसार व्यावहारिक workarounds की जरूरत पड़ी - उदाहरण में
"Happy New Year! I wish you"से 10 tokens generate करके"Happy New Year! I wish you all the best in your new year!"output किया गया, और लेखक के environment में इसमें 2 मिनट 44 सेकंड लगे
SQL से GPT-2 inference pipeline बनाना
- ChatGPT ने जवाब दिया कि SQL large language model implementation के लिए उपयुक्त नहीं है, लेकिन PostgreSQL SQL से GPT-2 inference pipeline implement की गई
- संदर्भ के रूप में Jay Mody की GPT in 60 Lines of NumPy implementation explanation ली गई, और उन्हीं components को database tables और queries में उतारा गया
- Generative LLM को
llm(prompt: str) -> list[tuple[str, float]]रूप वाले function की तरह देखा जा सकता है- input text prompt है
- output अगली आने वाली string candidates और probabilities की array है
- अगर internal math और parameters समान हों, तो समान input पर समान result लौटाता है
- ChatGPT जैसे products के समान सवाल पर अलग जवाब दे पाने की वजह model खुद से ज्यादा next token selection step में probabilistic selection है
Text generation loop
- Generation process prompt को token array में बदलने के बाद model को बार-बार call करके next token चुनता है और उसे prompt के पीछे जोड़ता है
- basic flow इन steps से बना है
tokenize(prompt)से string को token ID array में convert करनाgpt2(tokens)50257 tokens के लिए probabilities calculate करता हैselect_next_token(candidates)अगला token चुनता है- चुने गए token को array में add करना
- तय token count, timeout, stopword जैसी conditions पर रोकना
detokenize(tokens)से token array को string में restore करना
- इस तरह accumulated token sequence grammar, syntax, meaning और reasoning जैसी दिखने वाली विशेषताओं वाला natural language text बन सकता है
BPE tokenizer को SQL में implement करना
- Neural network input से पहले text को numbers की list में बदलना पड़ता है, लेकिन Unicode codepoints को सीधे इस्तेमाल करने पर token space और length inefficient हो जाते हैं
- GPT-2 Byte pair encoding का एक variant इस्तेमाल करता है
- token dictionary 50257 codepoints का उपयोग करती है
- इसमें UTF-8 byte sequences और “end of text” token शामिल हैं
- शुरुआत 256 byte tokens से होती है, फिर अक्सर आने वाले adjacent token pairs को नए token के रूप में जोड़ा जाता है
- इस merge को 50000 बार repeat करके 50256 tokens बनाए जाते हैं, और अंत में end-of-text token जोड़ा जाता है
- GPT-2 tokenizer में bytes को string characters पर map करने वाली एक अतिरिक्त layer है, और यह mapping OpenAI GPT-2 के
encoder.pyमें define है - SQL implementation में OpenAI से download की गई token dictionary को
tokenizertable में डाला गया, और byte-character mapping कोencodertable में store किया गया "Mississippilessly"example recursive CTE से single bytes से शुरू होकर merge किए जा सकने वाले best adjacent pair को बार-बार merge करता है- example में token count 17 से घटकर 5 हो जाता है
- Unicode के करीब 150k codepoint space के बजाय GPT-2 का करीब 50k token space इस्तेमाल होता है
- कई words process करते समय GPT-2 regex से text को split करके हर word के अंदर merge करता है
- PostgreSQL regex में Unicode character properties support नहीं करता, इसलिए original GPT-2 regex को कुछ modify किया गया
- संभव है कि इस modification ने सही Unicode support को नुकसान पहुंचाया हो
"PostgreSQL is great"SQL tokenizer में[6307, 47701, 318, 1049]में convert होता है- token clusters हैं
Post,greSQL,Ġis,Ġgreat Ġspace को दर्शाता है
- token clusters हैं
Embedding और context window
- Token ID सीधे model calculations में इस्तेमाल नहीं होते, बल्कि embedding vectors में convert होते हैं
- GPT-2 tokens और positions को अलग-अलग embed करता है
WTEword token embedding है और 50257×768 matrix हैWPEword position embedding है और 1024×768 matrix है
- हर token position पर
WTEvector औरWPEvector को जोड़कर next step का input vector बनाया जाता है - क्योंकि
WPEमें सिर्फ 1024 positions हैं, GPT-2 prompt में इस्तेमाल किए जा सकने वाले tokens की maximum संख्या 1024 है- यही संख्या LLM की context window के बराबर है
- यह model design के समय तय hyperparameter है और training से नहीं बदलता
- SQL implementation pgvector का उपयोग करता है
- arrays पर vector operations खुद define करके pure SQL से भी संभव है, लेकिन performance कम हो जाती है
- शुरुआती version pure SQL functions से चलता था, लेकिन धीमा था
self-attention को SQL query में विस्तार देना
- Transformer का core self-attention mechanism है, और यह 2017 के paper Attention is all you need पर आधारित है
- attention token vectors को एक-दूसरे को प्रभावित करने देता है, ताकि prompt के शुरुआती हिस्से की information आखिरी vector तक पहुंच सके
- GPT-2 implementation
Q,K,Vmatrices के 12 sets का उपयोग करता है- हर set एक attention head है
- हर head 64-dimensional है
c_attn768×2304 linear transformation है, और resultQ,K,Vको horizontally stack करके बना 2304-dimensional vector है- weights और bias
c_attn_w,c_attn_btables में store होते हैं
- attention calculation से पहले layer normalization apply होती है
- scale और shift parameters
ln_1_g,ln_1_btables में store होते हैं
- scale और shift parameters
- causal self-attention में बाद के tokens को पहले के tokens को प्रभावित करने से रोकने के लिए causal mask apply किया जाता है
- model का next token candidate अंततः last embedding से तय होता है
- information flow last vector की ओर होना चाहिए, और last vector की intermediate value को previous vectors को प्रभावित नहीं करना चाहिए
- SQL implementation में softmax calculation के दौरान PostgreSQL
EXPके बहुत छोटे numbers पर fail होने की समस्या से बचने के लिए input -745.13 से छोटा हो तो उसे 0 माना जाता है - causal mask की वजह से नए token को prompt में जोड़ने पर भी previous tokens के calculation results नहीं बदलते
- original GPT-2 implementation इसी property का उपयोग करता है
- SQL implementation simplicity के लिए इस reuse का उपयोग नहीं करता
multi-head attention और residual connection
- 12 heads के attention results हर एक 64-dimensional होते हैं, जिन्हें horizontally stack करके फिर 768-dimensional बनाया जाता है
- इसके बाद
c_proj_w,c_proj_bमें stored trained linear transformation से attention output को project किया जाता है - multi-headed attention result में original input फिर से add किया जाता है
- यह residual connection original Transformer paper में शामिल technique है
- इसे training के दौरान vanishing gradient और exploding gradient problems को कम करने वाली design के रूप में introduce किया गया था
feedforward step और Transformer block
- attention के बाद feedforward neural network आता है
- GPT-2 का feedforward step 3-layer multi-layer perceptron से बना है
- dimensions 768 → 3072 → 768 हैं
- activation function GELU इस्तेमाल होता है
- linear transformation parameters इन tables में store हैं
mlp_c_fc_w,mlp_c_fc_bmlp_c_proj_w,mlp_c_proj_b
- feedforward input भी पहले
ln_2parameters से normalize होता हैln_2_g,ln_2_bscale और shift store करते हैं
- feedforward output में भी input को फिर से add करने वाला residual connection apply होता है
- attention + feedforward का यह combination एक block है, और GPT-2 12 blocks को pipeline की तरह connect करता है
- हर block के अपने trained parameter sets होते हैं
- SQL में blocks को recursive CTE से connect किया जाता है
- last block output को
ln_fparameters से फिर normalize किया जाता है
वापस next token में बदलना
- final output में last position का 768-dimensional vector next token की embedding है
- इस vector को फिर token में बदलने के लिए initial token embedding में इस्तेमाल हुआ
WTEmatrix फिर इस्तेमाल किया जाता है - exact inverse transformation आम तौर पर संभव नहीं है
- predicted embedding
WTEकी किसी specific row के बिल्कुल समान नहीं हो सकती - इसलिए हर token embedding के साथ dot product calculate करके करीब token खोजा जाता है
- predicted embedding
WTEऔर predicted embedding के dot product results 50257 scores, यानी logits बनते हैं- ये scores softmax से गुजरकर probabilities में बदलते हैं
- top candidate count
top_nहै - probability distribution को adjust करने वाली value temperature है
- temperature जितना अधिक होगा, rank 1 के अलावा tokens के चुने जाने की संभावना उतनी बढ़ेगी, और inference कम predictable होगा
- top candidate count
"PostgreSQL is great"example में top 5 next token candidates ये हैंĠfor,.ĠatĠto
- temperature 0.5, 1, 2 में बदलने पर समान candidates की softmax probability distribution बदल जाती है
वास्तविक inference result और code
- final SQL tokens को probability के अनुसार चुनने और prompt में जोड़ने की process को repeat करता है
- model खुद deterministic है, और non-deterministic element सिर्फ token selection में शामिल random numbers हैं
- example settings इस प्रकार हैं
- prompt:
"Happy New Year! I wish you" - generated token count: 10
- temperature: 2
- top_n: 1
SETSEED(0.20231231)का उपयोग
- prompt:
- लेखक के environment में query 2 मिनट 44 सेकंड चली
- output result
"Happy New Year! I wish you all the best in your new year!"है - query और installation code GitHub repository quassnoi/explain-extended-2024 में हैं
1 टिप्पणियां
Hacker News टिप्पणियाँ
बहुत सुंदर। मैं भी SQLite में कुछ ऐसा ही rabbit hole खोद रहा था, लेकिन अभी तक neural network तक नहीं पहुँच पाया था
makemore lecture series[0] से प्रेरणा मिली थी, और लगभग 1 घंटे बाद वह counting approach से neural network पर चली जाती है; मैं भी लगभग वहीं तक पहुँचा था
इसे relational model में तोड़कर देखना वाकई बहुत अच्छा अभ्यास है
[0] https://www.youtube.com/watch?v=PaCmpygFfXo
डेमो अच्छा है, लेकिन लेख में causal masking की व्याख्या training और inference को मिलाती हुई लगती है
causal masking का उद्देश्य training के दौरान future tokens को “झाँकने” से रोकना होता है, और GPT-शैली की architectures में inference के दौरान autoregressiveness को लागू करना भी इसका उद्देश्य है
inference में वैसे भी सिर्फ आख़िरी token का उपयोग होता है, इसलिए वह token पूरे input sequence पर attention देता है; इसीलिए अगला token सिर्फ आख़िरी token की embedding से तय नहीं होता
मुझे जिज्ञासा है कि क्या यह GPT के driver loop को सही तरह से दिखाता है: prompt को tokenize करना,
gpt2(tokens)से 50257 tokens की probabilities लेना, अगला token चुनना, उसे token list में जोड़ना, stop condition जाँचना, और अंत में detokenize करना — कुछ ऐसा दिख रहा हैलेकिन यह state machine Shlemiel the painter algorithm लागू करती हुई लगती है, इसलिए generation task की मूल computational cost को लेकर सवाल उठता है
वह window एक sliding window होती है
gpt2function के अंदर हैयह ज़्यादा से ज़्यादा generated tokens को एक वाक्य में इकट्ठा करने का तरीका दिखाता है
संबंधित सामग्री: A GPT in 60 Lines of NumPy - https://news.ycombinator.com/item?id=34726115 - फ़रवरी 2023, 146 टिप्पणियाँ
इसी तरह के संदर्भ में, मैंने GPT को पूरी तरह spreadsheet functions में implement किया था, और साथ में देखने लायक video tutorial भी बनाया था
https://spreadsheets-are-all-you-need.ai/
मुझे LLM काफ़ी कमाल का लगता है, लेकिन उसके असली काम करने के तरीके को पेशेवर रूप से सीखने की ज़रूरत कभी नहीं पड़ी; ऐसे में 10 मिनट के उस वीडियो ने उलझी हुई HN टिप्पणियाँ और सतही mainstream media लेख कई साल पढ़ने से ज़्यादा सिखा दिया
floating-point numbers की भारी मात्रा को computation के इंतज़ार में जमा हुआ देखकर यह भी कहीं ज़्यादा सहज रूप से समझ आया कि यह तकनीक GPU इतनी ज़्यादा क्यों खाती है
अगर हर training example में हर parameter का derivative निकाला जाए और साफ़ दिखाया जाए कि वह उस parameter पर कैसे map होता है, तो training process भी अच्छी तरह समझाई जा सकती है
बढ़िया। जो चीज़ सिर्फ 1 साल पहले तक किसी तरह के जादू जैसी लगती थी, अब उसे इतने अच्छे से, लगभग इस हद तक समझाया जा रहा है कि बच्चे भी उसका पीछा कर सकें
लेख में समझाया गया model GPT-2 है, जो 2019 की शुरुआत में जारी किया गया था
इस लेख को ठीक से समझने के लिए computer science की पृष्ठभूमि काफ़ी मज़बूत होनी चाहिए, और शीर्षक भी अपने-आप में मानवता के 99% लोगों के लिए कम सुलभ है
मैं अब तक GPT और LLM से पूरी तरह बचता आया हूँ, लेकिन यह तरीका text output में कुछ हद तक fluency तो पैदा कर सकता है, पर सवाल समझकर जवाब देने की क्षमता तक पहुँचता हुआ नहीं लगता
मैं सोच रहा हूँ कि क्या कोई सरल blog post या course है जो बताए कि यह वास्तव में कैसे काम करता है, या Python जैसी toy engine दिखाए
अब तक मैंने जो शैक्षिक सामग्री देखी है, वह platforms का उपयोग कैसे करें इस पर ज़्यादा केंद्रित थी, अंदरूनी कामकाज पर नहीं
खासकर [0], [1], [2] अच्छे हैं
[0] http://jalammar.github.io/illustrated-transformer/
[1] http://jalammar.github.io/illustrated-gpt2/
[2] https://jalammar.github.io/visualizing-neural-machine-transl...
दिलचस्प बात यह है कि आधुनिक machine learning को Turing completeness की ज़रूरत नहीं होती
फिर भी हम AGI की संभावना पर विचार कर रहे हैं, इसलिए अगर निष्कर्ष यह निकले कि Turing completeness ज़रूरी नहीं है, तो वह काफ़ी रोचक होगा
सीधी वजह यह है कि मैं अपने दिमाग़ में Turing-complete code के execution का पीछा कर सकता हूँ
लेख शानदार था, और हर component की व्याख्या साफ़ और काफ़ी thorough थी, इसलिए पढ़ना अच्छा लगा
बस गलती से “+ expand source” दबा दिया, और उस चौंकाने वाले monster को देखने के बाद मुझे ChatGPT की यह बात माननी पड़ी कि “SQL large language models को implement करने के लिए उपयुक्त नहीं है”
“साधारण Unicode neural networks के साथ अच्छी तरह काम नहीं करता” — यह बात सही नहीं है। उदाहरण के लिए ByT5 को देखिए
लेख में जिसे “alphabet” कहा गया है, उसे आम तौर पर vocabulary कहा जाता है, और अगर UTF-8 bytes को vocabulary बनाया जाए तो tokens 149186 नहीं बल्कि 256 होंगे
ByT5 ठीक यही करता है
बाज़ार में सबसे अच्छा performance देने वाले models सभी tokenization का उपयोग करते हैं; यही इसका सबूत है
यह कोई रहस्य नहीं कि tokenization मूल रूप से एक तरह का hack है, और आदर्श रूप में लोग चाहते हैं कि किसी न किसी तरह इसे कभी हटाया जा सके (https://twitter.com/karpathy/status/1657949234535211009)
सिद्धांत रूप में byte-level tokenization की कमियों की भरपाई बड़े models और बड़े context से की जा सकती है, लेकिन व्यवहार में उसी स्तर की intelligence वाला model train करने के लिए कहीं ज़्यादा resources लगते हैं
हाँ, कुछ खास tasks — जैसे किसी शब्द में अक्षरों की संख्या गिनना — ऐसे भी हैं जहाँ tokenization उल्टा intelligence को नुकसान पहुँचाती है