{ "cells": [ { "cell_type": "markdown", "id": "7abd1d8d", "metadata": {}, "source": [ "# šŸŽ­ Three Character Text Generators\n", "## Mickey Mouse 🐭 | Yoda 🟢 | Spider-Man šŸ•·ļø\n", "\n", "This notebook fine-tunes 3 separate LoRA adapters for each character and creates an interactive chat interface.\n", "\n", "**Characters:**\n", "- 🐭 **Mickey Mouse** - Cheerful and optimistic mouse from Toontown\n", "- 🟢 **Yoda** - Wise Jedi Master with unique backward speech pattern\n", "- šŸ•·ļø **Spider-Man** - Friendly neighborhood web-slinging superhero" ] }, { "cell_type": "markdown", "id": "0ac3f3d3", "metadata": {}, "source": [ "---\n", "## šŸš€ Google Colab Setup (FREE GPU!)\n", "\n", "**Follow these steps to run this notebook on Google Colab with free GPU:**\n", "\n", "1. **Upload to Google Drive:**\n", " - Go to [Google Drive](https://drive.google.com)\n", " - Upload this notebook: `CharacterTextGenerators.ipynb`\n", " - Upload the 3 training data files: `mickeymouse.txt`, `yoda.txt`, `spiderman.txt`\n", " - Keep all files in the same folder\n", "\n", "2. **Open in Colab:**\n", " - Right-click `CharacterTextGenerators.ipynb` in Google Drive\n", " - Select \"Open with\" → \"Google Colaboratory\"\n", "\n", "3. **Enable GPU:**\n", " - In Colab, click \"Runtime\" → \"Change runtime type\"\n", " - Set \"Hardware accelerator\" to \"T4 GPU\" (free tier)\n", " - Click \"Save\"\n", "\n", "4. **Run the notebook:**\n", " - The GPU check cell will confirm GPU is available\n", " - Training will take ~10-15 minutes (instead of hours on CPU!)\n", "\n", "**Colab will automatically handle all library installations - no setup needed!**\n", "\n", "---" ] }, { "cell_type": "markdown", "id": "ad548564", "metadata": {}, "source": [ "---\n", "## 1ļøāƒ£ Setup: Install Libraries and Load Training Data" ] }, { "cell_type": "code", "execution_count": null, "id": "776810af", "metadata": {}, "outputs": [], "source": [ "# Install required libraries\n", "%pip install transformers peft datasets accelerate ipywidgets\n", "\n", "import torch\n", "from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments, Trainer\n", "from peft import LoraConfig, get_peft_model, TaskType, PeftModel\n", "from datasets import Dataset\n", "\n", "print(\"āœ… Libraries imported successfully!\")" ] }, { "cell_type": "code", "execution_count": null, "id": "29a56176", "metadata": {}, "outputs": [], "source": [ "# Check if GPU is available\n", "import torch\n", "\n", "print(\"šŸ” Checking hardware availability...\\n\")\n", "\n", "if torch.cuda.is_available():\n", " print(f\"āœ… GPU Available: {torch.cuda.get_device_name(0)}\")\n", " print(f\" GPU Memory: {torch.cuda.get_device_properties(0).total_memory / 1024**3:.2f} GB\")\n", " print(f\" CUDA Version: {torch.version.cuda}\")\n", " print(f\" Current Device: cuda:{torch.cuda.current_device()}\")\n", " print(\"\\nšŸŽ® Training will use GPU acceleration!\")\n", "else:\n", " print(\"āš ļø WARNING: No GPU detected!\")\n", " print(\" Training will use CPU (much slower)\")\n", " print(\" Consider using Google Colab or a system with GPU\")\n", "\n", "print(f\"\\nšŸ“Š PyTorch Version: {torch.__version__}\")" ] }, { "cell_type": "code", "execution_count": null, "id": "c305f195", "metadata": {}, "outputs": [], "source": [ "# Load the character training data from text files\n", "exec(open('mickeymouse.txt').read())\n", "exec(open('yoda.txt').read())\n", "exec(open('spiderman.txt').read())\n", "\n", "print(f\"āœ… Mickey Mouse: {len(train_data_mickey)} training examples\")\n", "print(f\"āœ… Yoda: {len(train_data_yoda)} training examples\")\n", "print(f\"āœ… Spider-Man: {len(train_data_spider_man)} training examples\")" ] }, { "cell_type": "markdown", "id": "c6e87ec7", "metadata": {}, "source": [ "---\n", "## 2ļøāƒ£ Load Base Model and Tokenizer" ] }, { "cell_type": "code", "execution_count": null, "id": "8bcba967", "metadata": {}, "outputs": [], "source": [ "# Choose a small, efficient model\n", "model_name = \"Qwen/Qwen2-0.5B-Instruct\"\n", "\n", "# Load tokenizer\n", "tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)\n", "tokenizer.pad_token = tokenizer.eos_token\n", "tokenizer.padding_side = \"right\"\n", "\n", "# Load base model\n", "base_model = AutoModelForCausalLM.from_pretrained(\n", " model_name,\n", " torch_dtype=torch.float16,\n", " device_map=\"auto\",\n", " trust_remote_code=True\n", ")\n", "\n", "print(f\"šŸ”¹ Base model loaded: {model_name}\")\n", "print(f\"šŸ”¹ Parameters: {base_model.num_parameters():,}\")" ] }, { "cell_type": "markdown", "id": "83f6f8f7", "metadata": {}, "source": [ "---\n", "## 3ļøāƒ£ Training Function" ] }, { "cell_type": "code", "execution_count": null, "id": "8f1fe22c", "metadata": {}, "outputs": [], "source": [ "def train_character(character_name, train_data, output_dir, epochs=3):\n", " \"\"\"\n", " Fine-tune a LoRA adapter for a specific character\n", " \n", " Args:\n", " character_name: Name of the character\n", " train_data: List of training examples\n", " output_dir: Directory to save the adapter\n", " epochs: Number of training epochs\n", " \"\"\"\n", " print(f\"\\n{'='*70}\")\n", " print(f\"šŸŽ­ TRAINING {character_name.upper()}\")\n", " print(f\"{'='*70}\\n\")\n", " \n", " # Reload base model fresh for each character\n", " model = AutoModelForCausalLM.from_pretrained(\n", " model_name,\n", " torch_dtype=torch.float16,\n", " device_map=\"auto\",\n", " trust_remote_code=True\n", " )\n", " \n", " # Configure LoRA\n", " lora_config = LoraConfig(\n", " r=16,\n", " lora_alpha=32,\n", " target_modules=[\"q_proj\", \"v_proj\", \"k_proj\", \"o_proj\"],\n", " lora_dropout=0.05,\n", " bias=\"none\",\n", " task_type=TaskType.CAUSAL_LM\n", " )\n", " \n", " # Apply LoRA\n", " model = get_peft_model(model, lora_config)\n", " print(f\"āœ… LoRA adapter applied\")\n", " model.print_trainable_parameters()\n", " \n", " # Format dataset using chat template\n", " def format_chat(example):\n", " text = tokenizer.apply_chat_template(\n", " example[\"messages\"],\n", " tokenize=False,\n", " add_generation_prompt=False\n", " )\n", " return {\"text\": text}\n", " \n", " dataset = Dataset.from_list(train_data)\n", " dataset = dataset.map(format_chat)\n", " \n", " # Tokenize\n", " def tokenize_function(examples):\n", " result = tokenizer(\n", " examples[\"text\"],\n", " truncation=True,\n", " padding=\"max_length\",\n", " max_length=256\n", " )\n", " result[\"labels\"] = result[\"input_ids\"].copy()\n", " return result\n", " \n", " tokenized_dataset = dataset.map(tokenize_function, batched=True, remove_columns=[\"text\", \"messages\"])\n", " \n", " # Training arguments\n", " training_args = TrainingArguments(\n", " output_dir=output_dir,\n", " num_train_epochs=epochs,\n", " per_device_train_batch_size=2,\n", " gradient_accumulation_steps=2,\n", " learning_rate=2e-4,\n", " logging_steps=5, # Log more frequently for better progress visibility\n", " save_strategy=\"epoch\",\n", " report_to=\"none\",\n", " fp16=True,\n", " use_cpu=False, # Force GPU usage\n", " no_cuda=False, # Enable CUDA\n", " disable_tqdm=False, # Enable progress bars\n", " logging_first_step=True, # Show initial progress\n", " )\n", " \n", " # Train\n", " trainer = Trainer(\n", " model=model,\n", " args=training_args,\n", " train_dataset=tokenized_dataset,\n", " tokenizer=tokenizer,\n", " )\n", " \n", " print(f\"\\nšŸ”„ Starting training for {character_name}...\\n\")\n", " trainer.train()\n", " \n", " # Save\n", " model.save_pretrained(output_dir)\n", " tokenizer.save_pretrained(output_dir)\n", " \n", " print(f\"\\nāœ… {character_name} adapter saved to {output_dir}\\n\")\n", " \n", " # Clear memory\n", " del model\n", " del trainer\n", " torch.cuda.empty_cache()\n", " \n", " return output_dir\n", "\n", "print(\"āœ… Training function defined!\")" ] }, { "cell_type": "markdown", "id": "6e520227", "metadata": {}, "source": [ "---\n", "## 4ļøāƒ£ Train All Three Characters\n", "\n", "āš ļø **Note:** This will take approximately 10-15 minutes on a GPU (T4 or better recommended)" ] }, { "cell_type": "code", "execution_count": null, "id": "e04031a7", "metadata": {}, "outputs": [], "source": [ "# Train Mickey Mouse\n", "# Note: Press the stop button (ā– ) in the notebook toolbar to interrupt training if needed\n", "\n", "import signal\n", "import sys\n", "\n", "def signal_handler(sig, frame):\n", " print('\\nāš ļø Training interrupted by user!')\n", " sys.exit(0)\n", "\n", "signal.signal(signal.SIGINT, signal_handler)\n", "\n", "print(\"🐭 Training Mickey Mouse...\")\n", "print(\"šŸ’” Tip: Click the stop button (ā– ) to interrupt training\\n\")\n", "\n", "mickey_adapter = train_character(\n", " character_name=\"Mickey Mouse\",\n", " train_data=train_data_mickey,\n", " output_dir=\"./mickey-lora-adapter\",\n", " epochs=3\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "d4fa5595", "metadata": {}, "outputs": [], "source": [ "# Train Yoda\n", "# Note: Press the stop button (ā– ) in the notebook toolbar to interrupt training if needed\n", "\n", "import signal\n", "import sys\n", "\n", "def signal_handler(sig, frame):\n", " print('\\nāš ļø Training interrupted by user!')\n", " sys.exit(0)\n", "\n", "signal.signal(signal.SIGINT, signal_handler)\n", "\n", "print(\"🟢 Training Yoda...\")\n", "print(\"šŸ’” Tip: Click the stop button (ā– ) to interrupt training\\n\")\n", "\n", "yoda_adapter = train_character(\n", " character_name=\"Yoda\",\n", " train_data=train_data_yoda,\n", " output_dir=\"./yoda-lora-adapter\",\n", " epochs=3\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "b703cf4e", "metadata": {}, "outputs": [], "source": [ "# Train Spider-Man\n", "# Note: Press the stop button (ā– ) in the notebook toolbar to interrupt training if needed\n", "\n", "import signal\n", "import sys\n", "\n", "def signal_handler(sig, frame):\n", " print('\\nāš ļø Training interrupted by user!')\n", " sys.exit(0)\n", "\n", "signal.signal(signal.SIGINT, signal_handler)\n", "\n", "print(\"šŸ•·ļø Training Spider-Man...\")\n", "print(\"šŸ’” Tip: Click the stop button (ā– ) to interrupt training\\n\")\n", "\n", "spiderman_adapter = train_character(\n", " character_name=\"Spider-Man\",\n", " train_data=train_data_spider_man,\n", " output_dir=\"./spiderman-lora-adapter\",\n", " epochs=3\n", ")\n", "\n", "print(\"\\n\" + \"=\"*70)\n", "print(\"šŸŽ‰ ALL THREE CHARACTERS TRAINED SUCCESSFULLY!\")\n", "print(\"=\"*70)" ] }, { "cell_type": "markdown", "id": "f315ffab", "metadata": {}, "source": [ "---\n", "## 5ļøāƒ£ Character Chat System\n", "\n", "Create an interactive chat interface to talk with any of the three characters!" ] }, { "cell_type": "code", "execution_count": null, "id": "08114e83", "metadata": {}, "outputs": [], "source": [ "class CharacterChat:\n", " \"\"\"Interactive chat with multiple character personalities\"\"\"\n", " \n", " def __init__(self):\n", " self.characters = {\n", " \"Mickey Mouse\": {\n", " \"adapter\": \"./mickey-lora-adapter\",\n", " \"emoji\": \"🐭\",\n", " \"description\": \"Cheerful and optimistic mouse from Toontown\"\n", " },\n", " \"Yoda\": {\n", " \"adapter\": \"./yoda-lora-adapter\",\n", " \"emoji\": \"🟢\",\n", " \"description\": \"Wise Jedi Master who speaks in unique way\"\n", " },\n", " \"Spider-Man\": {\n", " \"adapter\": \"./spiderman-lora-adapter\",\n", " \"emoji\": \"šŸ•·ļø\",\n", " \"description\": \"Friendly neighborhood web-slinging hero\"\n", " }\n", " }\n", " \n", " self.current_character = None\n", " self.current_model = None\n", " self.base_model = None\n", " self.tokenizer = None\n", " \n", " def load_character(self, character_name):\n", " \"\"\"Load a specific character's LoRA adapter\"\"\"\n", " if character_name not in self.characters:\n", " print(f\"āŒ Character '{character_name}' not found!\")\n", " return False\n", " \n", " print(f\"\\nšŸ”„ Loading {character_name}...\")\n", " \n", " # Clear previous model if exists\n", " if self.current_model is not None:\n", " del self.current_model\n", " torch.cuda.empty_cache()\n", " \n", " # Load base model if not loaded\n", " if self.base_model is None:\n", " self.base_model = AutoModelForCausalLM.from_pretrained(\n", " model_name,\n", " torch_dtype=torch.float16,\n", " device_map=\"auto\",\n", " trust_remote_code=True\n", " )\n", " \n", " # Load tokenizer if not loaded\n", " if self.tokenizer is None:\n", " adapter_path = self.characters[character_name][\"adapter\"]\n", " self.tokenizer = AutoTokenizer.from_pretrained(adapter_path)\n", " \n", " # Load character's LoRA adapter\n", " adapter_path = self.characters[character_name][\"adapter\"]\n", " self.current_model = PeftModel.from_pretrained(self.base_model, adapter_path)\n", " self.current_model.eval()\n", " \n", " self.current_character = character_name\n", " \n", " emoji = self.characters[character_name][\"emoji\"]\n", " print(f\"āœ… {emoji} {character_name} loaded and ready to chat!\\n\")\n", " return True\n", " \n", " def chat(self, user_message, max_tokens=50, temperature=0.7):\n", " \"\"\"Generate a response from the current character\"\"\"\n", " if self.current_model is None:\n", " return \"āŒ No character loaded! Please load a character first.\"\n", " \n", " # Format message using chat template\n", " messages = [{\"role\": \"user\", \"content\": user_message}]\n", " prompt = self.tokenizer.apply_chat_template(\n", " messages, \n", " tokenize=False, \n", " add_generation_prompt=True\n", " )\n", " \n", " # Generate response\n", " inputs = self.tokenizer(prompt, return_tensors=\"pt\").to(self.current_model.device)\n", " \n", " with torch.no_grad():\n", " outputs = self.current_model.generate(\n", " **inputs,\n", " max_new_tokens=max_tokens,\n", " do_sample=True,\n", " temperature=temperature,\n", " top_p=0.9,\n", " repetition_penalty=1.1,\n", " pad_token_id=self.tokenizer.eos_token_id\n", " )\n", " \n", " # Decode response\n", " response = self.tokenizer.decode(\n", " outputs[0][len(inputs['input_ids'][0]):], \n", " skip_special_tokens=True\n", " )\n", " \n", " return response\n", " \n", " def show_characters(self):\n", " \"\"\"Display available characters\"\"\"\n", " print(\"\\n\" + \"=\"*70)\n", " print(\"šŸŽ­ AVAILABLE CHARACTERS:\")\n", " print(\"=\"*70)\n", " for i, (name, info) in enumerate(self.characters.items(), 1):\n", " emoji = info[\"emoji\"]\n", " desc = info[\"description\"]\n", " current = \" ⭐ (CURRENT)\" if name == self.current_character else \"\"\n", " print(f\"\\n{i}. {emoji} {name}{current}\")\n", " print(f\" {desc}\")\n", " print(\"\\n\" + \"=\"*70 + \"\\n\")\n", "\n", "# Create the chat instance\n", "chat = CharacterChat()\n", "print(\"āœ… Character Chat System initialized!\")" ] }, { "cell_type": "markdown", "id": "9365b754", "metadata": {}, "source": [ "---\n", "## 6ļøāƒ£ View Available Characters" ] }, { "cell_type": "code", "execution_count": null, "id": "96b9749c", "metadata": {}, "outputs": [], "source": [ "chat.show_characters()" ] }, { "cell_type": "markdown", "id": "e7f6d0a1", "metadata": {}, "source": [ "---\n", "## 7ļøāƒ£ Chat with Mickey Mouse 🐭" ] }, { "cell_type": "code", "execution_count": null, "id": "d1098b5d", "metadata": {}, "outputs": [], "source": [ "chat.load_character(\"Mickey Mouse\")\n", "\n", "# Test with different prompts\n", "test_prompts = [\n", " \"Hello! How are you today?\",\n", " \"What's your favorite thing to do?\",\n", " \"Tell me about your friends\",\n", "]\n", "\n", "for prompt in test_prompts:\n", " response = chat.chat(prompt)\n", " print(f\"šŸ‘¤ You: {prompt}\")\n", " print(f\"🐭 Mickey: {response}\")\n", " print(\"-\" * 70 + \"\\n\")" ] }, { "cell_type": "markdown", "id": "785e2f85", "metadata": {}, "source": [ "---\n", "## 8ļøāƒ£ Chat with Yoda 🟢" ] }, { "cell_type": "code", "execution_count": null, "id": "679a53f3", "metadata": {}, "outputs": [], "source": [ "chat.load_character(\"Yoda\")\n", "\n", "test_prompts = [\n", " \"Hello! How are you today?\",\n", " \"What is the Force?\",\n", " \"Can you teach me to be a Jedi?\",\n", "]\n", "\n", "for prompt in test_prompts:\n", " response = chat.chat(prompt)\n", " print(f\"šŸ‘¤ You: {prompt}\")\n", " print(f\"🟢 Yoda: {response}\")\n", " print(\"-\" * 70 + \"\\n\")" ] }, { "cell_type": "markdown", "id": "03881450", "metadata": {}, "source": [ "---\n", "## 9ļøāƒ£ Chat with Spider-Man šŸ•·ļø" ] }, { "cell_type": "code", "execution_count": null, "id": "77515949", "metadata": {}, "outputs": [], "source": [ "chat.load_character(\"Spider-Man\")\n", "\n", "test_prompts = [\n", " \"Hello! How are you today?\",\n", " \"How do you swing between buildings?\",\n", " \"What's it like being a hero?\",\n", "]\n", "\n", "for prompt in test_prompts:\n", " response = chat.chat(prompt)\n", " print(f\"šŸ‘¤ You: {prompt}\")\n", " print(f\"šŸ•·ļø Spider-Man: {response}\")\n", " print(\"-\" * 70 + \"\\n\")" ] }, { "cell_type": "markdown", "id": "a3ac6fea", "metadata": {}, "source": [ "---\n", "## šŸ”Ÿ Interactive Chat Interface\n", "\n", "Chat freely with any character! Switch between them anytime." ] }, { "cell_type": "code", "execution_count": null, "id": "350d85ea", "metadata": {}, "outputs": [], "source": [ "def interactive_chat():\n", " \"\"\"\n", " Interactive chat interface - chat with any character!\n", " \n", " Commands:\n", " - Type your message to chat with the current character\n", " - Type 'switch' to change character\n", " - Type 'list' to see available characters\n", " - Type 'quit' to exit\n", " \"\"\"\n", " \n", " print(\"\\n\" + \"=\"*70)\n", " print(\"šŸŽ­ INTERACTIVE CHARACTER CHAT\")\n", " print(\"=\"*70)\n", " print(\"\\nCommands:\")\n", " print(\" - Type your message to chat with the current character\")\n", " print(\" - Type 'switch' to change character\")\n", " print(\" - Type 'list' to see available characters\")\n", " print(\" - Type 'quit' to exit\")\n", " print(\"\\n\" + \"=\"*70 + \"\\n\")\n", " \n", " # Load first character if none loaded\n", " if chat.current_character is None:\n", " chat.load_character(\"Mickey Mouse\")\n", " \n", " while True:\n", " # Get current character info\n", " emoji = chat.characters[chat.current_character][\"emoji\"]\n", " \n", " # Get user input\n", " user_input = input(f\"\\nšŸ‘¤ You: \").strip()\n", " \n", " if not user_input:\n", " continue\n", " \n", " # Handle commands\n", " if user_input.lower() == 'quit':\n", " print(\"\\nšŸ‘‹ Goodbye! Thanks for chatting!\\n\")\n", " break\n", " \n", " elif user_input.lower() == 'list':\n", " chat.show_characters()\n", " continue\n", " \n", " elif user_input.lower() == 'switch':\n", " chat.show_characters()\n", " \n", " character_choice = input(\"Enter character name (or press Enter to cancel): \").strip()\n", " \n", " if character_choice and character_choice in chat.characters:\n", " chat.load_character(character_choice)\n", " elif character_choice:\n", " print(f\"āŒ '{character_choice}' not found. Staying with {chat.current_character}\")\n", " \n", " continue\n", " \n", " # Generate response\n", " response = chat.chat(user_input)\n", " print(f\"{emoji} {chat.current_character}: {response}\")\n", "\n", "# Ready to start\n", "print(\"šŸ’¬ Ready to start interactive chat!\")\n", "print(\"Run: interactive_chat()\")" ] }, { "cell_type": "code", "execution_count": null, "id": "ecacfb59", "metadata": {}, "outputs": [], "source": [ "# Uncomment and run to start chatting!\n", "# interactive_chat()" ] }, { "cell_type": "markdown", "id": "2b8a32fc", "metadata": {}, "source": [ "---\n", "## šŸŽŖ BONUS: Character Comparison\n", "\n", "Ask the same question to all three characters and compare their responses!" ] }, { "cell_type": "code", "execution_count": null, "id": "12927d9c", "metadata": {}, "outputs": [], "source": [ "def compare_characters(question):\n", " \"\"\"Ask the same question to all three characters\"\"\"\n", " \n", " print(\"\\n\" + \"=\"*70)\n", " print(f\"ā“ QUESTION: {question}\")\n", " print(\"=\"*70 + \"\\n\")\n", " \n", " for character_name in [\"Mickey Mouse\", \"Yoda\", \"Spider-Man\"]:\n", " chat.load_character(character_name)\n", " response = chat.chat(question, max_tokens=60)\n", " \n", " emoji = chat.characters[character_name][\"emoji\"]\n", " print(f\"{emoji} {character_name}:\")\n", " print(f\" {response}\\n\")\n", " print(\"-\" * 70 + \"\\n\")\n", "\n", "print(\"āœ… Comparison function ready!\")" ] }, { "cell_type": "code", "execution_count": null, "id": "b0832fbc", "metadata": {}, "outputs": [], "source": [ "# Test with various questions\n", "questions = [\n", " \"What makes you happy?\",\n", " \"What's your biggest challenge?\",\n", " \"Do you have any advice for me?\",\n", "]\n", "\n", "for q in questions:\n", " compare_characters(q)" ] }, { "cell_type": "markdown", "id": "5971ef5d", "metadata": {}, "source": [ "---\n", "## šŸŽÆ Summary\n", "\n", "You've successfully created 3 character text generators!\n", "\n", "**What you can do:**\n", "1. āœ… Chat with Mickey Mouse, Yoda, or Spider-Man\n", "2. āœ… Switch between characters anytime\n", "3. āœ… Compare how each character responds to the same question\n", "4. āœ… Use the interactive chat for natural conversations\n", "\n", "**Each character maintains their unique personality:**\n", "- 🐭 Mickey Mouse: Cheerful, optimistic, uses \"Oh boy!\" and \"Haha!\"\n", "- 🟢 Yoda: Wise, speaks in reverse syntax, uses \"Hmm\" and \"Yes\"\n", "- šŸ•·ļø Spider-Man: Witty, heroic, makes jokes about swinging and web-slinging\n", "\n", "**Try your own prompts and have fun chatting!** šŸŽ‰" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.9" } }, "nbformat": 4, "nbformat_minor": 5 }