chatbot1-11 Exercise 2: Your Own Golden Conversation ======================================================= ex2.py (save in the project root): import asyncio, json, pathlib, tempfile from bot.golden import check CASE = { "name": "my first golden conversation", "script": ["We open at nine.", {"error": "ServerError"}, "Back again."], "options": {"safety": {"disclosure": None}}, "turns": [ {"say": "When do you open?"}, {"say": "And on Sundays?"}, {"say": "Are you there?"}, {"say": "/help"}, ], } async def main(): with tempfile.TemporaryDirectory() as d: path = pathlib.Path(d) / "mine.json" path.write_text(json.dumps(CASE, indent=2), encoding="utf8") print("1. First run, no expectations written yet (every turn 'differs'), with update=True to record them:") await check(path, update=True) for turn in json.loads(path.read_text(encoding="utf8"))["turns"]: print(f" {turn['say']!r:<26} -> {turn['reply'][:60]!r}") print("2. Check again with no changes:", await check(path) or "passes") print("3. Someone changes what the bot says for /help (simulated by editing the expectation):") data = json.loads(path.read_text(encoding="utf8")) data["turns"][3]["reply"] = "Commands: just ask me anything!" path.write_text(json.dumps(data), encoding="utf8") for p in await check(path): print(" ", p.replace("\n", "\n ")) asyncio.run(main()) Run with: py ex2.py Output: 1. First run, no expectations written yet (every turn 'differs'), with update=True to record them: 'When do you open?' -> 'We open at nine.' 'And on Sundays?' -> '' 'Are you there?' -> 'Back again.' '/help' -> 'Commands:\n/remember ask me to remember something ab' 2. Check again with no changes: passes 3. Someone changes what the bot says for /help (simulated by editing the expectation): mine.json turn 4 ('/help'): expected: 'Commands: just ask me anything!' got: 'Commands:\n/remember ask me to remember something about you\n/facts list what I remember\n/forget forget one thing (or /forget all)\n/reset clear this conversation\n/export show everything I have stored for you as JSON\n/privacy what I store and for how long\n/deleteme erase your chats and notes' What you must do before committing a file produced by --update: READ every changed expectation, and decide for each one whether the new text is what you want the bot to say. --update records what the code does now, so it will record a bug as readily as a deliberate change. If a diff shows a reply you did not mean to change, fix the code, not the golden file. Note the second turn: the scripted ServerError reaches the caller (the bot does not catch provider errors; the channel adapters do), and the golden player records it as "" so that the transcript still has a line for that turn. WHY THIS WORKS AS AN ANSWER --------------------------- The case lists the model's scripted replies (a text, an error, a text), the settings, and the turns. check() plays the turns through a fresh Bot with a fake clock and compares each reply with the expected one. With update=True it writes the actual replies into the file. A later change to any reply (here a hand edit to the /help text) produces a message naming the turn and showing the expected and actual text, which is exactly what a reviewer needs to decide whether the change was intended.