hammad-python 0.0.23__py3-none-any.whl → 0.0.24__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hammad/__init__.py +282 -13
- hammad/cli/plugins.py +3 -1
- hammad/genai/__init__.py +51 -0
- hammad/genai/agents/__init__.py +6 -0
- hammad/genai/agents/agent.py +640 -213
- hammad/genai/agents/run.py +50 -12
- hammad/genai/agents/types/agent_response.py +2 -1
- hammad/genai/graphs/__init__.py +113 -0
- hammad/genai/graphs/base.py +1103 -0
- hammad/genai/graphs/plugins.py +316 -0
- hammad/genai/graphs/types.py +638 -0
- hammad/genai/models/language/model.py +46 -0
- hammad/genai/models/language/run.py +22 -4
- hammad/genai/models/language/types/language_model_response.py +1 -1
- hammad/genai/types/tools.py +1 -1
- hammad/logging/logger.py +10 -0
- {hammad_python-0.0.23.dist-info → hammad_python-0.0.24.dist-info}/METADATA +5 -1
- {hammad_python-0.0.23.dist-info → hammad_python-0.0.24.dist-info}/RECORD +20 -21
- hammad/_main/__init__.py +0 -4
- hammad/_main/_fn.py +0 -20
- hammad/_main/_new.py +0 -52
- hammad/_main/_run.py +0 -50
- hammad/_main/_to.py +0 -19
- {hammad_python-0.0.23.dist-info → hammad_python-0.0.24.dist-info}/WHEEL +0 -0
- {hammad_python-0.0.23.dist-info → hammad_python-0.0.24.dist-info}/licenses/LICENSE +0 -0
hammad/genai/agents/agent.py
CHANGED
@@ -210,6 +210,13 @@ def _update_context_object(
|
|
210
210
|
raise ValueError(f"Cannot update context of type {type(context)}")
|
211
211
|
|
212
212
|
|
213
|
+
def mark_complete() -> None:
|
214
|
+
"""If you feel you are ready to respond to the user, or have completed
|
215
|
+
the task given to you, call this function to mark your response as
|
216
|
+
complete."""
|
217
|
+
return "complete"
|
218
|
+
|
219
|
+
|
213
220
|
class Agent(BaseGenAIModel, Generic[T]):
|
214
221
|
"""A generative AI agent that can execute tools, generate structured outputs,
|
215
222
|
and maintain context across multiple conversation steps.
|
@@ -245,6 +252,11 @@ class Agent(BaseGenAIModel, Generic[T]):
|
|
245
252
|
tools: Union[List[Tool], Callable, None] = None,
|
246
253
|
settings: Optional[AgentSettings] = None,
|
247
254
|
instructor_mode: Optional[LanguageModelInstructorMode] = None,
|
255
|
+
# Defaults
|
256
|
+
max_steps: int = 10,
|
257
|
+
# End Strategy
|
258
|
+
end_strategy: Literal["tool"] | None = None,
|
259
|
+
end_tool: Callable = mark_complete,
|
248
260
|
# Context management parameters
|
249
261
|
context_updates: Optional[
|
250
262
|
Union[List[Literal["before", "after"]], Literal["before", "after"]]
|
@@ -256,6 +268,8 @@ class Agent(BaseGenAIModel, Generic[T]):
|
|
256
268
|
context_selection_instructions: Optional[str] = None,
|
257
269
|
context_update_instructions: Optional[str] = None,
|
258
270
|
context_format: Literal["json", "python", "markdown"] = "json",
|
271
|
+
verbose: bool = False,
|
272
|
+
debug: bool = False,
|
259
273
|
**kwargs: Any,
|
260
274
|
):
|
261
275
|
"""Create a new AI agent with specified capabilities and behavior.
|
@@ -272,6 +286,11 @@ class Agent(BaseGenAIModel, Generic[T]):
|
|
272
286
|
tools: List of tools/functions the agent can call, or a single callable
|
273
287
|
settings: AgentSettings object to customize default behavior
|
274
288
|
instructor_mode: Mode for structured output generation
|
289
|
+
max_steps: Default ,aximum number of steps the agent can take before stopping
|
290
|
+
end_strategy: Optional alternative strategy to provide an end tool for determining agent's final
|
291
|
+
response.
|
292
|
+
end_tool: The tool the agent will call to determine if it should stop.
|
293
|
+
This is only used if end_strategy is set to "tool".
|
275
294
|
context_updates: When to update context - "before", "after", or both
|
276
295
|
context_confirm: Whether to confirm context updates with the user
|
277
296
|
context_strategy: How to select context updates - "selective" or "all"
|
@@ -280,6 +299,8 @@ class Agent(BaseGenAIModel, Generic[T]):
|
|
280
299
|
context_selection_instructions: Custom instructions for context selection
|
281
300
|
context_update_instructions: Custom instructions for context updates
|
282
301
|
context_format: Format for context display - "json", "python", or "markdown"
|
302
|
+
verbose: If True, set logger to INFO level for detailed output
|
303
|
+
debug: If True, set logger to DEBUG level for maximum verbosity
|
283
304
|
**kwargs: Additional parameters passed to the underlying language model
|
284
305
|
|
285
306
|
Example:
|
@@ -307,6 +328,17 @@ class Agent(BaseGenAIModel, Generic[T]):
|
|
307
328
|
self.settings = settings or AgentSettings()
|
308
329
|
self.instructor_mode = instructor_mode
|
309
330
|
|
331
|
+
# Store max_steps as instance variable (overrides settings if provided)
|
332
|
+
self.max_steps = max_steps if max_steps is not None else self.settings.max_steps
|
333
|
+
|
334
|
+
# Store end strategy parameters
|
335
|
+
self.end_strategy = end_strategy
|
336
|
+
self.end_tool = end_tool if end_tool is not None else mark_complete
|
337
|
+
|
338
|
+
# Add end_tool to tools if end_strategy is 'tool'
|
339
|
+
if self.end_strategy == "tool":
|
340
|
+
self.tools.append(define_tool(self.end_tool))
|
341
|
+
|
310
342
|
# Process instructions
|
311
343
|
self.instructions = _get_instructions(
|
312
344
|
name=name,
|
@@ -314,11 +346,23 @@ class Agent(BaseGenAIModel, Generic[T]):
|
|
314
346
|
add_name_to_instructions=self.settings.add_name_to_instructions,
|
315
347
|
)
|
316
348
|
|
349
|
+
# Store verbose/debug settings
|
350
|
+
self.verbose = verbose
|
351
|
+
self.debug = debug
|
352
|
+
|
353
|
+
# Set logger level based on verbose/debug flags
|
354
|
+
if debug:
|
355
|
+
logger.level = "debug"
|
356
|
+
elif verbose:
|
357
|
+
logger.level = "info"
|
358
|
+
|
317
359
|
# Initialize the language model
|
318
360
|
if isinstance(model, LanguageModel):
|
319
361
|
self._language_model = model
|
320
362
|
else:
|
321
|
-
self._language_model = LanguageModel(
|
363
|
+
self._language_model = LanguageModel(
|
364
|
+
model=model, verbose=verbose, debug=debug, **kwargs
|
365
|
+
)
|
322
366
|
|
323
367
|
# Context management settings
|
324
368
|
self.context_updates = context_updates
|
@@ -689,6 +733,8 @@ Please update the appropriate fields based on the conversation. Only update fiel
|
|
689
733
|
max_steps: Optional[int] = None,
|
690
734
|
context: Optional[AgentContext] = None,
|
691
735
|
output_type: Optional[Type[T]] = None,
|
736
|
+
end_strategy: Optional[Literal["tool"]] = None,
|
737
|
+
end_tool: Optional[Callable] = None,
|
692
738
|
context_updates: Optional[
|
693
739
|
Union[List[Literal["before", "after"]], Literal["before", "after"]]
|
694
740
|
] = None,
|
@@ -699,6 +745,8 @@ Please update the appropriate fields based on the conversation. Only update fiel
|
|
699
745
|
context_selection_instructions: Optional[str] = None,
|
700
746
|
context_update_instructions: Optional[str] = None,
|
701
747
|
context_format: Optional[Literal["json", "python", "markdown"]] = None,
|
748
|
+
verbose: Optional[bool] = None,
|
749
|
+
debug: Optional[bool] = None,
|
702
750
|
*,
|
703
751
|
stream: Literal[False] = False,
|
704
752
|
**kwargs: Any,
|
@@ -712,6 +760,8 @@ Please update the appropriate fields based on the conversation. Only update fiel
|
|
712
760
|
max_steps: Optional[int] = None,
|
713
761
|
context: Optional[AgentContext] = None,
|
714
762
|
output_type: Optional[Type[T]] = None,
|
763
|
+
end_strategy: Optional[Literal["tool"]] = None,
|
764
|
+
end_tool: Optional[Callable] = None,
|
715
765
|
context_updates: Optional[
|
716
766
|
Union[List[Literal["before", "after"]], Literal["before", "after"]]
|
717
767
|
] = None,
|
@@ -722,6 +772,8 @@ Please update the appropriate fields based on the conversation. Only update fiel
|
|
722
772
|
context_selection_instructions: Optional[str] = None,
|
723
773
|
context_update_instructions: Optional[str] = None,
|
724
774
|
context_format: Optional[Literal["json", "python", "markdown"]] = None,
|
775
|
+
verbose: Optional[bool] = None,
|
776
|
+
debug: Optional[bool] = None,
|
725
777
|
*,
|
726
778
|
stream: Literal[True],
|
727
779
|
**kwargs: Any,
|
@@ -734,6 +786,8 @@ Please update the appropriate fields based on the conversation. Only update fiel
|
|
734
786
|
max_steps: Optional[int] = None,
|
735
787
|
context: Optional[AgentContext] = None,
|
736
788
|
output_type: Optional[Type[T]] = None,
|
789
|
+
end_strategy: Optional[Literal["tool"]] = None,
|
790
|
+
end_tool: Optional[Callable] = None,
|
737
791
|
context_updates: Optional[
|
738
792
|
Union[List[Literal["before", "after"]], Literal["before", "after"]]
|
739
793
|
] = None,
|
@@ -744,6 +798,8 @@ Please update the appropriate fields based on the conversation. Only update fiel
|
|
744
798
|
context_selection_instructions: Optional[str] = None,
|
745
799
|
context_update_instructions: Optional[str] = None,
|
746
800
|
context_format: Optional[Literal["json", "python", "markdown"]] = None,
|
801
|
+
verbose: Optional[bool] = None,
|
802
|
+
debug: Optional[bool] = None,
|
747
803
|
stream: bool = False,
|
748
804
|
**kwargs: Any,
|
749
805
|
) -> Union[AgentResponse[T, AgentContext], AgentStream[T, AgentContext]]:
|
@@ -831,132 +887,320 @@ Please update the appropriate fields based on the conversation. Only update fiel
|
|
831
887
|
**kwargs,
|
832
888
|
)
|
833
889
|
|
834
|
-
#
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
max_steps
|
845
|
-
|
846
|
-
# Get effective context settings
|
847
|
-
effective_context_settings = self._get_effective_context_settings(
|
848
|
-
context_updates=context_updates,
|
849
|
-
context_confirm=context_confirm,
|
850
|
-
context_strategy=context_strategy,
|
851
|
-
context_max_retries=context_max_retries,
|
852
|
-
context_confirm_instructions=context_confirm_instructions,
|
853
|
-
context_selection_instructions=context_selection_instructions,
|
854
|
-
context_update_instructions=context_update_instructions,
|
855
|
-
context_format=context_format,
|
890
|
+
# Set logger level for this request if specified
|
891
|
+
original_level = logger.level
|
892
|
+
if debug or (debug is None and self.debug):
|
893
|
+
logger.level = "debug"
|
894
|
+
elif verbose or (verbose is None and self.verbose):
|
895
|
+
logger.level = "info"
|
896
|
+
|
897
|
+
# Log agent execution start
|
898
|
+
logger.info(f"Starting agent '{self.name}' execution")
|
899
|
+
logger.debug(
|
900
|
+
f"Agent settings: max_steps={max_steps or self.max_steps}, tools={len(self.tools)}"
|
856
901
|
)
|
857
902
|
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
context, "before", effective_context_settings["context_updates"]
|
868
|
-
):
|
869
|
-
context = self._perform_context_update(
|
870
|
-
context=context,
|
871
|
-
model=working_model,
|
872
|
-
current_messages=current_messages,
|
873
|
-
timing="before",
|
874
|
-
effective_settings=effective_context_settings,
|
875
|
-
)
|
876
|
-
|
877
|
-
# Format messages with instructions and context for first step only
|
878
|
-
if step == 0:
|
879
|
-
formatted_messages = self._format_messages_with_context(
|
880
|
-
messages=current_messages,
|
881
|
-
context=context,
|
903
|
+
try:
|
904
|
+
# Use provided model or default
|
905
|
+
if model is None:
|
906
|
+
working_model = self.language_model
|
907
|
+
elif isinstance(model, str):
|
908
|
+
working_model = LanguageModel(
|
909
|
+
model=model,
|
910
|
+
verbose=verbose or self.verbose,
|
911
|
+
debug=debug or self.debug,
|
882
912
|
)
|
883
913
|
else:
|
884
|
-
|
885
|
-
|
886
|
-
# Prepare kwargs for language model
|
887
|
-
model_kwargs = kwargs.copy()
|
888
|
-
if output_type:
|
889
|
-
model_kwargs["type"] = output_type
|
890
|
-
if self.instructor_mode:
|
891
|
-
model_kwargs["instructor_mode"] = self.instructor_mode
|
892
|
-
|
893
|
-
# Get language model response
|
894
|
-
response = working_model.run(
|
895
|
-
messages=formatted_messages,
|
896
|
-
tools=[tool.to_dict() for tool in self.tools] if self.tools else None,
|
897
|
-
**model_kwargs,
|
898
|
-
)
|
914
|
+
working_model = model
|
899
915
|
|
900
|
-
#
|
901
|
-
if
|
902
|
-
|
903
|
-
current_messages.append(response.to_message())
|
916
|
+
# Use provided max_steps or default from instance
|
917
|
+
if max_steps is None:
|
918
|
+
max_steps = self.max_steps
|
904
919
|
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
920
|
+
# Use provided end_strategy or default from instance
|
921
|
+
effective_end_strategy = (
|
922
|
+
end_strategy if end_strategy is not None else self.end_strategy
|
923
|
+
)
|
924
|
+
effective_end_tool = end_tool if end_tool is not None else self.end_tool
|
925
|
+
|
926
|
+
# Create working tools list with end_tool if needed
|
927
|
+
working_tools = self.tools.copy()
|
928
|
+
if effective_end_strategy == "tool" and effective_end_tool is not None:
|
929
|
+
end_tool_obj = define_tool(effective_end_tool)
|
930
|
+
# Only add if not already present
|
931
|
+
if not any(tool.name == end_tool_obj.name for tool in working_tools):
|
932
|
+
working_tools.append(end_tool_obj)
|
933
|
+
|
934
|
+
# Get effective context settings
|
935
|
+
effective_context_settings = self._get_effective_context_settings(
|
936
|
+
context_updates=context_updates,
|
937
|
+
context_confirm=context_confirm,
|
938
|
+
context_strategy=context_strategy,
|
939
|
+
context_max_retries=context_max_retries,
|
940
|
+
context_confirm_instructions=context_confirm_instructions,
|
941
|
+
context_selection_instructions=context_selection_instructions,
|
942
|
+
context_update_instructions=context_update_instructions,
|
943
|
+
context_format=context_format,
|
944
|
+
)
|
912
945
|
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
946
|
+
# Parse initial messages
|
947
|
+
parsed_messages = parse_messages(messages)
|
948
|
+
current_messages = parsed_messages.copy()
|
949
|
+
steps: List[LanguageModelResponse[str]] = []
|
950
|
+
|
951
|
+
# RUN MAIN AGENTIC LOOP
|
952
|
+
logger.debug(f"Starting agentic loop with max_steps={max_steps}")
|
953
|
+
for step in range(max_steps):
|
954
|
+
logger.debug(f"Agent step {step + 1}/{max_steps}")
|
955
|
+
# Update context before processing if configured
|
918
956
|
if context and self._should_update_context(
|
919
|
-
context, "
|
957
|
+
context, "before", effective_context_settings["context_updates"]
|
920
958
|
):
|
921
959
|
context = self._perform_context_update(
|
922
960
|
context=context,
|
923
961
|
model=working_model,
|
924
962
|
current_messages=current_messages,
|
925
|
-
timing="
|
963
|
+
timing="before",
|
926
964
|
effective_settings=effective_context_settings,
|
927
965
|
)
|
928
|
-
|
929
|
-
|
966
|
+
|
967
|
+
# Format messages with instructions and context for first step only
|
968
|
+
if step == 0:
|
969
|
+
formatted_messages = self._format_messages_with_context(
|
970
|
+
messages=current_messages,
|
971
|
+
context=context,
|
972
|
+
)
|
973
|
+
else:
|
974
|
+
formatted_messages = current_messages
|
975
|
+
|
976
|
+
# Prepare kwargs for language model
|
977
|
+
model_kwargs = kwargs.copy()
|
978
|
+
# Don't add output_type for intermediate steps - only for final response
|
979
|
+
if self.instructor_mode:
|
980
|
+
model_kwargs["instructor_mode"] = self.instructor_mode
|
981
|
+
|
982
|
+
# Get language model response
|
983
|
+
response = working_model.run(
|
984
|
+
messages=formatted_messages,
|
985
|
+
tools=[tool.to_dict() for tool in working_tools]
|
986
|
+
if working_tools
|
987
|
+
else None,
|
988
|
+
**model_kwargs,
|
930
989
|
)
|
931
990
|
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
991
|
+
# Check if response has tool calls
|
992
|
+
if response.has_tool_calls():
|
993
|
+
logger.info(
|
994
|
+
f"Agent '{self.name}' making tool calls: {len(response.tool_calls)} tools"
|
995
|
+
)
|
996
|
+
for tool_call in response.tool_calls:
|
997
|
+
logger.debug(
|
998
|
+
f"Tool call: {tool_call.function.name}({tool_call.function.arguments})"
|
999
|
+
)
|
1000
|
+
|
1001
|
+
# Add response to message history (with tool calls)
|
1002
|
+
current_messages.append(response.to_message())
|
1003
|
+
|
1004
|
+
# Execute tools and add their responses to messages
|
1005
|
+
tool_responses = execute_tools_from_language_model_response(
|
1006
|
+
tools=working_tools, response=response
|
1007
|
+
)
|
1008
|
+
# Add tool responses to message history
|
1009
|
+
for tool_resp in tool_responses:
|
1010
|
+
current_messages.append(tool_resp.to_dict())
|
1011
|
+
|
1012
|
+
# This is not the final step, add to steps
|
1013
|
+
steps.append(response)
|
1014
|
+
else:
|
1015
|
+
# No tool calls - check if this is actually the final step based on end_strategy
|
1016
|
+
if effective_end_strategy == "tool":
|
1017
|
+
# Check if the end_tool was called
|
1018
|
+
end_tool_called = (
|
1019
|
+
any(
|
1020
|
+
tool_call.function.name == effective_end_tool.__name__
|
1021
|
+
for tool_call in response.tool_calls
|
1022
|
+
)
|
1023
|
+
if response.tool_calls
|
1024
|
+
else False
|
1025
|
+
)
|
1026
|
+
|
1027
|
+
if not end_tool_called:
|
1028
|
+
# End tool not called, continue the conversation
|
1029
|
+
logger.debug(
|
1030
|
+
f"Agent '{self.name}' step {step + 1}: No end tool called, continuing..."
|
1031
|
+
)
|
1032
|
+
|
1033
|
+
# Add the response to history
|
1034
|
+
current_messages.append(response.to_message())
|
1035
|
+
|
1036
|
+
# Add system message instructing agent to call the end tool
|
1037
|
+
current_messages.append(
|
1038
|
+
{
|
1039
|
+
"role": "system",
|
1040
|
+
"content": f"You must call the {effective_end_tool.__name__} tool to complete your response. Do not provide a final answer until you have called this tool.",
|
1041
|
+
}
|
1042
|
+
)
|
1043
|
+
|
1044
|
+
# Add user message to continue
|
1045
|
+
current_messages.append(
|
1046
|
+
{"role": "user", "content": "continue"}
|
1047
|
+
)
|
1048
|
+
|
1049
|
+
# Remove the continue message and append assistant content
|
1050
|
+
current_messages.pop() # Remove "continue" message
|
1051
|
+
|
1052
|
+
# This is not the final step, add to steps and continue
|
1053
|
+
steps.append(response)
|
1054
|
+
continue
|
1055
|
+
|
1056
|
+
# This is the final step (either no end_strategy or end_tool was called)
|
1057
|
+
logger.info(
|
1058
|
+
f"Agent '{self.name}' completed execution in {step + 1} steps"
|
1059
|
+
)
|
1060
|
+
# Now we can make the final call with the output_type if specified
|
1061
|
+
if output_type:
|
1062
|
+
# Make a final call with the structured output type
|
1063
|
+
final_model_kwargs = kwargs.copy()
|
1064
|
+
final_model_kwargs["type"] = output_type
|
1065
|
+
if self.instructor_mode:
|
1066
|
+
final_model_kwargs["instructor_mode"] = self.instructor_mode
|
1067
|
+
|
1068
|
+
# Create a clean conversation history for structured output
|
1069
|
+
# Include the original messages and the final response content
|
1070
|
+
clean_messages = []
|
1071
|
+
# Add original user messages (excluding tool calls/responses)
|
1072
|
+
for msg in formatted_messages:
|
1073
|
+
if isinstance(msg, dict) and msg.get("role") not in [
|
1074
|
+
"tool",
|
1075
|
+
"assistant",
|
1076
|
+
]:
|
1077
|
+
clean_messages.append(msg)
|
1078
|
+
elif hasattr(msg, "role") and msg.role not in [
|
1079
|
+
"tool",
|
1080
|
+
"assistant",
|
1081
|
+
]:
|
1082
|
+
clean_messages.append(msg.to_dict())
|
1083
|
+
|
1084
|
+
# Add the final assistant response content
|
1085
|
+
clean_messages.append(
|
1086
|
+
{"role": "assistant", "content": response.get_content()}
|
1087
|
+
)
|
1088
|
+
|
1089
|
+
# Use the clean conversation history to generate structured output
|
1090
|
+
final_response = working_model.run(
|
1091
|
+
messages=clean_messages,
|
1092
|
+
**final_model_kwargs,
|
1093
|
+
)
|
1094
|
+
|
1095
|
+
# Update context after processing if configured
|
1096
|
+
if context and self._should_update_context(
|
1097
|
+
context,
|
1098
|
+
"after",
|
1099
|
+
effective_context_settings["context_updates"],
|
1100
|
+
):
|
1101
|
+
context = self._perform_context_update(
|
1102
|
+
context=context,
|
1103
|
+
model=working_model,
|
1104
|
+
current_messages=current_messages,
|
1105
|
+
timing="after",
|
1106
|
+
effective_settings=effective_context_settings,
|
1107
|
+
)
|
1108
|
+
return _create_agent_response_from_language_model_response(
|
1109
|
+
response=final_response, steps=steps, context=context
|
1110
|
+
)
|
1111
|
+
else:
|
1112
|
+
# Update context after processing if configured
|
1113
|
+
if context and self._should_update_context(
|
1114
|
+
context,
|
1115
|
+
"after",
|
1116
|
+
effective_context_settings["context_updates"],
|
1117
|
+
):
|
1118
|
+
context = self._perform_context_update(
|
1119
|
+
context=context,
|
1120
|
+
model=working_model,
|
1121
|
+
current_messages=current_messages,
|
1122
|
+
timing="after",
|
1123
|
+
effective_settings=effective_context_settings,
|
1124
|
+
)
|
1125
|
+
return _create_agent_response_from_language_model_response(
|
1126
|
+
response=response, steps=steps, context=context
|
1127
|
+
)
|
1128
|
+
|
1129
|
+
# Max steps reached - return last response
|
1130
|
+
if steps:
|
1131
|
+
final_response = steps[-1]
|
1132
|
+
# If we have an output_type, make a final structured call
|
1133
|
+
if output_type:
|
1134
|
+
final_model_kwargs = kwargs.copy()
|
1135
|
+
final_model_kwargs["type"] = output_type
|
1136
|
+
if self.instructor_mode:
|
1137
|
+
final_model_kwargs["instructor_mode"] = self.instructor_mode
|
1138
|
+
|
1139
|
+
# Create clean messages for structured output
|
1140
|
+
clean_messages = []
|
1141
|
+
formatted_messages = self._format_messages_with_context(
|
1142
|
+
messages=current_messages,
|
1143
|
+
context=context,
|
1144
|
+
)
|
1145
|
+
|
1146
|
+
# Add original user messages (excluding tool calls/responses)
|
1147
|
+
for msg in formatted_messages:
|
1148
|
+
if isinstance(msg, dict) and msg.get("role") not in [
|
1149
|
+
"tool",
|
1150
|
+
"assistant",
|
1151
|
+
]:
|
1152
|
+
clean_messages.append(msg)
|
1153
|
+
elif hasattr(msg, "role") and msg.role not in [
|
1154
|
+
"tool",
|
1155
|
+
"assistant",
|
1156
|
+
]:
|
1157
|
+
clean_messages.append(msg.to_dict())
|
1158
|
+
|
1159
|
+
# Add final response content
|
1160
|
+
clean_messages.append(
|
1161
|
+
{"role": "assistant", "content": final_response.get_content()}
|
1162
|
+
)
|
1163
|
+
|
1164
|
+
final_response = working_model.run(
|
1165
|
+
messages=clean_messages,
|
1166
|
+
**final_model_kwargs,
|
1167
|
+
)
|
1168
|
+
else:
|
1169
|
+
# No steps taken, make a final call
|
1170
|
+
final_model_kwargs = kwargs.copy()
|
1171
|
+
if output_type:
|
1172
|
+
final_model_kwargs["type"] = output_type
|
1173
|
+
if self.instructor_mode:
|
1174
|
+
final_model_kwargs["instructor_mode"] = self.instructor_mode
|
1175
|
+
|
1176
|
+
final_response = working_model.run(
|
1177
|
+
messages=self._format_messages_with_context(
|
1178
|
+
messages=current_messages,
|
1179
|
+
context=context,
|
1180
|
+
),
|
1181
|
+
**final_model_kwargs,
|
1182
|
+
)
|
1183
|
+
|
1184
|
+
# Update context after processing if configured
|
1185
|
+
if context and self._should_update_context(
|
1186
|
+
context, "after", effective_context_settings["context_updates"]
|
1187
|
+
):
|
1188
|
+
context = self._perform_context_update(
|
940
1189
|
context=context,
|
941
|
-
|
942
|
-
|
943
|
-
|
1190
|
+
model=working_model,
|
1191
|
+
current_messages=current_messages,
|
1192
|
+
timing="after",
|
1193
|
+
effective_settings=effective_context_settings,
|
1194
|
+
)
|
944
1195
|
|
945
|
-
|
946
|
-
|
947
|
-
context, "after", effective_context_settings["context_updates"]
|
948
|
-
):
|
949
|
-
context = self._perform_context_update(
|
950
|
-
context=context,
|
951
|
-
model=working_model,
|
952
|
-
current_messages=current_messages,
|
953
|
-
timing="after",
|
954
|
-
effective_settings=effective_context_settings,
|
1196
|
+
return _create_agent_response_from_language_model_response(
|
1197
|
+
response=final_response, steps=steps, context=context
|
955
1198
|
)
|
956
1199
|
|
957
|
-
|
958
|
-
|
959
|
-
|
1200
|
+
finally:
|
1201
|
+
# Restore original logger level
|
1202
|
+
if debug is not None or verbose is not None:
|
1203
|
+
logger.level = original_level
|
960
1204
|
|
961
1205
|
async def async_run(
|
962
1206
|
self,
|
@@ -975,6 +1219,10 @@ Please update the appropriate fields based on the conversation. Only update fiel
|
|
975
1219
|
context_selection_instructions: Optional[str] = None,
|
976
1220
|
context_update_instructions: Optional[str] = None,
|
977
1221
|
context_format: Optional[Literal["json", "python", "markdown"]] = None,
|
1222
|
+
verbose: Optional[bool] = None,
|
1223
|
+
debug: Optional[bool] = None,
|
1224
|
+
end_strategy: Optional[Literal["tool"]] = None,
|
1225
|
+
end_tool: Optional[Callable] = None,
|
978
1226
|
**kwargs: Any,
|
979
1227
|
) -> AgentResponse[T, AgentContext]:
|
980
1228
|
"""Runs this agent asynchronously and returns a final agent response.
|
@@ -1044,132 +1292,301 @@ Please update the appropriate fields based on the conversation. Only update fiel
|
|
1044
1292
|
... )
|
1045
1293
|
... return response.output
|
1046
1294
|
"""
|
1047
|
-
#
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
context_strategy=context_strategy,
|
1064
|
-
context_max_retries=context_max_retries,
|
1065
|
-
context_confirm_instructions=context_confirm_instructions,
|
1066
|
-
context_selection_instructions=context_selection_instructions,
|
1067
|
-
context_update_instructions=context_update_instructions,
|
1068
|
-
context_format=context_format,
|
1069
|
-
)
|
1070
|
-
|
1071
|
-
# Parse initial messages
|
1072
|
-
parsed_messages = parse_messages(messages)
|
1073
|
-
current_messages = parsed_messages.copy()
|
1074
|
-
steps: List[LanguageModelResponse[str]] = []
|
1075
|
-
|
1076
|
-
# RUN MAIN AGENTIC LOOP
|
1077
|
-
for step in range(max_steps):
|
1078
|
-
# Update context before processing if configured
|
1079
|
-
if context and self._should_update_context(
|
1080
|
-
context, "before", effective_context_settings["context_updates"]
|
1081
|
-
):
|
1082
|
-
context = self._perform_context_update(
|
1083
|
-
context=context,
|
1084
|
-
model=working_model,
|
1085
|
-
current_messages=current_messages,
|
1086
|
-
timing="before",
|
1087
|
-
effective_settings=effective_context_settings,
|
1088
|
-
)
|
1089
|
-
|
1090
|
-
# Format messages with instructions and context for first step only
|
1091
|
-
if step == 0:
|
1092
|
-
formatted_messages = self._format_messages_with_context(
|
1093
|
-
messages=current_messages,
|
1094
|
-
context=context,
|
1295
|
+
# Set logger level for this request if specified
|
1296
|
+
original_level = logger.level
|
1297
|
+
if debug or (debug is None and self.debug):
|
1298
|
+
logger.level = "debug"
|
1299
|
+
elif verbose or (verbose is None and self.verbose):
|
1300
|
+
logger.level = "info"
|
1301
|
+
|
1302
|
+
try:
|
1303
|
+
# Use provided model or default
|
1304
|
+
if model is None:
|
1305
|
+
working_model = self.language_model
|
1306
|
+
elif isinstance(model, str):
|
1307
|
+
working_model = LanguageModel(
|
1308
|
+
model=model,
|
1309
|
+
verbose=verbose or self.verbose,
|
1310
|
+
debug=debug or self.debug,
|
1095
1311
|
)
|
1096
1312
|
else:
|
1097
|
-
|
1098
|
-
|
1099
|
-
# Prepare kwargs for language model
|
1100
|
-
model_kwargs = kwargs.copy()
|
1101
|
-
if output_type:
|
1102
|
-
model_kwargs["type"] = output_type
|
1103
|
-
if self.instructor_mode:
|
1104
|
-
model_kwargs["instructor_mode"] = self.instructor_mode
|
1105
|
-
|
1106
|
-
# Get language model response
|
1107
|
-
response = await working_model.async_run(
|
1108
|
-
messages=formatted_messages,
|
1109
|
-
tools=[tool.to_dict() for tool in self.tools] if self.tools else None,
|
1110
|
-
**model_kwargs,
|
1111
|
-
)
|
1313
|
+
working_model = model
|
1112
1314
|
|
1113
|
-
#
|
1114
|
-
if
|
1115
|
-
|
1116
|
-
current_messages.append(response.to_message())
|
1315
|
+
# Use provided max_steps or default from instance
|
1316
|
+
if max_steps is None:
|
1317
|
+
max_steps = self.max_steps
|
1117
1318
|
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1319
|
+
# Use provided end_strategy or default from instance
|
1320
|
+
effective_end_strategy = (
|
1321
|
+
end_strategy if end_strategy is not None else self.end_strategy
|
1322
|
+
)
|
1323
|
+
effective_end_tool = end_tool if end_tool is not None else self.end_tool
|
1324
|
+
|
1325
|
+
# Create working tools list with end_tool if needed
|
1326
|
+
working_tools = self.tools.copy()
|
1327
|
+
if effective_end_strategy == "tool" and effective_end_tool is not None:
|
1328
|
+
end_tool_obj = define_tool(effective_end_tool)
|
1329
|
+
# Only add if not already present
|
1330
|
+
if not any(tool.name == end_tool_obj.name for tool in working_tools):
|
1331
|
+
working_tools.append(end_tool_obj)
|
1332
|
+
|
1333
|
+
# Get effective context settings
|
1334
|
+
effective_context_settings = self._get_effective_context_settings(
|
1335
|
+
context_updates=context_updates,
|
1336
|
+
context_confirm=context_confirm,
|
1337
|
+
context_strategy=context_strategy,
|
1338
|
+
context_max_retries=context_max_retries,
|
1339
|
+
context_confirm_instructions=context_confirm_instructions,
|
1340
|
+
context_selection_instructions=context_selection_instructions,
|
1341
|
+
context_update_instructions=context_update_instructions,
|
1342
|
+
context_format=context_format,
|
1343
|
+
)
|
1125
1344
|
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
|
1345
|
+
# Parse initial messages
|
1346
|
+
parsed_messages = parse_messages(messages)
|
1347
|
+
current_messages = parsed_messages.copy()
|
1348
|
+
steps: List[LanguageModelResponse[str]] = []
|
1349
|
+
|
1350
|
+
# RUN MAIN AGENTIC LOOP
|
1351
|
+
for step in range(max_steps):
|
1352
|
+
# Update context before processing if configured
|
1131
1353
|
if context and self._should_update_context(
|
1132
|
-
context, "
|
1354
|
+
context, "before", effective_context_settings["context_updates"]
|
1133
1355
|
):
|
1134
1356
|
context = self._perform_context_update(
|
1135
1357
|
context=context,
|
1136
1358
|
model=working_model,
|
1137
1359
|
current_messages=current_messages,
|
1138
|
-
timing="
|
1360
|
+
timing="before",
|
1139
1361
|
effective_settings=effective_context_settings,
|
1140
1362
|
)
|
1141
|
-
|
1142
|
-
|
1363
|
+
|
1364
|
+
# Format messages with instructions and context for first step only
|
1365
|
+
if step == 0:
|
1366
|
+
formatted_messages = self._format_messages_with_context(
|
1367
|
+
messages=current_messages,
|
1368
|
+
context=context,
|
1369
|
+
)
|
1370
|
+
else:
|
1371
|
+
formatted_messages = current_messages
|
1372
|
+
|
1373
|
+
# Prepare kwargs for language model
|
1374
|
+
model_kwargs = kwargs.copy()
|
1375
|
+
# Don't add output_type for intermediate steps - only for final response
|
1376
|
+
if self.instructor_mode:
|
1377
|
+
model_kwargs["instructor_mode"] = self.instructor_mode
|
1378
|
+
|
1379
|
+
# Get language model response
|
1380
|
+
response = await working_model.async_run(
|
1381
|
+
messages=formatted_messages,
|
1382
|
+
tools=[tool.to_dict() for tool in working_tools]
|
1383
|
+
if working_tools
|
1384
|
+
else None,
|
1385
|
+
**model_kwargs,
|
1143
1386
|
)
|
1144
1387
|
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1388
|
+
# Check if response has tool calls
|
1389
|
+
if response.has_tool_calls():
|
1390
|
+
# Add response to message history (with tool calls)
|
1391
|
+
current_messages.append(response.to_message())
|
1392
|
+
|
1393
|
+
# Execute tools and add their responses to messages
|
1394
|
+
tool_responses = execute_tools_from_language_model_response(
|
1395
|
+
tools=working_tools, response=response
|
1396
|
+
)
|
1397
|
+
# Add tool responses to message history
|
1398
|
+
for tool_resp in tool_responses:
|
1399
|
+
current_messages.append(tool_resp.to_dict())
|
1400
|
+
|
1401
|
+
# This is not the final step, add to steps
|
1402
|
+
steps.append(response)
|
1403
|
+
else:
|
1404
|
+
# No tool calls - check if this is actually the final step based on end_strategy
|
1405
|
+
if effective_end_strategy == "tool":
|
1406
|
+
# Check if the end_tool was called
|
1407
|
+
end_tool_called = (
|
1408
|
+
any(
|
1409
|
+
tool_call.function.name == effective_end_tool.__name__
|
1410
|
+
for tool_call in response.tool_calls
|
1411
|
+
)
|
1412
|
+
if response.tool_calls
|
1413
|
+
else False
|
1414
|
+
)
|
1415
|
+
|
1416
|
+
if not end_tool_called:
|
1417
|
+
# End tool not called, continue the conversation
|
1418
|
+
logger.debug(
|
1419
|
+
f"Agent '{self.name}' step {step + 1}: No end tool called, continuing..."
|
1420
|
+
)
|
1421
|
+
|
1422
|
+
# Add the response to history
|
1423
|
+
current_messages.append(response.to_message())
|
1424
|
+
|
1425
|
+
# Add system message instructing agent to call the end tool
|
1426
|
+
current_messages.append(
|
1427
|
+
{
|
1428
|
+
"role": "system",
|
1429
|
+
"content": f"You must call the {effective_end_tool.__name__} tool to complete your response. Do not provide a final answer until you have called this tool.",
|
1430
|
+
}
|
1431
|
+
)
|
1432
|
+
|
1433
|
+
# Add user message to continue
|
1434
|
+
current_messages.append(
|
1435
|
+
{"role": "user", "content": "continue"}
|
1436
|
+
)
|
1437
|
+
|
1438
|
+
# Remove the continue message and append assistant content
|
1439
|
+
current_messages.pop() # Remove "continue" message
|
1440
|
+
|
1441
|
+
# This is not the final step, add to steps and continue
|
1442
|
+
steps.append(response)
|
1443
|
+
continue
|
1444
|
+
|
1445
|
+
# This is the final step (either no end_strategy or end_tool was called)
|
1446
|
+
# Now we can make the final call with the output_type if specified
|
1447
|
+
if output_type:
|
1448
|
+
# Make a final call with the structured output type
|
1449
|
+
final_model_kwargs = kwargs.copy()
|
1450
|
+
final_model_kwargs["type"] = output_type
|
1451
|
+
if self.instructor_mode:
|
1452
|
+
final_model_kwargs["instructor_mode"] = self.instructor_mode
|
1453
|
+
|
1454
|
+
# Create a clean conversation history for structured output
|
1455
|
+
# Include the original messages and the final response content
|
1456
|
+
clean_messages = []
|
1457
|
+
# Add original user messages (excluding tool calls/responses)
|
1458
|
+
for msg in formatted_messages:
|
1459
|
+
if isinstance(msg, dict) and msg.get("role") not in [
|
1460
|
+
"tool",
|
1461
|
+
"assistant",
|
1462
|
+
]:
|
1463
|
+
clean_messages.append(msg)
|
1464
|
+
elif hasattr(msg, "role") and msg.role not in [
|
1465
|
+
"tool",
|
1466
|
+
"assistant",
|
1467
|
+
]:
|
1468
|
+
clean_messages.append(msg.to_dict())
|
1469
|
+
|
1470
|
+
# Add the final assistant response content
|
1471
|
+
clean_messages.append(
|
1472
|
+
{"role": "assistant", "content": response.get_content()}
|
1473
|
+
)
|
1474
|
+
|
1475
|
+
# Use the clean conversation history to generate structured output
|
1476
|
+
final_response = await working_model.async_run(
|
1477
|
+
messages=clean_messages,
|
1478
|
+
**final_model_kwargs,
|
1479
|
+
)
|
1480
|
+
|
1481
|
+
# Update context after processing if configured
|
1482
|
+
if context and self._should_update_context(
|
1483
|
+
context,
|
1484
|
+
"after",
|
1485
|
+
effective_context_settings["context_updates"],
|
1486
|
+
):
|
1487
|
+
context = self._perform_context_update(
|
1488
|
+
context=context,
|
1489
|
+
model=working_model,
|
1490
|
+
current_messages=current_messages,
|
1491
|
+
timing="after",
|
1492
|
+
effective_settings=effective_context_settings,
|
1493
|
+
)
|
1494
|
+
return _create_agent_response_from_language_model_response(
|
1495
|
+
response=final_response, steps=steps, context=context
|
1496
|
+
)
|
1497
|
+
else:
|
1498
|
+
# Update context after processing if configured
|
1499
|
+
if context and self._should_update_context(
|
1500
|
+
context,
|
1501
|
+
"after",
|
1502
|
+
effective_context_settings["context_updates"],
|
1503
|
+
):
|
1504
|
+
context = self._perform_context_update(
|
1505
|
+
context=context,
|
1506
|
+
model=working_model,
|
1507
|
+
current_messages=current_messages,
|
1508
|
+
timing="after",
|
1509
|
+
effective_settings=effective_context_settings,
|
1510
|
+
)
|
1511
|
+
return _create_agent_response_from_language_model_response(
|
1512
|
+
response=response, steps=steps, context=context
|
1513
|
+
)
|
1514
|
+
|
1515
|
+
# Max steps reached - return last response
|
1516
|
+
if steps:
|
1517
|
+
final_response = steps[-1]
|
1518
|
+
# If we have an output_type, make a final structured call
|
1519
|
+
if output_type:
|
1520
|
+
final_model_kwargs = kwargs.copy()
|
1521
|
+
final_model_kwargs["type"] = output_type
|
1522
|
+
if self.instructor_mode:
|
1523
|
+
final_model_kwargs["instructor_mode"] = self.instructor_mode
|
1524
|
+
|
1525
|
+
# Create clean messages for structured output
|
1526
|
+
clean_messages = []
|
1527
|
+
formatted_messages = self._format_messages_with_context(
|
1528
|
+
messages=current_messages,
|
1529
|
+
context=context,
|
1530
|
+
)
|
1531
|
+
|
1532
|
+
# Add original user messages (excluding tool calls/responses)
|
1533
|
+
for msg in formatted_messages:
|
1534
|
+
if isinstance(msg, dict) and msg.get("role") not in [
|
1535
|
+
"tool",
|
1536
|
+
"assistant",
|
1537
|
+
]:
|
1538
|
+
clean_messages.append(msg)
|
1539
|
+
elif hasattr(msg, "role") and msg.role not in [
|
1540
|
+
"tool",
|
1541
|
+
"assistant",
|
1542
|
+
]:
|
1543
|
+
clean_messages.append(msg.to_dict())
|
1544
|
+
|
1545
|
+
# Add final response content
|
1546
|
+
clean_messages.append(
|
1547
|
+
{"role": "assistant", "content": final_response.get_content()}
|
1548
|
+
)
|
1549
|
+
|
1550
|
+
final_response = await working_model.async_run(
|
1551
|
+
messages=clean_messages,
|
1552
|
+
**final_model_kwargs,
|
1553
|
+
)
|
1554
|
+
else:
|
1555
|
+
# No steps taken, make a final call
|
1556
|
+
final_model_kwargs = kwargs.copy()
|
1557
|
+
if output_type:
|
1558
|
+
final_model_kwargs["type"] = output_type
|
1559
|
+
if self.instructor_mode:
|
1560
|
+
final_model_kwargs["instructor_mode"] = self.instructor_mode
|
1561
|
+
|
1562
|
+
final_response = await working_model.async_run(
|
1563
|
+
messages=self._format_messages_with_context(
|
1564
|
+
messages=current_messages,
|
1565
|
+
context=context,
|
1566
|
+
),
|
1567
|
+
**final_model_kwargs,
|
1568
|
+
)
|
1569
|
+
|
1570
|
+
# Update context after processing if configured
|
1571
|
+
if context and self._should_update_context(
|
1572
|
+
context, "after", effective_context_settings["context_updates"]
|
1573
|
+
):
|
1574
|
+
context = self._perform_context_update(
|
1153
1575
|
context=context,
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1576
|
+
model=working_model,
|
1577
|
+
current_messages=current_messages,
|
1578
|
+
timing="after",
|
1579
|
+
effective_settings=effective_context_settings,
|
1580
|
+
)
|
1157
1581
|
|
1158
|
-
|
1159
|
-
|
1160
|
-
context, "after", effective_context_settings["context_updates"]
|
1161
|
-
):
|
1162
|
-
context = self._perform_context_update(
|
1163
|
-
context=context,
|
1164
|
-
model=working_model,
|
1165
|
-
current_messages=current_messages,
|
1166
|
-
timing="after",
|
1167
|
-
effective_settings=effective_context_settings,
|
1582
|
+
return _create_agent_response_from_language_model_response(
|
1583
|
+
response=final_response, steps=steps, context=context
|
1168
1584
|
)
|
1169
1585
|
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1586
|
+
finally:
|
1587
|
+
# Restore original logger level
|
1588
|
+
if debug is not None or verbose is not None:
|
1589
|
+
logger.level = original_level
|
1173
1590
|
|
1174
1591
|
def stream(
|
1175
1592
|
self,
|
@@ -1221,6 +1638,8 @@ Please update the appropriate fields based on the conversation. Only update fiel
|
|
1221
1638
|
context_selection_instructions: Optional[str] = None,
|
1222
1639
|
context_update_instructions: Optional[str] = None,
|
1223
1640
|
context_format: Optional[Literal["json", "python", "markdown"]] = None,
|
1641
|
+
end_strategy: Optional[Literal["tool"]] = None,
|
1642
|
+
end_tool: Optional[Callable] = None,
|
1224
1643
|
**kwargs: Any,
|
1225
1644
|
) -> AgentStream[T, AgentContext]:
|
1226
1645
|
"""Iterate over agent steps, yielding each step response.
|
@@ -1314,6 +1733,8 @@ Please update the appropriate fields based on the conversation. Only update fiel
|
|
1314
1733
|
context=context,
|
1315
1734
|
output_type=output_type,
|
1316
1735
|
stream=True,
|
1736
|
+
end_strategy=end_strategy,
|
1737
|
+
end_tool=end_tool,
|
1317
1738
|
**kwargs,
|
1318
1739
|
)
|
1319
1740
|
|
@@ -1370,6 +1791,8 @@ def create_agent(
|
|
1370
1791
|
context_selection_instructions: Optional[str] = None,
|
1371
1792
|
context_update_instructions: Optional[str] = None,
|
1372
1793
|
context_format: Literal["json", "python", "markdown"] = "json",
|
1794
|
+
verbose: bool = False,
|
1795
|
+
debug: bool = False,
|
1373
1796
|
**kwargs: Any,
|
1374
1797
|
) -> Agent[T]:
|
1375
1798
|
"""Create a new AI agent with specified capabilities and behavior.
|
@@ -1394,6 +1817,8 @@ def create_agent(
|
|
1394
1817
|
context_selection_instructions: Custom instructions for context selection
|
1395
1818
|
context_update_instructions: Custom instructions for context updates
|
1396
1819
|
context_format: Format for context display - "json", "python", or "markdown"
|
1820
|
+
verbose: If True, set logger to INFO level for detailed output
|
1821
|
+
debug: If True, set logger to DEBUG level for maximum verbosity
|
1397
1822
|
**kwargs: Additional parameters passed to the underlying language model
|
1398
1823
|
|
1399
1824
|
Example:
|
@@ -1425,6 +1850,8 @@ def create_agent(
|
|
1425
1850
|
context_selection_instructions=context_selection_instructions,
|
1426
1851
|
context_update_instructions=context_update_instructions,
|
1427
1852
|
context_format=context_format,
|
1853
|
+
verbose=verbose,
|
1854
|
+
debug=debug,
|
1428
1855
|
**kwargs,
|
1429
1856
|
)
|
1430
1857
|
|