karrrr123456 commited on
Commit
6e593bb
·
verified ·
1 Parent(s): d197885

Upload 1140 files

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +1 -0
  2. AI/.coveragerc +12 -0
  3. AI/.deepsource.toml +12 -0
  4. AI/.devcontainer/Dockerfile +27 -0
  5. AI/.devcontainer/devcontacener.json +50 -0
  6. AI/.devcontainer/docker-compose.yml +57 -0
  7. AI/.dockerignore +11 -0
  8. AI/.env +1 -0
  9. AI/.gitattributes +35 -0
  10. AI/.github/ISSUE_TEMPLATE.md +2 -0
  11. AI/.github/ISSUE_TEMPLATE/bug_report.md +34 -0
  12. AI/.github/ISSUE_TEMPLATE/config.yml +11 -0
  13. AI/.github/PULL_REQUEST_AUTOMATIC_TEMPLATE.md +10 -0
  14. AI/.github/PULL_REQUEST_TEMPLATE.md +8 -0
  15. AI/.github/change_filters.yml +28 -0
  16. AI/.github/configs/mr-test-example.yaml +49 -0
  17. AI/.github/configs/mr-test-schedule.json +3 -0
  18. AI/.github/configs/tf-cuda.json +25 -0
  19. AI/.github/dependabot.yml +34 -0
  20. AI/.github/matchers/flake8-error-matcher.json +17 -0
  21. AI/.github/no-response.yml +12 -0
  22. AI/.github/poetry_version.txt +2 -0
  23. AI/.github/runner/github-runner-deployment.yaml.tmpl +74 -0
  24. AI/.github/scripts/download_pretrained.py +120 -0
  25. AI/.github/scripts/mr_generate_summary.py +55 -0
  26. AI/.github/scripts/mr_publish_results.py +293 -0
  27. AI/.github/scripts/start_dd_agent.sh +79 -0
  28. AI/.github/scripts/validate_cpu.py +14 -0
  29. AI/.github/scripts/validate_gpus.py +14 -0
  30. AI/.github/stale.yml +18 -0
  31. AI/.github/templates/README.md +63 -0
  32. AI/.github/templates/configuration_variables.tmpl +43 -0
  33. AI/.github/templates/model_regression_test_config_comment.tmpl +45 -0
  34. AI/.github/templates/model_regression_test_config_to_json.tmpl +71 -0
  35. AI/.github/templates/model_regression_test_read_dataset_branch.tmpl +13 -0
  36. AI/.github/templates/model_regression_test_results.tmpl +159 -0
  37. AI/.github/tests/test_data/bert_diet_response2t.yml +23 -0
  38. AI/.github/tests/test_data/comment_body.json +3 -0
  39. AI/.github/tests/test_data/comment_body_no_dataset_branch.json +3 -0
  40. AI/.github/tests/test_data/intent_report.json +120 -0
  41. AI/.github/tests/test_data/report-on-schedule-2022-02-02.json +303 -0
  42. AI/.github/tests/test_data/report_listformat_core.json +70 -0
  43. AI/.github/tests/test_data/report_listformat_nlu.json +98 -0
  44. AI/.github/tests/test_download_pretrained.py +111 -0
  45. AI/.github/tests/test_model_regression_test_read_dataset_branch_tmpl.py +27 -0
  46. AI/.github/tests/test_model_regression_test_results_tmpl.py +50 -0
  47. AI/.github/tests/test_mr_generate_summary.py +208 -0
  48. AI/.github/tests/test_mr_publish_results.py +132 -0
  49. AI/.github/tests/test_validate_gpus.py +27 -0
  50. AI/.github/workflows/automatic-pr-update.yml +22 -0
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ AI/docs/docs/llms/llm-IntentClassifier-docs.jpg filter=lfs diff=lfs merge=lfs -text
AI/.coveragerc ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [report]
2
+ exclude_lines =
3
+ pragma: no cover
4
+ def __repr__
5
+ raise NotImplementedError
6
+ if __name__ == .__main__.:
7
+ def create_argument_parser
8
+ if typing.TYPE_CHECKING
9
+ # Ellipsis are used as placeholders in python 3 that will be overridden
10
+ \.\.\.
11
+ [run]
12
+ source = rasa
AI/.deepsource.toml ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version = 1
2
+
3
+ test_patterns = ["tests/**"]
4
+
5
+ exclude_patterns = ["docs/**"]
6
+
7
+ [[analyzers]]
8
+ name = "python"
9
+ enabled = true
10
+
11
+ [analyzers.meta]
12
+ runtime_version = "3.x.x"
AI/.devcontainer/Dockerfile ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # [Choice] Python version (use -bullseye variants on local arm64/Apple Silicon): 3, 3.10, 3.9, 3.8, 3.7, 3.6, 3-bullseye, 3.10-bullseye, 3.9-bullseye, 3.8-bullseye, 3.7-bullseye, 3.6-bullseye, 3-buster, 3.10-buster, 3.9-buster, 3.8-buster, 3.7-buster, 3.6-buster
2
+ ARG VARIANT=3-bullseye
3
+ FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT}
4
+
5
+ ENV PYTHONFAULTHANDLER=1 \
6
+ PYTHONUNBUFFERED=1 \
7
+ PYTHONHASHSEED=random \
8
+ PIP_NO_CACHE_DIR=off \
9
+ PIP_DISABLE_PIP_VERSION_CHECK=on \
10
+ PIP_DEFAULT_TIMEOUT=100
11
+
12
+ # [Choice] Node.js version: none, lts/*, 16, 14, 12, 10
13
+ ARG NODE_VERSION="none"
14
+ RUN if [ "${NODE_VERSION}" != "nne" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi
15
+
16
+ # [Optional] If your requirements rarely change, uncomment this section to add them to the image.
17
+ # COPY requirements.txt /tmp/pip-tmp/
18
+ # RUN pip3 --disable-pip-version-check --no-cache-dir install -r /tmp/pip-tmp/requirements.txt \
19
+ # && rm -rf /tmp/pip-tmp
20
+ RUN pip install poetry==1.1.10 pre-commit
21
+ COPY ../poetry.lock ../pyproject.toml /tmp/pip-tmp/rasa/
22
+ RUN cd /tmp/pip-tmp/rasa && poetry config virtualenvs.create false \
23
+ && poetry install --no-interaction --no-ansi --no-root
24
+
25
+ # [Optional] Uncomment this section to install additional OS packages.
26
+ # RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
27
+ # && apt-get -y install --no-install-recommends <your-package-list-here>
AI/.devcontainer/devcontacener.json ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
2
+ // https://github.com/microsoft/vscode-dev-containers/tree/v0.233.0/containers/python-3-postgres
3
+ // Update the VARIANT arg in docker-compose.yml to pick a Python version
4
+ {
5
+ "name": "Rasa Open Source",
6
+ "dockerComposeFile": "docker-compose.yml",
7
+ "service": "app",
8
+ "workspaceFolder": "/workspaces/rasa",
9
+ // Set *default* container specific settings.json values on container create.
10
+ "settings": {
11
+ "python.defaultInterpreterPath": "/usr/local/bin/python",
12
+ "python.linting.enabled": true,
13
+ "python.linting.pylintEnabled": true,
14
+ "python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8",
15
+ "python.formatting.blackPath": "/usr/local/py-utils/bin/black",
16
+ "python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf",
17
+ "python.linting.banditPath": "/usr/local/py-utils/bin/bandit",
18
+ "python.linting.ruffPath": "/usr/local/py-utils/bin/ruff",
19
+ "python.linting.mypyPath": "/usr/local/py-utils/bin/mypy",
20
+ "python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle",
21
+ "python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle",
22
+ "python.linting.pylintPath": "/usr/local/py-utils/bin/pylint",
23
+ "python.testing.pytestPath": "/usr/local/py-utils/bin/pytest"
24
+ },
25
+ // Add the IDs of extensions you want installed when the container is created.
26
+ "extensions": [
27
+ "ms-python.python",
28
+ "ms-python.vscode-pylance"
29
+ ],
30
+ // memory is required for frontend build...fails for machines with less than 10g
31
+ // "hostRequirements": {
32
+ // "memory": "12gb"
33
+ // },
34
+ // Use 'forwardPorts' to make a list of ports inside the container available locally.
35
+ // This can be used to network with other containers or the host.
36
+ "forwardPorts": [
37
+ 5005
38
+ ],
39
+ // Use 'postCreateCommand' to run commands after the container is created.
40
+ "updateContentCommand": "make install && make install-docs && cd / && mkdir example && rasa init --no-prompt --init-dir example",
41
+ // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
42
+ //"remoteUser": "vscode",
43
+ "features": {
44
+ "docker-in-docker": "20.10",
45
+ "docker-from-docker": "20.10",
46
+ "git": "os-provided",
47
+ "github-cli": "latest",
48
+ "sshd": "latest"
49
+ }
50
+ }
AI/.devcontainer/docker-compose.yml ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ app:
5
+ build:
6
+ context: ..
7
+ dockerfile: .devcontainer/Dockerfile
8
+ args:
9
+ # Update 'VARIANT' to pick a version of Python: 3, 3.10, 3.9, 3.8, 3.7, 3.6
10
+ # Append -bullseye or -buster to pin to an OS version.
11
+ # Use -bullseye variants on local arm64/Apple Silicon.
12
+ VARIANT: "3.8"
13
+ # Optional Node.js version to install
14
+ NODE_VERSION: "16"
15
+ environment:
16
+ DB_DRIVER: "postgresql"
17
+ DB_USER: "admin"
18
+ DB_PASSWORD: "postgres"
19
+
20
+ volumes:
21
+ - ..:/workspaces/rasa:cached
22
+
23
+ # Overrides default command so things don't shut down after the process ends.
24
+ command: sleep infinity
25
+
26
+ # Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function.
27
+ network_mode: service:db
28
+ # Uncomment the next line to use a non-root user for all processes.
29
+ # user: vscode
30
+
31
+ db:
32
+ image: "bitnami/postgresql:11.15.0"
33
+ restart: unless-stopped
34
+ volumes:
35
+ - postgres-data:/bitnami/postgresql
36
+ environment:
37
+ POSTGRESQL_USERNAME: admin
38
+ POSTGRESQL_DATABASE: rasa
39
+ POSTGRESQL_PASSWORD: postgres
40
+
41
+ duckling:
42
+ restart: unless-stopped
43
+ image: "rasa/duckling:0.2.0.2"
44
+ expose:
45
+ - "8000"
46
+ command: ["duckling-example-exe", "--no-access-log", "--no-error-log"]
47
+
48
+ redis:
49
+ restart: unless-stopped
50
+ image: "bitnami/redis:6.2.7"
51
+ environment:
52
+ REDIS_PASSWORD: "redis"
53
+ expose:
54
+ - "6379"
55
+
56
+ volumes:
57
+ postgres-data: null
AI/.dockerignore ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ docker*
2
+ docs
3
+ .git*
4
+ **/*.pyc
5
+ **/__pycache__
6
+ !docker/configs
7
+ rasa/tests
8
+ rasa/scripts
9
+ data/
10
+ examples/
11
+ docker-data/*
AI/.env ADDED
@@ -0,0 +1 @@
 
 
1
+ TIMES=2
AI/.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
AI/.github/ISSUE_TEMPLATE.md ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ <!-- IF YOU ARE ASKING A USAGE QUESTION (E.G. "HOW DO I DO XYZ") PLEASE POST
2
+ YOUR QUESTION ON https://forum.rasa.com INSTEAD -->
AI/.github/ISSUE_TEMPLATE/bug_report.md ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ name: Bug report
3
+ about: Create a report to help us reproduce and fix the issue
4
+ ---
5
+
6
+ **Before submitting a bug, please make sure the issue hasn't been already addressed by searching through the [FAQs](https://ai.meta.com/llama/faq/) and [existing/past issues](https://github.com/facebookresearch/llama/issues)**
7
+
8
+ ## Describe the bug
9
+ <Please provide a clear and concise description of what the bug is. If relevant, please include a _minimal_ (least lines of code necessary) _reproducible_ (running this will give us the same result as you get) code snippet. Make sure to include the relevant imports.>
10
+
11
+ ### Minimal reproducible example
12
+ <Remember to wrap the code in ```` ```triple-quotes blocks``` ````>
13
+
14
+ ```python
15
+ # sample code to repro the bug
16
+ ```
17
+
18
+ ### Output
19
+ <Remember to wrap the output in ```` ```triple-quotes blocks``` ````>
20
+
21
+ ```
22
+ <paste stacktrace and other outputs here>
23
+ ```
24
+
25
+ ## Runtime Environment
26
+ - Model: [eg: `meta-llama-3-8b-instruct`]
27
+ - Using via huggingface?: [yes/no]
28
+ - OS: [eg. Linux/Ubuntu, Windows]
29
+ - GPU VRAM:
30
+ - Number of GPUs:
31
+ - GPU Make: [eg: Nvidia, AMD, Intel]
32
+
33
+ **Additional context**
34
+ Add any other context about the problem or environment here.
AI/.github/ISSUE_TEMPLATE/config.yml ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: Bug Report
4
+ url: https://rasa-open-source.atlassian.net/browse/OSS
5
+ about: Create a report to help us improve https://rasa-open-source.atlassian.net/browse/OSS
6
+ - name: Feature request
7
+ url: https://rasa-open-source.atlassian.net/browse/OSS
8
+ about: Suggest an idea on how to improve Rasa https://rasa-open-source.atlassian.net/browse/OSS
9
+ - name: Ask a question
10
+ url: https://forum.rasa.com/
11
+ about: If you have a "How do I?" question please ask in the forum https://forum.rasa.com
AI/.github/PULL_REQUEST_AUTOMATIC_TEMPLATE.md ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ :bulb: This pull request was created automatically to merge a release branch back into the `main` branch.
2
+
3
+ The changes you see here should have already been reviewed by someone, and shouldn't need an extra
4
+ review. Nonetheless, if you notice something that needs to be addressed, please reach out to the person
5
+ responsible for the original changes. In case additional changes need to be made, they need to target the release branch
6
+ (not this pull request nor `main`).
7
+
8
+ :auto_rickshaw: This PR should be merged automatically once it has been approved. If it doesn't happen:
9
+ - [ ] Handle merge conflicts
10
+ - [ ] Fix build errors
AI/.github/PULL_REQUEST_TEMPLATE.md ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ **Proposed changes**:
2
+ - ...
3
+
4
+ **Status (please check what you already did)**:
5
+ - [ ] added some tests for the functionality
6
+ - [ ] updated the documentation
7
+ - [ ] updated the changelog (please check [changelog](https://github.com/RasaHQ/rasa/tree/main/changelog) for instructions)
8
+ - [ ] reformat files using `black` (please check [Readme](https://github.com/RasaHQ/rasa#code-style) for instructions)
AI/.github/change_filters.yml ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ backend:
2
+ - 'pyproject.toml'
3
+ - 'poetry.lock'
4
+ - 'rasa/**/*'
5
+ - 'tests/**/*'
6
+ - 'data/**/*'
7
+ - 'examples/**/*'
8
+ - 'Makefile'
9
+ - '.github/workflows/continous-integration.yml'
10
+ - '.github/workflows/security-scans.yml'
11
+
12
+ docker:
13
+ - 'pyproject.toml'
14
+ - 'poetry.lock'
15
+ - 'rasa/**/*'
16
+ - 'docker/**/*'
17
+ - 'Makefile'
18
+
19
+ docs:
20
+ - 'docs/**/*'
21
+ - 'changelog/*'
22
+ - 'CHANGELOG.mdx'
23
+ - 'tests/docs/*'
24
+ - 'data/**/*'
25
+ - 'examples/**/*'
26
+ - 'Makefile'
27
+ - '.github/workflows/documentation.yml'
28
+ - '.github/workflows/ci-docs-tests.yml'
AI/.github/configs/mr-test-example.yaml ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Example configuration
2
+ #################### syntax #################
3
+ ## include:
4
+ ## - dataset: ["<dataset_name>"]
5
+ ## config: ["<configuration_name>"]
6
+ #
7
+ ## Example:
8
+ ## include:
9
+ ## - dataset: ["Carbon Bot"]
10
+ ## config: ["Sparse + DIET(bow) + ResponseSelector(bow)"]
11
+ #
12
+ ## Shortcut:
13
+ ## You can use the "all" shortcut to include all available configurations or datasets
14
+ #
15
+ ## Example: Use the "Sparse + EmbeddingIntent + ResponseSelector(bow)" configuration
16
+ ## for all available datasets
17
+ ## include:
18
+ ## - dataset: ["all"]
19
+ ## config: ["Sparse + DIET(bow) + ResponseSelector(bow)"]
20
+ #
21
+ ## Example: Use all available configurations for the "Carbon Bot" and "Sara" datasets
22
+ ## and for the "Hermit" dataset use the "Sparse + DIET + ResponseSelector(T2T)" and
23
+ ## "BERT + DIET + ResponseSelector(T2T)" configurations:
24
+ ## include:
25
+ ## - dataset: ["Carbon Bot", "Sara"]
26
+ ## config: ["all"]
27
+ ## - dataset: ["Hermit"]
28
+ ## config: ["Sparse + DIET(seq) + ResponseSelector(t2t)", "BERT + DIET(seq) + ResponseSelector(t2t)"]
29
+ #
30
+ ## Example: Define a branch name to check-out for a dataset repository. Default branch is 'main'
31
+ ## dataset_branch: "test-branch"
32
+ ## include:
33
+ ## - dataset: ["Carbon Bot", "Sara"]
34
+ ## config: ["all"]
35
+ #
36
+ ## Example: Define number of repetitions. This will inform how often to repeat all runs defined in the include section. Default is 1
37
+ ## num_repetitions: 2
38
+ ## include:
39
+ ## - dataset: ["Carbon Bot", "Sara"]
40
+ ## config: ["Sparse + DIET(seq) + ResponseSelector(t2t)"]
41
+ ##
42
+ ## Shortcuts:
43
+ ## You can use the "all" shortcut to include all available configurations or datasets.
44
+ ## You can use the "all-nlu" shortcut to include all available NLU configurations or datasets.
45
+ ## You can use the "all-core" shortcut to include all available core configurations or datasets.
46
+
47
+ include:
48
+ - dataset: ["Carbon Bot"]
49
+ config: ["Sparse + DIET(bow) + ResponseSelector(bow)"]
AI/.github/configs/mr-test-schedule.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "body": "```yml\r\ninclude:\r\n - dataset: [\"all\"]\r\n config: [\"all\"]\r\n```"
3
+ }
AI/.github/configs/tf-cuda.json ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "default_image_tag": "latest",
3
+ "config": [
4
+ {
5
+ "TF": "2.3",
6
+ "IMAGE_TAG": "cuda-10.1-cudnn7"
7
+ },
8
+ {
9
+ "TF": "2.5",
10
+ "IMAGE_TAG": "cuda-11.2.0-cudnn8"
11
+ },
12
+ {
13
+ "TF": "2.6",
14
+ "IMAGE_TAG": "cuda-11.2.0-cudnn8"
15
+ },
16
+ {
17
+ "TF": "2.7",
18
+ "IMAGE_TAG": "cuda-11.2.0-cudnn8"
19
+ },
20
+ {
21
+ "TF": "2.11",
22
+ "IMAGE_TAG": "cuda-11.2.0-cudnn8"
23
+ }
24
+ ]
25
+ }
AI/.github/dependabot.yml ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: pip
4
+ directory: "/"
5
+ schedule:
6
+ interval: weekly
7
+ time: "13:00"
8
+ pull-request-branch-name:
9
+ separator: "-"
10
+ open-pull-requests-limit: 10
11
+ labels:
12
+ - type:dependencies
13
+ - release:main
14
+ ignore:
15
+ - dependency-name: prompt-toolkit
16
+ versions:
17
+ - "> 2.0.10"
18
+ - dependency-name: pytest-asyncio
19
+ versions:
20
+ - "> 0.10.0"
21
+
22
+ - package-ecosystem: github-actions
23
+ directory: "/"
24
+ schedule:
25
+ interval: weekly
26
+ day: monday
27
+ time: "12:00"
28
+ pull-request-branch-name:
29
+ separator: "-"
30
+ open-pull-requests-limit: 10
31
+ reviewers:
32
+ - RasaHQ/infrastructure-squad
33
+ labels:
34
+ - type:dependencies
AI/.github/matchers/flake8-error-matcher.json ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "problemMatcher": [
3
+ {
4
+ "owner": "flake8-error",
5
+ "severity": "error",
6
+ "pattern": [
7
+ {
8
+ "regexp": "^([^:]+):(\\d+):(\\d+):\\s+([DCFNWE]\\d+\\s+.+)$",
9
+ "file": 1,
10
+ "line": 2,
11
+ "column": 3,
12
+ "message": 4
13
+ }
14
+ ]
15
+ }
16
+ ]
17
+ }
AI/.github/no-response.yml ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Configuration for probot-no-response - https://github.com/probot/no-response
2
+
3
+ # Number of days of inactivity before an Issue is closed for lack of response
4
+ daysUntilClose: 14
5
+ # Label requiring a response
6
+ responseRequiredLabel: status:more-details-needed
7
+ # Comment to post when closing an Issue for lack of response. Set to `false` to disable
8
+ closeComment: >
9
+ This issue has been automatically closed because there has been no response
10
+ to our request for more information from the original author. Without this,
11
+ we don't have enough information to help you. Please comment below with the
12
+ requested information if you still need help.
AI/.github/poetry_version.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ # The poetry version is stored in a separate file due to the https://github.com/python-poetry/poetry/issues/3316
2
+ poetry-version=1.4.2
AI/.github/runner/github-runner-deployment.yaml.tmpl ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # GitHub Runner deployment - uses to deploy a github runner
2
+ # which is used by the CI for model regression tests
3
+ apiVersion: apps/v1
4
+ kind: Deployment
5
+ metadata:
6
+ name: github-runner-{{getenv "GITHUB_RUN_ID"}}
7
+ namespace: github-runner
8
+ labels:
9
+ app: github-runner
10
+ pod: github-runner-{{getenv "GITHUB_RUN_ID"}}
11
+ spec:
12
+ replicas: {{getenv "NUM_REPLICAS" "1"}}
13
+ selector:
14
+ matchLabels:
15
+ app: github-runner
16
+ pod: github-runner-{{getenv "GITHUB_RUN_ID"}}
17
+ template:
18
+ metadata:
19
+ labels:
20
+ app: github-runner
21
+ pod: github-runner-{{getenv "GITHUB_RUN_ID"}}
22
+ spec:
23
+ priorityClassName: high-priority
24
+ automountServiceAccountToken: false
25
+ terminationGracePeriodSeconds: 720
26
+ containers:
27
+ - name: github-runner
28
+ image: {{getenv "GH_RUNNER_IMAGE"}}:{{getenv "GH_RUNNER_IMAGE_TAG" "latest"}}
29
+ imagePullPolicy: Always
30
+ livenessProbe:
31
+ initialDelaySeconds: 30
32
+ periodSeconds: 15
33
+ failureThreshold: 3
34
+ exec:
35
+ command:
36
+ - /bin/bash
37
+ - -c
38
+ - "if [[ `curl -sX GET -H \"Authorization: token ${GITHUB_PAT}\" \
39
+ https://api.github.com/repos/${GITHUB_OWNER}/${GITHUB_REPOSITORY}/actions/runners | \
40
+ jq -r '.runners[] | select(.name == \"'${POD_NAME}'\") | .status'` == \"offline\" ]]; then \
41
+ echo \"The GitHub API returns offline status for the ${POD_NAME} runner\" && exit 1; fi"
42
+ resources:
43
+ limits:
44
+ nvidia.com/gpu: 1
45
+ requests:
46
+ nvidia.com/gpu: 1
47
+ memory: 10G
48
+ env:
49
+ - name: POD_NAME
50
+ valueFrom:
51
+ fieldRef:
52
+ fieldPath: metadata.name
53
+ # RUNNER_LABELS - defines labels
54
+ # with which a github-runner will be registered
55
+ - name: RUNNER_LABELS
56
+ value: "self-hosted,gpu,kubernetes,{{getenv "GITHUB_RUN_ID"}}"
57
+ # GITHUB_OWNER - a name of the repository owner
58
+ - name: GITHUB_OWNER
59
+ valueFrom:
60
+ secretKeyRef:
61
+ name: github-rasa
62
+ key: owner
63
+ # GITHUB_REPOSITORY - a name of the repository
64
+ - name: GITHUB_REPOSITORY
65
+ valueFrom:
66
+ secretKeyRef:
67
+ name: github-rasa
68
+ key: repository
69
+ # GITHUB_PAT - Personal Access Token
70
+ - name: GITHUB_PAT
71
+ valueFrom:
72
+ secretKeyRef:
73
+ name: github-rasa
74
+ key: pat
AI/.github/scripts/download_pretrained.py ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import logging
3
+ import time
4
+ from typing import List, NamedTuple, Optional, Text
5
+
6
+ from transformers import AutoTokenizer, TFAutoModel
7
+
8
+ import rasa.shared.utils.io
9
+ from rasa.nlu.utils.hugging_face.registry import (
10
+ model_weights_defaults,
11
+ model_class_dict,
12
+ )
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+ COMP_NAME = "LanguageModelFeaturizer"
17
+ DEFAULT_MODEL_NAME = "bert"
18
+
19
+
20
+ class LmfSpec(NamedTuple):
21
+ """Holds information about the LanguageModelFeaturizer."""
22
+
23
+ model_name: Text
24
+ model_weights: Text
25
+ cache_dir: Optional[Text] = None
26
+
27
+
28
+ def get_model_name_and_weights_from_config(
29
+ config_path: str,
30
+ ) -> List[LmfSpec]:
31
+ config = rasa.shared.utils.io.read_config_file(config_path)
32
+ logger.info(config)
33
+ steps = config.get("pipeline", [])
34
+
35
+ # Look for LanguageModelFeaturizer steps
36
+ steps = list(filter(lambda x: x["name"] == COMP_NAME, steps))
37
+
38
+ lmf_specs = []
39
+ for lmfeat_step in steps:
40
+ if "model_name" not in lmfeat_step:
41
+ if "model_weights" in lmfeat_step:
42
+ model_weights = lmfeat_step["model_weights"]
43
+ raise KeyError(
44
+ "When model_name is not given, then model_weights cannot be set. "
45
+ f"Here, model_weigths is set to {model_weights}"
46
+ )
47
+ model_name = DEFAULT_MODEL_NAME
48
+ model_weights = model_weights_defaults[DEFAULT_MODEL_NAME]
49
+ else:
50
+ model_name = lmfeat_step["model_name"]
51
+
52
+ if model_name not in model_class_dict:
53
+ raise KeyError(
54
+ f"'{model_name}' not a valid model name. Choose from "
55
+ f"{list(model_class_dict.keys())!s} or create"
56
+ f"a new class inheriting from this class to support your model."
57
+ )
58
+
59
+ model_weights = lmfeat_step.get("model_weights")
60
+ if not model_weights:
61
+ logger.info(
62
+ f"Model weights not specified. Will choose default model "
63
+ f"weights: {model_weights_defaults[model_name]}"
64
+ )
65
+ model_weights = model_weights_defaults[model_name]
66
+ cache_dir = lmfeat_step.get("cache_dir", None)
67
+ lmf_specs.append(LmfSpec(model_name, model_weights, cache_dir))
68
+
69
+ return lmf_specs
70
+
71
+
72
+ def instantiate_to_download(comp: LmfSpec) -> None:
73
+ """Instantiates Auto class instances, but only to download."""
74
+
75
+ _ = AutoTokenizer.from_pretrained(comp.model_weights, cache_dir=comp.cache_dir)
76
+ logger.info("Done with AutoTokenizer, now doing TFAutoModel")
77
+ _ = TFAutoModel.from_pretrained(comp.model_weights, cache_dir=comp.cache_dir)
78
+
79
+
80
+ def download(config_path: str):
81
+ lmf_specs = get_model_name_and_weights_from_config(config_path)
82
+
83
+ if not lmf_specs:
84
+ logger.info(f"No {COMP_NAME} found, therefore, skipping download")
85
+ return
86
+
87
+ for lmf_spec in lmf_specs:
88
+ logger.info(
89
+ f"model_name: {lmf_spec.model_name}, "
90
+ f"model_weights: {lmf_spec.model_weights}, "
91
+ f"cache_dir: {lmf_spec.cache_dir}"
92
+ )
93
+ start = time.time()
94
+
95
+ instantiate_to_download(lmf_spec)
96
+
97
+ duration_in_sec = time.time() - start
98
+ logger.info(f"Instantiating Auto classes takes {duration_in_sec:.2f}seconds")
99
+
100
+
101
+ def create_argument_parser() -> argparse.ArgumentParser:
102
+ """Downloads pretrained models, i.e., Huggingface weights."""
103
+ parser = argparse.ArgumentParser(
104
+ description="Downloads pretrained models, i.e., Huggingface weights, "
105
+ "e.g. path to bert_diet_responset2t.yml"
106
+ )
107
+ parser.add_argument(
108
+ "-c",
109
+ "--config",
110
+ type=str,
111
+ required=True,
112
+ help="The path to the config yaml file.",
113
+ )
114
+ return parser
115
+
116
+
117
+ if __name__ == "__main__":
118
+ arg_parser = create_argument_parser()
119
+ cmdline_args = arg_parser.parse_args()
120
+ download(cmdline_args.config)
AI/.github/scripts/mr_generate_summary.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Collect the results of the various model test runs which are done as part of
2
+ # the model regression CI pipeline and dump them as a single file artifact.
3
+ # This artifact will the then be published at the end of the tests.
4
+ from collections import defaultdict
5
+ import json
6
+ import os
7
+ from pathlib import Path
8
+ from typing import Dict, List
9
+
10
+
11
+ def combine_result(
12
+ result1: Dict[str, dict], result2: Dict[str, Dict[str, Dict]]
13
+ ) -> Dict[str, Dict[str, List]]:
14
+ """Combines 2 result dicts to accumulated dict of the same format.
15
+
16
+ Args:
17
+ result1: dict of key: dataset, value: (dict of key: config, value: list of res)
18
+ Example: {
19
+ "Carbon Bot": {
20
+ "Sparse + DIET(bow) + ResponseSelector(bow)": [{
21
+ "Entity Prediction": {
22
+ "macro avg": {
23
+ "f1-score": 0.88,
24
+ }
25
+ },
26
+ "test_run_time": "47s",
27
+ }]
28
+ }
29
+ }
30
+ result2: dict of key: dataset, value: (dict of key: config, value: list of res)
31
+
32
+ Returns:
33
+ dict of key: dataset, and value: (dict of key: config value: list of results)
34
+ """
35
+ combined_dict = defaultdict(lambda: defaultdict(list))
36
+ for new_dict in [result1, result2]:
37
+ for dataset, results_for_dataset in new_dict.items():
38
+ for config, res in results_for_dataset.items():
39
+ for res_dict in res:
40
+ combined_dict[dataset][config].append(res_dict)
41
+ return combined_dict
42
+
43
+
44
+ if __name__ == "__main__":
45
+ data = {}
46
+ reports_dir = Path(os.environ["REPORTS_DIR"])
47
+ reports_paths = list(reports_dir.glob("*/report.json"))
48
+
49
+ for report_path in reports_paths:
50
+ report_dict = json.load(open(report_path))
51
+ data = combine_result(data, report_dict)
52
+
53
+ summary_file = os.environ["SUMMARY_FILE"]
54
+ with open(summary_file, "w") as f:
55
+ json.dump(data, f, sort_keys=True, indent=2)
AI/.github/scripts/mr_publish_results.py ADDED
@@ -0,0 +1,293 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Send model regression test results to Datadog
2
+ # with a summary of all test results.
3
+ # Also write them into a report file.
4
+ import copy
5
+ import datetime
6
+ import json
7
+ import os
8
+ from typing import Any, Dict, List, Text, Tuple
9
+
10
+ from datadog_api_client.v1 import ApiClient, Configuration
11
+ from datadog_api_client.v1.api.metrics_api import MetricsApi
12
+ from datadog_api_client.v1.model.metrics_payload import MetricsPayload
13
+ from datadog_api_client.v1.model.point import Point
14
+ from datadog_api_client.v1.model.series import Series
15
+
16
+ DD_ENV = "rasa-regression-tests"
17
+ DD_SERVICE = "rasa"
18
+ METRIC_RUNTIME_PREFIX = "rasa.perf.benchmark."
19
+ METRIC_ML_PREFIX = "rasa.perf.ml."
20
+ CONFIG_REPOSITORY = "training-data"
21
+
22
+ TASK_MAPPING = {
23
+ "intent_report.json": "intent_classification",
24
+ "CRFEntityExtractor_report.json": "entity_prediction",
25
+ "DIETClassifier_report.json": "entity_prediction",
26
+ "response_selection_report.json": "response_selection",
27
+ "story_report.json": "story_prediction",
28
+ }
29
+
30
+ METRICS = {
31
+ "test_run_time": "TEST_RUN_TIME",
32
+ "train_run_time": "TRAIN_RUN_TIME",
33
+ "total_run_time": "TOTAL_RUN_TIME",
34
+ }
35
+
36
+ MAIN_TAGS = {
37
+ "config": "CONFIG",
38
+ "dataset": "DATASET_NAME",
39
+ }
40
+
41
+ OTHER_TAGS = {
42
+ "config_repository_branch": "DATASET_REPOSITORY_BRANCH",
43
+ "dataset_commit": "DATASET_COMMIT",
44
+ "accelerator_type": "ACCELERATOR_TYPE",
45
+ "type": "TYPE",
46
+ "index_repetition": "INDEX_REPETITION",
47
+ "host_name": "HOST_NAME",
48
+ }
49
+
50
+ GIT_RELATED_TAGS = {
51
+ "pr_id": "PR_ID",
52
+ "pr_url": "PR_URL",
53
+ "github_event": "GITHUB_EVENT_NAME",
54
+ "github_run_id": "GITHUB_RUN_ID",
55
+ "github_sha": "GITHUB_SHA",
56
+ "workflow": "GITHUB_WORKFLOW",
57
+ }
58
+
59
+
60
+ def create_dict_of_env(name_to_env: Dict[Text, Text]) -> Dict[Text, Text]:
61
+ return {name: os.environ[env_var] for name, env_var in name_to_env.items()}
62
+
63
+
64
+ def _get_is_external_and_dataset_repository_branch() -> Tuple[bool, Text]:
65
+ is_external = os.environ["IS_EXTERNAL"]
66
+ dataset_repository_branch = os.environ["DATASET_REPOSITORY_BRANCH"]
67
+ if is_external.lower() in ("yes", "true", "t", "1"):
68
+ is_external_flag = True
69
+ dataset_repository_branch = os.environ["EXTERNAL_DATASET_REPOSITORY_BRANCH"]
70
+ else:
71
+ is_external_flag = False
72
+ return is_external_flag, dataset_repository_branch
73
+
74
+
75
+ def prepare_datasetrepo_and_external_tags() -> Dict[Text, Any]:
76
+ is_external, dataset_repo_branch = _get_is_external_and_dataset_repository_branch()
77
+ return {
78
+ "dataset_repository_branch": dataset_repo_branch,
79
+ "external_dataset_repository": is_external,
80
+ }
81
+
82
+
83
+ def prepare_dsrepo_and_external_tags_as_str() -> Dict[Text, Text]:
84
+ return {
85
+ "dataset_repository_branch": os.environ["DATASET_REPOSITORY_BRANCH"],
86
+ "external_dataset_repository": os.environ["IS_EXTERNAL"],
87
+ }
88
+
89
+
90
+ def transform_to_seconds(duration: Text) -> float:
91
+ """Transform string (with hours, minutes, and seconds) to seconds.
92
+
93
+ Args:
94
+ duration: Examples: '1m27s', '1m27.3s', '27s', '1h27s', '1h1m27s'
95
+
96
+ Raises:
97
+ Exception: If the input is not supported.
98
+
99
+ Returns:
100
+ Duration converted in seconds.
101
+ """
102
+ h_split = duration.split("h")
103
+ if len(h_split) == 1:
104
+ rest = h_split[0]
105
+ hours = 0
106
+ else:
107
+ hours = int(h_split[0])
108
+ rest = h_split[1]
109
+ m_split = rest.split("m")
110
+ if len(m_split) == 2:
111
+ minutes = int(m_split[0])
112
+ seconds = float(m_split[1].rstrip("s"))
113
+ elif len(m_split) == 1:
114
+ minutes = 0
115
+ seconds = float(m_split[0].rstrip("s"))
116
+ else:
117
+ raise Exception(f"Unsupported duration: {duration}")
118
+ overall_seconds = hours * 60 * 60 + minutes * 60 + seconds
119
+ return overall_seconds
120
+
121
+
122
+ def prepare_ml_metric(result: Dict[Text, Any]) -> Dict[Text, float]:
123
+ """Converts a nested result dict into a list of metrics.
124
+
125
+ Args:
126
+ result: Example
127
+ {'accuracy': 1.0,
128
+ 'weighted avg': {
129
+ 'precision': 1.0, 'recall': 1.0, 'f1-score': 1.0, 'support': 28
130
+ }
131
+ }
132
+
133
+ Returns:
134
+ Dict of metric name and metric value
135
+ """
136
+ metrics_ml = {}
137
+ result = copy.deepcopy(result)
138
+ result.pop("file_name", None)
139
+ task = result.pop("task", None)
140
+
141
+ for metric_name, metric_value in result.items():
142
+ if isinstance(metric_value, float):
143
+ metric_full_name = f"{task}.{metric_name}"
144
+ metrics_ml[metric_full_name] = float(metric_value)
145
+ elif isinstance(metric_value, dict):
146
+ for mname, mval in metric_value.items():
147
+ metric_full_name = f"{task}.{metric_name}.{mname}"
148
+ metrics_ml[metric_full_name] = float(mval)
149
+ else:
150
+ raise Exception(
151
+ f"metric_value {metric_value} has",
152
+ f"unexpected type {type(metric_value)}",
153
+ )
154
+ return metrics_ml
155
+
156
+
157
+ def prepare_ml_metrics(results: List[Dict[Text, Any]]) -> Dict[Text, float]:
158
+ metrics_ml = {}
159
+ for result in results:
160
+ new_metrics_ml = prepare_ml_metric(result)
161
+ metrics_ml.update(new_metrics_ml)
162
+
163
+ return metrics_ml
164
+
165
+
166
+ def prepare_datadog_tags() -> List[Text]:
167
+ tags = {
168
+ "env": DD_ENV,
169
+ "service": DD_SERVICE,
170
+ "branch": os.environ["BRANCH"],
171
+ "config_repository": CONFIG_REPOSITORY,
172
+ **prepare_dsrepo_and_external_tags_as_str(),
173
+ **create_dict_of_env(MAIN_TAGS),
174
+ **create_dict_of_env(OTHER_TAGS),
175
+ **create_dict_of_env(GIT_RELATED_TAGS),
176
+ }
177
+ tags_list = [f"{k}:{v}" for k, v in tags.items()]
178
+ return tags_list
179
+
180
+
181
+ def send_to_datadog(results: List[Dict[Text, Any]]) -> None:
182
+ """Sends metrics to datadog."""
183
+ # Prepare
184
+ tags_list = prepare_datadog_tags()
185
+ timestamp = datetime.datetime.now().timestamp()
186
+ series = []
187
+
188
+ # Send metrics about runtime
189
+ metrics_runtime = create_dict_of_env(METRICS)
190
+ for metric_name, metric_value in metrics_runtime.items():
191
+ overall_seconds = transform_to_seconds(metric_value)
192
+ series.append(
193
+ Series(
194
+ metric=f"{METRIC_RUNTIME_PREFIX}{metric_name}.gauge",
195
+ type="gauge",
196
+ points=[Point([timestamp, overall_seconds])],
197
+ tags=tags_list,
198
+ )
199
+ )
200
+
201
+ # Send metrics about ML model performance
202
+ metrics_ml = prepare_ml_metrics(results)
203
+ for metric_name, metric_value in metrics_ml.items():
204
+ series.append(
205
+ Series(
206
+ metric=f"{METRIC_ML_PREFIX}{metric_name}.gauge",
207
+ type="gauge",
208
+ points=[Point([timestamp, float(metric_value)])],
209
+ tags=tags_list,
210
+ )
211
+ )
212
+
213
+ body = MetricsPayload(series=series)
214
+ with ApiClient(Configuration()) as api_client:
215
+ api_instance = MetricsApi(api_client)
216
+ response = api_instance.submit_metrics(body=body)
217
+ if response.get("status") != "ok":
218
+ print(response)
219
+
220
+
221
+ def read_results(file: Text) -> Dict[Text, Any]:
222
+ with open(file) as json_file:
223
+ data = json.load(json_file)
224
+
225
+ keys = [
226
+ "accuracy",
227
+ "weighted avg",
228
+ "macro avg",
229
+ "micro avg",
230
+ "conversation_accuracy",
231
+ ]
232
+ result = {key: data[key] for key in keys if key in data}
233
+
234
+ return result
235
+
236
+
237
+ def get_result(file_name: Text, file: Text) -> Dict[Text, Any]:
238
+ result = read_results(file)
239
+ result["file_name"] = file_name
240
+ result["task"] = TASK_MAPPING[file_name]
241
+ return result
242
+
243
+
244
+ def send_all_to_datadog() -> None:
245
+ results = []
246
+ for dirpath, dirnames, files in os.walk(os.environ["RESULT_DIR"]):
247
+ for f in files:
248
+ if any(f.endswith(valid_name) for valid_name in TASK_MAPPING.keys()):
249
+ result = get_result(f, os.path.join(dirpath, f))
250
+ results.append(result)
251
+ send_to_datadog(results)
252
+
253
+
254
+ def generate_json(file: Text, task: Text, data: dict) -> dict:
255
+ config = os.environ["CONFIG"]
256
+ dataset = os.environ["DATASET_NAME"]
257
+
258
+ if dataset not in data:
259
+ data = {dataset: {config: []}, **data}
260
+ elif config not in data[dataset]:
261
+ data[dataset] = {config: [], **data[dataset]}
262
+
263
+ assert len(data[dataset][config]) <= 1
264
+
265
+ data[dataset][config] = [
266
+ {
267
+ "config_repository": CONFIG_REPOSITORY,
268
+ **prepare_datasetrepo_and_external_tags(),
269
+ **create_dict_of_env(METRICS),
270
+ **create_dict_of_env(OTHER_TAGS),
271
+ **(data[dataset][config][0] if data[dataset][config] else {}),
272
+ task: read_results(file),
273
+ }
274
+ ]
275
+ return data
276
+
277
+
278
+ def create_report_file() -> None:
279
+ data = {}
280
+ for dirpath, dirnames, files in os.walk(os.environ["RESULT_DIR"]):
281
+ for f in files:
282
+ if f not in TASK_MAPPING.keys():
283
+ continue
284
+
285
+ data = generate_json(os.path.join(dirpath, f), TASK_MAPPING[f], data)
286
+
287
+ with open(os.environ["SUMMARY_FILE"], "w") as f:
288
+ json.dump(data, f, sort_keys=True, indent=2)
289
+
290
+
291
+ if __name__ == "__main__":
292
+ send_all_to_datadog()
293
+ create_report_file()
AI/.github/scripts/start_dd_agent.sh ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ DD_API_KEY=$1
4
+ ACCELERATOR_TYPE=$2
5
+ NVML_INTERVAL_IN_SEC=${3:-15} # 15 seconds are the default interval
6
+
7
+ # Install Datadog system agent
8
+ DD_AGENT_MAJOR_VERSION=7 DD_API_KEY=$DD_API_KEY DD_SITE="datadoghq.eu" bash -c "$(curl -L https://s3.amazonaws.com/dd-agent/scripts/install_script.sh)"
9
+ DATADOG_YAML_PATH=/etc/datadog-agent/datadog.yaml
10
+ sudo chmod 666 $DATADOG_YAML_PATH
11
+
12
+ # Associate metrics with tags and env
13
+ {
14
+ echo "env: rasa-regression-tests"
15
+ echo "tags:"
16
+ echo "- service:rasa"
17
+ echo "- accelerator_type:${ACCELERATOR_TYPE}"
18
+ echo "- dataset:${DATASET_NAME}"
19
+ echo "- config:${CONFIG}"
20
+ echo "- dataset_commit:${DATASET_COMMIT}"
21
+ echo "- branch:${BRANCH}"
22
+ echo "- github_sha:${GITHUB_SHA}"
23
+ echo "- pr_id:${PR_ID:-schedule}"
24
+ echo "- pr_url:${PR_URL:-schedule}"
25
+ echo "- type:${TYPE}"
26
+ echo "- dataset_repository_branch:${DATASET_REPOSITORY_BRANCH}"
27
+ echo "- external_dataset_repository:${IS_EXTERNAL:-none}"
28
+ echo "- config_repository:training-data"
29
+ echo "- config_repository_branch:${DATASET_REPOSITORY_BRANCH}"
30
+ echo "- workflow:${GITHUB_WORKFLOW:-none}"
31
+ echo "- github_run_id:${GITHUB_RUN_ID:-none}"
32
+ echo "- github_event:${GITHUB_EVENT_NAME:-none}"
33
+ echo "- index_repetition:${INDEX_REPETITION}"
34
+ echo "- host_name:${HOST_NAME}"
35
+ echo ""
36
+ echo "apm_config:"
37
+ echo " enabled: true"
38
+ echo "process_config:"
39
+ echo " enabled: false"
40
+ echo "use_dogstatsd: true"
41
+ } >> $DATADOG_YAML_PATH
42
+
43
+ # Enable system_core integration
44
+ sudo mv /etc/datadog-agent/conf.d/system_core.d/conf.yaml.example /etc/datadog-agent/conf.d/system_core.d/conf.yaml
45
+
46
+ if [[ "${ACCELERATOR_TYPE}" == "GPU" ]]; then
47
+ # Install and enable NVML integration
48
+ sudo datadog-agent integration --allow-root install -t datadog-nvml==1.0.1
49
+ sudo -u dd-agent -H /opt/datadog-agent/embedded/bin/pip3 install grpcio pynvml
50
+ NVML_CONF_FPATH="/etc/datadog-agent/conf.d/nvml.d/conf.yaml"
51
+ sudo mv "${NVML_CONF_FPATH}.example" ${NVML_CONF_FPATH}
52
+ if [[ "${NVML_INTERVAL_IN_SEC}" != 15 ]]; then
53
+ # Append a line to the NVML config file
54
+ sudo echo " min_collection_interval: ${NVML_INTERVAL_IN_SEC}" | sudo tee -a ${NVML_CONF_FPATH} > /dev/null
55
+ fi
56
+ fi
57
+
58
+ # Apply changes
59
+ sudo service datadog-agent stop
60
+
61
+ # Restart agent (such that GPU/NVML metrics are collected)
62
+ # Adusted code from /etc/init/datadog-agent.conf
63
+ INSTALL_DIR="/opt/datadog-agent"
64
+ AGENTPATH="$INSTALL_DIR/bin/agent/agent"
65
+ PIDFILE="$INSTALL_DIR/run/agent.pid"
66
+ AGENT_USER="dd-agent"
67
+ LD_LIBRARY_PATH="/usr/local/cuda/extras/CUPTI/lib64:/usr/local/cuda/lib64:/usr/local/nvidia/lib:/usr/local/nvidia/lib64"
68
+ sudo -E start-stop-daemon --start --background --quiet --chuid $AGENT_USER --pidfile $PIDFILE --user $AGENT_USER --startas /bin/bash -- -c "LD_LIBRARY_PATH=$LD_LIBRARY_PATH $AGENTPATH run -p $PIDFILE"
69
+
70
+ # Adusted code from /etc/init/datadog-agent-process.conf
71
+ TRACE_AGENTPATH="$INSTALL_DIR/embedded/bin/trace-agent"
72
+ TRACE_PIDFILE="$INSTALL_DIR/run/trace-agent.pid"
73
+ sudo -E start-stop-daemon --start --background --quiet --chuid $AGENT_USER --pidfile $TRACE_PIDFILE --user $AGENT_USER --startas /bin/bash -- -c "LD_LIBRARY_PATH=$LD_LIBRARY_PATH $TRACE_AGENTPATH --config $DATADOG_YAML_PATH --pid $TRACE_PIDFILE"
74
+
75
+ # Adusted code from /etc/init/datadog-agent-trace.conf
76
+ PROCESS_AGENTPATH="$INSTALL_DIR/embedded/bin/process-agent"
77
+ PROCESS_PIDFILE="$INSTALL_DIR/run/process-agent.pid"
78
+ SYSTEM_PROBE_YAML="/etc/datadog-agent/system-probe.yaml"
79
+ sudo -E start-stop-daemon --start --background --quiet --chuid $AGENT_USER --pidfile $PROCESS_PIDFILE --user $AGENT_USER --startas /bin/bash -- -c "LD_LIBRARY_PATH=$LD_LIBRARY_PATH $PROCESS_AGENTPATH --config=$DATADOG_YAML_PATH --sysprobe-config=$SYSTEM_PROBE_YAML --pid=$PROCESS_PIDFILE"
AI/.github/scripts/validate_cpu.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+
3
+ import tensorflow as tf
4
+
5
+
6
+ def check_gpu_not_available():
7
+ num_gpus = len(tf.config.list_physical_devices("GPU"))
8
+ print(f"Num GPUs Available: {num_gpus}")
9
+ if num_gpus > 0:
10
+ sys.exit(1)
11
+
12
+
13
+ if __name__ == "__main__":
14
+ check_gpu_not_available()
AI/.github/scripts/validate_gpus.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+
3
+ import tensorflow as tf
4
+
5
+
6
+ def check_gpu_available():
7
+ num_gpus = len(tf.config.list_physical_devices("GPU"))
8
+ print(f"Num GPUs Available: {num_gpus}")
9
+ if num_gpus <= 0:
10
+ sys.exit(1)
11
+
12
+
13
+ if __name__ == "__main__":
14
+ check_gpu_available()
AI/.github/stale.yml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Number of days of inactivity before an issue becomes stale
2
+ daysUntilStale: 90
3
+ # Label to use when marking an issue as stale
4
+ staleLabel: stale
5
+
6
+ pulls:
7
+ # Give more time before closing PRs
8
+ daysUntilClose: 21
9
+ # Comment to post when marking a PR as stale. Set to `false` to disable
10
+ markComment: >
11
+ This PR has been automatically marked as stale because it has not had
12
+ recent activity. It will be closed if no further activity occurs. Thank you
13
+ for your contributions.
14
+ # Comment to post when closing a stale PR. Set to `false` to disable
15
+ closeComment: >
16
+ This PR has been automatically closed due to inactivity. Please reopen
17
+ this PR or a new one if you plan to follow-up on it. Thank you for your
18
+ contributions.
AI/.github/templates/README.md ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # gomplate templates for GitHub Actions
2
+
3
+ This document describes gomplate templates use for GitHub Actions.
4
+
5
+ ## Requirements
6
+
7
+ You have to have installed [gomplate](https://docs.gomplate.ca/installing/) tool in order to render a template file.
8
+
9
+ > gomplate is a template renderer which supports a growing list of datastores, such as: JSON (including EJSON - encrypted JSON), YAML, AWS EC2 metadata, BoltDB, Hashicorp Consul and Hashicorp Vault secrets.
10
+
11
+ ## Templates
12
+
13
+ Below you can find a list of templates with their description and the commands to render them.
14
+
15
+ ### `configuration_variables.tmpl`
16
+
17
+ The template maps dataset name and configuration name for the model regression tests into paths where files are located. As a result, the template returns two environment variables `DATASET` and `CONFIG` which contain paths to file/directory.
18
+
19
+ #### How to run locally
20
+
21
+ ```shell
22
+ gomplate -d mapping=<path_to_json_file_with_mapping> -f .github/templates/configuration_variables.tmpl
23
+ ```
24
+
25
+ ### `model_regression_test_config_comment.tmpl`
26
+
27
+ The template returns a comment message which is used as a help description in a PR. The template reads the `.github/configs/mr-test-example.yaml` file and include it as example content.
28
+
29
+ The help message is triggered by adding `status:model-regression-tests` label.
30
+ Comment with a help message is added if a PR doesn't contain a comment with a configuration for the model regression tests.
31
+
32
+ #### How to run locally
33
+
34
+ ```shell
35
+ gomplate -f .github/templates/model_regression_test_config_comment.tmpl
36
+ ```
37
+
38
+ The template uses the `GITHUB_ACTOR` environment variable, you have to export the variable before executing the command.
39
+
40
+ ### `model_regression_test_config_to_json.tmpl`
41
+
42
+ The template reads an issue/a PR comment and transforms a YAML code block into JSON.
43
+
44
+ #### How to run locally
45
+
46
+ ```shell
47
+ gomplate -d github=https://api.github.com/repos/${{ github.repository }}/issues/comments/${{ comment-id }} -H 'github=Authorization:token ${{ secrets.GITHUB_TOKEN }}' -f .github/templates/model_regression_test_config_to_json.tmpl
48
+ ```
49
+
50
+ ### `model_regression_test_results.tmpl`
51
+
52
+ The template reads a file with a report (the report file is available as an artifact in the model regression tests workflow) and returns markdown table with a summary of tests.
53
+
54
+ #### How to run locally
55
+
56
+ ```shell
57
+ gomplate -d data=report.json -d results_main=report_main.json -f .github/templates/model_regression_test_results.tmpl
58
+ ```
59
+
60
+ In order to be able to use the `.github/templates/model_regression_test_results.tmpl` template you need the following files:
61
+
62
+ - `report.json` - the file with a report generated by the `CI - Model Regression` workflow run in a PR. The report is available to download as an artifact in the workflow related to the PR.
63
+ - `report_main.json` - the file with a report generated by the `CI - Model Regression` workflow that is triggered on schedule event. A list of the workflows that you can download an artifact from, can be found [here](https://github.com/RasaHQ/rasa/actions?query=workflow%3A%22CI+-+Model+Regression%22+event%3Aschedule).
AI/.github/templates/configuration_variables.tmpl ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {{- /*
2
+
3
+ The template maps dataset name and configuration name for the model
4
+ regression tests into paths where files are located. As a result,
5
+ the template returns two environment variables `DATASET` and `CONFIG`
6
+ which contain paths to file/directory.
7
+
8
+ */ -}}
9
+ {{- $mapping := (datasource "mapping") -}}
10
+ {{- $dataset := (index $mapping.datasets (getenv "DATASET_NAME")) -}}
11
+ {{- $config := $mapping.configurations -}}
12
+ {{- if has $dataset "repository" }}
13
+ export DATASET="{{ $dataset.repository }}"
14
+ export IS_EXTERNAL="true"
15
+ echo "::add-mask::{{ $dataset.repository }}"
16
+ {{ if has $dataset "repository_branch" }}
17
+ export EXTERNAL_DATASET_REPOSITORY_BRANCH="{{ $dataset.repository_branch }}"
18
+ {{ else }}
19
+ export EXTERNAL_DATASET_REPOSITORY_BRANCH="main"
20
+ {{ end }}
21
+ {{- else if has $dataset "path" }}
22
+ export DATASET="{{ $dataset.path }}"
23
+ export IS_EXTERNAL="false"
24
+ echo "::add-mask::{{ $dataset.path }}"
25
+ {{ end }}
26
+
27
+ {{- if has $dataset "train" }}
28
+ export TRAIN_DIR="{{ $dataset.train }}"
29
+ {{ end }}
30
+ {{- if has $dataset "test" }}
31
+ export TEST_DIR="{{ $dataset.test }}"
32
+ {{ end }}
33
+ {{- if has $dataset "domain" }}
34
+ export DOMAIN_FILE="{{ $dataset.domain }}"
35
+ {{ end }}
36
+
37
+ {{- if (has $config.nlu (getenv "CONFIG_NAME")) }}
38
+ export CONFIG="{{ $dataset.language }}/nlu/{{ index $config.nlu (getenv "CONFIG_NAME") }}"
39
+ echo "::add-mask::{{ $dataset.language }}/nlu/{{ index $config.nlu (getenv "CONFIG_NAME") }}"
40
+ {{ else if (has $config.core (getenv "CONFIG_NAME")) }}
41
+ export CONFIG="{{ $dataset.language }}/core/{{ index $config.core (getenv "CONFIG_NAME") }}"
42
+ echo "::add-mask::{{ $dataset.language }}/core/{{ index $config.core (getenv "CONFIG_NAME") }}"
43
+ {{ end -}}
AI/.github/templates/model_regression_test_config_comment.tmpl ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {{- /*
2
+
3
+ The template returns a comment message which is used as a help description
4
+ in a PR. The template reads the `.github/configs/mr-test-example.yaml` file
5
+ and include it as example content.
6
+
7
+ The help message is triggered by adding `status:model-regression-tests` label.
8
+ Comment with a help message is added if a PR doesn't contain a comment
9
+ with a configuration for the model regression tests.
10
+
11
+ */ -}}
12
+ {{ define "check_available_configuration" -}}
13
+ NLU
14
+ {{- if has .dataset "domain" -}}
15
+ , Core
16
+ {{- end -}}
17
+ {{- end -}}
18
+ Hey @{{ .Env.GITHUB_ACTOR }}! :wave: To run model regression tests, comment with the `/modeltest` command and a configuration.
19
+
20
+ _Tips :bulb:: The model regression test will be run on `push` events. You can re-run the tests by re-add `status:model-regression-tests` label or use a `Re-run jobs` button in Github Actions workflow._
21
+
22
+ _Tips :bulb:: Every time when you want to change a configuration you should edit the comment with the previous configuration._
23
+
24
+ You can copy this in your comment and customize:
25
+
26
+ > /modeltest
27
+ > ~~~yml
28
+ >```yml
29
+ >##########
30
+ >## Available datasets
31
+ >##########
32
+ {{range (coll.Keys (datasource "mapping").datasets)}}># - "{{ . }}" ({{ template "check_available_configuration" (dict "dataset" (index (datasource "mapping").datasets .)) }}){{"\n"}}{{ end -}}
33
+ >
34
+ >##########
35
+ >## Available NLU configurations
36
+ >##########
37
+ {{range (coll.Keys (datasource "mapping").configurations.nlu)}}># - "{{.}}"{{"\n"}}{{ end -}}
38
+ >
39
+ >##########
40
+ >## Available Core configurations
41
+ >##########
42
+ {{range (coll.Keys (datasource "mapping").configurations.core)}}># - "{{.}}"{{"\n"}}{{ end -}}
43
+ >
44
+ {{range split (file.Read ".github/configs/mr-test-example.yaml") "\n"}}>{{.}}{{"\n"}}{{ end -}}
45
+ >```
AI/.github/templates/model_regression_test_config_to_json.tmpl ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {{- /*
2
+
3
+ The template reads an issue/a PR comment and transforms a YAML code block into JSON.
4
+
5
+ */ -}}
6
+ {{ define "check_config_type" -}}
7
+ {{- if has (datasource "mapping").configurations.nlu . -}}
8
+ nlu
9
+ {{- else if has (datasource "mapping").configurations.core . -}}
10
+ core
11
+ {{- end -}}
12
+ {{- end -}}
13
+ {{- $config := ((datasource "github").body | regexp.Find "```(?s)(.*)```" | regexp.ReplaceLiteral "```.*|\r" "" | yaml | toJSON | json) -}}
14
+ {{- $num_repetitions := 1 -}}
15
+ {{- if has $config "num_repetitions" -}}
16
+ {{- $num_repetitions = $config.num_repetitions -}}
17
+ {{- end -}}
18
+ {"include":[
19
+ {{- $inc := coll.Slice -}}
20
+ {{- $dataset := coll.Slice -}}
21
+ {{- range $pair := $config.include -}}
22
+ {{- /* use all available datasets if value is equal to all */ -}}
23
+ {{- if eq (index $pair.dataset 0) "all" -}}
24
+ {{ $dataset = (coll.Keys (datasource "mapping").datasets) }}
25
+ {{- else if eq (index $pair.dataset 0) "all-core" -}}
26
+ {{- range $dataset_name, $dataset_spec := (datasource "mapping").datasets -}}
27
+ {{- if has $dataset_spec "domain" -}}
28
+ {{ $dataset = (coll.Append $dataset_name $dataset) -}}
29
+ {{- end -}}
30
+ {{- end -}}
31
+ {{- else if eq (index $pair.dataset 0) "all-nlu" -}}
32
+ {{- range $dataset_name, $dataset_spec := (datasource "mapping").datasets -}}
33
+ {{- if not (has $dataset_spec "domain") -}}
34
+ {{ $dataset = (coll.Append $dataset_name $dataset) -}}
35
+ {{- end -}}
36
+ {{- end -}}
37
+ {{- else -}}
38
+ {{- $dataset = $pair.dataset -}}
39
+ {{- end -}}
40
+ {{- range $index_dataset, $value_dataset := $dataset -}}
41
+ {{- range $index_config, $value_config := $pair.config -}}
42
+ {{ range $index_repetition, $element := (strings.Repeat $num_repetitions "x " | strings.Trim " " | strings.Split " ") }}
43
+ {{- /* use all available configurations if value is equal to all */ -}}
44
+ {{- if eq $value_config "all" -}}
45
+ {{- range $config_type := (coll.Keys (datasource "mapping").configurations) -}}
46
+ {{- range $config_name, $config_file := (index (datasource "mapping").configurations $config_type ) -}}
47
+
48
+ {{ $inc = (coll.Append (dict "index_repetition" $index_repetition "dataset" $value_dataset "config" $config_name "type" $config_type | toJSON) $inc) -}}
49
+ {{- end -}}
50
+ {{- end -}}
51
+ {{- else if eq $value_config "all-core" -}}
52
+ {{- range $config_name, $config_file := (datasource "mapping").configurations.core -}}
53
+ {{ $inc = (coll.Append (dict "index_repetition" $index_repetition "dataset" $value_dataset "config" $config_name "type" "core" | toJSON) $inc) -}}
54
+ {{- end -}}
55
+ {{- else if eq $value_config "all-nlu" -}}
56
+ {{- range $config_name, $config_file := (datasource "mapping").configurations.nlu -}}
57
+ {{ $inc = (coll.Append (dict "index_repetition" $index_repetition "dataset" $value_dataset "config" $config_name "type" "nlu" | toJSON) $inc) -}}
58
+ {{- end -}}
59
+ {{- else -}}
60
+ {{- if has (datasource "mapping").configurations.nlu $value_config -}}
61
+ {{ $inc = (coll.Append (dict "index_repetition" $index_repetition "dataset" $value_dataset "config" $value_config "type" "nlu" | toJSON) $inc) -}}
62
+ {{- else if has (datasource "mapping").configurations.core $value_config -}}
63
+ {{ $inc = (coll.Append (dict "index_repetition" $index_repetition "dataset" $value_dataset "config" $value_config "type" "core" | toJSON) $inc) -}}
64
+ {{- end -}}
65
+ {{- end -}}
66
+ {{- end -}}
67
+ {{- end -}}
68
+ {{- end -}}
69
+ {{- end -}}
70
+ {{- join $inc "," -}}
71
+ ]}
AI/.github/templates/model_regression_test_read_dataset_branch.tmpl ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {{- /*
2
+
3
+ The template reads a PR comment and gets the dataset branch for the training-data
4
+ repository.
5
+
6
+ */ -}}
7
+ {{- $config := ((datasource "github").body | regexp.Find "```(?s)(.*)```" | regexp.ReplaceLiteral "```.*|\r" "" | yaml | toJSON | json) -}}
8
+ {{- $dataset_branch := "main" -}}
9
+ {{- /* if a branch name for dataset repository is not defined use the main branch */ -}}
10
+ {{- if has $config "dataset_branch" -}}
11
+ {{- $dataset_branch = $config.dataset_branch -}}
12
+ {{- end -}}
13
+ export DATASET_BRANCH="{{ $dataset_branch }}"
AI/.github/templates/model_regression_test_results.tmpl ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {{- /*
2
+
3
+ The template reads a file with a report (the report file is available
4
+ as an artifact in the model regression tests workflow) and returns
5
+ a markdown table with a summary of the tests.
6
+
7
+ */ -}}
8
+ {{- /*
9
+
10
+ The print_result_nlu template returns data depends on available fields.
11
+
12
+ */ -}}
13
+ {{ define "print_result_nlu" -}}
14
+ {{- if and (has (index .branch "micro avg") "f1-score") (has (index .main "micro avg") "f1-score") -}}
15
+ {{ printf "%.4f" (index (index .branch "micro avg") "f1-score") }} ({{ printf "%.2f" ((index (index .main "micro avg") "f1-score") | math.Sub (index (index .branch "micro avg") "f1-score")) }})
16
+ {{- else if and (has .branch "accuracy") (has .main "accuracy") -}}
17
+ {{ printf "%.4f" .branch.accuracy }} ({{ printf "%.2f" (.main.accuracy | math.Sub .branch.accuracy) }})
18
+ {{- else if and (has .branch "accuracy") (has (index .main "micro avg") "f1-score") -}}
19
+ {{ printf "%.4f" .branch.accuracy }} ({{ printf "%.2f" ((index (index .main "micro avg") "f1-score") | math.Sub .branch.accuracy) }})
20
+ {{- else if and (has (index .branch "micro avg") "f1-score") (has .main "accuracy") -}}
21
+ {{ printf "%.4f" (index (index .branch "micro avg") "f1-score") }} ({{ printf "%.2f" (.main.accuracy | math.Sub (index (index .branch "micro avg") "f1-score")) }})
22
+ {{- else if (has .branch "accuracy") -}}
23
+ {{ printf "%.4f" .branch.accuracy }} (`no data`)
24
+ {{- else if has (index .branch "micro avg") "f1-score" -}}
25
+ {{ printf "%.4f" (index (index .branch "micro avg") "f1-score") }} (`no data`)
26
+ {{- else -}}
27
+ `no data`
28
+ {{- end -}}
29
+ {{- end -}}
30
+ {{- /*
31
+
32
+ The print_result_core template returns data depends on available fields.
33
+
34
+ */ -}}
35
+ {{ define "print_result_core_micro_avg" -}}
36
+ {{- if and (has (index .branch "micro avg") "f1-score") (has (index .main "micro avg") "f1-score") -}}
37
+ {{ printf "%.4f" (index (index .branch "micro avg") "f1-score") }} ({{ printf "%.2f" ((index (index .main "micro avg") "f1-score") | math.Sub (index (index .branch "micro avg") "f1-score")) }})
38
+ {{- else if and (has .branch "accuracy") (has .main "accuracy") -}}
39
+ {{ printf "%.4f" .branch.accuracy }} ({{ printf "%.2f" (.main.accuracy | math.Sub .branch.accuracy) }})
40
+ {{- else if and (has .branch "accuracy") (has (index .main "micro avg") "f1-score") -}}
41
+ {{ printf "%.4f" .branch.accuracy }} ({{ printf "%.2f" ((index (index .main "micro avg") "f1-score") | math.Sub .branch.accuracy) }})
42
+ {{- else if and (has (index .branch "micro avg") "f1-score") (has .main "accuracy") -}}
43
+ {{ printf "%.4f" (index (index .branch "micro avg") "f1-score") }} ({{ printf "%.2f" (.main.accuracy | math.Sub (index (index .branch "micro avg") "f1-score")) }})
44
+ {{- else if (has .branch "accuracy") -}}
45
+ {{ printf "%.4f" .branch.accuracy }} (`no data`)
46
+ {{- else if has (index .branch "micro avg") "f1-score" -}}
47
+ {{ printf "%.4f" (index (index .branch "micro avg") "f1-score") }} (`no data`)
48
+ {{- else -}}
49
+ `no data`
50
+ {{- end -}}
51
+ {{- end -}}
52
+
53
+ {{ define "print_result_core_conversation_accuracy" -}}
54
+ {{- if and (has (index .branch "conversation_accuracy") "accuracy") (has (index .main "conversation_accuracy") "accuracy") -}}
55
+ {{ printf "%.4f" (index (index .branch "conversation_accuracy") "accuracy") }} ({{ printf "%.2f" ((index (index .main "conversation_accuracy") "accuracy") | math.Sub (index (index .branch "conversation_accuracy") "accuracy")) }})
56
+ {{- else if has (index .branch "conversation_accuracy") "accuracy" -}}
57
+ {{ printf "%.4f" (index (index .branch "conversation_accuracy") "accuracy") }} (`no data`)
58
+ {{- else -}}
59
+ `no data`
60
+ {{- end -}}
61
+ {{- end -}}
62
+
63
+ {{ define "print_table_nlu" }}
64
+ {{- $available_types := (index .results_for_dataset | jsonpath `@..type`) -}}
65
+ {{- if isKind "string" $available_types }}{{- $available_types = (index .results_for_dataset | jsonpath `@..type` | slice) -}}{{- end -}}
66
+ {{- if has $available_types "nlu" -}}
67
+ | Configuration | Intent Classification Micro F1 | Entity Recognition Micro F1 | Response Selection Micro F1 |
68
+ |---------------|-----------------|-----------------|-------------------|
69
+ {{ range $config_name, $config_data_array := .results_for_dataset -}}
70
+ {{ range $config_data := $config_data_array }}
71
+ {{- if eq $config_data.type "nlu" -}}
72
+ | `{{ $config_name }}`<br> test: `{{ $config_data.test_run_time }}`, train: `{{ $config_data.train_run_time }}`, total: `{{ $config_data.total_run_time }}`|
73
+ {{- if has $config_data "intent_classification" -}}
74
+ {{- $intent_class_main := dict -}}
75
+ {{- if has $.results_for_dataset_main $config_name -}}
76
+ {{- $intent_class_main = (index (index $.results_for_dataset_main $config_name) 0).intent_classification -}}
77
+ {{- end -}}
78
+ {{- $intent_class := $config_data.intent_classification -}}
79
+ {{ template "print_result_nlu" (dict "branch" $intent_class "main" $intent_class_main) }}|
80
+ {{- else -}}
81
+ `no data`|
82
+ {{- end -}}
83
+ {{- if has $config_data "entity_prediction" -}}
84
+ {{- $entity_class_main := dict -}}
85
+ {{- if has $.results_for_dataset_main $config_name -}}
86
+ {{- $entity_class_main = (index (index $.results_for_dataset_main $config_name) 0).entity_prediction -}}
87
+ {{- end -}}
88
+ {{- $entity_class := $config_data.entity_prediction -}}
89
+ {{ template "print_result_nlu" (dict "branch" $entity_class "main" $entity_class_main) }}|
90
+ {{- else -}}
91
+ `no data`|
92
+ {{- end -}}
93
+ {{- if has $config_data "response_selection" -}}
94
+ {{- $response_class_main := dict -}}
95
+ {{- if has $.results_for_dataset_main $config_name -}}
96
+ {{- $response_class_main = (index (index $.results_for_dataset_main $config_name) 0).response_selection -}}
97
+ {{- end -}}
98
+ {{- $response_class := $config_data.response_selection -}}
99
+ {{ template "print_result_nlu" (dict "branch" $response_class "main" $response_class_main) }}|
100
+ {{- else -}}
101
+ `no data`|
102
+ {{- end }}
103
+ {{end}}
104
+ {{- end}}
105
+ {{- end}}
106
+ {{- end -}}
107
+ {{- end -}}
108
+
109
+ {{- define "print_table_core" -}}
110
+ {{- $available_types := (index .results_for_dataset | jsonpath `@..type`) -}}
111
+ {{- if isKind "string" $available_types }}{{- $available_types = (index .results_for_dataset | jsonpath `@..type` | slice) -}}{{- end -}}
112
+ {{- if has $available_types "core" -}}
113
+ | Dialog Policy Configuration | Action Level Micro Avg. F1 | Conversation Level Accuracy | Run Time Train | Run Time Test |
114
+ |---------------|-----------------|-----------------|-------------------|-------------------|
115
+ {{ range $config_name, $config_data_array := .results_for_dataset -}}
116
+ {{ range $config_data := $config_data_array }}
117
+ {{- if eq $config_data.type "core" -}}
118
+ | `{{ $config_name }}` |
119
+ {{- if has $config_data "story_prediction" -}}
120
+ {{- $story_prediction_main := dict -}}
121
+ {{- if has $.results_for_dataset_main $config_name -}}
122
+ {{- $story_prediction_main = (index (index $.results_for_dataset_main $config_name) 0).story_prediction -}}
123
+ {{- end -}}
124
+ {{- $story_prediction := $config_data.story_prediction -}}
125
+ {{ template "print_result_core_micro_avg" (dict "branch" $story_prediction "main" $story_prediction_main) }}|
126
+ {{- else -}}
127
+ `no data`|
128
+ {{- end -}}
129
+ {{- if has $config_data "story_prediction" -}}
130
+ {{- $story_prediction_main := dict -}}
131
+ {{- if has $.results_for_dataset_main $config_name -}}
132
+ {{- $story_prediction_main = (index (index $.results_for_dataset_main $config_name) 0).story_prediction -}}
133
+ {{- end -}}
134
+ {{- $story_prediction := index $config_data.story_prediction -}}
135
+ {{ template "print_result_core_conversation_accuracy" (dict "branch" $story_prediction "main" $story_prediction_main) }}|
136
+ {{- else -}}
137
+ `no data`|
138
+ {{- end -}}
139
+ `{{ $config_data.train_run_time }}`| `{{ $config_data.test_run_time }}`|
140
+ {{ end }}
141
+ {{- end}}
142
+ {{- end}}
143
+ {{- end -}}
144
+ {{- end -}}
145
+
146
+ {{- $results_main := (datasource "results_main") -}}
147
+ {{ range $dataset, $results_for_dataset := (datasource "data")}}
148
+ {{ $results_for_dataset_main := (index $results_main $dataset) -}}
149
+ {{ $content_dicts := index $results_for_dataset (index (keys $results_for_dataset) 0) -}}
150
+ {{ $one_content_dict := index $content_dicts 0 -}}
151
+ {{- if ($one_content_dict).external_dataset_repository -}}
152
+ Dataset: `{{$dataset}}`, Dataset repository branch: `{{ ($one_content_dict).dataset_repository_branch }}` (external repository), commit: `{{ ($one_content_dict).dataset_commit }}`
153
+ Configuration repository branch: `{{ ($one_content_dict).config_repository_branch }}`
154
+ {{ else -}}
155
+ Dataset: `{{$dataset}}`, Dataset repository branch: `{{ ($one_content_dict).dataset_repository_branch }}`, commit: `{{ ($one_content_dict).dataset_commit }}`
156
+ {{ end -}}
157
+ {{ template "print_table_nlu" (dict "results_for_dataset" $results_for_dataset "results_for_dataset_main" $results_for_dataset_main) }}
158
+ {{ template "print_table_core" (dict "results_for_dataset" $results_for_dataset "results_for_dataset_main" $results_for_dataset_main) }}
159
+ {{- end }}
AI/.github/tests/test_data/bert_diet_response2t.yml ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Configuration for Rasa NLU.
2
+ # https://rasa.com/docs/rasa/nlu/components/
3
+ language: en
4
+ pipeline:
5
+ - name: WhitespaceTokenizer
6
+ - name: LanguageModelFeaturizer
7
+ alias: "lmf"
8
+ - name: RegexFeaturizer
9
+ alias: "rf"
10
+ - name: LexicalSyntacticFeaturizer
11
+ alias: "lsf"
12
+ - name: DIETClassifier
13
+ epochs: 50
14
+ random_seed: 42
15
+ - name: ResponseSelector
16
+ epochs: 100
17
+ num_transformer_layers: 2
18
+ transformer_size: 256
19
+ hidden_layers_size:
20
+ text: []
21
+ label: []
22
+ random_seed: 42
23
+ featurizers: ["lmf"]
AI/.github/tests/test_data/comment_body.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "body": "/modeltest\r\n\r\n```yml\r\ndataset_branch: \"test_dataset_branch\"\r\ninclude:\r\n - dataset: [\"financial-demo\"]\r\n config: [\"TEST\"]\r\n ```\r\n\r\n<!-- comment-id:comment_configuration -->"
3
+ }
AI/.github/tests/test_data/comment_body_no_dataset_branch.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "body": "/modeltest\r\n\r\n```yml\r\ninclude:\r\n - dataset: [\"financial-demo\"]\r\n config: [\"TEST\"]\r\n ```\r\n\r\n<!-- comment-id:comment_configuration -->"
3
+ }
AI/.github/tests/test_data/intent_report.json ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "search_transactions": {
3
+ "precision": 1.0,
4
+ "recall": 1.0,
5
+ "f1-score": 1.0,
6
+ "support": 1,
7
+ "confused_with": {}
8
+ },
9
+ "greet": {
10
+ "precision": 1.0,
11
+ "recall": 1.0,
12
+ "f1-score": 1.0,
13
+ "support": 2,
14
+ "confused_with": {}
15
+ },
16
+ "out_of_scope": {
17
+ "precision": 1.0,
18
+ "recall": 1.0,
19
+ "f1-score": 1.0,
20
+ "support": 1,
21
+ "confused_with": {}
22
+ },
23
+ "thankyou": {
24
+ "precision": 1.0,
25
+ "recall": 1.0,
26
+ "f1-score": 1.0,
27
+ "support": 1,
28
+ "confused_with": {}
29
+ },
30
+ "help": {
31
+ "precision": 1.0,
32
+ "recall": 1.0,
33
+ "f1-score": 1.0,
34
+ "support": 2,
35
+ "confused_with": {}
36
+ },
37
+ "inform": {
38
+ "precision": 1.0,
39
+ "recall": 1.0,
40
+ "f1-score": 1.0,
41
+ "support": 1,
42
+ "confused_with": {}
43
+ },
44
+ "goodbye": {
45
+ "precision": 1.0,
46
+ "recall": 1.0,
47
+ "f1-score": 1.0,
48
+ "support": 1,
49
+ "confused_with": {}
50
+ },
51
+ "affirm": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1-score": 1.0,
55
+ "support": 3,
56
+ "confused_with": {}
57
+ },
58
+ "pay_cc": {
59
+ "precision": 1.0,
60
+ "recall": 1.0,
61
+ "f1-score": 1.0,
62
+ "support": 2,
63
+ "confused_with": {}
64
+ },
65
+ "check_balance": {
66
+ "precision": 1.0,
67
+ "recall": 1.0,
68
+ "f1-score": 1.0,
69
+ "support": 5,
70
+ "confused_with": {}
71
+ },
72
+ "deny": {
73
+ "precision": 1.0,
74
+ "recall": 1.0,
75
+ "f1-score": 1.0,
76
+ "support": 1,
77
+ "confused_with": {}
78
+ },
79
+ "ask_transfer_charge": {
80
+ "precision": 1.0,
81
+ "recall": 1.0,
82
+ "f1-score": 1.0,
83
+ "support": 1,
84
+ "confused_with": {}
85
+ },
86
+ "transfer_money": {
87
+ "precision": 1.0,
88
+ "recall": 1.0,
89
+ "f1-score": 1.0,
90
+ "support": 3,
91
+ "confused_with": {}
92
+ },
93
+ "check_recipients": {
94
+ "precision": 1.0,
95
+ "recall": 1.0,
96
+ "f1-score": 1.0,
97
+ "support": 2,
98
+ "confused_with": {}
99
+ },
100
+ "check_earnings": {
101
+ "precision": 1.0,
102
+ "recall": 1.0,
103
+ "f1-score": 1.0,
104
+ "support": 2,
105
+ "confused_with": {}
106
+ },
107
+ "accuracy": 1.0,
108
+ "macro avg": {
109
+ "precision": 1.0,
110
+ "recall": 1.0,
111
+ "f1-score": 1.0,
112
+ "support": 28
113
+ },
114
+ "weighted avg": {
115
+ "precision": 1.0,
116
+ "recall": 1.0,
117
+ "f1-score": 1.0,
118
+ "support": 28
119
+ }
120
+ }
AI/.github/tests/test_data/report-on-schedule-2022-02-02.json ADDED
@@ -0,0 +1,303 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "RasaHQ/financial-demo": {
3
+ "BERT + DIET(bow) + ResponseSelector(bow)": [{
4
+ "accelerator_type": "GPU",
5
+ "config_repository": "training-data",
6
+ "config_repository_branch": "main",
7
+ "dataset_commit": "52a3ad3eb5292d56542687e23b06703431f15ead",
8
+ "dataset_repository_branch": "fix-model-regression-tests",
9
+ "entity_prediction": {
10
+ "macro avg": {
11
+ "f1-score": 0.7333333333333333,
12
+ "precision": 0.8,
13
+ "recall": 0.7,
14
+ "support": 14
15
+ },
16
+ "micro avg": {
17
+ "f1-score": 0.8333333333333333,
18
+ "precision": 1.0,
19
+ "recall": 0.7142857142857143,
20
+ "support": 14
21
+ },
22
+ "weighted avg": {
23
+ "f1-score": 0.738095238095238,
24
+ "precision": 0.7857142857142857,
25
+ "recall": 0.7142857142857143,
26
+ "support": 14
27
+ }
28
+ },
29
+ "external_dataset_repository": true,
30
+ "intent_classification": {
31
+ "accuracy": 1.0,
32
+ "macro avg": {
33
+ "f1-score": 1.0,
34
+ "precision": 1.0,
35
+ "recall": 1.0,
36
+ "support": 28
37
+ },
38
+ "weighted avg": {
39
+ "f1-score": 1.0,
40
+ "precision": 1.0,
41
+ "recall": 1.0,
42
+ "support": 28
43
+ }
44
+ },
45
+ "test_run_time": "35s",
46
+ "total_run_time": "2m2s",
47
+ "train_run_time": "1m28s",
48
+ "type": "nlu"
49
+ }],
50
+ "BERT + DIET(seq) + ResponseSelector(t2t)": [{
51
+ "accelerator_type": "GPU",
52
+ "config_repository": "training-data",
53
+ "config_repository_branch": "main",
54
+ "dataset_commit": "52a3ad3eb5292d56542687e23b06703431f15ead",
55
+ "dataset_repository_branch": "fix-model-regression-tests",
56
+ "entity_prediction": {
57
+ "macro avg": {
58
+ "f1-score": 0.7333333333333333,
59
+ "precision": 0.8,
60
+ "recall": 0.7,
61
+ "support": 14
62
+ },
63
+ "micro avg": {
64
+ "f1-score": 0.8333333333333333,
65
+ "precision": 1.0,
66
+ "recall": 0.7142857142857143,
67
+ "support": 14
68
+ },
69
+ "weighted avg": {
70
+ "f1-score": 0.738095238095238,
71
+ "precision": 0.7857142857142857,
72
+ "recall": 0.7142857142857143,
73
+ "support": 14
74
+ }
75
+ },
76
+ "external_dataset_repository": true,
77
+ "intent_classification": {
78
+ "accuracy": 1.0,
79
+ "macro avg": {
80
+ "f1-score": 1.0,
81
+ "precision": 1.0,
82
+ "recall": 1.0,
83
+ "support": 28
84
+ },
85
+ "weighted avg": {
86
+ "f1-score": 1.0,
87
+ "precision": 1.0,
88
+ "recall": 1.0,
89
+ "support": 28
90
+ }
91
+ },
92
+ "test_run_time": "55s",
93
+ "total_run_time": "2m8s",
94
+ "train_run_time": "1m14s",
95
+ "type": "nlu"
96
+ }],
97
+ "Rules + Memo + TED": [{
98
+ "accelerator_type": "GPU",
99
+ "config_repository": "training-data",
100
+ "config_repository_branch": "main",
101
+ "dataset_commit": "52a3ad3eb5292d56542687e23b06703431f15ead",
102
+ "dataset_repository_branch": "fix-model-regression-tests",
103
+ "external_dataset_repository": true,
104
+ "story_prediction": {
105
+ "accuracy": 1.0,
106
+ "conversation_accuracy": {
107
+ "accuracy": 1.0,
108
+ "correct": 48,
109
+ "total": 48,
110
+ "with_warnings": 0
111
+ },
112
+ "macro avg": {
113
+ "f1-score": 1.0,
114
+ "precision": 1.0,
115
+ "recall": 1.0,
116
+ "support": 317
117
+ },
118
+ "weighted avg": {
119
+ "f1-score": 1.0,
120
+ "precision": 1.0,
121
+ "recall": 1.0,
122
+ "support": 317
123
+ }
124
+ },
125
+ "test_run_time": "51s",
126
+ "total_run_time": "8m15s",
127
+ "train_run_time": "7m24s",
128
+ "type": "core"
129
+ }]
130
+ },
131
+ "RasaHQ/retail-demo": {
132
+ "BERT + DIET(bow) + ResponseSelector(bow)": [{
133
+ "accelerator_type": "GPU",
134
+ "config_repository": "training-data",
135
+ "config_repository_branch": "main",
136
+ "dataset_commit": "8226b51b4312aa4d3723098cf6d4028feea040b4",
137
+ "dataset_repository_branch": "fix-model-regression-tests",
138
+ "entity_prediction": {
139
+ "macro avg": {
140
+ "f1-score": 0.25,
141
+ "precision": 0.25,
142
+ "recall": 0.25,
143
+ "support": 6
144
+ },
145
+ "micro avg": {
146
+ "f1-score": 0.2857142857142857,
147
+ "precision": 1.0,
148
+ "recall": 0.16666666666666666,
149
+ "support": 6
150
+ },
151
+ "weighted avg": {
152
+ "f1-score": 0.16666666666666666,
153
+ "precision": 0.16666666666666666,
154
+ "recall": 0.16666666666666666,
155
+ "support": 6
156
+ }
157
+ },
158
+ "external_dataset_repository": true,
159
+ "intent_classification": {
160
+ "macro avg": {
161
+ "f1-score": 0.8,
162
+ "precision": 0.8,
163
+ "recall": 0.85,
164
+ "support": 16
165
+ },
166
+ "micro avg": {
167
+ "f1-score": 0.8387096774193549,
168
+ "precision": 0.8666666666666667,
169
+ "recall": 0.8125,
170
+ "support": 16
171
+ },
172
+ "weighted avg": {
173
+ "f1-score": 0.8125,
174
+ "precision": 0.875,
175
+ "recall": 0.8125,
176
+ "support": 16
177
+ }
178
+ },
179
+ "test_run_time": "29s",
180
+ "total_run_time": "1m16s",
181
+ "train_run_time": "47s",
182
+ "type": "nlu"
183
+ }],
184
+ "BERT + DIET(seq) + ResponseSelector(t2t)": [{
185
+ "accelerator_type": "GPU",
186
+ "config_repository": "training-data",
187
+ "config_repository_branch": "main",
188
+ "dataset_commit": "8226b51b4312aa4d3723098cf6d4028feea040b4",
189
+ "dataset_repository_branch": "fix-model-regression-tests",
190
+ "entity_prediction": {
191
+ "macro avg": {
192
+ "f1-score": 0.25,
193
+ "precision": 0.25,
194
+ "recall": 0.25,
195
+ "support": 6
196
+ },
197
+ "micro avg": {
198
+ "f1-score": 0.2857142857142857,
199
+ "precision": 1.0,
200
+ "recall": 0.16666666666666666,
201
+ "support": 6
202
+ },
203
+ "weighted avg": {
204
+ "f1-score": 0.16666666666666666,
205
+ "precision": 0.16666666666666666,
206
+ "recall": 0.16666666666666666,
207
+ "support": 6
208
+ }
209
+ },
210
+ "external_dataset_repository": true,
211
+ "intent_classification": {
212
+ "accuracy": 0.875,
213
+ "macro avg": {
214
+ "f1-score": 0.8300000000000001,
215
+ "precision": 0.8166666666666667,
216
+ "recall": 0.85,
217
+ "support": 16
218
+ },
219
+ "weighted avg": {
220
+ "f1-score": 0.85,
221
+ "precision": 0.8333333333333333,
222
+ "recall": 0.875,
223
+ "support": 16
224
+ }
225
+ },
226
+ "test_run_time": "56s",
227
+ "total_run_time": "2m2s",
228
+ "train_run_time": "1m6s",
229
+ "type": "nlu"
230
+ }],
231
+ "Rules + Memo": [{
232
+ "accelerator_type": "GPU",
233
+ "config_repository": "training-data",
234
+ "config_repository_branch": "main",
235
+ "dataset_commit": "8226b51b4312aa4d3723098cf6d4028feea040b4",
236
+ "dataset_repository_branch": "fix-model-regression-tests",
237
+ "external_dataset_repository": true,
238
+ "story_prediction": {
239
+ "conversation_accuracy": {
240
+ "accuracy": 0.8888888888888888,
241
+ "correct": 8,
242
+ "total": 9,
243
+ "with_warnings": 0
244
+ },
245
+ "macro avg": {
246
+ "f1-score": 0.9663698541747322,
247
+ "precision": 1.0,
248
+ "recall": 0.946007696007696,
249
+ "support": 67
250
+ },
251
+ "micro avg": {
252
+ "f1-score": 0.9692307692307692,
253
+ "precision": 1.0,
254
+ "recall": 0.9402985074626866,
255
+ "support": 67
256
+ },
257
+ "weighted avg": {
258
+ "f1-score": 0.9656317714563074,
259
+ "precision": 1.0,
260
+ "recall": 0.9402985074626866,
261
+ "support": 67
262
+ }
263
+ },
264
+ "test_run_time": "10s",
265
+ "total_run_time": "19s",
266
+ "train_run_time": "10s",
267
+ "type": "core"
268
+ }],
269
+ "Rules + Memo + TED": [{
270
+ "accelerator_type": "GPU",
271
+ "config_repository": "training-data",
272
+ "config_repository_branch": "main",
273
+ "dataset_commit": "8226b51b4312aa4d3723098cf6d4028feea040b4",
274
+ "dataset_repository_branch": "fix-model-regression-tests",
275
+ "external_dataset_repository": true,
276
+ "story_prediction": {
277
+ "accuracy": 1.0,
278
+ "conversation_accuracy": {
279
+ "accuracy": 1.0,
280
+ "correct": 9,
281
+ "total": 9,
282
+ "with_warnings": 0
283
+ },
284
+ "macro avg": {
285
+ "f1-score": 1.0,
286
+ "precision": 1.0,
287
+ "recall": 1.0,
288
+ "support": 67
289
+ },
290
+ "weighted avg": {
291
+ "f1-score": 1.0,
292
+ "precision": 1.0,
293
+ "recall": 1.0,
294
+ "support": 67
295
+ }
296
+ },
297
+ "test_run_time": "31s",
298
+ "total_run_time": "4m57s",
299
+ "train_run_time": "4m27s",
300
+ "type": "core"
301
+ }]
302
+ }
303
+ }
AI/.github/tests/test_data/report_listformat_core.json ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "RasaHQ/retail-demo": {
3
+ "Rules + Memo + TED": [{
4
+ "accelerator_type": "GPU",
5
+ "config_repository": "training-data",
6
+ "config_repository_branch": "main",
7
+ "dataset_commit": "8226b51b4312aa4d3723098cf6d4028feea040b4",
8
+ "dataset_repository_branch": "fix-model-regression-tests",
9
+ "external_dataset_repository": true,
10
+ "story_prediction": {
11
+ "accuracy": 1.0,
12
+ "conversation_accuracy": {
13
+ "accuracy": 1.0,
14
+ "correct": 9,
15
+ "total": 9,
16
+ "with_warnings": 0
17
+ },
18
+ "macro avg": {
19
+ "f1-score": 1.0,
20
+ "precision": 1.0,
21
+ "recall": 1.0,
22
+ "support": 67
23
+ },
24
+ "weighted avg": {
25
+ "f1-score": 1.0,
26
+ "precision": 1.0,
27
+ "recall": 1.0,
28
+ "support": 67
29
+ }
30
+ },
31
+ "test_run_time": "31s",
32
+ "total_run_time": "4m57s",
33
+ "train_run_time": "4m27s",
34
+ "type": "core"
35
+ },
36
+ {
37
+ "accelerator_type": "GPU",
38
+ "config_repository": "training-data",
39
+ "config_repository_branch": "main",
40
+ "dataset_commit": "8226b51b4312aa4d3723098cf6d4028feea040b4",
41
+ "dataset_repository_branch": "fix-model-regression-tests",
42
+ "external_dataset_repository": true,
43
+ "story_prediction": {
44
+ "accuracy": 1.0,
45
+ "conversation_accuracy": {
46
+ "accuracy": 1.0,
47
+ "correct": 9,
48
+ "total": 9,
49
+ "with_warnings": 0
50
+ },
51
+ "macro avg": {
52
+ "f1-score": 1.0,
53
+ "precision": 1.0,
54
+ "recall": 1.0,
55
+ "support": 67
56
+ },
57
+ "weighted avg": {
58
+ "f1-score": 1.0,
59
+ "precision": 1.0,
60
+ "recall": 1.0,
61
+ "support": 67
62
+ }
63
+ },
64
+ "test_run_time": "41s",
65
+ "total_run_time": "5m57s",
66
+ "train_run_time": "5m27s",
67
+ "type": "core"
68
+ }]
69
+ }
70
+ }
AI/.github/tests/test_data/report_listformat_nlu.json ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "RasaHQ/financial-demo": {
3
+ "BERT + DIET(seq) + ResponseSelector(t2t)": [{
4
+ "accelerator_type": "CPU",
5
+ "config_repository": "training-data",
6
+ "config_repository_branch": "main",
7
+ "dataset_commit": "52a3ad3eb5292d56542687e23b06703431f15ead",
8
+ "dataset_repository_branch": "fix-model-regression-tests",
9
+ "entity_prediction": {
10
+ "macro avg": {
11
+ "f1-score": 0.7333333333333333,
12
+ "precision": 0.8,
13
+ "recall": 0.7,
14
+ "support": 14
15
+ },
16
+ "micro avg": {
17
+ "f1-score": 0.8333333333333333,
18
+ "precision": 1.0,
19
+ "recall": 0.7142857142857143,
20
+ "support": 14
21
+ },
22
+ "weighted avg": {
23
+ "f1-score": 0.738095238095238,
24
+ "precision": 0.7857142857142857,
25
+ "recall": 0.7142857142857143,
26
+ "support": 14
27
+ }
28
+ },
29
+ "external_dataset_repository": true,
30
+ "intent_classification": {
31
+ "accuracy": 1.0,
32
+ "macro avg": {
33
+ "f1-score": 1.0,
34
+ "precision": 1.0,
35
+ "recall": 1.0,
36
+ "support": 28
37
+ },
38
+ "weighted avg": {
39
+ "f1-score": 1.0,
40
+ "precision": 1.0,
41
+ "recall": 1.0,
42
+ "support": 28
43
+ }
44
+ },
45
+ "test_run_time": "1m29s",
46
+ "total_run_time": "4m24s",
47
+ "train_run_time": "2m55s",
48
+ "type": "nlu"
49
+ },
50
+ {
51
+ "accelerator_type": "CPU",
52
+ "config_repository": "training-data",
53
+ "config_repository_branch": "main",
54
+ "dataset_commit": "52a3ad3eb5292d56542687e23b06703431f15ead",
55
+ "dataset_repository_branch": "fix-model-regression-tests",
56
+ "entity_prediction": {
57
+ "macro avg": {
58
+ "f1-score": 0.7333333333333333,
59
+ "precision": 0.8,
60
+ "recall": 0.7,
61
+ "support": 14
62
+ },
63
+ "micro avg": {
64
+ "f1-score": 0.8333333333333333,
65
+ "precision": 1.0,
66
+ "recall": 0.7142857142857143,
67
+ "support": 14
68
+ },
69
+ "weighted avg": {
70
+ "f1-score": 0.738095238095238,
71
+ "precision": 0.7857142857142857,
72
+ "recall": 0.7142857142857143,
73
+ "support": 14
74
+ }
75
+ },
76
+ "external_dataset_repository": true,
77
+ "intent_classification": {
78
+ "accuracy": 1.0,
79
+ "macro avg": {
80
+ "f1-score": 1.0,
81
+ "precision": 1.0,
82
+ "recall": 1.0,
83
+ "support": 28
84
+ },
85
+ "weighted avg": {
86
+ "f1-score": 1.0,
87
+ "precision": 1.0,
88
+ "recall": 1.0,
89
+ "support": 28
90
+ }
91
+ },
92
+ "test_run_time": "2m29s",
93
+ "total_run_time": "5m24s",
94
+ "train_run_time": "3m55s",
95
+ "type": "nlu"
96
+ }]
97
+ }
98
+ }
AI/.github/tests/test_download_pretrained.py ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from copy import deepcopy
2
+ import sys
3
+ import tempfile
4
+ from pathlib import Path
5
+
6
+ import pytest
7
+ from ruamel.yaml import YAML
8
+
9
+ sys.path.append(".github/scripts")
10
+ import download_pretrained # noqa: E402
11
+
12
+ CONFIG_FPATH = Path(__file__).parent / "test_data" / "bert_diet_response2t.yml"
13
+
14
+
15
+ def test_download_pretrained_lmf_exists_no_params():
16
+ lmf_specs = download_pretrained.get_model_name_and_weights_from_config(CONFIG_FPATH)
17
+ assert lmf_specs[0].model_name == "bert"
18
+ assert lmf_specs[0].model_weights == "rasa/LaBSE"
19
+
20
+
21
+ def test_download_pretrained_lmf_exists_with_model_name():
22
+ yaml = YAML(typ="safe")
23
+ config = yaml.load(CONFIG_FPATH)
24
+
25
+ steps = config.get("pipeline", [])
26
+ step = list( # noqa: RUF015
27
+ filter(lambda x: x["name"] == download_pretrained.COMP_NAME, steps)
28
+ )[0]
29
+ step["model_name"] = "roberta"
30
+ step["cache_dir"] = "/this/dir"
31
+
32
+ with tempfile.NamedTemporaryFile("w+") as fp:
33
+ yaml.dump(config, fp)
34
+ fp.seek(0)
35
+ lmf_specs = download_pretrained.get_model_name_and_weights_from_config(fp.name)
36
+ assert lmf_specs[0].model_name == "roberta"
37
+ assert lmf_specs[0].model_weights == "roberta-base"
38
+ assert lmf_specs[0].cache_dir == "/this/dir"
39
+
40
+
41
+ def test_download_pretrained_unknown_model_name():
42
+ yaml = YAML(typ="safe")
43
+ config = yaml.load(CONFIG_FPATH)
44
+
45
+ steps = config.get("pipeline", [])
46
+ step = list( # noqa: RUF015
47
+ filter(lambda x: x["name"] == download_pretrained.COMP_NAME, steps)
48
+ )[0]
49
+ step["model_name"] = "unknown"
50
+
51
+ with tempfile.NamedTemporaryFile("w+") as fp:
52
+ yaml.dump(config, fp)
53
+ fp.seek(0)
54
+ with pytest.raises(KeyError):
55
+ download_pretrained.get_model_name_and_weights_from_config(fp.name)
56
+
57
+
58
+ def test_download_pretrained_multiple_model_names():
59
+ yaml = YAML(typ="safe")
60
+ config = yaml.load(CONFIG_FPATH)
61
+
62
+ steps = config.get("pipeline", [])
63
+ step = list( # noqa: RUF015
64
+ filter(lambda x: x["name"] == download_pretrained.COMP_NAME, steps)
65
+ )[0]
66
+ step_new = deepcopy(step)
67
+ step_new["model_name"] = "roberta"
68
+ steps.append(step_new)
69
+
70
+ with tempfile.NamedTemporaryFile("w+") as fp:
71
+ yaml.dump(config, fp)
72
+ fp.seek(0)
73
+ lmf_specs = download_pretrained.get_model_name_and_weights_from_config(fp.name)
74
+ assert len(lmf_specs) == 2
75
+ assert lmf_specs[1].model_name == "roberta"
76
+
77
+
78
+ def test_download_pretrained_with_model_name_and_nondefault_weight():
79
+ yaml = YAML(typ="safe")
80
+ config = yaml.load(CONFIG_FPATH)
81
+
82
+ steps = config.get("pipeline", [])
83
+ step = list( # noqa: RUF015
84
+ filter(lambda x: x["name"] == download_pretrained.COMP_NAME, steps)
85
+ )[0]
86
+ step["model_name"] = "bert"
87
+ step["model_weights"] = "bert-base-uncased"
88
+
89
+ with tempfile.NamedTemporaryFile("w+") as fp:
90
+ yaml.dump(config, fp)
91
+ fp.seek(0)
92
+ lmf_specs = download_pretrained.get_model_name_and_weights_from_config(fp.name)
93
+ assert lmf_specs[0].model_name == "bert"
94
+ assert lmf_specs[0].model_weights == "bert-base-uncased"
95
+
96
+
97
+ def test_download_pretrained_lmf_doesnt_exists():
98
+ yaml = YAML(typ="safe")
99
+ config = yaml.load(CONFIG_FPATH)
100
+
101
+ steps = config.get("pipeline", [])
102
+ step = list( # noqa: RUF015
103
+ filter(lambda x: x["name"] == download_pretrained.COMP_NAME, steps)
104
+ )[0]
105
+ steps.remove(step)
106
+
107
+ with tempfile.NamedTemporaryFile("w+") as fp:
108
+ yaml.dump(config, fp)
109
+ fp.seek(0)
110
+ lmf_specs = download_pretrained.get_model_name_and_weights_from_config(fp.name)
111
+ assert len(lmf_specs) == 0
AI/.github/tests/test_model_regression_test_read_dataset_branch_tmpl.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pathlib
2
+ import subprocess
3
+ import pytest
4
+ from typing import Text
5
+
6
+ TEMPLATE_FPATH = ".github/templates/model_regression_test_read_dataset_branch.tmpl"
7
+ REPO_DIR = pathlib.Path("").absolute()
8
+ TEST_DATA_DIR = str(pathlib.Path(__file__).parent / "test_data")
9
+ DEFAULT_DATASET_BRANCH = "main"
10
+
11
+
12
+ @pytest.mark.parametrize(
13
+ "comment_body_file,expected_dataset_branch",
14
+ [
15
+ ("comment_body.json", "test_dataset_branch"),
16
+ ("comment_body_no_dataset_branch.json", DEFAULT_DATASET_BRANCH),
17
+ ],
18
+ )
19
+ def test_read_dataset_branch(comment_body_file: Text, expected_dataset_branch: Text):
20
+ cmd = (
21
+ "gomplate "
22
+ f"-d github={TEST_DATA_DIR}/{comment_body_file} "
23
+ f"-f {TEMPLATE_FPATH}"
24
+ )
25
+ output = subprocess.check_output(cmd.split(" "), cwd=REPO_DIR)
26
+ output = output.decode("utf-8").strip()
27
+ assert output == f'export DATASET_BRANCH="{expected_dataset_branch}"'
AI/.github/tests/test_model_regression_test_results_tmpl.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pathlib
2
+ import subprocess
3
+
4
+ TEMPLATE_FPATH = ".github/templates/model_regression_test_results.tmpl"
5
+ REPO_DIR = pathlib.Path("").absolute()
6
+ TEST_DATA_DIR = str(pathlib.Path(__file__).parent / "test_data")
7
+
8
+
9
+ def test_comment_nlu():
10
+ cmd = (
11
+ "gomplate "
12
+ f"-d data={TEST_DATA_DIR}/report_listformat_nlu.json "
13
+ f"-d results_main={TEST_DATA_DIR}/report-on-schedule-2022-02-02.json "
14
+ f"-f {TEMPLATE_FPATH}"
15
+ )
16
+ output = subprocess.check_output(cmd.split(" "), cwd=REPO_DIR)
17
+ output = output.decode("utf-8")
18
+ expected_output = """
19
+ Dataset: `RasaHQ/financial-demo`, Dataset repository branch: `fix-model-regression-tests` (external repository), commit: `52a3ad3eb5292d56542687e23b06703431f15ead`
20
+ Configuration repository branch: `main`
21
+ | Configuration | Intent Classification Micro F1 | Entity Recognition Micro F1 | Response Selection Micro F1 |
22
+ |---------------|-----------------|-----------------|-------------------|
23
+ | `BERT + DIET(seq) + ResponseSelector(t2t)`<br> test: `1m29s`, train: `2m55s`, total: `4m24s`|1.0000 (0.00)|0.8333 (0.00)|`no data`|
24
+ | `BERT + DIET(seq) + ResponseSelector(t2t)`<br> test: `2m29s`, train: `3m55s`, total: `5m24s`|1.0000 (0.00)|0.8333 (0.00)|`no data`|
25
+
26
+
27
+ """ # noqa E501
28
+ assert output == expected_output
29
+
30
+
31
+ def test_comment_core():
32
+ cmd = (
33
+ "gomplate "
34
+ f"-d data={TEST_DATA_DIR}/report_listformat_core.json "
35
+ f"-d results_main={TEST_DATA_DIR}/report-on-schedule-2022-02-02.json "
36
+ f"-f {TEMPLATE_FPATH}"
37
+ )
38
+ output = subprocess.check_output(cmd.split(" "), cwd=REPO_DIR)
39
+ output = output.decode("utf-8")
40
+ expected_output = """
41
+ Dataset: `RasaHQ/retail-demo`, Dataset repository branch: `fix-model-regression-tests` (external repository), commit: `8226b51b4312aa4d3723098cf6d4028feea040b4`
42
+ Configuration repository branch: `main`
43
+
44
+ | Dialog Policy Configuration | Action Level Micro Avg. F1 | Conversation Level Accuracy | Run Time Train | Run Time Test |
45
+ |---------------|-----------------|-----------------|-------------------|-------------------|
46
+ | `Rules + Memo + TED` |1.0000 (0.00)|1.0000 (0.00)|`4m27s`| `31s`|
47
+ | `Rules + Memo + TED` |1.0000 (0.00)|1.0000 (0.00)|`5m27s`| `41s`|
48
+
49
+ """ # noqa E501
50
+ assert output == expected_output
AI/.github/tests/test_mr_generate_summary.py ADDED
@@ -0,0 +1,208 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+
3
+ sys.path.append(".github/scripts")
4
+ from mr_generate_summary import combine_result # noqa: E402
5
+
6
+
7
+ RESULT1 = {
8
+ "financial-demo": {
9
+ "BERT + DIET(bow) + ResponseSelector(bow)": [
10
+ {
11
+ "Entity Prediction": {
12
+ "macro avg": {
13
+ "f1-score": 0.7333333333333333,
14
+ }
15
+ },
16
+ "test_run_time": "47s",
17
+ }
18
+ ]
19
+ }
20
+ }
21
+
22
+
23
+ def test_same_ds_different_config():
24
+ result2 = {
25
+ "financial-demo": {
26
+ "Sparse + DIET(bow) + ResponseSelector(bow)": [
27
+ {
28
+ "Entity Prediction": {
29
+ "macro avg": {
30
+ "f1-score": 0.88,
31
+ }
32
+ },
33
+ "test_run_time": "47s",
34
+ }
35
+ ]
36
+ }
37
+ }
38
+ expected_combined = {
39
+ "financial-demo": {
40
+ "BERT + DIET(bow) + ResponseSelector(bow)": [
41
+ {
42
+ "Entity Prediction": {
43
+ "macro avg": {
44
+ "f1-score": 0.7333333333333333,
45
+ }
46
+ },
47
+ "test_run_time": "47s",
48
+ }
49
+ ],
50
+ "Sparse + DIET(bow) + ResponseSelector(bow)": [
51
+ {
52
+ "Entity Prediction": {
53
+ "macro avg": {
54
+ "f1-score": 0.88,
55
+ }
56
+ },
57
+ "test_run_time": "47s",
58
+ }
59
+ ],
60
+ }
61
+ }
62
+
63
+ actual_combined = combine_result(RESULT1, result2)
64
+ assert actual_combined == expected_combined
65
+
66
+ actual_combined = combine_result(result2, RESULT1)
67
+ assert actual_combined == expected_combined
68
+
69
+
70
+ def test_different_ds_same_config():
71
+ result2 = {
72
+ "Carbon Bot": {
73
+ "Sparse + DIET(bow) + ResponseSelector(bow)": [
74
+ {
75
+ "Entity Prediction": {
76
+ "macro avg": {
77
+ "f1-score": 0.88,
78
+ }
79
+ },
80
+ "test_run_time": "47s",
81
+ }
82
+ ]
83
+ }
84
+ }
85
+ expected_combined = {
86
+ "financial-demo": {
87
+ "BERT + DIET(bow) + ResponseSelector(bow)": [
88
+ {
89
+ "Entity Prediction": {
90
+ "macro avg": {
91
+ "f1-score": 0.7333333333333333,
92
+ }
93
+ },
94
+ "test_run_time": "47s",
95
+ }
96
+ ],
97
+ },
98
+ "Carbon Bot": {
99
+ "Sparse + DIET(bow) + ResponseSelector(bow)": [
100
+ {
101
+ "Entity Prediction": {
102
+ "macro avg": {
103
+ "f1-score": 0.88,
104
+ }
105
+ },
106
+ "test_run_time": "47s",
107
+ }
108
+ ]
109
+ },
110
+ }
111
+
112
+ actual_combined = combine_result(RESULT1, result2)
113
+ assert actual_combined == expected_combined
114
+
115
+ actual_combined = combine_result(result2, RESULT1)
116
+ assert actual_combined == expected_combined
117
+
118
+
119
+ def test_start_empty():
120
+ result2 = {}
121
+ expected_combined = {
122
+ "financial-demo": {
123
+ "BERT + DIET(bow) + ResponseSelector(bow)": [
124
+ {
125
+ "Entity Prediction": {
126
+ "macro avg": {
127
+ "f1-score": 0.7333333333333333,
128
+ }
129
+ },
130
+ "test_run_time": "47s",
131
+ }
132
+ ]
133
+ }
134
+ }
135
+
136
+ actual_combined = combine_result(RESULT1, result2)
137
+ assert actual_combined == expected_combined
138
+
139
+ actual_combined = combine_result(result2, RESULT1)
140
+ assert actual_combined == expected_combined
141
+
142
+
143
+ def test_combine_result_repetition():
144
+ expected_combined = {
145
+ "financial-demo": {
146
+ "BERT + DIET(bow) + ResponseSelector(bow)": [
147
+ {
148
+ "Entity Prediction": {
149
+ "macro avg": {
150
+ "f1-score": 0.7333333333333333,
151
+ }
152
+ },
153
+ "test_run_time": "47s",
154
+ },
155
+ {
156
+ "Entity Prediction": {
157
+ "macro avg": {
158
+ "f1-score": 0.7333333333333333,
159
+ }
160
+ },
161
+ "test_run_time": "47s",
162
+ },
163
+ ]
164
+ }
165
+ }
166
+
167
+ actual_combined = combine_result(RESULT1, RESULT1)
168
+ assert actual_combined == expected_combined
169
+
170
+
171
+ def test_combine_result_repetition_3times():
172
+ expected_combined = {
173
+ "financial-demo": {
174
+ "BERT + DIET(bow) + ResponseSelector(bow)": [
175
+ {
176
+ "Entity Prediction": {
177
+ "macro avg": {
178
+ "f1-score": 0.7333333333333333,
179
+ }
180
+ },
181
+ "test_run_time": "47s",
182
+ },
183
+ {
184
+ "Entity Prediction": {
185
+ "macro avg": {
186
+ "f1-score": 0.7333333333333333,
187
+ }
188
+ },
189
+ "test_run_time": "47s",
190
+ },
191
+ {
192
+ "Entity Prediction": {
193
+ "macro avg": {
194
+ "f1-score": 0.7333333333333333,
195
+ }
196
+ },
197
+ "test_run_time": "47s",
198
+ },
199
+ ]
200
+ }
201
+ }
202
+
203
+ tmp_combined = combine_result(RESULT1, RESULT1)
204
+ actual_combined = combine_result(tmp_combined, RESULT1)
205
+ assert actual_combined == expected_combined
206
+
207
+ actual_combined = combine_result(RESULT1, tmp_combined)
208
+ assert actual_combined == expected_combined
AI/.github/tests/test_mr_publish_results.py ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from pathlib import Path
3
+ import sys
4
+ from unittest import mock
5
+
6
+ sys.path.append(".github/scripts")
7
+ from mr_publish_results import ( # noqa: E402
8
+ prepare_ml_metric,
9
+ prepare_ml_metrics,
10
+ transform_to_seconds,
11
+ generate_json,
12
+ prepare_datadog_tags,
13
+ )
14
+
15
+ EXAMPLE_CONFIG = "Sparse + BERT + DIET(seq) + ResponseSelector(t2t)"
16
+ EXAMPLE_DATASET_NAME = "financial-demo"
17
+
18
+ ENV_VARS = {
19
+ "BRANCH": "my-branch",
20
+ "PR_ID": "10927",
21
+ "PR_URL": "https://github.com/RasaHQ/rasa/pull/10856/",
22
+ "GITHUB_EVENT_NAME": "pull_request",
23
+ "GITHUB_RUN_ID": "1882718340",
24
+ "GITHUB_SHA": "abc",
25
+ "GITHUB_WORKFLOW": "CI - Model Regression",
26
+ "IS_EXTERNAL": "false",
27
+ "DATASET_REPOSITORY_BRANCH": "main",
28
+ "CONFIG": EXAMPLE_CONFIG,
29
+ "DATASET_NAME": EXAMPLE_DATASET_NAME,
30
+ "CONFIG_REPOSITORY_BRANCH": "main",
31
+ "DATASET_COMMIT": "52a3ad3eb5292d56542687e23b06703431f15ead",
32
+ "ACCELERATOR_TYPE": "CPU",
33
+ "TEST_RUN_TIME": "1m54s",
34
+ "TRAIN_RUN_TIME": "4m4s",
35
+ "TOTAL_RUN_TIME": "5m58s",
36
+ "TYPE": "nlu",
37
+ "INDEX_REPETITION": "0",
38
+ "HOST_NAME": "github-runner-2223039222-22df222fcd-2cn7d",
39
+ }
40
+
41
+
42
+ @mock.patch.dict(os.environ, ENV_VARS, clear=True)
43
+ def test_generate_json():
44
+ f = Path(__file__).parent / "test_data" / "intent_report.json"
45
+ result = generate_json(f, task="intent_classification", data={})
46
+ assert isinstance(result[EXAMPLE_DATASET_NAME][EXAMPLE_CONFIG], list)
47
+
48
+ actual = result[EXAMPLE_DATASET_NAME][EXAMPLE_CONFIG][0]["intent_classification"]
49
+ expected = {
50
+ "accuracy": 1.0,
51
+ "weighted avg": {
52
+ "precision": 1.0,
53
+ "recall": 1.0,
54
+ "f1-score": 1.0,
55
+ "support": 28,
56
+ },
57
+ "macro avg": {"precision": 1.0, "recall": 1.0, "f1-score": 1.0, "support": 28},
58
+ }
59
+ assert expected == actual
60
+
61
+
62
+ def test_transform_to_seconds():
63
+ assert 87.0 == transform_to_seconds("1m27s")
64
+ assert 87.3 == transform_to_seconds("1m27.3s")
65
+ assert 27.0 == transform_to_seconds("27s")
66
+ assert 3627.0 == transform_to_seconds("1h27s")
67
+ assert 3687.0 == transform_to_seconds("1h1m27s")
68
+
69
+
70
+ def test_prepare_ml_model_perf_metrics():
71
+ results = [
72
+ {
73
+ "macro avg": {
74
+ "precision": 0.8,
75
+ "recall": 0.8,
76
+ "f1-score": 0.8,
77
+ "support": 14,
78
+ },
79
+ "micro avg": {
80
+ "precision": 1.0,
81
+ "recall": 0.7857142857142857,
82
+ "f1-score": 0.88,
83
+ "support": 14,
84
+ },
85
+ "file_name": "DIETClassifier_report.json",
86
+ "task": "Entity Prediction",
87
+ },
88
+ {
89
+ "accuracy": 1.0,
90
+ "weighted avg": {
91
+ "precision": 1.0,
92
+ "recall": 1.0,
93
+ "f1-score": 1.0,
94
+ "support": 28,
95
+ },
96
+ "macro avg": {
97
+ "precision": 1.0,
98
+ "recall": 1.0,
99
+ "f1-score": 1.0,
100
+ "support": 28,
101
+ },
102
+ "file_name": "intent_report.json",
103
+ "task": "Intent Classification",
104
+ },
105
+ ]
106
+ metrics_ml = prepare_ml_metrics(results)
107
+ assert len(metrics_ml) == 17
108
+
109
+
110
+ def test_prepare_ml_model_perf_metrics_simple():
111
+ result = {
112
+ "accuracy": 1.0,
113
+ "weighted avg": {"precision": 1, "recall": 1.0, "f1-score": 1, "support": 28},
114
+ "task": "Intent Classification",
115
+ }
116
+ metrics_ml = prepare_ml_metric(result)
117
+ assert len(metrics_ml) == 5
118
+
119
+ for _, v in metrics_ml.items():
120
+ assert isinstance(v, float)
121
+
122
+ key, value = "Intent Classification.accuracy", 1.0
123
+ assert key in metrics_ml and value == metrics_ml[key]
124
+
125
+ key, value = "Intent Classification.weighted avg.f1-score", 1.0
126
+ assert key in metrics_ml and value == metrics_ml[key]
127
+
128
+
129
+ @mock.patch.dict(os.environ, ENV_VARS, clear=True)
130
+ def test_prepare_datadog_tags():
131
+ tags_list = prepare_datadog_tags()
132
+ assert "dataset:financial-demo" in tags_list
AI/.github/tests/test_validate_gpus.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ from unittest import mock
4
+
5
+ import pytest
6
+
7
+ sys.path.append(".github/scripts")
8
+ import validate_cpu # noqa: E402
9
+ import validate_gpus # noqa: E402
10
+
11
+ ENV_VARS = {
12
+ "CUDA_VISIBLE_DEVICES": "-1",
13
+ }
14
+
15
+
16
+ @mock.patch.dict(os.environ, ENV_VARS, clear=True)
17
+ def test_validate_cpu_succeeds_when_there_are_no_gpus():
18
+ validate_cpu.check_gpu_not_available()
19
+
20
+
21
+ @mock.patch.dict(os.environ, ENV_VARS, clear=True)
22
+ def test_validate_gpus_exits_when_there_are_no_gpus():
23
+ # This unit test assumes that unit tests are run on a CPU
24
+ with pytest.raises(SystemExit) as pytest_wrapped_e:
25
+ validate_gpus.check_gpu_available()
26
+ assert pytest_wrapped_e.type == SystemExit
27
+ assert pytest_wrapped_e.value.code == 1
AI/.github/workflows/automatic-pr-update.yml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Automatic PR Merger
2
+
3
+ on:
4
+ push: {} # update PR when base branch is updated
5
+
6
+ jobs:
7
+ # thats's all. single step is needed - if PR is mergeable according to
8
+ # branch protection rules it will be merged automatically
9
+ mergepal:
10
+ runs-on: ubuntu-22.04
11
+ if: github.repository == 'RasaHQ/rasa'
12
+
13
+ steps:
14
+ - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
15
+ - uses: rasahq/update-pr-branch@f7012036a6d5659cfbc37f180716963511e81f95
16
+ with:
17
+ token: ${{ secrets.UPDATE_BRANCH_PAT }}
18
+ # required parameter by original action -
19
+ # check is already done through protected branches so not needed for us
20
+ required_approval_count: 0
21
+ # update branch despite failing check runs
22
+ require_passed_checks: false