import numpy as np from typing import List, Dict, Tuple import gradio as gr import string TELUGU_SAMPLE_TEXT = """అది మీకు కొత్తగాదు నాకెవరూ దాన్ని నేర్పక్కర్లేదను కుంటాను ఏ కమిటీ మెంబర్ సూక్ష్మ పరీక్షకయినా మరో కమిటీ మెంబర్ అడ్డు రాకూడదు అది విశ్వాత్మ వీలునామాలో స్పష్టంగా వుంది అసహనంగా తన సీట్లో కదులుతూ కూర్చున్నాడు ధృతకుమార్ వారిమధ్య జరుగుతున్న వాగ్వివాదాన్ని ఆనందంగా తిలకిస్తోంది శృతి ఒకసారి తప్పుచేస్తే పొరపాటు రెండోసారి చేస్తే గ్రహపాటు మూడోసారి చేస్తే అది చెడ్డ అలవాటు మనమిప్పుడు ఇక్కడ సమావేశమయింది పొరపాటు చేయటానికి గ్రహపాటుకి లోనుకావటానికి కాదు మిస్టర్ మిత్రా నాకన్నా వయస్సులో చిన్నవాడివి ఆ చనువుతోనే చెబుతున్నాను తొందరపాటు మంచిది కాదు ఇక్కడ మనమందరం కలిసి విశ్వాత్మనంటూ వచ్చిన వ్యక్తిని శల్యపరీక్ష చేయాలేగాని మనల్ని మనంకాదు యజ్ఞవల్కి సౌమ్యంగానే అన్నా ఆయన మాటల్లో ఒకింత కరుకుదనం తొంగిచూడక పోలేదు మిత్రా మౌనంగా వున్నా లోలోన కుతకుతలాడిపోయాడు నీలో నువ్వు అవధులు కల్పించుకుని విడి ముక్కలై పోయి విభాగమయిన నీ ఆత్మని లక్షపేర్లతో పిలుచుకుంటే ఆ స్వయంకల్పిత విభజన నేను గా రూపొందుతుంది నాయనా అదే అహానికి దారితీస్తుంది అహం అంచునే వినాశనం పొంచి వుంటుంది చిరంజీవి ధృతకుమార్ అన్న మాటల్లో నాకు తప్పేమీ కనిపించలేదు అతడ్ని సమర్ధించిన చిరంజీవి యజ్ఞవల్కి మాటల్లోనూ నాకు తప్పు కనిపించలేదు గంభీరంగా అన్న లలాటనేత్రస్వామి మాటలతో మిత్రా తలదించుకున్నాడు కొద్దిక్షణాలు మనిషంటే ఏమిటి దర్శనలింగస్వామి ప్రశాంత వదనంతో అకియోతోకేసి చూస్తూ అడిగాడు వెంటనే అకియోతో కలవరానికి లోనయ్యాడు ఆధ్యాత్మికపరమైన ప్రశ్నలకు సమాధానాలు చెప్పవలసి వస్తుందని ఫణివర్మ వూహించలేదు మనిషంతే ఆత్మ దానికో శరీరం వుంటుంది మనిషి తానెవరో తెలుసుకోలేనప్పుడు నిర్భంధకాల్ని అన్నిటినీ విడిచిపెట్టేస్తాడు అతను ఆధ్యాత్మిక కవిస్మృతి అనే తన సాధారణ స్థితిలో గందరగోళంలో పడి వున్నంత కాలం పరిసర నియమం తాలూకు సూక్ష్మ శృంఖలాల్లో చిక్కుకొనే వుంటాడు అలా వుండేవాడే మనిషి ఆ దశ దాటితే దేవుడే లలాటనేత్రస్వామి సావధానంగా చెప్పారు అకియోతో అప్పటికే బాగా ఉద్రిక్తతకు లోనయి వున్నాడు పోనీ దేవుడంటే ఏమిటి తిరిగి ప్రశ్నించాడు హిమలింగస్వామి ఆ ప్రశ్నకు ముందుగా ఫణివర్మ మొహం వాలిపోయింది ఏవో చిన్న చిన్న ప్రశ్నలేసి క్రిప్టోగ్రాఫ్ రూమ్ లోకి తీసుకెళతారని ఆశపడిన ఫణివర్మకి ఆ క్షణాన ఏం చేయాలో తోచలేదు డైరెక్టర్ మిత్రా ఆత్రుతగా అకియోతోకేసి చూడసాగాడు నాలుగైదు నిమిషాలయినా ఆ హాలు నిశ్శబ్దంతో మునిగిపోయి వుందేకాని అకియోతో మాటలతో ధ్వనించలేదు దేవుడంటే నీతి నిజాయితీ ప్రేమ మంచి సామరస్యం దేవుడితో ఐక్యానుసంధానం పొందిన భక్తుడు ఏ పనీ తప్పుగా చేయడు అతని కార్యకలాపాలు జ్యోతిష నియమానుసారంగా సరిగా సహజంగా జరగవలసిన సమయంలోనే జరుగుతాయి గాఢంగా ప్రార్థన ధ్యానం చేసిన తరువాత అతనికి దివ్య చైతన్యంతో సంపర్క మేర్పడుతుంది ఆంతరికమైన ఆ రక్షణ శక్తిని మించిన గొప్ప శక్తి మరొకటి ఏదీ లేదు ఇవేమీ నీకు స్ఫురణకు రావటం లేదా ఆశ్చర్యంగా వుంది విశ్వాత్మ గొప్ప ఆధ్యాత్మికవాది గొప్ప భక్తుడు నీలో ఆ లక్షణాలు ఎందుకు కనిపించటం లేదు ఈసారి యజ్ఞవల్కి ప్రశ్నించాడు అవి గుర్తుండి తీరాలా సడన్ గా నిగ్రహించుకోలేక అడిగాడు ఫణివర్మ అక్కడున్న అందరూ ఒక్కసారి ఫణివర్మకేసి చూశారు అసహనంగా పూర్వజన్మ స్మృతి లేనప్పుడు అవి గుర్తుండాల్సిన అవసరం లేదు లేకపోవచ్చు కానీ ఇప్పుడితను విశ్వాత్మనంటూ వచ్చాడు గతజన్మ స్మృతిలేని వ్యక్తికి విశ్వాత్మ కలలో ఎలా కనిపించగలడు ధృతకుమార్ సీరియస్ గా ప్రశ్నించాడు తిరిగి హల్లో నిశ్శబ్దం మానససరోవరం ఎక్కడుంది ఈసారి దర్శనలింగస్వామి ప్రశ్నించారు ఆయన ఏ ప్రశ్న అడగాలో అదే అడిగారనిపించింది అక్కడున్న అందరికీ ఆ ప్రశ్న వింటూనే అకియోతో మొహం క్షణకాలంలో వెలిగిపోయింది కైలాసపర్వతానికి అడుగున వుంది సంతోషంగా చెప్పాడు అకియోతో తిరిగి అందరి కళ్ళలో తళుక్కుమనే సన్నని కాంతిరేఖ టూరిజమ్ లో భాగంగా అకియోతో తన ఇరవయ్యో ఏట హిమాలయ పర్వతాల్ని సందర్శించి ఆ ప్రాంతపు వివరాల్ని తన జ్ఞాపకపు అరల్లో నిక్షిప్తం చేసుకున్నట్లు అతని తాతగారు కుషుయోతోకి తప్ప మరెవరికీ తెలియదు అందుకే కుషుయోతో మొహం అప్పటికే ఆనందంతో ప్రకాశిస్తోంది దానికి మానససరోవరమని ఎందుకు పేరొచ్చింది లలాటనేత్రస్వామి అడిగారు బ్రహ్మదేవుడి మనస్సంకల్పంతో ఏర్పడింది గనుక దానికా పేరొచ్చింది తెలియని ప్రశ్నలడిగినప్పుడు ఎంత తలదించుకున్నాడో అంతకంటే రెట్టింపు ఉత్సాహాన్ని తోడు తీసుకొని చెప్పాడు అకియోతో ఆ సరస్సు సముద్రానికి ఎన్నివేల అడుగుల ఎత్తున వుంది ధృతకుమార్ ప్రశ్నించాడు వేల నాలుగువందల అడుగుల ఎత్తున ఎంత వైశాల్యంలో నూరుద్దీన్ హసన్ అడిగారు మైళ్ళ వైశాల్యంలో విస్తరించుకొని వుంది దానినుండి ఒక నది పుట్టింది దాని పేరేంటి మరొకరు ప్రశ్నించారు క్షణం కూడా గేప్ ఇవ్వకుండా ప్రశ్న వెంట ప్రశ్న వర్షంలా కురుస్తున్నాయి సరయూనది అకియోతో నోటెంట సమాధానాలు బుల్లెట్స్ లా దూసుకొస్తున్నాయి ఫణివర్మ మొహం మతాబులా వెలిగిపోతోంది దానికి సరయూనది అనే పేరెందుకొచ్చింది సరస్సులోంచి ఉద్భవించింది గనుక ఆ నది ప్రధానంగా ఏ నగరాన్ని చుట్టుకొని ప్రవహిస్తుంది అయోధ్య దానికి సమీపంలోనే మరో సరస్సు వుంది దాని పేరేమిటి దర్శనలింగస్వామికి ఒళ్ళు పులకించిపోతోంది హిమాలయాలకు సంబంధించిన ప్రశ్నల్ని అందరూ అడుగుతుండటంతో రాక్షస్థల్ సెభాష్ నాయనా అని మెచ్చుకున్నాడు దర్శనలింగస్వామి ఆ మెచ్చుకోవటం అటు శృతికిగాని ఇటు ధృతకుమార్ కిగాని నచ్చలేదు ఎందుకో ఎంత నచ్చజెప్పుకుందామన్నా అతనే విశ్వాత్మ అంటే మనసు అంగీకరించటంలేదు యజ్ఞవల్కి విషయంలో కూడా""" def clean_text(text): # Remove special characters and extra whitespace text = text.replace('\r', ' ') text = text.replace('\n', ' ') text = text.replace('\xa0', ' ') # Remove all punctuation using string.punctuation for punct in string.punctuation: text = text.replace(punct, ' ') # Replace multiple spaces with single space text = ' '.join(text.split()) return text def get_stats(ids: List[int]) -> Dict[Tuple[int, int], int]: stats = {} for i in range(len(ids) - 1): pair = (ids[i], ids[i + 1]) stats[pair] = stats.get(pair, 0) + 1 return stats def merge(ids: List[int], pair: Tuple[int, int], idx: int) -> List[int]: new_ids = [] i = 0 while i < len(ids): if i < len(ids) - 1 and ids[i] == pair[0] and ids[i + 1] == pair[1]: new_ids.append(idx) i += 2 else: new_ids.append(ids[i]) i += 1 return new_ids def train_bpe(vocab_size: int = 350): try: # Clean the sample text print("Preprocessing Telugu text...") cleaned_text = clean_text(TELUGU_SAMPLE_TEXT) # Convert text to tokens print("Converting text to tokens...") bytes_tokens = cleaned_text.encode('utf-8') tokens = list(map(int, bytes_tokens)) # Train merges print(f"Training BPE with vocab size {vocab_size}...") num_merges = vocab_size - 256 # First 256 tokens are byte tokens ids = tokens merges = {} for i in range(num_merges): stats = get_stats(ids) if not stats: # If no more pairs to merge break pair = max(stats, key=stats.get) idx = 256 + i print(f"Merge #{i+1}: {pair} -> {idx}") ids = merge(ids, pair, idx) merges[pair] = idx return merges except Exception as e: raise Exception(f"Error during BPE training: {str(e)}") class OptimizedBPETokenizer: def __init__(self, merges: Dict[Tuple[int, int], int]): self.merges = merges self.idx_to_pair = {idx: pair for pair, idx in merges.items()} # Create lookup table for faster encoding self.merge_lookup = {} for (first, second), idx in merges.items(): if first not in self.merge_lookup: self.merge_lookup[first] = {} self.merge_lookup[first][second] = idx def encode(self, text: str, chunk_size: int = 1000000) -> List[int]: if not isinstance(text, str): return [] # Clean the input text first text = clean_text(text) # Convert to numpy array for faster processing ids = np.array(list(text.encode('utf-8')), dtype=np.uint16) # Process in chunks to handle large texts result = [] for i in range(0, len(ids), chunk_size): chunk = ids[i:i + chunk_size] processed_chunk = self._encode_chunk(chunk) result.extend(processed_chunk) return result def _encode_chunk(self, ids: np.ndarray) -> List[int]: output = [] i = 0 while i < len(ids): if i < len(ids) - 1: first, second = ids[i], ids[i + 1] if first in self.merge_lookup and second in self.merge_lookup[first]: output.append(self.merge_lookup[first][second]) i += 2 continue output.append(int(ids[i])) i += 1 return output def decode(self, ids: List[int]) -> str: result = [] for token in ids: if token < 256: result.append(token) else: result.extend(self._expand_token(token)) return bytes(result).decode('utf-8') def _expand_token(self, token: int) -> List[int]: if token < 256: return [token] pair = self.idx_to_pair[token] expanded = [] for t in pair: expanded.extend(self._expand_token(t)) return expanded if __name__ == "__main__": print("Initializing Telugu BPE Tokenizer...") try: # Train the tokenizer with the sample text merges = train_bpe(vocab_size=350) tokenizer = OptimizedBPETokenizer(merges) print("Tokenizer initialized successfully!") # Create the Gradio interface with custom styling with gr.Blocks( title="Telugu BPE Tokenizer", css=""" .container { margin: 15px; padding: 15px; border-radius: 10px; } .header { text-align: center; margin-bottom: 30px; } .encode-container { background-color: #f0f7ff; } .decode-container { background-color: #fff0f7; } .footer { text-align: center; margin-top: 20px; } """ ) as iface: # Header with gr.Column(elem_classes="header"): gr.Markdown( """ # 🔤 Telugu BPE Tokenizer ### A sophisticated byte-pair encoding tokenizer for Telugu text processing --- """ ) # Main content with gr.Row(): # Encode Section with gr.Column(elem_classes="container encode-container"): gr.Markdown("### 📝 Encode Text") input_text = gr.Textbox( label="Input Text", placeholder="Enter Telugu text to encode...", lines=5, elem_classes="input-box" ) encode_button = gr.Button( "🔄 Encode", variant="primary", size="lg" ) encode_output = gr.Textbox( label="Encoding Result", lines=3, elem_classes="output-box" ) # Decode Section with gr.Column(elem_classes="container decode-container"): gr.Markdown("### 📋 Decode Tokens") input_tokens = gr.Textbox( label="Input Tokens", placeholder="Enter comma-separated tokens (e.g., 256,257,258)", lines=5, elem_classes="input-box" ) decode_button = gr.Button( "🔄 Decode", variant="primary", size="lg" ) decode_output = gr.Textbox( label="Decoding Result", lines=3, elem_classes="output-box" ) # Examples Section with gr.Row(): with gr.Column(): gr.Markdown(""" ### 📚 Examples Try these sample texts to see how the tokenizer works """) gr.Examples( examples=[ [TELUGU_SAMPLE_TEXT[:100]], ["నమస్కారం"], ["తెలుగు భాష చాలా అందమైనది"], ], inputs=input_text, outputs=encode_output, fn=lambda x: f"Encoded tokens: {tokenizer.encode(x)}\nToken count: {len(tokenizer.encode(x))}", label="Sample Telugu Texts" ) # Footer with gr.Column(elem_classes="footer"): gr.Markdown(""" --- ### 📌 About This tokenizer uses Byte-Pair Encoding (BPE) to efficiently tokenize Telugu text. It has a vocabulary size of 350 tokens and handles Unicode characters properly. Made with ❤️ for Telugu NLP """) # Event handlers encode_button.click( fn=lambda x: f"Encoded tokens: {tokenizer.encode(x)}\nToken count: {len(tokenizer.encode(x))}", inputs=input_text, outputs=encode_output ) decode_button.click( fn=lambda x: f"Decoded text: {tokenizer.decode([int(t) for t in x.strip('[]').split(',')])}", inputs=input_tokens, outputs=decode_output ) # Launch with custom configurations iface.launch( share=False, server_name="0.0.0.0", server_port=7860, show_error=True, favicon_path="🔤" ) except Exception as e: print(f"Error initializing tokenizer: {str(e)}")