Skip to content

Commit ccc636a

Browse files
fix: resolve critical runtime issues in callback enhancement
- Fix undefined variables in llm.py response() and aresponse() methods by adding missing parameters to method signatures - Fix backward compatibility by adding signature checking to callbacks in display_interaction(), execute_callback(), and execute_sync_callback() - Ensure consistent parameter propagation in agent.py get_response calls - Legacy callbacks now work without TypeError, new callbacks get full context Co-authored-by: Mervin Praison <MervinPraison@users.noreply.github.com>
1 parent 1a05ece commit ccc636a

3 files changed

Lines changed: 99 additions & 17 deletions

File tree

src/praisonai-agents/praisonaiagents/agent/agent.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,10 @@ def _chat_completion(self, messages, temperature=0.2, tools=None, stream=True, r
11001100
execute_tool_fn=self.execute_tool,
11011101
agent_name=self.name,
11021102
agent_role=self.role,
1103+
agent_tools=[t.__name__ for t in self.tools] if self.tools else None,
1104+
task_name=task_name,
1105+
task_description=task_description,
1106+
task_id=task_id,
11031107
reasoning_steps=reasoning_steps
11041108
)
11051109
else:
@@ -1116,6 +1120,10 @@ def _chat_completion(self, messages, temperature=0.2, tools=None, stream=True, r
11161120
execute_tool_fn=self.execute_tool,
11171121
agent_name=self.name,
11181122
agent_role=self.role,
1123+
agent_tools=[t.__name__ for t in self.tools] if self.tools else None,
1124+
task_name=task_name,
1125+
task_description=task_description,
1126+
task_id=task_id,
11191127
reasoning_steps=reasoning_steps
11201128
)
11211129
else:
@@ -1162,12 +1170,24 @@ def _execute_callback_and_display(self, prompt: str, response: str, generation_t
11621170
message=prompt,
11631171
response=response,
11641172
markdown=self.markdown,
1165-
generation_time=generation_time
1173+
generation_time=generation_time,
1174+
agent_name=self.name,
1175+
agent_role=self.role,
1176+
agent_tools=[t.__name__ for t in self.tools] if self.tools else None,
1177+
task_name=None, # Not available in this context
1178+
task_description=None, # Not available in this context
1179+
task_id=None # Not available in this context
11661180
)
11671181
# Only display interaction if not using custom LLM (to avoid double output) and verbose is True
11681182
if self.verbose and not self._using_custom_llm:
11691183
display_interaction(prompt, response, markdown=self.markdown,
1170-
generation_time=generation_time, console=self.console)
1184+
generation_time=generation_time, console=self.console,
1185+
agent_name=self.name,
1186+
agent_role=self.role,
1187+
agent_tools=[t.__name__ for t in self.tools] if self.tools else None,
1188+
task_name=None, # Not available in this context
1189+
task_description=None, # Not available in this context
1190+
task_id=None) # Not available in this context
11711191

11721192
def chat(self, prompt, temperature=0.2, tools=None, output_json=None, output_pydantic=None, reasoning_steps=False, stream=True, task_name=None, task_description=None, task_id=None):
11731193
# Log all parameter values when in debug mode
@@ -1585,6 +1605,9 @@ async def achat(self, prompt: str, temperature=0.2, tools=None, output_json=None
15851605
agent_name=self.name,
15861606
agent_role=self.role,
15871607
agent_tools=[t.__name__ if hasattr(t, '__name__') else str(t) for t in (tools if tools is not None else self.tools)],
1608+
task_name=task_name,
1609+
task_description=task_description,
1610+
task_id=task_id,
15881611
execute_tool_fn=self.execute_tool_async,
15891612
reasoning_steps=reasoning_steps
15901613
)

src/praisonai-agents/praisonaiagents/llm/llm.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2153,6 +2153,12 @@ def response(
21532153
verbose: bool = True,
21542154
markdown: bool = True,
21552155
console: Optional[Console] = None,
2156+
agent_name: Optional[str] = None,
2157+
agent_role: Optional[str] = None,
2158+
agent_tools: Optional[List[str]] = None,
2159+
task_name: Optional[str] = None,
2160+
task_description: Optional[str] = None,
2161+
task_id: Optional[str] = None,
21562162
**kwargs
21572163
) -> str:
21582164
"""Simple function to get model response without tool calls or complex features"""
@@ -2246,6 +2252,12 @@ async def aresponse(
22462252
verbose: bool = True,
22472253
markdown: bool = True,
22482254
console: Optional[Console] = None,
2255+
agent_name: Optional[str] = None,
2256+
agent_role: Optional[str] = None,
2257+
agent_tools: Optional[List[str]] = None,
2258+
task_name: Optional[str] = None,
2259+
task_description: Optional[str] = None,
2260+
task_id: Optional[str] = None,
22492261
**kwargs
22502262
) -> str:
22512263
"""Async version of response function"""

src/praisonai-agents/praisonaiagents/main.py

Lines changed: 62 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,18 @@ def execute_sync_callback(display_type: str, **kwargs):
7373
"""
7474
if display_type in sync_display_callbacks:
7575
callback = sync_display_callbacks[display_type]
76-
callback(**kwargs)
76+
import inspect
77+
sig = inspect.signature(callback)
78+
79+
# Filter kwargs to what the callback accepts to maintain backward compatibility
80+
if any(p.kind == inspect.Parameter.VAR_KEYWORD for p in sig.parameters.values()):
81+
# Callback accepts **kwargs, so pass all arguments
82+
supported_kwargs = kwargs
83+
else:
84+
# Only pass arguments that the callback signature supports
85+
supported_kwargs = {k: v for k, v in kwargs.items() if k in sig.parameters}
86+
87+
callback(**supported_kwargs)
7788

7889
async def execute_callback(display_type: str, **kwargs):
7990
"""Execute both sync and async callbacks for a given display type.
@@ -82,16 +93,38 @@ async def execute_callback(display_type: str, **kwargs):
8293
display_type (str): Type of display event
8394
**kwargs: Arguments to pass to the callback functions
8495
"""
96+
import inspect
97+
8598
# Execute synchronous callback if registered
8699
if display_type in sync_display_callbacks:
87100
callback = sync_display_callbacks[display_type]
101+
sig = inspect.signature(callback)
102+
103+
# Filter kwargs to what the callback accepts to maintain backward compatibility
104+
if any(p.kind == inspect.Parameter.VAR_KEYWORD for p in sig.parameters.values()):
105+
# Callback accepts **kwargs, so pass all arguments
106+
supported_kwargs = kwargs
107+
else:
108+
# Only pass arguments that the callback signature supports
109+
supported_kwargs = {k: v for k, v in kwargs.items() if k in sig.parameters}
110+
88111
loop = asyncio.get_event_loop()
89-
await loop.run_in_executor(None, lambda: callback(**kwargs))
112+
await loop.run_in_executor(None, lambda: callback(**supported_kwargs))
90113

91114
# Execute asynchronous callback if registered
92115
if display_type in async_display_callbacks:
93116
callback = async_display_callbacks[display_type]
94-
await callback(**kwargs)
117+
sig = inspect.signature(callback)
118+
119+
# Filter kwargs to what the callback accepts to maintain backward compatibility
120+
if any(p.kind == inspect.Parameter.VAR_KEYWORD for p in sig.parameters.values()):
121+
# Callback accepts **kwargs, so pass all arguments
122+
supported_kwargs = kwargs
123+
else:
124+
# Only pass arguments that the callback signature supports
125+
supported_kwargs = {k: v for k, v in kwargs.items() if k in sig.parameters}
126+
127+
await callback(**supported_kwargs)
95128

96129
def _clean_display_content(content: str, max_length: int = 20000) -> str:
97130
"""Helper function to clean and truncate content for display."""
@@ -129,18 +162,32 @@ def display_interaction(message, response, markdown=True, generation_time=None,
129162

130163
# Execute synchronous callback if registered
131164
if 'interaction' in sync_display_callbacks:
132-
sync_display_callbacks['interaction'](
133-
message=message,
134-
response=response,
135-
markdown=markdown,
136-
generation_time=generation_time,
137-
agent_name=agent_name,
138-
agent_role=agent_role,
139-
agent_tools=agent_tools,
140-
task_name=task_name,
141-
task_description=task_description,
142-
task_id=task_id
143-
)
165+
callback = sync_display_callbacks['interaction']
166+
import inspect
167+
sig = inspect.signature(callback)
168+
169+
all_kwargs = {
170+
'message': message,
171+
'response': response,
172+
'markdown': markdown,
173+
'generation_time': generation_time,
174+
'agent_name': agent_name,
175+
'agent_role': agent_role,
176+
'agent_tools': agent_tools,
177+
'task_name': task_name,
178+
'task_description': task_description,
179+
'task_id': task_id
180+
}
181+
182+
# Filter kwargs to what the callback accepts to maintain backward compatibility
183+
if any(p.kind == inspect.Parameter.VAR_KEYWORD for p in sig.parameters.values()):
184+
# Callback accepts **kwargs, so pass all arguments
185+
supported_kwargs = all_kwargs
186+
else:
187+
# Only pass arguments that the callback signature supports
188+
supported_kwargs = {k: v for k, v in all_kwargs.items() if k in sig.parameters}
189+
190+
callback(**supported_kwargs)
144191
# Rest of the display logic...
145192
if generation_time:
146193
console.print(Text(f"Response generated in {generation_time:.1f}s", style="dim"))

0 commit comments

Comments
 (0)