Naming
By having consistent naming conventions, we make our code more readable at first sight. Additionally, it gives us hints about what exactly we are importing from a module.
Functions
Section titled “Functions”Asynchronous functions
Section titled “Asynchronous functions”All asynchronous functions must be prefixed with a_.
async def a_call_api() -> Response:In some cases, we have sync and async versions of the same function. In this
case, the prefix should be the only difference between the two.
async def a_call_api() -> Response:def call_api() -> Response:Endpoints
Section titled “Endpoints”All endpoints must be prefixed with e_.
@app.get("/user")async def e_get_user() -> User:With this, we avoid potential conflicts between endpoints and functions that perform actions closely tied to those endpoints.
For example, suppose we want to implement an endpoint to retrieve a template given its name.
def get_template(name: str) -> Template:We can use this function in an endpoint.
from templates import get_template
@app.get("/template")async def get_template(name: str) -> Template: return get_template(name)In this case, this causes a clash between the two function names. We could rename one of them with a synonym, but that’s typically not the cleanest solution.
We avoid this by prefixing the endpoint function with e_.
from templates import get_template
@app.get("/template")async def e_get_template(name: str) -> Template: return get_template(name)Database calls
Section titled “Database calls”All database calls must be prefixed with db_.
from modules.db.core.synchronous import db_get_document
@app.get("/document")async def e_get_document(id: str) -> Document: return db_get_document(id)For the vector database, we use the dbv_ prefix.
from modules.db.vector.synchronous import dbv_get_document_summaries
@app.get("/document/summaries")async def e_get_document_summaries(id: str) -> list[str]: return dbv_get_document_summaries(id)Asynchronous database calls must include the a_ prefix as well. This
translates to adb_ for the regular database and adbv_ for the vector
database.
Celery tasks must be prefixed with t_. This makes importing them
straightforward, avoiding any confusion with regular functions.
from tasks import t_generate_presentation
@app.post("/presentation/generate")async def e_generate_presentation() -> JSONResponse: return t_generate_presentation.delay()If a task access the database, we also include the
database prefix. This results in the prefix tdb_ for
regular database calls and tdbv_ for vector database calls.
Private functions
Section titled “Private functions”Private functions are functions that are only used within a module. To mark
this, they must be prefixed with a single underscore _. They should always be
declared as top level private functions of the module. For example:
def _print_letter(letter: str) -> None: print(f"Letter: {letter}")Across our codebase, we have naming conventions for files. These conventions convey information about the content and purpose of the file.
Here is an overview of all of these conventions.
- api.py: Endpoints.
- tasks.py: Celery tasks.
- models.py: Pydantic models.
- exceptions.py: Custom errors.
- agents.py: AI agents.
- prompts.py: LLM prompts.
- config.py: Constants.
- tests.py: Test suites.