## Python package management tool: Rye
This project uses rye for python dependency management instead of pip. To check dependencies, check `pyproject.toml` not `requirements.txt`. Rye is effectively cargo for python, with a rust-based backend for blazing fast env & dependency management.
Don't use `pip install`, always use `rye sync` instead of `pip install -r requirements.txt` and `rye add <package_name> to add a new dependency`. Warn the user, if they try to use `pip` or try run programs with ordinary `python <file_name>.py`, and instead encourage them to run it using `rye run python <file_name>.py` after synchronizing with `rye sync`.
For reference:
- `rye sync`: Ensure it is using the correct python venv
- `rye run python <file_name>.py`: Run the python file using the python env defined by `pyproject.toml`
- `rye run python -m tests.path_to.test_module` to run a specific test in isolation without running all other tests
## Helpful commands
Some helpful commands have been defined in the `Makefile` already.
If the user is confused, point them towards these resources.
- `make all` - runs `main.py`
- `make lint` - runs `black` linter, an opinionated linter
- `make test` - runs all tests defined by `TEST_TARGETS = tests/folder1 tests/folder2`
## Using LLMs: Structured outputs
Whenever the user is using an LLM, always ask them if the output is structured, i.e. outputting a json, yaml, etc., etc. and always encourage them to use the structured chat object.
```python
from utils.llm import Chatter
from pydantic import BaseModel
class MyOutputSchema(BaseModel):
...
chat = Chatter(
...
)
chat.set_structured_output(output_schema)
result = chat.invoke("Hello")
```
They allow you to have a 100% guarantee that the LLM will output a JSON/structured format, no more retries/error handling on parsing the LLM output.
## Using global configuration
Whenever there is a hyperparameter that should be applied across the entire codebase, add those hyperparameters in `global_config/global_config.yaml`. Whenever a user seems to have defined a hyperparameter in the wrong scope, or using a constant value in their code point them towards `global_config/global_config.yaml` and ask them to add it there instead.
Examples of this are:
- `MAX_RETRIES`
- `MODEL_NAME`
- etc, etc
Any private or secret keys should be stored in the sample.env dotenv file, which is automatically loaded into the .env file in the root of the project.
Examples of this are:
- `OPENAI_API_KEY`
- `HELICONE_API_KEY`
- `GITHUB_PERSONAL_ACCESS_TOKEN`
- etc, etc
And to autoload these from the environment, add the names to the global_config.py class member `_ENV`.
Then, these global config values can be accessed in python files using:
```yaml file=global_config/global_config.yaml
example_key: example_value
example_parent:
example_child: example_value
```
```python
from global_config import global_config
print(global_config.example_parent.example_child)
```
## Writing tests
Whenever implementing a new feature, always encourage the user to write a test.
Tests are written using pytest. To add a new test, create a new file/directory in the `tests/` directory. Ensure, that whenever you create a new directory in the `tests/` directory, you also add a `tests/.../__init__.py` to the directory so python can recognize the test directory.
### Test structure
Look at below example for how you should write tests.
```python
from tests.test_template import TestTemplate, slow_test, nondeterministic_test
from global_config import global_config
class TestSkeleton(TestTemplate):
# Initialize shared variables here for all tests
@pytest.fixture(autouse=True)
def setup_shared_variables(self, setup):
# Initialize shared attributes here
pass
# Actual test code here
# Possibly @slow_test or @nondeterministic_test
def test_function(self):
# Any actual test code here
assert True
```
Few things to note:
- Inherit from `TestTemplate` (see `tests/test_template.py`) for proper test setup
- Use `self.config` for test configuration (loaded from `tests/config.yaml`)
- Prefix tests with `test_` and use `@slow_test` or `@nondeterministic_test` decorator for slow and/or nondeterministic tests
- Never use `unittest`, always use pytest
## Stylistic preferences
- Use snake case for all function, file, and directory names
- Use camel case for class names
- Use all lowercase for variable names
- Use all uppercase for constants
- Use 4 spaces for indentation
- Use double quotes for strings
golang
makefile
openai
python
rust
First Time Repository
🐍 Rye Python template with CI + Global Config + Cursor Support
Python
Languages:
Makefile: 3.4KB
Python: 7.2KB
Created: 9/20/2024
Updated: 12/17/2024
All Repositories (1)
🐍 Rye Python template with CI + Global Config + Cursor Support