'), Textarea(value='', description='Learni…"
+ ],
+ "application/vnd.jupyter.widget-view+json": {
+ "version_major": 2,
+ "version_minor": 0,
+ "model_id": "267d309e116a456ebee8b8f85f393e06"
+ }
+ },
+ "metadata": {}
+ }
+ ],
+ "source": [
+ "InstructorGradingConfig().run_ui_container()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "W9SqmkpeIgpk"
+ },
+ "source": [
+ "You will need an OpenAI API key in order to access the chat functionality. In the following cell, you'll see a blank box pop up - copy your API key there and press enter."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "MK8R5DmEYiG5",
+ "outputId": "c756cf79-85ee-43e2-b261-aaabc0f76e85"
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "··········\n"
+ ]
+ }
+ ],
+ "source": [
+ "# setup open AI api key\n",
+ "openai_api_key = getpass()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "collapsed": true,
+ "id": "0bp158bj_0s6"
+ },
+ "source": [
+ "# Execute Grading\n",
+ "Run this cell set to have the generative AI assist you in grading."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "vyJuQ7RUR8tB"
+ },
+ "source": [
+ "## Installation and Loading"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {
+ "id": "tjKxWLA3YiG5"
+ },
+ "outputs": [],
+ "source": [
+ "%%capture\n",
+ "# install additional packages if needed\n",
+ "! pip install -q langchain openai"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {
+ "id": "S3oQiNm_YiG5"
+ },
+ "outputs": [],
+ "source": [
+ "# import necessary libraries here\n",
+ "from langchain.llms import OpenAI\n",
+ "from langchain.chat_models import ChatOpenAI\n",
+ "from langchain.prompts import PromptTemplate\n",
+ "from langchain.document_loaders import TextLoader\n",
+ "from langchain.indexes import VectorstoreIndexCreator\n",
+ "from langchain.text_splitter import CharacterTextSplitter\n",
+ "from langchain.embeddings import OpenAIEmbeddings\n",
+ "from langchain.schema import SystemMessage, HumanMessage, AIMessage\n",
+ "import openai"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {
+ "id": "uXfSTQPrYiG5"
+ },
+ "outputs": [],
+ "source": [
+ "# Helper because lines are printed too long; helps with wrapping visualization\n",
+ "from IPython.display import HTML, display\n",
+ "\n",
+ "def set_css():\n",
+ " display(HTML('''\n",
+ " \n",
+ " '''))\n",
+ "get_ipython().events.register('pre_run_cell', set_css)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 17
+ },
+ "id": "sTQFW9TxYiG5",
+ "outputId": "b5552d55-8549-4b56-c91e-54ef76d9308d"
+ },
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "text/html": [
+ "\n",
+ " \n",
+ " "
+ ]
+ },
+ "metadata": {}
+ }
+ ],
+ "source": [
+ "# Set pandas display options\n",
+ "pd.set_option('display.max_columns', None)\n",
+ "pd.set_option('display.max_colwidth', 0)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "DOACT_LSSM58"
+ },
+ "source": [
+ "Setting of API key in environment and other settings"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 17
+ },
+ "id": "OV05xRtDYiG5",
+ "outputId": "aefc4782-11d7-450c-cece-b9289a256e2f"
+ },
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "text/html": [
+ "\n",
+ " \n",
+ " "
+ ]
+ },
+ "metadata": {}
+ }
+ ],
+ "source": [
+ "#extract info from dictionary\n",
+ "json_file_path = grade_settings['json_file_path']\n",
+ "learning_objectives = grade_settings['learning_objectives']\n",
+ "\n",
+ "#set API key\n",
+ "os.environ[\"OPENAI_API_KEY\"] = openai_api_key\n",
+ "openai.api_key = openai_api_key"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "YreIs-I-tuxx"
+ },
+ "source": [
+ "Initiate the OpenAI model using Langchain."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 17
+ },
+ "id": "ZRn9wbJBYiG5",
+ "outputId": "7dbbfb85-1a1d-44b7-d2b1-86bb6f6b3948"
+ },
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "text/html": [
+ "\n",
+ " \n",
+ " "
+ ]
+ },
+ "metadata": {}
+ }
+ ],
+ "source": [
+ "llm = ChatOpenAI(model='gpt-3.5-turbo-16k')\n",
+ "messages = [\n",
+ " SystemMessage(content=\"You are a helpful assistant.\"),\n",
+ " HumanMessage(content=\"\")\n",
+ "]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "pIKYtr0UTJNc"
+ },
+ "source": [
+ "## Functions to help with loading json"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "t7O3XPC29Osw"
+ },
+ "source": [
+ "`file_upload_json_to_df` helps when you use the file uploader as the json is directly read in this case. `clean_keys` helps when there are errors on the keys when reading."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 17
+ },
+ "id": "qGxPHexrYiG5",
+ "outputId": "9f9fd378-e67f-404a-9ee1-9eacaf535c22"
+ },
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "text/html": [
+ "\n",
+ " \n",
+ " "
+ ]
+ },
+ "metadata": {}
+ }
+ ],
+ "source": [
+ "# Strip beginning and ending newlines\n",
+ "def clean_keys(loaded_json):\n",
+ " out_json = [{key.strip():value for key, value in json_dict.items()} for json_dict in loaded_json ]\n",
+ " return out_json\n",
+ "\n",
+ "# Convert difficult datatypes to newlines\n",
+ "def file_upload_json_to_df(upload_json):\n",
+ "\n",
+ " #get middle key of json to extract content\n",
+ " fname = list(upload_json.keys())[0]\n",
+ "\n",
+ " #load the json; strict allows us to get around encoding issues\n",
+ " loaded_json = json.loads(upload_json[fname]['content'], strict=False)\n",
+ "\n",
+ " #clean the keys if needed\n",
+ " loaded_json = clean_keys(loaded_json)\n",
+ "\n",
+ " return pd.DataFrame(loaded_json)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "MOwaLI97Igpm"
+ },
+ "source": [
+ "`load_json_as_df` helps when you use the file uploader as the json is directly read in this case. It accepts the path to the JSON to load the dataframe based on the json."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 17
+ },
+ "id": "w0xN9CJeYiG6",
+ "outputId": "8d72824d-2a57-4d17-f967-4c2d4793b32e"
+ },
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "text/html": [
+ "\n",
+ " \n",
+ " "
+ ]
+ },
+ "metadata": {}
+ }
+ ],
+ "source": [
+ "def load_json_as_df(fpath):\n",
+ " # check if file is .json\n",
+ " if not fpath.endswith('.json'):\n",
+ " return None\n",
+ "\n",
+ " keys = [\"timestamp\", \"author\", \"message\"]\n",
+ "\n",
+ " df_out = None\n",
+ " out_error = None\n",
+ "\n",
+ " try:\n",
+ " # Read JSON file\n",
+ " with open(fpath, \"r\") as f:\n",
+ " json_data = f.read()\n",
+ "\n",
+ " # Load JSON data\n",
+ " data = json.loads(json_data, strict=False)\n",
+ "\n",
+ " # Quick check to see if we can fix common errors in json\n",
+ " # 1. JSON responses wrapped in enclosing dictionary\n",
+ " if isinstance(data, dict):\n",
+ " if len(data.keys()) == 1:\n",
+ " data = data[list(data.keys())[0]]\n",
+ " else:\n",
+ " data = [data] #convert to list otherwise\n",
+ "\n",
+ " # We only operate on lists of dictionaries\n",
+ " if isinstance(data, list):\n",
+ " data = clean_keys(data) #clean keys to make sure there are no unnecessary newlines\n",
+ "\n",
+ " if all(all(k in d for k in keys) for d in data):\n",
+ " df_out = pd.json_normalize(data)\n",
+ " if len(df_out) <=1:\n",
+ " out_error = [fpath, \"Warning: JSON keys correct, but something wrong with the overall structure of the JSON when converting to dataframe. The dataframe only has one row. Skipping.\"]\n",
+ " df_out = None\n",
+ " else:\n",
+ " out_error = [fpath, \"Error: JSON Keys are incorrect. Found keys: \" + str(list(data[0].keys()))]\n",
+ " else:\n",
+ " out_error = [fpath, \"Error: Something is wrong with the structure of the JSON.\"]\n",
+ "\n",
+ " except Exception as e:\n",
+ " print(f\"Error processing file {fpath}: {str(e)}\")\n",
+ " out_error = [fpath, \"Fatal System Error: \"+str(e)]\n",
+ "\n",
+ " if df_out is not None:\n",
+ " df_out['filename'] = fpath\n",
+ "\n",
+ " return df_out, out_error\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "N2yuYFQJYiG6"
+ },
+ "source": [
+ "`create_user_dataframe` filters based on role to create a dataframe for only user responses"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 17
+ },
+ "id": "58hygjTXYiG6",
+ "outputId": "a6d4d789-e168-4b57-ccf4-c8acf36974cd"
+ },
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "text/html": [
+ "\n",
+ " \n",
+ " "
+ ]
+ },
+ "metadata": {}
+ }
+ ],
+ "source": [
+ "def create_user_dataframe(df):\n",
+ " df_user = df.query(\"`author` == 'user'\")\n",
+ "\n",
+ " return df_user"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "KA5moX-1Igpn"
+ },
+ "source": [
+ "The `process_file` and `process_files` functions provide the implementation of prompt templates for instructor grading. It uses the input components to assemble a prompt and then sends this prompt to the llm for evaluation alongside the read dataframes."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 17
+ },
+ "id": "nFz3UVL3YiG6",
+ "outputId": "d0e5b187-85f4-48d4-8ef6-1a15b0b1f640"
+ },
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "text/html": [
+ "\n",
+ " \n",
+ " "
+ ]
+ },
+ "metadata": {}
+ }
+ ],
+ "source": [
+ "def process_file(df, desc, instr, print_results):\n",
+ " messages_as_string = '\\n'.join(df['message'].astype(str))\n",
+ " context = messages_as_string\n",
+ "\n",
+ " # Assemble prompt\n",
+ " prompt = desc if desc is not None else \"\"\n",
+ " prompt = (prompt + instr + \"\\n\") if instr is not None else prompt\n",
+ " prompt = prompt + \"Here is the chat log: \\n\\n\" + context + \"\\n\"\n",
+ "\n",
+ " # Get results and optionally print\n",
+ " messages[1] = HumanMessage(content=prompt)\n",
+ " result = llm(messages)\n",
+ "\n",
+ " # Check if 'filename' exists in df\n",
+ " if 'filename' in df:\n",
+ " if print_results:\n",
+ " print(f\"\\n\\nResult for file {df['filename'][0]}: \\n{result.content}\")\n",
+ " else:\n",
+ " if print_results:\n",
+ " print(f\"\\n\\nResult for file: Unknown Filename \\n{result.content}\")\n",
+ "\n",
+ " return result\n",
+ "\n",
+ "def process_files(json_dfs, output_desc=None, grad_instructions=None, use_defaults = False, print_results=True):\n",
+ " if use_defaults:\n",
+ " output_desc = (\"Given the following chat log, create a table with the question number, the question content, answer, \"\n",
+ " \"whether or not the student answered correctly on the first try, and the number of attempts it took to get the right answer. \")\n",
+ " grad_instructions = (\"Then, calculate the quiz grade from the total number of assessment questions. \"\n",
+ " \"Importantly, a point should only be granted if an answer was correct on the very first attempt. \"\n",
+ " \"If an answer was not correct on the first attempt, even if it was correct in subsequent attempts, no point should be awarded for that question. \")\n",
+ "\n",
+ " results = [process_file(df, output_desc, grad_instructions, print_results) for df in json_dfs]\n",
+ "\n",
+ " return results"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "lXQ45cJ1AztR"
+ },
+ "source": [
+ "`pretty_print` makes dataframes look better when printed by substituting non-HTML with HTML for rendering."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 17
+ },
+ "id": "0te_RLOOYiG6",
+ "outputId": "a5761b65-c641-46e9-b76a-f9906a7df6c3"
+ },
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "text/html": [
+ "\n",
+ " \n",
+ " "
+ ]
+ },
+ "metadata": {}
+ }
+ ],
+ "source": [
+ "def pretty_print(df):\n",
+ " return display( HTML( df.to_html().replace(\"\\\\n\",\" \") ) )"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "I3rKk7lJYiG6"
+ },
+ "source": [
+ "`save_as_csv` saves the dataframe as a CSV"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 17
+ },
+ "id": "DnrH2ldeYiG6",
+ "outputId": "b7f7132a-4e59-4f70-80a7-477f788acf1b"
+ },
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "text/html": [
+ "\n",
+ " \n",
+ " "
+ ]
+ },
+ "metadata": {}
+ }
+ ],
+ "source": [
+ "def save_as_csv(df, file_name):\n",
+ " df.to_csv(file_name, index=False)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 19,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 17
+ },
+ "id": "Vgo_y8R8bzTE",
+ "outputId": "c50bb1b5-77d9-49bd-817f-ebc727c65256"
+ },
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "text/html": [
+ "\n",
+ " \n",
+ " "
+ ]
+ },
+ "metadata": {}
+ }
+ ],
+ "source": [
+ "def show_json_loading_errors(err_list):\n",
+ " if err_list:\n",
+ " print(\"The following files have the following errors upon loading and will NOT be processed:\", '\\n'.join(err_list))\n",
+ " else:\n",
+ " print(\"No errors found in uploaded zip JSON files.\")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "85h5oTysJkHs"
+ },
+ "source": [
+ "## Final data preparation steps"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 17
+ },
+ "id": "Upah5_ygZRZx",
+ "outputId": "42cb51a7-3ce7-41e6-8209-d76844742f65"
+ },
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "text/html": [
+ "\n",
+ " \n",
+ " "
+ ]
+ },
+ "metadata": {}
+ }
+ ],
+ "source": [
+ "#additional processing setup\n",
+ "json_files = grade_settings['json_files']\n",
+ "load_responses = [load_json_as_df(jf) for jf in json_files]\n",
+ "\n",
+ "#unzip to two separate lists\n",
+ "all_json_dfs, errors_list = zip(*load_responses)\n",
+ "\n",
+ "# Remove failed JSONs\n",
+ "all_json_dfs = [df for df in all_json_dfs if df is not None]\n",
+ "\n",
+ "# Update errors list to be individual strings\n",
+ "errors_list = [' '.join(err) for err in errors_list if err is not None]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "P_H4uIfmAsr0"
+ },
+ "source": [
+ "# AI-Assisted Evaluation\n",
+ "Introduction and Instructions\n",
+ "--------------------------------------------------\n",
+ "The following example illustrates how you can specify important components of the prompts for sending to the llm. The `process_files` function will iterate over all of the submissions in your zip file, create dataframes of results (via instruction by setting `output_setup`), and also perform evaluation based on your instructions (via instruction by setting `grading_instructions`).\n",
+ "\n",
+ "Example functionality is demonstrated below."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 71
+ },
+ "id": "9zIPjG5lco3Z",
+ "outputId": "95fc2ea1-bce6-4a70-ef79-068240c2f936"
+ },
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "text/html": [
+ "\n",
+ " \n",
+ " "
+ ]
+ },
+ "metadata": {}
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "The following files have the following errors upon loading and will NOT be processed: test2/poem_demo.json Error: JSON Keys are incorrect. Found keys: ['role', 'content']\n",
+ "test2/algebra_demo (1).json Error: JSON Keys are incorrect. Found keys: ['role', 'content']\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Print list of files with the incorrect format\n",
+ "show_json_loading_errors(errors_list)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 356
+ },
+ "id": "utPzYUoKYiG9",
+ "outputId": "57a11896-5e50-4018-fb52-3ec0e1b36188"
+ },
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "text/html": [
+ "\n",
+ " \n",
+ " "
+ ]
+ },
+ "metadata": {}
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "\n",
+ "\n",
+ "Result for file test2/demo_json (1).json: \n",
+ "Here is the table with the question number, question content, answer, whether or not the student answered correctly on the first try, and the number of attempts it took to get the right answer:\n",
+ "\n",
+ "| Question Number | Question Content | Answer | Correct on First Try | Number of Attempts |\n",
+ "|-----------------|-----------------|--------|----------------------|--------------------|\n",
+ "| 1 | | C | Yes | 1 |\n",
+ "| 2 | | A | No | 1 |\n",
+ "| 3 | | D | Yes | 2 |\n",
+ "| 4 | | C | Yes | 1 |\n",
+ "| 5 | | B | Yes | 1 |\n",
+ "\n",
+ "\n",
+ "To calculate the quiz grade, we will only count the questions where the student answered correctly on the first try. In this case, the student answered questions 1, 3, 4, and 5 correctly on the first try. Therefore, the quiz grade would be 4 out of 5, or 80%.\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Example\n",
+ "output_setup = (\"Given the following chat log, create a table with the question number, the question content, answer, \"\n",
+ " \"whether or not the student answered correctly on the first try, and the number of attempts it took to get the right answer. \")\n",
+ "grading_instructions = (\"Then, calculate the quiz grade from the total number of assessment questions. \"\n",
+ " \"Importantly, a point should only be granted if an answer was correct on the very first attempt. \"\n",
+ " \"If an answer was not correct on the first attempt, even if it was correct in subsequent attempts, no point should be awarded for that question. \")\n",
+ "\n",
+ "# Assuming `file_paths` is a list of file paths.\n",
+ "processed_submissions = process_files(all_json_dfs, output_setup, grading_instructions, use_defaults = False, print_results=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "Pc1myGweIgpo"
+ },
+ "source": [
+ "## Instructor-Specified Evaluation\n",
+ "Now, you can use the following code to create your settings. Change `output_setup` and `grading_instructions` as desired, making sure to keep the syntax (beginning and ending parentheses,and quotes at the beginning and end of each line) correct. `output_setup` has been copied from the previous cell, but you should fill in `grading_instructions`.\n",
+ "\n",
+ "### File Processing Options\n",
+ "The `process_files` function has a number of settings.\n",
+ "* The first setting must always be `all_json_dfs`, which contains the tabular representation of the json output.\n",
+ "* The other settings should be set by name, and are:\n",
+ " * **`output_desc`**: Shown as `output_setup` here, this contains the isntructions about how you want to the tabular representation to be set up. Note that you can also leave this off of the function list (just erase it and the following comma).\n",
+ " * **`grad_instructions`**: Shown as `grading_instructions` here, use this variable to set grading instructions. Note that you can also leave this off of the function list (erase it and the following comma)\n",
+ " * **`use_defaults`**: Some default grading and instruction prompts have already been created. If you set `use_defaults=TRUE`, both the grading instructions and the output table description will use the default prompts provided by the program, regardless of whether you have set values for `output_desc` or `grad_instructions`.\n",
+ " * **`print_results`**: By default, the results will be printed for all students. However, if you don't want to see this output, you can set `print_results=False`.\n",
+ "\n",
+ "Again, make sure to observe the syntax. The defaults used in the program are shown in the above example."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "id": "GiebKVlbYiG9"
+ },
+ "outputs": [],
+ "source": [
+ "output_setup = (\"Given the following chat log, create a table with the question number, the question content, answer, \"\n",
+ " \"whether or not the student answered correctly on the first try, and the number of attempts it took to get the right answer. \")\n",
+ "\n",
+ "# add your own grading instructions\n",
+ "grading_instructions = (\"INSERT ANY CUSTOM GRADING INSTRUCTIONS HERE\")\n",
+ "\n",
+ "# Assuming `file_paths` is a list of file paths.\n",
+ "processed_submissions = process_files(all_json_dfs, output_setup, grading_instructions, use_defaults = False, print_results=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "snLA6OZ83CrS"
+ },
+ "source": [
+ "## Grading based on Blooms Taxonomy\n",
+ "Another mechanism of evaluation is through Bloom's Taxonomy, where student responses will be evaluated based on where they fall on Bloom's Taxonomy. The higher the score with Bloom's Taxonomy, the more depth is illustrated by the question."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 1000
+ },
+ "id": "HEPXCJdrYiG-",
+ "outputId": "0800cdfe-396c-4b30-bee5-237561433145"
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ " \n",
+ " "
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "\n",
+ "Result for file demo_json/cs_demo.json: \n",
+ "Based on the student's responses, here is the evaluation of their overall level of engagement and knowledge, based on Bloom's Taxonomy:\n",
+ "\n",
+ "1. What are the differences between stacks and queues?\n",
+ "Level: Understand (2)\n",
+ "The student demonstrates an understanding of the differences between stacks and queues by asking for examples.\n",
+ "\n",
+ "2. Can you list examples of when you would want to use stacks over queues and vice versa?\n",
+ "Level: Apply (3)\n",
+ "The student applies their understanding of stacks and queues by providing examples of when each data structure would be preferred.\n",
+ "\n",
+ "3. Given the following two learning objectives: Objective 1: Understand the differences stacks and queues... Is there anything else I need to know?\n",
+ "Level: Understand (2)\n",
+ "The student shows an understanding by asking if there is any additional information needed to achieve the learning objectives.\n",
+ "\n",
+ "4. I think I understand the material. Please generate a five question, multiple-choice quiz for me on the material we have just discussed...\n",
+ "Level: Create (6)\n",
+ "The student demonstrates their ability to create a quiz based on their understanding of the material.\n",
+ "\n",
+ "5. Question 1: Which of the following best describes the order of removal in a stack?...\n",
+ "Level: Evaluate (5)\n",
+ "The student evaluates their knowledge by answering the question correctly and providing an explanation of the Last-In, First-Out (LIFO) principle.\n",
+ "\n",
+ "6. Question 2: Which data structure is commonly used to implement function call stacks and undo/redo functionality?...\n",
+ "Level: Evaluate (5)\n",
+ "The student evaluates their knowledge by answering the question correctly and providing an explanation of how stacks are commonly used.\n",
+ "\n",
+ "7. Question 3: Which of the following best describes the order of removal in a queue?...\n",
+ "Level: Understand (2)\n",
+ "The student demonstrates an understanding of queues by answering the question incorrectly and being corrected.\n",
+ "\n",
+ "8. Question 4: Which data structure allows access to both the front and back elements?...\n",
+ "Level: Understand (2)\n",
+ "The student demonstrates an understanding by answering the question correctly.\n",
+ "\n",
+ "9. Question 5: Which data structure is commonly used in job scheduling and print spooling?...\n",
+ "Level: Evaluate (5)\n",
+ "The student evaluates their knowledge by answering the question incorrectly and being corrected.\n",
+ "\n",
+ "10. I am ready for a final quiz on this chapter...\n",
+ "Level: Create (6)\n",
+ "The student demonstrates their ability to create a quiz based on the material.\n",
+ "\n",
+ "Overall, the student shows a good level of engagement and knowledge, with a range of levels from understanding (2) to evaluating (5), and even creating (6) their own quiz.\n",
+ "\n",
+ "\n",
+ "Result for file demo_json/demo_json.json: \n",
+ "Based on the student's responses, their overall level of engagement and knowledge can be evaluated using Bloom's Taxonomy as follows:\n",
+ "\n",
+ "Question 1: The student correctly identifies the statement that best describes capital expenditures. This demonstrates an understanding of the concept. Level: 2 (Understand)\n",
+ "\n",
+ "Question 2: The student initially selects the incorrect answer but then corrects their response. This indicates some confusion or lack of knowledge initially, but they are able to correct themselves. Level: 2 (Understand)\n",
+ "\n",
+ "Question 3: The student correctly identifies the purpose of capitalizing expenses. This shows an understanding of the concept. Level: 2 (Understand)\n",
+ "\n",
+ "Question 4: The student correctly identifies the financial statement that provides information about capital expenditures. This demonstrates an understanding of the concept. Level: 2 (Understand)\n",
+ "\n",
+ "Question 5: The student correctly identifies the purpose of the matching principle in relation to capitalizing expenses. This shows an understanding of the concept. Level: 2 (Understand)\n",
+ "\n",
+ "Overall, the student's responses indicate an understanding of the material and an ability to apply the concepts discussed. Their level of engagement and knowledge can be evaluated as a 2 (Understand) on Bloom's Taxonomy.\n"
+ ]
+ }
+ ],
+ "source": [
+ "output_setup = None\n",
+ "grading_instructions = \"\"\"\\nEvaluate the student's overall level or engagement and knowledge, based on bloom's taxonomy using their responses.\n",
+ "Bloom's taxonomy is rated on a 1-6 point system, with 1 being remember (recall facts and basic concepts), 2 being understand (explain ideas or concepts),\n",
+ "3 being apply (use information in new situations), 4 being analyze (draw connections among ideas), 5 being evaluate (justify a stand or decision),\n",
+ "and 6 being create (produce new or original work). Assign the interaction a score from 1-6, where 1 = remember, 2 = understand, 3 = apply, 4 = analyze,\n",
+ "5 = evaluate, and 6 = create.\"\"\"\n",
+ "\n",
+ "# Assuming `file_paths` is a list of file paths.\n",
+ "processed_submissions = process_files(all_json_dfs, output_setup, grading_instructions, use_defaults = False, print_results=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "FI5-vnUvXM03"
+ },
+ "source": [
+ "# Returning Results\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "LgoGt82CYiG-"
+ },
+ "source": [
+ "**Extract Student Responses ONLY from CHAT JSON**\n",
+ "\n",
+ "Below are relevant user components of dataframes, including the conversion from the original json, the interaction labeled dataframe, and the output dataframe. Check to make sure they make sense."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 1000
+ },
+ "id": "HVq9i_mXYiG-",
+ "outputId": "032da076-f228-45e1-b48d-f13883ec6317"
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ " \n",
+ " "
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ " \n",
+ "
\n",
+ "
\n",
+ "
timestamp
\n",
+ "
author
\n",
+ "
message
\n",
+ "
filename
\n",
+ "
question_label
\n",
+ "
\n",
+ " \n",
+ " \n",
+ "
\n",
+ "
0
\n",
+ "
2023-06-08T15:30:00
\n",
+ "
user
\n",
+ "
What are the differences between stacks and queues?
\n",
+ "
demo_json/cs_demo.json
\n",
+ "
self study
\n",
+ "
\n",
+ "
\n",
+ "
2
\n",
+ "
2023-06-08T15:32:15
\n",
+ "
user
\n",
+ "
Can you list examples of when you would want to use stacks over queues and vice versa?
\n",
+ "
demo_json/cs_demo.json
\n",
+ "
self study
\n",
+ "
\n",
+ "
\n",
+ "
4
\n",
+ "
2023-06-08T15:35:10
\n",
+ "
user
\n",
+ "
Given the following two learning objectives: Objective 1: Understand the differences stacks and queues... Is there anything else I need to know?
\n",
+ "
demo_json/cs_demo.json
\n",
+ "
self study
\n",
+ "
\n",
+ "
\n",
+ "
6
\n",
+ "
2023-06-08T15:38:25
\n",
+ "
user
\n",
+ "
I think I understand the material. Please generate a five question, multiple-choice quiz for me on the material we have just discussed...
\n",
+ "
demo_json/cs_demo.json
\n",
+ "
self study quiz
\n",
+ "
\n",
+ "
\n",
+ "
9
\n",
+ "
2023-06-08T15:40:47
\n",
+ "
user
\n",
+ "
A
\n",
+ "
demo_json/cs_demo.json
\n",
+ "
self study quiz
\n",
+ "
\n",
+ "
\n",
+ "
12
\n",
+ "
2023-06-08T15:42:22
\n",
+ "
user
\n",
+ "
A
\n",
+ "
demo_json/cs_demo.json
\n",
+ "
self study quiz
\n",
+ "
\n",
+ "
\n",
+ "
15
\n",
+ "
2023-06-08T15:43:57
\n",
+ "
user
\n",
+ "
B
\n",
+ "
demo_json/cs_demo.json
\n",
+ "
self study quiz
\n",
+ "
\n",
+ "
\n",
+ "
18
\n",
+ "
2023-06-08T15:45:32
\n",
+ "
user
\n",
+ "
C
\n",
+ "
demo_json/cs_demo.json
\n",
+ "
self study quiz
\n",
+ "
\n",
+ "
\n",
+ "
21
\n",
+ "
2023-06-08T15:47:07
\n",
+ "
user
\n",
+ "
A
\n",
+ "
demo_json/cs_demo.json
\n",
+ "
self study quiz
\n",
+ "
\n",
+ "
\n",
+ "
23
\n",
+ "
2023-06-08T15:49:07
\n",
+ "
user
\n",
+ "
I am ready for a final quiz on this chapter. Do not repeat any questions that you have given me already. Generate a five question, multiple-choice quiz for me on the material. As I answer each question, tell me whether I got it correct or not, and if I was incorrect, explain why. Please ask me questions one at a time and wait for my response (and your assessment) before asking me the next question.
How do you capitalize expenses using typical information in firm financial disclosures?
\n",
+ "
demo_json/demo_json.json
\n",
+ "
self study
\n",
+ "
\n",
+ "
\n",
+ "
3
\n",
+ "
2023-06-07T08:06:00Z
\n",
+ "
user
\n",
+ "
Yes
\n",
+ "
demo_json/demo_json.json
\n",
+ "
self study
\n",
+ "
\n",
+ "
\n",
+ "
5
\n",
+ "
2023-06-07T08:12:00Z
\n",
+ "
user
\n",
+ "
Given the following two learning objectives: Objective 1: Understand how to capitalize expenses so they can be incorporated into an estimate of corporate earnings. Objective 2: Understand what kinds of expenses should be capitalized and why. Is there anything else I need to know?
\n",
+ "
demo_json/demo_json.json
\n",
+ "
self study
\n",
+ "
\n",
+ "
\n",
+ "
7
\n",
+ "
2023-06-07T08:15:00Z
\n",
+ "
user
\n",
+ "
I think I understand the material. Please generate a five-question, multiple-choice quiz for me on the material we have just discussed. As I answer each question, tell me whether I got it correct or not, and if I was incorrect, explain why. Please ask me questions one at a time and wait for my response (and your assessment) before asking me the next question.
\n",
+ "
demo_json/demo_json.json
\n",
+ "
self study quiz
\n",
+ "
\n",
+ "
\n",
+ "
10
\n",
+ "
2023-06-07T08:16:30Z
\n",
+ "
user
\n",
+ "
C
\n",
+ "
demo_json/demo_json.json
\n",
+ "
self study quiz
\n",
+ "
\n",
+ "
\n",
+ "
13
\n",
+ "
2023-06-07T08:18:00Z
\n",
+ "
user
\n",
+ "
A
\n",
+ "
demo_json/demo_json.json
\n",
+ "
self study quiz
\n",
+ "
\n",
+ "
\n",
+ "
16
\n",
+ "
2023-06-07T08:19:30Z
\n",
+ "
user
\n",
+ "
D
\n",
+ "
demo_json/demo_json.json
\n",
+ "
self study quiz
\n",
+ "
\n",
+ "
\n",
+ "
19
\n",
+ "
2023-06-07T08:21:00Z
\n",
+ "
user
\n",
+ "
C
\n",
+ "
demo_json/demo_json.json
\n",
+ "
self study quiz
\n",
+ "
\n",
+ "
\n",
+ "
22
\n",
+ "
2023-06-07T08:22:30Z
\n",
+ "
user
\n",
+ "
C
\n",
+ "
demo_json/demo_json.json
\n",
+ "
self study quiz
\n",
+ "
\n",
+ "
\n",
+ "
25
\n",
+ "
2023-06-07T08:24:00Z
\n",
+ "
user
\n",
+ "
B
\n",
+ "
demo_json/demo_json.json
\n",
+ "
self study quiz
\n",
+ "
\n",
+ " \n",
+ "
"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "# Create a DataFrame with user responses only and print\n",
+ "json_df_user = [create_user_dataframe(json_df) for json_df in all_json_dfs]\n",
+ "res = [pretty_print(df) for df in json_df_user]\n",
+ "\n",
+ "# This can be saved as well - shown for an individual file\n",
+ "save_as_csv(json_df_user[0], \"user_responses.csv\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "1WIGxKmDYiG-"
+ },
+ "source": [
+ "**Saving/Downloading AI-Assisted Student Evaluation from Chat JSON**\n",
+ "\n",
+ "Execute the following cell to have all of your students' data returned in a set of CSV files, removing the messages of the assistant."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 23,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 432
+ },
+ "id": "QnWNEeqjYiG-",
+ "outputId": "8e1efbca-3f6b-4cff-a649-d78ab06e51c9"
+ },
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": [
+ ""
+ ],
+ "text/html": [
+ "\n",
+ " \n",
+ " "
+ ]
+ },
+ "metadata": {}
+ },
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "Data from file: demo_json (1)\n"
+ ]
+ },
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": [
+ " Here is the table with the question number, question content, answer, whether or not the student answered correctly on the first try, and the number of attempts it took to get the right answer:\n",
+ "0 | Question Number | Question Content | Answer | Correct on First Try | Number of Attempts | \n",
+ "1 |-----------------|-----------------|--------|----------------------|--------------------| \n",
+ "2 | 1 | | C | Yes | 1 | \n",
+ "3 | 2 | | A | No | 1 | \n",
+ "4 | 3 | | D | Yes | 2 | \n",
+ "5 | 4 | | C | Yes | 1 | \n",
+ "6 | 5 | | B | Yes | 1 | \n",
+ "7 To calculate the quiz grade, we will only count the questions where the student answered correctly on the first try. In this case, the student answered questions 1, 3, 4, and 5 correctly on the first try. Therefore, the quiz grade would be 4 out of 5, or 80%."
+ ],
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
\n",
+ "
Here is the table with the question number, question content, answer, whether or not the student answered correctly on the first try, and the number of attempts it took to get the right answer:
\n",
+ "
\n",
+ " \n",
+ " \n",
+ "
\n",
+ "
0
\n",
+ "
| Question Number | Question Content | Answer | Correct on First Try | Number of Attempts |
To calculate the quiz grade, we will only count the questions where the student answered correctly on the first try. In this case, the student answered questions 1, 3, 4, and 5 correctly on the first try. Therefore, the quiz grade would be 4 out of 5, or 80%.