diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..61acb30 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,18 @@ +name: lint + +on: [push, pull_request] + +jobs: + ruff-black-isort: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: chartboost/ruff-action@v1 + - name: Install dependencies + run: | + python -m pip install . + pip install -r dev-requirements.txt + - name: black check + run: black --check --preview . + - name: isort check + run: isort --profile black --check . diff --git a/dev-requirements.txt b/dev-requirements.txt new file mode 100644 index 0000000..390b096 --- /dev/null +++ b/dev-requirements.txt @@ -0,0 +1,3 @@ +black==23.9.1 +isort==5.12.0 +ruff==0.0.292 diff --git a/pyproject.toml b/pyproject.toml index f9f666f..5acb930 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,3 +26,15 @@ Issues = "https://github.com/AbanteAI/rawdog/issues" [project.scripts] rawdog = "rawdog.__main__:main" + +[tool.ruff] +line-length = 120 +extend-exclude = ["examples", "src/rawdog/prompts.py"] + +[tool.isort] +profile = "black" +extend_skip = ["examples"] + +[tool.black] +preview = "true" +extend-exclude = "examples" diff --git a/scripts/fine_tune.py b/scripts/fine_tune.py index 937ae3e..4650702 100755 --- a/scripts/fine_tune.py +++ b/scripts/fine_tune.py @@ -1,11 +1,10 @@ #!/usr/bin/env python import argparse -import os +import time from openai import OpenAI client = OpenAI() -import time parser = argparse.ArgumentParser(description="Fine tuning GPT-3") parser.add_argument( diff --git a/src/rawdog/__main__.py b/src/rawdog/__main__.py index 5e2f1c4..8f094cd 100644 --- a/src/rawdog/__main__.py +++ b/src/rawdog/__main__.py @@ -1,6 +1,4 @@ import argparse -import os -import platform import readline from rawdog import __version__ @@ -55,18 +53,18 @@ def rawdog(prompt: str, config, llm_client): def banner(): - print( - f""" / \__ + print(f""" / \__ ( @\___ ┳┓┏┓┏ ┓┳┓┏┓┏┓ / O ┣┫┣┫┃┃┃┃┃┃┃┃┓ / (_____/ ┛┗┛┗┗┻┛┻┛┗┛┗┛ -/_____/ U Rawdog v{__version__}""" - ) +/_____/ U Rawdog v{__version__}""") def main(): parser = argparse.ArgumentParser( - description="A smart assistant that can execute Python code to help or hurt you." + description=( + "A smart assistant that can execute Python code to help or hurt you." + ) ) parser.add_argument( "prompt", @@ -92,7 +90,7 @@ def main(): if llm_client.session_cost > 0: print(f"Session cost: ${llm_client.session_cost:.4f}") print("What can I do for you? (Ctrl-C to exit)") - prompt = input(f"> ") + prompt = input("> ") # Save history after each command to avoid losing it in case of crash readline.write_history_file(history_file) print("") diff --git a/src/rawdog/execute_script.py b/src/rawdog/execute_script.py index 29c25d7..1659156 100644 --- a/src/rawdog/execute_script.py +++ b/src/rawdog/execute_script.py @@ -58,7 +58,8 @@ def execute_script(script: str, llm_client) -> str: module_name = llm_client.get_python_package(module) if ( input( - f"Rawdog wants to use {module_name}. Install to rawdog's venv with pip? (Y/n): " + f"Rawdog wants to use {module_name}. Install to rawdog's" + " venv with pip? (Y/n): " ) .strip() .lower() diff --git a/src/rawdog/llm_client.py b/src/rawdog/llm_client.py index 10d9d55..12eccc0 100644 --- a/src/rawdog/llm_client.py +++ b/src/rawdog/llm_client.py @@ -1,6 +1,6 @@ import json import os -from textwrap import dedent, indent +from textwrap import dedent from typing import Optional from litellm import completion, completion_cost @@ -12,7 +12,6 @@ class LLMClient: - def __init__(self, config: dict): # In general it's hard to know if the user needs an API key or which environment variables to set # We do a simple check here for the default case (gpt- models from openai). @@ -24,10 +23,11 @@ def __init__(self, config: dict): os.environ["OPENAI_API_KEY"] = config_api_key elif not env_api_key: print( - "It looks like you're using a GPT model without an API key. " - "You can add your API key by setting the OPENAI_API_KEY environment variable " - "or by adding an llm_api_key field to ~/.rawdog/config.yaml. " - "If this was intentional, you can ignore this message." + "It looks like you're using a GPT model without an API key. You can" + " add your API key by setting the OPENAI_API_KEY environment" + " variable or by adding an llm_api_key field to" + " ~/.rawdog/config.yaml. If this was intentional, you can ignore" + " this message." ) self.conversation = [ @@ -45,15 +45,13 @@ def get_python_package(self, import_name: str): messages = [ { "role": "system", - "content": dedent( - f"""\ + "content": dedent(f"""\ The following python import failed: import {import_name}. \ Respond with only one word which is the name of the package \ on pypi. For instance if the import is "import numpy", you \ should respond with "numpy". If the import is "import PIL" \ you should respond with "Pillow". If you are unsure respond \ - with the original import name.""" - ), + with the original import name."""), } ] @@ -119,7 +117,7 @@ def get_script(self, prompt: Optional[str] = None, stream=False): log_conversation(self.conversation, metadata=metadata) except Exception as e: log["error"] = str(e) - print(f"Error:\n", str(log)) + print("Error:\n", str(log)) raise e finally: with open(rawdog_log_path, "a") as f: diff --git a/src/rawdog/logging.py b/src/rawdog/logging.py index d02ba64..47cc461 100644 --- a/src/rawdog/logging.py +++ b/src/rawdog/logging.py @@ -37,12 +37,10 @@ def log_conversation( for function_name, function in functions.items(): script += f"def {function_name}():\n" + indent(function, " ") + "\n\n\n" - script += dedent( - f"""\ + script += dedent(f"""\ if __name__ == "__main__": function_{len(functions)}() - """ - ) + """) if filename is None: script_filename = rawdog_dir / f"script_{timestamp}.py" diff --git a/src/rawdog/parsing.py b/src/rawdog/parsing.py index 2332fb0..aaef9df 100644 --- a/src/rawdog/parsing.py +++ b/src/rawdog/parsing.py @@ -20,10 +20,10 @@ def parse_script(response: str) -> tuple[str, str]: script = "\n".join(script.split("\n")[1:]) try: # Make sure it isn't json script = json.loads(script) - except Exception as e: + except Exception: pass try: # Make sure it's valid python ast.parse(script) - except SyntaxError as e: + except SyntaxError: return f"Script contains invalid Python:\n{response}", "" return message, script