Skip to content

Commit

Permalink
Merge pull request #334 from NVIDIA/feature/colang-2.0
Browse files Browse the repository at this point in the history
Colang 2.0 - Preview
  • Loading branch information
drazvan committed Feb 15, 2024
2 parents d098c52 + d452bc2 commit 1edbd2b
Show file tree
Hide file tree
Showing 150 changed files with 19,654 additions and 570 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ coverage.xml
.eggs
mellon.egg-info
scratch.py
.vscode
*.egg-info
firebase.json
build
Expand All @@ -26,3 +25,4 @@ original_dataset
eval_outputs
/**/chitchat/user.co
/**/banking/user.co
.mypy_cache
31 changes: 17 additions & 14 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,25 @@
# Note that environment variables can be set in several places
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
- test
- test
sast:
stage: test
stage: test
include:
- template: Security/SAST.gitlab-ci.yml
- template: Security/SAST.gitlab-ci.yml

# Runs the tests suite
test:
stage: test
image: python:3.8
cache:
key: "feature--speed-up-ci-with-cache-non_protected"
paths:
- .cache/pip
before_script:
- pip install --cache-dir .cache/pip ".[dev,sdd]"
script:
- python -m pytest --cov=./nemoguardrails --cov=./examples --no-cov-on-fail --cov-fail-under=55
coverage: /(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/
stage: test
image: python:3.10
cache:
key: "feature--speed-up-ci-with-cache-non_protected"
paths:
- .cache/pip
before_script:
- pip install --upgrade pip
- pip --version
- pip install --cache-dir .cache/pip .[dev]
- pip install -e .[sdd]
script:
- python -m pytest --cov=./nemoguardrails --cov=./examples --no-cov-on-fail --cov-fail-under=55
coverage: /(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/
17 changes: 17 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"recommendations": [
"ms-python.python",
"ms-python.vscode-pylance",
"ms-python.isort",
"ms-python.mypy-type-checker",
"ms-python.pylint",
"ms-python.flake8",
"ms-python.autopep8",
"ms-python.black-formatter",
"mhutchie.git-graph",
"streetsidesoftware.code-spell-checker",
"esbenp.prettier-vscode",
"davidanson.vscode-markdownlint",
"tamasfe.even-better-toml"
]
}
70 changes: 70 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug python (current file)",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${workspaceFolder}${pathSeparator}${env:PYTHONPATH}"
}
},
{
"name": "Debug story (current directory)",
"type": "debugpy",
"request": "launch",
"console": "integratedTerminal",
"module": "nemoguardrails",
"args": [
"chat",
"--config=${fileDirname}",
"--verbose",
"--verbose-llm-calls",
"--debug-level=DEBUG"
],
"justMyCode": true,
"env": {
"PYTHONPATH": "${workspaceFolder}${pathSeparator}${env:PYTHONPATH}"
}
},
{
"name": "Run story verbose (current directory)",
"type": "debugpy",
"request": "launch",
"console": "integratedTerminal",
"module": "nemoguardrails",
"args": [
"chat",
"--config=${fileDirname}",
"--verbose",
"--verbose-llm-calls"
],
"justMyCode": true,
"env": {
"PYTHONPATH": "${workspaceFolder}${pathSeparator}${env:PYTHONPATH}"
}
},
{
"name": "Run story (current directory)",
"type": "debugpy",
"request": "launch",
"console": "integratedTerminal",
"module": "nemoguardrails",
"args": ["chat", "--config=${fileDirname}"],
"justMyCode": true,
"env": {
"PYTHONPATH": "${workspaceFolder}${pathSeparator}${env:PYTHONPATH}"
}
},
{
"name": "Run mypy",
"type": "debugpy",
"request": "launch",
"program": "",
"console": "integratedTerminal",
"preLaunchTask": "Run mypy"
}
]
}
82 changes: 82 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
{
// GENERAL
"editor.rulers": [120],
"editor.formatOnSave": true,
"files.trimTrailingWhitespace": true,
"files.trimFinalNewlines": true,
"prettier.tabWidth": 4,
"isort.args": ["--profile", "black"],

// MARKDOWN
"[markdown]": {
"editor.wordWrap": "bounded",
"editor.wordWrapColumn": 120,
"editor.defaultFormatter": "DavidAnson.vscode-markdownlint"
},

// JSONC
"[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},

// JSON
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},

// YAML
"[yaml]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},

// YAML
"[yml]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},

// PYTHON
"[python]": {
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit"
},
"editor.defaultFormatter": "ms-python.black-formatter"
},
"python.envFile": "${workspaceFolder}/.venv",
"python.languageServer": "Pylance",
"python.testing.pytestEnabled": true,
"python.testing.pytestArgs": ["${workspaceFolder}/tests"],
"python.testing.unittestEnabled": false,
//"python.envFile": "${workspaceFolder}/python_release.env",

// MYPY
"mypy-type-checker.args": [
"--ignore-missing-imports",
"--follow-imports=silent",
"--show-column-numbers"
// "--disallow-untyped-defs",
// "--disallow-untyped-calls"
],

// CSPELL
"cSpell.words": [
"appendleft",
"colang",
"elif",
"interruptible",
"langchain",
"nemoguardrails",
"orwhen",
"popleft",
"simpleeval",
"statemachine",
"subflow",
"uids",
"UMIM",
"uniquify"
],
"cSpell.enableFiletypes": ["co", "colang"],

// FLAKE8
"flake8.args": ["--max-line-length=120"],
"python.formatting.provider": "none"
}
33 changes: 33 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Run mypy",
"type": "shell",
"command": "python3",
"args": ["-mmypy", "--show-column", "nemoguardrails"],
"problemMatcher": {
"owner": "linter",
"fileLocation": ["relative", "${workspaceFolder}"],
"pattern": {
"regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5
}
},
"presentation": {
"revealProblems": "onProblem",
"clear": true
},
"group": {
"kind": "build"
},
"icon": {
"id": "gear"
}
}
]
}
9 changes: 5 additions & 4 deletions docs/user_guides/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
## Guardrails CLI
For testing purposes, the Guardrails toolkit provides a command line chat that can be used to interact with the LLM.
```
> nemoguardrails chat --config examples/ [--verbose]
> nemoguardrails chat --config examples/ [--verbose] [--verbose-llm-calls]
```
#### Options
- `--config`: The configuration that should be used. Can be a folder or a .co/.yml file.
- `--verbose`: In verbose mode, debugging information is also shown. This includes the entire prompt that is sent to the bot, the flow that is executed, the generated canonical form and the response that is received.
- `--verbose`: In verbose mode, detailed debugging information is also shown.
- `--verbose-llm-calls`: In verbose LLM calls mode, the debugging information includes the entire prompt that is sent to the LLM and the completion.


7. You should now be able to invoke the `nemoguardrails` CLI.
Expand Down Expand Up @@ -58,8 +59,8 @@ For testing purposes, the Guardrails toolkit provides a command line chat that c
--config TEXT Path to a directory containing configuration files
to use. Can also point to a single configuration
file. [default: config]
--verbose / --no-verbose If the chat should be verbose and output the
prompts [default: no-verbose]
--verbose / --no-verbose If the chat should be verbose and output detailed logging information. [default: no-verbose]
--verbose-llm-calls --no-verbose-llm-calls If the chat should be verbose and include the prompts and responses for the LLM calls. [default: no-verbose-llm-calls]
--help Show this message and exit.
```

Expand Down
5 changes: 5 additions & 0 deletions mypy.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[mypy-simpleeval]
ignore_missing_imports = True

[mypy-yaml]
ignore_missing_imports = True
4 changes: 0 additions & 4 deletions nemoguardrails/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import logging

from nemoguardrails.cli import app

if __name__ == "__main__":
# Set the default logging level to INFO
logging.basicConfig(level=logging.WARNING)

app()
20 changes: 18 additions & 2 deletions nemoguardrails/actions/action_dispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@

class ActionDispatcher:
def __init__(
self, load_all_actions: bool = True, config_path: Optional[str] = None
self,
load_all_actions: bool = True,
config_path: Optional[str] = None,
import_paths: Optional[List[str]] = None,
):
"""
Initializes an actions dispatcher.
Expand All @@ -40,6 +43,8 @@ def __init__(
'actions' folder both in the current working directory and in the package.
config_path (str, optional): The path from which the configuration was loaded.
If there are actions at the specified path, it loads them as well.
import_paths (List[str], optional): Additional imported paths from which actions
should be loaded.
"""
log.info("Initializing action dispatcher")

Expand Down Expand Up @@ -71,6 +76,11 @@ def __init__(
for path in config_path:
self.load_actions_from_path(path)

# If there are any imported paths, we load the actions from there as well.
if import_paths:
for import_path in import_paths:
self.load_actions_from_path(import_path)

log.info(f"Registered Actions: {self._registered_actions}")
log.info("Action dispatcher initialized")

Expand Down Expand Up @@ -175,9 +185,15 @@ async def execute_action(
try:
# We support both functions and classes as actions
if inspect.isfunction(fn) or inspect.ismethod(fn):
# We support both sync and async actions.
result = fn(**params)
if inspect.iscoroutine(result):
result = await result
else:
log.warning(
f"Synchronous action `{action_name}` has been called."
)

elif isinstance(fn, Chain):
try:
chain = fn
Expand Down Expand Up @@ -209,7 +225,7 @@ async def execute_action(
result = fn.run(**params)
return result, "success"
except Exception as e:
log.exception(f"Error {e} while execution {action_name}")
log.warning(f"Error while execution {action_name}: {e}")

return None, "failed"

Expand Down
9 changes: 7 additions & 2 deletions nemoguardrails/actions/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,17 @@
from typing import Any, List, Optional


# A decorator that sets a property on the function to indicate if it's a system action or not.
def action(is_system_action: bool = False, name: Optional[str] = None):
def action(
is_system_action: bool = False,
name: Optional[str] = None,
execute_async: bool = False,
):
"""Decorator to mark a function or class as an action.
Args:
is_system_action (bool): Flag indicating if the action is a system action.
name (Optional[str]): The name to associate with the action.
execute_async: Whether the function should be executed in async mode.
Returns:
callable: The decorated function or class.
Expand All @@ -38,6 +42,7 @@ def decorator(fn_or_cls):
fn_or_cls.action_meta = {
"name": name or fn_or_cls.__name__,
"is_system_action": is_system_action,
"execute_async": execute_async,
}
return fn_or_cls

Expand Down
Loading

0 comments on commit 1edbd2b

Please sign in to comment.