Tech reviews, sponsored videos and collaborations. Contact via youtube.com/@RainyTechLab
Good points, Ahmet. The sample line in the post is the same authentication/authorization question I used for the before/after answers, so as written, that comparison shows behaviour on a trained example, not generalisation. To be precise on selection: I picked step 10 from that one answer, not from the two held-out test prompts. That's still a weak basis, though. A small validation rubric to pick the checkpoint, then untouched held-out answers, is the cleaner setup. Thanks for spelling it out.
Thanks, that part is done now. tools.py in the repo and the snippet in the article both look the tool up with TOOLS.get(name) and check the argument names against the function's signature (inspect.signature) before running anything. An unknown tool or an unexpected field never reaches a handler. It goes back to the model as the tool message for that call. To be honest, two things aren't there yet. The error is still a plain string, not a structured object. And the check only catches extra fields, not missing required ones. Neither function takes arguments right now, so that hasn't come up yet. There are no tests either. The two-call case was only checked by hand in the video run: one response asked for get_disk_free and get_memory, and both results came back in order (150 GB disk free, 61% of 16 GB memory free). Your two regression cases are a good checklist for when I add a tool that takes arguments.
Honestly, it was a budget I set up front. The command was --iters 300 with an eval and a checkpoint saved every 100 steps. I only picked the step-100 checkpoint afterwards, once I saw val loss go 1.382 → 1.665 → 1.811 while train loss kept dropping to 0.046. Looking back, 300 was far too many for the data. It's 108 training examples at batch size 4, so about 27 steps per epoch. 300 steps is roughly 11 passes over the same data, and step 100 is already about 3.7. The validation set is also small (only 12 examples), and I only checked it every 100 steps. So 100 is just the best of the three points I measured, not the actual lowest point. The real minimum could be anywhere from about step 50 to 150. Next time I'll run eval every 25 steps and stop when val loss stops improving. Thanks for raising it. It's an easy one to miss when the training curve looks so good.
Good catch, thank you! You're right: I shortened the loop for the article, and that version always calls get_disk_free() and re-appends the assistant message for every call. The code in the repo does it your way: a TOOLS dict mapping each name to its function, response.message appended once, then TOOLS[call.function.name](**call.function.arguments) for each call. It doesn't validate arguments yet, so I'll add that and fix the snippet in the article. The full version is tools.py in the GitHub repo linked at the top of the post.