diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..47efcc7
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,4 @@
+# API Keys and Other Secrets
+OPENAI_API_KEY="something"
+MISTRAL_API_KEY="anoher-secret"
+HUGGINGFACE_TOKEN="and-anotherg"
diff --git a/.gitignore b/.gitignore
index 5eff2a9..691c57a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,7 +13,7 @@ slides/
# Distribution / packaging
.Python
-env/
+.venv/
build/
develop-eggs/
dist/
diff --git a/data/docs/who-docs/Cholera-Report.pdf b/data/docs/who-docs/Cholera-Report.pdf
new file mode 100644
index 0000000..7ecf47d
Binary files /dev/null and b/data/docs/who-docs/Cholera-Report.pdf differ
diff --git a/data/docs/who-docs/Dengue-Global-situation.pdf b/data/docs/who-docs/Dengue-Global-situation.pdf
new file mode 100644
index 0000000..defa68c
Binary files /dev/null and b/data/docs/who-docs/Dengue-Global-situation.pdf differ
diff --git a/data/docs/who-docs/Hepatitis-Chad.pdf b/data/docs/who-docs/Hepatitis-Chad.pdf
new file mode 100644
index 0000000..502796a
Binary files /dev/null and b/data/docs/who-docs/Hepatitis-Chad.pdf differ
diff --git a/data/docs/who-docs/MidEast-COVID.pdf b/data/docs/who-docs/MidEast-COVID.pdf
new file mode 100644
index 0000000..0a76ac4
Binary files /dev/null and b/data/docs/who-docs/MidEast-COVID.pdf differ
diff --git a/notebooks/malawi-nov-24/2-document-classification-with-sklearn.ipynb b/notebooks/malawi-nov-24/2-document-classification-with-sklearn.ipynb
deleted file mode 100644
index 20c458b..0000000
--- a/notebooks/malawi-nov-24/2-document-classification-with-sklearn.ipynb
+++ /dev/null
@@ -1,575 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Building a Document Classification System\n",
- "The NumPy (Numerical Python) library used for working iwith arrays, and the Scikit-learn library is a python library built on NumPy, SciPy and matplotlib for data analytics and machine learning. The NLTK (Natural Language Toolkit) provides access to over 50 corpora and lexical resources such as WordNet, along with a suite of text processing libraries for classification, tokenization, stemming, tagging, parsing, and semantic reasoning, wrappers for industrial-strength NLP libraries."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Ensuring that you have the necessary libraries\n",
- "# !pip install nltk\n",
- "# !pip install numpy\n",
- "# !pip install scikit-learn"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "import nltk\n",
- "from nltk.corpus import reuters\n",
- "from sklearn.feature_extraction.text import TfidfVectorizer\n",
- "from sklearn.model_selection import train_test_split\n",
- "from sklearn.svm import LinearSVC\n",
- "from sklearn.metrics import accuracy_score, classification_report\n",
- "\n",
- "from sklearn.feature_extraction.text import CountVectorizer\n",
- "from sklearn.naive_bayes import MultinomialNB"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 1. Load your data"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The Reuters-21578 dataset is one of the most widely used data collections for text categorization research. It is a collection of documents with news articles and the original corpus has 10,369 documents and a vocabulary of 29,930 word and has labeled categories such as \"earnings\", \"acquisitions\".. etc. You can read metadata about the dataset on [Hugging Face](https://huggingface.co/datasets/ucirvine/reuters21578)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "[nltk_data] Downloading package reuters to\n",
- "[nltk_data] /Users/dunstanmatekenya/nltk_data...\n",
- "[nltk_data] Package reuters is already up-to-date!\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 2,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# download the dataset\n",
- "nltk.download('reuters')"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Load the Reuters-21578 dataset\n",
- "documents = reuters.fileids()\n",
- "train_docs = list(filter(lambda doc: doc.startswith(\"train\"), documents))\n",
- "test_docs = list(filter(lambda doc: doc.startswith(\"test\"), documents))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 2. Prepare your data"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Prepare the data by extracting the raw text and category labels for both the training and testing documents. Assumption is that each document has only one category label, so we take only the first category label for each document."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Prepare the data\n",
- "train_data = [reuters.raw(doc_id) for doc_id in train_docs]\n",
- "train_labels = [reuters.categories(doc_id)[0] for doc_id in train_docs]\n",
- "test_data = [reuters.raw(doc_id) for doc_id in test_docs]\n",
- "test_labels = [reuters.categories(doc_id)[0] for doc_id in test_docs]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Question-How many different classes are in the training data?"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Explore some of the training examples"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 17,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Article content: COMPUTER TERMINAL SYSTEMS <CPML> COMPLETES SALE\n",
- " Computer Terminal Systems Inc said\n",
- " it has completed the sale of 200,000 shares of its common\n",
- " stock, and warrants to acquire an additional one mln shares, to\n",
- " <Sedio N.V.> of Lugano, Switzerland for 50,000 dlrs.\n",
- " The company said the warrants are exercisable for five\n",
- " years at a purchase price of .125 dlrs per share.\n",
- " Computer Terminal said Sedio also has the right to buy\n",
- " additional shares and increase its total holdings up to 40 pct\n",
- " of the Computer Terminal's outstanding common stock under\n",
- " certain circumstances involving change of control at the\n",
- " company.\n",
- " The company said if the conditions occur the warrants would\n",
- " be exercisable at a price equal to 75 pct of its common stock's\n",
- " market price at the time, not to exceed 1.50 dlrs per share.\n",
- " Computer Terminal also said it sold the technolgy rights to\n",
- " its Dot Matrix impact technology, including any future\n",
- " improvements, to <Woodco Inc> of Houston, Tex. for 200,000\n",
- " dlrs. But, it said it would continue to be the exclusive\n",
- " worldwide licensee of the technology for Woodco.\n",
- " The company said the moves were part of its reorganization\n",
- " plan and would help pay current operation costs and ensure\n",
- " product delivery.\n",
- " Computer Terminal makes computer generated labels, forms,\n",
- " tags and ticket printers and terminals.\n",
- " \n",
- "\n",
- " n\\, Label: acq\n"
- ]
- }
- ],
- "source": [
- "print(\"Article content: {} n\\, Label: {}\".format(train_data[1], train_labels[1]))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 3. Vectorizing the text data"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "- Vectorize the text data using the TfidVectorizer from scikit-learn. TF-IDF is an abbreviation for Term Frequency Inverse Document Frequency. This is very common algorithm to transform text into a meaningful representation of numbers which is used to fit machine algorithm for prediction. \n",
- "- Its worth noting that nowadays, this vectorization approach is not commonly used. We will cover **word embeddings** tomorrow which is a better approach to represent words as numbers because **vector embeddings** can capture semantic meanings better.\n",
- "\n",
- "For the sklearn TF-IDF vectorizer, you can learn more about it [here](https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfVectorizer.html)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 18,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Vectorize the text data\n",
- "vectorizer = TfidfVectorizer(stop_words=\"english\", max_features=1000)\n",
- "X_train = vectorizer.fit_transform(train_data)\n",
- "X_test = vectorizer.transform(test_data)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### Question: What role are the ```stop words``` playing in the code above? You might have learned this from Prof. Mohamad Ali already."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 4. Training a Linear Support Vector Machine (LinearSVC) classifier using the vectorized training data and corresponding label"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 20,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "
LinearSVC()
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
LinearSVC()
"
- ],
- "text/plain": [
- "LinearSVC()"
- ]
- },
- "execution_count": 20,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# Train the classifier\n",
- "classifier = LinearSVC()\n",
- "classifier.fit(X_train, train_labels)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "classifier."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 5. Evaluate the classifier used and calculate the accuracy score as well as some other metrics (Precision, Recall and F-1 score)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 21,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Accuracy: 0.876117919841007\n",
- " precision recall f1-score support\n",
- "\n",
- " acq 0.95 0.96 0.96 719\n",
- " alum 0.33 0.18 0.24 22\n",
- " barley 1.00 0.71 0.83 14\n",
- " bop 0.77 0.80 0.79 30\n",
- " carcass 0.79 0.65 0.71 17\n",
- " castor-oil 0.00 0.00 0.00 1\n",
- " cocoa 0.94 1.00 0.97 17\n",
- " coconut 0.00 0.00 0.00 2\n",
- " coconut-oil 0.00 0.00 0.00 2\n",
- " coffee 0.89 0.96 0.92 25\n",
- " copper 0.93 0.93 0.93 15\n",
- " corn 0.85 0.81 0.83 48\n",
- " cotton 1.00 0.86 0.92 14\n",
- " cpi 0.62 0.62 0.62 24\n",
- " cpu 0.00 0.00 0.00 1\n",
- " crude 0.79 0.93 0.86 182\n",
- " dfl 0.00 0.00 0.00 1\n",
- " dlr 0.70 0.72 0.71 43\n",
- " dmk 0.00 0.00 0.00 1\n",
- " earn 0.98 0.99 0.98 1083\n",
- " fuel 1.00 0.22 0.36 9\n",
- " gas 0.75 0.33 0.46 9\n",
- " gnp 0.59 0.89 0.71 19\n",
- " gold 0.96 0.96 0.96 26\n",
- " grain 0.71 0.77 0.74 77\n",
- " groundnut 0.00 0.00 0.00 3\n",
- " heat 1.00 0.75 0.86 4\n",
- " hog 1.00 0.50 0.67 4\n",
- " housing 1.00 0.67 0.80 3\n",
- " income 1.00 0.80 0.89 5\n",
- " instal-debt 1.00 1.00 1.00 1\n",
- " interest 0.78 0.76 0.77 124\n",
- " ipi 1.00 1.00 1.00 11\n",
- " iron-steel 0.69 0.64 0.67 14\n",
- " jet 0.00 0.00 0.00 1\n",
- " jobs 0.73 0.85 0.79 13\n",
- " l-cattle 0.00 0.00 0.00 2\n",
- " lead 0.83 0.42 0.56 12\n",
- " lei 1.00 1.00 1.00 3\n",
- " livestock 0.50 0.50 0.50 6\n",
- " lumber 0.00 0.00 0.00 5\n",
- " meal-feed 0.20 0.17 0.18 6\n",
- " money-fx 0.65 0.65 0.65 96\n",
- " money-supply 0.80 0.83 0.81 29\n",
- " naphtha 0.00 0.00 0.00 1\n",
- " nat-gas 0.64 0.54 0.58 13\n",
- " nickel 0.00 0.00 0.00 1\n",
- " oilseed 0.54 0.54 0.54 13\n",
- " orange 0.75 0.33 0.46 9\n",
- " palladium 0.00 0.00 0.00 1\n",
- " palm-oil 0.67 1.00 0.80 4\n",
- " pet-chem 1.00 0.50 0.67 6\n",
- " platinum 0.00 0.00 0.00 3\n",
- " potato 1.00 0.67 0.80 3\n",
- " propane 0.00 0.00 0.00 2\n",
- " rape-oil 0.00 0.00 0.00 1\n",
- " reserves 1.00 0.64 0.78 14\n",
- " retail 1.00 1.00 1.00 1\n",
- " rice 0.00 0.00 0.00 1\n",
- " rubber 0.69 1.00 0.82 9\n",
- " ship 0.39 0.41 0.40 39\n",
- " silver 0.00 0.00 0.00 0\n",
- " soy-oil 0.00 0.00 0.00 2\n",
- " soybean 0.00 0.00 0.00 2\n",
- "strategic-metal 0.00 0.00 0.00 6\n",
- " sugar 0.71 0.96 0.81 25\n",
- " tea 0.00 0.00 0.00 3\n",
- " tin 0.71 0.50 0.59 10\n",
- " trade 0.70 0.93 0.80 76\n",
- " veg-oil 0.54 0.64 0.58 11\n",
- " wpi 0.62 0.56 0.59 9\n",
- " yen 0.00 0.00 0.00 6\n",
- " zinc 0.00 0.00 0.00 5\n",
- "\n",
- " accuracy 0.88 3019\n",
- " macro avg 0.53 0.48 0.49 3019\n",
- " weighted avg 0.86 0.88 0.87 3019\n",
- "\n"
- ]
- },
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "/Users/dunstanmatekenya/anaconda3/lib/python3.10/site-packages/sklearn/metrics/_classification.py:1344: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.\n",
- " _warn_prf(average, modifier, msg_start, len(result))\n",
- "/Users/dunstanmatekenya/anaconda3/lib/python3.10/site-packages/sklearn/metrics/_classification.py:1344: UndefinedMetricWarning: Recall and F-score are ill-defined and being set to 0.0 in labels with no true samples. Use `zero_division` parameter to control this behavior.\n",
- " _warn_prf(average, modifier, msg_start, len(result))\n",
- "/Users/dunstanmatekenya/anaconda3/lib/python3.10/site-packages/sklearn/metrics/_classification.py:1344: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.\n",
- " _warn_prf(average, modifier, msg_start, len(result))\n",
- "/Users/dunstanmatekenya/anaconda3/lib/python3.10/site-packages/sklearn/metrics/_classification.py:1344: UndefinedMetricWarning: Recall and F-score are ill-defined and being set to 0.0 in labels with no true samples. Use `zero_division` parameter to control this behavior.\n",
- " _warn_prf(average, modifier, msg_start, len(result))\n",
- "/Users/dunstanmatekenya/anaconda3/lib/python3.10/site-packages/sklearn/metrics/_classification.py:1344: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.\n",
- " _warn_prf(average, modifier, msg_start, len(result))\n",
- "/Users/dunstanmatekenya/anaconda3/lib/python3.10/site-packages/sklearn/metrics/_classification.py:1344: UndefinedMetricWarning: Recall and F-score are ill-defined and being set to 0.0 in labels with no true samples. Use `zero_division` parameter to control this behavior.\n",
- " _warn_prf(average, modifier, msg_start, len(result))\n"
- ]
- }
- ],
- "source": [
- "# Evaluate the classifier\n",
- "y_pred = classifier.predict(X_test)\n",
- "accuracy = accuracy_score(test_labels, y_pred)\n",
- "print(\"Accuracy:\", accuracy)\n",
- "print(classification_report(test_labels, y_pred))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 6. Classify new documents (new BBC headlines) by vectorizing them using the same TfidfVectorizer and predicting their labels using the trained classifier"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 22,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Predicted labels: ['ship' 'ship' 'acq']\n"
- ]
- }
- ],
- "source": [
- "# Classify new documents (recent headlines obtained from BBC news regarding Tunisia)\n",
- "new_docs = [\n",
- " \"Tunisia says 23 people missing in Mediterranean sea.\",\n",
- " \"Tunisia officials arrested in dispute over flag display.\",\n",
- " \"Tunisia lawyer arrested during live news broadcast.\"\n",
- "]\n",
- "new_docs_vectors = vectorizer.transform(new_docs)\n",
- "predicted_labels = classifier.predict(new_docs_vectors)\n",
- "print(\"Predicted labels:\", predicted_labels)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Discussion"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "How did this classifier fare? What can you do to improve the model? \n",
- "Ans: Experimenting with different preprocessing techniques, feature extraction models and classification algorithms."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Trying with a different classifier"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Steps 1 - 3 will be the same."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Load the Reuters-21578 dataset\n",
- "documents = reuters.fileids()\n",
- "train_docs = list(filter(lambda doc: doc.startswith(\"train\"), documents))\n",
- "test_docs = list(filter(lambda doc: doc.startswith(\"test\"), documents))\n",
- "\n",
- "# Prepare the data\n",
- "train_data = [reuters.raw(doc_id) for doc_id in train_docs]\n",
- "train_labels = [reuters.categories(doc_id)[0] for doc_id in train_docs]\n",
- "test_data = [reuters.raw(doc_id) for doc_id in test_docs]\n",
- "test_labels = [reuters.categories(doc_id)[0] for doc_id in test_docs]\n",
- "\n",
- "# Vectorize the text data\n",
- "vectorizer = CountVectorizer(stop_words=\"english\", max_features=1000)\n",
- "X_train = vectorizer.fit_transform(train_data)\n",
- "X_test = vectorizer.transform(test_data)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Different Classifier (Multinomial Naive Bayes)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "classifier = MultinomialNB()\n",
- "classifier.fit(X_train, train_labels)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Evaluate the classifier\n",
- "y_pred = classifier.predict(X_test)\n",
- "accuracy = accuracy_score(test_labels, y_pred)\n",
- "print(\"Accuracy:\", accuracy)\n",
- "print(classification_report(test_labels, y_pred))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Classify new documents (recent headlines obtained from BBC news regarding Tunisia)\n",
- "new_docs = [\n",
- " \"Tunisia says 23 people missing in Mediterranean sea.\",\n",
- " \"Tunisia officials arrested in dispute over flag display.\",\n",
- " \"Tunisia lawyer arrested during live news broadcast.\"\n",
- "]\n",
- "new_docs_vectors = vectorizer.transform(new_docs)\n",
- "predicted_labels = classifier.predict(new_docs_vectors)\n",
- "print(\"Predicted labels:\", predicted_labels)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Discussion: Compare the results"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The choice of classifier depends on the specific characteristics of your dataset and the problem at hand. Multinomial Naive Bayes is known to work well with text data and can handle high-dimensional feature spaces efficiently. However, it assumes that the features are independent of each other, which may not always be the case in real-world scenarios.\n",
- "\n",
- "You can also experiment with different classifiers, such as Logistic Regression, Random Forest, or Gradient Boosting, and compare their performance to find the best fit for your dataset. You can also refine the model by trying different feature extraction techniques and hyperparameters."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### There are also other ways you can approach this, for example, Document Classification using BERT. Here is a notebook example on Kaggle that you can explore: https://www.kaggle.com/code/merishnasuwal/document-classification-using-bert"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "BERT (Bidirectional Encoder Representations from Transformers) and other Transformer encoder architectures can also be used on a variety of tasks in NLP (natural language processing). They compute vector-space representations of natural language that are suitable for use in deep learning models. The BERT family of models uses the Transformer encoder architecture to process each token of input text in the full context of all tokens before and after. BERT models are usually pre-trained on a large corpus of text, then fine-tuned for specific tasks."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3 (ipykernel)",
- "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.10.8"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/notebooks/malawi-nov-24/3-intro-langchain.ipynb b/notebooks/malawi-nov-24/3-intro-langchain.ipynb
index 82950fc..dedc751 100644
--- a/notebooks/malawi-nov-24/3-intro-langchain.ipynb
+++ b/notebooks/malawi-nov-24/3-intro-langchain.ipynb
@@ -1,14 +1,6 @@
{
"cells": [
{
- "attachments": {
- "7153af0c-fb8b-4b47-826e-57ac60696e0c.png": {
- "image/png": "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"
- },
- "faf11697-6be8-49bc-ab24-b3c4385b8a67.png": {
- "image/png": "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"
- }
- },
"cell_type": "markdown",
"id": "740ffa74-4eda-4843-9b5b-486caab1153b",
"metadata": {
@@ -17,15 +9,14 @@
"source": [
"# Introduction to LangChain\n",
"---------\n",
- "![image.png](attachment:faf11697-6be8-49bc-ab24-b3c4385b8a67.png)![image.png](attachment:7153af0c-fb8b-4b47-826e-57ac60696e0c.png)\n",
"\n",
- "**DIHPA'24**\n",
+ "**ICTAM, AI and LLM Training, Nkopola, November 2024**\n",
"\n",
"**Author:** Dunstan Matekenya \n",
"\n",
"**Affiliation:** DECAT, The World Bank Group \n",
"\n",
- "**Date:** May 30, 2024\n",
+ "**Date:** November, 2024\n",
"\n",
"\n",
"## What you will learn \n",
@@ -65,15 +56,150 @@
},
{
"cell_type": "code",
- "execution_count": 1,
+ "execution_count": 7,
"id": "b9a13ee9-f3d9-4141-a1a2-929cdc1b5113",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "True"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"import os\n",
- "from pathlib import Path"
+ "from pathlib import Path\n",
+ "\n",
+ "\n",
+ "# =======================\n",
+ "# ENVIRONMENT HANDLING\n",
+ "# =======================\n",
+ "from dotenv import load_dotenv\n",
+ "load_dotenv()"
]
},
+ {
+ "cell_type": "markdown",
+ "id": "51203f5f",
+ "metadata": {},
+ "source": [
+ "# Test OpenAI and HuggingFace"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "id": "28693074",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "44942.48999999999"
+ ]
+ },
+ "execution_count": 16,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "(1498083*0.15) - (1498083*0.12)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "id": "4ee60ee5",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0.75"
+ ]
+ },
+ "execution_count": 18,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "9/12"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "8d810eca",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "44983.889999999985"
+ ]
+ },
+ "execution_count": 11,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "224919.44999999998 - 179935.56"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "9b2abf53",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from langchain_openai import ChatOpenAI\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "98bc75bc",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Result : Malawi is located in southeastern Africa, bordered by Tanzania to the north and northeast, Zambia to the west, and Mozambique to the east, south and southwest.\n"
+ ]
+ }
+ ],
+ "source": [
+ "llm = ChatOpenAI()\n",
+ "res = llm.invoke(\"Where is Malawi?\").content\n",
+ "print(f\"Result : {res}\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "049080c6",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Result : I'm just a computer program, so I don't have feelings or emotions. How can I assist you today?\n"
+ ]
+ }
+ ],
+ "source": []
+ },
{
"cell_type": "markdown",
"id": "1e1dad1b-4014-48e9-b911-2095c9864a84",
@@ -521,27 +647,6 @@
"print(output)"
]
},
- {
- "cell_type": "code",
- "execution_count": 1,
- "id": "e9bda8e1-dce1-49c1-b308-82063fa53e6a",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "3544"
- ]
- },
- "execution_count": 1,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "2*1772"
- ]
- },
{
"cell_type": "markdown",
"id": "7381c4a5-5a33-405c-b82a-baacfebe6e56",
@@ -559,7 +664,7 @@
"id": "f4edd5e5-44fa-49b0-b150-64a580da8f66",
"metadata": {},
"source": [
- "### . Prompt templates\n",
+ "### Prompt templates\n",
"Prompt templates are used for creating prompts in a more modular way, so they can be reused and built on. Chains act as the glue in LangChain; bringing the other components together into workflows that pass inputs and outputs between the different components\n",
"- They are recipes for generating prompts\n",
"- Flexible and modular\n",
@@ -659,14 +764,6 @@
"llm(full_prompt)"
]
},
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "e11ea305-a3c9-439f-b135-236e26c39ac1",
- "metadata": {},
- "outputs": [],
- "source": []
- },
{
"cell_type": "markdown",
"id": "c3e8c433-8672-4ae8-9579-66d5201bc657",
@@ -1876,9 +1973,9 @@
],
"metadata": {
"kernelspec": {
- "display_name": "Python3.12-audio",
+ "display_name": ".venv",
"language": "python",
- "name": "audio"
+ "name": "python3"
},
"language_info": {
"codemirror_mode": {
diff --git a/notebooks/malawi-nov-24/LLM_Teaching_Notebook_with_Conclusion.ipynb b/notebooks/malawi-nov-24/LLM_Teaching_Notebook_with_Conclusion.ipynb
index 3b556e5..21253b9 100644
--- a/notebooks/malawi-nov-24/LLM_Teaching_Notebook_with_Conclusion.ipynb
+++ b/notebooks/malawi-nov-24/LLM_Teaching_Notebook_with_Conclusion.ipynb
@@ -1,3915 +1,3929 @@
{
- "cells": [
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "L-hCapPatC1R"
+ },
+ "source": [
+ "# Introduction to LLMs\n",
+ "Large Language Models (LLMs) are AI models that can generate human-like text based on given prompts. They work by:\n",
+ "\n",
+ "\n",
+ "* Understanding and tokenizing the input text.\n",
+ "* Predicting the most likely sequence of words (tokens) to follow.\n",
+ "* Using probabilities to generate coherent and contextually relevant outputs.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "VVoiHfQdt0rp"
+ },
+ "source": [
+ "##Setting Up the Environment\n",
+ "Below is the code to set up the environment using the Hugging Face transformers library:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "HvKJfKCws8pQ",
+ "outputId": "133950ce-ede3-4435-c477-17da1f1ce4d4"
+ },
+ "outputs": [
{
- "cell_type": "markdown",
- "metadata": {
- "id": "L-hCapPatC1R"
- },
- "source": [
- "# Introduction to LLMs\n",
- "Large Language Models (LLMs) are AI models that can generate human-like text based on given prompts. They work by:\n",
- "\n",
- "\n",
- "* Understanding and tokenizing the input text.\n",
- "* Predicting the most likely sequence of words (tokens) to follow.\n",
- "* Using probabilities to generate coherent and contextually relevant outputs.\n",
- "\n"
- ]
+ "ename": "ModuleNotFoundError",
+ "evalue": "No module named 'torch'",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)",
+ "Cell \u001b[0;32mIn[1], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m# Importing necessary libraries\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mtorch\u001b[39;00m\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtransformers\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m AutoTokenizer, AutoModelForCausalLM, pipeline, set_seed\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mmatplotlib\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpyplot\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mplt\u001b[39;00m\n",
+ "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'torch'"
+ ]
+ }
+ ],
+ "source": [
+ "# Importing necessary libraries\n",
+ "import torch\n",
+ "from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline, set_seed\n",
+ "import matplotlib.pyplot as plt\n",
+ "\n",
+ "# Checking if GPU is available\n",
+ "device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n",
+ "print(f\"Using device: {device}\")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "eUs4IPMTuBof"
+ },
+ "source": [
+ "# Tokenization\n",
+ "In this section, we'll explain tokenization and demonstrate it using a sample prompt."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 397,
+ "referenced_widgets": [
+ "ed52f970e5ae4c11863e8e46f9ae828f",
+ "d54161703d0c489e9cc2e0c2bc8cdde0",
+ "dd73d4c00bcb4815a47e466ffeb764f7",
+ "d0f03e93e94a48e88bb807ce9fcd3626",
+ "247cef68024a44d792583d015eee698f",
+ "eedbbeb237564aa6bf1024699404a0d8",
+ "da9b0dfeb44b46bb81534080eaf0047f",
+ "d3da6b9fec5149f596dd627fdc0ddf28",
+ "7db8af670bd5408ea41df7b09762233d",
+ "909e5b085ea848b29d1aac95c4dd1ee7",
+ "0023a18e9bf7450997c5af11070b5cc2",
+ "643145af92da4183b9607eb7e2e6d0f7",
+ "9d78f9dff3dd45218b53496767b00c70",
+ "66f3d33e3f514f31bf0e6b2ce35801be",
+ "836388e618d944aebb9dce0dea9c56e1",
+ "39cbea48cd8848b19b9dc20736708df1",
+ "ab0a2da0da2e4b3eb966395e54729ffa",
+ "786d8c0044ba4e02809f8edb03af9c2a",
+ "83f9d9548db2456ab0a26a96e03e9581",
+ "58b715f058384647b70276588eb2bf92",
+ "1dd3f850d0d9484bb5313a067392a139",
+ "995591cb74bc4395813e80fe8087f623",
+ "a98d240475f549a894b283fcec9097a8",
+ "f41832a72fdb4cb79530c9fc44693185",
+ "00ad49ed4b5e447eb6915708c628f491",
+ "a4f33b68497e470593bb3c53e2e73703",
+ "83c8a96b28a3406b86167b22a3bf1c7c",
+ "427a17311b0c4419897745ccb319fc0c",
+ "1d77d79208c54108bbe8ef2c72fcbe4c",
+ "5e3f481ead9b4dffb22b019fb7286a75",
+ "9a1af9363cc44ec5a89ddda9a94466fd",
+ "4d2fa322281a45ab8a1464be57439749",
+ "ff32f023a7c043599760bf3b3bf83cb2",
+ "97784968743c46a3b094f942a617f505",
+ "3a22215d257e44da912f098e75bcad67",
+ "459cba8b3a834331985dffea92c541bd",
+ "b155188a446441348e47eeefee321a7b",
+ "e2f11ebb13c24dcd81cdba4bedf3ded4",
+ "355db76789934773b18bbba7be586bf3",
+ "c32dd63b33a147edb63e8b2ef0da5376",
+ "2817038686c042aa836954a2c1bdd314",
+ "59935aff77684051ad3eef45af4a8d39",
+ "4eb227bcee9e409199cc51caab0c7696",
+ "bef5ad3f28674648a365a6f60eb21371",
+ "eb5e86fa57df476ea37013c7912a743e",
+ "7ccbeb6d75264e489e768710b10e0ab0",
+ "5c159af238114e4abe4bd36cf482d119",
+ "2ef6a55cd791473992084f043bd9226c",
+ "f6744817df8a4006bd0ff225aa9e4aab",
+ "7adf04d2c6c04e9b8246c70dfc58fdcc",
+ "bb30e9fd347f4166b1966997d462c5cd",
+ "5af88d5e9e1041b7ab5a8826e3ed1fa5",
+ "20446918559f460da71d704b4a3816c5",
+ "ceee626d21094ac486ddbb88634512ad",
+ "272d275596eb495a889496b640279965",
+ "a8033e173deb48448ab9f3d78bd0339c",
+ "fc63e2a321524fdb85fd891bb611246a",
+ "f04694026e2a41e391281b788248c2a2",
+ "d422c21430884a37b730da4955f3a574",
+ "05cf4d5fea694221aa439a784f45ac94",
+ "a646d1d0286d489c98c81bdffb2559ed",
+ "32ef2f84eb174debae5f2a2e6c8011dd",
+ "fd9e1e0e51974c8a8c473c464f99d018",
+ "c56b0483ad8549089f908989e5616dd1",
+ "d595683824734914a9f67634d4e08f98",
+ "6050b0136e754378b71b1295dab6c2c8",
+ "8832939841fc4180a3aeafdc7aaafb63",
+ "964d2abc5311445d8c9e515fee2ec571",
+ "c8d64d6591db4bec9fb752345e249530",
+ "2ea9aa390af84712893e431108ba80d2",
+ "e5c16313f7c94eb7a390a99f5d09ef77",
+ "9e874cda300f4056807b378d386789cb",
+ "85baaaffafea4de693f7637e5e1f09c8",
+ "6377db896bed44299ffdf88704c925ff",
+ "c8b3fb7df3fa4d0f8d57efe9721d3a67",
+ "6e3b8ae4aa044e8e878c3f3ea1e76887",
+ "e3d9044e0c0f4cf8b3783d617b0e4649"
+ ]
},
+ "id": "Ea5dAG_KuDyl",
+ "outputId": "4a40cd1d-2e02-4999-aa04-398ed4f1cf6e"
+ },
+ "outputs": [
{
- "cell_type": "markdown",
- "metadata": {
- "id": "VVoiHfQdt0rp"
- },
- "source": [
- "##Setting Up the Environment\n",
- "Below is the code to set up the environment using the Hugging Face transformers library:"
- ]
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/usr/local/lib/python3.10/dist-packages/huggingface_hub/utils/_auth.py:94: UserWarning: \n",
+ "The secret `HF_TOKEN` does not exist in your Colab secrets.\n",
+ "To authenticate with the Hugging Face Hub, create a token in your settings tab (https://huggingface.co/settings/tokens), set it as secret in your Google Colab and restart your session.\n",
+ "You will be able to reuse this secret in all of your notebooks.\n",
+ "Please note that authentication is recommended but still optional to access public models or datasets.\n",
+ " warnings.warn(\n"
+ ]
},
{
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/"
- },
- "id": "HvKJfKCws8pQ",
- "outputId": "133950ce-ede3-4435-c477-17da1f1ce4d4"
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "ed52f970e5ae4c11863e8e46f9ae828f",
+ "version_major": 2,
+ "version_minor": 0
},
- "outputs": [
- {
- "output_type": "stream",
- "name": "stdout",
- "text": [
- "Using device: cpu\n"
- ]
- }
- ],
- "source": [
- "# Importing necessary libraries\n",
- "import torch\n",
- "from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline, set_seed\n",
- "import matplotlib.pyplot as plt\n",
- "\n",
- "# Checking if GPU is available\n",
- "device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n",
- "print(f\"Using device: {device}\")\n"
+ "text/plain": [
+ "tokenizer_config.json: 0%| | 0.00/26.0 [00:00, ?B/s]"
]
+ },
+ "metadata": {},
+ "output_type": "display_data"
},
{
- "cell_type": "markdown",
- "metadata": {
- "id": "eUs4IPMTuBof"
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "643145af92da4183b9607eb7e2e6d0f7",
+ "version_major": 2,
+ "version_minor": 0
},
- "source": [
- "# Tokenization\n",
- "In this section, we'll explain tokenization and demonstrate it using a sample prompt."
+ "text/plain": [
+ "config.json: 0%| | 0.00/665 [00:00, ?B/s]"
]
+ },
+ "metadata": {},
+ "output_type": "display_data"
},
{
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/",
- "height": 397,
- "referenced_widgets": [
- "ed52f970e5ae4c11863e8e46f9ae828f",
- "d54161703d0c489e9cc2e0c2bc8cdde0",
- "dd73d4c00bcb4815a47e466ffeb764f7",
- "d0f03e93e94a48e88bb807ce9fcd3626",
- "247cef68024a44d792583d015eee698f",
- "eedbbeb237564aa6bf1024699404a0d8",
- "da9b0dfeb44b46bb81534080eaf0047f",
- "d3da6b9fec5149f596dd627fdc0ddf28",
- "7db8af670bd5408ea41df7b09762233d",
- "909e5b085ea848b29d1aac95c4dd1ee7",
- "0023a18e9bf7450997c5af11070b5cc2",
- "643145af92da4183b9607eb7e2e6d0f7",
- "9d78f9dff3dd45218b53496767b00c70",
- "66f3d33e3f514f31bf0e6b2ce35801be",
- "836388e618d944aebb9dce0dea9c56e1",
- "39cbea48cd8848b19b9dc20736708df1",
- "ab0a2da0da2e4b3eb966395e54729ffa",
- "786d8c0044ba4e02809f8edb03af9c2a",
- "83f9d9548db2456ab0a26a96e03e9581",
- "58b715f058384647b70276588eb2bf92",
- "1dd3f850d0d9484bb5313a067392a139",
- "995591cb74bc4395813e80fe8087f623",
- "a98d240475f549a894b283fcec9097a8",
- "f41832a72fdb4cb79530c9fc44693185",
- "00ad49ed4b5e447eb6915708c628f491",
- "a4f33b68497e470593bb3c53e2e73703",
- "83c8a96b28a3406b86167b22a3bf1c7c",
- "427a17311b0c4419897745ccb319fc0c",
- "1d77d79208c54108bbe8ef2c72fcbe4c",
- "5e3f481ead9b4dffb22b019fb7286a75",
- "9a1af9363cc44ec5a89ddda9a94466fd",
- "4d2fa322281a45ab8a1464be57439749",
- "ff32f023a7c043599760bf3b3bf83cb2",
- "97784968743c46a3b094f942a617f505",
- "3a22215d257e44da912f098e75bcad67",
- "459cba8b3a834331985dffea92c541bd",
- "b155188a446441348e47eeefee321a7b",
- "e2f11ebb13c24dcd81cdba4bedf3ded4",
- "355db76789934773b18bbba7be586bf3",
- "c32dd63b33a147edb63e8b2ef0da5376",
- "2817038686c042aa836954a2c1bdd314",
- "59935aff77684051ad3eef45af4a8d39",
- "4eb227bcee9e409199cc51caab0c7696",
- "bef5ad3f28674648a365a6f60eb21371",
- "eb5e86fa57df476ea37013c7912a743e",
- "7ccbeb6d75264e489e768710b10e0ab0",
- "5c159af238114e4abe4bd36cf482d119",
- "2ef6a55cd791473992084f043bd9226c",
- "f6744817df8a4006bd0ff225aa9e4aab",
- "7adf04d2c6c04e9b8246c70dfc58fdcc",
- "bb30e9fd347f4166b1966997d462c5cd",
- "5af88d5e9e1041b7ab5a8826e3ed1fa5",
- "20446918559f460da71d704b4a3816c5",
- "ceee626d21094ac486ddbb88634512ad",
- "272d275596eb495a889496b640279965",
- "a8033e173deb48448ab9f3d78bd0339c",
- "fc63e2a321524fdb85fd891bb611246a",
- "f04694026e2a41e391281b788248c2a2",
- "d422c21430884a37b730da4955f3a574",
- "05cf4d5fea694221aa439a784f45ac94",
- "a646d1d0286d489c98c81bdffb2559ed",
- "32ef2f84eb174debae5f2a2e6c8011dd",
- "fd9e1e0e51974c8a8c473c464f99d018",
- "c56b0483ad8549089f908989e5616dd1",
- "d595683824734914a9f67634d4e08f98",
- "6050b0136e754378b71b1295dab6c2c8",
- "8832939841fc4180a3aeafdc7aaafb63",
- "964d2abc5311445d8c9e515fee2ec571",
- "c8d64d6591db4bec9fb752345e249530",
- "2ea9aa390af84712893e431108ba80d2",
- "e5c16313f7c94eb7a390a99f5d09ef77",
- "9e874cda300f4056807b378d386789cb",
- "85baaaffafea4de693f7637e5e1f09c8",
- "6377db896bed44299ffdf88704c925ff",
- "c8b3fb7df3fa4d0f8d57efe9721d3a67",
- "6e3b8ae4aa044e8e878c3f3ea1e76887",
- "e3d9044e0c0f4cf8b3783d617b0e4649"
- ]
- },
- "id": "Ea5dAG_KuDyl",
- "outputId": "4a40cd1d-2e02-4999-aa04-398ed4f1cf6e"
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "a98d240475f549a894b283fcec9097a8",
+ "version_major": 2,
+ "version_minor": 0
},
- "outputs": [
- {
- "output_type": "stream",
- "name": "stderr",
- "text": [
- "/usr/local/lib/python3.10/dist-packages/huggingface_hub/utils/_auth.py:94: UserWarning: \n",
- "The secret `HF_TOKEN` does not exist in your Colab secrets.\n",
- "To authenticate with the Hugging Face Hub, create a token in your settings tab (https://huggingface.co/settings/tokens), set it as secret in your Google Colab and restart your session.\n",
- "You will be able to reuse this secret in all of your notebooks.\n",
- "Please note that authentication is recommended but still optional to access public models or datasets.\n",
- " warnings.warn(\n"
- ]
- },
- {
- "output_type": "display_data",
- "data": {
- "text/plain": [
- "tokenizer_config.json: 0%| | 0.00/26.0 [00:00, ?B/s]"
- ],
- "application/vnd.jupyter.widget-view+json": {
- "version_major": 2,
- "version_minor": 0,
- "model_id": "ed52f970e5ae4c11863e8e46f9ae828f"
- }
- },
- "metadata": {}
- },
- {
- "output_type": "display_data",
- "data": {
- "text/plain": [
- "config.json: 0%| | 0.00/665 [00:00, ?B/s]"
- ],
- "application/vnd.jupyter.widget-view+json": {
- "version_major": 2,
- "version_minor": 0,
- "model_id": "643145af92da4183b9607eb7e2e6d0f7"
- }
- },
- "metadata": {}
- },
- {
- "output_type": "display_data",
- "data": {
- "text/plain": [
- "vocab.json: 0%| | 0.00/1.04M [00:00, ?B/s]"
- ],
- "application/vnd.jupyter.widget-view+json": {
- "version_major": 2,
- "version_minor": 0,
- "model_id": "a98d240475f549a894b283fcec9097a8"
- }
- },
- "metadata": {}
- },
- {
- "output_type": "display_data",
- "data": {
- "text/plain": [
- "merges.txt: 0%| | 0.00/456k [00:00, ?B/s]"
- ],
- "application/vnd.jupyter.widget-view+json": {
- "version_major": 2,
- "version_minor": 0,
- "model_id": "97784968743c46a3b094f942a617f505"
- }
- },
- "metadata": {}
- },
- {
- "output_type": "display_data",
- "data": {
- "text/plain": [
- "tokenizer.json: 0%| | 0.00/1.36M [00:00, ?B/s]"
- ],
- "application/vnd.jupyter.widget-view+json": {
- "version_major": 2,
- "version_minor": 0,
- "model_id": "eb5e86fa57df476ea37013c7912a743e"
- }
- },
- "metadata": {}
- },
- {
- "output_type": "display_data",
- "data": {
- "text/plain": [
- "model.safetensors: 0%| | 0.00/548M [00:00, ?B/s]"
- ],
- "application/vnd.jupyter.widget-view+json": {
- "version_major": 2,
- "version_minor": 0,
- "model_id": "a8033e173deb48448ab9f3d78bd0339c"
- }
- },
- "metadata": {}
- },
- {
- "output_type": "display_data",
- "data": {
- "text/plain": [
- "generation_config.json: 0%| | 0.00/124 [00:00, ?B/s]"
- ],
- "application/vnd.jupyter.widget-view+json": {
- "version_major": 2,
- "version_minor": 0,
- "model_id": "8832939841fc4180a3aeafdc7aaafb63"
- }
- },
- "metadata": {}
- },
- {
- "output_type": "stream",
- "name": "stdout",
- "text": [
- "Tokens: tensor([[ 8001, 9542, 9345, 318, 25449, 262, 995, 13]])\n",
- "Decoded Text: Artificial Intelligence is transforming the world.\n"
- ]
- }
- ],
- "source": [
- "# Load a pre-trained GPT model and its tokenizer\n",
- "model_name = \"gpt2\"\n",
- "tokenizer = AutoTokenizer.from_pretrained(model_name)\n",
- "model = AutoModelForCausalLM.from_pretrained(model_name).to(device)\n",
- "\n",
- "# Sample text for tokenization\n",
- "text = \"Artificial Intelligence is transforming the world.\"\n",
- "\n",
- "# Tokenizing the text\n",
- "tokens = tokenizer.encode(text, return_tensors=\"pt\").to(device)\n",
- "print(f\"Tokens: {tokens}\")\n",
- "\n",
- "# Decoding tokens back to text\n",
- "decoded_text = tokenizer.decode(tokens[0])\n",
- "print(f\"Decoded Text: {decoded_text}\")\n"
+ "text/plain": [
+ "vocab.json: 0%| | 0.00/1.04M [00:00, ?B/s]"
]
+ },
+ "metadata": {},
+ "output_type": "display_data"
},
{
- "cell_type": "markdown",
- "metadata": {
- "id": "Swo_D3eOuVO0"
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "97784968743c46a3b094f942a617f505",
+ "version_major": 2,
+ "version_minor": 0
},
- "source": [
- "Tokenization converts text into numerical tokens that the model can understand.\n",
- "Each token represents a word, part of a word, or a special character."
+ "text/plain": [
+ "merges.txt: 0%| | 0.00/456k [00:00, ?B/s]"
]
+ },
+ "metadata": {},
+ "output_type": "display_data"
},
{
- "cell_type": "markdown",
- "metadata": {
- "id": "7lBpkJvRuZdv"
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "eb5e86fa57df476ea37013c7912a743e",
+ "version_major": 2,
+ "version_minor": 0
},
- "source": [
- "# Understanding Token Probabilities\n",
- "We'll explore how LLMs generate text using token probabilities."
+ "text/plain": [
+ "tokenizer.json: 0%| | 0.00/1.36M [00:00, ?B/s]"
]
+ },
+ "metadata": {},
+ "output_type": "display_data"
},
{
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/"
- },
- "id": "sn17gwMcuRb7",
- "outputId": "157692d5-0e73-48f5-b8ce-5114ad621423"
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "a8033e173deb48448ab9f3d78bd0339c",
+ "version_major": 2,
+ "version_minor": 0
},
- "outputs": [
- {
- "output_type": "stream",
- "name": "stdout",
- "text": [
- "Token: is, Probability: 0.2314\n",
- "Token: in, Probability: 0.0686\n",
- "Token: and, Probability: 0.0668\n",
- "Token: will, Probability: 0.0649\n",
- "Token: ,, Probability: 0.0427\n"
- ]
- }
- ],
- "source": [
- "# Generate output with token probabilities\n",
- "input_ids = tokenizer.encode(\"The future of AI\", return_tensors=\"pt\").to(device)\n",
- "output = model(input_ids)\n",
- "\n",
- "# Extract logits (raw scores) for the next token prediction\n",
- "logits = output.logits[0, -1, :]\n",
- "probs = torch.softmax(logits, dim=0)\n",
- "\n",
- "# Show the top 5 probable tokens\n",
- "top_k = 5\n",
- "top_k_indices = torch.topk(probs, top_k).indices\n",
- "top_k_probs = torch.topk(probs, top_k).values\n",
- "\n",
- "# Display top-k tokens with their probabilities\n",
- "for i in range(top_k):\n",
- " token = tokenizer.decode(top_k_indices[i].item())\n",
- " print(f\"Token: {token}, Probability: {top_k_probs[i].item():.4f}\")\n"
+ "text/plain": [
+ "model.safetensors: 0%| | 0.00/548M [00:00, ?B/s]"
]
+ },
+ "metadata": {},
+ "output_type": "display_data"
},
{
- "cell_type": "markdown",
- "metadata": {
- "id": "edrAVmvgujfh"
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "8832939841fc4180a3aeafdc7aaafb63",
+ "version_major": 2,
+ "version_minor": 0
},
- "source": [
- "#Text Generation\n",
- "We'll demonstrate how LLMs generate text and how different parameters affect the output."
+ "text/plain": [
+ "generation_config.json: 0%| | 0.00/124 [00:00, ?B/s]"
]
+ },
+ "metadata": {},
+ "output_type": "display_data"
},
{
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/"
- },
- "id": "Xa9UVyBMugwg",
- "outputId": "00883b42-8a5c-45c3-f1ba-4d544c4d383f"
- },
- "outputs": [
- {
- "output_type": "stream",
- "name": "stderr",
- "text": [
- "The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.\n",
- "Setting `pad_token_id` to `eos_token_id`:None for open-end generation.\n",
- "The attention mask is not set and cannot be inferred from input because pad token is same as eos token. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.\n"
- ]
- },
- {
- "output_type": "stream",
- "name": "stdout",
- "text": [
- "The advancements in artificial intelligence and artificial intelligence technologies have enabled us to build new technologies to help us solve many of the challenges of our time. However, many of our technological achievements have been based on the assumption that humans will eventually become super-intelligent\n"
- ]
- }
- ],
- "source": [
- "# Generating text using different decoding methods\n",
- "def generate_text(prompt, max_length=50, temperature=0.7, top_k=50, top_p=0.9):\n",
- " input_ids = tokenizer(prompt, return_tensors=\"pt\").input_ids.to(device)\n",
- " output = model.generate(\n",
- " input_ids,\n",
- " max_length=max_length,\n",
- " temperature=temperature,\n",
- " top_k=top_k,\n",
- " top_p=top_p,\n",
- " do_sample=True,\n",
- " )\n",
- " return tokenizer.decode(output[0], skip_special_tokens=True)\n",
- "\n",
- "# Example prompt\n",
- "prompt = \"The advancements in artificial intelligence\"\n",
- "print(generate_text(prompt))\n"
- ]
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Tokens: tensor([[ 8001, 9542, 9345, 318, 25449, 262, 995, 13]])\n",
+ "Decoded Text: Artificial Intelligence is transforming the world.\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Load a pre-trained GPT model and its tokenizer\n",
+ "model_name = \"gpt2\"\n",
+ "tokenizer = AutoTokenizer.from_pretrained(model_name)\n",
+ "model = AutoModelForCausalLM.from_pretrained(model_name).to(device)\n",
+ "\n",
+ "# Sample text for tokenization\n",
+ "text = \"Artificial Intelligence is transforming the world.\"\n",
+ "\n",
+ "# Tokenizing the text\n",
+ "tokens = tokenizer.encode(text, return_tensors=\"pt\").to(device)\n",
+ "print(f\"Tokens: {tokens}\")\n",
+ "\n",
+ "# Decoding tokens back to text\n",
+ "decoded_text = tokenizer.decode(tokens[0])\n",
+ "print(f\"Decoded Text: {decoded_text}\")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "Swo_D3eOuVO0"
+ },
+ "source": [
+ "Tokenization converts text into numerical tokens that the model can understand.\n",
+ "Each token represents a word, part of a word, or a special character."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "7lBpkJvRuZdv"
+ },
+ "source": [
+ "# Understanding Token Probabilities\n",
+ "We'll explore how LLMs generate text using token probabilities."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
},
+ "id": "sn17gwMcuRb7",
+ "outputId": "157692d5-0e73-48f5-b8ce-5114ad621423"
+ },
+ "outputs": [
{
- "cell_type": "markdown",
- "metadata": {
- "id": "y39j59swuueC"
- },
- "source": [
- "Temperature: Controls randomness in generation. Higher values (e.g., 1.0) make output more random.\n",
- "\n",
- "Top-k Sampling: Limits selection to the top-k probable tokens.\n",
- "\n",
- "Top-p Sampling (Nucleus Sampling): Limits selection to tokens that cover a cumulative probability of p."
- ]
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Token: is, Probability: 0.2314\n",
+ "Token: in, Probability: 0.0686\n",
+ "Token: and, Probability: 0.0668\n",
+ "Token: will, Probability: 0.0649\n",
+ "Token: ,, Probability: 0.0427\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Generate output with token probabilities\n",
+ "input_ids = tokenizer.encode(\"The future of AI\", return_tensors=\"pt\").to(device)\n",
+ "output = model(input_ids)\n",
+ "\n",
+ "# Extract logits (raw scores) for the next token prediction\n",
+ "logits = output.logits[0, -1, :]\n",
+ "probs = torch.softmax(logits, dim=0)\n",
+ "\n",
+ "# Show the top 5 probable tokens\n",
+ "top_k = 5\n",
+ "top_k_indices = torch.topk(probs, top_k).indices\n",
+ "top_k_probs = torch.topk(probs, top_k).values\n",
+ "\n",
+ "# Display top-k tokens with their probabilities\n",
+ "for i in range(top_k):\n",
+ " token = tokenizer.decode(top_k_indices[i].item())\n",
+ " print(f\"Token: {token}, Probability: {top_k_probs[i].item():.4f}\")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "edrAVmvgujfh"
+ },
+ "source": [
+ "#Text Generation\n",
+ "We'll demonstrate how LLMs generate text and how different parameters affect the output."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
},
+ "id": "Xa9UVyBMugwg",
+ "outputId": "00883b42-8a5c-45c3-f1ba-4d544c4d383f"
+ },
+ "outputs": [
{
- "cell_type": "markdown",
- "metadata": {
- "id": "txvqGkF1u0UV"
- },
- "source": [
- "#Stochastic Nature of LLMs\n",
- "Here, we'll show how randomness affects outputs by generating multiple responses for the same prompt."
- ]
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.\n",
+ "Setting `pad_token_id` to `eos_token_id`:None for open-end generation.\n",
+ "The attention mask is not set and cannot be inferred from input because pad token is same as eos token. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.\n"
+ ]
},
{
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/"
- },
- "id": "xcnsCdHlu4v6",
- "outputId": "28c11c0e-20ef-4469-a00e-641770274de3"
- },
- "outputs": [
- {
- "output_type": "stream",
- "name": "stderr",
- "text": [
- "The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.\n",
- "Setting `pad_token_id` to `eos_token_id`:None for open-end generation.\n",
- "The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.\n",
- "Setting `pad_token_id` to `eos_token_id`:None for open-end generation.\n"
- ]
- },
- {
- "output_type": "stream",
- "name": "stdout",
- "text": [
- "Output 1: The advancements in artificial intelligence have allowed researchers to create more accurate models of human behavior, including how people behave in the world. The results are presented at the International Conference on Artificial Intelligence (ICAI) in Seoul, South Korea, on October 7-\n",
- "\n"
- ]
- },
- {
- "output_type": "stream",
- "name": "stderr",
- "text": [
- "The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.\n",
- "Setting `pad_token_id` to `eos_token_id`:None for open-end generation.\n"
- ]
- },
- {
- "output_type": "stream",
- "name": "stdout",
- "text": [
- "Output 2: The advancements in artificial intelligence have been made possible by the development of new algorithms that are able to recognize people's faces in a variety of ways, from the way they look to how they behave.\n",
- "\n",
- "The first such algorithm, known as the Face\n",
- "\n",
- "Output 3: The advancements in artificial intelligence and robotics have made it possible to create a computer that is capable of performing complex tasks that have never been done before.\n",
- "\n",
- "\"We're doing things that will not be possible before,\" said Dr. Gail M.\n",
- "\n"
- ]
- }
- ],
- "source": [
- "# Generate multiple outputs for the same prompt\n",
- "set_seed(42) # Setting a seed for reproducibility\n",
- "for i in range(3):\n",
- " print(f\"Output {i+1}: {generate_text(prompt)}\\n\")\n"
- ]
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "The advancements in artificial intelligence and artificial intelligence technologies have enabled us to build new technologies to help us solve many of the challenges of our time. However, many of our technological achievements have been based on the assumption that humans will eventually become super-intelligent\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Generating text using different decoding methods\n",
+ "def generate_text(prompt, max_length=50, temperature=0.7, top_k=50, top_p=0.9):\n",
+ " input_ids = tokenizer(prompt, return_tensors=\"pt\").input_ids.to(device)\n",
+ " output = model.generate(\n",
+ " input_ids,\n",
+ " max_length=max_length,\n",
+ " temperature=temperature,\n",
+ " top_k=top_k,\n",
+ " top_p=top_p,\n",
+ " do_sample=True,\n",
+ " )\n",
+ " return tokenizer.decode(output[0], skip_special_tokens=True)\n",
+ "\n",
+ "# Example prompt\n",
+ "prompt = \"The advancements in artificial intelligence\"\n",
+ "print(generate_text(prompt))\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "y39j59swuueC"
+ },
+ "source": [
+ "Temperature: Controls randomness in generation. Higher values (e.g., 1.0) make output more random.\n",
+ "\n",
+ "Top-k Sampling: Limits selection to the top-k probable tokens.\n",
+ "\n",
+ "Top-p Sampling (Nucleus Sampling): Limits selection to tokens that cover a cumulative probability of p."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "txvqGkF1u0UV"
+ },
+ "source": [
+ "#Stochastic Nature of LLMs\n",
+ "Here, we'll show how randomness affects outputs by generating multiple responses for the same prompt."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
},
+ "id": "xcnsCdHlu4v6",
+ "outputId": "28c11c0e-20ef-4469-a00e-641770274de3"
+ },
+ "outputs": [
{
- "cell_type": "markdown",
- "metadata": {
- "id": "9H14GOeivCXC"
- },
- "source": [
- " # Prompt Engineering\n",
- "\n",
- "This section covers how modifying prompts can change the outputs generated."
- ]
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.\n",
+ "Setting `pad_token_id` to `eos_token_id`:None for open-end generation.\n",
+ "The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.\n",
+ "Setting `pad_token_id` to `eos_token_id`:None for open-end generation.\n"
+ ]
},
{
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/"
- },
- "id": "EQTyEIbcu_TI",
- "outputId": "1470032c-e517-49ed-9daf-2cc382fb33ed"
- },
- "outputs": [
- {
- "output_type": "stream",
- "name": "stderr",
- "text": [
- "The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.\n",
- "Setting `pad_token_id` to `eos_token_id`:None for open-end generation.\n"
- ]
- },
- {
- "output_type": "stream",
- "name": "stdout",
- "text": [
- "Prompt: Explain the concept of machine learning.\n"
- ]
- },
- {
- "output_type": "stream",
- "name": "stderr",
- "text": [
- "The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.\n",
- "Setting `pad_token_id` to `eos_token_id`:None for open-end generation.\n"
- ]
- },
- {
- "output_type": "stream",
- "name": "stdout",
- "text": [
- "Explain the concept of machine learning.\n",
- "\n",
- "This is the third article in a series of articles in Computer Vision and Machine Learning.\n",
- "\n",
- "The first article is from the Computer Vision and Machine Learning Institute.\n",
- "\n",
- "The second article is from the\n",
- "\n",
- "--------------------------------------------------\n",
- "\n",
- "Prompt: Explain the concept of machine learning in simple terms.\n"
- ]
- },
- {
- "output_type": "stream",
- "name": "stderr",
- "text": [
- "The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.\n",
- "Setting `pad_token_id` to `eos_token_id`:None for open-end generation.\n"
- ]
- },
- {
- "output_type": "stream",
- "name": "stdout",
- "text": [
- "Explain the concept of machine learning in simple terms.\n",
- "\n",
- "The machine learning is a system of learning that can be applied to any task. In particular, machine learning is a system that can be applied to any task in the world.\n",
- "\n",
- "\n",
- "\n",
- "--------------------------------------------------\n",
- "\n",
- "Prompt: Explain machine learning to a 10-year-old.\n",
- "Explain machine learning to a 10-year-old.\n",
- "\n",
- "The next step is to find a way to teach students the basics of machine learning.\n",
- "\n",
- "\"We have some of the most advanced systems available,\" said Chris Binder, a\n",
- "\n",
- "--------------------------------------------------\n",
- "\n"
- ]
- }
- ],
- "source": [
- "# Testing prompt engineering\n",
- "prompts = [\n",
- " \"Explain the concept of machine learning.\",\n",
- " \"Explain the concept of machine learning in simple terms.\",\n",
- " \"Explain machine learning to a 10-year-old.\",\n",
- "]\n",
- "\n",
- "for p in prompts:\n",
- " print(f\"Prompt: {p}\")\n",
- " print(generate_text(p))\n",
- " print(\"\\n\" + \"-\"*50 + \"\\n\")\n"
- ]
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Output 1: The advancements in artificial intelligence have allowed researchers to create more accurate models of human behavior, including how people behave in the world. The results are presented at the International Conference on Artificial Intelligence (ICAI) in Seoul, South Korea, on October 7-\n",
+ "\n"
+ ]
},
{
- "cell_type": "markdown",
- "metadata": {
- "id": "2fa5476a"
- },
- "source": [
- "\n",
- "## Tokenization Explained in Detail\n",
- "\n",
- "In this section, we'll dive deeper into tokenization. The process of tokenization is essential for transforming raw text into tokens that the model can understand. Each token represents a word, part of a word, or even special characters.\n",
- "\n",
- "Let's see a practical demonstration of how a sentence is tokenized using a pre-trained GPT model. We will also visualize how text is broken down into tokens.\n"
- ]
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.\n",
+ "Setting `pad_token_id` to `eos_token_id`:None for open-end generation.\n"
+ ]
},
{
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/",
- "height": 444
- },
- "id": "a0c8b391",
- "outputId": "6bd7567c-5647-4d80-8918-abb3e72b2fc2"
- },
- "outputs": [
- {
- "output_type": "stream",
- "name": "stdout",
- "text": [
- "Tokens: tensor([[ 8001, 9542, 9345, 318, 25449, 262, 995, 13]])\n",
- "Decoded Text: Artificial Intelligence is transforming the world.\n"
- ]
- },
- {
- "output_type": "display_data",
- "data": {
- "text/plain": [
- "