vision-agent 0.2.172__py3-none-any.whl → 0.2.174__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -492,19 +492,10 @@ class VisionAgent(Agent):
492
492
  }
493
493
  )
494
494
 
495
+ code_action = response.get("execute_python", None)
495
496
  # sometimes it gets stuck in a loop, so we force it to exit
496
497
  if last_response == response:
497
498
  response["let_user_respond"] = True
498
-
499
- finished = response.get("let_user_respond", False)
500
-
501
- code_action = response.get("execute_python", None)
502
- if code_action is not None:
503
- code_action = use_extra_vision_agent_args(
504
- code_action, test_multi_plan, custom_tool_names
505
- )
506
-
507
- if last_response == response:
508
499
  self.streaming_message(
509
500
  {
510
501
  "role": "assistant",
@@ -514,7 +505,7 @@ class VisionAgent(Agent):
514
505
  "value": "Agent is stuck in conversation loop, exited",
515
506
  "traceback_raw": [],
516
507
  },
517
- "finished": finished and code_action is None,
508
+ "finished": code_action is None,
518
509
  }
519
510
  )
520
511
  else:
@@ -524,10 +515,18 @@ class VisionAgent(Agent):
524
515
  "content": new_format_to_old_format(
525
516
  add_step_descriptions(response)
526
517
  ),
527
- "finished": finished and code_action is None,
518
+ "finished": response.get("let_user_respond", False)
519
+ and code_action is None,
528
520
  }
529
521
  )
530
522
 
523
+ finished = response.get("let_user_respond", False)
524
+
525
+ if code_action is not None:
526
+ code_action = use_extra_vision_agent_args(
527
+ code_action, test_multi_plan, custom_tool_names
528
+ )
529
+
531
530
  if code_action is not None:
532
531
  result, obs = execute_code_action(
533
532
  artifacts,
@@ -5,7 +5,7 @@ import sys
5
5
  from pathlib import Path
6
6
  from typing import Any, Callable, Dict, List, Optional, Sequence, Union, cast
7
7
 
8
- from redbaron import RedBaron # type: ignore
8
+ import libcst as cst
9
9
  from tabulate import tabulate
10
10
 
11
11
  import vision_agent.tools as T
@@ -49,42 +49,112 @@ WORKSPACE = Path(os.getenv("WORKSPACE", ""))
49
49
  _LOGGER = logging.getLogger(__name__)
50
50
 
51
51
 
52
- def strip_function_calls(code: str, exclusions: Optional[List[str]] = None) -> str:
52
+ def strip_function_calls( # noqa: C901
53
+ code: str, exclusions: Optional[List[str]] = None
54
+ ) -> str:
53
55
  """This will strip out all code that calls functions except for functions included
54
56
  in exclusions.
55
57
  """
56
58
  if exclusions is None:
57
59
  exclusions = []
58
60
 
59
- red = RedBaron(code)
60
- nodes_to_remove = []
61
- for node in red:
62
- if node.type == "def":
63
- continue
64
- elif node.type == "import" or node.type == "from_import":
65
- continue
66
- elif node.type == "call":
67
- if node.value and node.value[0].value in exclusions:
68
- continue
69
- nodes_to_remove.append(node)
70
- elif node.type == "atomtrailers":
71
- if node[0].value in exclusions:
72
- continue
73
- nodes_to_remove.append(node)
74
- elif node.type == "assignment":
75
- if node.value.type == "call" or node.value.type == "atomtrailers":
76
- func_name = node.value[0].value
77
- if func_name in exclusions:
78
- continue
79
- nodes_to_remove.append(node)
80
- elif node.type == "endl":
81
- continue
82
- else:
83
- nodes_to_remove.append(node)
84
- for node in nodes_to_remove:
85
- node.parent.remove(node)
86
- cleaned_code = red.dumps().strip()
87
- return cleaned_code if isinstance(cleaned_code, str) else code
61
+ def check_and_remove_node(node: cst.CSTNode, exclusions: List[str]) -> cst.CSTNode:
62
+ if hasattr(node, "value") and isinstance(node.value, cst.Call):
63
+ if (
64
+ isinstance(node.value.func, cst.Name)
65
+ and node.value.func.value in exclusions
66
+ ):
67
+ return node
68
+ return cst.RemoveFromParent() # type: ignore
69
+ return node
70
+
71
+ class StripFunctionCallsTransformer(cst.CSTTransformer):
72
+ def __init__(self, exclusions: List[str]):
73
+ # Store exclusions to skip removing certain function calls
74
+ self.exclusions = exclusions
75
+ self.in_function_or_class = False
76
+
77
+ def visit_FunctionDef(self, node: cst.FunctionDef) -> Optional[bool]:
78
+ self.in_function_or_class = True
79
+ return True
80
+
81
+ def leave_FunctionDef(
82
+ self, original_node: cst.FunctionDef, updated_node: cst.FunctionDef
83
+ ) -> cst.BaseStatement:
84
+ self.in_function_or_class = False
85
+ return updated_node
86
+
87
+ def visit_ClassDef(self, node: cst.ClassDef) -> Optional[bool]:
88
+ self.in_function_or_class = True
89
+ return True
90
+
91
+ def leave_ClassDef(
92
+ self, node: cst.ClassDef, updated_node: cst.ClassDef
93
+ ) -> cst.BaseStatement:
94
+ self.in_function_or_class = False
95
+ return updated_node
96
+
97
+ def leave_Expr(
98
+ self, original_node: cst.Expr, updated_node: cst.Expr
99
+ ) -> cst.Expr:
100
+ if not self.in_function_or_class:
101
+ return cast(
102
+ cst.Expr, check_and_remove_node(updated_node, self.exclusions)
103
+ )
104
+ return updated_node
105
+
106
+ def leave_Assign(
107
+ self, original_node: cst.Assign, updated_node: cst.Assign
108
+ ) -> cst.Assign:
109
+ if not self.in_function_or_class:
110
+ return cast(
111
+ cst.Assign, check_and_remove_node(updated_node, self.exclusions)
112
+ )
113
+ return updated_node
114
+
115
+ def leave_If(self, original_node: cst.If, updated_node: cst.If) -> cst.If:
116
+ if not self.in_function_or_class:
117
+ return cast(
118
+ cst.If, check_and_remove_node(updated_node, self.exclusions)
119
+ )
120
+ return updated_node
121
+
122
+ def leave_For(self, original_node: cst.For, updated_node: cst.For) -> cst.For:
123
+ if not self.in_function_or_class:
124
+ return cast(
125
+ cst.For, check_and_remove_node(updated_node, self.exclusions)
126
+ )
127
+ return updated_node
128
+
129
+ def leave_While(
130
+ self, original_node: cst.While, updated_node: cst.While
131
+ ) -> cst.While:
132
+ if not self.in_function_or_class:
133
+ return cast(
134
+ cst.While, check_and_remove_node(updated_node, self.exclusions)
135
+ )
136
+ return updated_node
137
+
138
+ def leave_With(
139
+ self, original_node: cst.With, updated_node: cst.With
140
+ ) -> cst.With:
141
+ if not self.in_function_or_class:
142
+ return cast(
143
+ cst.With, check_and_remove_node(updated_node, self.exclusions)
144
+ )
145
+ return updated_node
146
+
147
+ def leave_Try(self, original_node: cst.Try, updated_node: cst.Try) -> cst.Try:
148
+ if not self.in_function_or_class:
149
+ return cast(
150
+ cst.Try, check_and_remove_node(updated_node, self.exclusions)
151
+ )
152
+ return updated_node
153
+
154
+ tree = cst.parse_module(code)
155
+ transformer = StripFunctionCallsTransformer(exclusions)
156
+ modified_tree = tree.visit(transformer)
157
+ return modified_tree.code
88
158
 
89
159
 
90
160
  def write_code(
@@ -8,8 +8,8 @@ import tempfile
8
8
  from pathlib import Path
9
9
  from typing import Any, Dict, List, Optional, Union
10
10
 
11
+ import libcst as cst
11
12
  from IPython.display import display
12
- from redbaron import RedBaron # type: ignore
13
13
 
14
14
  import vision_agent as va
15
15
  from vision_agent.agent.agent_utils import extract_json
@@ -663,21 +663,79 @@ def use_extra_vision_agent_args(
663
663
  Returns:
664
664
  str: The edited code.
665
665
  """
666
- red = RedBaron(code)
667
- for node in red:
668
- # seems to always be atomtrailers not call type
669
- if node.type == "atomtrailers":
670
- if node.name.value == "generate_vision_code":
671
- node.value[1].value.append(f"test_multi_plan={test_multi_plan}")
672
-
673
- if (
674
- node.name.value == "generate_vision_code"
675
- or node.name.value == "edit_vision_code"
676
- ):
677
- if custom_tool_names is not None:
678
- node.value[1].value.append(f"custom_tool_names={custom_tool_names}")
679
- cleaned_code = red.dumps().strip()
680
- return cleaned_code if isinstance(cleaned_code, str) else code
666
+
667
+ class VisionAgentTransformer(cst.CSTTransformer):
668
+ def __init__(
669
+ self, test_multi_plan: bool, custom_tool_names: Optional[List[str]]
670
+ ):
671
+ self.test_multi_plan = test_multi_plan
672
+ self.custom_tool_names = custom_tool_names
673
+
674
+ def leave_Call(
675
+ self, original_node: cst.Call, updated_node: cst.Call
676
+ ) -> cst.Call:
677
+ # Check if the function being called is generate_vision_code or edit_vision_code
678
+ if isinstance(updated_node.func, cst.Name) and updated_node.func.value in [
679
+ "generate_vision_code",
680
+ "edit_vision_code",
681
+ ]:
682
+ # Add test_multi_plan argument to generate_vision_code calls
683
+ if updated_node.func.value == "generate_vision_code":
684
+ new_arg = cst.Arg(
685
+ keyword=cst.Name("test_multi_plan"),
686
+ value=cst.Name(str(self.test_multi_plan)),
687
+ equal=cst.AssignEqual(
688
+ whitespace_before=cst.SimpleWhitespace(""),
689
+ whitespace_after=cst.SimpleWhitespace(""),
690
+ ),
691
+ )
692
+ updated_node = updated_node.with_changes(
693
+ args=[*updated_node.args, new_arg]
694
+ )
695
+
696
+ # Add custom_tool_names if provided
697
+ if self.custom_tool_names is not None:
698
+ list_arg = []
699
+ for i, tool_name in enumerate(self.custom_tool_names):
700
+ if i < len(self.custom_tool_names) - 1:
701
+ list_arg.append(
702
+ cst._nodes.expression.Element(
703
+ value=cst.SimpleString(value=f'"{tool_name}"'),
704
+ comma=cst.Comma(
705
+ whitespace_before=cst.SimpleWhitespace(""),
706
+ whitespace_after=cst.SimpleWhitespace(" "),
707
+ ),
708
+ )
709
+ )
710
+ else:
711
+ list_arg.append(
712
+ cst._nodes.expression.Element(
713
+ value=cst.SimpleString(value=f'"{tool_name}"'),
714
+ )
715
+ )
716
+ new_arg = cst.Arg(
717
+ keyword=cst.Name("custom_tool_names"),
718
+ value=cst.List(list_arg),
719
+ equal=cst.AssignEqual(
720
+ whitespace_before=cst.SimpleWhitespace(""),
721
+ whitespace_after=cst.SimpleWhitespace(""),
722
+ ),
723
+ )
724
+ updated_node = updated_node.with_changes(
725
+ args=[*updated_node.args, new_arg]
726
+ )
727
+
728
+ return updated_node
729
+
730
+ # Parse the input code into a CST node
731
+ tree = cst.parse_module(code)
732
+
733
+ # Apply the transformer to modify the CST
734
+ transformer = VisionAgentTransformer(test_multi_plan, custom_tool_names)
735
+ modified_tree = tree.visit(transformer)
736
+
737
+ # Return the modified code as a string
738
+ return modified_tree.code
681
739
 
682
740
 
683
741
  def use_object_detection_fine_tuning(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vision-agent
3
- Version: 0.2.172
3
+ Version: 0.2.174
4
4
  Summary: Toolset for Vision Agent
5
5
  Author: Landing AI
6
6
  Author-email: dev@landing.ai
@@ -16,6 +16,7 @@ Requires-Dist: e2b-code-interpreter (==0.0.11a37)
16
16
  Requires-Dist: flake8 (>=7.0.0,<8.0.0)
17
17
  Requires-Dist: ipykernel (>=6.29.4,<7.0.0)
18
18
  Requires-Dist: langsmith (>=0.1.58,<0.2.0)
19
+ Requires-Dist: libcst (>=1.5.0,<2.0.0)
19
20
  Requires-Dist: nbclient (>=0.10.0,<0.11.0)
20
21
  Requires-Dist: nbformat (>=5.10.4,<6.0.0)
21
22
  Requires-Dist: numpy (>=1.21.0,<2.0.0)
@@ -27,7 +28,6 @@ Requires-Dist: pillow-heif (>=0.16.0,<0.17.0)
27
28
  Requires-Dist: pydantic (==2.7.4)
28
29
  Requires-Dist: pydantic-settings (>=2.2.1,<3.0.0)
29
30
  Requires-Dist: pytube (==15.0.0)
30
- Requires-Dist: redbaron (>=0.9.2,<0.10.0)
31
31
  Requires-Dist: requests (>=2.0.0,<3.0.0)
32
32
  Requires-Dist: rich (>=13.7.1,<14.0.0)
33
33
  Requires-Dist: scipy (>=1.13.0,<1.14.0)
@@ -2,8 +2,8 @@ vision_agent/__init__.py,sha256=EAb4-f9iyuEYkBrX4ag1syM8Syx8118_t0R6_C34M9w,57
2
2
  vision_agent/agent/__init__.py,sha256=RRMPhH8mgm_pCtEKiVFSjJyDi4lCr4F7k05AhK01xlM,436
3
3
  vision_agent/agent/agent.py,sha256=2cjIOxEuSJrqbfPXYoV0qER5ihXsPFCoEFJa4jpqan0,597
4
4
  vision_agent/agent/agent_utils.py,sha256=eSgg8CwWylX_erLTqTg2pVhEEgVkMLRrQfYRyJzI3so,5443
5
- vision_agent/agent/vision_agent.py,sha256=zzXLIOi5fNLiqCGt18kfOI4OQPq1qhEeKanfrzl7Qj0,26223
6
- vision_agent/agent/vision_agent_coder.py,sha256=aVkl0b9LKvy-auuHGYSag-ixYnue0iRQqD1PYLPBR-s,29312
5
+ vision_agent/agent/vision_agent.py,sha256=lEda43d-Ri68FIjmn-MPIgLs8_jMpyDVXslusQedhWA,26222
6
+ vision_agent/agent/vision_agent_coder.py,sha256=3Q1VWrN-BNUoSD4OAqKazvXkP2c04PXDYu2Z1f5dQb0,31960
7
7
  vision_agent/agent/vision_agent_coder_prompts.py,sha256=gPLVXQMNSzYnQYpNm0wlH_5FPkOTaFDV24bqzK3jQ40,12221
8
8
  vision_agent/agent/vision_agent_planner.py,sha256=mjmnXG9CvYf_ZA7ZJ3ri4H-2U_Km55gF1sZYRSOlxpY,19027
9
9
  vision_agent/agent/vision_agent_planner_prompts.py,sha256=JDARUzko2HZdxkBtcy6wuP9DCCmbqhK_gnVgrjr6l1k,6691
@@ -17,7 +17,7 @@ vision_agent/lmm/__init__.py,sha256=jyY1sJb_tYKg5-Wzs3p1lvwFkc-aUNZfMcLy3TOC4Zg,
17
17
  vision_agent/lmm/lmm.py,sha256=B5ClgwvbybVCWkf9opDMLjTtJZemUU4KUkQoRxGh43I,16787
18
18
  vision_agent/lmm/types.py,sha256=ZEXR_ptBL0ZwDMTDYkgxUCmSZFmBYPQd2jreNzr_8UY,221
19
19
  vision_agent/tools/__init__.py,sha256=u-vS5iORB4ccvxoAjbtpvhTALDhXGilcATIq1_eZhKo,2332
20
- vision_agent/tools/meta_tools.py,sha256=zcqp3POpGcS4cfceMih0AD1c6MwS_PFLLA6EjTXhonM,28013
20
+ vision_agent/tools/meta_tools.py,sha256=SVevrA5yxtSIXR8352QMMJv-jW8MIuA68Nj93DjW-60,30640
21
21
  vision_agent/tools/prompts.py,sha256=V1z4YJLXZuUl_iZ5rY0M5hHc_2tmMEUKr0WocXKGt4E,1430
22
22
  vision_agent/tools/tool_utils.py,sha256=VPGqGJ2ZYEJA6AW7K9X7hQv6vRlMtAQcybE4izdToCw,8196
23
23
  vision_agent/tools/tools.py,sha256=iKsBZxJ5--xWK-mqgZ1jbX_bfGS5HmAp-VRZ69m9yPg,77921
@@ -29,7 +29,7 @@ vision_agent/utils/image_utils.py,sha256=rm9GfXvD4JrjnqKrP_f2gfq4SzmqYC0IdC1kKwd
29
29
  vision_agent/utils/sim.py,sha256=ZuSS07TUXFGjipmiQoY8TKRmSes7XXCdtU9PI8PC1sw,5609
30
30
  vision_agent/utils/type_defs.py,sha256=BE12s3JNQy36QvauXHjwyeffVh5enfcvd4vTzSwvEZI,1384
31
31
  vision_agent/utils/video.py,sha256=fOPR48-SuwMbE5eB5rc2F7lVo6k1mVHn26eEJ0QCslc,5602
32
- vision_agent-0.2.172.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
33
- vision_agent-0.2.172.dist-info/METADATA,sha256=igL_7hfPKB2VSQgOobgmqVSLtmWOltFUsKE58MNYQDM,18342
34
- vision_agent-0.2.172.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
35
- vision_agent-0.2.172.dist-info/RECORD,,
32
+ vision_agent-0.2.174.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
33
+ vision_agent-0.2.174.dist-info/METADATA,sha256=V3d-gcpI2IZ4QWygiErgGAeNza-ROlsU-s1eH5Fr9UM,18339
34
+ vision_agent-0.2.174.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
35
+ vision_agent-0.2.174.dist-info/RECORD,,