diff --git a/ai.md b/ai.md index 41600a6..01e5ed2 100644 --- a/ai.md +++ b/ai.md @@ -12,15 +12,15 @@ This section covers how it works and the various supported options. You can choose between two options for your LLM chat: OpenAI and LLM (generic). The OpenAI option limits you to OpenAI models, but supports streaming and asynchronous API access. -The generic "LLM" option uses the [llm library](https://github.com/simonw/llm) and can be used with many different -models---including local ones. However, it does not yet support streaming responses. +The generic "LLM" option uses the [litellm library](https://docs.litellm.ai/docs/) and can be used with many different +models---including local ones. We recommend choosing "OpenAI" unless you know you want to use a different model. ### Configuring OpenAI If you're using OpenAI, you need to set `OPENAI_API_KEY` in your environment or settings file (`.env` in development). -You can also change the model used by setting `OPENAI_MODEL`, which defualts to `"gpt-3.5-turbo"`. +You can also change the model used by setting `OPENAI_MODEL`, which defaults to `"gpt-4o"`. See [this page](https://help.openai.com/en/articles/4936850-where-do-i-find-my-secret-api-key) for help finding your OpenAI API key. @@ -32,23 +32,39 @@ values in your `settings.py`. For example: ```python LLM_MODELS = { - "gpt4": {"key": env("OPENAI_API_KEY", default="")}, - "claude-3-opus": {"key": env("ANTHROPIC_API_KEY", default="")}, # requires llm-claude-3 - "Meta-Llama-3-8B-Instruct": {}, # requires llm-gpt4all + "gpt-3.5-turbo": {"api_key": env("OPENAI_API_KEY", default="")}, + "gpt-4o": {"api_key": env("OPENAI_API_KEY", default="")}, + "claude-3-opus-20240229": {"api_key": env("ANTHROPIC_API_KEY", default="")}, + "ollama_chat/llama3": {"api_base": env("OLLAMA_API_BASE", default="http://localhost:11434")}, # requires a running ollama instance } -DEFAULT_LLM_MODEL = "gpt4" +DEFAULT_LLM_MODEL = env("DEFAULT_LLM_MODEL", default="gpt4") ``` The chat UI will use whatever is set in `DEFAULT_LLM_MODEL` out-of-the-box, but you can quickly change it to another model to try different options. -Any models that you add will need to be installed as [llm plugins](https://llm.datasette.io/en/stable/plugins/index.html). -You can do this by putting them in your requirements files, [as outlined here](./python.md#adding-or-removing-a-package). -For example, to use Claude 3 you need to add the [`llm-claude-3` plugin](https://github.com/simonw/llm-claude-3), -and to use local models like Llama 3, you need [`llm-gpt4all`](https://github.com/simonw/llm-gpt4all). - -For further reading, see the documentation of the [llm Python API](https://llm.datasette.io/en/stable/python-api.html), -and [llm generally](https://llm.datasette.io/en/stable/index.html). +For further reading, see the documentation of the [litellm Python API](https://docs.litellm.ai/docs/completion), +and [litellm providers](https://docs.litellm.ai/docs/providers). + +### Running open source LLMs +To run models like Mixtral or Llama3, you will need to run an [Ollama](https://ollama.com/) server in a separate process. + +1. [Download](https://ollama.com/download) and run Ollama or use the Docker [image](https://hub.docker.com/r/ollama/ollama) +2. Download the model you want to run: + ```shell + ollama pull llama3 + # or with docker + docker exec -it ollama ollama pull llama3 + ``` + See the [documentation](https://docs.litellm.ai/docs/providers/ollama) for the list of supported models. +3. Update your django settings to point to the Ollama server. For example: + ```python + LLM_MODELS = { + "ollama_chat/llama3": {"api_base": "http://localhost:11434"}, + } + DEFAULT_LLM_MODEL = "ollama_chat/llama3" + ``` +4. Restart your Django server. ### The Chat UI diff --git a/code-structure.md b/code-structure.md index 956fc15..27d5209 100644 --- a/code-structure.md +++ b/code-structure.md @@ -83,7 +83,9 @@ The majority of the project's base template layouts are in the `templates/web` f ## Code formatting For projects that have enabled the `Autoformat code` option, the code will have been formatted -using [black](https://black.readthedocs.io/en/stable/) and [isort](https://pycqa.github.io/isort/). +using [ruff](https://github.com/astral-sh/ruff)—a drop-in replacement for +[black](https://black.readthedocs.io/en/stable/) and [isort](https://pycqa.github.io/isort/) that runs +much faster than those tools. The project will also include [pre-commit](https://pre-commit.com/) as a dependency in the requirements file as well as the `.pre-commit-config.yaml` file in the root directory. pre-commit is a tool for managing pre-commit @@ -96,19 +98,18 @@ $ pre-commit install --install-hooks pre-commit installed at .git/hooks/pre-commit ``` -The default configuration that ships with Pegasus will run `isort` and `black` prior to every Git +The default configuration that ships with Pegasus will run `ruff` and `ruff-format` prior to every Git commit. If there are fixes that are needed you will be notified in the shell output. ### pre-commit Usage **Manually running hooks** + ```shell # run all hooks against currently staged files pre-commit run # run all the hooks against all the files. This is a useful invocation if you are using pre-commit in CI. pre-commit run --all-files -# only run the isort hook against all staged files -pre-commit run isort ``` **Temporarily disable hooks** @@ -120,27 +121,16 @@ For more information on using and configuring pre-commit check out the ### Tool configurations -The configuration for the tools can be found in the [`pyproject.toml`][toml] file. - -[toml]: https://black.readthedocs.io/en/stable/usage_and_configuration/the_basics.html#what-on-earth-is-a-pyproject-toml-file -**isort** +The configuration for the tools can be found in the [`pyproject.toml`][toml] file, using the same syntax as `black`. -| Parameter | Value | -|--------------|---------| -| Filter Files | `true` | -| Profile | `black` | -| Line Length | `120` | - -[iSort docs](https://pycqa.github.io/isort/docs/configuration/options) - -**black** +[toml]: https://black.readthedocs.io/en/stable/usage_and_configuration/the_basics.html#what-on-earth-is-a-pyproject-toml-file -| Parameter | Value | -|--------------|---------| -| Line Length | `120` | +For the most part the default black/ruff formats have been preserved, with a few updates, for example, +increasing the line length to 120. -[Black docs](https://black.readthedocs.io/en/stable/usage_and_configuration/the_basics.html) +You can find more information about these values in the +[ruff README](https://github.com/astral-sh/ruff?tab=readme-ov-file#configuration). ### Upgrading diff --git a/configuration.md b/configuration.md index 6d154c1..cd205cc 100644 --- a/configuration.md +++ b/configuration.md @@ -284,6 +284,20 @@ For help configuring LLMs and AIs, see the [AI docs](./ai.md). See the [celery docs](/celery) for set up and configuration of Celery. +## Turnstile + +To enable support for [Cloudflare Turnstile](https://www.cloudflare.com/products/turnstile/), +set `TURNSTILE_KEY` and `TURNSTILE_SECRET` in your settings or environment variables. + +This should automatically enable turnstile on your sign up pages. + +It is recommended to create two different Turnstile accounts on Cloudflare for development and production. +In development you can specify "localhost" as your domain like this: + +![Turnstile Dev](/images/turnstile.png) + +In production, you should replace that with your site's production domain. + ## Mailing List diff --git a/cookbooks.md b/cookbooks.md index 65c0c95..0a25f7e 100644 --- a/cookbooks.md +++ b/cookbooks.md @@ -33,9 +33,9 @@ To migrate a project from non-formatted to formatted code, you can go through th 1. First, do a full Pegasus upgrade to the version you want to update to, as described [here](./upgrading.md). **Do *not* check the "autoformat" checkbox yet.** 2. Next, run the formatting tools on your project's `main` branch: - 1. Install black and isort: `pip install black isort` - 2. Run black: `black --extend-exclude migrations --line-length 120 .` - 3. Run isort: `isort -l 120 --profile black .` + 1. Install ruff: `pip install ruff` + 2. Run ruff linting `ruff check --extend-exclude migrations --line-length 120 . --fix` + 3. Run ruff formatting: `ruff format --line-length 120 .` 3. Commit the result: 1. `git add .` 2. `git commit -m "apply formatting changes"` diff --git a/deployment/production-checklist.md b/deployment/production-checklist.md index 18c828e..e6d9e35 100644 --- a/deployment/production-checklist.md +++ b/deployment/production-checklist.md @@ -51,6 +51,7 @@ Ensure that you have configured the following variables (if you are using them): `STRIPE_LIVE_PUBLIC_KEY`, and `STRIPE_LIVE_SECRET_KEY` config vars (or whatever subset you are using). - If you set up email, ensure whatever keys/secrets you need are set. - If you're using Mailchimp, set `MAILCHIMP_API_KEY` and `MAILCHIMP_LIST_ID`. +- If you're using Health Checks, set `HEALTH_CHECK_TOKENS`. Refer to your [chosen platform's documentation](/deployment.rst) for details on how to set environment variables in that platform. @@ -94,7 +95,7 @@ The platform-specific docs have some guidance on setting this up where possible. ## Update other configuration options See [the configuration page](/configuration.md) for a larger list of options, -including social login, sign up flow changes, analytics, logging, and so on. +including social login, sign up flow changes, analytics, logging, adding captchas, and so on. ## Set up monitoring @@ -104,7 +105,18 @@ see any errors that are encountered. It's also recommended to enable the health check endpoint and connect it to a monitoring tool like [StatusCake](https://www.statuscake.com/) or [Uptime Robot](https://uptimerobot.com/) so that you can be alerted whenever your site or services are having an outage. -The URL you should connect is: yourdomain.com/health/. +The URL you should connect is: `yourdomain.com/health/`. + +If you have the "Health Check Endpoint" option enabled for your project you should also ensure that +you have set the `HEALTH_CHECK_TOKENS` environment variable to a secure value. This can be a comma-separated +list of tokens that are required to access the health check endpoint: + +``` +yourdomain.com/health/?token=your_secret_token +``` + +You can then use this URL with the monitoring tool to ensure that only your monitoring tool can +access the health check endpoint. ## Double-check your language settings diff --git a/images/turnstile.png b/images/turnstile.png new file mode 100644 index 0000000..b56b4dc Binary files /dev/null and b/images/turnstile.png differ diff --git a/release-notes.md b/release-notes.md index abe267f..7772cab 100644 --- a/release-notes.md +++ b/release-notes.md @@ -3,6 +3,134 @@ Version History and Release Notes Releases of [SaaS Pegasus: The Django SaaS Boilerplate](https://www.saaspegasus.com/) are documented here. +## Version 2024.6 + +This is a feature release with a few big updates and a lot of smaller ones. + +### AI model changes + +The library used for non-OpenAI LLMs has been changed from [`llm`](https://github.com/simonw/llm) +to [`litellm`](https://docs.litellm.ai/docs/). Reasons for this change include: + +- It has far fewer additional dependencies. +- It supports async APIs out of the box (for most models). +- The `llm` library is more targeted for the command line use-case, whereas `litellm` offers similar functionality + as a native Python library with a cleaner API. + +Litellm can still be used with all common AI models, including OpenAI, Anthropic/Claude, and local models +(via ollama). For details on getting started with `litellm` see the updated [AI documentation](./ai.md). + +### Formatting and linting now use Ruff + +Black and isort have been replaced with [ruff](https://github.com/astral-sh/ruff)---a Python linter/formatter +that offers the same functionality as those tools but is much faster. + +Additionally, Pegasus will now remove unused imports from your files automatically, both +when building your project and if you have set up `pre-commit`. + +This change should be a relatively seamless drop-in replacement, though you may see some new lint errors +in your projects which you can choose to address. + +### Spam prevention updates + +There has been a dramatic increase in spam-bots over the last month. +Many of these bots target seemingly-innocuous functionality like sign up and password reset forms. + +This version includes a few updates to help combat these bots. +First, you can now easily add [Cloudflare turnstile](https://www.cloudflare.com/products/turnstile/) to your sign up forms, +which will present the user with a captcha and should help reduce bot sign-ups. +See [the turnstile documentation](./configuration.md#turnstile) for information on setting this up. + +Additionally, the `ACCOUNT_EMAIL_UNKNOWN_ACCOUNTS` setting has been set to `False` by default. +This prevents "forgot password" and "magic link" emails from being sent out to unknown accounts. +It should also help reduce unnecessary email sending. + +Finally, the [admin dashboard](#admin-dashboard) no longer shows users with unconfirmed email addresses if you have set +`ACCOUNT_EMAIL_VERIFICATION = 'mandatory'`. +This helps filter out likely bots from the report to provide clearer visibilty of people actually signing up for your app. + +### Complete changelog + +Below is the complete set of changes in this release. + +#### Added + +- **Added configurable captcha support on sign up pages, using [Cloudflare turnstile](https://www.cloudflare.com/products/turnstile/).** + See [the turnstile documentation](./configuration.md#turnstile) for more information on setting this up. (Thanks Troy, Jacob, Robert and others for suggesting.) +- Added API views for two-factor authentication, and to change the logged-in user's password. (Thanks Finbar for suggesting!) +- Add UI to tell users they need a verified email address prior to setting up two-factor auth. + - Also added a `has_verified_email` helper class to the `CustomUser` model. +- Added tests for the delete team view for both team admins and members. (HTMX builds only) +- Added test for team member removal permissions. +- Add display and sort on the number of active members in the teams admin. + +#### Fixed + +- Fixed a bug where team names longer than 50 characters could cause a crash during sign up. +- Fixed a bug where multi-factor authentication QR codes had a dark background when dark mode was enabled (Tailwind builds only). + (Thanks Artem for reporting!) +- Fixed a bug where it was possible to bypass two-factor-authentication when using the API authentication views. + (Thanks Finbar for reporting and helping with the fix!) +- Fixed a bug where deleting the user's only team while impersonating them resulted in a temporary crash. + (Thanks EJ for reporting!) +- Fixed a bug where creating an API key crashed if your user's first + last name combined to more than 40 characters. + (Thanks Luc for reporting!) +- Improved the UI feedback when LLMs fail (e.g. if your API key is wrong or ollama is not running). +- Removed the `static/css` and `static/js` directories from the `.dockerignore` file so that other project files + can be included in these directories. + Also updated the production Docker build process so that any existing files are overwritten + by the built versions. (Thanks Raul for reporting!) +- Made some performance improvements to the production Dockerfile build (don't rebuild the front end if there are + no changes in the dependent files). +- Better support trialing subscriptions with no payment methods. + The subscription UI will now show the date the trial ends and won't log errors about missing invoices. (Thanks Jarrett for reporting!) + +#### Changed + +- **Upgraded all Python packages to the latest versions.** +- **Upgraded all JavaScript packages to the latest versions.** +- **Non-OpenAI builds now use `litellm` instead of `llm`.** See above. (Thanks Sarthak for the suggestion!) +- **Changed the formatter/linter from `black` and `isort` to [ruff](https://github.com/astral-sh/ruff).** See above. + - Also addressed a handful of minor linting errors that came up as a result of this change. + - Codebase linting is now substantially faster. + - Unused imports are now automatically removed when building your projects. +- **Celerybeat now uses the `django-celery-beat` library to store tasks in the database instead of on the filesystem.** + This improves support for celerybeat on Docker-based platforms. (Thanks Peter and Artem for the suggestion!) + - Also added a migration to save the default scheduled tasks in the database. +- The login API response has changed, to allow for two-factor auth prompts, and more machine-readable status fields. +- Removed the no-longer-used `use_json_field=True` argument from wagtail `StreamField`s. +- The admin dashboard no longer shows users with unconfirmed email addresses if you have set `ACCOUNT_EMAIL_VERIFICATION = 'mandatory'`. +- The admin dashboard now includes sign ups from the current date, by default. +- Changed behavior when team role checks fail from raising a `TeamPermissionError` to returning a 403 response, + and updated affected tests. One side effect of this is that the stack traces are removed from successful test runs. +- Secret keys should no longer change every time you build your Pegasus project. + They are also now clearly prefixed with `django-insecure-` to indicate that they should be changed in production. +- Updated the default OpenAI chat model to gpt-4o. +- Upgraded the openapi client generator to version 7.5.0 and also pinned the version used by `make build-api-client` + to the same one. +- Team IDs are now optional on the create team page (HTMX builds only). +- Add clearer error message when charts are broken due to api config issue. (Thanks Yngve for reporting!) +- Added `assume_scheme="https"` to form `URLField`s to be compatible with Django 6 behavior. +- Added `FORMS_URLFIELD_ASSUME_HTTPS = True` to be compatible with Django 6 behavior. +- Set `ACCOUNT_EMAIL_UNKNOWN_ACCOUNTS = False` by default, so that "forgot password" emails do not get sent to unknown accounts. + This can help prevent spam bots. + +#### Removed + +- Removed `black` and `isort` from dev-requirements, since they have been replaced by `ruff`. +- Removed `llm` library and associated code, since it has been replaced by `litellm`. +- Removed no longer used `TeamPermissionError` class. + +#### Standalone front end + +The following changes affect the experimental [standalone front end](./experimental/react-front-end.md): + +- **The standalone React front end now supports two-factor-authentication.** +- Improve the UI when you have login issues in the standalone React front end. + +*June 5, 2024* + + ## Version 2024.5.3 This is a hotfix release that fixes a bug where the landing and dashboard page image was accidentally @@ -56,6 +184,9 @@ and Celery workers and returns a non-200 response code if there are any identifi These endpoints can be connected to a monitoring tool like [StatusCake](https://www.statuscake.com/) or [Uptime Robot](https://uptimerobot.com/) so that you can be alerted whenever your site is having issues. +See the section on [monitoring](./deployment/production-checklist.md#set-up-monitoring) in the +production checklist for more information. + ### Allauth updates The [django-allauth](https://docs.allauth.org/en/latest/) library was updated to the latest version, @@ -3433,4 +3564,3 @@ Documentation for subscriptions can be [found here](/subscriptions). ## Version 0.4 and earlier Release notes for earlier versions are no longer publicly available. -