diff --git a/week08_LLM_v2/mistral_api_practice.ipynb b/week08_LLM_v2/mistral_api_practice.ipynb new file mode 100644 index 0000000..e7c96cb --- /dev/null +++ b/week08_LLM_v2/mistral_api_practice.ipynb @@ -0,0 +1,955 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "cb1f8207", + "metadata": { + "id": "cb1f8207" + }, + "source": [ + "# Seminar: Using Modern Large Language Models with Mistral API" + ] + }, + { + "cell_type": "markdown", + "id": "894f0f73", + "metadata": { + "id": "894f0f73" + }, + "source": [ + "\n", + "## 1. Introduction\n", + "In this seminar, we will learn how to use Mistral's Large Language Models (LLMs) through their API.\n", + "We will cover setting up the environment, authenticating, exploring text generation, embeddings, and other advanced features.\n", + "\n", + "### Learning Objectives\n", + "- Understand the fundamentals of using LLMs via API.\n", + "- Get hands-on experience with the Mistral API for practical use cases like text generation, embeddings, and fine-tuning.\n" + ] + }, + { + "cell_type": "markdown", + "id": "e6f5d142", + "metadata": { + "id": "e6f5d142" + }, + "source": [ + "## 2. Setting Up the Environment" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "9ea74b75", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "9ea74b75", + "outputId": "df0a83f4-797b-4113-8c2d-a668abf85da8" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collecting mistralai\n", + " Downloading mistralai-1.2.1-py3-none-any.whl.metadata (26 kB)\n", + "Requirement already satisfied: eval-type-backport<0.3.0,>=0.2.0 in /usr/local/lib/python3.10/dist-packages (from mistralai) (0.2.0)\n", + "Requirement already satisfied: httpx<0.28.0,>=0.27.0 in /usr/local/lib/python3.10/dist-packages (from mistralai) (0.27.2)\n", + "Collecting jsonpath-python<2.0.0,>=1.0.6 (from mistralai)\n", + " Downloading jsonpath_python-1.0.6-py3-none-any.whl.metadata (12 kB)\n", + "Requirement already satisfied: pydantic<3.0.0,>=2.9.0 in /usr/local/lib/python3.10/dist-packages (from mistralai) (2.9.2)\n", + "Requirement already satisfied: python-dateutil==2.8.2 in /usr/local/lib/python3.10/dist-packages (from mistralai) (2.8.2)\n", + "Collecting typing-inspect<0.10.0,>=0.9.0 (from mistralai)\n", + " Downloading typing_inspect-0.9.0-py3-none-any.whl.metadata (1.5 kB)\n", + "Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.10/dist-packages (from python-dateutil==2.8.2->mistralai) (1.16.0)\n", + "Requirement already satisfied: anyio in /usr/local/lib/python3.10/dist-packages (from httpx<0.28.0,>=0.27.0->mistralai) (3.7.1)\n", + "Requirement already satisfied: certifi in /usr/local/lib/python3.10/dist-packages (from httpx<0.28.0,>=0.27.0->mistralai) (2024.8.30)\n", + "Requirement already satisfied: httpcore==1.* in /usr/local/lib/python3.10/dist-packages (from httpx<0.28.0,>=0.27.0->mistralai) (1.0.6)\n", + "Requirement already satisfied: idna in /usr/local/lib/python3.10/dist-packages (from httpx<0.28.0,>=0.27.0->mistralai) (3.10)\n", + "Requirement already satisfied: sniffio in /usr/local/lib/python3.10/dist-packages (from httpx<0.28.0,>=0.27.0->mistralai) (1.3.1)\n", + "Requirement already satisfied: h11<0.15,>=0.13 in /usr/local/lib/python3.10/dist-packages (from httpcore==1.*->httpx<0.28.0,>=0.27.0->mistralai) (0.14.0)\n", + "Requirement already satisfied: annotated-types>=0.6.0 in /usr/local/lib/python3.10/dist-packages (from pydantic<3.0.0,>=2.9.0->mistralai) (0.7.0)\n", + "Requirement already satisfied: pydantic-core==2.23.4 in /usr/local/lib/python3.10/dist-packages (from pydantic<3.0.0,>=2.9.0->mistralai) (2.23.4)\n", + "Requirement already satisfied: typing-extensions>=4.6.1 in /usr/local/lib/python3.10/dist-packages (from pydantic<3.0.0,>=2.9.0->mistralai) (4.12.2)\n", + "Collecting mypy-extensions>=0.3.0 (from typing-inspect<0.10.0,>=0.9.0->mistralai)\n", + " Downloading mypy_extensions-1.0.0-py3-none-any.whl.metadata (1.1 kB)\n", + "Requirement already satisfied: exceptiongroup in /usr/local/lib/python3.10/dist-packages (from anyio->httpx<0.28.0,>=0.27.0->mistralai) (1.2.2)\n", + "Downloading mistralai-1.2.1-py3-none-any.whl (254 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m254.6/254.6 kB\u001b[0m \u001b[31m4.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hDownloading jsonpath_python-1.0.6-py3-none-any.whl (7.6 kB)\n", + "Downloading typing_inspect-0.9.0-py3-none-any.whl (8.8 kB)\n", + "Downloading mypy_extensions-1.0.0-py3-none-any.whl (4.7 kB)\n", + "Installing collected packages: mypy-extensions, jsonpath-python, typing-inspect, mistralai\n", + "Successfully installed jsonpath-python-1.0.6 mistralai-1.2.1 mypy-extensions-1.0.0 typing-inspect-0.9.0\n" + ] + } + ], + "source": [ + "\n", + "# Ensure you have an API key from Mistral's platform, then install the required package:\n", + "!pip install mistralai\n" + ] + }, + { + "cell_type": "markdown", + "id": "51d393f6", + "metadata": { + "id": "51d393f6" + }, + "source": [ + "\n", + "Next, store your API key as an environment variable for secure access within your code.\n", + "\n", + "```python\n", + "import os\n", + "os.environ[\"MISTRAL_API_KEY\"] = \"your_api_key_here\"\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "id": "85594a5e", + "metadata": { + "id": "85594a5e" + }, + "source": [ + "## 3. Using the Mistral API" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "cc9450db", + "metadata": { + "id": "cc9450db" + }, + "outputs": [], + "source": [ + "from mistralai import Mistral\n", + "api_key = os.environ[\"MISTRAL_API_KEY\"]\n", + "client = Mistral(api_key=api_key)" + ] + }, + { + "cell_type": "markdown", + "id": "27439904", + "metadata": { + "id": "27439904" + }, + "source": [ + "### 3.1 Text Generation" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "b5a9e194", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "b5a9e194", + "outputId": "41594ace-cfcb-45eb-f436-3fef711eceda" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "France is renowned for its diverse and exquisite range of cheeses. Here are some of the best French cheeses, categorized by type:\n", + "\n", + "1. **Soft Cheeses:**\n", + " - **Brie de Meaux**: A creamy, soft cheese with a bloomy rind, often considered one of the finest French cheeses.\n", + " - **Camembert de Normandie**: A soft, creamy cheese with a strong flavor, similar to Brie but typically stronger.\n", + " - **Chèvre (Goat Cheese)**: Available in many forms, such as fresh (Chèvre frais), aged (Chèvre sec), or coated in ash (Selles-sur-Cher).\n", + "\n", + "2. **Semi-Soft Cheeses:**\n", + " - **Morbier**: A creamy, semi-soft cheese with a distinctive layer of ash in the middle.\n", + " - **Reblochon**: A nutty, semi-soft cheese from the Alps, often used in the dish Tartiflette.\n", + "\n", + "3. **Hard Cheeses:**\n", + " - **Comté**: A firm, nutty cheese made from unpasteurized cow's milk, similar to Gruyère.\n", + " - **Beaufort**: A firm, nutty cheese similar to Comté but often more intense in flavor.\n", + " - **Cantal**: A semi-hard, strong-flavored cheese, one of the oldest French cheeses.\n", + "\n", + "4. **Blue Cheeses:**\n", + " - **Roquefort**: A tangy, crumbly blue cheese made from sheep's milk, often considered the king of blue cheeses.\n", + " - **Bleu d'Auvergne**: A creamy, strong blue cheese, similar to Roquefort but made from cow's milk.\n", + "\n", + "5. **Washed-Rind Cheeses:**\n", + " - **Munster**: A strong-smelling, soft cheese with a washed rind, often served with cumin seeds.\n", + " - **Pont-l'Évêque**: A square-shaped, soft cheese with a washed rind, similar to Munster but milder.\n", + "\n", + "6. **Fresh Cheeses:**\n", + " - **Fromage Blanc**: A fresh, soft cheese similar to cream cheese, often used in desserts or as a spread.\n", + "\n", + "This list is not exhaustive, as France has hundreds of different cheeses, each with its unique characteristics. Exploring French cheeses is a delightful journey for any food enthusiast.\n" + ] + } + ], + "source": [ + "# Example: Generating text based on a prompt\n", + "model = \"mistral-large-latest\"\n", + "chat_response = client.chat.complete(\n", + " model=model,\n", + " messages=[\n", + " {\"role\": \"user\", \"content\": \"What are the best French cheeses?\"}\n", + " ]\n", + ")\n", + "print(chat_response.choices[0].message.content)" + ] + }, + { + "cell_type": "markdown", + "id": "91f32cf6", + "metadata": { + "id": "91f32cf6" + }, + "source": [ + "In this cell, we used the Mistral model to answer a simple query." + ] + }, + { + "cell_type": "markdown", + "id": "4d60eef5", + "metadata": { + "id": "4d60eef5" + }, + "source": [ + "### Text Generation Exercises" + ] + }, + { + "cell_type": "markdown", + "id": "c5840a83", + "metadata": { + "id": "c5840a83" + }, + "source": [ + "\n", + "#### Exercise 1: Generate a List of Items\n", + "Use the Mistral model to generate a list of the top five tourist attractions in Paris.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "d367be59", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "d367be59", + "outputId": "b6f45189-5701-4b06-a83b-9b42be9570a5" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Sure, here are the top five tourist attractions in Paris:\n", + "\n", + "1. **Eiffel Tower**: The Eiffel Tower is the most-visited paid monument in the world. It's a global icon of France and one of the most recognizable structures in the world. Visitors can climb up to its three levels or enjoy a meal at one of its restaurants.\n", + "\n", + "2. **Louvre Museum**: Home to thousands of works of art, including the Mona Lisa and the Winged Victory, the Louvre is the world's largest and most visited art museum. The glass pyramid in the courtyard is also a famous landmark.\n", + "\n", + "3. **Notre-Dame Cathedral**: Although severely damaged by a fire in 2019, Notre-Dame remains an iconic symbol of Paris. It's a masterpiece of French Gothic architecture and was the inspiration for Victor Hugo's novel \"The Hunchback of Notre-Dame\".\n", + "\n", + "4. **Champs-Élysées / Arc de Triomphe**: The Avenue des Champs-Élysées is known for its theaters, cafés, and luxury shops, while the Arc de Triomphe is a monument honoring those who fought and died for France. You can climb to the top of the Arc for a panoramic view of the city.\n", + "\n", + "5. **Montmartre**: Known for its bohemian past, the charming hilltop village of Montmartre is home to the Sacré-Cœur Basilica, which offers stunning views of the city. The area is also famous for its winding streets, cafés, and the Place du Tertre, where local artists create and sell their work.\n", + "\n", + "These attractions represent just a fraction of what Paris has to offer, but they are a great starting point for any visitor.\n" + ] + } + ], + "source": [ + "# Generate a list of the top five tourist attractions in Paris\n", + "chat_response = client.chat.complete(\n", + " model=model,\n", + " messages=[\n", + " {\"role\": \"user\", \"content\": \"List the top five tourist attractions in Paris.\"}\n", + " ]\n", + ")\n", + "print(chat_response.choices[0].message.content)" + ] + }, + { + "cell_type": "markdown", + "id": "c0ced2c2", + "metadata": { + "id": "c0ced2c2" + }, + "source": [ + "\n", + "#### Exercise 2: Generate Responses with Different Styles\n", + "Use the model to answer the same question in two distinct styles: formal and informal.\n", + "\n", + "**Question**: Explain the benefits of healthy eating.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "20adc0c1", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "20adc0c1", + "outputId": "83ecd231-0e34-4f77-c220-bb4e0c7827c8" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Formal style response: Healthy eating confers a myriad of benefits that transcend mere physical well-being, extending to enhanced mental acuity, improved emotional stability, and augmented overall quality of life. Primarily, a balanced diet, replete with fruits, vegetables, whole grains, lean proteins, and healthy fats, contributes to optimal physical health. It aids in maintaining a healthy weight, reducing the risk of chronic diseases such as heart disease, diabetes, and certain cancers. Moreover, it strengthens the immune system, enabling the body to more effectively combat infections and expedite recovery from illnesses.\n", + "\n", + "From a mental perspective, the consumption of nutrient-dense foods has been linked to improved cognitive function and decreased risk of age-related cognitive decline. Specific nutrients, such as omega-3 fatty acids, antioxidants, and B vitamins, play pivotal roles in supporting brain health and enhancing mental acuity. Additionally, a healthy diet can positively influence mood and reduce symptoms of depression, as evidenced by numerous scientific studies.\n", + "\n", + "Furthermore, healthy eating habits have been shown to stabilize energy levels, thereby enhancing productivity and reducing fatigue. The consumption of foods with a low glycemic index ensures a steady release of energy, in contrast to the transient energy spikes and subsequent crashes associated with high-sugar, highly processed foods.\n", + "\n", + "In the realm of emotional well-being, a nutritious diet can contribute to reduced stress levels and improved mood regulation. Certain nutrients, such as magnesium and B vitamins, are instrumental in supporting the body's stress response and promoting emotional equilibrium.\n", + "\n", + "Moreover, the adoption of healthy eating habits fosters a sense of self-care and self-respect, which can bolster self-esteem and encourage the adoption of other healthful behaviors. This holistic approach to well-being can lead to improved relationships, increased resilience, and a more positive outlook on life.\n", + "\n", + "In conclusion, the benefits of healthy eating are multifarious and far-reaching, encompassing physical, mental, and emotional dimensions. The cultivation of sound nutritional habits is, therefore, a prudent investment in one's overall well-being and longevity.\n", + "Informal style response: Hey there! So, you're wondering why everyone's always harping on about healthy eating, huh? Well, let me break it down for you.\n", + "\n", + "First off, when you chow down on the good stuff like fruits, veggies, whole grains, and lean proteins, you're fueling your body with essential nutrients. Think of it like putting high-quality gas in your car – it just runs better. You'll feel more energized, ready to take on the world!\n", + "\n", + "Eating healthy also means you're doing your future self a solid. You know, reducing the risk of nasty stuff like heart disease, diabetes, and even some types of cancer. Plus, it keeps your immune system in tip-top shape, helping you fight off those pesky bugs going around.\n", + "\n", + "Now, let's talk about how it makes you look and feel. A diet packed with wholesome foods can help you maintain a healthy weight. No more feeling sluggish and weighed down after those heavy, greasy meals. And who doesn't want glowing skin, strong nails, and shiny hair? Yeah, healthy eating can help with that too!\n", + "\n", + "Lastly, it's not just about your physical health. Believe it or not, what you eat can affect your mood. Foods rich in vitamins and minerals can boost your brain power, improve your mood, and even help you sleep better. So, you'll be happier and sharper – talk about a win-win!\n", + "\n", + "So there you have it! Eating healthy isn't just about counting calories or looking good in your jeans (though that's a nice bonus). It's about feeling awesome, inside and out. Give it a shot, and I promise your body will thank you!\n" + ] + } + ], + "source": [ + "# Generating formal and informal responses\n", + "responses = []\n", + "styles = [\"formal\", \"informal\"]\n", + "\n", + "for style in styles:\n", + " response = client.chat.complete(\n", + " model=model,\n", + " messages=[\n", + " {\"role\": \"user\", \"content\": f\"Explain the benefits of healthy eating in a {style} style.\"}\n", + " ]\n", + " )\n", + " responses.append(response.choices[0].message.content)\n", + "\n", + "for style, text in zip(styles, responses):\n", + " print(f\"{style.capitalize()} style response: {text}\")" + ] + }, + { + "cell_type": "markdown", + "id": "e679df42", + "metadata": { + "id": "e679df42" + }, + "source": [ + "## 4. Generating Embeddings" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "2e723c60", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "2e723c60", + "outputId": "79035ba3-5d66-49c8-9784-0984f3989905" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Embeddings generated for each sentence\n" + ] + } + ], + "source": [ + "# Generate embeddings for sentences\n", + "embedding_response = client.embeddings.create(\n", + " model=\"mistral-embed\",\n", + " inputs=[\"Climate change affects global temperatures.\", \"The rise in global temperatures is influenced by climate change.\"])\n", + "embeddings = [item.embedding for item in embedding_response.data]\n", + "print(\"Embeddings generated for each sentence\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "d639ca88", + "metadata": { + "id": "d639ca88" + }, + "source": [ + "\n", + "### Embedding Exercise: Compare Sentence Similarity\n", + "Generate embeddings for the sentences below and calculate their similarity to see how related they are.\n", + "- \"Climate change affects global temperatures.\"\n", + "- \"The rise in global temperatures is influenced by climate change.\"\n", + "\n", + "*Use cosine similarity to compare the two embedding vectors.*\n" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "65db9ee0", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "65db9ee0", + "outputId": "30d113c1-2f06-49bc-94f4-7e40bb350c0d" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Cosine similarity: 0.9342\n" + ] + } + ], + "source": [ + "from scipy.spatial.distance import cosine\n", + "\n", + "# Calculate cosine similarity\n", + "similarity = 1 - cosine(embeddings[0], embeddings[1])\n", + "print(f\"Cosine similarity: {similarity:.4f}\")" + ] + }, + { + "cell_type": "markdown", + "id": "60236f48", + "metadata": { + "id": "60236f48" + }, + "source": [ + "## 5. Building a Chatbot" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "662691b5", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "662691b5", + "outputId": "efd10e2f-c517-4026-c3e7-217aebd60864" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "What do you call a fake noodle? An impasta.\n" + ] + } + ], + "source": [ + "# Define a simple chatbot function\n", + "conversation_history = []\n", + "\n", + "def chatbot(user_input):\n", + " conversation_history.append({\"role\": \"user\", \"content\": user_input})\n", + " response = client.chat.complete(\n", + " model=model,\n", + " messages=conversation_history\n", + " )\n", + " conversation_history.append({\"role\": \"assistant\", \"content\": response.choices[0].message.content})\n", + " return response.choices[0].message.content\n", + "\n", + "# Test the chatbot function\n", + "print(chatbot(\"Tell me a joke.\"))" + ] + }, + { + "cell_type": "markdown", + "id": "f6fac90c", + "metadata": { + "id": "f6fac90c" + }, + "source": [ + "\n", + "### Chatbot Exercise: Implement Memory for Contextual Chat\n", + "Modify the chatbot function to retain conversation context by storing previous messages and responses.\n", + "This will allow the chatbot to maintain context over multiple interactions.\n" + ] + }, + { + "cell_type": "markdown", + "id": "ccllZfNnLyIT", + "metadata": { + "id": "ccllZfNnLyIT" + }, + "source": [ + "## 6. Code Generation with Codestral" + ] + }, + { + "cell_type": "markdown", + "id": "L9Z2R1sjL2iU", + "metadata": { + "id": "L9Z2R1sjL2iU" + }, + "source": [ + "\n", + "Codestral is Mistral's code-generation model optimized for tasks like code completion and fill-in-the-middle.\n", + "\n", + "### Codestral Domains\n", + "There are two Codestral domains:\n", + "- `codestral.mistral.ai` (recommended for IDE plugins and user-facing applications)\n", + "- `api.mistral.ai` (recommended for direct API key usage in business cases)\n", + "\n", + "This guide demonstrates code generation using `api.mistral.ai`.\n" + ] + }, + { + "cell_type": "markdown", + "id": "L1Z7VAf6L5a-", + "metadata": { + "id": "L1Z7VAf6L5a-" + }, + "source": [ + "### Fill-in-the-middle Example" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "68sG1liaLzFj", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "68sG1liaLzFj", + "outputId": "fc6f300d-dba0-49d6-a37c-c962c6be6fd1" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "def fibonacci(n: int): \n", + "\n", + " if n <= 0:\n", + " return 'Invalid input'\n", + " elif n == 1:\n", + " return 0\n", + " elif n == 2:\n", + " return 1\n", + " else:\n", + " a, b = 0, 1\n", + " for _ in range(2, n):\n", + " a, b = b, a + b\n", + " return b\n", + "\n", + " n = int(input('Enter a number: ')) print(fibonacci(n))\n" + ] + } + ], + "source": [ + "model = \"codestral-latest\"\n", + "prompt = \"def fibonacci(n: int):\"\n", + "suffix = \"n = int(input('Enter a number: ')) print(fibonacci(n))\"\n", + "\n", + "response = client.fim.complete(\n", + " model=model,\n", + " prompt=prompt,\n", + " suffix=suffix,\n", + " temperature=0,\n", + " top_p=1,\n", + ")\n", + "\n", + "print(f\"{prompt} {response.choices[0].message.content} {suffix}\")" + ] + }, + { + "cell_type": "markdown", + "id": "wx6ZnFcpMKG7", + "metadata": { + "id": "wx6ZnFcpMKG7" + }, + "source": [ + "### Code Completion Example" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "aaYK-F5oL-rF", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "aaYK-F5oL-rF", + "outputId": "e87c2668-2ff2-4cc9-d3f6-86f9e98fda56" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "def is_even(n): \n", + " return n % 2 == 0 \n", + "def test_is_even():\n", + "\n", + " assert is_even(2) == True\n", + " assert is_even(3) == False\n", + " assert is_even(8) == True\n", + " assert is_even(100) == True\n", + " assert is_even(0) == True\n", + "print(\"All test cases pass\")\n" + ] + } + ], + "source": [ + "prompt = '''def is_even(n):\n", + " return n % 2 == 0\n", + "def test_is_even():'''\n", + "response = client.fim.complete(model=model, prompt=prompt, temperature=0, top_p=1)\n", + "print(f'''{prompt}\n", + "{response.choices[0].message.content}''')\n" + ] + }, + { + "cell_type": "markdown", + "id": "Mj_jD8KQM1Aw", + "metadata": { + "id": "Mj_jD8KQM1Aw" + }, + "source": [ + "### Adding Stop Tokens for Controlled Output" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "wpvKyQoCMny6", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "wpvKyQoCMny6", + "outputId": "10aebd6b-2b9a-4276-8cf6-55167c7071fc" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "def calculate_factorial(n): \n", + " if n == 0:\n", + " return 1 \n", + " else:\n", + "\n", + " return n * calculate_factorial(n-1)\n" + ] + } + ], + "source": [ + "prompt = '''def calculate_factorial(n):\n", + " if n == 0:\n", + " return 1\n", + " else:'''\n", + "response = client.fim.complete(model=model, prompt=prompt, temperature=0, top_p=1, stop=['''\n", + "\n", + "'''])\n", + "print(f'''{prompt}\n", + "{response.choices[0].message.content}''')" + ] + }, + { + "cell_type": "markdown", + "id": "uaZPTIDVNjqa", + "metadata": { + "id": "uaZPTIDVNjqa" + }, + "source": [ + "### Code Generation Exercises" + ] + }, + { + "cell_type": "markdown", + "id": "f9G0oDECNm9W", + "metadata": { + "id": "f9G0oDECNm9W" + }, + "source": [ + "#### Exercise 1: Generate Code Using Fill-in-the-middle\n", + "Write a prompt and suffix for Codestral to generate a function that sorts a list in ascending order.\n", + "\n", + "#### Exercise 2: Code Completion Task\n", + "Write a prompt for a function `calculate_square` that takes an integer as input and returns its square. Let Codestral complete it." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "88seyk36NJRw", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "88seyk36NJRw", + "outputId": "450f1f0f-753b-4998-ae04-07dce9c19198" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "def sort_list(nums):\n", + "\n", + "\n", + " for i in range(len(nums)):\n", + " for j in range(len(nums) - 1):\n", + " if nums[j] > nums[j + 1]:\n", + " nums[j], nums[j + 1] = nums[j + 1], nums[j]\n", + "\n", + " return nums\n", + "\n", + "\n", + "print(sort_list([3, 1, 2]))\n" + ] + } + ], + "source": [ + "# Code Exercise Solution\n", + "# FIM example: prompt + suffix for sorting a list\n", + "prompt = \"def sort_list(nums):\"\n", + "suffix = \"print(sort_list([3, 1, 2]))\"\n", + "\n", + "response = client.fim.complete(\n", + " model=model, prompt=prompt, suffix=suffix, temperature=0, top_p=1\n", + ")\n", + "print(f'''{prompt}\n", + "{response.choices[0].message.content}\n", + "{suffix}''')" + ] + }, + { + "cell_type": "markdown", + "id": "ORVLj44qNvAs", + "metadata": { + "id": "ORVLj44qNvAs" + }, + "source": [ + "## 7. Vision Analysis with Pixtral" + ] + }, + { + "cell_type": "markdown", + "id": "q01t9SNBNzjX", + "metadata": { + "id": "q01t9SNBNzjX" + }, + "source": [ + "Pixtral introduces vision capabilities, allowing analysis of images. You can provide an image URL or a base64-encoded image.\n" + ] + }, + { + "cell_type": "markdown", + "id": "9pu_MlWPN7MG", + "metadata": { + "id": "9pu_MlWPN7MG" + }, + "source": [ + "### Analyzing an Image from a URL" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "Eh1ogRFSNwdI", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Eh1ogRFSNwdI", + "outputId": "3fff8403-5757-41d6-9bd6-f5044f118325" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The image depicts a wintery scene with the Eiffel Tower prominently visible in the background. The Eiffel Tower is covered in a light dusting of snow. Surrounding the Eiffel Tower are snow-covered trees and bushes. In the foreground, there's a pathway, streetlight, and some fencing, all dusted with snow. The atmosphere appears serene and cold, with the snow creating a peaceful winter ambiance.\n" + ] + } + ], + "source": [ + "model = \"pixtral-12b-2409\"\n", + "messages = [\n", + " {\n", + " \"role\": \"user\",\n", + " \"content\": [\n", + " {\"type\": \"text\", \"text\": \"What's in this image?\"},\n", + " {\"type\": \"image_url\", \"image_url\": \"https://tripfixers.com/wp-content/uploads/2019/11/eiffel-tower-with-snow.jpeg\"}\n", + " ]\n", + " }\n", + "]\n", + "chat_response = client.chat.complete(model=model, messages=messages)\n", + "print(chat_response.choices[0].message.content)" + ] + }, + { + "cell_type": "markdown", + "id": "Yy1h5c1sOXj_", + "metadata": { + "id": "Yy1h5c1sOXj_" + }, + "source": [ + "### Analyzing a Base64 Encoded Image" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "U5gu4VjwOYCa", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "U5gu4VjwOYCa", + "outputId": "e44bfbb6-c19b-4e86-b246-4ec9206e441c" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The image is a receipt for a dine-in service from a restaurant. The receipt includes the following details:\n", + "\n", + "1. **Date and Time**: The receipt is dated 02-Apr-2022 at 5:01:56 PM.\n", + "2. **Items Ordered**:\n", + " - 1 Empanada (Beef) - $3.00\n", + " - 1 Empanada (Cheese) - $3.00\n", + " - 1 Empanada (Chicken) - $3.00\n", + " - 1 Talarin Huancaina Lomo Saltado - $19.99\n", + " - 1 1/2 Pisco Sour - $15.00\n", + "3. **Subtotal**: The subtotal amount for the items is $43.99.\n", + "4. **Local Taxes**: A tax of 5.5% is applied, amounting to $2.42.\n", + "5. **Total**: The total amount to be paid is $46.41.\n", + "\n", + "Additionally, there is a message at the bottom of the receipt that reads:\n", + "\"IMMIGRANTS MAKE AMERICA GREAT THEY ALSO COOKED YOUR FOOD AND SERVED YOU TODAY GOD BLESS YOU\"\n", + "\n", + "The receipt also contains information for online services and privacy policies:\n", + "- Online: https://clover.com/r/D0BQZ3R656MDC\n", + "- Order: D0BQZ3R656MDC\n", + "- Clover Privacy Policy: https://clover.com/privacy\n" + ] + } + ], + "source": [ + "import base64\n", + "import requests\n", + "\n", + "def encode_image_from_url(image_url):\n", + " response = requests.get(image_url)\n", + " if response.status_code == 200:\n", + " return base64.b64encode(response.content).decode('utf-8')\n", + " else:\n", + " print(\"Failed to download the image.\")\n", + " return None\n", + "\n", + "# URL to the image\n", + "image_url = \"https://www.boredpanda.com/blog/wp-content/uploads/2022/11/interesting-receipts-102-6364c8d181c6a__700.jpg\"\n", + "base64_image = encode_image_from_url(image_url)\n", + "\n", + "if base64_image:\n", + " messages = [\n", + " {\n", + " \"role\": \"user\",\n", + " \"content\": [\n", + " {\"type\": \"text\", \"text\": \"What's in this image?\"},\n", + " {\"type\": \"image_url\", \"image_url\": f\"data:image/jpeg;base64,{base64_image}\"}\n", + " ]\n", + " }\n", + " ]\n", + " chat_response = client.chat.complete(model=model, messages=messages)\n", + " print(chat_response.choices[0].message.content)" + ] + }, + { + "cell_type": "markdown", + "id": "-cjVwtlsQXsN", + "metadata": { + "id": "-cjVwtlsQXsN" + }, + "source": [ + "### Vision Analysis Exercises" + ] + }, + { + "cell_type": "markdown", + "id": "EyIPjaRYQbIQ", + "metadata": { + "id": "EyIPjaRYQbIQ" + }, + "source": [ + "#### Exercise: Provide an Image URL\n", + "1. Find an image online that you would like to analyze.\n", + "2. Modify the `image_url` to point to your chosen image and analyze it using Pixtral." + ] + }, + { + "cell_type": "markdown", + "id": "439_E_yJQeJO", + "metadata": { + "id": "439_E_yJQeJO" + }, + "source": [ + "## 8. Conclusion and Recap" + ] + }, + { + "cell_type": "markdown", + "id": "-lmnXyBqQnFH", + "metadata": { + "id": "-lmnXyBqQnFH" + }, + "source": [ + "In this seminar, we explored:\n", + "- Setting up and using the Mistral API for various LLM tasks.\n", + "- Advanced text generation, embedding comparisons, chatbot memory, and API function calls.\n", + "- Hands-on examples to expand understanding and applications.\n", + "- Text and Code Generation with Codestral's FIM and Completion models.\n", + "- Vision analysis using Pixtral with both URL and Base64 image inputs.\n", + "\n", + "Thank you for participating, and feel free to experiment further with Mistral AI!" + ] + } + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}