diff --git a/.env.example b/.env.example index ff691cb55..61b6f00ca 100644 --- a/.env.example +++ b/.env.example @@ -59,6 +59,8 @@ DJANGO_SETTINGS_MODULE=redbox_app.settings DEBUG=True DJANGO_SECRET_KEY=1n53cur3K3y DJANGO_LOG_LEVEL=DEBUG +# If you want to disable asim_log formatting comment out below line +DJANGO_LOG_FORMAT=asim_formatter ENVIRONMENT=LOCAL POSTGRES_USER=redbox-core POSTGRES_DB=redbox-core diff --git a/Makefile b/Makefile index e297232b8..cb6a350ff 100644 --- a/Makefile +++ b/Makefile @@ -78,7 +78,7 @@ safe: ## .PHONY: check-migrations check-migrations: stop ## Check types in redbox and worker - docker compose up -d --wait db minio elasticsearch + docker compose up -d --wait db minio opensearch cd django_app && poetry run python manage.py migrate cd django_app && poetry run python manage.py makemigrations --check diff --git a/django_app/Dockerfile b/django_app/Dockerfile index 34827e23d..93b39bda2 100644 --- a/django_app/Dockerfile +++ b/django_app/Dockerfile @@ -50,7 +50,7 @@ COPY --from=poetry-packages /src/venv ./venv ENV DJANGO_SETTINGS_MODULE='redbox_app.settings' ENV PYTHONPATH "${PYTHONPATH}:/." -EXPOSE 8090 +EXPOSE 8080 RUN chmod +x start.sh RUN chmod +x health.sh diff --git a/django_app/frontend/package.json b/django_app/frontend/package.json index 0800c55ce..6b84a80c4 100644 --- a/django_app/frontend/package.json +++ b/django_app/frontend/package.json @@ -49,6 +49,8 @@ }, "author": "", "dependencies": { + "@parcel/config-default": "^2.13.1", + "@parcel/transformer-typescript-tsc": "^2.13.1", "govuk-frontend": "^5.2.0", "i.ai-design-system": "^0.4.8", "posthog-js": "^1.143.0" diff --git a/django_app/poetry.lock b/django_app/poetry.lock index 50b2be367..99e21424d 100644 --- a/django_app/poetry.lock +++ b/django_app/poetry.lock @@ -122,6 +122,20 @@ files = [ [package.dependencies] frozenlist = ">=1.1.0" +[[package]] +name = "amqp" +version = "5.3.1" +description = "Low-level AMQP client for Python (fork of amqplib)." +optional = false +python-versions = ">=3.6" +files = [ + {file = "amqp-5.3.1-py3-none-any.whl", hash = "sha256:43b3319e1b4e7d1251833a93d672b4af1e40f3d632d479b98661a95f117880a2"}, + {file = "amqp-5.3.1.tar.gz", hash = "sha256:cddc00c725449522023bad949f70fff7b48f0b1ade74d170a6f10ab044739432"}, +] + +[package.dependencies] +vine = ">=5.0.0,<6.0.0" + [[package]] name = "annotated-types" version = "0.7.0" @@ -307,6 +321,17 @@ charset-normalizer = ["charset-normalizer"] html5lib = ["html5lib"] lxml = ["lxml"] +[[package]] +name = "billiard" +version = "4.2.1" +description = "Python multiprocessing fork with improvements and bugfixes" +optional = false +python-versions = ">=3.7" +files = [ + {file = "billiard-4.2.1-py3-none-any.whl", hash = "sha256:40b59a4ac8806ba2c2369ea98d876bc6108b051c227baffd928c644d15d8f3cb"}, + {file = "billiard-4.2.1.tar.gz", hash = "sha256:12b641b0c539073fc8d3f5b8b7be998956665c4233c7c1fcd66a7e677c4fb36f"}, +] + [[package]] name = "blessed" version = "1.20.0" @@ -803,6 +828,62 @@ types-awscrt = "*" [package.extras] botocore = ["botocore"] +[[package]] +name = "celery" +version = "5.4.0" +description = "Distributed Task Queue." +optional = false +python-versions = ">=3.8" +files = [ + {file = "celery-5.4.0-py3-none-any.whl", hash = "sha256:369631eb580cf8c51a82721ec538684994f8277637edde2dfc0dacd73ed97f64"}, + {file = "celery-5.4.0.tar.gz", hash = "sha256:504a19140e8d3029d5acad88330c541d4c3f64c789d85f94756762d8bca7e706"}, +] + +[package.dependencies] +billiard = ">=4.2.0,<5.0" +click = ">=8.1.2,<9.0" +click-didyoumean = ">=0.3.0" +click-plugins = ">=1.1.1" +click-repl = ">=0.2.0" +kombu = ">=5.3.4,<6.0" +python-dateutil = ">=2.8.2" +tzdata = ">=2022.7" +vine = ">=5.1.0,<6.0" + +[package.extras] +arangodb = ["pyArango (>=2.0.2)"] +auth = ["cryptography (==42.0.5)"] +azureblockblob = ["azure-storage-blob (>=12.15.0)"] +brotli = ["brotli (>=1.0.0)", "brotlipy (>=0.7.0)"] +cassandra = ["cassandra-driver (>=3.25.0,<4)"] +consul = ["python-consul2 (==0.1.5)"] +cosmosdbsql = ["pydocumentdb (==2.3.5)"] +couchbase = ["couchbase (>=3.0.0)"] +couchdb = ["pycouchdb (==1.14.2)"] +django = ["Django (>=2.2.28)"] +dynamodb = ["boto3 (>=1.26.143)"] +elasticsearch = ["elastic-transport (<=8.13.0)", "elasticsearch (<=8.13.0)"] +eventlet = ["eventlet (>=0.32.0)"] +gcs = ["google-cloud-storage (>=2.10.0)"] +gevent = ["gevent (>=1.5.0)"] +librabbitmq = ["librabbitmq (>=2.0.0)"] +memcache = ["pylibmc (==1.6.3)"] +mongodb = ["pymongo[srv] (>=4.0.2)"] +msgpack = ["msgpack (==1.0.8)"] +pymemcache = ["python-memcached (>=1.61)"] +pyro = ["pyro4 (==4.82)"] +pytest = ["pytest-celery[all] (>=1.0.0)"] +redis = ["redis (>=4.5.2,!=4.5.5,<6.0.0)"] +s3 = ["boto3 (>=1.26.143)"] +slmq = ["softlayer-messaging (>=1.0.3)"] +solar = ["ephem (==4.1.5)"] +sqlalchemy = ["sqlalchemy (>=1.4.48,<2.1)"] +sqs = ["boto3 (>=1.26.143)", "kombu[sqs] (>=5.3.4)", "pycurl (>=7.43.0.5)", "urllib3 (>=1.26.16)"] +tblib = ["tblib (>=1.3.0)", "tblib (>=1.5.0)"] +yaml = ["PyYAML (>=3.10)"] +zookeeper = ["kazoo (>=1.3.1)"] +zstd = ["zstandard (==0.22.0)"] + [[package]] name = "certifi" version = "2024.8.30" @@ -1052,6 +1133,55 @@ files = [ [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} +[[package]] +name = "click-didyoumean" +version = "0.3.1" +description = "Enables git-like *did-you-mean* feature in click" +optional = false +python-versions = ">=3.6.2" +files = [ + {file = "click_didyoumean-0.3.1-py3-none-any.whl", hash = "sha256:5c4bb6007cfea5f2fd6583a2fb6701a22a41eb98957e63d0fac41c10e7c3117c"}, + {file = "click_didyoumean-0.3.1.tar.gz", hash = "sha256:4f82fdff0dbe64ef8ab2279bd6aa3f6a99c3b28c05aa09cbfc07c9d7fbb5a463"}, +] + +[package.dependencies] +click = ">=7" + +[[package]] +name = "click-plugins" +version = "1.1.1" +description = "An extension module for click to enable registering CLI commands via setuptools entry-points." +optional = false +python-versions = "*" +files = [ + {file = "click-plugins-1.1.1.tar.gz", hash = "sha256:46ab999744a9d831159c3411bb0c79346d94a444df9a3a3742e9ed63645f264b"}, + {file = "click_plugins-1.1.1-py2.py3-none-any.whl", hash = "sha256:5d262006d3222f5057fd81e1623d4443e41dcda5dc815c06b442aa3c02889fc8"}, +] + +[package.dependencies] +click = ">=4.0" + +[package.extras] +dev = ["coveralls", "pytest (>=3.6)", "pytest-cov", "wheel"] + +[[package]] +name = "click-repl" +version = "0.3.0" +description = "REPL plugin for Click" +optional = false +python-versions = ">=3.6" +files = [ + {file = "click-repl-0.3.0.tar.gz", hash = "sha256:17849c23dba3d667247dc4defe1757fff98694e90fe37474f3feebb69ced26a9"}, + {file = "click_repl-0.3.0-py3-none-any.whl", hash = "sha256:fb7e06deb8da8de86180a33a9da97ac316751c094c6899382da7feeeeb51b812"}, +] + +[package.dependencies] +click = ">=7.0" +prompt-toolkit = ">=3.0.36" + +[package.extras] +testing = ["pytest (>=7.2.1)", "pytest-cov (>=4.0.0)", "tox (>=4.4.3)"] + [[package]] name = "colorama" version = "0.4.6" @@ -1322,6 +1452,43 @@ files = [ marshmallow = ">=3.18.0,<4.0.0" typing-inspect = ">=0.4.0,<1" +[[package]] +name = "dbt-copilot-python" +version = "0.2.2" +description = "Helper functions to run Django and Flask applications in AWS Copilot/ECS." +optional = false +python-versions = "<4.0,>=3.9" +files = [ + {file = "dbt_copilot_python-0.2.2-py3-none-any.whl", hash = "sha256:7485ffced952e40bab79801b0b8f5eecfbd602f84a9086238c69e4aacdee23bf"}, + {file = "dbt_copilot_python-0.2.2.tar.gz", hash = "sha256:529f6638bbdae96687b8c197eb450357dfbb9d7def6ac8bf23e0846d8b0fea73"}, +] + +[package.dependencies] +celery = ">=5.3.6,<6.0.0" +opentelemetry-distro = "0.43b0" +opentelemetry-exporter-otlp = "1.22.0" +opentelemetry-instrumentation-wsgi = "0.43b0" +opentelemetry-propagator-aws-xray = ">=1.0.1,<2.0.0" +opentelemetry-sdk-extension-aws = ">=2.0.1,<3.0.0" +requests = ">=2.31.0,<3.0.0" + +[[package]] +name = "deprecated" +version = "1.2.15" +description = "Python @deprecated decorator to deprecate old python classes, functions or methods." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" +files = [ + {file = "Deprecated-1.2.15-py2.py3-none-any.whl", hash = "sha256:353bc4a8ac4bfc96800ddab349d89c25dec1079f65fd53acdcc1e0b975b21320"}, + {file = "deprecated-1.2.15.tar.gz", hash = "sha256:683e561a90de76239796e6b6feac66b99030d2dd3fcf61ef996330f14bbb9b0d"}, +] + +[package.dependencies] +wrapt = ">=1.10,<2" + +[package.extras] +dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "jinja2 (>=3.0.3,<3.1.0)", "setuptools", "sphinx (<2)", "tox"] + [[package]] name = "detect-secrets" version = "1.5.0" @@ -1392,6 +1559,21 @@ files = [ {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, ] +[[package]] +name = "dj-database-url" +version = "2.3.0" +description = "Use Database URLs in your Django Application." +optional = false +python-versions = "*" +files = [ + {file = "dj_database_url-2.3.0-py3-none-any.whl", hash = "sha256:bb0d414ba0ac5cd62773ec7f86f8cc378a9dbb00a80884c2fc08cc570452521e"}, + {file = "dj_database_url-2.3.0.tar.gz", hash = "sha256:ae52e8e634186b57e5a45e445da5dc407a819c2ceed8a53d1fac004cc5288787"}, +] + +[package.dependencies] +Django = ">=4.2" +typing_extensions = ">=3.10.0.0" + [[package]] name = "django" version = "5.1.3" @@ -1545,6 +1727,21 @@ files = [ django-compressor = ">=1.3" libsass = ">=0.7.0,<1" +[[package]] +name = "django-log-formatter-asim" +version = "0.0.6" +description = "Formats Django logs in ASIM format." +optional = false +python-versions = "<4,>=3.9" +files = [ + {file = "django_log_formatter_asim-0.0.6-py3-none-any.whl", hash = "sha256:00923cb95b599082d94895af1333d1bb8fce05a3d742dd571d32b7e0e480ead3"}, + {file = "django_log_formatter_asim-0.0.6.tar.gz", hash = "sha256:ba35df7a8c5f5bad2e006b55dea8e339ef82f7476a93e6cae4d2bbea12938c2b"}, +] + +[package.dependencies] +django = {version = ">=3,<6", markers = "python_version >= \"3.10\" and python_version < \"4\""} +pre-commit = ">=3.5.0,<4.0.0" + [[package]] name = "django-magic-link" version = "1.0.0" @@ -1646,6 +1843,24 @@ files = [ [package.dependencies] Django = ">=3.0" +[[package]] +name = "django-staff-sso-client" +version = "4.3.0" +description = "Reusable Django app to facilitate gov.uk Staff Single Sign On" +optional = false +python-versions = "*" +files = [ + {file = "django_staff_sso_client-4.3.0-py3-none-any.whl", hash = "sha256:873279b74cc40517af6b5c6c043db74e66d3d4f147ed1495ec357ac26c14d6fa"}, + {file = "django_staff_sso_client-4.3.0.tar.gz", hash = "sha256:4f320c5c5da02a9da9f5da90b32749ff3a0ad0dcf51eb758fb85fd0e932b5261"}, +] + +[package.dependencies] +Django = ">=4.2.10,<6.0" +requests-oauthlib = "*" + +[package.extras] +test = ["build", "codecov", "flake8 (==4.0.1)", "pytest (==7.1.1)", "pytest-cov", "pytest-django", "raven", "requests-mock", "setuptools", "twine", "wheel"] + [[package]] name = "django-storages" version = "1.14.4" @@ -2028,6 +2243,23 @@ monitor = ["psutil (>=5.7.0)"] recommended = ["cffi (>=1.17.1)", "dnspython (>=1.16.0,<2.0)", "idna", "psutil (>=5.7.0)"] test = ["cffi (>=1.17.1)", "coverage (>=5.0)", "dnspython (>=1.16.0,<2.0)", "idna", "objgraph", "psutil (>=5.7.0)", "requests"] +[[package]] +name = "googleapis-common-protos" +version = "1.66.0" +description = "Common protobufs used in Google APIs" +optional = false +python-versions = ">=3.7" +files = [ + {file = "googleapis_common_protos-1.66.0-py2.py3-none-any.whl", hash = "sha256:d7abcd75fabb2e0ec9f74466401f6c119a0b498e27370e9be4c94cb7e382b8ed"}, + {file = "googleapis_common_protos-1.66.0.tar.gz", hash = "sha256:c3e7b33d15fdca5374cc0a7346dd92ffa847425cc4ea941d970f13680052ec8c"}, +] + +[package.dependencies] +protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" + +[package.extras] +grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] + [[package]] name = "greenlet" version = "3.1.1" @@ -2114,6 +2346,73 @@ files = [ docs = ["Sphinx", "furo"] test = ["objgraph", "psutil"] +[[package]] +name = "grpcio" +version = "1.68.0" +description = "HTTP/2-based RPC framework" +optional = false +python-versions = ">=3.8" +files = [ + {file = "grpcio-1.68.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:619b5d0f29f4f5351440e9343224c3e19912c21aeda44e0c49d0d147a8d01544"}, + {file = "grpcio-1.68.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:a59f5822f9459bed098ffbceb2713abbf7c6fd13f2b9243461da5c338d0cd6c3"}, + {file = "grpcio-1.68.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:c03d89df516128febc5a7e760d675b478ba25802447624edf7aa13b1e7b11e2a"}, + {file = "grpcio-1.68.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44bcbebb24363d587472089b89e2ea0ab2e2b4df0e4856ba4c0b087c82412121"}, + {file = "grpcio-1.68.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79f81b7fbfb136247b70465bd836fa1733043fdee539cd6031cb499e9608a110"}, + {file = "grpcio-1.68.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:88fb2925789cfe6daa20900260ef0a1d0a61283dfb2d2fffe6194396a354c618"}, + {file = "grpcio-1.68.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:99f06232b5c9138593ae6f2e355054318717d32a9c09cdc5a2885540835067a1"}, + {file = "grpcio-1.68.0-cp310-cp310-win32.whl", hash = "sha256:a6213d2f7a22c3c30a479fb5e249b6b7e648e17f364598ff64d08a5136fe488b"}, + {file = "grpcio-1.68.0-cp310-cp310-win_amd64.whl", hash = "sha256:15327ab81131ef9b94cb9f45b5bd98803a179c7c61205c8c0ac9aff9d6c4e82a"}, + {file = "grpcio-1.68.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:3b2b559beb2d433129441783e5f42e3be40a9e1a89ec906efabf26591c5cd415"}, + {file = "grpcio-1.68.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e46541de8425a4d6829ac6c5d9b16c03c292105fe9ebf78cb1c31e8d242f9155"}, + {file = "grpcio-1.68.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:c1245651f3c9ea92a2db4f95d37b7597db6b246d5892bca6ee8c0e90d76fb73c"}, + {file = "grpcio-1.68.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f1931c7aa85be0fa6cea6af388e576f3bf6baee9e5d481c586980c774debcb4"}, + {file = "grpcio-1.68.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b0ff09c81e3aded7a183bc6473639b46b6caa9c1901d6f5e2cba24b95e59e30"}, + {file = "grpcio-1.68.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8c73f9fbbaee1a132487e31585aa83987ddf626426d703ebcb9a528cf231c9b1"}, + {file = "grpcio-1.68.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6b2f98165ea2790ea159393a2246b56f580d24d7da0d0342c18a085299c40a75"}, + {file = "grpcio-1.68.0-cp311-cp311-win32.whl", hash = "sha256:e1e7ed311afb351ff0d0e583a66fcb39675be112d61e7cfd6c8269884a98afbc"}, + {file = "grpcio-1.68.0-cp311-cp311-win_amd64.whl", hash = "sha256:e0d2f68eaa0a755edd9a47d40e50dba6df2bceda66960dee1218da81a2834d27"}, + {file = "grpcio-1.68.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:8af6137cc4ae8e421690d276e7627cfc726d4293f6607acf9ea7260bd8fc3d7d"}, + {file = "grpcio-1.68.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4028b8e9a3bff6f377698587d642e24bd221810c06579a18420a17688e421af7"}, + {file = "grpcio-1.68.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:f60fa2adf281fd73ae3a50677572521edca34ba373a45b457b5ebe87c2d01e1d"}, + {file = "grpcio-1.68.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e18589e747c1e70b60fab6767ff99b2d0c359ea1db8a2cb524477f93cdbedf5b"}, + {file = "grpcio-1.68.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0d30f3fee9372796f54d3100b31ee70972eaadcc87314be369360248a3dcffe"}, + {file = "grpcio-1.68.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:7e0a3e72c0e9a1acab77bef14a73a416630b7fd2cbd893c0a873edc47c42c8cd"}, + {file = "grpcio-1.68.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a831dcc343440969aaa812004685ed322cdb526cd197112d0db303b0da1e8659"}, + {file = "grpcio-1.68.0-cp312-cp312-win32.whl", hash = "sha256:5a180328e92b9a0050958ced34dddcb86fec5a8b332f5a229e353dafc16cd332"}, + {file = "grpcio-1.68.0-cp312-cp312-win_amd64.whl", hash = "sha256:2bddd04a790b69f7a7385f6a112f46ea0b34c4746f361ebafe9ca0be567c78e9"}, + {file = "grpcio-1.68.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:fc05759ffbd7875e0ff2bd877be1438dfe97c9312bbc558c8284a9afa1d0f40e"}, + {file = "grpcio-1.68.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:15fa1fe25d365a13bc6d52fcac0e3ee1f9baebdde2c9b3b2425f8a4979fccea1"}, + {file = "grpcio-1.68.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:32a9cb4686eb2e89d97022ecb9e1606d132f85c444354c17a7dbde4a455e4a3b"}, + {file = "grpcio-1.68.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dba037ff8d284c8e7ea9a510c8ae0f5b016004f13c3648f72411c464b67ff2fb"}, + {file = "grpcio-1.68.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0efbbd849867e0e569af09e165363ade75cf84f5229b2698d53cf22c7a4f9e21"}, + {file = "grpcio-1.68.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:4e300e6978df0b65cc2d100c54e097c10dfc7018b9bd890bbbf08022d47f766d"}, + {file = "grpcio-1.68.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:6f9c7ad1a23e1047f827385f4713b5b8c6c7d325705be1dd3e31fb00dcb2f665"}, + {file = "grpcio-1.68.0-cp313-cp313-win32.whl", hash = "sha256:3ac7f10850fd0487fcce169c3c55509101c3bde2a3b454869639df2176b60a03"}, + {file = "grpcio-1.68.0-cp313-cp313-win_amd64.whl", hash = "sha256:afbf45a62ba85a720491bfe9b2642f8761ff348006f5ef67e4622621f116b04a"}, + {file = "grpcio-1.68.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:f8f695d9576ce836eab27ba7401c60acaf9ef6cf2f70dfe5462055ba3df02cc3"}, + {file = "grpcio-1.68.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9fe1b141cda52f2ca73e17d2d3c6a9f3f3a0c255c216b50ce616e9dca7e3441d"}, + {file = "grpcio-1.68.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:4df81d78fd1646bf94ced4fb4cd0a7fe2e91608089c522ef17bc7db26e64effd"}, + {file = "grpcio-1.68.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:46a2d74d4dd8993151c6cd585594c082abe74112c8e4175ddda4106f2ceb022f"}, + {file = "grpcio-1.68.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a17278d977746472698460c63abf333e1d806bd41f2224f90dbe9460101c9796"}, + {file = "grpcio-1.68.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:15377bce516b1c861c35e18eaa1c280692bf563264836cece693c0f169b48829"}, + {file = "grpcio-1.68.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cc5f0a4f5904b8c25729a0498886b797feb817d1fd3812554ffa39551112c161"}, + {file = "grpcio-1.68.0-cp38-cp38-win32.whl", hash = "sha256:def1a60a111d24376e4b753db39705adbe9483ef4ca4761f825639d884d5da78"}, + {file = "grpcio-1.68.0-cp38-cp38-win_amd64.whl", hash = "sha256:55d3b52fd41ec5772a953612db4e70ae741a6d6ed640c4c89a64f017a1ac02b5"}, + {file = "grpcio-1.68.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:0d230852ba97654453d290e98d6aa61cb48fa5fafb474fb4c4298d8721809354"}, + {file = "grpcio-1.68.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:50992f214264e207e07222703c17d9cfdcc2c46ed5a1ea86843d440148ebbe10"}, + {file = "grpcio-1.68.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:14331e5c27ed3545360464a139ed279aa09db088f6e9502e95ad4bfa852bb116"}, + {file = "grpcio-1.68.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f84890b205692ea813653ece4ac9afa2139eae136e419231b0eec7c39fdbe4c2"}, + {file = "grpcio-1.68.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0cf343c6f4f6aa44863e13ec9ddfe299e0be68f87d68e777328bff785897b05"}, + {file = "grpcio-1.68.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:fd2c2d47969daa0e27eadaf15c13b5e92605c5e5953d23c06d0b5239a2f176d3"}, + {file = "grpcio-1.68.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:18668e36e7f4045820f069997834e94e8275910b1f03e078a6020bd464cb2363"}, + {file = "grpcio-1.68.0-cp39-cp39-win32.whl", hash = "sha256:2af76ab7c427aaa26aa9187c3e3c42f38d3771f91a20f99657d992afada2294a"}, + {file = "grpcio-1.68.0-cp39-cp39-win_amd64.whl", hash = "sha256:e694b5928b7b33ca2d3b4d5f9bf8b5888906f181daff6b406f4938f3a997a490"}, + {file = "grpcio-1.68.0.tar.gz", hash = "sha256:7e7483d39b4a4fddb9906671e9ea21aaad4f031cdfc349fec76bdfa1e404543a"}, +] + +[package.extras] +protobuf = ["grpcio-tools (>=1.68.0)"] + [[package]] name = "h11" version = "0.14.0" @@ -2238,6 +2537,25 @@ files = [ [package.extras] all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] +[[package]] +name = "importlib-metadata" +version = "6.11.0" +description = "Read metadata from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_metadata-6.11.0-py3-none-any.whl", hash = "sha256:f0afba6205ad8f8947c7d338b5342d5db2afbfd82f9cbef7879a9539cc12eb9b"}, + {file = "importlib_metadata-6.11.0.tar.gz", hash = "sha256:1231cf92d825c9e03cfc4da076a16de6422c863558229ea0b22b675657463443"}, +] + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] + [[package]] name = "incremental" version = "24.7.2" @@ -2470,6 +2788,39 @@ scipy = ">=1.0.0" plot = ["matplotlib (>=2.2.5)"] testing = ["matplotlib (>=2.2.5)", "pytest (>=5.0.1)", "pytest-cov (>=3.0.0)"] +[[package]] +name = "kombu" +version = "5.4.2" +description = "Messaging library for Python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "kombu-5.4.2-py3-none-any.whl", hash = "sha256:14212f5ccf022fc0a70453bb025a1dcc32782a588c49ea866884047d66e14763"}, + {file = "kombu-5.4.2.tar.gz", hash = "sha256:eef572dd2fd9fc614b37580e3caeafdd5af46c1eff31e7fba89138cdb406f2cf"}, +] + +[package.dependencies] +amqp = ">=5.1.1,<6.0.0" +tzdata = {version = "*", markers = "python_version >= \"3.9\""} +vine = "5.1.0" + +[package.extras] +azureservicebus = ["azure-servicebus (>=7.10.0)"] +azurestoragequeues = ["azure-identity (>=1.12.0)", "azure-storage-queue (>=12.6.0)"] +confluentkafka = ["confluent-kafka (>=2.2.0)"] +consul = ["python-consul2 (==0.1.5)"] +librabbitmq = ["librabbitmq (>=2.0.0)"] +mongodb = ["pymongo (>=4.1.1)"] +msgpack = ["msgpack (==1.1.0)"] +pyro = ["pyro4 (==4.82)"] +qpid = ["qpid-python (>=0.26)", "qpid-tools (>=0.26)"] +redis = ["redis (>=4.5.2,!=4.5.5,!=5.0.2)"] +slmq = ["softlayer-messaging (>=1.0.3)"] +sqlalchemy = ["sqlalchemy (>=1.4.48,<2.1)"] +sqs = ["boto3 (>=1.26.143)", "pycurl (>=7.43.0.5)", "urllib3 (>=1.26.16)"] +yaml = ["PyYAML (>=3.10)"] +zookeeper = ["kazoo (>=2.8.0)"] + [[package]] name = "langchain" version = "0.3.7" @@ -3102,6 +3453,22 @@ files = [ {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"}, ] +[[package]] +name = "oauthlib" +version = "3.2.2" +description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" +optional = false +python-versions = ">=3.6" +files = [ + {file = "oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca"}, + {file = "oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918"}, +] + +[package.extras] +rsa = ["cryptography (>=3.0.0)"] +signals = ["blinker (>=1.4.0)"] +signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] + [[package]] name = "openai" version = "1.54.5" @@ -3150,6 +3517,234 @@ develop = ["black (>=24.3.0)", "botocore", "coverage (<8.0.0)", "jinja2", "myst- docs = ["aiohttp (>=3.9.4,<4)", "myst-parser", "sphinx", "sphinx-copybutton", "sphinx-rtd-theme"] kerberos = ["requests-kerberos"] +[[package]] +name = "opentelemetry-api" +version = "1.22.0" +description = "OpenTelemetry Python API" +optional = false +python-versions = ">=3.7" +files = [ + {file = "opentelemetry_api-1.22.0-py3-none-any.whl", hash = "sha256:43621514301a7e9f5d06dd8013a1b450f30c2e9372b8e30aaeb4562abf2ce034"}, + {file = "opentelemetry_api-1.22.0.tar.gz", hash = "sha256:15ae4ca925ecf9cfdfb7a709250846fbb08072260fca08ade78056c502b86bed"}, +] + +[package.dependencies] +deprecated = ">=1.2.6" +importlib-metadata = ">=6.0,<7.0" + +[[package]] +name = "opentelemetry-distro" +version = "0.43b0" +description = "OpenTelemetry Python Distro" +optional = false +python-versions = ">=3.7" +files = [ + {file = "opentelemetry_distro-0.43b0-py3-none-any.whl", hash = "sha256:a33f4a5f40f51dbb9f1d21b426d128312f9e2a12fe04da31a9017da6c20c958e"}, + {file = "opentelemetry_distro-0.43b0.tar.gz", hash = "sha256:ab4876203d06d40c77cffe1e79c859cff6b471725a846076946cc94df1a863a9"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.12,<2.0" +opentelemetry-instrumentation = "0.43b0" +opentelemetry-sdk = ">=1.13,<2.0" + +[package.extras] +otlp = ["opentelemetry-exporter-otlp (==1.22.0)"] + +[[package]] +name = "opentelemetry-exporter-otlp" +version = "1.22.0" +description = "OpenTelemetry Collector Exporters" +optional = false +python-versions = ">=3.7" +files = [ + {file = "opentelemetry_exporter_otlp-1.22.0-py3-none-any.whl", hash = "sha256:cb03a1cbf300e12b47690858be13dd26fe2f60b2610204959f3497cd6645e3a1"}, + {file = "opentelemetry_exporter_otlp-1.22.0.tar.gz", hash = "sha256:309a7d4dc67602801f15818e110ce452e78989886aaab5d37e7cf7f55f1d3d27"}, +] + +[package.dependencies] +opentelemetry-exporter-otlp-proto-grpc = "1.22.0" +opentelemetry-exporter-otlp-proto-http = "1.22.0" + +[[package]] +name = "opentelemetry-exporter-otlp-proto-common" +version = "1.22.0" +description = "OpenTelemetry Protobuf encoding" +optional = false +python-versions = ">=3.7" +files = [ + {file = "opentelemetry_exporter_otlp_proto_common-1.22.0-py3-none-any.whl", hash = "sha256:3f2538bec5312587f8676c332b3747f54c89fe6364803a807e217af4603201fa"}, + {file = "opentelemetry_exporter_otlp_proto_common-1.22.0.tar.gz", hash = "sha256:71ae2f81bc6d6fe408d06388826edc8933759b2ca3a97d24054507dc7cfce52d"}, +] + +[package.dependencies] +backoff = {version = ">=1.10.0,<3.0.0", markers = "python_version >= \"3.7\""} +opentelemetry-proto = "1.22.0" + +[[package]] +name = "opentelemetry-exporter-otlp-proto-grpc" +version = "1.22.0" +description = "OpenTelemetry Collector Protobuf over gRPC Exporter" +optional = false +python-versions = ">=3.7" +files = [ + {file = "opentelemetry_exporter_otlp_proto_grpc-1.22.0-py3-none-any.whl", hash = "sha256:b5bcadc129272004316a455e9081216d3380c1fc2231a928ea6a70aa90e173fb"}, + {file = "opentelemetry_exporter_otlp_proto_grpc-1.22.0.tar.gz", hash = "sha256:1e0e5aa4bbabc74942f06f268deffd94851d12a8dc30b02527472ef1729fe5b1"}, +] + +[package.dependencies] +backoff = {version = ">=1.10.0,<3.0.0", markers = "python_version >= \"3.7\""} +deprecated = ">=1.2.6" +googleapis-common-protos = ">=1.52,<2.0" +grpcio = ">=1.0.0,<2.0.0" +opentelemetry-api = ">=1.15,<2.0" +opentelemetry-exporter-otlp-proto-common = "1.22.0" +opentelemetry-proto = "1.22.0" +opentelemetry-sdk = ">=1.22.0,<1.23.0" + +[package.extras] +test = ["pytest-grpc"] + +[[package]] +name = "opentelemetry-exporter-otlp-proto-http" +version = "1.22.0" +description = "OpenTelemetry Collector Protobuf over HTTP Exporter" +optional = false +python-versions = ">=3.7" +files = [ + {file = "opentelemetry_exporter_otlp_proto_http-1.22.0-py3-none-any.whl", hash = "sha256:e002e842190af45b91dc55a97789d0b98e4308c88d886b16049ee90e17a4d396"}, + {file = "opentelemetry_exporter_otlp_proto_http-1.22.0.tar.gz", hash = "sha256:79ed108981ec68d5f7985355bca32003c2f3a5be1534a96d62d5861b758a82f4"}, +] + +[package.dependencies] +backoff = {version = ">=1.10.0,<3.0.0", markers = "python_version >= \"3.7\""} +deprecated = ">=1.2.6" +googleapis-common-protos = ">=1.52,<2.0" +opentelemetry-api = ">=1.15,<2.0" +opentelemetry-exporter-otlp-proto-common = "1.22.0" +opentelemetry-proto = "1.22.0" +opentelemetry-sdk = ">=1.22.0,<1.23.0" +requests = ">=2.7,<3.0" + +[package.extras] +test = ["responses (==0.22.0)"] + +[[package]] +name = "opentelemetry-instrumentation" +version = "0.43b0" +description = "Instrumentation Tools & Auto Instrumentation for OpenTelemetry Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "opentelemetry_instrumentation-0.43b0-py3-none-any.whl", hash = "sha256:0ff1334d7e359e27640e9d420024efeb73eacae464309c2e14ede7ba6c93967e"}, + {file = "opentelemetry_instrumentation-0.43b0.tar.gz", hash = "sha256:c3755da6c4be8033be0216d0501e11f4832690f4e2eca5a3576fbf113498f0f6"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.4,<2.0" +setuptools = ">=16.0" +wrapt = ">=1.0.0,<2.0.0" + +[[package]] +name = "opentelemetry-instrumentation-wsgi" +version = "0.43b0" +description = "WSGI Middleware for OpenTelemetry" +optional = false +python-versions = ">=3.7" +files = [ + {file = "opentelemetry_instrumentation_wsgi-0.43b0-py3-none-any.whl", hash = "sha256:0b7511469daa29a6e75b9cc54b4d01a9bb46aa1f964471dc3ee3f06ff39f94b2"}, + {file = "opentelemetry_instrumentation_wsgi-0.43b0.tar.gz", hash = "sha256:3a1cf045f7ccf04987a89cdd49eda93e9195de4c8b73be228a9e565ec3ab453c"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.12,<2.0" +opentelemetry-instrumentation = "0.43b0" +opentelemetry-semantic-conventions = "0.43b0" +opentelemetry-util-http = "0.43b0" + +[package.extras] +test = ["opentelemetry-test-utils (==0.43b0)"] + +[[package]] +name = "opentelemetry-propagator-aws-xray" +version = "1.0.2" +description = "AWS X-Ray Propagator for OpenTelemetry" +optional = false +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_propagator_aws_xray-1.0.2-py3-none-any.whl", hash = "sha256:1c99181ee228e99bddb638a0c911a297fa21f1c3a0af951f841e79919b5f1934"}, + {file = "opentelemetry_propagator_aws_xray-1.0.2.tar.gz", hash = "sha256:6b2cee5479d2ef0172307b66ed2ed151f598a0fd29b3c01133ac87ca06326260"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.12,<2.0" + +[[package]] +name = "opentelemetry-proto" +version = "1.22.0" +description = "OpenTelemetry Python Proto" +optional = false +python-versions = ">=3.7" +files = [ + {file = "opentelemetry_proto-1.22.0-py3-none-any.whl", hash = "sha256:ce7188d22c75b6d0fe53e7fb58501613d0feade5139538e79dedd9420610fa0c"}, + {file = "opentelemetry_proto-1.22.0.tar.gz", hash = "sha256:9ec29169286029f17ca34ec1f3455802ffb90131642d2f545ece9a63e8f69003"}, +] + +[package.dependencies] +protobuf = ">=3.19,<5.0" + +[[package]] +name = "opentelemetry-sdk" +version = "1.22.0" +description = "OpenTelemetry Python SDK" +optional = false +python-versions = ">=3.7" +files = [ + {file = "opentelemetry_sdk-1.22.0-py3-none-any.whl", hash = "sha256:a730555713d7c8931657612a88a141e3a4fe6eb5523d9e2d5a8b1e673d76efa6"}, + {file = "opentelemetry_sdk-1.22.0.tar.gz", hash = "sha256:45267ac1f38a431fc2eb5d6e0c0d83afc0b78de57ac345488aa58c28c17991d0"}, +] + +[package.dependencies] +opentelemetry-api = "1.22.0" +opentelemetry-semantic-conventions = "0.43b0" +typing-extensions = ">=3.7.4" + +[[package]] +name = "opentelemetry-sdk-extension-aws" +version = "2.0.2" +description = "AWS SDK extension for OpenTelemetry" +optional = false +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_sdk_extension_aws-2.0.2-py3-none-any.whl", hash = "sha256:4c6e4b9fec01a4a9cfeac5272ce5aae6bc80e080a6bae1e52098746f53a7b32d"}, + {file = "opentelemetry_sdk_extension_aws-2.0.2.tar.gz", hash = "sha256:9faa9bdf480d1c5c53151dabee75735c94dbde09e4762c68ff5c7bd4aa3408f3"}, +] + +[package.dependencies] +opentelemetry-sdk = ">=1.12,<2.0" + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.43b0" +description = "OpenTelemetry Semantic Conventions" +optional = false +python-versions = ">=3.7" +files = [ + {file = "opentelemetry_semantic_conventions-0.43b0-py3-none-any.whl", hash = "sha256:291284d7c1bf15fdaddf309b3bd6d3b7ce12a253cec6d27144439819a15d8445"}, + {file = "opentelemetry_semantic_conventions-0.43b0.tar.gz", hash = "sha256:b9576fb890df479626fa624e88dde42d3d60b8b6c8ae1152ad157a8b97358635"}, +] + +[[package]] +name = "opentelemetry-util-http" +version = "0.43b0" +description = "Web util for OpenTelemetry" +optional = false +python-versions = ">=3.7" +files = [ + {file = "opentelemetry_util_http-0.43b0-py3-none-any.whl", hash = "sha256:f25a820784b030f6cb86b3d76e5676c769b75ed3f55a210bcdae0a5e175ebadb"}, + {file = "opentelemetry_util_http-0.43b0.tar.gz", hash = "sha256:3ff6ab361dbe99fc81200d625603c0fb890c055c6e416a3e6d661ddf47a6c7f7"}, +] + [[package]] name = "orjson" version = "3.10.11" @@ -3385,6 +3980,20 @@ nodeenv = ">=0.11.1" pyyaml = ">=5.1" virtualenv = ">=20.10.0" +[[package]] +name = "prompt-toolkit" +version = "3.0.48" +description = "Library for building powerful interactive command lines in Python" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "prompt_toolkit-3.0.48-py3-none-any.whl", hash = "sha256:f49a827f90062e411f1ce1f854f2aedb3c23353244f8108b89283587397ac10e"}, + {file = "prompt_toolkit-3.0.48.tar.gz", hash = "sha256:d6623ab0477a80df74e646bdbc93621143f5caf104206aa29294d53de1a03d90"}, +] + +[package.dependencies] +wcwidth = "*" + [[package]] name = "propcache" version = "0.2.0" @@ -3492,6 +4101,26 @@ files = [ {file = "propcache-0.2.0.tar.gz", hash = "sha256:df81779732feb9d01e5d513fad0122efb3d53bbc75f61b2a4f29a020bc985e70"}, ] +[[package]] +name = "protobuf" +version = "4.25.5" +description = "" +optional = false +python-versions = ">=3.8" +files = [ + {file = "protobuf-4.25.5-cp310-abi3-win32.whl", hash = "sha256:5e61fd921603f58d2f5acb2806a929b4675f8874ff5f330b7d6f7e2e784bbcd8"}, + {file = "protobuf-4.25.5-cp310-abi3-win_amd64.whl", hash = "sha256:4be0571adcbe712b282a330c6e89eae24281344429ae95c6d85e79e84780f5ea"}, + {file = "protobuf-4.25.5-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:b2fde3d805354df675ea4c7c6338c1aecd254dfc9925e88c6d31a2bcb97eb173"}, + {file = "protobuf-4.25.5-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:919ad92d9b0310070f8356c24b855c98df2b8bd207ebc1c0c6fcc9ab1e007f3d"}, + {file = "protobuf-4.25.5-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:fe14e16c22be926d3abfcb500e60cab068baf10b542b8c858fa27e098123e331"}, + {file = "protobuf-4.25.5-cp38-cp38-win32.whl", hash = "sha256:98d8d8aa50de6a2747efd9cceba361c9034050ecce3e09136f90de37ddba66e1"}, + {file = "protobuf-4.25.5-cp38-cp38-win_amd64.whl", hash = "sha256:b0234dd5a03049e4ddd94b93400b67803c823cfc405689688f59b34e0742381a"}, + {file = "protobuf-4.25.5-cp39-cp39-win32.whl", hash = "sha256:abe32aad8561aa7cc94fc7ba4fdef646e576983edb94a73381b03c53728a626f"}, + {file = "protobuf-4.25.5-cp39-cp39-win_amd64.whl", hash = "sha256:7a183f592dc80aa7c8da7ad9e55091c4ffc9497b3054452d629bb85fa27c2a45"}, + {file = "protobuf-4.25.5-py3-none-any.whl", hash = "sha256:0aebecb809cae990f8129ada5ca273d9d670b76d9bfc9b1809f0a9c02b7dbf41"}, + {file = "protobuf-4.25.5.tar.gz", hash = "sha256:7f8249476b4a9473645db7f8ab42b02fe1488cbe5fb72fddd445e0665afd8584"}, +] + [[package]] name = "psycopg2-binary" version = "2.9.10" @@ -4271,6 +4900,24 @@ requests = ">=2.22,<3" [package.extras] fixture = ["fixtures"] +[[package]] +name = "requests-oauthlib" +version = "2.0.0" +description = "OAuthlib authentication support for Requests." +optional = false +python-versions = ">=3.4" +files = [ + {file = "requests-oauthlib-2.0.0.tar.gz", hash = "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9"}, + {file = "requests_oauthlib-2.0.0-py2.py3-none-any.whl", hash = "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36"}, +] + +[package.dependencies] +oauthlib = ">=3.0.0" +requests = ">=2.0.0" + +[package.extras] +rsa = ["oauthlib[signedtoken] (>=3.0.0)"] + [[package]] name = "requests-toolbelt" version = "1.0.0" @@ -5180,6 +5827,17 @@ h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] +[[package]] +name = "vine" +version = "5.1.0" +description = "Python promises." +optional = false +python-versions = ">=3.6" +files = [ + {file = "vine-5.1.0-py3-none-any.whl", hash = "sha256:40fdf3c48b2cfe1c38a49e9ae2da6fda88e4794c810050a728bd7413811fb1dc"}, + {file = "vine-5.1.0.tar.gz", hash = "sha256:8b62e981d35c41049211cf62a0a1242d8c1ee9bd15bb196ce38aefd6799e61e0"}, +] + [[package]] name = "virtualenv" version = "20.27.1" @@ -5562,6 +6220,25 @@ idna = ">=2.0" multidict = ">=4.0" propcache = ">=0.2.0" +[[package]] +name = "zipp" +version = "3.21.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.9" +files = [ + {file = "zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931"}, + {file = "zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4"}, +] + +[package.extras] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] +cover = ["pytest-cov"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +enabler = ["pytest-enabler (>=2.2)"] +test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] +type = ["pytest-mypy"] + [[package]] name = "zope-event" version = "5.0" @@ -5637,4 +6314,4 @@ testing = ["coverage[toml]", "zope.event", "zope.testing"] [metadata] lock-version = "2.0" python-versions = ">=3.12,<3.13" -content-hash = "8d4609dca19fbed4cafdbefd3bd83768b5156d9dc765a807a33ce21be31c08b3" +content-hash = "88988127b70f28820042586a4d537cd14d5d33375552238051a41e37f5883c79" diff --git a/django_app/pyproject.toml b/django_app/pyproject.toml index 46172d6f0..f82c45773 100644 --- a/django_app/pyproject.toml +++ b/django_app/pyproject.toml @@ -45,6 +45,10 @@ pandas = "^2.2.2" django-waffle = "^4.1.0" opensearch-py = "^2.7.1" scikit-learn = "^1.5.2" +django-staff-sso-client = "^4.3.0" +dj-database-url = "^2.3.0" +dbt-copilot-python = "^0.2.2" +django-log-formatter-asim = "^0.0.6" [tool.poetry.group.dev.dependencies] pytest = "^8.3.2" diff --git a/django_app/redbox_app/redbox_core/migrations/0057_citation_text_in_answer.py b/django_app/redbox_app/redbox_core/migrations/0057_citation_text_in_answer.py index f5d9f3604..100915894 100644 --- a/django_app/redbox_app/redbox_core/migrations/0057_citation_text_in_answer.py +++ b/django_app/redbox_app/redbox_core/migrations/0057_citation_text_in_answer.py @@ -10,9 +10,9 @@ class Migration(migrations.Migration): ] operations = [ - migrations.AddField( - model_name='citation', - name='text_in_answer', - field=models.TextField(blank=True, null=True), - ), + # migrations.AddField( + # model_name='citation', + # name='text_in_answer', + # field=models.TextField(blank=True, null=True), + # ), ] diff --git a/django_app/redbox_app/redbox_core/migrations/0061_alter_citation_text_in_answer.py b/django_app/redbox_app/redbox_core/migrations/0061_alter_citation_text_in_answer.py index b0b35c263..50304fada 100644 --- a/django_app/redbox_app/redbox_core/migrations/0061_alter_citation_text_in_answer.py +++ b/django_app/redbox_app/redbox_core/migrations/0061_alter_citation_text_in_answer.py @@ -10,9 +10,9 @@ class Migration(migrations.Migration): ] operations = [ - migrations.AlterField( - model_name='citation', - name='text_in_answer', - field=models.TextField(blank=True, help_text='the part of the answer the citation refers too - useful for adding in footnotes', null=True), - ), + # migrations.AlterField( + # model_name='citation', + # name='text_in_answer', + # field=models.TextField(blank=True, help_text='the part of the answer the citation refers too - useful for adding in footnotes', null=True), + # ), ] diff --git a/django_app/redbox_app/redbox_core/migrations/0070_alter_user_options_alter_user_managers_and_more.py b/django_app/redbox_app/redbox_core/migrations/0070_alter_user_options_alter_user_managers_and_more.py new file mode 100644 index 000000000..5f5ab8952 --- /dev/null +++ b/django_app/redbox_app/redbox_core/migrations/0070_alter_user_options_alter_user_managers_and_more.py @@ -0,0 +1,26 @@ +# Generated by Django 5.1.3 on 2024-11-26 14:01 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("redbox_core", "0069_alter_citation_source"), + ] + + operations = [ + migrations.AlterModelOptions( + name="user", + options={"verbose_name": "user", "verbose_name_plural": "users"}, + ), + migrations.AlterModelManagers( + name="user", + managers=[], + ), + migrations.AlterField( + model_name="user", + name="email", + field=models.EmailField(max_length=254, unique=True), + ), + ] diff --git a/django_app/redbox_app/redbox_core/migrations/0071_create_username_field.py b/django_app/redbox_app/redbox_core/migrations/0071_create_username_field.py new file mode 100644 index 000000000..177792cb3 --- /dev/null +++ b/django_app/redbox_app/redbox_core/migrations/0071_create_username_field.py @@ -0,0 +1,21 @@ +# Custom generated migration will need to be amended for contribution back to i.ai + +import redbox_app.redbox_core.models +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("redbox_core", "0070_alter_user_options_alter_user_managers_and_more"), + ] + + operations = [ + migrations.AddField( + model_name="user", + name="username", + field=models.EmailField( + max_length=254, null=True + ), + ), + ] diff --git a/django_app/redbox_app/redbox_core/migrations/0072_populate_username_values.py b/django_app/redbox_app/redbox_core/migrations/0072_populate_username_values.py new file mode 100644 index 000000000..ab354925a --- /dev/null +++ b/django_app/redbox_app/redbox_core/migrations/0072_populate_username_values.py @@ -0,0 +1,28 @@ +# Custom generated migration will need to be amended for contribution back to i.ai + +import redbox_app.redbox_core.models +from django.db import migrations, models + + +# Custom generated migration will need to be amended for contribution back to i.ai + +import logging +logger = logging.getLogger(__name__) + + +def populate_existing_users_username(apps, schema_editor): + users = redbox_app.redbox_core.models.User.objects.all() + + for user in users: + user.username = user.email + user.save(update_fields=["username"]) + +class Migration(migrations.Migration): + + dependencies = [ + ("redbox_core", "0071_create_username_field"), + ] + + operations = [ + migrations.RunPython(populate_existing_users_username, reverse_code=migrations.RunPython.noop), + ] diff --git a/django_app/redbox_app/redbox_core/migrations/0073_alter_user_options_alter_user_managers_and_more.py b/django_app/redbox_app/redbox_core/migrations/0073_alter_user_options_alter_user_managers_and_more.py new file mode 100644 index 000000000..6a5b4b920 --- /dev/null +++ b/django_app/redbox_app/redbox_core/migrations/0073_alter_user_options_alter_user_managers_and_more.py @@ -0,0 +1,79 @@ +# Generated by Django 5.1.3 on 2024-11-27 11:09 + +import redbox_app.redbox_core.models +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("auth", "0012_alter_user_first_name_max_length"), + ("redbox_core", "0072_populate_username_values"), + ] + + operations = [ + migrations.AlterField( + model_name="user", + name="username", + field=models.EmailField( + max_length=254, unique=True, default="default@default.com" + ), + ), + migrations.AlterModelOptions( + name="user", + options={}, + ), + migrations.AlterModelManagers( + name="user", + managers=[ + ("objects", redbox_app.redbox_core.models.SSOUserManager()), + ], + ), + migrations.RemoveField( + model_name="user", + name="date_joined", + ), + migrations.RemoveField( + model_name="user", + name="first_name", + ), + migrations.RemoveField( + model_name="user", + name="last_name", + ), + migrations.AlterField( + model_name="user", + name="groups", + field=models.ManyToManyField( + blank=True, + related_name="sso_user_set", + to="auth.group", + verbose_name="groups", + ), + ), + migrations.AlterField( + model_name="user", + name="is_active", + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name="user", + name="is_staff", + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name="user", + name="is_superuser", + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name="user", + name="user_permissions", + field=models.ManyToManyField( + blank=True, + related_name="sso_user_set", + to="auth.permission", + verbose_name="user permissions", + ), + ), + ] diff --git a/django_app/redbox_app/redbox_core/migrations/0074_citation_text_in_answer_user_first_name_and_more.py b/django_app/redbox_app/redbox_core/migrations/0074_citation_text_in_answer_user_first_name_and_more.py new file mode 100644 index 000000000..a307071ed --- /dev/null +++ b/django_app/redbox_app/redbox_core/migrations/0074_citation_text_in_answer_user_first_name_and_more.py @@ -0,0 +1,25 @@ +# Generated by Django 5.1.3 on 2024-11-27 13:58 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("redbox_core", "0073_alter_user_options_alter_user_managers_and_more"), + ] + + operations = [ + migrations.AddField( + model_name="user", + name="first_name", + field=models.CharField(default="default", max_length=48), + preserve_default=False, + ), + migrations.AddField( + model_name="user", + name="last_name", + field=models.CharField(default="default", max_length=48), + preserve_default=False, + ), + ] diff --git a/django_app/redbox_app/redbox_core/models.py b/django_app/redbox_app/redbox_core/models.py index 176adc1fe..515a0a978 100644 --- a/django_app/redbox_app/redbox_core/models.py +++ b/django_app/redbox_app/redbox_core/models.py @@ -15,7 +15,8 @@ from django.db.models import Max, Min, Prefetch, UniqueConstraint from django.utils import timezone from django.utils.translation import gettext_lazy as _ -from django_use_email_as_username.models import BaseUser, BaseUserManager +# from django_use_email_as_username.models import BaseUser, BaseUserManager +from django.contrib.auth.models import AbstractBaseUser, Group, PermissionsMixin from yarl import URL from redbox.models.settings import get_settings @@ -185,17 +186,16 @@ def __str__(self) -> str: class SSOUserManager(BaseSSOUserManager): use_in_migrations = True - def _create_user(self, username, password, **extra_fields): """Create and save a User with the given email and password.""" if not username: - msg = "The given email must be set." - raise ValueError(msg) - user = self.model(email=username, **extra_fields) - user.set_password(password) - user.save(using=self._db) + raise ValueError("The given email must be set") + # email = self.normalize_email(email) + User = self.model(email=username, **extra_fields) + User.set_password(password) + User.save(using=self._db) return User - + def create_user(self, username, password=None, **extra_fields): """Create and save a regular User with the given email and password.""" extra_fields.setdefault("is_staff", False) @@ -208,16 +208,14 @@ def create_superuser(self, username, password=None, **extra_fields): extra_fields.setdefault("is_superuser", True) if extra_fields.get("is_staff") is not True: - msg = "Superuser must have is_staff=True." - raise ValueError(msg) + raise ValueError("Superuser must have is_staff=True.") if extra_fields.get("is_superuser") is not True: - msg = "Superuser must have is_superuser=True." - raise ValueError(msg) + raise ValueError("Superuser must have is_superuser=True.") return self._create_user(username, password, **extra_fields) -class User(BaseUser, UUIDPrimaryKeyBase): +class User(AbstractBaseUser, PermissionsMixin, UUIDPrimaryKeyBase): class UserGrade(models.TextChoices): AA = "AA", _("AA") AO = "AO", _("AO") @@ -435,11 +433,17 @@ class DurationTasks(models.TextChoices): MORE_THAN_2_DAYS = "More than 2 days", _("More than 2 days") MORE_THAN_1_WEEK = "More than a week", _("More than a week") - username = None + username = models.EmailField(unique=True, default="default@default.com") + email = models.EmailField(unique=True) password = models.CharField("password", max_length=128, blank=True, null=True) + first_name = models.CharField(max_length=48) + last_name = models.CharField(max_length=48) business_unit = models.CharField(null=True, blank=True, max_length=64, choices=BusinessUnit) grade = models.CharField(null=True, blank=True, max_length=3, choices=UserGrade) name = models.CharField(null=True, blank=True) + is_staff = models.BooleanField(default=False) + is_active = models.BooleanField(default=True) + is_superuser = models.BooleanField(default=False) ai_experience = models.CharField(null=True, blank=True, max_length=25, choices=AIExperienceLevel) profession = models.CharField(null=True, blank=True, max_length=4, choices=Profession) info_about_user = models.CharField(null=True, blank=True, help_text="user entered info from profile overlay") @@ -506,7 +510,21 @@ class DurationTasks(models.TextChoices): consent_understand = models.BooleanField(null=True, blank=True, default=False) consent_agreement = models.BooleanField(null=True, blank=True, default=False) - objects = BaseUserManager() + user_permissions = models.ManyToManyField( + "auth.Permission", + verbose_name="user permissions", + blank=True, + related_name="sso_user_set", + ) + groups = models.ManyToManyField( + Group, verbose_name="groups", blank=True, related_name="sso_user_set" + ) + + USERNAME_FIELD = 'username' + + REQUIRED_FIELDS = [] + + objects = SSOUserManager() def __str__(self) -> str: # pragma: no cover return f"{self.email}" @@ -880,7 +898,7 @@ def log(self): es_client.create( index=env.elastic_chat_mesage_index, id=uuid.uuid4(), - document=elastic_log_msg, + body=elastic_log_msg, ) def unique_citation_uris(self) -> list[tuple[str, str]]: diff --git a/django_app/redbox_app/redbox_core/views/signup_views.py b/django_app/redbox_app/redbox_core/views/signup_views.py index fdff0aad0..f87d739d4 100644 --- a/django_app/redbox_app/redbox_core/views/signup_views.py +++ b/django_app/redbox_app/redbox_core/views/signup_views.py @@ -104,7 +104,7 @@ def post(self, request: HttpRequest) -> HttpResponse: form.add_error(field, "You must give consent in order to sign up to Redbox") if form.is_valid(): - user = User.objects.create_user(email=request.session["sign_up_data"]["email"]) + user = User.objects.create_user(username=request.session["sign_up_data"]["email"]) #change arg from email to username for field_name, field_value in form.cleaned_data.items(): setattr(user, field_name, field_value) user.save() diff --git a/django_app/redbox_app/setting_enums.py b/django_app/redbox_app/setting_enums.py index 7b7b2d129..6bc271329 100644 --- a/django_app/redbox_app/setting_enums.py +++ b/django_app/redbox_app/setting_enums.py @@ -23,7 +23,7 @@ def uses_minio(self) -> bool: LOCAL = ("LOCAL", True, [*LOCAL_HOSTS, *ADDITIONAL_HOSTS]) # nosec: B104: Not in prod INTEGRATION = ("INTEGRATION", True, [*LOCAL_HOSTS, *ADDITIONAL_HOSTS]) # nosec: B104: Not in prod - DEV = ("DEV", False, ["redbox-dev.ai.cabinetoffice.gov.uk", *ADDITIONAL_HOSTS]) + DEV = ("DEV", False, ["dev.redbox.uktrade.digital", *ADDITIONAL_HOSTS]) PREPROD = ("PREPROD", False, ["redbox-preprod.ai.cabinetoffice.gov.uk", *ADDITIONAL_HOSTS]) PROD = ("PROD", False, ["redbox.ai.cabinetoffice.gov.uk", *ADDITIONAL_HOSTS]) diff --git a/django_app/redbox_app/settings.py b/django_app/redbox_app/settings.py index cad964356..db6fd5af1 100644 --- a/django_app/redbox_app/settings.py +++ b/django_app/redbox_app/settings.py @@ -1,13 +1,16 @@ # mypy: ignore-errors import logging import os +import json import socket from pathlib import Path from urllib.parse import urlparse import environ import sentry_sdk +from dbt_copilot_python.database import database_from_env from django.urls import reverse_lazy +from django_log_formatter_asim import ASIMFormatter from dotenv import load_dotenv from import_export.formats.base_formats import CSV from sentry_sdk.integrations.django import DjangoIntegration @@ -161,6 +164,7 @@ ACCOUNT_EMAIL_VERIFICATION = "none" if LOGIN_METHOD == "sso": + # os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1' #TO REMOVE AUTHBROKER_URL = env.str("AUTHBROKER_URL") AUTHBROKER_CLIENT_ID = env.str("AUTHBROKER_CLIENT_ID") AUTHBROKER_CLIENT_SECRET = env.str("AUTHBROKER_CLIENT_SECRET") @@ -187,6 +191,7 @@ "plausible.io", "eu.i.posthog.com", "eu-assets.i.posthog.com", + "'sha256-qmCu1kQifDfCnUd+L49nusp7+PeRl23639pzN5QF2WA='", ) CSP_OBJECT_SRC = ("'none'",) CSP_REQUIRE_TRUSTED_TYPES_FOR = ("'script'",) @@ -275,7 +280,7 @@ ALLOWED_HOSTS = ENVIRONMENT.hosts else: LOCALHOST = socket.gethostbyname(socket.gethostname()) - ALLOWED_HOSTS = [LOCALHOST, *ENVIRONMENT.hosts] + ALLOWED_HOSTS = ["*"] if not ENVIRONMENT.is_local: @@ -302,28 +307,40 @@ def filter_transactions(event): ) SENTRY_REPORT_TO_ENDPOINT = URL(env.str("SENTRY_REPORT_TO_ENDPOINT", "")) or None -DATABASES = { - "default": { - "ENGINE": "django.db.backends.postgresql", - "NAME": env.str("POSTGRES_DB"), - "USER": env.str("POSTGRES_USER"), - "PASSWORD": env.str("POSTGRES_PASSWORD"), - "HOST": env.str("POSTGRES_HOST"), - "PORT": "5432", +database_credentials = os.getenv("DATABASE_CREDENTIALS") +if database_credentials: + DATABASES = database_from_env("DATABASE_CREDENTIALS") + DATABASES["default"]["ENGINE"] = "django.db.backends.postgresql" + +else: + DATABASES = { + "default": { + "ENGINE": "django.db.backends.postgresql", + "NAME": env.str("POSTGRES_DB"), + "USER": env.str("POSTGRES_USER"), + "PASSWORD": env.str("POSTGRES_PASSWORD"), + "HOST": env.str("POSTGRES_HOST"), + "PORT": "5432", + } } -} LOG_LEVEL = env.str("DJANGO_LOG_LEVEL", "WARNING") +LOG_FORMAT = env.str("DJANGO_LOG_FORMAT", "verbose") LOGGING = { "version": 1, "disable_existing_loggers": False, - "formatters": {"verbose": {"format": "%(asctime)s %(levelname)s %(module)s: %(message)s"}}, + "formatters": { + "verbose": {"format": "%(asctime)s %(levelname)s %(module)s: %(message)s"}, + "asim_formatter": { + "()": ASIMFormatter, + }, + }, "handlers": { "console": { "level": LOG_LEVEL, "class": "logging.StreamHandler", - "formatter": "verbose", - }, + "formatter": LOG_FORMAT, + } }, "root": {"handlers": ["console"], "level": LOG_LEVEL}, "loggers": { @@ -392,3 +409,4 @@ def filter_transactions(event): GOOGLE_ANALYTICS_TAG = env.str("GOOGLE_ANALYTICS_TAG", " ") GOOGLE_ANALYTICS_LINK = env.str("GOOGLE_ANALYTICS_LINK", " ") +# TEST_SSO_PROVIDER_SET_RETURNED_ACCESS_TOKEN = 'someCode' diff --git a/django_app/redbox_app/templates/base.html b/django_app/redbox_app/templates/base.html index 9a6fc2efb..c5519fc18 100644 --- a/django_app/redbox_app/templates/base.html +++ b/django_app/redbox_app/templates/base.html @@ -20,10 +20,10 @@ {% if environment | lower in ["dev", "preprod"] %} + data-domain="dev.redbox.uktrade.digital" src="https://plausible.io/js/script.pageview-props.tagged-events.outbound-links.file-downloads.local.js"> {% elif environment | lower == "prod" %} + data-domain="dev.redbox.uktrade.digital" src="https://plausible.io/js/script.pageview-props.tagged-events.outbound-links.file-downloads.js"> {% endif %} {% if environment | lower == "prod" and waffle_flag(request, 'uktrade') %} @@ -48,7 +48,11 @@ - + + Skip to main content {% if environment | lower != "prod" %} diff --git a/django_app/redbox_app/templates/documents.html b/django_app/redbox_app/templates/documents.html index 8e8b603f4..193a72603 100644 --- a/django_app/redbox_app/templates/documents.html +++ b/django_app/redbox_app/templates/documents.html @@ -73,7 +73,7 @@

Processing

-

You have documents that failed to process. Please try again, and if the problem persists contact redbox-support@cabinetoffice.gov.uk with details.

+

You have documents that failed to process. Please try again, and if the problem persists contact redbox@businessandtrade.gov.uk with details.

diff --git a/django_app/redbox_app/templates/homepage.html b/django_app/redbox_app/templates/homepage.html index f447f1539..20301c8f9 100644 --- a/django_app/redbox_app/templates/homepage.html +++ b/django_app/redbox_app/templates/homepage.html @@ -60,4 +60,195 @@

Secure +
+
+
+
+

Frequently Asked Questions

+

Responses to these FAQs about Redbox were generated using Redbox.

+
+
+
+
+
+

+ + What is Redbox? + +

+
+
+

+ Redbox is a new kind of tool for civil servants which uses Large Language Models (LLMs) to process text-based information. + Redbox is currently only available to a small number of DBT staff as the department assesses its usefulness. +

+

+ What makes Redbox particularly useful is that it can look at any documents you upload and work with you on them. +

+
+
+
+
+

+ + What is Generative AI? + +

+
+
+

+ Generative AI is a fairly new kind of algorithmic machine learning based on 'neural architecture' This architecture allows + machine learning models (called large language models in this case) to be trained on large amounts of information, and then + be able to converse with a user by 'generating' answers to questions or assisting with text-based processing tasks. +

+
+
+
+
+

+ + Do I need technical skills to use Redbox? + +

+
+
+

+ Not at all, the interface for Redbox comprises a document upload feature and a chat feature. No technical skills are required, + but an understanding of what large language models are and what they can do makes an enormous different to users when interacting + with them. The principal skill to use Redbox well comes down to a skill called 'prompt engineering', which is just natural language + you type in and get the tool to respond. There are some great Gov.uk short courses on generative AI you may consider taking: + See the courses here. +

+
+
+
+
+

+ + What can I and can’t I share with Redbox? + +

+
+
+

+ For the moment, you can share text and documents up to the {{ security }} classification level. Take care to check before sharing + text or documents with Redbox that they do not exceed this designation. +

+

+ Alongside this, do not share Personal Data with Redbox, for more information on what constitutes personal data, watch this short + video. If + you are unsure whether you are processing personal data, you should contact the Data Protection Team + to check. +

+
+
+
+
+

+ + What is a ‘hallucination’? + +

+
+
+

+ In the context of LLMs, a hallucination refers to the generation of information that is incorrect, nonsensical, or entirely fabricated, despite + being presented in a credible manner. This can happen when the model produces details, facts, or asserts that are not grounded in reality or the + data it was trained on, potentialliy leading to misinformation or misunderstanding. +

+
+
+
+
+

+ + What are the main things Redbox can do? + +

+
+
+

+ Redbox allows you to chat to a LLM, summarise and interact with documents (up to around 140 pages), and even search within documents. Here are some + helpful insights into those: +

+

Chat

+

+ By using @chat at the beginning of any message you send, you will speak directly with the LLM, gaining access to its 'world model', which is everything + it was trained on. +

+
+

+ Top tip: when you chat with the LLM, all the contents of your current chat are considered by the LLM, and you can switch between chat and other interaction + types (more below) in the same chat. +

+
+

Summarise

+

+ By using @summarise at the beginning of any message you send, and ensuring that a document is selected in the left hand panel, you can get the LLM to + look at an entire document and summarise it for you. +

+
+

+ Top tip: like using @chat, using the @summarise feature is very flexible, and you can instruct the LLM to summarise from a particular point of view, or + follow a particular kind of format in its response. Here's an example prompt - imagine you have selected an HR Policy document on taking leave at DBT:

+ @summarise this HR policy from the perspective of a line manager, as my line report has asked to take extended leave and I want to know what steps I need to take.

+ In this example, Redbox will take those instructions into account and generate a response that best fits your requirements. +

+
+

Search

+

+ By using @search at the beginning of any message you send, with any number of documents selected in the side panel, Redbox will search within them + for results that relate to the question or instruction given. +

+
+

+ Top tip: Search is great at finding exact parts of documents which relate to a given theme or topic, and the results will also show you the exact + text it found from the documents os you can be sure of accuracy. +

+
+
+
+
+
+

+ + What can’t Redbox do? + +

+
+
+

+ Redbox is limited to its own training data and document processing, as it cannot currently search the internet, making it inadequate for getting reliable real-time information. +

+

+ Redbox is not well-suited for tasks that involve precise numerical calculations, counting, or data tabulation, such as those often required in spreadsheets or financial analyses. They + may generate incorrect numerical results or misinterpret mathematical expressions, leading to unrealiable outputs. Additionally, Redbox struggles with organising and + manipulating structured data effectively, as it is primarily designed for language generation rather than data processing. +

+

+ This can make Redbox inadequate for tasks requiring accurate data comparison, aggregation, and spreadsheet functions, where human oversight and intervention remain essential + for ensuring accuracy and reliability. +

+
+
+
+
+

+ + Why can Redbox get things wrong? + +

+
+
+

+ Redbox can get things wrong for several reasons, primarily due to its reliance on patterns found in the training data of the LLM rather than true understanding or + reasoning. Redbox may generate inaccurate information because they lack context awareness, leading to misinterpretations, especially in complex or nuanced scenarios. + Additionally, biases inherent in the LLM training data can result in the propagation of errors, stereotypes, or nonsensical outputs, further compromising the accuracy of Redbox' responses. + For more information, read the FAQ section on 'hallucinations' above. +

+
+
+
+
+ {% endblock %} diff --git a/django_app/redbox_app/templates/privacy-notice.html b/django_app/redbox_app/templates/privacy-notice.html index 46023ab06..ac2584e4f 100644 --- a/django_app/redbox_app/templates/privacy-notice.html +++ b/django_app/redbox_app/templates/privacy-notice.html @@ -24,20 +24,21 @@

Privacy notice for Redbox

Your data

Purpose

The purposes for which we are processing your personal data are:

-