1414# limitations under the License.
1515
1616import logging
17- from typing import Dict , Optional
17+ from typing import Dict , List , Optional
1818
1919from nemoguardrails import RailsConfig
2020from nemoguardrails .actions import action
21- from nemoguardrails .actions .llm .utils import llm_call , warn_if_truncated
22- from nemoguardrails .context import llm_call_info_var
21+ from nemoguardrails .library .self_check .utils import (
22+ SELF_CHECK_OUTPUT_DEFAULT_TASK ,
23+ SELF_CHECK_OUTPUT_FLOW ,
24+ SELF_CHECK_OUTPUT_TASK_PARAM ,
25+ resolve_self_check_task ,
26+ run_self_check_task ,
27+ )
2328from nemoguardrails .llm .taskmanager import LLMTaskManager
24- from nemoguardrails .logging .explain import LLMCallInfo
2529from nemoguardrails .types import LLMModel
2630
2731log = logging .getLogger (__name__ )
2832
29- DEFAULT_TASK = "self_check_output"
30-
31-
32- def _get_llm (
33- llms : Dict [str , LLMModel ], task : str , default_task : str , default_llm : Optional [LLMModel ]
34- ) -> Optional [LLMModel ]:
35- if task in llms :
36- return llms [task ]
37- elif default_task in llms :
38- log .debug (f"No model found with type={ task } , falling back to default { default_task } model" )
39- return llms [default_task ]
40- elif default_llm is not None :
41- log .debug (f"No model found with type={ task } or type={ default_task } , falling back to main model" )
42- return default_llm
43- else :
44- error_msg = (
45- f"No matching model for task={ task } found. "
46- f"Please configure a model with type={ task } , type={ default_task } , or type=main"
47- )
48- raise ValueError (error_msg )
33+ DEFAULT_TASK = SELF_CHECK_OUTPUT_DEFAULT_TASK
4934
5035
5136@action (is_system_action = True , output_mapping = lambda value : not value )
5237async def self_check_output (
5338 llms : Dict [str , LLMModel ],
5439 llm_task_manager : LLMTaskManager ,
5540 context : Optional [dict ] = None ,
41+ events : Optional [List [dict ]] = None ,
5642 llm : Optional [LLMModel ] = None ,
5743 config : Optional [RailsConfig ] = None ,
58- task : str = DEFAULT_TASK ,
44+ task : Optional [ str ] = None ,
5945 ** kwargs ,
6046):
6147 """Checks if the output from the bot.
@@ -70,57 +56,40 @@ async def self_check_output(
7056 True if the output should be allowed, False otherwise.
7157 """
7258
73- _MAX_TOKENS = 1024
59+ context = context or {}
7460 bot_response = context .get ("bot_message" )
7561 user_input = context .get ("user_message" )
7662 bot_thinking = context .get ("bot_thinking" )
7763
78- # guard against an unset $task variable
79- if task .startswith ("$" ) and task .endswith ("_task" ):
80- task = DEFAULT_TASK
81-
82- llm = _get_llm (llms , task , default_task = DEFAULT_TASK , default_llm = llm )
64+ task = resolve_self_check_task (
65+ task ,
66+ context ,
67+ events ,
68+ triggered_rail_key = "triggered_output_rail" ,
69+ start_rail_event_type = "StartOutputRail" ,
70+ flow_id = SELF_CHECK_OUTPUT_FLOW ,
71+ task_param = SELF_CHECK_OUTPUT_TASK_PARAM ,
72+ default_task = DEFAULT_TASK ,
73+ )
8374
8475 if bot_response :
85- prompt = llm_task_manager . render_task_prompt (
76+ is_safe , response = await run_self_check_task (
8677 task = task ,
87- context = {
78+ prompt_context = {
8879 "user_input" : user_input ,
8980 "bot_response" : bot_response ,
9081 "bot_thinking" : bot_thinking ,
9182 },
83+ llms = llms ,
84+ default_task = DEFAULT_TASK ,
85+ main_llm = llm ,
86+ llm_task_manager = llm_task_manager ,
87+ lowest_temperature = config .lowest_temperature ,
9288 )
93- stop = llm_task_manager .get_stop_tokens (task = task )
94- max_tokens = llm_task_manager .get_max_tokens (task = task )
95- max_tokens = max_tokens or _MAX_TOKENS
96-
97- # Initialize the LLMCallInfo object
98- llm_call_info_var .set (LLMCallInfo (task = task ))
99-
100- llm_response = await llm_call (
101- llm ,
102- prompt ,
103- stop = stop ,
104- llm_params = {
105- "temperature" : config .lowest_temperature ,
106- "max_tokens" : max_tokens ,
107- },
108- )
109- warn_if_truncated (llm_response , task )
110- response = llm_response .content
11189
11290 if task == DEFAULT_TASK :
11391 log .info (f"Output self-checking result is: `{ response } `." )
11492 else :
11593 log .info (f"Output self-checking result for task={ task } is: `{ response } `." )
11694
117- # for sake of backward compatibility
118- # if the output_parser is not registered we will use the default one
119- if llm_task_manager .has_output_parser (task ):
120- result = llm_task_manager .parse_task_output (task , output = response )
121- else :
122- result = llm_task_manager .parse_task_output (task , output = response , forced_output_parser = "is_content_safe" )
123-
124- is_safe = result [0 ]
125-
12695 return is_safe
0 commit comments