NeMo Guardrailsnemoguardrails 0.24.0 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
35 small wins to finish your pathNext lesson

Changing the answer instead of refusing

Refusing is not the only thing an output rail can do. It can replace the reply with a safer one and let the conversation carry on, by assigning to $bot_message.

Assigning to $bot_message

text
define flow mask staff codes
  $leak = execute has_staff_code
  if $leak
    $bot_message = "Use the code on your receipt for a staff price."

No bot statement and no stop: the flow changes the value the runtime is about to send. Lesson 20 named the other route, an action that returns RailOutcome.transform with TransformTarget.BOT_MESSAGE; assigning in the flow is the shorter of the two when the new text is fixed.

Example
import pretend_nemo
from nemoguardrails import LLMRails, RailsConfig

from config_actions import has_staff_code

rails = LLMRails(RailsConfig.from_path("."))
rails.register_action(has_staff_code, "has_staff_code")
rails.llm.say('Bot message: "Use code STAFF20 for a staff price."', task="generate_bot_message")
result = rails.generate(messages=[{"role": "user", "content": "Any deals for staff?"}],
                        options={"log": {"activated_rails": True}})
print(result.response[0]["content"])
print([(rail.type, rail.name, rail.stop) for rail in result.log.activated_rails][-1])

The user got the replacement sentence, and the output rail is in the log with stop set to False: the turn finished normally, with different words.

Choose between the two on what the user needs next. A refusal ends the exchange. A rewrite keeps it going, which suits a reply that was mostly right and had one thing in it that must not be sent.

Try it yourself
  • Build the rewritten sentence from part of the original $bot_message instead of a fixed string.
  • Put hide staff codes from lesson 22 after mask staff codes in the list and predict which one wins.
  • Rewrite the action to return RailOutcome.transform and read the reply the runtime sends.

Slow is fine. Stopping is the only problem.