{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# DSPy Tutorial: Building a Code Plagiarism Detector\n",
"\n",
"If you've ever felt intimidated by DSPy, don't worryβit might look complex at first glance, but it's actually quite approachable. This tutorial will walk you through the process of building a project, providing a clear, step-by-step approach to understanding and implementing DSPy concepts.\n",
"\n",
"## TLDR π\n",
"\n",
"We're going to build a system for code plagiarism detection. Our goal is to compare two input code files, determine if plagiarism has occurred, and provide an explanation for the result. \n",
"\n",
"This project will showcase:\n",
"\n",
"- Multiple inputs and outputs\n",
"- Double validation techniques\n",
"\n",
"I strongly recommend reading the [DSPy Cheatsheet](https://dspy-docs.vercel.app/docs/cheatsheet) it will help you with quick start.\n",
"\n",
"## How to Start?\n",
"\n",
"A highly effective practice I've found to be game-changing when starting any DSPy project is to answer [these 8 key questions](https://dspy-docs.vercel.app/docs/building-blocks/solving_your_task). This exercise helps you develop a clear vision for your project before diving into the code.\n",
"\n",
"Here's an example of how your answers might look:\n",
"1. **Define your task**\n",
" - Expected input: Two input code files (strings containing plain code) to be compared.\n",
" - Expected output:\n",
" - Plagiarism detection result (Yes/No)\n",
" - Explanation/justification of the result\n",
" - Quality and Cost Specifications: Cost is not a concern; quality is the main priority. We want to try different models.\n",
"\n",
"2. **Define your pipeline**\n",
" - We don't need any external tools or document retrieval. It will be a simple chain-of-thought step, as we want to evaluate LLM capabilities for plagiarism detection.\n",
"\n",
"3. **Explore a few examples**\n",
" - We explored LLM capabilities for plagiarism detection using a few examples with ChatGPT and Claude, yielding promising results.\n",
"\n",
"4. **Define your data**\n",
" - We are working with a dataset from the publication: [Source Code Plagiarism Detection in Academia with Information Retrieval: Dataset and the Observation](https://github.com/oscarkarnalim/sourcecodeplagiarismdataset/blob/master/IR-Plag-Dataset.zip)\n",
" - We selected a subset and manually labeled the dataset with our output labels. This dataset should be used for training and testing, while the rest of the original dataset should be used for evaluation.\n",
" - Dataset: [train.csv](/data/train.tsv) (65 samples)\n",
" - When you don't have labeled dataset, it is good idea to try hand-labeling a few examples to get a sense of the task. It will help you to understand the task better and also increase the quality of program.\n",
"\n",
"5. **Define your metric**\n",
" - We are dealing with a **classification problem**, so we will use accuracy as our main metric. \n",
" - Our metric will be simple: if pred_label == true_label then 1 else 0.\n",
" - As second evaluation we will be evaluating the quality of the explanation via secondary LLM.\n",
"\n",
"6. **Collect preliminary \"zero-shot\" evaluations**\n",
" - Done in code.\n",
"\n",
"7. **Compile with a DSPy optimizer**\n",
" - We don't want to update weights of the LLM, so we are looking at optimizers such as:\n",
" - BootstrapFewShot\n",
" - BootstrapFewShotWithRandomSearch\n",
" - MIPRO\n",
" - ...\n",
"\n",
"8. **Iterate**\n",
" - Regroup and attack again!\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import re\n",
"\n",
"import dspy\n",
"import pandas as pd\n",
"from dotenv import load_dotenv\n",
"from dspy.evaluate import Evaluate\n",
"from dspy.teleprompt import (\n",
" BootstrapFewShot,\n",
" BootstrapFewShotWithRandomSearch,\n",
" KNNFewShot,\n",
" MIPROv2,\n",
")\n",
"\n",
"# load your environment variables from .env file\n",
"load_dotenv()\n",
"\n",
"# azure-openai model deployment\n",
"AZURE_OPENAI_KEY = os.getenv(\"AZURE_OPENAI_KEY\")\n",
"AZURE_OPENAI_ENDPOINT = os.getenv(\"AZURE_OPENAI_ENDPOINT\")\n",
"AZURE_OPENAI_DEPLOYMENT = os.getenv(\"AZURE_OPENAI_DEPLOYMENT\")\n",
"AZURE_OPENAI_VERSION = os.getenv(\"AZURE_OPENAI_VERSION\")\n",
"\n",
"# openai model deployment\n",
"\n",
"OPENAI_MODEL = os.getenv(\"OPENAI_MODEL\")\n",
"OPENAI_API_KEY = os.getenv(\"OPENAI_API_KEY\")\n",
"\n",
"# ollama deployment\n",
"OLLAMA_URL = os.getenv(\"OLLAMA_URL\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 0. Load dataset\n",
"\n",
"Our first task is to load our dataset. Each entry in our dataset will consist of the following components:\n",
"\n",
"* `sample_1`: The first code sample to be analyzed\n",
"* `sample_2`: The second code sample to be compared against the first\n",
"* `plagiarized`: A boolean value (True if plagiarism is detected, False otherwise)\n",
"* `reason`: A detailed explanation of the plagiarism detection result\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
| \n", " | L | \n", "case | \n", "sample_1 | \n", "sample_2 | \n", "plagiarized | \n", "reason | \n", "
|---|---|---|---|---|---|---|
| 0 | \n", "0 | \n", "1 | \n", "public class T1 { public static void main(Str... | \n", "/* * To change this license header, choose Li... | \n", "False | \n", "The two code samples, while producing similar ... | \n", "
| 1 | \n", "0 | \n", "1 | \n", "public class T1 { public static void main(Str... | \n", "/** * * @author 65FBEF05E01FAC390CB3FA073FB3... | \n", "False | \n", "The code samples demonstrate different approac... | \n", "
| 2 | \n", "0 | \n", "1 | \n", "public class T1 { public static void main(Str... | \n", "/** * * @author CB6AB3315634A1E4D11B091BA48B... | \n", "False | \n", "The two code samples produce the same output b... | \n", "
| 3 | \n", "1 | \n", "1 | \n", "public class T1 { public static void main(Str... | \n", "* * To change this license header, choose Lice... | \n", "True | \n", "The two code samples are nearly identical in t... | \n", "
| 4 | \n", "2 | \n", "1 | \n", "public class T1 { public static void main(Str... | \n", "/* * To change this license header, choose Li... | \n", "True | \n", "The two code samples contain identical main me... | \n", "