-
Notifications
You must be signed in to change notification settings - Fork 102
Evaluation #122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
ashsong-nv
merged 105 commits into
NVIDIA-AI-Blueprints:develop
from
katherineh123:wip-evaluation
Nov 3, 2025
Merged
Evaluation #122
Changes from all commits
Commits
Show all changes
105 commits
Select commit
Hold shift + click to select a range
7bb5b6d
wip evaluation: custom nat evaluation for simple accuracy, with custo…
bf613be
putting back error handling info in readme that got deleted by accident
3c66a49
removed wrong comment on accuracy numbers
7ffb912
readme update for running multiple eval runs
a3a117f
add to readme how to run multiple reps of eval
2fc3535
test commit
katherineh123 530f918
test commit
katherineh123 f1d24f1
nat custom evaluator for label accuracy
katherineh123 9d8a677
renamed eval custom input parser
katherineh123 e3617d4
changed status accuracy evaluator name to status_accuracy from simple…
katherineh123 5763947
function renames + update readme with label accuracy evaluator
katherineh123 22c0910
readme typo
katherineh123 77639c7
more README typos
katherineh123 5988743
implemented more in-depth evaluators for within-experiment multi repe…
katherineh123 65b6a8e
new eval dataset input file format
katherineh123 ef053df
Ground truth input file structure changed to list all containers; rea…
katherineh123 6e4f145
fix readme description for within-experiment custom evaluators
katherineh123 26a257f
readme typo
katherineh123 c7ad0f6
readme typo
katherineh123 6275d52
removed alikeability word from comments, calling it consistency instead
katherineh123 d0a087c
readme typo
katherineh123 59d2502
fix model endpoints
katherineh123 fb21f6e
change aiq imports to nat
katherineh123 8397ef7
stop tracking old_eval_datasets
katherineh123 6cf2249
small changes to custom evaluator examples
katherineh123 1deaf90
slight file structure and naming changes based on pr comments
katherineh123 ee16609
moved evaluators to evaluator dir
katherineh123 fd45a3b
modified gitignore to removed .tmp files
katherineh123 2b68b79
use one register.py file, remove separate evaluator_register.py
katherineh123 99ad152
change eval test set file structure so each test set has its own .json
katherineh123 f91f1bc
update readme to match new eval test set input file structure. moved …
katherineh123 68fbde5
renamed response spread evaluator to response similarity, updated com…
katherineh123 e91b610
removed response similarity custom evaluator
katherineh123 5d8a9b3
fixed evaluator average accuracy calculation bug. refactored consiste…
katherineh123 625dae6
refactored accuracy evaluator to accept field variable, updated readme
katherineh123 f3e3c39
refactored accuracy evaluator to take in multiple_reps=True/False par…
katherineh123 2ee6ad0
readme updates about plotting box and whisker
katherineh123 ea7f936
add conflict_policy param to accuracy evaluator to allow for lenient …
katherineh123 ccd6bde
data model for eval input
katherineh123 fc91b67
clean up config file
katherineh123 e015abb
added robust parsing to checklist generation output. added max_concur…
katherineh123 d755b8e
add accidentally removed .tmp files back
katherineh123 be4b26f
update accidentally removed CVE markdown report to be same as origina…
katherineh123 93be050
moved markdown report back to original dir
katherineh123 881087f
fix formatting of function description
katherineh123 583875d
add license to all files
katherineh123 9565d65
minor formatting fixes
katherineh123 881be76
remove separated morpheus test sets, renamed combined test set to eva…
katherineh123 99986f3
change eval data model names to be more descriptive
katherineh123 3bc0140
accuracy evaluator for multiple reps outputs DataFrame.describe() met…
katherineh123 5b48a31
add parent dir for profile and eval datasets
katherineh123 5855cc6
readme update on eval dataset file location
katherineh123 bc83a42
added required dataset_id field for test sets (and kept optional data…
katherineh123 c6b57ab
update eval input data model validation to use predefined label/statu…
katherineh123 0e6777a
minor: remove dead code
katherineh123 4b502ec
minor: implementation fixes to accuracy evaluator (keeps same logic)
katherineh123 f14845f
minor: consistency evaluator implementation change, logic same
katherineh123 9482c0f
minor: move example usage of script to docstring
katherineh123 2a274e9
add docstrings to explain custom input parser script
katherineh123 b0b8a0b
readme typo fix
katherineh123 958caa5
renamed accuracy evaluator's duplicate handling policy config options
katherineh123 43fc883
make evaluator config fields use typing.Literal and pydantic Fields
katherineh123 9a5dda0
removed constraint that every container input needs same test set of …
katherineh123 3285389
revert checklist prompt generator (moved robust parsing version to an…
katherineh123 31ab517
refactor consistency evaluator to categorize by container. Add errori…
katherineh123 1d7b6cf
infer multiple reps instead of having manual config option in accurac…
katherineh123 111a4fc
readme updtes
katherineh123 53a7088
changed accuracy to be per rep, not per container
katherineh123 4391b9e
remove plot
katherineh123 9ec04be
more stable eval dataset
katherineh123 7e268f7
Update README.md
katherineh123 db495a4
remove redundant output field
katherineh123 9c04647
readme updates
katherineh123 4cb2459
fix readme merge conflict
katherineh123 695f817
fix profiler dataset path
katherineh123 e41f63c
remove max concurrency config from summarize, justify, cve_checklist
katherineh123 a90785a
update config file and readme to match removed max_concurrency fields
katherineh123 54e1c33
readme updates
katherineh123 8a17dbb
remove max concurrency from readme
katherineh123 fa20933
Update README.md
katherineh123 e41d49e
Update README.md
katherineh123 8ff40d3
Update README.md
katherineh123 e08aac9
Update README.md
katherineh123 5aa552e
Update README.md
katherineh123 a51d5ed
Update src/vuln_analysis/data/eval_datasets/eval_dataset.json
katherineh123 b0051a7
Update src/vuln_analysis/eval/parse_eval_input.py
katherineh123 f3b82f5
Update README.md
katherineh123 e560b6c
Update README.md
katherineh123 ff48ab6
Update README.md
katherineh123 622ea09
Update README.md
katherineh123 516f187
Update README.md
katherineh123 21f1cbc
Update README.md
katherineh123 c7d20be
Update README.md
katherineh123 0644ab7
Update README.md
katherineh123 5347c96
Update README.md
katherineh123 e795af7
Update README.md
katherineh123 d777265
Update README.md
katherineh123 110aada
Update README.md
katherineh123 4233d42
Update README.md
katherineh123 88d60f8
minor readme updates
katherineh123 5f84e46
update eval dataset container names to match example input message da…
katherineh123 6c02d5d
example output for accuracy evaluator with multiple runs
katherineh123 ef1a856
minor readme
katherineh123 631eae4
README cleanup
ashsong-nv 54b0cc3
Fix JSON syntax highlighting in README
ashsong-nv File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,199 @@ | ||
| # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| general: | ||
| use_uvloop: true | ||
|
|
||
| functions: | ||
| cve_generate_vdbs: | ||
| _type: cve_generate_vdbs | ||
| agent_name: cve_agent_executor # Used to determine which tools are enabled | ||
| embedder_name: nim_embedder | ||
| base_git_dir: .cache/am_cache/git | ||
| base_vdb_dir: .cache/am_cache/vdb | ||
| base_code_index_dir: .cache/am_cache/code_index | ||
| cve_fetch_intel: | ||
| _type: cve_fetch_intel | ||
| cve_process_sbom: | ||
| _type: cve_process_sbom | ||
| cve_check_vuln_deps : | ||
| _type: cve_check_vuln_deps | ||
| skip: false | ||
| cve_checklist: | ||
| _type: cve_checklist | ||
| llm_name: checklist_llm | ||
| Container Image Code QA System: | ||
| _type: local_vdb_retriever | ||
| embedder_name: nim_embedder | ||
| llm_name: code_vdb_retriever_llm | ||
| vdb_type: code | ||
| return_source_documents: false | ||
| Container Image Developer Guide QA System: | ||
| _type: local_vdb_retriever | ||
| embedder_name: nim_embedder | ||
| llm_name: doc_vdb_retriever_llm | ||
| vdb_type: doc | ||
| return_source_documents: false | ||
| Lexical Search Container Image Code QA System: | ||
| _type: lexical_code_search | ||
| top_k: 5 | ||
| Internet Search: | ||
| _type: serp_wrapper | ||
| max_retries: 5 | ||
| cve_agent_executor: | ||
| _type: cve_agent_executor | ||
| llm_name: cve_agent_executor_llm | ||
| tool_names: | ||
| - Container Image Code QA System | ||
| - Container Image Developer Guide QA System | ||
| # - Lexical Search Container Image Code QA System # Uncomment to enable lexical search | ||
| - Internet Search | ||
| max_concurrency: null | ||
| max_iterations: 10 | ||
| prompt_examples: false | ||
| replace_exceptions: true | ||
| replace_exceptions_value: "I do not have a definitive answer for this checklist item." | ||
| return_intermediate_steps: false | ||
| verbose: false | ||
| cve_summarize: | ||
| _type: cve_summarize | ||
| llm_name: summarize_llm | ||
| cve_justify: | ||
| _type: cve_justify | ||
| llm_name: justify_llm | ||
| cve_file_output: | ||
| _type: cve_file_output | ||
| file_path: .tmp/output.json | ||
| markdown_dir: .tmp/vulnerability_markdown_reports | ||
| overwrite: true | ||
|
|
||
| llms: | ||
| checklist_llm: | ||
| _type: nim | ||
| base_url: ${NVIDIA_API_BASE:-https://integrate.api.nvidia.com/v1} | ||
| model_name: ${CHECKLIST_MODEL_NAME:-meta/llama-3.1-70b-instruct} | ||
| temperature: 0.0 | ||
| max_tokens: 2000 | ||
| top_p: 0.01 | ||
| do_auto_retry: True | ||
| max_retries: 5 | ||
| retry_on_status_codes: [429, 500, 502, 503, 504] | ||
| retry_on_errors: ["Too Many Requests", "Internal Server Error", "Bad Gateway", "Service Unavailable", "Gateway Time-out", "Gateway Timeout"] | ||
| code_vdb_retriever_llm: | ||
| _type: nim | ||
| base_url: ${NVIDIA_API_BASE:-https://integrate.api.nvidia.com/v1} | ||
| model_name: ${CODE_VDB_RETRIEVER_MODEL_NAME:-meta/llama-3.1-70b-instruct} | ||
| temperature: 0.0 | ||
| max_tokens: 2000 | ||
| top_p: 0.01 | ||
| do_auto_retry: True | ||
| max_retries: 5 | ||
| retry_on_status_codes: [429, 500, 502, 503, 504] | ||
| retry_on_errors: ["Too Many Requests", "Internal Server Error", "Bad Gateway", "Service Unavailable", "Gateway Time-out", "Gateway Timeout"] | ||
| doc_vdb_retriever_llm: | ||
| _type: nim | ||
| base_url: ${NVIDIA_API_BASE:-https://integrate.api.nvidia.com/v1} | ||
| model_name: ${DOC_VDB_RETRIEVER_MODEL_NAME:-meta/llama-3.1-70b-instruct} | ||
| temperature: 0.0 | ||
| max_tokens: 2000 | ||
| top_p: 0.01 | ||
| do_auto_retry: True | ||
| max_retries: 5 | ||
| retry_on_status_codes: [429, 500, 502, 503, 504] | ||
| retry_on_errors: ["Too Many Requests", "Internal Server Error", "Bad Gateway", "Service Unavailable", "Gateway Time-out", "Gateway Timeout"] | ||
| cve_agent_executor_llm: | ||
| _type: nim | ||
| base_url: ${NVIDIA_API_BASE:-https://integrate.api.nvidia.com/v1} | ||
| model_name: ${CVE_AGENT_EXECUTOR_MODEL_NAME:-meta/llama-3.1-70b-instruct} | ||
| temperature: 0.0 | ||
| max_tokens: 2000 | ||
| top_p: 0.01 | ||
| do_auto_retry: True | ||
| max_retries: 5 | ||
| retry_on_status_codes: [429, 500, 502, 503, 504] | ||
| retry_on_errors: ["Too Many Requests", "Internal Server Error", "Bad Gateway", "Service Unavailable", "Gateway Time-out", "Gateway Timeout"] | ||
| summarize_llm: | ||
| _type: nim | ||
| base_url: ${NVIDIA_API_BASE:-https://integrate.api.nvidia.com/v1} | ||
| model_name: ${SUMMARIZE_MODEL_NAME:-meta/llama-3.1-70b-instruct} | ||
| temperature: 0.0 | ||
| max_tokens: 1024 | ||
| top_p: 0.01 | ||
| do_auto_retry: True | ||
| max_retries: 5 | ||
| retry_on_status_codes: [429, 500, 502, 503, 504] | ||
| retry_on_errors: ["Too Many Requests", "Internal Server Error", "Bad Gateway", "Service Unavailable", "Gateway Time-out", "Gateway Timeout"] | ||
| justify_llm: | ||
| _type: nim | ||
| base_url: ${NVIDIA_API_BASE:-https://integrate.api.nvidia.com/v1} | ||
| model_name: ${JUSTIFY_MODEL_NAME:-meta/llama-3.1-70b-instruct} | ||
| temperature: 0.0 | ||
| max_tokens: 1024 | ||
| top_p: 0.01 | ||
| do_auto_retry: True | ||
| max_retries: 5 | ||
| retry_on_status_codes: [429, 500, 502, 503, 504] | ||
| retry_on_errors: ["Too Many Requests", "Internal Server Error", "Bad Gateway", "Service Unavailable", "Gateway Time-out", "Gateway Timeout"] | ||
|
|
||
| embedders: | ||
| nim_embedder: | ||
| _type: nim | ||
| base_url: ${NIM_EMBED_BASE_URL:-https://integrate.api.nvidia.com/v1} | ||
| model_name: ${EMBEDDER_MODEL_NAME:-nvidia/nv-embedqa-e5-v5} | ||
| truncate: END | ||
| max_batch_size: 128 | ||
| do_auto_retry: True | ||
| max_retries: 5 | ||
| retry_on_status_codes: [429, 500, 502, 503, 504] | ||
| retry_on_errors: ["Too Many Requests", "Internal Server Error", "Bad Gateway", "Service Unavailable", "Gateway Time-out", "Gateway Timeout"] | ||
|
|
||
| workflow: | ||
| _type: cve_agent | ||
| cve_generate_vdbs_name: cve_generate_vdbs | ||
| cve_fetch_intel_name: cve_fetch_intel | ||
| cve_process_sbom_name: cve_process_sbom | ||
| cve_check_vuln_deps_name: cve_check_vuln_deps | ||
| cve_checklist_name: cve_checklist | ||
| cve_agent_executor_name: cve_agent_executor | ||
| cve_summarize_name: cve_summarize | ||
| cve_justify_name: cve_justify | ||
| cve_output_config_name: cve_file_output | ||
|
|
||
| eval: | ||
| general: | ||
| output_dir: ./.tmp/evaluators | ||
| dataset: | ||
| _type: custom | ||
| file_path: data/eval_datasets/eval_dataset.json | ||
| function: vuln_analysis.eval.parse_eval_input.parse_input | ||
|
|
||
| evaluators: | ||
| status_accuracy: | ||
| _type: accuracy | ||
| field: status | ||
| duplicates_policy: drop_all # Options: drop_all, keep_first, keep_all | ||
| label_accuracy: | ||
| _type: accuracy | ||
| field: label | ||
| duplicates_policy: drop_all | ||
|
|
||
| # Uncomment to enable consistency evaluator | ||
| # NOTE: Only use this evaluator if evaluation is being run with multiple repetitions | ||
| # status_consistency: | ||
| # _type: consistency | ||
| # field: status | ||
| # label_consistency: | ||
| # _type: consistency | ||
| # field: label |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,103 @@ | ||
| [ | ||
| { | ||
| "id": 1, | ||
| "question": "{\"image\":{\"name\":\"nvcr.io\/nvidia\/morpheus\/morpheus\",\"tag\":\"23.11-runtime\",\"source_info\":[{\"type\":\"code\",\"git_repo\":\"https:\/\/github.com\/nv-morpheus\/Morpheus.git\",\"ref\":\"v23.11.01\",\"include\":[\"**\/*.cpp\",\"**\/*.cu\",\"**\/*.cuh\",\"**\/*.h\",\"**\/*.hpp\",\"**\/*.ipynb\",\"**\/*.py\",\"**\/*Dockerfile\"],\"exclude\":[\"tests\/**\/*\"]},{\"type\":\"doc\",\"git_repo\":\"https:\/\/github.com\/nv-morpheus\/Morpheus.git\",\"ref\":\"v23.11.01\",\"include\":[\"**\/*.md\",\"docs\/**\/*.rst\"]}],\"sbom_info\":{\"_type\":\"file\",\"file_path\":\"data\/sboms\/nvcr.io\/nvidia\/morpheus\/morpheus:v23.11.01-runtime.sbom\"}},\"scan\":{\"vulns\":[{\"vuln_id\":\"GHSA-3f63-hfp8-52jq\"},{\"vuln_id\":\"CVE-2023-50782\"}]}}", | ||
| "answer": "N/A" | ||
| { | ||
| "dataset_id": "example-eval-dataset", | ||
| "dataset_description": "Example eval dataset with two containers", | ||
| "containers": { | ||
| "morpheus:23.11-runtime": { | ||
| "container_image": { | ||
| "name": "nvcr.io/nvidia/morpheus/morpheus", | ||
| "tag": "23.11-runtime", | ||
| "source_info": [ | ||
| { | ||
| "type": "code", | ||
| "git_repo": "https://github.com/nv-morpheus/Morpheus.git", | ||
| "ref": "branch-23.11", | ||
| "include": [ | ||
| "**/*.cpp", | ||
| "**/*.cu", | ||
| "**/*.cuh", | ||
| "**/*.h", | ||
| "**/*.hpp", | ||
| "**/*.ipynb", | ||
| "**/*.py", | ||
| "**/*Dockerfile" | ||
| ], | ||
| "exclude": [ | ||
| "tests/**/*" | ||
| ] | ||
| }, | ||
| { | ||
| "type": "doc", | ||
| "git_repo": "https://github.com/nv-morpheus/Morpheus.git", | ||
| "ref": "branch-23.11", | ||
| "include": [ | ||
| "**/*.md", | ||
| "docs/**/*.rst" | ||
| ] | ||
| } | ||
| ], | ||
| "sbom_info": { | ||
| "_type": "file", | ||
| "file_path": "data/sboms/nvcr.io/nvidia/morpheus/morpheus:v23.11.01-runtime.sbom" | ||
| } | ||
| }, | ||
| "ground_truth": [ | ||
| { | ||
| "vuln_id": "GHSA-3f63-hfp8-52jq", | ||
| "status": "NOT AFFECTED", | ||
| "label": "code_not_reachable" | ||
| }, | ||
| { | ||
| "vuln_id": "CVE-2023-5388", | ||
| "status": "NOT AFFECTED", | ||
| "label": "false_positive" | ||
| } | ||
| ] | ||
| }, | ||
| "morpheus:24.03-runtime": { | ||
| "container_image": { | ||
| "name": "nvcr.io/nvidia/morpheus/morpheus", | ||
| "tag": "v24.03.02-runtime", | ||
| "source_info": [ | ||
| { | ||
| "type": "code", | ||
| "git_repo": "https://github.com/nv-morpheus/Morpheus.git", | ||
| "ref": "v24.03.02", | ||
| "include": [ | ||
| "**/*.cpp", | ||
| "**/*.cu", | ||
| "**/*.cuh", | ||
| "**/*.h", | ||
| "**/*.hpp", | ||
| "**/*.ipynb", | ||
| "**/*.py", | ||
| "**/*Dockerfile" | ||
| ], | ||
| "exclude": [ | ||
| "tests/**/*" | ||
| ] | ||
| }, | ||
| { | ||
| "type": "doc", | ||
| "git_repo": "https://github.com/nv-morpheus/Morpheus.git", | ||
| "ref": "v24.03.02", | ||
| "include": [ | ||
| "**/*.md", | ||
| "docs/**/*.rst" | ||
| ] | ||
| } | ||
| ], | ||
| "sbom_info": { | ||
| "_type": "file", | ||
| "file_path": "data/sboms/nvcr.io/nvidia/morpheus/morpheus:v24.03.02-runtime.sbom" | ||
| } | ||
| }, | ||
| "ground_truth": [ | ||
| { | ||
| "vuln_id": "CVE-2023-5388", | ||
| "status": "NOT AFFECTED", | ||
| "label": "false_positive" | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| ] | ||
| } |
7 changes: 7 additions & 0 deletions
7
src/vuln_analysis/data/profiler_datasets/profiler_dataset.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| [ | ||
| { | ||
| "id": 1, | ||
| "question": "{\"image\":{\"name\":\"nvcr.io\/nvidia\/morpheus\/morpheus\",\"tag\":\"23.11-runtime\",\"source_info\":[{\"type\":\"code\",\"git_repo\":\"https:\/\/github.com\/nv-morpheus\/Morpheus.git\",\"ref\":\"v23.11.01\",\"include\":[\"**\/*.cpp\",\"**\/*.cu\",\"**\/*.cuh\",\"**\/*.h\",\"**\/*.hpp\",\"**\/*.ipynb\",\"**\/*.py\",\"**\/*Dockerfile\"],\"exclude\":[\"tests\/**\/*\"]},{\"type\":\"doc\",\"git_repo\":\"https:\/\/github.com\/nv-morpheus\/Morpheus.git\",\"ref\":\"v23.11.01\",\"include\":[\"**\/*.md\",\"docs\/**\/*.rst\"]}],\"sbom_info\":{\"_type\":\"file\",\"file_path\":\"data\/sboms\/nvcr.io\/nvidia\/morpheus\/morpheus:v23.11.01-runtime.sbom\"}},\"scan\":{\"vulns\":[{\"vuln_id\":\"GHSA-3f63-hfp8-52jq\"},{\"vuln_id\":\"CVE-2023-50782\"}]}}", | ||
| "answer": "N/A" | ||
| } | ||
| ] |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.