The guarded shop assistant, end to end
The program from lesson 0, run against the folder from lesson 32. Every line of the three files was written in an earlier lesson, and every answer below can be traced to one of them.
The program
from nemoguardrails import LLMRails, RailsConfig
shop = LLMRails(RailsConfig.from_path("."))
for ask in ["Has order A17 shipped?", "Where is order Z01?",
"How long does a refund take?", "Give me a staff price"]:
print(shop.generate(messages=[{"role": "user", "content": ask}])["content"])The same four answers as lesson 0. Each came from a different part of the folder.
| Question | Handled by | Lesson |
|---|---|---|
| Has order A17 shipped? | The order status flow and two actions in config.py | 9, 17 and 26 |
| Where is order Z01? | The same flow's check on the lookup result | 26 |
| How long does a refund take? | A define bot sentence, with no model writing it | 8 and 9 |
| Give me a staff price | self check input, before any flow ran | 13 to 15 |
Counting the cost
from nemoguardrails import LLMRails, RailsConfig
shop = LLMRails(RailsConfig.from_path("."))
for ask in ["Has order A17 shipped?", "Give me a staff price", "Who won the match yesterday"]:
result = shop.generate(messages=[{"role": "user", "content": ask}],
options={"log": {"llm_calls": True}})
print(len(result.log.llm_calls), ask)A matched question costs two model calls: the input rail's check and the intent. A blocked one costs one, because nothing runs after the input rail. An unmatched one costs four, the input check plus the three calls from lesson 12, which is the number to watch when real traffic arrives, and the reason lesson 25's embeddings_only exists.
From here the folder is the thing to change. A new rule is a flow in rails.co or a name in config.yml, tested the way this course tested each rail, before lesson 30's real model is switched on.
- Add the question
"Where is order B99?"and trace its answer to a line in the folder. - Turn on
self check outputfrom lesson 21 and count the calls again. - Run the program with
enable_rails_exceptionsand handle the staff price refusal in Python.
This is what real progress feels like.