Free lesson · GenAI Agent Engineering
தரவு பைப்லைன்களை உருவாக்குங்கள்
திறமையான தரவு செயலாக்க பைப்லைன்களை நீங்கள் உருவாக்குவீர்கள். பல generators-ஐ ஒன்றாக இணைத்து, பெரிய கோப்புகளை memory-யில் ஏற்றாமல் lazy முறையில் செயலாக்கி, தரவு streams-ஐ வடிகட்டி மாற்றியமைப்பீர்கள்.
Course: LLM Foundations for Agent Builders · Chapter 1 · Generators & Iterators
Free to read — no subscription required.
ஜெனரேட்டர்களின் மிகவும் சக்திவாய்ந்த பயன்பாடுகளில் ஒன்று தரவு செயலாக்க பைப்லைன்களை உருவாக்குவது. பைப்லைனில் உள்ள ஒவ்வொரு நிலையும் (stage) ஒரு ஜெனரேட்டர் ஆகும் — அது முந்தைய நிலையிலிருந்து உள்ளீட்டைப் பெற்று, செயலாக்கி, அடுத்த நிலைக்கு வெளியீட்டை yield செய்கிறது. முழு தரவுத்தொகுப்பையும் நினைவகத்தில் ஏற்றாமலேயே, தரவு ஒரு நேரத்தில் ஒரு உருப்படியாக பைப்லைன் வழியாகப் பாய்கிறது.
அறிமுகம்
நினைவகத்தை விட பெரிய தரவுத்தொகுப்புகளை — log கோப்புகள், பயிற்சி corpus-கள், JSONL ஏற்றுமதிகள் — செயலாக்க வேண்டியிருக்கும்போது, எல்லாவற்றையும் ஒரே நேரத்தில் (eagerly) ஏற்றுவது சாத்தியமில்லை. ஜெனரேட்டர் பைப்லைன்கள் ஒரு பதிவை (record) பல மாற்ற நிலைகள் வழியாக ஸ்ட்ரீம் செய்ய அனுமதிக்கின்றன — எந்த நேரத்திலும் ஒரே ஒரு உருப்படியை மட்டுமே நினைவகத்தில் வைத்திருக்கும். இதைத் தவறாகச் செய்தால், pod-ஐ OOM ஆக்குவீர்கள், நினைவக வரம்புகளைத் தாண்டுவீர்கள், அல்லது முடிவடையாத ஒரு load படிநிலைக்காக மணிக்கணக்கில் காத்திருப்பீர்கள். இந்தப் பாடத்தின் முடிவில், ஜெனரேட்டர்களை பல-நிலை பைப்லைன்களாக இணைக்கவும், RAM-ஐ விட பெரிய கோப்புகளைச் செயலாக்கவும், துணை-ஜெனரேட்டர்களுக்கு ஒப்படைக்க (delegate) yield from-ஐப் பயன்படுத்தவும் உங்களால் முடியும்.
முக்கிய சொற்கள்
- Pipeline stage (பைப்லைன் நிலை) — மேல்நிலை (upstream) iterable-இலிருந்து நுகர்ந்து, கீழ்நிலை (downstream) நுகர்வோருக்கு yield செய்யும் ஒற்றை ஜெனரேட்டர் செயல்பாடு; இந்த நிலைகளை இணைத்து (compose) பைப்லைன்கள் கட்டமைக்கப்படுகின்றன, இதனால் தரவு ஒரு நேரத்தில் ஒரு உருப்படியாகப் பாய்கிறது.
- Lazy evaluation (சோம்பேறி மதிப்பீடு) — நுகர்வோர் ஒரு மதிப்பை இழுக்கும் வரை வேலை ஒத்திவைக்கப்படுகிறது; இதுவே ஒரு பல-நிலை பைப்லைன் கிகாபைட் அளவிலான உள்ளீடுகளை மாறாத (constant) நினைவகத்துடன் செயலாக்க அனுமதிக்கிறது.
yield from— Python 3.3+ இல் அறிமுகமான ஒரு statement; இது iteration-ஐ ஒரு துணை-ஜெனரேட்டருக்கோ அல்லது எந்த iterable-க்கோ ஒப்படைக்கிறது. ஜெனரேட்டர்களை இணைக்கவும், கைமுறை loops இல்லாமல் உள்ளமைந்த (nested) கட்டமைப்புகளைத் தட்டையாக்கவும் (flatten) இது நிலையான கருவி.- ETL — extract-transform-load, நியதியான (canonical) தரவு-பைப்லைன் pattern; இதில் ஒவ்வொரு படிநிலையும் (read, filter, parse, extract) இயல்பாகவே ஒரு ஜெனரேட்டர் நிலையாக வெளிப்படுத்தக்கூடியது.
கருத்துகள்
ஜெனரேட்டர்களை சங்கிலியாக இணைத்தல்
ஒரு பைப்லைன் என்பது ஜெனரேட்டர் செயல்பாடுகளின் சங்கிலியே — ஒவ்வொரு நிலையும் அதன் முந்தையதிலிருந்து இழுத்து, அதன் அடுத்ததற்கு yield செய்கிறது. ஒவ்வொரு நிலையும் lazy என்பதால், ஒரு இறுதி (terminal) நுகர்வோர் iterate செய்யும் வரை எந்த வேலையும் நடக்காது — அந்தத் தருணத்தில், அடுத்த பதிவு இழுக்கப்படும் முன் சரியாக ஒரு பதிவு மட்டுமே சங்கிலி முழுவதும் கடந்து செல்கிறது. LLM வெளியீடுகளைச் செயலாக்குதல், தரவுத்தொகுப்புகளை மாற்றுதல், திறமையான ETL workflows-ஐ உருவாக்குதல் ஆகியவற்றுக்கு இதுவே அடித்தளம் (Code Walkthrough பார்க்கவும்).
அம்புக்குறிகள் தள்ளுதலை (push) அல்ல, தேவையை (demand) குறிக்கின்றன: நுகர்வோர் extract_field-இடம் ஒரு மதிப்பைக் கேட்கிறது, அது parse_json_lines-ஐக் கேட்கிறது, அது filter_non_empty-ஐக் கேட்கிறது, அது read_lines-ஐக் கேட்கிறது, அது வட்டிலிருந்து (disk) சரியாக ஒரு வரியைப் படிக்கிறது. கோப்பின் அளவு எதுவாக இருந்தாலும் நினைவகப் பயன்பாடு சமமாகவே இருக்கும்.
RAM-ஐ விட பெரிய கோப்புகளை ஸ்ட்ரீம் செய்தல்
திறந்த கோப்பு object-ஐ iterate செய்வது (for line in open(filename)) கோப்பை முழுவதுமாக விழுங்காமல் ஒரு நேரத்தில் ஒரு வரியை yield செய்கிறது — இதுவே நியதியான குறைந்த-நினைவக ஸ்ட்ரீமிங் idiom. மேலே உள்ள பைப்லைன் pattern-உடன் இணைந்து, சில நூறு மெகாபைட் RAM மட்டுமே உள்ள ஒரு pod-இல் பல-கிகாபைட் பயிற்சி corpus-களையோ log காப்பகங்களையோ இப்படித்தான் செயலாக்குவீர்கள். ஒப்பந்தம் (contract): எந்த நேரத்திலும் ஒரே ஒரு பதிவு (நீங்கள் வைத்திருக்கும் running counters எதுவும் சேர்த்து) மட்டுமே நினைவகத்தில் இருக்கும்.
yield from மூலம் ஒப்படைத்தல் (Delegation)
Iteration-ஐ ஒரு துணை-ஜெனரேட்டருக்கோ அல்லது எந்த iterable-க்கோ ஒற்றை statement-இல் ஒப்படைக்க Python 3.3 yield from-ஐ அறிமுகப்படுத்தியது. இது இரண்டு சூழ்நிலைகளுக்குச் சரியான கருவி: ஜெனரேட்டர்களை இணைத்தல் (பல மூலங்களை ஒரே ஸ்ட்ரீமாக இணைத்தல்) மற்றும் உள்ளமைந்த கட்டமைப்புகளின் மீது recursion செய்தல் (கைமுறை stack மேலாண்மை இல்லாமல் மரங்களைத் தட்டையாக்குதல்). வெறும் syntactic sugar-ஐத் தாண்டி, இது send(), throw() மற்றும் return மதிப்புகளை ஒப்படைக்கப்பட்ட ஜெனரேட்டருக்குச் சரியாக அனுப்புகிறது — கையால் எழுதப்பட்ட for x in sub: yield x loop தவறாகச் செய்யும் ஒன்று இது (Code Walkthrough பார்க்கவும்).
Code Walkthrough
ஒவ்வொரு பைப்லைன் நிலையும் அதன் முந்தையதிலிருந்து எப்படி lazy-ஆக இழுக்கிறது என்பதை இப்போது பார்த்துவிட்டீர்கள்; அந்த இணைப்பு (wiring) code-இல் எப்படி இருக்கும் என்பது இதோ.
முதல் snippet, கருத்துகள் பிரிவில் உள்ள வரைபடத்தின் நான்கு நிலைகளையும் — read_lines, filter_non_empty, parse_json_lines, மற்றும் extract_field — ஒரே JSONL செயலியாக இணைத்து செயல்படுத்துகிறது. இரண்டாவது snippet, recursive தட்டையாக்கல் மற்றும் மூல-இணைப்பு (source concatenation) இரண்டிற்கும் yield from-ஐ விளக்குகிறது.
Code snippetpython
1def read_lines(filename): 2 """Stage 1: yield one stripped line at a time from a file.""" 3 with open(filename, 'r') as f: 4 for line in f: 5 yield line.strip() 6 7def filter_non_empty(lines): 8 """Stage 2: drop blank lines.""" 9 for line in lines: 10 if line: 11 yield line 12 13def parse_json_lines(lines): 14 """Stage 3: parse JSON, skipping malformed records.""" 15 import json 16 for line in lines: 17 try: 18 yield json.loads(line) 19 except json.JSONDecodeError: 20 continue 21 22def extract_field(records, field): 23 """Stage 4: project a single field out of each record.""" 24 for record in records: 25 if field in record: 26 yield record[field] 27 28# Compose: no I/O has happened yet. 29lines = read_lines('data.jsonl') 30non_empty = filter_non_empty(lines) 31records = parse_json_lines(non_empty) 32texts = extract_field(records, 'text') 33 34# Iteration is what makes data flow through the chain. 35for text in texts: 36 print(text)
read_lines:for line in fகோப்பை lazy-ஆக ஸ்ட்ரீம் செய்கிறது — ஒரு நேரத்தில் ஒரே ஒரு வரி மட்டுமே நினைவகத்தில் இருக்கும், எனவே பல-GB உள்ளீடுகள் சிக்கலின்றி வேலை செய்யும்.filter_non_empty/parse_json_lines/extract_field: ஒவ்வொன்றும் ஒற்றை-நோக்க நிலை — முந்தையதிலிருந்து இழுத்து கீழ்நோக்கி yield செய்கிறது. குறுகலானexcept json.JSONDecodeError-ஐக் கவனியுங்கள் — நாம் parse தோல்விகளை மட்டுமே தவிர்க்கிறோம், எல்லா exception-களையும் அல்ல.- Composition:
texts-ஐ உருவாக்குவது கோப்பைப் படிக்காது;for text in textsloop-தான் பதிவுகளை முழு பைப்லைன் வழியாகவும், ஒரு நேரத்தில் ஒன்றாக, இழுக்கிறது.
Code snippetpython
1def flatten(nested_list): 2 """Recursively flatten a nested list using yield from.""" 3 for item in nested_list: 4 if isinstance(item, list): 5 yield from flatten(item) 6 else: 7 yield item 8 9def combined_sources(*iterables): 10 """Concatenate any number of iterables into one stream.""" 11 for iterable in iterables: 12 yield from iterable 13 14print(list(flatten([1, [2, 3, [4, 5]], 6, [7, [8, 9]]]))) 15# [1, 2, 3, 4, 5, 6, 7, 8, 9] 16 17print(list(combined_sources([1, 2], [3, 4], [5, 6]))) 18# [1, 2, 3, 4, 5, 6]
flatten:yield from flatten(item)உள்ளமைந்த பட்டியல்களுக்குள் recursion செய்கிறது; இலைகள் (leaves) நேரடியாக yield செய்யப்படுகின்றன. ஒவ்வொரு மதிப்பும் அடைந்தவுடனேயே வெளிவருகிறது — இடைநிலை பட்டியல்களின் stack எதுவும் இல்லை.combined_sources:yield from iterableஜெனரேட்டர்களுக்கு மட்டுமல்ல, எந்த iterable-க்கும் வேலை செய்கிறது — ஸ்ட்ரீம்களை ஒன்றாக இணைக்க இது ஒரு ஒற்றை-வரி வழி.
JSONL பைப்லைனை ஒரு சிறிய கோப்பின் மீது இயக்கி, ஒவ்வொரு பதிவிற்கும் text field-ஐ மட்டும் காணும்போதும், உள்ளீட்டின் அளவு வளர்ந்தாலும் நினைவகப் பயன்பாடு சமமாக இருப்பதைக் கவனிக்கும்போதும் — மேலும் list(flatten(...)) எவ்வளவு ஆழமாக உள்ளமைந்த உள்ளீட்டிற்கும் எதிர்பார்க்கப்படும் தட்டையான வரிசையை உருவாக்கும்போதும் — அது வேலை செய்கிறது என்பதை அறிவீர்கள்.
-க்கான நடைமுறையில்
Code Walkthrough-இல் உள்ள பைப்லைன் pattern-ஐ அடிப்படையாகக் கொண்டு, அது உங்கள் அன்றாட வேலையில் எப்படி வெளிப்படுகிறது என்பது இதோ.
செய்ய வேண்டியவை மற்றும் செய்யக்கூடாதவை
செய்ய வேண்டியவை
- சிறிய, ஒற்றை-நோக்க நிலைகளை இணைத்து உருவாக்குங்கள் — ஒவ்வொரு ஜெனரேட்டர் செயல்பாடும் ஒரே ஒரு விஷயத்தை read, filter, parse அல்லது extract செய்ய வேண்டும்; அவற்றை இணைப்பது பைப்லைனைச் சோதிக்கவும் வரிசை மாற்றவும் எளிதாக வைத்திருக்கும்.
- கோப்பை
for line in open(...)மூலம் நேரடியாக iterate செய்யுங்கள் — இதுவே நியதியான குறைந்த-நினைவக ஸ்ட்ரீமிங் idiom; கோப்பின் அளவு எதுவாக இருந்தாலும் RAM பயன்பாட்டைச் சமமாக வைத்திருக்கும். - கைமுறை துணை-iteration-ஐ விட
yield from-ஐ விரும்புங்கள் — துணை-ஜெனரேட்டர்களுக்கு ஒப்படைப்பது exception propagation மற்றும்send()/returnமதிப்பு அனுப்புதல் தொடர்பான நுட்பமான bugs-ஐத் தவிர்க்கிறது.
செய்யக்கூடாதவை
- மேல்நிலை ஸ்ட்ரீமின் மீது
f.read()அல்லதுlist(...)அழைக்காதீர்கள் — இரண்டும் முழு தரவுத்தொகுப்பையும் நினைவகத்தில் உருவாக்கி (materialize), lazy பைப்லைனின் நோக்கத்தையே தோற்கடிக்கின்றன. Exception-ஐப் பிடித்து விழுங்காதீர்கள் — உங்கள்except-ஐ நீங்கள் எதிர்பார்க்கும் குறிப்பிட்ட பிழைக்கு (எ.கா.json.JSONDecodeError) குறுக்குங்கள்; இல்லையெனில் உண்மையான bugs ஒருcontinue-க்குப் பின்னால் மறைந்துவிடும்.- தீர்ந்துபோன (exhausted) ஜெனரேட்டர் object-ஐ மீண்டும் பயன்படுத்தாதீர்கள் — ஜெனரேட்டர்கள் ஒரு-முறை iterators; மீண்டும் iterate செய்ய வேண்டுமெனில் புதிய பைப்லைனை உருவாக்குங்கள்.
A hands-on lab comes with this lesson — real code, in a cloud IDE. Create a free account to run it. No card.
Free account · no card · straight to the lab
Or get the full path — from
Listen to this lesson
Audio overviews of this lesson's labs and its chapter, from GenBodha Bytes.
- Data Pipelines - Configurable Generator Pipeline with GeminiLab5 min
- Generators & IteratorsChapter overview19 min
More free lessons in LLM Foundations for Agent Builders
- Ch 1Build data pipelinesYou are here
- Ch 3Create Pydantic models
- Ch 3Configure Pydantic
- Ch 6Install Gemini SDK
- Ch 17Compare embedding models