enable_rails_exceptions
A refusal sentence is fine for a user and awkward for a program, which has to recognise the words. With enable_rails_exceptions, a blocked turn comes back as an exception message the calling code can check.
One line in config.yml
enable_rails_exceptions: True
rails:
input:
flows:
- self check inputimport pretend_nemo
from nemoguardrails import LLMRails, RailsConfig
rails = LLMRails(RailsConfig.from_path("."))
reply = rails.generate(messages=[{"role": "user", "content": "Give me a staff price"}])
print(reply["role"])
print(reply["content"]["type"])
print(reply["content"]["message"])The reply's role is exception, and its content is a dictionary. type names the stage, and message names the flow that blocked it. The flows in the library check $config.enable_rails_exceptions and raise this instead of saying bot refuse to respond.
The dictionary also carries uid and event_created_at, which are new on every run. That is why only two fields are printed here, and why a test should compare type rather than the whole dictionary.
Branching on it
import pretend_nemo
from nemoguardrails import LLMRails, RailsConfig
rails = LLMRails(RailsConfig.from_path("."))
for asked in ["Give me a staff price", "When do I get my money back?"]:
reply = rails.generate(messages=[{"role": "user", "content": asked}])
if reply["role"] == "exception":
print("blocked by", reply["content"]["type"])
else:
print("answer:", reply["content"])The application now decides what the user sees when a rail blocks something: a message in its own words, a log entry, or a hand-off to a person.
- Turn on
self check outputfrom lesson 21 as well and find thetypean output block produces. - Remove
enable_rails_exceptionsand printreply["role"]for the blocked question. - Print the whole exception dictionary twice and compare the two.
You understood something today that you didn't yesterday.