alita-sdk 0.3.391__py3-none-any.whl → 0.3.392__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.

Potentially problematic release.


This version of alita-sdk might be problematic. Click here for more details.

@@ -263,6 +263,9 @@ class Assistant:
263
263
  schema_dict = {
264
264
  'name': 'react_agent',
265
265
  'state': {
266
+ 'input': {
267
+ 'type': 'str'
268
+ },
266
269
  'messages': state_messages_config
267
270
  },
268
271
  'nodes': [{
@@ -271,6 +274,16 @@ class Assistant:
271
274
  'prompt': {
272
275
  'template': escaped_prompt
273
276
  },
277
+ 'input_mapping': {
278
+ 'system': {
279
+ 'type': 'fixed',
280
+ 'value': escaped_prompt
281
+ },
282
+ 'task': {
283
+ 'type': 'variable',
284
+ 'value': 'input'
285
+ }
286
+ },
274
287
  'input': ['messages'],
275
288
  'output': ['messages'],
276
289
  'transition': 'END'
@@ -123,9 +123,16 @@ class LLMNode(BaseTool):
123
123
  for key, value in (self.structured_output_dict or {}).items()
124
124
  }
125
125
  struct_model = create_pydantic_model(f"LLMOutput", struct_params)
126
- llm = llm_client.with_structured_output(struct_model)
127
- completion = llm.invoke(messages, config=config)
128
- result = completion.model_dump()
126
+ completion = llm_client.invoke(messages, config=config)
127
+ if hasattr(completion, 'tool_calls') and completion.tool_calls:
128
+ new_messages, _ = self.__perform_tool_calling(completion, messages, llm_client, config)
129
+ llm = self.__get_struct_output_model(llm_client, struct_model)
130
+ completion = llm.invoke(new_messages, config=config)
131
+ result = completion.model_dump()
132
+ else:
133
+ llm = self.__get_struct_output_model(llm_client, struct_model)
134
+ completion = llm.invoke(messages, config=config)
135
+ result = completion.model_dump()
129
136
 
130
137
  # Ensure messages are properly formatted
131
138
  if result.get('messages') and isinstance(result['messages'], list):
@@ -139,117 +146,13 @@ class LLMNode(BaseTool):
139
146
  # Handle both tool-calling and regular responses
140
147
  if hasattr(completion, 'tool_calls') and completion.tool_calls:
141
148
  # Handle iterative tool-calling and execution
142
- new_messages = messages + [completion]
143
- max_iterations = 15
144
- iteration = 0
145
-
146
- # Continue executing tools until no more tool calls or max iterations reached
147
- current_completion = completion
148
- while (hasattr(current_completion, 'tool_calls') and
149
- current_completion.tool_calls and
150
- iteration < max_iterations):
151
-
152
- iteration += 1
153
- logger.info(f"Tool execution iteration {iteration}/{max_iterations}")
154
-
155
- # Execute each tool call in the current completion
156
- tool_calls = current_completion.tool_calls if hasattr(current_completion.tool_calls,
157
- '__iter__') else []
158
-
159
- for tool_call in tool_calls:
160
- tool_name = tool_call.get('name', '') if isinstance(tool_call, dict) else getattr(tool_call,
161
- 'name',
162
- '')
163
- tool_args = tool_call.get('args', {}) if isinstance(tool_call, dict) else getattr(tool_call,
164
- 'args',
165
- {})
166
- tool_call_id = tool_call.get('id', '') if isinstance(tool_call, dict) else getattr(
167
- tool_call, 'id', '')
168
-
169
- # Find the tool in filtered tools
170
- filtered_tools = self.get_filtered_tools()
171
- tool_to_execute = None
172
- for tool in filtered_tools:
173
- if tool.name == tool_name:
174
- tool_to_execute = tool
175
- break
176
-
177
- if tool_to_execute:
178
- try:
179
- logger.info(f"Executing tool '{tool_name}' with args: {tool_args}")
180
- # Pass the underlying config to the tool execution invoke method
181
- # since it may be another agent, graph, etc. to see it properly in thinking steps
182
- tool_result = tool_to_execute.invoke(tool_args, config=config)
183
-
184
- # Create tool message with result - preserve structured content
185
- from langchain_core.messages import ToolMessage
186
-
187
- # Check if tool_result is structured content (list of dicts)
188
- # TODO: need solid check for being compatible with ToolMessage content format
189
- if isinstance(tool_result, list) and all(
190
- isinstance(item, dict) and 'type' in item for item in tool_result
191
- ):
192
- # Use structured content directly for multimodal support
193
- tool_message = ToolMessage(
194
- content=tool_result,
195
- tool_call_id=tool_call_id
196
- )
197
- else:
198
- # Fallback to string conversion for other tool results
199
- tool_message = ToolMessage(
200
- content=str(tool_result),
201
- tool_call_id=tool_call_id
202
- )
203
- new_messages.append(tool_message)
204
-
205
- except Exception as e:
206
- logger.error(f"Error executing tool '{tool_name}': {e}")
207
- # Create error tool message
208
- from langchain_core.messages import ToolMessage
209
- tool_message = ToolMessage(
210
- content=f"Error executing {tool_name}: {str(e)}",
211
- tool_call_id=tool_call_id
212
- )
213
- new_messages.append(tool_message)
214
- else:
215
- logger.warning(f"Tool '{tool_name}' not found in available tools")
216
- # Create error tool message for missing tool
217
- from langchain_core.messages import ToolMessage
218
- tool_message = ToolMessage(
219
- content=f"Tool '{tool_name}' not available",
220
- tool_call_id=tool_call_id
221
- )
222
- new_messages.append(tool_message)
223
-
224
- # Call LLM again with tool results to get next response
225
- try:
226
- current_completion = llm_client.invoke(new_messages, config=config)
227
- new_messages.append(current_completion)
228
-
229
- # Check if we still have tool calls
230
- if hasattr(current_completion, 'tool_calls') and current_completion.tool_calls:
231
- logger.info(f"LLM requested {len(current_completion.tool_calls)} more tool calls")
232
- else:
233
- logger.info("LLM completed without requesting more tools")
234
- break
235
-
236
- except Exception as e:
237
- logger.error(f"Error in LLM call during iteration {iteration}: {e}")
238
- # Add error message and break the loop
239
- error_msg = f"Error processing tool results in iteration {iteration}: {str(e)}"
240
- new_messages.append(AIMessage(content=error_msg))
241
- break
242
-
243
- # Log completion status
244
- if iteration >= max_iterations:
245
- logger.warning(f"Reached maximum iterations ({max_iterations}) for tool execution")
246
- # Add a warning message to the chat
247
- warning_msg = f"Maximum tool execution iterations ({max_iterations}) reached. Stopping tool execution."
248
- new_messages.append(AIMessage(content=warning_msg))
249
- else:
250
- logger.info(f"Tool execution completed after {iteration} iterations")
149
+ new_messages, current_completion = self.__perform_tool_calling(completion, messages, llm_client, config)
251
150
 
252
- return {"messages": new_messages}
151
+ output_msgs = {"messages": new_messages}
152
+ if self.output_variables:
153
+ output_msgs[self.output_variables[0]] = current_completion.content if current_completion else None
154
+
155
+ return output_msgs
253
156
  else:
254
157
  # Regular text response
255
158
  content = completion.content.strip() if hasattr(completion, 'content') else str(completion)
@@ -275,4 +178,121 @@ class LLMNode(BaseTool):
275
178
 
276
179
  def _run(self, *args, **kwargs):
277
180
  # Legacy support for old interface
278
- return self.invoke(kwargs, **kwargs)
181
+ return self.invoke(kwargs, **kwargs)
182
+
183
+ def __perform_tool_calling(self, completion, messages, llm_client, config):
184
+ # Handle iterative tool-calling and execution
185
+ new_messages = messages + [completion]
186
+ max_iterations = 15
187
+ iteration = 0
188
+
189
+ # Continue executing tools until no more tool calls or max iterations reached
190
+ current_completion = completion
191
+ while (hasattr(current_completion, 'tool_calls') and
192
+ current_completion.tool_calls and
193
+ iteration < max_iterations):
194
+
195
+ iteration += 1
196
+ logger.info(f"Tool execution iteration {iteration}/{max_iterations}")
197
+
198
+ # Execute each tool call in the current completion
199
+ tool_calls = current_completion.tool_calls if hasattr(current_completion.tool_calls,
200
+ '__iter__') else []
201
+
202
+ for tool_call in tool_calls:
203
+ tool_name = tool_call.get('name', '') if isinstance(tool_call, dict) else getattr(tool_call,
204
+ 'name',
205
+ '')
206
+ tool_args = tool_call.get('args', {}) if isinstance(tool_call, dict) else getattr(tool_call,
207
+ 'args',
208
+ {})
209
+ tool_call_id = tool_call.get('id', '') if isinstance(tool_call, dict) else getattr(
210
+ tool_call, 'id', '')
211
+
212
+ # Find the tool in filtered tools
213
+ filtered_tools = self.get_filtered_tools()
214
+ tool_to_execute = None
215
+ for tool in filtered_tools:
216
+ if tool.name == tool_name:
217
+ tool_to_execute = tool
218
+ break
219
+
220
+ if tool_to_execute:
221
+ try:
222
+ logger.info(f"Executing tool '{tool_name}' with args: {tool_args}")
223
+ # Pass the underlying config to the tool execution invoke method
224
+ # since it may be another agent, graph, etc. to see it properly in thinking steps
225
+ tool_result = tool_to_execute.invoke(tool_args, config=config)
226
+
227
+ # Create tool message with result - preserve structured content
228
+ from langchain_core.messages import ToolMessage
229
+
230
+ # Check if tool_result is structured content (list of dicts)
231
+ # TODO: need solid check for being compatible with ToolMessage content format
232
+ if isinstance(tool_result, list) and all(
233
+ isinstance(item, dict) and 'type' in item for item in tool_result
234
+ ):
235
+ # Use structured content directly for multimodal support
236
+ tool_message = ToolMessage(
237
+ content=tool_result,
238
+ tool_call_id=tool_call_id
239
+ )
240
+ else:
241
+ # Fallback to string conversion for other tool results
242
+ tool_message = ToolMessage(
243
+ content=str(tool_result),
244
+ tool_call_id=tool_call_id
245
+ )
246
+ new_messages.append(tool_message)
247
+
248
+ except Exception as e:
249
+ logger.error(f"Error executing tool '{tool_name}': {e}")
250
+ # Create error tool message
251
+ from langchain_core.messages import ToolMessage
252
+ tool_message = ToolMessage(
253
+ content=f"Error executing {tool_name}: {str(e)}",
254
+ tool_call_id=tool_call_id
255
+ )
256
+ new_messages.append(tool_message)
257
+ else:
258
+ logger.warning(f"Tool '{tool_name}' not found in available tools")
259
+ # Create error tool message for missing tool
260
+ from langchain_core.messages import ToolMessage
261
+ tool_message = ToolMessage(
262
+ content=f"Tool '{tool_name}' not available",
263
+ tool_call_id=tool_call_id
264
+ )
265
+ new_messages.append(tool_message)
266
+
267
+ # Call LLM again with tool results to get next response
268
+ try:
269
+ current_completion = llm_client.invoke(new_messages, config=config)
270
+ new_messages.append(current_completion)
271
+
272
+ # Check if we still have tool calls
273
+ if hasattr(current_completion, 'tool_calls') and current_completion.tool_calls:
274
+ logger.info(f"LLM requested {len(current_completion.tool_calls)} more tool calls")
275
+ else:
276
+ logger.info("LLM completed without requesting more tools")
277
+ break
278
+
279
+ except Exception as e:
280
+ logger.error(f"Error in LLM call during iteration {iteration}: {e}")
281
+ # Add error message and break the loop
282
+ error_msg = f"Error processing tool results in iteration {iteration}: {str(e)}"
283
+ new_messages.append(AIMessage(content=error_msg))
284
+ break
285
+
286
+ # Log completion status
287
+ if iteration >= max_iterations:
288
+ logger.warning(f"Reached maximum iterations ({max_iterations}) for tool execution")
289
+ # Add a warning message to the chat
290
+ warning_msg = f"Maximum tool execution iterations ({max_iterations}) reached. Stopping tool execution."
291
+ new_messages.append(AIMessage(content=warning_msg))
292
+ else:
293
+ logger.info(f"Tool execution completed after {iteration} iterations")
294
+
295
+ return new_messages, current_completion
296
+
297
+ def __get_struct_output_model(self, llm_client, pydantic_model):
298
+ return llm_client.with_structured_output(pydantic_model)
@@ -199,7 +199,7 @@ class PGVectorAdapter(VectorStoreAdapter):
199
199
 
200
200
  result = {}
201
201
  try:
202
- vectorstore_wrapper._log_data("Retrieving already indexed code data from PGVector vectorstore",
202
+ vectorstore_wrapper._log_tool_event(message="Retrieving already indexed code data from PGVector vectorstore",
203
203
  tool_name="index_code_data")
204
204
  store = vectorstore_wrapper.vectorstore
205
205
  with (Session(store.session_maker.bind) as session):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alita_sdk
3
- Version: 0.3.391
3
+ Version: 0.3.392
4
4
  Summary: SDK for building langchain agents using resources from Alita
5
5
  Author-email: Artem Rozumenko <artyom.rozumenko@gmail.com>, Mikalai Biazruchka <mikalai_biazruchka@epam.com>, Roman Mitusov <roman_mitusov@epam.com>, Ivan Krakhmaliuk <lifedj27@gmail.com>, Artem Dubrovskiy <ad13box@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -41,7 +41,7 @@ alita_sdk/runtime/clients/datasource.py,sha256=HAZovoQN9jBg0_-lIlGBQzb4FJdczPhkH
41
41
  alita_sdk/runtime/clients/prompt.py,sha256=li1RG9eBwgNK_Qf0qUaZ8QNTmsncFrAL2pv3kbxZRZg,1447
42
42
  alita_sdk/runtime/clients/sandbox_client.py,sha256=OhEasE0MxBBDw4o76xkxVCpNpr3xJ8spQsrsVxMrjUA,16192
43
43
  alita_sdk/runtime/langchain/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
- alita_sdk/runtime/langchain/assistant.py,sha256=w6OUXNOWxWkju5n99Tfs_bbXlRsu397QRIlhig9SGmg,15041
44
+ alita_sdk/runtime/langchain/assistant.py,sha256=ssgiRln0ZpPSjStqitTKj-EaSlsh5F6Ag6yMETESQUw,15456
45
45
  alita_sdk/runtime/langchain/chat_message_template.py,sha256=kPz8W2BG6IMyITFDA5oeb5BxVRkHEVZhuiGl4MBZKdc,2176
46
46
  alita_sdk/runtime/langchain/constants.py,sha256=eHVJ_beJNTf1WJo4yq7KMK64fxsRvs3lKc34QCXSbpk,3319
47
47
  alita_sdk/runtime/langchain/indexer.py,sha256=0ENHy5EOhThnAiYFc7QAsaTNp9rr8hDV_hTK8ahbatk,37592
@@ -114,7 +114,7 @@ alita_sdk/runtime/tools/function.py,sha256=jk_JrtuYByR9Df5EFOGFheB9HktNPJcOwf4js
114
114
  alita_sdk/runtime/tools/graph.py,sha256=7jImBBSEdP5Mjnn2keOiyUwdGDFhEXLUrgUiugO3mgA,3503
115
115
  alita_sdk/runtime/tools/image_generation.py,sha256=Kls9D_ke_SK7xmVr7I9SlQcAEBJc86gf66haN0qIj9k,7469
116
116
  alita_sdk/runtime/tools/indexer_tool.py,sha256=whSLPevB4WD6dhh2JDXEivDmTvbjiMV1MrPl9cz5eLA,4375
117
- alita_sdk/runtime/tools/llm.py,sha256=AOxC3OEQ8FQCiI6f1we6s_X3a7DGyd2Z6yi1P_1jqoY,15376
117
+ alita_sdk/runtime/tools/llm.py,sha256=0Ki8YrwDYjAnMbo5eh_3t15ZTWqd4AyE328muFzOsmU,15365
118
118
  alita_sdk/runtime/tools/loop.py,sha256=uds0WhZvwMxDVFI6MZHrcmMle637cQfBNg682iLxoJA,8335
119
119
  alita_sdk/runtime/tools/loop_output.py,sha256=U4hO9PCQgWlXwOq6jdmCGbegtAxGAPXObSxZQ3z38uk,8069
120
120
  alita_sdk/runtime/tools/mcp_server_tool.py,sha256=MhLxZJ44LYrB_0GrojmkyqKoDRaqIHkEQAsg718ipog,4277
@@ -332,7 +332,7 @@ alita_sdk/tools/testrail/api_wrapper.py,sha256=tQcGlFJmftvs5ZiO4tsP19fCo4CrJeq_U
332
332
  alita_sdk/tools/utils/__init__.py,sha256=xB9OQgW65DftadrSpoAAitnEIbIXZKBOCji0NDe7FRM,3923
333
333
  alita_sdk/tools/utils/available_tools_decorator.py,sha256=IbrdfeQkswxUFgvvN7-dyLMZMyXLiwvX7kgi3phciCk,273
334
334
  alita_sdk/tools/utils/content_parser.py,sha256=7ohj8HeL_-rmc-Fv0TS8IpxIQC8tOpfuhyT3XlWx-gQ,15368
335
- alita_sdk/tools/vector_adapters/VectorStoreAdapter.py,sha256=RIDWVqONN5z6CyMkqfkSUbOlGWaBDQoUreHPwZYJXPc,19389
335
+ alita_sdk/tools/vector_adapters/VectorStoreAdapter.py,sha256=I7YCDT2qslXmiUzDAzaUEN1gCy8DJ5RcUAipl3ISzA0,19403
336
336
  alita_sdk/tools/vector_adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
337
337
  alita_sdk/tools/xray/__init__.py,sha256=eOMWP8VamFbbJgt1xrGpGPqB9ByOTA0Cd3LCaETzGk4,4376
338
338
  alita_sdk/tools/xray/api_wrapper.py,sha256=uj5kzUgPdo_Oct9WCNMOpkb6o_3L7J4LZrEGtrwYMmc,30157
@@ -353,8 +353,8 @@ alita_sdk/tools/zephyr_scale/api_wrapper.py,sha256=kT0TbmMvuKhDUZc0i7KO18O38JM9S
353
353
  alita_sdk/tools/zephyr_squad/__init__.py,sha256=0ne8XLJEQSLOWfzd2HdnqOYmQlUliKHbBED5kW_Vias,2895
354
354
  alita_sdk/tools/zephyr_squad/api_wrapper.py,sha256=kmw_xol8YIYFplBLWTqP_VKPRhL_1ItDD0_vXTe_UuI,14906
355
355
  alita_sdk/tools/zephyr_squad/zephyr_squad_cloud_client.py,sha256=R371waHsms4sllHCbijKYs90C-9Yu0sSR3N4SUfQOgU,5066
356
- alita_sdk-0.3.391.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
357
- alita_sdk-0.3.391.dist-info/METADATA,sha256=ezfSHQ0lNP1x_5-E0IYrMlydmJH8oe6mMqycT_gcAo4,19071
358
- alita_sdk-0.3.391.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
359
- alita_sdk-0.3.391.dist-info/top_level.txt,sha256=0vJYy5p_jK6AwVb1aqXr7Kgqgk3WDtQ6t5C-XI9zkmg,10
360
- alita_sdk-0.3.391.dist-info/RECORD,,
356
+ alita_sdk-0.3.392.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
357
+ alita_sdk-0.3.392.dist-info/METADATA,sha256=zU605qkaYYtpcH3eynsv5q72sw6tofJq_SPcqIjS0qI,19071
358
+ alita_sdk-0.3.392.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
359
+ alita_sdk-0.3.392.dist-info/top_level.txt,sha256=0vJYy5p_jK6AwVb1aqXr7Kgqgk3WDtQ6t5C-XI9zkmg,10
360
+ alita_sdk-0.3.392.dist-info/RECORD,,