diff --git a/book/_toc.yml b/book/_toc.yml index 791787b..c694c81 100644 --- a/book/_toc.yml +++ b/book/_toc.yml @@ -37,6 +37,21 @@ parts: title: "Rule 6: Test Code" - file: golden-rules/collaborate title: "Rule 7: Collaborate" + - file: llms/overview + title: Using LLMs + sections: + - file: llms/setup-guide + title: Setup Guide + - file: llms/effective-prompting + title: Effective Prompting + - file: llms/generating-code + title: Generating Code + - file: llms/debugging-errors + title: Debugging Errors + - file: llms/human-in-the-loop + title: The Importance of Human-in-the-Loop + + - caption: Installation chapters: - file: install/common diff --git a/book/llms/debugging-errors.ipynb b/book/llms/debugging-errors.ipynb new file mode 100644 index 0000000..16ef45f --- /dev/null +++ b/book/llms/debugging-errors.ipynb @@ -0,0 +1,201 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "914cfac4", + "metadata": {}, + "source": [ + "(llms-debugging-errors)=\n", + "# Debugging Errors\n", + "\n", + "LLMs are highly effective at identifying and fixing bugs in code, thanks to their training on vast datasets that include common coding mistakes and solutions. Instead of manually troubleshooting errors, you can leverage an AI coding assistant to quickly resolve issues and get back to building your project.\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "5cc84426", + "metadata": {}, + "source": [ + "## Quick Fixes\n", + "For minor errors, LLMs are very effective at providing quick fixes. In large projects, be careful to not provide too much context, as this can lead the LLM to focus on the wrong aspects of the code. Try being specific about the snippet you want it to analyze, rather than providing a lot of background information about the code's purpose or functionality. LLMs work best with concise, focused prompts that directly address the code snippet at hand.\n", + "\n", + "Practice using an LLM to solve the simple bugs you encounter in the code below which plots a sine wave. Typically you can copy and paste the code snippet into the LLM's input field and ask it to identify and fix the errors. \n", + "\n", + "```{admonition} Example Prompt\n", + ":class: example\n", + "As an example prompt, you can use:\n", + "> The following Python code has an error. Identify the error and provide a corrected version of the code. \n", + "> \n", + "> [Insert code snippet here]\n", + "```\n", + "\n", + "\n", + "Below is the code with some simple errors:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8b6ca224", + "metadata": {}, + "outputs": [], + "source": [ + "# ---------------------- student exercise --------------------------------- #\n", + "# DEBUG AND FIX THE FOLLOWING CODE USING AI FEATURES (hint: there are 3 bugs)\n", + "\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "x = np.linspace(0, 2 * np.pi, 100)\n", + "y = np.sin[x]\n", + "\n", + "plt.plot(x, y)\n", + "plt.title = \"Sine Wave\"\n", + "plt.xlabel(\"x values\")\n", + "plt.ylable(\"sin(x)\")\n", + "plt.show()\n", + "\n", + "# ---------------------- student exercise --------------------------------- #" + ] + }, + { + "cell_type": "markdown", + "id": "3f33d375", + "metadata": { + "vscode": { + "languageId": "plaintext" + } + }, + "source": [ + "## Providing Error Messages \n", + "\n", + "Typically when you run into an error, you will see an error message in the console. You can copy and paste this error message into the LLM to help it understand the problem. The LLM can then provide a solution based on the error message. This is especially useful for more complex issues where the code itself may not clearly indicate the problem. \n", + "\n", + "The below Python snippet is meant to plot a list of numbers after taking their inverse, however, it fails for a certain value. It still produces a (mostly correct) plot, but the error is visible in the console. Run the code below to see the error message, then copy and paste it into the LLM to get a fixed version.\n", + "\n", + "You will see an error message similar to:\n", + "> RuntimeWarning: divide by zero encountered in divide\n", + "\n", + "```{admonition} Example Prompt\n", + ":class: example\n", + "As an example prompt, you can use:\n", + "> The following Python code has an error, please identify the error and provide a corrected version of the code:\n", + "> \n", + "> [Insert code snippet here]\n", + ">\n", + "> The error message is:\n", + "> [Insert error message here]\n", + "```\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "95cca551", + "metadata": {}, + "outputs": [], + "source": [ + "# ---------------------- student exercise --------------------------------- #\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "def compute_inverse(arr):\n", + " return 1 / arr\n", + "\n", + "x = np.linspace(-1, 1, 101)\n", + "y = compute_inverse(x)\n", + "\n", + "plt.plot(x, y)\n", + "plt.title(\"Inverse Function\")\n", + "plt.xlabel(\"x values\")\n", + "plt.ylabel(\"1/x\")\n", + "plt.show()\n", + "# ---------------------- student exercise --------------------------------- #" + ] + }, + { + "cell_type": "markdown", + "id": "48ff0294", + "metadata": {}, + "source": [ + "More complex errors may require you to provide additional context or information about the code. In these cases, you can include a brief description of what the code is supposed to do, along with the error message. This helps the LLM understand the intended functionality and provide a more accurate solution.\n", + "\n", + "The error message you see on more complex errors may also provide more context about the issue in the form of a `traceback`. A traceback is a report that provides information about the sequence of function calls that led to the error. It can help you understand where the error occurred in the code and what might have caused it. \n", + "\n", + "```{admonition} Tip\n", + ":class: tip\n", + "Tracebacks can sometimes be very long and often contain a lot of information that is not relevant to the specific error you are trying to fix. When providing a traceback to an LLM, try to focus on the most relevant parts of the traceback which are typically the last few lines. In general, it is often sufficient to include the last few traceback calls and the final error message when debugging more complex issues.\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "fcb0ca2f", + "metadata": {}, + "source": [ + "## Iterative Debugging\n", + "The previous examples were able to be solved with a single prompt. However, more complex issues may require an iterative approach. This means you may need to provide additional context or information to the LLM based on its initial response, or it solves the first issue but after rerunning the code, another bug appears. In these cases, you can continue to refine your prompts and provide more information until the LLM arrives at a solution.\n", + "\n", + "```{admonition} Tip\n", + ":class: tip\n", + "When interacting with an LLM, it typically has a memory of the conversation, so you can refer back to previous messages. This means you can just provide the error messages without providing the code snippet again if it was already provided in the conversation. This can help streamline the debugging process and make it easier to focus on the specific issues at hand.\n", + "```\n", + "\n", + "Try running the code below to see an example of an iterative debugging process. The goal is to visualize a noisy sine wave. You can copy and paste the error message into the LLM, and then continue to refine your prompts based on its responses until you arrive at a solution. There are two errors in the code, so after providing the first error message, you can run the code again to see the second error message and provide that to the LLM as well until you have a working fully working code snippet." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "90dba6ee", + "metadata": {}, + "outputs": [], + "source": [ + "# ---------------------- student exercise --------------------------------- #\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "def scale_data(data, factor):\n", + " return data * factor\n", + "\n", + "def generate_and_scale_data():\n", + " x = np.linspace(0, 10, 100)\n", + " noise = np.random.normal(0, 1, 100)\n", + " y = np.sin(x) + noise\n", + " scaled = scale_data(y, \"2\")\n", + " return x, scaled\n", + "\n", + "x, y_scaled = generate_and_scale_data()\n", + "plt.scatter(x, y_scaled[::2])\n", + "plt.title(\"Noisy Sine Wave\")\n", + "plt.xlabel(\"x\")\n", + "plt.ylabel(\"scaled y\")\n", + "plt.show()\n", + "# ---------------------- student exercise --------------------------------- #" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/book/llms/effective-prompting.md b/book/llms/effective-prompting.md new file mode 100644 index 0000000..2f268a9 --- /dev/null +++ b/book/llms/effective-prompting.md @@ -0,0 +1,43 @@ +(llms-effective-prompting)= +# Effective Prompting +When interacting with an LLM about your code, the way you prompt the model can significantly impact the quality of its responses. We recommend using the integrated AI chat panel if present in your editor instead of external chatbot like ChatGPT. This allows the LLM to directly reference your project files and the broader code context. + +```{tip} +If you are using a coding assistant embedded into your editor, such as GitHub Copilot or Cursor AI, you can open the chatbot panel to interact with the LLM. This is typically found in the sidebar of your coding editor, allowing you to ask questions and get code suggestions directly related to your current project. +``` + +## Best Practices for Prompting LLMs +When prompting an LLM, it is essential to be clear and specific about what you want. Here are some strategies to improve your prompts: +1. **Be Specific**: Instead of asking a vague question, provide clear details about what you need. The more specific your question, the more related and useful the response will be. + +2. **Specify Context**: If you are working with a specific language, library, or framework, mention it in your prompt. This helps the LLM tailor its response to your needs. + +```{admonition} Example +:class: example +Say you want to create a numpy array with random values. Instead of asking "How do I create a random array?", you can ask "How do I create a numpy array with random integers between 1 and 10 in Python?". +``` + +3. **Desired Output Format**: If you want the response in a specific format, such as code with comments or a brief explanation, include that in your prompt. + +```{admonition} Example +:class: example +Instead of asking "How do I use Matplotlib in Python?", you can ask "Outline the steps to create a simple line plot using Matplotlib in Python, and provide a code example with comments explaining each step." +``` + +4. **Task Definition**: Telling the LLM what you want it to do in clear steps is far more important than telling it what not to do. + +```{admonition} Example +:class: example +Instead of saying "Don't give me a long explanation," you can say "Provide a brief example." +``` + + +5. **Structure**: Using a structure format in your question can lead to drastically better results. Rather than asking a general multipart question, break it down into smaller, more manageable parts with clear instructions. + +6. . **Role Definition**: If you want the LLM to act as a specific type of expert, such as a patient mentor or an expert in a particular field, specify that in your prompt. This helps the LLM understand the tone and depth of response you expect. + + +```{admonition} Tip +:class: tip +These skills apply to any LLM interaction, not just coding assistants. Next time you are using a personal assistant like ChatGPT, remember that specific prompts with context will yield better results! +``` \ No newline at end of file diff --git a/book/llms/generating-code.ipynb b/book/llms/generating-code.ipynb new file mode 100644 index 0000000..635cc75 --- /dev/null +++ b/book/llms/generating-code.ipynb @@ -0,0 +1,179 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "d0b11905", + "metadata": {}, + "source": [ + "(llms-generating-code)=\n", + "# Generating Code\n", + "One of the most powerful features of an AI coding assistant is its ability to generate repetitive or boilerplate code under your direction. This capability allows you to write code much faster while staying focused on higher-level concepts rather than getting stuck on syntax or implementation details. It is especially useful for tasks involving new libraries or functions that you may not be familiar with." + ] + }, + { + "cell_type": "markdown", + "id": "e8109d9c", + "metadata": {}, + "source": [ + "## Generating Snippets\n", + "When generating code snippets, you can provide a description of the functionality you need, and the AI will generate the corresponding code. You should specify the programming language and any relevant libraries or frameworks you want to use if you are using a chatbot that is not integrated in your editor. You can also specify the structure of the code, such as whether you want it in a function. \n", + "\n", + "In the code snippet below, ask the LLM to generate a function that normalizes a list of numbers. Ask the LLM to use the same function signature as the one you provided, and to use the `numpy` library for calculations. You can copy and paste the template below along your prompt to have the LLM fill it in.\n", + "\n", + "```{admonition} Tip\n", + ":class: tip\n", + "If using an integrated LLM like GitHub Copilot, you can generate code inline and avoid the hassle of copying and pasting. **You also then do not have to specify context regarding the programming langauge or surrounding comments.** It learns from context around the place where you call the inline code generation, so you can start typing a function signature or a comment, and it will suggest the code that follows! No extra prompting is needed as the function signature is often enough for simple tasks, and otherwise writing comments helps guide the integrated assistant.\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "640e873f", + "metadata": {}, + "outputs": [], + "source": [ + "# ---------------------- student exercise --------------------------------- #\n", + "import numpy as np\n", + "\n", + "def normalize_array(arr):\n", + " # YOUR CODE HERE\n", + " pass\n", + "\n", + "# ---------------------- student exercise --------------------------------- #" + ] + }, + { + "cell_type": "markdown", + "id": "094f23ca", + "metadata": {}, + "source": [ + "To verify the correctness of the generated code, run the cell below which runs a few tests. If the tests pass, it indicates that the code is functioning as expected." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "5a5dd182", + "metadata": {}, + "outputs": [], + "source": [ + "arr1 = np.array([0, 5, 10])\n", + "assert np.allclose(normalize_array(arr1), np.array([0.0, 0.5, 1.0]))\n", + "\n", + "arr2 = np.array([3, 3, 3])\n", + "assert np.allclose(normalize_array(arr2), np.array([np.nan, np.nan, np.nan])) or np.all(normalize_array(arr2) == 0)\n", + "\n", + "arr3 = np.array([-1, 0, 1])\n", + "assert np.allclose(normalize_array(arr3), np.array([0.0, 0.5, 1.0]))" + ] + }, + { + "cell_type": "markdown", + "id": "686dcef0", + "metadata": {}, + "source": [ + "## Generating Longer Code\n", + "For more complex tasks, the LLMs may struggle to generate the entire code in one go. Even if it does, it often fails to adhere to specific constraints or requirements you want if you ask for too much at once. In such cases, it is better to break down the task into smaller parts and generate code incrementally.\n", + "\n", + "You can start by asking the LLM to generate a function or a class and then iteratively refine it by asking for additional features or modifications. This way, you can guide the LLM to produce code that meets your specific needs. You can treat this as an interactive process or a conversation, where you provide feedback and ask for changes until the code meets your requirements. \n", + "\n", + "The example allows you to practice with a more complex task. Use LLMs to solve it!\n", + "\n", + "*Goal:* Write a function `find_local_maxima(matrix, threshold)` that takes a 2D NumPy array and returns the coordinates of all elements that are strict local maxima (greater than all 8 neighbors), and have a value greater than the threshold. The function should return a list of `(row, col)` index tuples.\n", + "\n", + "Although the example could still possibly be solved in one go, it is better to break it down into smaller parts. You can start by asking the LLM to generate a function that checks if a given element is a local maximum, and then build on that to find all local maxima in the matrix.\n", + "\n", + "```{admonition} Tip\n", + ":class: tip\n", + "To use code autocompletion features effectively, you can start typing a comment in the function that does the small subtask you want it to implement. For example, you can write `# Check if the element is a local maximum` and then let the LLM complete the snippet. This way, it will generate the complex task bit by bit, ensuring that it matches your expectations.\n", + "```\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "1b4f7740", + "metadata": {}, + "outputs": [], + "source": [ + "# ---------------------- student exercise --------------------------------- #\n", + "# YOUR CODE HERE\n", + "# ---------------------- student exercise --------------------------------- #" + ] + }, + { + "cell_type": "markdown", + "id": "4c4cf5b3", + "metadata": {}, + "source": [ + "Similarly to the previous example, you can run the cell below to test the correctness of the generated code. If the tests pass, it indicates that the code is functioning as expected." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "943c9a80", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "# Simple peak in center\n", + "mat1 = np.array([\n", + " [1, 2, 3],\n", + " [4, 9, 6],\n", + " [7, 8, 5]\n", + "])\n", + "assert find_local_maxima(mat1, threshold=5) == [(1, 1)]\n", + "\n", + "# No values above threshold\n", + "mat2 = np.array([\n", + " [1, 2, 1],\n", + " [2, 3, 2],\n", + " [1, 2, 1]\n", + "])\n", + "assert find_local_maxima(mat2, threshold=10) == []\n", + "\n", + "# Multiple peaks\n", + "mat3 = np.array([\n", + " [1, 9, 1, 9, 1],\n", + " [1, 1, 1, 1, 1],\n", + " [1, 9, 1, 9, 1]\n", + "])\n", + "expected = [(0, 1), (0, 3), (2, 1), (2, 3)]\n", + "assert sorted(find_local_maxima(mat3, threshold=5)) == expected\n", + "\n", + "# Border elements shouldn't be considered (by design)\n", + "mat4 = np.array([\n", + " [10, 10, 10],\n", + " [10, 5, 10],\n", + " [10, 10, 10]\n", + "])\n", + "# 5 is not greater than neighbors\n", + "assert find_local_maxima(mat4, threshold=0) == []\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/book/llms/human-in-the-loop.ipynb b/book/llms/human-in-the-loop.ipynb new file mode 100644 index 0000000..24f75c0 --- /dev/null +++ b/book/llms/human-in-the-loop.ipynb @@ -0,0 +1,61 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "4fd34523", + "metadata": {}, + "source": [ + "(llms-human-in-the-loop)=\n", + "# The Importance of Human-in-the-Loop\n", + "\n", + "While AI coding assistants can significantly speed up development, it is important to remember that these tools are meant to assist, not replace, human programmers. AI models can make critical errors, often in unexpected ways. To maintain high-quality code, it is essential to have **human oversight** by reviewing, testing, and validating any AI-generated code." + ] + }, + { + "cell_type": "markdown", + "id": "5ccd9d9b", + "metadata": {}, + "source": [ + "## Hallucinations\n", + "\n", + "AI models are more likely to produce incorrect outputs than admit to not knowing how to answer a question. Often, they will be confident in their wrong answers, which can lead to significant issues if not caught early. This phenomenon is known as **hallucination**.\n", + "\n", + "Real-world examples of AI hallucinations are numerous (and humorous), ranging from news articles publishing summer reading lists of fake books to attorneys referring to non-existent cases in court. \n", + "\n", + "In coding, this often means that the AI-generated code does not compile. In those cases, it is easy to spot the error. However, bugs, logic errors, or security vulnerabilities can be much harder to detect. These issues can lead to significant problems in production systems, including data loss, security breaches, and system failures.\n", + "\n", + "```{admonition} Example\n", + ":class: example\n", + "A famous example of LLMs being wrong is asking them to count. The rule-based nature of counting is not compatible with the probabilistic nature of LLMs. Try asking how many characters are in the following text:\n", + "> This is an example test designed to fool LLMs.\n", + "The correct answer is 46. You will likely get a different answer each time you ask, and it will almost always be wrong.\n", + "```\n", + "\n", + "In smaller Python scripts, it may simply mean that the code does not do what you expect it to do. \n", + "\n", + "The nondeterministic nature of LLMs means that they can generate different outputs for the same input, which can lead to inconsistencies and errors. This is particularly problematic in coding, where precision is crucial. " + ] + }, + { + "cell_type": "markdown", + "id": "8ecf0215", + "metadata": {}, + "source": [ + "## Best Practices\n", + "To mitigate the risks associated with AI coding assistants, it is essential to follow best practices:\n", + "\n", + "- **Review AI-generated code**: Always review the code generated by AI assistants. Look for logical errors, security vulnerabilities, and other potential issues.\n", + "- **Do not copy paste large blocks of code**: Instead, use AI to generate small snippets or to help with specific tasks. This allows you to maintain control over the code and reduces the risk of introducing errors.\n", + "- **Make sure you always understand the code**: If you do not understand what the AI-generated code does, it is likely that you will not be able to spot errors or issues. Take the time to read and understand the code before using it.\n", + "- **Test thoroughly**: Run tests on the AI-generated code to ensure it works as expected." + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/book/llms/overview.md b/book/llms/overview.md new file mode 100644 index 0000000..3a4dd47 --- /dev/null +++ b/book/llms/overview.md @@ -0,0 +1,21 @@ +# Using LLMs + +This section covers how to use Large Language Models (LLMs) as AI coding assistants, which can significantly enhance your programming experience. + +The part is structured as follows: +1. {ref}`How to set up your AI-assistant ` +2. {ref}`Effective Prompting with LLMs ` +3. {ref}`Generating Code with LLMs ` +4. {ref}`Debugging Errors with LLMs ` +5. {ref}`The Importance of Human-in-the-Loop ` + +## Overview +Programming often requires writing repetitive code and debugging nasty errors. These tasks can be time-consuming and may distract you from your original goal of solving a problem or building a feature. + +Large Language Models can be especially useful in this context, as they can be trained on large amounts of code to provide intelligent code completions, suggestions, and even bug fixes. It is common practice in today's software development landscape to use AI-powered tools to help with writing code. This concept in programming came to be known as pair programming with AI, which stems from the notion of pair programming, which is when two developers write code together, allowing them to spot each other's mistakes and collaborate on ideas while programming. Pair programming with AI has become so powerful that even in a top-tier company like Google which only hires the best programmers, [CEO Sundar Pichai made a statement](https://fortune.com/2024/10/30/googles-code-ai-sundar-pichai/) that over 25% of Google's code is now written by AI, and this number is expected to grow in the future. This shows how AI is revolutionizing the way we write code. + +In this series of notebooks, we explore how to effectively use AI coding assistants to streamline your Python development process. Some key concepts to take away from this workshop include: +* **Effective prompting**: Be specific and detailed in your prompts to receive accurate and relevant responses. +* **Generating code**: Use AI to generate repetitive or boilerplate code, but maintain control over the process. +* **Debugging errors**: Use AI assistants to quickly identify and fix bugs in your code. +* **Human-in-the-loop**: Always review and validate AI-generated code to ensure quality and accuracy. diff --git a/book/llms/setup-guide.md b/book/llms/setup-guide.md new file mode 100644 index 0000000..2f1b85e --- /dev/null +++ b/book/llms/setup-guide.md @@ -0,0 +1,36 @@ +(llms-setup-guide)= +# Setting up the environment + +LLMs can assist in various aspects of software development, but one of the most effective ways to integrate them into your programming experience is directly within your code editor. Tools like GitHub Copilot allow seamless access to AI-powered suggestions, reducing the need for copy-pasting and enabling the LLM to better understand the context of your entire project or file. + +This notebook will guide you through different options for setting up your environment. The following options provide an integrated experience and allow you to access powerful models with your student account.   + +## [Option 1, preferred, but GitHub account required] GitHub Copilot Set Up +GitHub Copilot is the industry standard for pair programming, and as a student, you can access it for free. You can request access to it by signing up for the [GitHub Student Developer Pack](https://education.github.com/pack). There is a detailed guide for [how to apply for GitHub Education as a student](https://docs.github.com/en/education/explore-the-benefits-of-teaching-and-learning-with-github-education/github-education-for-students/apply-to-github-education-as-a-student) which will grant you access to Copilot. Ensure you use your full student email (i.e. \@student.tudelft.nl) and note that it may take a few days before your application is processed/ accepted. If you don't want to create a GitHub account (GitHub is part of Microsoft), please consider the other options). After you have access, proceed with the following steps: +* Download [VS Code](https://code.visualstudio.com/download) or any other supported IDE you prefer. +* Under the "Extensions" tab on the left in VS Code, install two extensions: + * `GitHub Copilot` - this gives you code-generation features + * `GitHub Copilot Chat` - this is an add-on to Copilot that gives you a ChatGPT-like chat feature that has access to your codebase. + +```{admonition} Tip     +:class: tip     +Apply for GitHub Education as soon as possible, as it may take a few days for your application to be processed. Once you have access, you can start using GitHub Copilot in your IDE. +``` + +## [Option 2] Microsoft Copilot +With your student account, you've access to Microsoft Copilot: https://copilot.microsoft.com/. If you are using Microsoft Edge, you can sign in with your student account and use the built-in Copilot feature that is available in the sidebar. This allows you to interact with an LLM directly in your browser, and while it does not provide direct code generation capabilities like GitHub Copilot, it can still be useful for asking questions and getting explanations about code. To access it, simply open Microsoft Edge and look for the Copilot icon in the top right corner. + + +## [Option 3] Google Colab with Gemini +If you are using [Google Colab](https://colab.research.google.com/) to access their GPUs, you can use the built-in [Gemini](https://ai.google.dev/) chat feature. While this does not come with code generation directly, it serves as an integrated ChatGPT-like interface that can be extremely useful. There is no additional setup here, simply click on the "Gemini" button in the top right and it will open the chat feature. A google account is required for this service. + +## [Bonus Option] Cursor Editor Set Up +If you are provided with API keys to advanced models such as the ones provided by OpenAPIT, Cursor is a fork of VS Code that allows full integration with LLMs within the editor like GitHub Copilot and allows using private API keys. To help you set up your environment, we prepared [this video tutorial on setting up and getting started with the Cursor Editor](https://youtu.be/PjFaeqnCgLs) from the DSAIE course. Alternatively, follow the instructions below. Only use this option if API keys are provided. +* Download and install Cursor from the [website](https://www.cursor.com/) +* In Cursor, in the top left tabs select File > Preferences > Cursor Settings. Now on the left vertical tab select Models, scroll down to OpenAI API Key, and paste your API key. +* Download this notebook and open it in Cursor. + +Some helpful quick links for Cursor: +* [Documentation](https://docs.cursor.com/chat/overview) +* [Feature List](https://www.cursor.com/features) +* [Migrating from VS Code](https://docs.cursor.com/get-started/migrate-from-vscode)