diff --git a/all_agents_tutorials/TutorAgent.ipynb b/all_agents_tutorials/TutorAgent.ipynb new file mode 100644 index 0000000..143e0f3 --- /dev/null +++ b/all_agents_tutorials/TutorAgent.ipynb @@ -0,0 +1,847 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "language_info": { + "name": "python" + } + }, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "\n", + "\n", + "# Installation\n", + "\n" + ], + "metadata": { + "id": "ypAKjv4Uawcf" + } + }, + { + "cell_type": "markdown", + "source": [ + "" + ], + "metadata": { + "id": "anzVSy3wajEa" + } + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "CbdP1gVOQy75" + }, + "outputs": [], + "source": [ + "!pip install -qU pypdf\n", + "!pip install -qU pypdf scikit-learn langchain_community\n", + "!pip install --quiet langchain langchain-text-splitters langchain_google_genai\n", + "!pip install --quiet langchain_chroma\n", + "!pip install --quiet cohere\n", + "!pip install --upgrade --quiet langchain\n", + "!pip install --quiet PyPDF2\n", + "\n", + "!pip install -q cohere\n", + "\n", + "\n", + "!pip install --quiet google-api-python-client google-auth-httplib2 google-auth-oauthlib PyPDF2 langgraph\n" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Imports" + ], + "metadata": { + "id": "MeB7QPepbbXS" + } + }, + { + "cell_type": "code", + "source": [ + "from google.colab import userdata\n", + "from langchain_core.prompts import ChatPromptTemplate\n", + "import os\n", + "import google.generativeai as genai\n", + "from langchain_google_genai import GoogleGenerativeAI\n", + "import sqlite3\n", + "from google.colab import files\n", + "import PyPDF2\n", + "from langchain.text_splitter import RecursiveCharacterTextSplitter\n", + "from langchain_chroma import Chroma\n", + "from langchain.embeddings import CohereEmbeddings\n", + "from langchain.schema import Document\n", + "from uuid import uuid4\n", + "from langgraph.store.memory import InMemoryStore\n", + "from langchain.schema import Document\n", + "from pprint import pprint\n", + "from typing import Any, List, TypedDict\n", + "from IPython.display import display, Markdown\n", + "from langchain_core.runnables.config import RunnableConfig\n", + "from langgraph.store.base import BaseStore\n" + ], + "metadata": { + "id": "oijmdHHsbGJ2" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "source": [ + "# LLM Call" + ], + "metadata": { + "id": "GeNYofSkbjpK" + } + }, + { + "cell_type": "code", + "source": [ + "\n", + "\n", + "GEMINI_API_KEY = userdata.get(\"GEMINI_API_KEY\")\n", + "\n", + "genai.configure(api_key=GEMINI_API_KEY)\n", + "\n", + "llm = GoogleGenerativeAI(google_api_key=GEMINI_API_KEY, model=\"gemini-1.5-flash\")" + ], + "metadata": { + "id": "lu5llYaEQ3SQ" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "source": [], + "metadata": { + "id": "joxxrwvObonC" + } + }, + { + "cell_type": "markdown", + "source": [ + "# Upload pdf and store in vector database" + ], + "metadata": { + "id": "7Bp7nQrvbpq6" + } + }, + { + "cell_type": "code", + "source": [ + "import sqlite3\n", + "from uuid import uuid4\n", + "from langchain.schema import Document\n", + "from langchain.embeddings import CohereEmbeddings\n", + "from langchain.text_splitter import RecursiveCharacterTextSplitter\n", + "from langchain.vectorstores import Chroma\n", + "from IPython.display import Markdown\n", + "from langchain_core.runnables.config import RunnableConfig\n", + "from langgraph.store.base import BaseStore\n", + "from langgraph.store.memory import InMemoryStore\n", + "from typing import List, Any, TypedDict\n", + "from pprint import pprint\n", + "\n", + "import PyPDF2\n", + "from google.colab import files\n", + "\n", + "# SQLite database setup\n", + "db_path = \"uploaded_files_metadata.db\"\n", + "\n", + "# Function to initialize the database and create table if not exists\n", + "def initialize_db():\n", + " conn = sqlite3.connect(db_path)\n", + " cursor = conn.cursor()\n", + " cursor.execute('''\n", + " CREATE TABLE IF NOT EXISTS uploaded_files (\n", + " id INTEGER PRIMARY KEY AUTOINCREMENT,\n", + " collection_name TEXT UNIQUE,\n", + " file_name TEXT\n", + " )\n", + " ''')\n", + " conn.commit()\n", + " conn.close()\n", + "\n", + "# Function to insert file metadata into SQLite\n", + "def save_metadata(collection_name, file_name):\n", + " conn = sqlite3.connect(db_path)\n", + " cursor = conn.cursor()\n", + " cursor.execute('''\n", + " INSERT OR IGNORE INTO uploaded_files (collection_name, file_name)\n", + " VALUES (?, ?)\n", + " ''', (collection_name, file_name))\n", + " conn.commit()\n", + " conn.close()\n", + "\n", + "# Function to load metadata from SQLite\n", + "def load_metadata():\n", + " conn = sqlite3.connect(db_path)\n", + " cursor = conn.cursor()\n", + " cursor.execute('SELECT collection_name, file_name FROM uploaded_files')\n", + " rows = cursor.fetchall()\n", + " conn.close()\n", + "\n", + " return {row[0]: row[1] for row in rows}\n", + "\n", + "# Load and split PDF content\n", + "def load_pdf(file_path):\n", + " try:\n", + " with open(file_path, 'rb') as file:\n", + " reader = PyPDF2.PdfReader(file)\n", + " text = \"\"\n", + " for page in reader.pages:\n", + " text += page.extract_text() + \"\\n\"\n", + " return text.strip()\n", + " except Exception as e:\n", + " print(f\"Error loading PDF: {e}\")\n", + " return None\n", + "\n", + "# Process PDF to update vector store\n", + "def process_pdf(file_name, collection_name):\n", + " pdf_content = load_pdf(file_name)\n", + " if pdf_content:\n", + " print(\"PDF content loaded successfully.\")\n", + "\n", + " cohere_api_key = userdata.get(\"Embedding_API\") # Replace with actual key\n", + " embedding_function = CohereEmbeddings(\n", + " model=\"embed-english-light-v2.0\",\n", + " cohere_api_key=cohere_api_key,\n", + " user_agent=\"LangChainCohere\"\n", + " )\n", + "\n", + "\n", + " vector_db = Chroma(\n", + " collection_name=collection_name,\n", + " embedding_function=embedding_function\n", + " )\n", + "\n", + " text_splitter = RecursiveCharacterTextSplitter(chunk_size=7500, chunk_overlap=100)\n", + " docs = [Document(page_content=pdf_content)]\n", + " chunks = text_splitter.split_documents(docs)\n", + "\n", + " vector_db.add_texts([chunk.page_content for chunk in chunks])\n", + "\n", + " print(f\"PDF data from {file_name} updated in vector_db.\")\n", + " save_metadata(collection_name, file_name)\n", + "\n", + "# Handle file selection or upload\n", + "def handle_file_selection() -> str:\n", + " uploaded_files_metadata = load_metadata()\n", + " if uploaded_files_metadata:\n", + " print(\"Previously uploaded files:\")\n", + " for i, (collection, file_name) in enumerate(uploaded_files_metadata.items()):\n", + " print(f\"{i + 1}: {file_name} (Collection: {collection})\")\n", + " choice = input(\"Enter the number of the file to use or 'N' to upload a new one: \")\n", + "\n", + " if choice.upper() == 'N':\n", + " uploaded = files.upload()\n", + " if uploaded:\n", + " uploaded_file_path = next(iter(uploaded))\n", + " print(f\"Uploaded file: {uploaded_file_path}\")\n", + "\n", + " unique_collection_name = f\"pdf_chunks_{uuid4()}\"\n", + " process_pdf(uploaded_file_path, unique_collection_name)\n", + " return unique_collection_name\n", + " else:\n", + " chosen_index = int(choice) - 1\n", + " chosen_collection = list(uploaded_files_metadata.keys())[chosen_index]\n", + " print(f\"Using previously uploaded file: {uploaded_files_metadata[chosen_collection]}\")\n", + " return chosen_collection\n", + " else:\n", + " print(\"No files found in the vector DB. Please upload a new file.\")\n", + " uploaded = files.upload()\n", + " if uploaded:\n", + " uploaded_file_path = next(iter(uploaded))\n", + " print(f\"Uploaded file: {uploaded_file_path}\")\n", + "\n", + " unique_collection_name = f\"pdf_chunks_{uuid4()}\"\n", + " process_pdf(uploaded_file_path, unique_collection_name)\n", + " return unique_collection_name\n", + "\n", + "# Initialize the database\n", + "initialize_db()\n", + "\n", + "# Get the collection name based on user input\n", + "collection_name = handle_file_selection()" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "PkJDyirWQ5Pc", + "outputId": "e7158158-ff45-4b68-bea7-653c6fd8a065" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Previously uploaded files:\n", + "1: python-basics-sample-chapters.pdf (Collection: pdf_chunks_675d56f1-878a-415c-abba-c087eaaea650)\n", + "Enter the number of the file to use or 'N' to upload a new one: 1\n", + "Using previously uploaded file: python-basics-sample-chapters.pdf\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Functions and Main query" + ], + "metadata": { + "id": "VXj9KBkacB5c" + } + }, + { + "cell_type": "code", + "source": [ + "from langchain.schema import Document\n", + "from pprint import pprint\n", + "from typing import Any, List, TypedDict\n", + "from IPython.display import display, Markdown\n", + "from langchain_core.runnables.config import RunnableConfig\n", + "from langgraph.checkpoint.memory import MemorySaver\n", + "import json\n", + "from langgraph.store.base import BaseStore\n", + "\n", + "class Question(TypedDict):\n", + " question: str\n", + " options: dict[str, str]\n", + " answer: str\n", + " user_response: str\n", + "\n", + "class StateDocument(TypedDict):\n", + " questions: List[Question]\n", + " total_questions: int\n", + " current_question: int\n", + " human_input: str\n", + " ai_output: str\n", + " human_input_2: str\n", + " chat: str\n", + " decision: str\n", + " score: int\n", + " reason : str\n", + "\n", + "\n", + "from IPython.display import Markdown\n", + "from langgraph.store.memory import InMemoryStore\n", + "\n", + "config = {\"configurable\": {\"user_id\": input(\"Enter your username: \")}}\n", + "across_thread_memory = InMemoryStore()\n", + "\n", + "\n", + "# Define a VectorDatabase class to interact with the Chroma database\n", + "class VectorDatabase:\n", + " def __init__(self, chroma_db: Chroma):\n", + " self.chroma_db = chroma_db\n", + "\n", + " def similarity_search(self, query: str, k: int) -> List[Any]:\n", + " \"\"\"Performs a similarity search using the Chroma database.\"\"\"\n", + " return self.chroma_db.similarity_search(query, k=k)\n", + "\n", + "def questions(state: StateDocument) -> StateDocument:\n", + " while True:\n", + "\n", + " total_questions = input(\"How many questions do you want to generate (0 to 25): \")\n", + " try:\n", + " total_questions = int(total_questions) # Convert to integer\n", + " if 0 < total_questions <= 25:\n", + " state[\"human_input\"] = total_questions\n", + " break # Exit the loop if input is valid\n", + " else:\n", + " print(\"Invalid input. Please enter a number between 1 and 25.\")\n", + " except ValueError:\n", + " print(\"Invalid input. Please enter a valid number.\")\n", + " return state\n", + "\n", + "\n", + "def node_0(state: StateDocument) -> StateDocument:\n", + " state[\"decision\"] = input(\"Type 'chat' to chat or 'quiz' to start the quiz: \").lower().strip()\n", + " if state[\"decision\"] == \"chat\":\n", + " chatbot(vector_db, state)\n", + " else:\n", + " questions(state)\n", + " node_2(vector_db, state)\n", + " display_quiz(state)\n", + " return state\n", + "\n", + "def chatbot(db: VectorDatabase, state: StateDocument) -> StateDocument:\n", + " while True:\n", + " state[\"human_input_2\"] = input(\"What do you want to know about? (type 'quit' to exit chat): \").strip()\n", + " if state[\"human_input_2\"].lower() == \"quit\":\n", + " print(\"Exiting chat mode.\")\n", + " break\n", + " # Pass config and across_thread_memory to node_3\n", + " node_3(db, state, config, across_thread_memory)\n", + " display(Markdown(f\"Chat response: {state['chat']}\"))\n", + " quiz_ch = input(\"do you want to continue to quiz yes/no\").lower().strip()\n", + " if quiz_ch == \"yes\":\n", + " questions(state)\n", + " node_2(vector_db, state)\n", + " display_quiz(state)\n", + " return state\n", + "\n", + "\n", + "def clean_json_input(raw_input):\n", + " \"\"\"\n", + " Cleans the raw JSON input by removing enclosing backticks and the word 'json'.\n", + "\n", + " Args:\n", + " raw_input (str): The raw JSON string with backticks and 'json'.\n", + "\n", + " Returns:\n", + " dict: A Python dictionary representation of the cleaned JSON.\n", + " \"\"\"\n", + " try:\n", + " # Remove backticks and 'json' keyword\n", + " cleaned_input = raw_input.strip(\"```\").replace(\"json\", \"\").strip()\n", + " cleaned_input = cleaned_input.replace(\"```\", \"\")\n", + " # print(cleaned_input)\n", + " # Parse the cleaned JSON string into a dictionary\n", + " return json.loads(cleaned_input)\n", + "\n", + " except json.JSONDecodeError as e:\n", + " return {\"error\": f\"Invalid JSON format: {e}\"}\n", + "\n", + " # Clean the input and print the result\n", + " cleaned_json = clean_json_input(raw_input)\n", + " return json.dumps(cleaned_json, indent=4)\n", + "\n", + "\n", + "def parse_questions(ai_output):\n", + " \"\"\"\n", + " Parses multiple questions, options, answers, and user responses from AI output and stores them.\n", + "\n", + " Args:\n", + " ai_output: The output from the language model, expected to be in JSON format as a list of questions.\n", + "\n", + " Returns:\n", + " A list of dictionaries representing the questions in the desired format.\n", + " \"\"\"\n", + " try:\n", + " # Parse the AI output into a Python object\n", + " if isinstance(ai_output, list):\n", + " # print(\"Ai out put is list\")\n", + " parsed_output = ai_output\n", + " else:\n", + " # print(\"Ai out put is Json\")\n", + " parsed_output = json.loads(ai_output)\n", + "\n", + " # # Validate the structure\n", + " if not isinstance(parsed_output, list):\n", + " raise ValueError(\"AI output must be a list of questions.\")\n", + "\n", + "\n", + " # Process each question and store it\n", + " questions = []\n", + " for question_data in parsed_output:\n", + " question = question_data.get(\"question\")\n", + " options = question_data.get(\"options\")\n", + " answer = question_data.get(\"answer\")\n", + "\n", + " # Validate required fields\n", + " if not question or not options or not answer:\n", + " raise ValueError(\"Each question must include 'question', 'options', and 'answer'.\")\n", + "\n", + " if not isinstance(options, dict):\n", + " raise ValueError(\"Options must be a dictionary with keys (A, B, C, D).\")\n", + " structured_options = [\n", + " f\"{key}: {value}\" for key, value in options.items()]\n", + "\n", + " # Add the question to the list\n", + " questions.append({\n", + " \"question\": question,\n", + " \"options\": structured_options,\n", + " \"answer\": answer,\n", + " \"user_response\": None # Default value\n", + " })\n", + "\n", + " return questions\n", + "\n", + " except json.JSONDecodeError:\n", + " print(\"Error: AI output is not valid JSON.\")\n", + " except ValueError as e:\n", + " print(f\"Error: {e}\")\n", + " except Exception as e:\n", + " print(f\"Unexpected error: {e}\")\n", + "\n", + " return None\n", + "\n", + "\n", + "def node_2(db: VectorDatabase, state: StateDocument) -> StateDocument:\n", + "\n", + " no_of_questions = state[\"human_input\"]\n", + " state[\"total_questions\"] = int(no_of_questions)\n", + " # Format the prompt for quiz creation\n", + " prompt = f\"\"\"\n", + " You are an expert quiz creator. Create {no_of_questions} quiz questions. Each question should have four multiple-choice options (A, B, C, D), and provide the correct answer.\n", + "\n", + " Strictly adhere to the following format for each question:\n", + " [\n", + " {{\n", + " 'question': '[Question Text]',\n", + " 'options': {{\n", + " 'A': '[Option A]',\n", + " 'B': '[Option B]',\n", + " 'C': '[Option C]',\n", + " 'D': '[Option D]'\n", + " }},\n", + " 'answer': '[Correct Option Letter]' # Only use A, B, C, or D\n", + " }},\n", + " ...\n", + " ]\n", + "\n", + " For example:\n", + " [\n", + " {{\n", + " 'question': 'What is the capital of France?',\n", + " 'options': {{\n", + " 'A': 'Berlin',\n", + " 'B': 'Madrid',\n", + " 'C': 'Paris',\n", + " 'D': 'Rome'\n", + " }},\n", + " 'answer': 'C'\n", + " }}\n", + " ]\n", + "\n", + " Do not deviate from this format. Do not hallucinate. Provide all questions in this exact structure.\n", + " \"\"\"\n", + "\n", + " # Retrieve context from the database\n", + " relevant_docs = db.chroma_db.get()\n", + " documents = [Document(page_content=text) for text in relevant_docs[\"documents\"]]\n", + " context = \" \".join([doc.page_content for doc in documents])\n", + "\n", + " prompt_with_context = f\"{prompt}\\n\\nContext: {context}\"\n", + "\n", + " # Call your LLM here (replace with actual LLM call)\n", + " result = llm.invoke(prompt_with_context)\n", + " state[\"questionset\"] = result\n", + " clean = clean_json_input(result)\n", + " parsed = parse_questions(clean)\n", + " state[\"questions\"] = parsed\n", + " # print(parsed)\n", + " # return state\n", + "\n", + "def node_3(db: VectorDatabase, state: StateDocument, config: RunnableConfig, store: BaseStore) -> StateDocument:\n", + " # Retrieve context related to recent PDF for chat input\n", + " user_id = config[\"configurable\"][\"user_id\"]\n", + " namespace = (user_id)\n", + " existing_memory = store.get(namespace, \"user_memory\")\n", + "\n", + " if existing_memory:\n", + " existing_memory_content = existing_memory.value.get('memory')\n", + " else:\n", + " existing_memory_content = \"No existing memory found.\"\n", + "\n", + "\n", + " # Check if existing_memory is a dictionary and has a 'memory' key.\n", + " # If not, assume it's the memory content and use it directly.\n", + "\n", + "\n", + " relevant_docs = db.similarity_search(state[\"human_input_2\"], k=2)\n", + " context = \" \".join([doc.page_content for doc in relevant_docs])\n", + "\n", + " # Construct the prompt with context\n", + " prompt = f\"\"\"\n", + " Provide information based on the context below.\n", + " Don't hallucinate or web search information.\n", + " If user greet you then interact with him greet him ask him how can you help him today.\n", + " But when user ask any question then provide him with answer and at end say how can i assist you further\n", + " or prompt similar to it just to help out user.\n", + " Query input: \"{state['human_input_2']}\"\n", + " Context: {context}\n", + "\n", + " You are a helpful assistant with memory that provides information about the user.\n", + " If you have memory for this user, use it to personalize your responses.\n", + " Here is the memory (it may be empty): {existing_memory_content}\n", + " User: {state[\"human_input_2\"]}\"\"\"\n", + "\n", + " # Invoke the LLM with the prompt, no need to format again\n", + " state[\"chat\"] = llm.invoke(prompt)\n", + " store.put(namespace, \"user_memory\", {\"memory\": state[\"chat\"]}) # Use send_message and extract the text from the response\n", + " return state\n", + "\n", + "\n", + "\n", + "cohere_api_key = userdata.get(\"Embedding_API\") # Replace with actual key\n", + "embedding_function = CohereEmbeddings(\n", + " model=\"embed-english-light-v2.0\",\n", + " cohere_api_key=cohere_api_key,\n", + " user_agent=\"LangChainCohere\"\n", + ")\n", + "\n", + "def display_quiz(state: StateDocument) -> StateDocument:\n", + " \"\"\"\n", + " Conducts a quiz by asking questions to the user and scoring their answers.\n", + "\n", + " Args:\n", + " state (STATE): The current state containing questions, scores, and progress.\n", + "\n", + " Returns:\n", + " STATE: The updated state after the quiz has been completed.\n", + " \"\"\"\n", + " state['current_question'] = 0\n", + " # Loop through all questions\n", + " while state['current_question'] < state['total_questions']:\n", + " # Get the current question data\n", + " question_data = state['questions'][state['current_question']]\n", + " question_text = question_data[\"question\"]\n", + " options = question_data[\"options\"] # Get options for the current question\n", + "\n", + " # Present the question and options to the user\n", + " print(f\"\\n\\nQuestion {state['current_question'] + 1}: {question_text}\\n\")\n", + " for option in options:\n", + " print(option)\n", + " # Instruct the user on how to answer\n", + " display(Markdown(\"\\nPlease answer with A, B, C, or D.\"))\n", + "\n", + " # Get and validate user input\n", + " while True:\n", + " user_answer = input(\"Your answer: \").strip().lower() # Get user input and strip whitespace\n", + " if user_answer in ['a', 'b', 'c', 'd']:\n", + " break # Valid answer; exit the loop\n", + " else:\n", + " display(Markdown(\"\\nInvalid answer. Please answer with A, B, C, or D.\"))\n", + "\n", + " # Check the answer and update score\n", + " if user_answer.upper() == question_data[\"answer\"]: # Compare with the correct answer in uppercase\n", + " score = 1 # Award 1 point for a correct answer\n", + " # print(\"Correct!\\n\\n Explanation: \", question_data[\"explanation\"])\n", + " display(Markdown(\"Correct!\"))\n", + " else:\n", + " score = 0\n", + " # print(\"Incorrect. The correct answer was:\", question_data[\"answer\"], \"\\n\\n Explanation: \", question_data[\"explanation\"])\n", + " display(Markdown(f\"Incorrect. The correct answer was: {question_data['answer']}\"))\n", + "\n", + "\n", + " # Update the question's score and the overall total score\n", + " question_data[\"score\"] = score # Store score in the question data\n", + " state['score'] += score # Update total score\n", + " state['current_question'] += 1 # Move to the next question\n", + "\n", + " # Inform the user that the quiz is complete\n", + " display(Markdown(f\"Quiz finished! Your total score is: {state['score']}/{state['total_questions']}\"))\n", + " return state\n", + "\n", + "\n", + "\n", + "state: StateDocument = {\"human_input\": \"\", \"human_input_2\": \"\", \"decision\": \"\", \"chat\": \"\", \"ai_output\": \"\", \"score\": 0,\"reason\":\"\"}\n", + "\n", + "if collection_name:\n", + "\n", + " vector_db = VectorDatabase(Chroma(collection_name=collection_name, embedding_function=embedding_function))\n", + "state = node_0(state)\n" + ], + "metadata": { + "id": "6Tj3HFcPRG-q", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 1000 + }, + "outputId": "47ad5512-2e49-4ea0-bedd-95540f53414b" + }, + "execution_count": null, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Enter your username: ujjan\n", + "Type 'chat' to chat or 'quiz' to start the quiz: chat\n", + "What do you want to know about? (type 'quit' to exit chat): hi what is this file all about\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "Chat response: Hi there! How can I help you today?\n\nThis file is a book about learning Python programming. The first half focuses on fundamental programming concepts, while the second half tackles more advanced, real-world problems. It emphasizes a hands-on approach, encouraging readers to type code rather than copy-paste, and includes exercises and challenges with solutions. The book also provides access to online quizzes, a code repository, and additional learning resources. The estimated time to complete the book varies depending on prior programming experience.\n\nHow can I assist you further?\n" + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "What do you want to know about? (type 'quit' to exit chat): quit\n", + "Exiting chat mode.\n", + "do you want to continue to quiz yes/noyes\n", + "How many questions do you want to generate (0 to 25): 3\n", + "\n", + "\n", + "Question 1: What is the output of the following Python code?\n", + "python\n", + "string1 = \"abra\"\n", + "string2 = \"cadabra\"\n", + "magic_string = string1 + string2\n", + "print(magic_string)\n", + "\n", + "\n", + "A: abra cadabra\n", + "B: abracadabra\n", + "C: Error: cannot concatenate strings\n", + "D: 1\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "\nPlease answer with A, B, C, or D." + }, + "metadata": {} + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Your answer: b\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "Correct!" + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n", + "\n", + "Question 2: Which string method removes whitespace from the beginning and end of a string?\n", + "\n", + "A: .rstrip()\n", + "B: .lstrip()\n", + "C: .strip()\n", + "D: .lower()\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "\nPlease answer with A, B, C, or D." + }, + "metadata": {} + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Your answer: d\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "Incorrect. The correct answer was: C" + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n", + "\n", + "Question 3: What is the output of the following Python code?\n", + "python\n", + "my_string = \"Hello, World!\"\n", + "print(my_string.find(\"World\"))\n", + "\n", + "\n", + "A: 7\n", + "B: Error: .find() method not found\n", + "C: 0\n", + "D: False\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "\nPlease answer with A, B, C, or D." + }, + "metadata": {} + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Your answer: 1\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "\nInvalid answer. Please answer with A, B, C, or D." + }, + "metadata": {} + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Your answer: a\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "Correct!" + }, + "metadata": {} + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "Quiz finished! Your total score is: 2/3" + }, + "metadata": {} + } + ] + } + ] +}