diff --git a/week4/community-contributions/day5-homework.ipynb b/week4/community-contributions/day5-homework.ipynb new file mode 100644 index 0000000..3d6bded --- /dev/null +++ b/week4/community-contributions/day5-homework.ipynb @@ -0,0 +1,1276 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "6d67dba5-38ec-459a-9132-4a56c6a814cd", + "metadata": {}, + "outputs": [], + "source": [ + "Comment and Unit Test Generater \n", + "\n", + "The requirement: \n", + "* use an LLM to generate docstring and comments for Python code\n", + "* use an LLM to generate unit test\n", + "\n", + "This is my week 4 day 5 project." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "ea1841f6-4afc-4d29-ace8-5ca5a3915c8c", + "metadata": {}, + "outputs": [], + "source": [ + "# imports\n", + "\n", + "import os\n", + "import io\n", + "import sys\n", + "import json\n", + "import requests\n", + "from dotenv import load_dotenv\n", + "from openai import OpenAI\n", + "import google.generativeai\n", + "import anthropic\n", + "from IPython.display import Markdown, display, update_display\n", + "import gradio as gr\n", + "import subprocess\n", + "from huggingface_hub import login, InferenceClient\n", + "from transformers import AutoTokenizer" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "11957fd3-6c61-4496-aef1-8223cb9ec4ce", + "metadata": {}, + "outputs": [], + "source": [ + "# environment\n", + "\n", + "load_dotenv()\n", + "os.environ['OPENAI_API_KEY'] = os.getenv('OPENAI_API_KEY', 'your-key-if-not-using-env')\n", + "os.environ['ANTHROPIC_API_KEY'] = os.getenv('ANTHROPIC_API_KEY', 'your-key-if-not-using-env')\n", + "os.environ['HF_TOKEN'] = os.getenv('HF_TOKEN', 'your-key-if-not-using-env')" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "ee7b08fd-e678-4234-895e-4e3a925e60f0", + "metadata": {}, + "outputs": [], + "source": [ + "# initialize\n", + "\n", + "openai = OpenAI()\n", + "claude = anthropic.Anthropic()\n", + "OPENAI_MODEL = \"gpt-4o\"\n", + "CLAUDE_MODEL = \"claude-3-5-sonnet-20240620\"" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "c8023255-9c98-4fbc-92e4-c553bed3b605", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Note: Environment variable`HF_TOKEN` is set and is the current active token independently from the token you've just configured.\n" + ] + } + ], + "source": [ + "hf_token = os.environ['HF_TOKEN']\n", + "login(hf_token, add_to_git_credential=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "f8ce3f5e-74c4-4d35-bfbc-91c5be85e094", + "metadata": {}, + "outputs": [], + "source": [ + "code_qwen = \"Qwen/CodeQwen1.5-7B-Chat\"\n", + "CODE_QWEN_URL = \"https://g39mbjooiiwkbgyz.us-east-1.aws.endpoints.huggingface.cloud\"" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "id": "1bbc66b6-52ae-465e-a368-edc8f097fe9d", + "metadata": {}, + "outputs": [], + "source": [ + "def system_prompt_for_comment():\n", + " system=\"\"\"\n", + " You are a Python documentation expert. When writing documentation:\n", + " - Follow PEP 257 and Google docstring style guidelines\n", + " - Write clear, concise explanations\n", + " - Include practical examples\n", + " - Highlight edge cases and limitations\n", + " - Use type hints in docstrings\n", + " - Add inline comments only for complex logic\n", + " - Never skip documenting parameters or return values\n", + " - Validate that all documentation is accurate and complete\n", + " \"\"\"\n", + " return system" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "id": "b089f87b-53ae-40ad-8d06-b9924bb998a0", + "metadata": {}, + "outputs": [], + "source": [ + "def system_prompt_for_unit_test():\n", + " system=\"\"\"\n", + " You are an expert Python testing engineer who specializes in creating comprehensive unit tests. Follow these principles:\n", + " - Use pytest as the testing framework\n", + " - Follow the Arrange-Act-Assert pattern\n", + " - Test both valid and invalid inputs\n", + " - Include edge cases and boundary conditions\n", + " - Write descriptive test names that explain the scenario being tested\n", + " - Create independent tests that don't rely on each other\n", + " - Use appropriate fixtures and parametrize when needed\n", + " - Add clear comments explaining complex test logic\n", + " - Cover error cases and exceptions\n", + " - Achieve high code coverage while maintaining meaningful tests\n", + " \"\"\"\n", + " return system" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "id": "22193622-f3a0-4894-a6c4-eb6d88097861", + "metadata": {}, + "outputs": [], + "source": [ + "def user_prompt_for_comment(code):\n", + " user = f\"\"\"\n", + " Please document this Python code with:\n", + " \n", + " 1. A docstring containing:\n", + " - A clear description of purpose and functionality\n", + " - All parameters with types and descriptions\n", + " - Return values with types\n", + " - Exceptions that may be raised\n", + " - At least one usage example\n", + " - Any important notes or limitations\n", + " \n", + " 2. Strategic inline comments for:\n", + " - Complex algorithms or business logic\n", + " - Non-obvious implementation choices\n", + " - Performance considerations\n", + " - Edge cases\n", + " \n", + " Here's the code to document:\n", + " \\n{code}\n", + " \"\"\"\n", + " return user;" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "id": "81e61752-ec2f-44c1-86a2-ff3234a0358c", + "metadata": {}, + "outputs": [], + "source": [ + "def user_prompt_for_unit_test(code):\n", + " user = f\"\"\"\n", + " Please generate unit tests for the following Python code. Include:\n", + " \n", + " 1. Test cases for:\n", + " - Normal/expected inputs\n", + " - Edge cases and boundary values\n", + " - Invalid inputs and error conditions\n", + " - Different combinations of parameters\n", + " - All public methods and functions\n", + " \n", + " 2. For each test:\n", + " - Clear test function names describing the scenario\n", + " - Setup code (fixtures if needed)\n", + " - Test data preparation\n", + " - Expected outcomes\n", + " - Assertions checking results\n", + " - Comments explaining complex test logic\n", + " \n", + " 3. Include any necessary:\n", + " - Imports\n", + " - Fixtures\n", + " - Mock objects\n", + " - Helper functions\n", + " - Test data generators\n", + " \n", + " Here's the code to test:\n", + " \\n{code}\n", + " \"\"\"\n", + " return user" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "f31ceed3-0eb2-4962-ab86-2d0302185560", + "metadata": {}, + "outputs": [], + "source": [ + "pi = \"\"\"\n", + "import time\n", + "\n", + "def calculate(iterations, param1, param2):\n", + " result = 1.0\n", + " for i in range(1, iterations+1):\n", + " j = i * param1 - param2\n", + " result -= (1/j)\n", + " j = i * param1 + param2\n", + " result += (1/j)\n", + " return result\n", + "\n", + "start_time = time.time()\n", + "result = calculate(100_000_000, 4, 1) * 4\n", + "end_time = time.time()\n", + "\n", + "print(f\"Result: {result:.12f}\")\n", + "print(f\"Execution Time: {(end_time - start_time):.6f} seconds\")\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "192c30f5-4be6-49b7-a054-11bfcffa91e0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Result: 3.141592658589\n", + "Execution Time: 58.228012 seconds\n" + ] + } + ], + "source": [ + "exec(pi)" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "id": "d4e920dc-4094-42d8-9255-18f2919df2d4", + "metadata": {}, + "outputs": [], + "source": [ + "def messages_for_comment(python):\n", + " return [\n", + " {\"role\": \"system\", \"content\": system_prompt_for_comment()},\n", + " {\"role\": \"user\", \"content\": user_prompt_for_comment(python)}\n", + " ]" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "id": "77500cae-bf84-405c-8b03-2f984108951b", + "metadata": {}, + "outputs": [], + "source": [ + "def messages_for_unit_test(python):\n", + " return [\n", + " {\"role\": \"system\", \"content\": system_prompt_for_unit_test()},\n", + " {\"role\": \"user\", \"content\": user_prompt_for_unit_test(python)}\n", + " ]" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "id": "5ec58bf1-4a44-4c21-a71a-2cac359884e5", + "metadata": {}, + "outputs": [], + "source": [ + "def stream_comment_gpt(code):\n", + " stream = openai.chat.completions.create(model=OPENAI_MODEL, messages=messages_for_comment(code), stream=True)\n", + " reply = \"\"\n", + " for chunk in stream:\n", + " fragment = chunk.choices[0].delta.content or \"\"\n", + " reply += fragment\n", + " #print(fragment, end='', flush=True)\n", + " yield reply.replace('```','') \n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "47c615e2-4eb6-4ce1-ad09-7f2e6dbc3934", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "```python\n", + "import time\n", + "\n", + "def calculate(iterations: int, param1: float, param2: float) -> float:\n", + " \"\"\"\n", + " Performs a series of mathematical operations in a loop to calculate a result.\n", + "\n", + " This function iteratively modifies a result variable through a series of arithmetic\n", + " operations. Essentially, it calculates the sum of alternating series adjustments,\n", + " simulating a specific numerical approximation process.\n", + "\n", + " Args:\n", + " iterations (int): The number of iterations to perform. Must be a positive integer.\n", + " param1 (float): The factor applied for multiplication inside the iteration.\n", + " param2 (float): The factor subtracted and added inside the iteration for denominator adjustment.\n", + "\n", + " Returns:\n", + " float: The calculated result after completing all iterations.\n", + "\n", + " Raises:\n", + " ZeroDivisionError: If any calculated denominator becomes zero during execution,\n", + " which may happen if `i * param1 - param2` or `i * param1 + param2` evaluates to zero.\n", + "\n", + " Usage Example:\n", + " result = calculate(100_000_000, 4, 1)\n", + " print(f\"Calculated Result: {result * 4}\")\n", + "\n", + " Notes:\n", + " - The function can be computationally intensive depending on the number of iterations.\n", + " - Ensure that `param1` and `param2` are chosen to avoid division by zero.\n", + " - Floating-point precision issues might arise due to large iterations count.\n", + " \"\"\"\n", + " \n", + " result = 1.0\n", + " for i in range(1, iterations + 1):\n", + " # Calculate modified denominator by subtracting param2\n", + " j = i * param1 - param2\n", + " \n", + " # Subtract reciprocal from the result\n", + " # Potential ZeroDivisionError if (i * param1 - param2) == 0\n", + " result -= (1 / j)\n", + " \n", + " # Calculate modified denominator by adding param2\n", + " j = i * param1 + param2\n", + " \n", + " # Add reciprocal to the result\n", + " # Potential ZeroDivisionError if (i * param1 + param2) == 0\n", + " result += (1 / j)\n", + " \n", + " return result\n", + "\n", + "\n", + "start_time = time.time()\n", + "result = calculate(100_000_000, 4, 1) * 4 # Scaling final result by 4 for specific use case\n", + "end_time = time.time()\n", + "\n", + "# Output result with high precision and execution time for measurement\n", + "print(f\"Result: {result:.12f}\")\n", + "print(f\"Execution Time: {(end_time - start_time):.6f} seconds\")\n", + "```\n", + "\n", + "### Explanation of Changes:\n", + "- **Docstring**: The docstring provides a comprehensive explanation of the function's purpose and the calculations it performs, specifying parameter types and behavior.\n", + "- **Exceptions**: A note about `ZeroDivisionError` is included, as the calculation might lead to division by zero with certain inputs.\n", + "- **Usage Example**: Demonstrates how to call the function with a specific configuration.\n", + "- **Notes**: Provides guidance on potential performance concerns and precision limitations.\n", + "- **Inline Comments**: Added to clarify key lines where logical computations occur and where division by zero might be a risk." + ] + } + ], + "source": [ + "stream_comment_gpt(pi)" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "id": "0b990875-31fd-40e5-bc8c-f6099d362249", + "metadata": {}, + "outputs": [], + "source": [ + "def stream_unit_test_gpt(code):\n", + " stream = openai.chat.completions.create(model=OPENAI_MODEL, messages=messages_for_unit_test(code), stream=True)\n", + " reply = \"\"\n", + " for chunk in stream:\n", + " fragment = chunk.choices[0].delta.content or \"\"\n", + " reply += fragment\n", + " #print(fragment, end='', flush=True)\n", + " yield reply.replace('```','')" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "id": "3dc90578-4f5e-47f1-b30f-c21b5795e82f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 73, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "stream_unit_test_gpt(pi)" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "id": "17380c0f-b851-472b-a234-d86f5c219e50", + "metadata": {}, + "outputs": [], + "source": [ + "def stream_comment_claude(code):\n", + " result = claude.messages.stream(\n", + " model=CLAUDE_MODEL,\n", + " max_tokens=2000,\n", + " system=system_prompt_for_comment(),\n", + " messages=[{\"role\": \"user\", \"content\": user_prompt_for_comment(code)}],\n", + " )\n", + " reply = \"\"\n", + " with result as stream:\n", + " for text in stream.text_stream:\n", + " reply += text\n", + " #print(text, end=\"\", flush=True)\n", + " yield reply.replace('```','')" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "id": "0a2d016d-76a2-4752-bd4d-6f93ddec46be", + "metadata": {}, + "outputs": [], + "source": [ + "def stream_unit_test_claude(code):\n", + " result = claude.messages.stream(\n", + " model=CLAUDE_MODEL,\n", + " max_tokens=2000,\n", + " system=system_prompt_for_unit_test(),\n", + " messages=[{\"role\": \"user\", \"content\": user_prompt_for_unit_test(code)}],\n", + " )\n", + " reply = \"\"\n", + " with result as stream:\n", + " for text in stream.text_stream:\n", + " reply += text\n", + " #print(text, end=\"\", flush=True)\n", + " yield reply.replace('```','')" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "ee43428e-b577-4e95-944d-399f2f3b89ff", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Here's the documented version of your Python code:\n", + "\n", + "```python\n", + "import time\n", + "\n", + " float) -> float:rations: int, param1: float, param2:\n", + " \"\"\"\n", + "Calculates a series sum based on the given parameters.\n", + "\n", + " This function computes a series sum using the formula:\n", + "i*param1 + param2) - 1/(i*param1 - param2)) for i from 1 to iterations.\n", + "\n", + " Args:\n", + " iterations to perform. Must be positive.\n", + "float): The first parameter used in the calculation.\n", + "(float): The second parameter used in the calculation.\n", + "\n", + " Returns:\n", + ". float: The result of the series sum calculation\n", + "\n", + " Raises:\n", + ". ValueError: If iterations is not positive\n", + "is 0 or if param2 is equal to param1.\n", + "\n", + " Example:\n", + " = calculate(1000, 4, 1)\n", + ">>> print(f\"{result:.6f}\")\n", + ".392699 0\n", + "\n", + " Note:\n", + " The function may be computationally expensive for large numbers of iterations.\n", + ", floating-point precision limitations may affect accuracy.\n", + " \"\"\"\n", + " if iterations <= 0:\n", + " must be a positive integer\")rations\n", + "\n", + " result = 1.0\n", + " for i in range(1, iterations + 1):\n", + " the seriesalculate the denominators for both terms in\n", + "1 - param2 = i * param\n", + " param1 + param2\n", + "\n", + "d division by zero\n", + " 0 or j2 == 0:==\n", + " calculation\")ise ZeroDivisionError(\"Division by zero in\n", + "\n", + "d add the second terme first term an\n", + " result -= (1 / j1)\n", + " result += (1 / j2)\n", + "\n", + " return result\n", + "\n", + "# Measure execution time\n", + "()art_time = time.time\n", + "\n", + "# Perform calculation with 100 million iterations\n", + " The result is multiplied by 4 as per the original code\n", + "000, 4, 1) * 4late(100_000_\n", + "\n", + "d_time = time.time()\n", + "\n", + " with high precision for the calculated value\n", + "Result: {result:.12f}\")\n", + "(f\"Execution Time: {(end_time - start_time):.6f} seconds\")\n", + "```\n", + "\n", + " this documented version:\n", + "\n", + " been added to the `calculate` function, following Google style guidelines and including all the requested elements.\n", + "\n", + " hints have been added to the function signature for better clarity and to support static type checking.\n", + "\n", + "d to explain the key steps in the calculation process.\n", + "\n", + " check for positive iterations has been added to prevent invalid input.\n", + "\n", + " been added to handle potential errors.\n", + "\n", + " Comments have been added to the main script to explain the purpose of each step.\n", + "\n", + " documentation provides a clear understanding of the function's purpose, its parameters, return value, potential exceptions, and includes an example of usage. It also notes potential limitations regarding computational cost and floating-point precision for very large numbers of iterations." + ] + } + ], + "source": [ + "stream_comment_claude(pi)" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "id": "0565e33b-9f14-48b7-ae8d-d22dc03b93c9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Here's a comprehensive set of unit tests for the given Python code using pytest:\n", + "\n", + "```python\n", + "import pytest\n", + "import time\n", + " import isclose\n", + "from unittest.mock import patch\n", + "\n", + "# Import the function to be tested\n", + "# Assuming the code is in a file named your_module.py\n", + "\n", + "# Test data generator\n", + "_data():rate_test\n", + " return [\n", + ", 2, 1, 0.6931471805),\n", + " 3, 2, 0.6931471806),\n", + ", 3, 0.6931471806),\n", + ", 1, 0.6931471806),\n", + " ]\n", + "\n", + " datature for common test\n", + "@pytest.fixture\n", + "def common_data():\n", + "return {\n", + " 'iterations': 100,\n", + " 'param1': 4,\n", + " 'param2': 1\n", + " }\n", + "\n", + "# Normal case tests\n", + "rize(\"iterations, param1, param2, expected\", generate_test_data())\n", + "cases(iterations, param1, param2, expected):\n", + "1, param2) = calculate(iterations, param\n", + "(result, expected, rel_tol=1e-9), f\"Expected {expected}, but got {result}\"\n", + "\n", + " cases and boundary values\n", + "_cases():calculate_edge\n", + "d inputsst with minimum vali\n", + " 0) == 2.0 calculate(1, 1,\n", + " \n", + " # Test with very large iterations\n", + "_result = calculate(10**8, 4, 1)\n", + ", 0.6931471806, rel_tol=1e-9)lt\n", + "\n", + "# Invalid inputs and error conditions\n", + "def test_calculate_invalid_inputs():\n", + " with pytest.raises(ValueError):\n", + "0, 4, 1) # iterations should be positive\n", + " \n", + "(ZeroDivisionError):es\n", + "10, 1, 1) # This will cause division by zero\n", + "\n", + "TypeError):test.raises(\n", + "1) # iterations should be an integer\n", + "\n", + "# Test with different combinations of parameters\n", + "rize(\"iterations, param1, param2\", [\n", + "), (100, 2, 2\n", + " (1000, 3, 3),\n", + "(10000, 5, 5),\n", + " (100000, 10, 10)\n", + "])\n", + " param1, param2):e_parameter_combinations(iterations,\n", + " calculate(iterations, param1, param2)\n", + " assert isinstance(result, float)\n", + " assert result > 0\n", + "\n", + " execution time\n", + "common_data):ulate_execution_time(\n", + " time.time()me =\n", + " calculate(**common_data)\n", + " end_time = time.time()\n", + " execution_time = end_time - start_time\n", + " f\"Execution took {execution_time} seconds, which is too long\"\n", + "\n", + " result precision\n", + "data):st_calculate_precision(common_\n", + "data)esult = calculate(**common_\n", + "split('.')[1]) >= 10, \"Result should have at least 10 decimal places\"\n", + "\n", + "# Test with mocked time function\n", + ".time')'time\n", + "(mock_time, common_data):ocked_time\n", + ", 0.5] # Simulate 0.5 seconds execution time\n", + "_time = time.time()\n", + " = calculate(**common_data)\n", + "d_time = time.time()\n", + " end_time - start_time == 0.5\n", + "\n", + "# Helper function to test monotonicity\n", + "_monotonic(lst):\n", + " <= lst[i+1] for i in range(len(lst)-1)) or all(lst[i] >= lst[i+1] for i in range(len(lst)-1))\n", + "\n", + " increasing iterationscity with\n", + "def test_calculate_monotonicity():\n", + " 1) for i in range(1, 6)]10**i, 4,\n", + "), \"Results should be monotonic with increasing iterations\"\n", + "\n", + " Test with very small and very large parameters\n", + ", param1, param2\", [rize(\"iterations\n", + "(100, 1e-5, 1e-5),\n", + ", 1e5)00, 1e5\n", + "])\n", + "_parameters(iterations, param1, param2):\n", + "1, param2) = calculate(iterations, param\n", + "result == float('inf') or result == float('-inf')), \"Result should not be infinity\"\n", + "assert not isclose(result, 0, abs_tol=1e-10), \"Result should not be too close to zero\"\n", + "\n", + "```\n", + "\n", + " for the `calculate` function:range of scenarios\n", + "\n", + " with different inputs and expected outputs.\n", + " and boundary values, including minimum valid inputs and very large iterations.\n", + " Invalid inputs and error conditions, testing for expected exceptions.\n", + " Different combinations of parameters to ensure the function works correctly for various inputs.\n", + " to ensure the function performs within acceptable time limits.\n", + " Precision test to verify the result has sufficient decimal places.\n", + " A test with mocked time function to simulate and verify execution time measurement.\n", + " if results are consistent with increasing iterations.\n", + " with extreme parameters (very small and very large) to ensure numerical stability.\n", + "\n", + "rization, fixtures, and markers. It also includes necessary imports, helper functions, and a test data generator.\n", + "\n", + "d `test_your_module.py` in the same directory as your original code file (`your_module.py`). Then run `pytest test_your_module.py` from the command line.\n", + "\n", + " pytest (`pip install pytest`) before running the tests." + ] + } + ], + "source": [ + "stream_unit_test_claude(pi)" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "f13b3a5b-366d-4b28-adda-977a313e6b4d", + "metadata": {}, + "outputs": [], + "source": [ + "def stream_comment_model(model, model_url, code):\n", + " tokenizer = AutoTokenizer.from_pretrained(model)\n", + " messages = messages_for_comment(code)\n", + " text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)\n", + " client = InferenceClient(model_url, token=hf_token)\n", + " stream = client.text_generation(text, stream=True, details=True, max_new_tokens=3000)\n", + " result = \"\"\n", + " for r in stream:\n", + " #print(r.token.text, end = \"\")\n", + " result += r.token.text\n", + " yield result \n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "id": "e2efdb92-fc7a-4952-ab46-ae942cb996bf", + "metadata": {}, + "outputs": [], + "source": [ + "def stream_unit_test_model(model, model_url, code):\n", + " tokenizer = AutoTokenizer.from_pretrained(model)\n", + " messages = messages_for_unit_test(code)\n", + " text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)\n", + " client = InferenceClient(model_url, token=hf_token)\n", + " stream = client.text_generation(text, stream=True, details=True, max_new_tokens=3000)\n", + " result = \"\"\n", + " for r in stream:\n", + " #print(r.token.text, end = \"\")\n", + " result += r.token.text\n", + " yield result \n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "0a756193-fcba-43da-a981-203c10d36488", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "stream_comment_model(code_qwen, CODE_QWEN_URL, pi)" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "id": "12ddcbf4-6286-47a8-847b-5be78e7aa995", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Here are the unit tests for the given Python code:\n", + "\n", + "```python\n", + "import pytest\n", + "import time\n", + " unittest.mock import patch\n", + "\n", + "def calculate(iterations, param1, param2):\n", + " result = 1.0\n", + " for i in range(1, iterations+1):\n", + " i * param1 - param2\n", + "result -= (1/j)\n", + " j = i * param1 + param2\n", + "result += (1/j)\n", + " return result\n", + "\n", + "@pytest.fixture\n", + " mock_time():\n", + "('time.time') as mock_time:\n", + "yield mock_time\n", + "\n", + "_calculate_normal_inputs(mock_time):\n", + "mock_time.return_value = 0\n", + "result = calculate(100_000_000, 4, 1) * 4\n", + "expected_result = 0.0\n", + " == expected_result\n", + "\n", + "_calculate_edge_cases(mock_time):\n", + " mock_time.return_value = 0\n", + " calculate(0, 4, 1) * 4\n", + " expected_result = 0.0\n", + " result == expected_result\n", + "\n", + " = calculate(100_000_000, 0, 1) * 4\n", + "expected_result = 0.0\n", + " result == expected_result\n", + "\n", + " = calculate(100_000_000, 4, 0) * 4\n", + "_result = 0.0\n", + " assert result == expected_result\n", + "\n", + "def test_calculate_invalid_inputs(mock_time):\n", + " mock_time.return_value = 0\n", + ".raises(TypeError):\n", + "calculate(100_000_000, 'a', 1) * 4\n", + "with pytest.raises(TypeError):\n", + "100_000_000, 4, 'b') * 4\n", + ".raises(TypeError):\n", + "calculate('a', 4, 1) * 4\n", + "test.raises(TypeError):\n", + "(100_000_000, 4, 1, 'c') * 4\n", + "\n", + "def test_calculate_different_combinations(mock_time):\n", + " mock_time.return_value = 0\n", + "result = calculate(100_000_000, 4, 1) * 4\n", + " expected_result = 0.0\n", + " result == expected_result\n", + "\n", + " = calculate(100_000_000, 4, -1) * 4\n", + "expected_result = 0.0\n", + " == expected_result\n", + "\n", + " calculate(100_000_000, -4, 1) * 4\n", + "result = 0.0_\n", + "assert result == expected_result\n", + "\n", + "result = calculate(100_000_000, -4, -1) * 4\n", + " expected_result = 0.0\n", + " result == expected_result\n", + "\n", + "def test_calculate_execution_time(mock_time):\n", + "_time.return_value = 0\n", + "_time = mock_time.return_value\n", + "calculate(100_000_000, 4, 1) * 4\n", + "end_time = mock_time.return_value\n", + " expected_execution_time = 0.0\n", + " assert (end_time - start_time) == expected_execution_time\n", + "```\n", + "\n", + " covers all the scenarios mentioned in the problem description. It tests the function with normal inputs, edge cases, invalid inputs, different combinations of parameters, and checks the execution time.<|im_end|>" + ] + } + ], + "source": [ + "stream_unit_test_model(code_qwen, CODE_QWEN_URL, pi)" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "id": "321609ee-b64a-44fc-9090-39f87e1f8e0e", + "metadata": {}, + "outputs": [], + "source": [ + "def comment_code(python, model):\n", + " if model==\"GPT\":\n", + " result = stream_comment_gpt(python)\n", + " elif model==\"Claude\":\n", + " result = stream_comment_claude(python)\n", + " elif model==\"CodeQwen\":\n", + " result = stream_comment_model(code_qwen, CODE_QWEN_URL, python)\n", + " else:\n", + " raise ValueError(\"Unknown model\")\n", + " for stream_so_far in result:\n", + " yield stream_so_far " + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "id": "d4c560c9-922d-4893-941f-42893373b1be", + "metadata": {}, + "outputs": [], + "source": [ + "def get_unit_test(python, model):\n", + " if model==\"GPT\":\n", + " result = stream_unit_test_gpt(python)\n", + " elif model==\"Claude\":\n", + " result = stream_unit_test_claude(python)\n", + " elif model==\"CodeQwen\":\n", + " result = stream_unit_test_model(code_qwen, CODE_QWEN_URL, python)\n", + " else:\n", + " raise ValueError(\"Unknown model\")\n", + " for stream_so_far in result:\n", + " yield stream_so_far " + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "f85bc777-bebe-436b-88cc-b9ecdb6306c0", + "metadata": {}, + "outputs": [], + "source": [ + "css = \"\"\"\n", + ".python {background-color: #306998;}\n", + ".cpp {background-color: #050;}\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "id": "ee27cc91-81e6-42c8-ae3c-c04161229d8c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "* Running on local URL: http://127.0.0.1:7881\n", + "\n", + "To create a public link, set `share=True` in `launch()`.\n" + ] + }, + { + "data": { + "text/html": [ + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [] + }, + "execution_count": 74, + "metadata": {}, + "output_type": "execute_result" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Here are the unit tests for the given Python code:\n", + "\n", + "```python\n", + "import pytest\n", + "import time\n", + " unittest.mock import patch\n", + "\n", + "def calculate(iterations, param1, param2):\n", + " result = 1.0\n", + " for i in range(1, iterations+1):\n", + " i * param1 - param2\n", + " result -= (1/j)\n", + " i * param1 + param2\n", + "result += (1/j)\n", + " return result\n", + "\n", + "@pytest.fixture\n", + " mock_time():\n", + " with patch('time.time') as mock_time:\n", + "ield mock_time\n", + "\n", + "calculate_normal_inputs(mock_time):\n", + "time.return_value = 0\n", + " calculate(100_000_000, 4, 1) * 4\n", + "result = 0.0_\n", + "assert result == expected_result\n", + "\n", + " test_calculate_edge_cases(mock_time):\n", + "time.return_value = 0\n", + " calculate(0, 4, 1) * 4\n", + "_result = 0.0\n", + " assert result == expected_result\n", + "\n", + " result = calculate(100_000_000, 0, 1) * 4\n", + "result = 0.0_\n", + "assert result == expected_result\n", + "\n", + "result = calculate(100_000_000, 4, 0) * 4\n", + " expected_result = 0.0\n", + "assert result == expected_result\n", + "\n", + " test_calculate_invalid_inputs(mock_time):\n", + "_time.return_value = 0\n", + "test.raises(TypeError):\n", + " calculate(100_000_000, 'a', 1) * 4\n", + "with pytest.raises(TypeError):\n", + "ulate(100_000_000, 4, 'b') * 4\n", + " pytest.raises(TypeError):\n", + "ulate('a', 4, 1) * 4\n", + "test.raises(TypeError):\n", + " calculate(100_000_000, 4, 1, 'c') * 4\n", + "\n", + "_calculate_different_combinations(mock_time):\n", + " mock_time.return_value = 0\n", + " result = calculate(100_000_000, 4, 1) * 4\n", + " expected_result = 0.0\n", + " == expected_result\n", + "\n", + " calculate(100_000_000, 4, -1) * 4\n", + "_result = 0.0\n", + " assert result == expected_result\n", + "\n", + " result = calculate(100_000_000, -4, 1) * 4\n", + " expected_result = 0.0\n", + " result == expected_result\n", + "\n", + " calculate(100_000_000, -4, -1) * 4\n", + "_result = 0.0\n", + " assert result == expected_result\n", + "\n", + "def test_calculate_execution_time(mock_time):\n", + "mock_time.return_value = 0\n", + "start_time = mock_time.return_value\n", + " calculate(100_000_000, 4, 1) * 4\n", + " end_time = mock_time.return_value\n", + " expected_execution_time = 0.0\n", + " assert (end_time - start_time) == expected_execution_time\n", + "```\n", + "\n", + " covers all the scenarios mentioned in the problem description. It tests the function with normal inputs, edge cases, invalid inputs, different combinations of parameters, and checks the execution time.<|im_end|>" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Traceback (most recent call last):\n", + " File \"C:\\Users\\ebaba\\.conda\\envs\\llms\\Lib\\site-packages\\gradio\\queueing.py\", line 625, in process_events\n", + " response = await route_utils.call_process_api(\n", + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"C:\\Users\\ebaba\\.conda\\envs\\llms\\Lib\\site-packages\\gradio\\route_utils.py\", line 322, in call_process_api\n", + " output = await app.get_blocks().process_api(\n", + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"C:\\Users\\ebaba\\.conda\\envs\\llms\\Lib\\site-packages\\gradio\\blocks.py\", line 2047, in process_api\n", + " result = await self.call_function(\n", + " ^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"C:\\Users\\ebaba\\.conda\\envs\\llms\\Lib\\site-packages\\gradio\\blocks.py\", line 1606, in call_function\n", + " prediction = await utils.async_iteration(iterator)\n", + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"C:\\Users\\ebaba\\.conda\\envs\\llms\\Lib\\site-packages\\gradio\\utils.py\", line 714, in async_iteration\n", + " return await anext(iterator)\n", + " ^^^^^^^^^^^^^^^^^^^^^\n", + " File \"C:\\Users\\ebaba\\.conda\\envs\\llms\\Lib\\site-packages\\gradio\\utils.py\", line 708, in __anext__\n", + " return await anyio.to_thread.run_sync(\n", + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"C:\\Users\\ebaba\\.conda\\envs\\llms\\Lib\\site-packages\\anyio\\to_thread.py\", line 56, in run_sync\n", + " return await get_async_backend().run_sync_in_worker_thread(\n", + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"C:\\Users\\ebaba\\.conda\\envs\\llms\\Lib\\site-packages\\anyio\\_backends\\_asyncio.py\", line 2505, in run_sync_in_worker_thread\n", + " return await future\n", + " ^^^^^^^^^^^^\n", + " File \"C:\\Users\\ebaba\\.conda\\envs\\llms\\Lib\\site-packages\\anyio\\_backends\\_asyncio.py\", line 1005, in run\n", + " result = context.run(func, *args)\n", + " ^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"C:\\Users\\ebaba\\.conda\\envs\\llms\\Lib\\site-packages\\gradio\\utils.py\", line 691, in run_sync_iterator_async\n", + " return next(iterator)\n", + " ^^^^^^^^^^^^^^\n", + " File \"C:\\Users\\ebaba\\.conda\\envs\\llms\\Lib\\site-packages\\gradio\\utils.py\", line 852, in gen_wrapper\n", + " response = next(iterator)\n", + " ^^^^^^^^^^^^^^\n", + " File \"C:\\Users\\ebaba\\AppData\\Local\\Temp\\ipykernel_27660\\2822054561.py\", line 10, in get_unit_test\n", + " for stream_so_far in result:\n", + "TypeError: 'NoneType' object is not iterable\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Here are the unit tests for the given Python code:\n", + "\n", + "```python\n", + "import pytest\n", + "import time\n", + "est.mock import patch\n", + "\n", + "(iterations, param1, param2):\n", + "result = 1.0\n", + "for i in range(1, iterations+1):\n", + "j = i * param1 - param2\n", + " -= (1/j)esult\n", + "j = i * param1 + param2\n", + " += (1/j)esult\n", + "return result\n", + "\n", + "pytest.fixture\n", + "_time():\n", + " with patch('time.time') as mock_time:\n", + "ield mock_time\n", + "\n", + "calculate_normal_inputs(mock_time):\n", + "time.return_value = 0\n", + " calculate(100_000_000, 4, 1) * 4\n", + "_result = 0.0\n", + " assert result == expected_result\n", + "\n", + "def test_calculate_edge_cases(mock_time):\n", + "mock_time.return_value = 0\n", + "result = calculate(0, 4, 1) * 4\n", + " expected_result = 0.0\n", + " result == expected_result\n", + "\n", + " = calculate(100_000_000, 0, 1) * 4\n", + "_result = 0.0\n", + "assert result == expected_result\n", + "\n", + "result = calculate(100_000_000, 4, 0) * 4\n", + " expected_result = 0.0\n", + " result == expected_result\n", + "\n", + "_calculate_invalid_inputs(mock_time):\n", + "time.return_value = 0\n", + " with pytest.raises(TypeError):\n", + "(100_000_000, 'a', 1) * 4\n", + "ises(TypeError):ra\n", + "ulate(100_000_000, 4, 'b') * 4\n", + " pytest.raises(TypeError):\n", + "ulate('a', 4, 1) * 4\n", + " pytest.raises(TypeError):\n", + "ulate(100_000_000, 4, 1, 'c') * 4\n", + "\n", + "calculate_different_combinations(mock_time):\n", + " mock_time.return_value = 0\n", + " result = calculate(100_000_000, 4, 1) * 4\n", + " = 0.0pected_result\n", + " result == expected_result\n", + "\n", + " = calculate(100_000_000, 4, -1) * 4\n", + "expected_result = 0.0\n", + " expected_resultt ==\n", + "\n", + " result = calculate(100_000_000, -4, 1) * 4\n", + "result = 0.0_\n", + " == expected_result\n", + "\n", + " calculate(100_000_000, -4, -1) * 4\n", + " = 0.0pected_result\n", + " result == expected_result\n", + "\n", + "def test_calculate_execution_time(mock_time):\n", + "_time.return_value = 0\n", + "_time = mock_time.return_value\n", + "100_000_000, 4, 1) * 4\n", + " end_time = mock_time.return_value\n", + "_execution_time = 0.0\n", + " (end_time - start_time) == expected_execution_time\n", + "``\n", + "\n", + " suite covers all the scenarios mentioned in the problem description. It tests the function with normal inputs, edge cases, invalid inputs, different combinations of parameters, and checks the execution time.<|im_end|>" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Traceback (most recent call last):\n", + " File \"C:\\Users\\ebaba\\.conda\\envs\\llms\\Lib\\site-packages\\gradio\\queueing.py\", line 625, in process_events\n", + " response = await route_utils.call_process_api(\n", + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"C:\\Users\\ebaba\\.conda\\envs\\llms\\Lib\\site-packages\\gradio\\route_utils.py\", line 322, in call_process_api\n", + " output = await app.get_blocks().process_api(\n", + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"C:\\Users\\ebaba\\.conda\\envs\\llms\\Lib\\site-packages\\gradio\\blocks.py\", line 2047, in process_api\n", + " result = await self.call_function(\n", + " ^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"C:\\Users\\ebaba\\.conda\\envs\\llms\\Lib\\site-packages\\gradio\\blocks.py\", line 1606, in call_function\n", + " prediction = await utils.async_iteration(iterator)\n", + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"C:\\Users\\ebaba\\.conda\\envs\\llms\\Lib\\site-packages\\gradio\\utils.py\", line 714, in async_iteration\n", + " return await anext(iterator)\n", + " ^^^^^^^^^^^^^^^^^^^^^\n", + " File \"C:\\Users\\ebaba\\.conda\\envs\\llms\\Lib\\site-packages\\gradio\\utils.py\", line 708, in __anext__\n", + " return await anyio.to_thread.run_sync(\n", + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"C:\\Users\\ebaba\\.conda\\envs\\llms\\Lib\\site-packages\\anyio\\to_thread.py\", line 56, in run_sync\n", + " return await get_async_backend().run_sync_in_worker_thread(\n", + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"C:\\Users\\ebaba\\.conda\\envs\\llms\\Lib\\site-packages\\anyio\\_backends\\_asyncio.py\", line 2505, in run_sync_in_worker_thread\n", + " return await future\n", + " ^^^^^^^^^^^^\n", + " File \"C:\\Users\\ebaba\\.conda\\envs\\llms\\Lib\\site-packages\\anyio\\_backends\\_asyncio.py\", line 1005, in run\n", + " result = context.run(func, *args)\n", + " ^^^^^^^^^^^^^^^^^^^^^^^^\n", + " File \"C:\\Users\\ebaba\\.conda\\envs\\llms\\Lib\\site-packages\\gradio\\utils.py\", line 691, in run_sync_iterator_async\n", + " return next(iterator)\n", + " ^^^^^^^^^^^^^^\n", + " File \"C:\\Users\\ebaba\\.conda\\envs\\llms\\Lib\\site-packages\\gradio\\utils.py\", line 852, in gen_wrapper\n", + " response = next(iterator)\n", + " ^^^^^^^^^^^^^^\n", + " File \"C:\\Users\\ebaba\\AppData\\Local\\Temp\\ipykernel_27660\\2822054561.py\", line 10, in get_unit_test\n", + " for stream_so_far in result:\n", + "TypeError: 'NoneType' object is not iterable\n" + ] + } + ], + "source": [ + "with gr.Blocks(css=css) as ui:\n", + " gr.Markdown(\"## Convert code from Python to C++\")\n", + " with gr.Row():\n", + " python = gr.Textbox(label=\"Python code:\", value=pi, lines=10)\n", + " result = gr.Textbox(label=\"Result code:\", lines=10)\n", + " with gr.Row():\n", + " model = gr.Dropdown([\"GPT\", \"Claude\",\"CodeQwen\"], label=\"Select model\", value=\"GPT\")\n", + " with gr.Row():\n", + " comment_button = gr.Button(\"Comment code\")\n", + " with gr.Row():\n", + " unit_test_button = gr.Button(\"Unit Test code\")\n", + " \n", + " comment_button.click(comment_code, inputs=[python, model], outputs=[result])\n", + " unit_test_button.click(get_unit_test, inputs=[python, model], outputs=[result])\n", + "ui.launch(inbrowser=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "06e8279c-b488-4807-9bed-9d26be11c057", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}