Skip to main content

headless_lms_chatbot/azure_chatbot/client_tool_calls/
abort.rs

1//! Why a suspended tool call is closed without ever being carried out, and the text the model
2//! reads for it.
3
4use crate::chatbot_tools::ClientToolCallRefusal;
5use crate::prelude::*;
6
7/// Why a tool call's output was written without running the call.
8pub(crate) enum ToolCallAbortReason {
9    /// The turn that made this call died; a later request is repairing it.
10    Hanging,
11    /// The learner sent a new message instead of answering it.
12    Replaced,
13    /// The caller may not make this call: either they never could, or the roles that let them
14    /// were changed while it waited for the client.
15    NotAuthorized,
16    /// The category this call's tool belongs to was disabled on the configuration while it
17    /// waited for the client.
18    CategoryDisabled,
19}
20
21impl ToolCallAbortReason {
22    /// The output the model reads for a call closed this way.
23    ///
24    /// Prompt text: keep every variant byte-identical, or the model's behavior on seeing it changes.
25    pub(crate) fn model_output(&self) -> &'static str {
26        match self {
27            Self::Hanging => "Unexpected error encountered, tool call aborted.",
28            Self::Replaced => {
29                "The user sent a new message instead of answering this tool call, so it was never carried out and returned no data. Answer their new message; ask again only if you still need this."
30            }
31            Self::NotAuthorized => {
32                "The tool call was aborted and returned no data, because the user is not allowed to use this tool on what the call named. Do not call this tool again in this conversation. Answer without it, or tell the user that you cannot do that step for them."
33            }
34            Self::CategoryDisabled => {
35                "The tool call was aborted and returned no data, because this chatbot no longer offers this kind of tool: its configuration changed while the call was waiting for them. Do not call this tool again in this conversation. Answer without it, or tell the user that you cannot do that step for them."
36            }
37        }
38    }
39}
40
41/// The output the model reads for a call `check_client_tool_call` refused.
42///
43/// The refusal is checked both when the server plans to suspend on a call and when a client's
44/// answer to one arrives, since nothing bounds how long a call waits and a role or a
45/// configuration can change while it does.
46pub(crate) fn refused_call_output(refusal: ClientToolCallRefusal, tool_name: &str) -> &'static str {
47    match refusal {
48        ClientToolCallRefusal::NotAuthorized => {
49            warn!(
50                tool_name,
51                "Aborting a chatbot tool call: its caller is not allowed to make it"
52            );
53            ToolCallAbortReason::NotAuthorized.model_output()
54        }
55        ClientToolCallRefusal::CategoryDisabled => {
56            warn!(
57                tool_name,
58                "Aborting a chatbot tool call: its category is no longer enabled on the chatbot configuration"
59            );
60            ToolCallAbortReason::CategoryDisabled.model_output()
61        }
62    }
63}