vision-agent 0.2.162__tar.gz → 0.2.163__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. {vision_agent-0.2.162 → vision_agent-0.2.163}/PKG-INFO +2 -1
  2. {vision_agent-0.2.162 → vision_agent-0.2.163}/pyproject.toml +2 -1
  3. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/agent/agent_utils.py +22 -0
  4. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/agent/vision_agent.py +5 -5
  5. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/agent/vision_agent_coder.py +61 -25
  6. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/agent/vision_agent_coder_prompts.py +12 -18
  7. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/agent/vision_agent_planner.py +32 -2
  8. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/tools/meta_tools.py +23 -32
  9. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/tools/tools.py +2 -2
  10. {vision_agent-0.2.162 → vision_agent-0.2.163}/LICENSE +0 -0
  11. {vision_agent-0.2.162 → vision_agent-0.2.163}/README.md +0 -0
  12. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/__init__.py +0 -0
  13. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/agent/__init__.py +0 -0
  14. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/agent/agent.py +0 -0
  15. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/agent/vision_agent_planner_prompts.py +0 -0
  16. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/agent/vision_agent_prompts.py +0 -0
  17. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/clients/__init__.py +0 -0
  18. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/clients/http.py +0 -0
  19. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/clients/landing_public_api.py +0 -0
  20. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/fonts/__init__.py +0 -0
  21. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/fonts/default_font_ch_en.ttf +0 -0
  22. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/lmm/__init__.py +0 -0
  23. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/lmm/lmm.py +0 -0
  24. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/lmm/types.py +0 -0
  25. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/tools/__init__.py +0 -0
  26. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/tools/prompts.py +0 -0
  27. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/tools/tool_utils.py +0 -0
  28. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/tools/tools_types.py +0 -0
  29. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/utils/__init__.py +0 -0
  30. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/utils/exceptions.py +0 -0
  31. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/utils/execute.py +0 -0
  32. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/utils/image_utils.py +0 -0
  33. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/utils/sim.py +0 -0
  34. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/utils/type_defs.py +0 -0
  35. {vision_agent-0.2.162 → vision_agent-0.2.163}/vision_agent/utils/video.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vision-agent
3
- Version: 0.2.162
3
+ Version: 0.2.163
4
4
  Summary: Toolset for Vision Agent
5
5
  Author: Landing AI
6
6
  Author-email: dev@landing.ai
@@ -27,6 +27,7 @@ Requires-Dist: pillow-heif (>=0.16.0,<0.17.0)
27
27
  Requires-Dist: pydantic (==2.7.4)
28
28
  Requires-Dist: pydantic-settings (>=2.2.1,<3.0.0)
29
29
  Requires-Dist: pytube (==15.0.0)
30
+ Requires-Dist: redbaron (>=0.9.2,<0.10.0)
30
31
  Requires-Dist: requests (>=2.0.0,<3.0.0)
31
32
  Requires-Dist: rich (>=13.7.1,<14.0.0)
32
33
  Requires-Dist: scipy (>=1.13.0,<1.14.0)
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "vision-agent"
7
- version = "0.2.162"
7
+ version = "0.2.163"
8
8
  description = "Toolset for Vision Agent"
9
9
  authors = ["Landing AI <dev@landing.ai>"]
10
10
  readme = "README.md"
@@ -43,6 +43,7 @@ pytube = "15.0.0"
43
43
  anthropic = "^0.31.0"
44
44
  pydantic = "2.7.4"
45
45
  av = "^11.0.0"
46
+ redbaron = "^0.9.2"
46
47
 
47
48
  [tool.poetry.group.dev.dependencies]
48
49
  autoflake = "1.*"
@@ -13,6 +13,7 @@ import vision_agent.tools as T
13
13
  logging.basicConfig(stream=sys.stdout)
14
14
  _LOGGER = logging.getLogger(__name__)
15
15
  _CONSOLE = Console()
16
+ _MAX_TABULATE_COL_WIDTH = 80
16
17
 
17
18
 
18
19
  def _extract_sub_json(json_str: str) -> Optional[Dict[str, Any]]:
@@ -91,6 +92,27 @@ def extract_code(code: str) -> str:
91
92
  return code
92
93
 
93
94
 
95
+ def extract_tag(
96
+ content: str,
97
+ tag: str,
98
+ ) -> Optional[str]:
99
+ inner_content = None
100
+ remaning = content
101
+ all_inner_content = []
102
+
103
+ while f"<{tag}>" in remaning:
104
+ inner_content_i = remaning[remaning.find(f"<{tag}>") + len(f"<{tag}>") :]
105
+ if f"</{tag}>" not in inner_content_i:
106
+ break
107
+ inner_content_i = inner_content_i[: inner_content_i.find(f"</{tag}>")]
108
+ remaning = remaning[remaning.find(f"</{tag}>") + len(f"</{tag}>") :]
109
+ all_inner_content.append(inner_content_i)
110
+
111
+ if len(all_inner_content) > 0:
112
+ inner_content = "\n".join(all_inner_content)
113
+ return inner_content
114
+
115
+
94
116
  def remove_installs_from_code(code: str) -> str:
95
117
  pattern = r"\n!pip install.*?(\n|\Z)\n"
96
118
  code = re.sub(pattern, "", code, flags=re.DOTALL)
@@ -103,7 +103,7 @@ def execute_code_action(
103
103
  def parse_execution(
104
104
  response: str,
105
105
  test_multi_plan: bool = True,
106
- customed_tool_names: Optional[List[str]] = None,
106
+ custom_tool_names: Optional[List[str]] = None,
107
107
  ) -> Optional[str]:
108
108
  code = None
109
109
  remaining = response
@@ -122,7 +122,7 @@ def parse_execution(
122
122
  code = "\n".join(all_code)
123
123
 
124
124
  if code is not None:
125
- code = use_extra_vision_agent_args(code, test_multi_plan, customed_tool_names)
125
+ code = use_extra_vision_agent_args(code, test_multi_plan, custom_tool_names)
126
126
  return code
127
127
 
128
128
 
@@ -278,7 +278,7 @@ class VisionAgent(Agent):
278
278
  chat: List[Message],
279
279
  artifacts: Optional[Artifacts] = None,
280
280
  test_multi_plan: bool = True,
281
- customized_tool_names: Optional[List[str]] = None,
281
+ custom_tool_names: Optional[List[str]] = None,
282
282
  ) -> Tuple[List[Message], Artifacts]:
283
283
  """Chat with VisionAgent, it will use code to execute actions to accomplish
284
284
  its tasks.
@@ -292,7 +292,7 @@ class VisionAgent(Agent):
292
292
  test_multi_plan (bool): If True, it will test tools for multiple plans and
293
293
  pick the best one based off of the tool results. If False, it will go
294
294
  with the first plan.
295
- customized_tool_names (List[str]): A list of customized tools for agent to
295
+ custom_tool_names (List[str]): A list of customized tools for agent to
296
296
  pick and use. If not provided, default to full tool set from
297
297
  vision_agent.tools.
298
298
 
@@ -411,7 +411,7 @@ class VisionAgent(Agent):
411
411
  finished = response["let_user_respond"]
412
412
 
413
413
  code_action = parse_execution(
414
- response["response"], test_multi_plan, customized_tool_names
414
+ response["response"], test_multi_plan, custom_tool_names
415
415
  )
416
416
 
417
417
  if last_response == response:
@@ -5,14 +5,16 @@ 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
9
  from tabulate import tabulate
9
10
 
10
11
  import vision_agent.tools as T
11
12
  from vision_agent.agent.agent import Agent
12
13
  from vision_agent.agent.agent_utils import (
14
+ _MAX_TABULATE_COL_WIDTH,
13
15
  DefaultImports,
14
16
  extract_code,
15
- extract_json,
17
+ extract_tag,
16
18
  format_memory,
17
19
  print_code,
18
20
  remove_installs_from_code,
@@ -45,7 +47,44 @@ from vision_agent.utils.execute import CodeInterpreter
45
47
  logging.basicConfig(stream=sys.stdout)
46
48
  WORKSPACE = Path(os.getenv("WORKSPACE", ""))
47
49
  _LOGGER = logging.getLogger(__name__)
48
- _MAX_TABULATE_COL_WIDTH = 80
50
+
51
+
52
+ def strip_function_calls(code: str, exclusions: Optional[List[str]] = None) -> str:
53
+ """This will strip out all code that calls functions except for functions included
54
+ in exclusions.
55
+ """
56
+ if exclusions is None:
57
+ exclusions = []
58
+
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
49
88
 
50
89
 
51
90
  def write_code(
@@ -130,6 +169,7 @@ def write_and_test_code(
130
169
  plan_thoughts,
131
170
  format_memory(working_memory),
132
171
  )
172
+ code = strip_function_calls(code)
133
173
  test = write_test(
134
174
  tester, chat, tool_utils, code, format_memory(working_memory), media
135
175
  )
@@ -220,7 +260,9 @@ def debug_code(
220
260
  }
221
261
  )
222
262
 
223
- fixed_code_and_test = {"code": "", "test": "", "reflections": ""}
263
+ fixed_code = None
264
+ fixed_test = None
265
+ thoughts = ""
224
266
  success = False
225
267
  count = 0
226
268
  while not success and count < 3:
@@ -243,21 +285,16 @@ def debug_code(
243
285
  stream=False,
244
286
  )
245
287
  fixed_code_and_test_str = cast(str, fixed_code_and_test_str)
246
- fixed_code_and_test = extract_json(fixed_code_and_test_str)
247
- code = extract_code(fixed_code_and_test_str)
248
- if (
249
- "which_code" in fixed_code_and_test
250
- and fixed_code_and_test["which_code"] == "test"
251
- ):
252
- fixed_code_and_test["code"] = ""
253
- fixed_code_and_test["test"] = code
254
- else: # for everything else always assume it's updating code
255
- fixed_code_and_test["code"] = code
256
- fixed_code_and_test["test"] = ""
257
- if "which_code" in fixed_code_and_test:
258
- del fixed_code_and_test["which_code"]
259
-
260
- success = True
288
+ thoughts_tag = extract_tag(fixed_code_and_test_str, "thoughts")
289
+ thoughts = thoughts_tag if thoughts_tag is not None else ""
290
+ fixed_code = extract_tag(fixed_code_and_test_str, "code")
291
+ fixed_test = extract_tag(fixed_code_and_test_str, "test")
292
+
293
+ if fixed_code is None and fixed_test is None:
294
+ success = False
295
+ else:
296
+ success = True
297
+
261
298
  except Exception as e:
262
299
  _LOGGER.exception(f"Error while extracting JSON: {e}")
263
300
 
@@ -266,15 +303,15 @@ def debug_code(
266
303
  old_code = code
267
304
  old_test = test
268
305
 
269
- if fixed_code_and_test["code"].strip() != "":
270
- code = fixed_code_and_test["code"]
271
- if fixed_code_and_test["test"].strip() != "":
272
- test = fixed_code_and_test["test"]
306
+ if fixed_code is not None and fixed_code.strip() != "":
307
+ code = fixed_code
308
+ if fixed_test is not None and fixed_test.strip() != "":
309
+ test = fixed_test
273
310
 
274
311
  new_working_memory.append(
275
312
  {
276
313
  "code": f"{code}\n{test}",
277
- "feedback": fixed_code_and_test["reflections"],
314
+ "feedback": thoughts,
278
315
  "edits": get_diff(f"{old_code}\n{old_test}", f"{code}\n{test}"),
279
316
  }
280
317
  )
@@ -310,7 +347,7 @@ def debug_code(
310
347
  if verbosity == 2:
311
348
  print_code("Code and test after attempted fix:", code, test)
312
349
  _LOGGER.info(
313
- f"Reflection: {fixed_code_and_test['reflections']}\nCode execution result after attempted fix: {result.text(include_logs=True)}"
350
+ f"Reflection: {thoughts}\nCode execution result after attempted fix: {result.text(include_logs=True)}"
314
351
  )
315
352
 
316
353
  return code, test, result
@@ -514,7 +551,6 @@ class VisionAgentCoder(Agent):
514
551
  code = remove_installs_from_code(cast(str, results["code"]))
515
552
  test = remove_installs_from_code(cast(str, results["test"]))
516
553
  working_memory.extend(results["working_memory"])
517
-
518
554
  execution_result = cast(Execution, results["test_result"])
519
555
 
520
556
  return {
@@ -238,35 +238,29 @@ This is the documentation for the functions you have access to. You may call any
238
238
  {docstring}
239
239
 
240
240
  **Instructions**:
241
- Please re-complete the code to fix the error message. Here is the previous version:
242
- ```python
241
+ Please re-complete the code to fix the error message. Here is the current version of the CODE:
242
+ <code>
243
243
  {code}
244
- ```
244
+ </code>
245
245
 
246
- When we run this test code:
247
- ```python
246
+ When we run the TEST code:
247
+ <test>
248
248
  {tests}
249
- ```
249
+ </test>
250
250
 
251
251
  It raises this error:
252
- ```
252
+ <error>
253
253
  {result}
254
- ```
254
+ </error>
255
255
 
256
256
  This is previous feedback provided on the code:
257
257
  {feedback}
258
258
 
259
- Please fix the bug by correcting the error. Return the following JSON object followed by the fixed code in the below format:
260
- ```json
261
- {{
262
- "reflections": str # any thoughts you have about the bug and how you fixed it
263
- "which_code": str # the code that was fixed, can only be 'code' or 'test'
264
- }}
265
- ```
259
+ Please fix the bug by correcting the error. Return thoughts you have about the bug and how you fixed in <thoughts> tags followed by the fixed CODE in <code> tags and the fixed TEST in <test> tags. For example:
266
260
 
267
- ```python
268
- # Your fixed code here
269
- ```
261
+ <thoughts>Your thoughts here...</thoughts>
262
+ <code># your fixed code here</code>
263
+ <test># your fixed test here</test>
270
264
  """
271
265
 
272
266
 
@@ -5,10 +5,12 @@ from pathlib import Path
5
5
  from typing import Any, Callable, Dict, List, Optional, Tuple, Union, cast
6
6
 
7
7
  from pydantic import BaseModel
8
+ from tabulate import tabulate
8
9
 
9
10
  import vision_agent.tools as T
10
11
  from vision_agent.agent import Agent
11
12
  from vision_agent.agent.agent_utils import (
13
+ _MAX_TABULATE_COL_WIDTH,
12
14
  DefaultImports,
13
15
  extract_code,
14
16
  extract_json,
@@ -90,6 +92,18 @@ def retrieve_tools(
90
92
  return tool_lists_unique
91
93
 
92
94
 
95
+ def _check_plan_format(plan: Dict[str, Any]) -> bool:
96
+ if not isinstance(plan, dict):
97
+ return False
98
+
99
+ for k in plan:
100
+ if "thoughts" not in plan[k] or "instructions" not in plan[k]:
101
+ return False
102
+ if not isinstance(plan[k]["instructions"], list):
103
+ return False
104
+ return True
105
+
106
+
93
107
  def write_plans(
94
108
  chat: List[Message], tool_desc: str, working_memory: str, model: LMM
95
109
  ) -> Dict[str, Any]:
@@ -105,7 +119,16 @@ def write_plans(
105
119
  feedback=working_memory,
106
120
  )
107
121
  chat[-1]["content"] = prompt
108
- return extract_json(model(chat, stream=False)) # type: ignore
122
+ plans = extract_json(model(chat, stream=False)) # type: ignore
123
+
124
+ count = 0
125
+ while not _check_plan_format(plans) and count < 3:
126
+ _LOGGER.info("Invalid plan format. Retrying.")
127
+ plans = extract_json(model(chat, stream=False)) # type: ignore
128
+ count += 1
129
+ if count == 3:
130
+ raise ValueError("Failed to generate valid plans after 3 attempts.")
131
+ return plans
109
132
 
110
133
 
111
134
  def write_and_exec_plan_tests(
@@ -307,7 +330,6 @@ def pick_plan(
307
330
  "payload": plans[plan_thoughts["best_plan"]],
308
331
  }
309
332
  )
310
- # return plan_thoughts, "```python\n" + code + "\n```\n" + tool_output_str
311
333
  return plan_thoughts, code, tool_output
312
334
 
313
335
 
@@ -404,6 +426,14 @@ class VisionAgentPlanner(Agent):
404
426
  format_memory(working_memory),
405
427
  self.planner,
406
428
  )
429
+ if self.verbosity >= 1:
430
+ for plan in plans:
431
+ plan_fixed = [
432
+ {"instructions": e} for e in plans[plan]["instructions"]
433
+ ]
434
+ _LOGGER.info(
435
+ f"\n{tabulate(tabular_data=plan_fixed, headers='keys', tablefmt='mixed_grid', maxcolwidths=_MAX_TABULATE_COL_WIDTH)}"
436
+ )
407
437
 
408
438
  tool_docs = retrieve_tools(
409
439
  plans,
@@ -11,6 +11,7 @@ from typing import Any, Dict, List, Optional, Union
11
11
 
12
12
  import numpy as np
13
13
  from IPython.display import display
14
+ from redbaron import RedBaron # type: ignore
14
15
 
15
16
  import vision_agent as va
16
17
  from vision_agent.agent.agent_utils import extract_json
@@ -24,8 +25,6 @@ from vision_agent.utils.execute import Execution, MimeType
24
25
  from vision_agent.utils.image_utils import convert_to_b64, numpy_to_bytes
25
26
  from vision_agent.utils.video import frames_to_bytes
26
27
 
27
- # These tools are adapted from SWE-Agent https://github.com/princeton-nlp/SWE-agent
28
-
29
28
  CURRENT_FILE = None
30
29
  CURRENT_LINE = 0
31
30
  DEFAULT_WINDOW_SIZE = 100
@@ -154,6 +153,9 @@ class Artifacts:
154
153
  return name in self.artifacts
155
154
 
156
155
 
156
+ # These tools are adapted from SWE-Agent https://github.com/princeton-nlp/SWE-agent
157
+
158
+
157
159
  def format_lines(lines: List[str], start_idx: int) -> str:
158
160
  output = ""
159
161
  for i, line in enumerate(lines):
@@ -491,7 +493,7 @@ def edit_vision_code(
491
493
  name: str,
492
494
  chat_history: List[str],
493
495
  media: List[str],
494
- customized_tool_names: Optional[List[str]] = None,
496
+ custom_tool_names: Optional[List[str]] = None,
495
497
  ) -> str:
496
498
  """Edits python code to solve a vision based task.
497
499
 
@@ -499,7 +501,7 @@ def edit_vision_code(
499
501
  artifacts (Artifacts): The artifacts object to save the code to.
500
502
  name (str): The file path to the code.
501
503
  chat_history (List[str]): The chat history to used to generate the code.
502
- customized_tool_names (Optional[List[str]]): Do not change this parameter.
504
+ custom_tool_names (Optional[List[str]]): Do not change this parameter.
503
505
 
504
506
  Returns:
505
507
  str: The edited code.
@@ -542,7 +544,7 @@ def edit_vision_code(
542
544
  response = agent.generate_code(
543
545
  fixed_chat_history,
544
546
  test_multi_plan=False,
545
- custom_tool_names=customized_tool_names,
547
+ custom_tool_names=custom_tool_names,
546
548
  )
547
549
  redisplay_results(response["test_result"])
548
550
  code = response["code"]
@@ -705,7 +707,7 @@ def get_diff_with_prompts(name: str, before: str, after: str) -> str:
705
707
  def use_extra_vision_agent_args(
706
708
  code: str,
707
709
  test_multi_plan: bool = True,
708
- customized_tool_names: Optional[List[str]] = None,
710
+ custom_tool_names: Optional[List[str]] = None,
709
711
  ) -> str:
710
712
  """This is for forcing arguments passed by the user to VisionAgent into the
711
713
  VisionAgentCoder call.
@@ -713,36 +715,25 @@ def use_extra_vision_agent_args(
713
715
  Parameters:
714
716
  code (str): The code to edit.
715
717
  test_multi_plan (bool): Do not change this parameter.
716
- customized_tool_names (Optional[List[str]]): Do not change this parameter.
718
+ custom_tool_names (Optional[List[str]]): Do not change this parameter.
717
719
 
718
720
  Returns:
719
721
  str: The edited code.
720
722
  """
721
- generate_pattern = r"generate_vision_code\(\s*([^\)]+)\s*\)"
722
-
723
- def generate_replacer(match: re.Match) -> str:
724
- arg = match.group(1)
725
- out_str = f"generate_vision_code({arg}, test_multi_plan={test_multi_plan}"
726
- if customized_tool_names is not None:
727
- out_str += f", custom_tool_names={customized_tool_names})"
728
- else:
729
- out_str += ")"
730
- return out_str
731
-
732
- edit_pattern = r"edit_vision_code\(\s*([^\)]+)\s*\)"
733
-
734
- def edit_replacer(match: re.Match) -> str:
735
- arg = match.group(1)
736
- out_str = f"edit_vision_code({arg}"
737
- if customized_tool_names is not None:
738
- out_str += f", custom_tool_names={customized_tool_names})"
739
- else:
740
- out_str += ")"
741
- return out_str
742
-
743
- new_code = re.sub(generate_pattern, generate_replacer, code)
744
- new_code = re.sub(edit_pattern, edit_replacer, new_code)
745
- return new_code
723
+ red = RedBaron(code)
724
+ for node in red:
725
+ # seems to always be atomtrailers not call type
726
+ if node.type == "atomtrailers":
727
+ if (
728
+ node.name.value == "generate_vision_code"
729
+ or node.name.value == "edit_vision_code"
730
+ ):
731
+ node.value[1].value.append(f"test_multi_plan={test_multi_plan}")
732
+
733
+ if custom_tool_names is not None:
734
+ node.value[1].value.append(f"custom_tool_names={custom_tool_names}")
735
+ cleaned_code = red.dumps().strip()
736
+ return cleaned_code if isinstance(cleaned_code, str) else code
746
737
 
747
738
 
748
739
  def use_object_detection_fine_tuning(
@@ -1923,7 +1923,7 @@ def overlay_bounding_boxes(
1923
1923
  bboxes = bbox_int[i]
1924
1924
  bboxes = sorted(bboxes, key=lambda x: x["label"], reverse=True)
1925
1925
 
1926
- if len(bboxes) > 20:
1926
+ if len(bboxes) > 40:
1927
1927
  pil_image = _plot_counting(pil_image, bboxes, color)
1928
1928
  else:
1929
1929
  width, height = pil_image.size
@@ -2117,7 +2117,7 @@ def _plot_counting(
2117
2117
  colors: Dict[str, Tuple[int, int, int]],
2118
2118
  ) -> Image.Image:
2119
2119
  width, height = image.size
2120
- fontsize = max(10, int(min(width, height) / 80))
2120
+ fontsize = max(12, int(min(width, height) / 40))
2121
2121
  draw = ImageDraw.Draw(image)
2122
2122
  font = ImageFont.truetype(
2123
2123
  str(resources.files("vision_agent.fonts").joinpath("default_font_ch_en.ttf")),
File without changes
File without changes