vision-agent 0.2.93__py3-none-any.whl → 0.2.95__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- vision_agent/agent/vision_agent_coder.py +15 -19
- vision_agent/tools/tools.py +15 -10
- vision_agent/utils/execute.py +71 -36
- vision_agent/utils/sim.py +1 -0
- {vision_agent-0.2.93.dist-info → vision_agent-0.2.95.dist-info}/METADATA +3 -2
- {vision_agent-0.2.93.dist-info → vision_agent-0.2.95.dist-info}/RECORD +8 -8
- {vision_agent-0.2.93.dist-info → vision_agent-0.2.95.dist-info}/LICENSE +0 -0
- {vision_agent-0.2.93.dist-info → vision_agent-0.2.95.dist-info}/WHEEL +0 -0
@@ -373,7 +373,7 @@ def write_and_test_code(
|
|
373
373
|
"code": DefaultImports.prepend_imports(code),
|
374
374
|
"payload": {
|
375
375
|
"test": test,
|
376
|
-
"result": result.to_json(),
|
376
|
+
# "result": result.to_json(),
|
377
377
|
},
|
378
378
|
}
|
379
379
|
)
|
@@ -426,7 +426,8 @@ def debug_code(
|
|
426
426
|
) -> tuple[str, str, Execution]:
|
427
427
|
log_progress(
|
428
428
|
{
|
429
|
-
"type": "
|
429
|
+
"type": "log",
|
430
|
+
"log_content": ("Debugging code"),
|
430
431
|
"status": "started",
|
431
432
|
}
|
432
433
|
)
|
@@ -469,10 +470,11 @@ def debug_code(
|
|
469
470
|
)
|
470
471
|
log_progress(
|
471
472
|
{
|
472
|
-
"type": "
|
473
|
+
"type": "log",
|
474
|
+
"log_content": ("Running code"),
|
473
475
|
"status": "running",
|
476
|
+
"code": DefaultImports.prepend_imports(code),
|
474
477
|
"payload": {
|
475
|
-
"code": DefaultImports.prepend_imports(code),
|
476
478
|
"test": test,
|
477
479
|
},
|
478
480
|
}
|
@@ -483,12 +485,15 @@ def debug_code(
|
|
483
485
|
)
|
484
486
|
log_progress(
|
485
487
|
{
|
486
|
-
"type": "
|
488
|
+
"type": "log",
|
489
|
+
"log_content": (
|
490
|
+
"Code execution succeed" if result.success else "Code execution failed"
|
491
|
+
),
|
487
492
|
"status": "completed" if result.success else "failed",
|
493
|
+
"code": DefaultImports.prepend_imports(code),
|
488
494
|
"payload": {
|
489
|
-
"code": DefaultImports.prepend_imports(code),
|
490
495
|
"test": test,
|
491
|
-
"result": result.to_json(),
|
496
|
+
# "result": result.to_json(),
|
492
497
|
},
|
493
498
|
}
|
494
499
|
)
|
@@ -525,7 +530,8 @@ def retrieve_tools(
|
|
525
530
|
) -> Dict[str, str]:
|
526
531
|
log_progress(
|
527
532
|
{
|
528
|
-
"type": "
|
533
|
+
"type": "log",
|
534
|
+
"log_content": ("Retrieving tools for each plan"),
|
529
535
|
"status": "started",
|
530
536
|
}
|
531
537
|
)
|
@@ -802,17 +808,6 @@ class VisionAgentCoder(Agent):
|
|
802
808
|
plan.append({"code": code, "test": test, "plan": plan_i})
|
803
809
|
|
804
810
|
execution_result = cast(Execution, results["test_result"])
|
805
|
-
self.log_progress(
|
806
|
-
{
|
807
|
-
"type": "final_code",
|
808
|
-
"status": "completed" if success else "failed",
|
809
|
-
"payload": {
|
810
|
-
"code": DefaultImports.prepend_imports(code),
|
811
|
-
"test": test,
|
812
|
-
"result": execution_result.to_json(),
|
813
|
-
},
|
814
|
-
}
|
815
|
-
)
|
816
811
|
|
817
812
|
if display_visualization:
|
818
813
|
for res in execution_result.results:
|
@@ -822,6 +817,7 @@ class VisionAgentCoder(Agent):
|
|
822
817
|
play_video(res.mp4)
|
823
818
|
|
824
819
|
return {
|
820
|
+
"status": "completed" if success else "failed",
|
825
821
|
"code": DefaultImports.prepend_imports(code),
|
826
822
|
"test": test,
|
827
823
|
"test_result": execution_result,
|
vision_agent/tools/tools.py
CHANGED
@@ -9,7 +9,6 @@ from typing import Any, Dict, List, Optional, Tuple, Union, cast
|
|
9
9
|
import cv2
|
10
10
|
import numpy as np
|
11
11
|
import requests
|
12
|
-
from moviepy.editor import ImageSequenceClip
|
13
12
|
from PIL import Image, ImageDraw, ImageFont
|
14
13
|
from pillow_heif import register_heif_opener # type: ignore
|
15
14
|
from pytube import YouTube # type: ignore
|
@@ -1044,15 +1043,21 @@ def save_video(
|
|
1044
1043
|
if fps <= 0:
|
1045
1044
|
_LOGGER.warning(f"Invalid fps value: {fps}. Setting fps to 4 (default value).")
|
1046
1045
|
fps = 4
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1046
|
+
|
1047
|
+
if not output_video_path:
|
1048
|
+
output_video_path = tempfile.NamedTemporaryFile(
|
1049
|
+
suffix=".mp4", delete=False
|
1050
|
+
).name
|
1051
|
+
|
1052
|
+
height, width, layers = frames[0].shape if frames else (0, 0, 0)
|
1053
|
+
fourcc = cv2.VideoWriter_fourcc(*"mp4v") # type: ignore
|
1054
|
+
video = cv2.VideoWriter(output_video_path, fourcc, fps, (width, height))
|
1055
|
+
for frame in frames:
|
1056
|
+
video.write(cv2.cvtColor(frame, cv2.COLOR_RGB2BGR))
|
1057
|
+
video.release()
|
1058
|
+
|
1059
|
+
_save_video_to_result(output_video_path)
|
1060
|
+
return output_video_path
|
1056
1061
|
|
1057
1062
|
|
1058
1063
|
def _save_video_to_result(video_uri: str) -> None:
|
vision_agent/utils/execute.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
import abc
|
2
2
|
import base64
|
3
|
-
import copy
|
4
3
|
import logging
|
5
4
|
import os
|
6
5
|
import platform
|
@@ -17,9 +16,14 @@ from typing import Any, Dict, Iterable, List, Optional, Union
|
|
17
16
|
import nbformat
|
18
17
|
import tenacity
|
19
18
|
from dotenv import load_dotenv
|
19
|
+
from e2b.exceptions import SandboxException
|
20
20
|
from e2b_code_interpreter import CodeInterpreter as E2BCodeInterpreterImpl
|
21
21
|
from e2b_code_interpreter import Execution as E2BExecution
|
22
22
|
from e2b_code_interpreter import Result as E2BResult
|
23
|
+
from h11._util import LocalProtocolError
|
24
|
+
from httpx import ConnectError
|
25
|
+
from httpx import RemoteProtocolError as HttpcoreRemoteProtocolError
|
26
|
+
from httpx import RemoteProtocolError as HttpxRemoteProtocolError
|
23
27
|
from nbclient import NotebookClient
|
24
28
|
from nbclient import __version__ as nbclient_version
|
25
29
|
from nbclient.exceptions import CellTimeoutError, DeadKernelError
|
@@ -29,7 +33,6 @@ from pydantic import BaseModel, field_serializer
|
|
29
33
|
from typing_extensions import Self
|
30
34
|
|
31
35
|
from vision_agent.utils.exceptions import (
|
32
|
-
RemoteSandboxClosedError,
|
33
36
|
RemoteSandboxCreationError,
|
34
37
|
RemoteSandboxExecutionError,
|
35
38
|
)
|
@@ -106,13 +109,8 @@ class Result:
|
|
106
109
|
is_main_result: bool
|
107
110
|
"Whether this data is the result of the cell. Data can be produced by display calls of which can be multiple in a cell."
|
108
111
|
|
109
|
-
raw: Dict[str, str]
|
110
|
-
"Dictionary that maps MIME types to their corresponding string representations of the data."
|
111
|
-
|
112
112
|
def __init__(self, is_main_result: bool, data: Dict[str, Any]):
|
113
113
|
self.is_main_result = is_main_result
|
114
|
-
self.raw = copy.deepcopy(data)
|
115
|
-
|
116
114
|
self.text = data.pop(MimeType.TEXT_PLAIN, None)
|
117
115
|
if self.text and (self.text.startswith("'") and self.text.endswith("'")):
|
118
116
|
# This is a workaround for the issue that str result is wrapped with single quotes by notebook.
|
@@ -136,13 +134,13 @@ class Result:
|
|
136
134
|
|
137
135
|
# Allows to iterate over formats()
|
138
136
|
def __getitem__(self, key: Any) -> Any:
|
139
|
-
return
|
137
|
+
return getattr(self, key)
|
140
138
|
|
141
139
|
def __str__(self) -> str:
|
142
140
|
return repr(self)
|
143
141
|
|
144
142
|
def __repr__(self) -> str:
|
145
|
-
return str(self.
|
143
|
+
return str(self.text)
|
146
144
|
|
147
145
|
def _repr_html_(self) -> Optional[str]:
|
148
146
|
"""Returns the HTML representation of the data."""
|
@@ -215,9 +213,16 @@ class Result:
|
|
215
213
|
"""
|
216
214
|
Creates a Result object from an E2BResult object.
|
217
215
|
"""
|
216
|
+
data = {
|
217
|
+
MimeType.TEXT_PLAIN.value: result.text,
|
218
|
+
MimeType.IMAGE_PNG.value: result.png,
|
219
|
+
MimeType.APPLICATION_JSON.value: result.json,
|
220
|
+
}
|
221
|
+
for k, v in result.extra.items():
|
222
|
+
data[k] = v
|
218
223
|
return Result(
|
219
224
|
is_main_result=result.is_main_result,
|
220
|
-
data=
|
225
|
+
data=data,
|
221
226
|
)
|
222
227
|
|
223
228
|
|
@@ -367,7 +372,7 @@ class Execution(BaseModel):
|
|
367
372
|
value=_remove_escape_and_color_codes(exec.error.value),
|
368
373
|
traceback_raw=[
|
369
374
|
_remove_escape_and_color_codes(line)
|
370
|
-
for line in exec.error.
|
375
|
+
for line in exec.error.traceback.split("\n")
|
371
376
|
],
|
372
377
|
)
|
373
378
|
if exec.error
|
@@ -436,11 +441,12 @@ va_version = importlib.metadata.version("vision-agent")
|
|
436
441
|
print(f"Vision Agent version: {va_version}")"""
|
437
442
|
)
|
438
443
|
sys_versions = "\n".join(result.logs.stdout)
|
439
|
-
_LOGGER.info(
|
444
|
+
_LOGGER.info(
|
445
|
+
f"E2BCodeInterpreter (sandbox id: {self.interpreter.sandbox_id}) initialized:\n{sys_versions}"
|
446
|
+
)
|
440
447
|
|
441
448
|
def close(self, *args: Any, **kwargs: Any) -> None:
|
442
449
|
try:
|
443
|
-
self.interpreter.notebook.close()
|
444
450
|
self.interpreter.kill(request_timeout=2)
|
445
451
|
_LOGGER.info(
|
446
452
|
f"The sandbox {self.interpreter.sandbox_id} is closed successfully."
|
@@ -451,28 +457,67 @@ print(f"Vision Agent version: {va_version}")"""
|
|
451
457
|
)
|
452
458
|
|
453
459
|
def restart_kernel(self) -> None:
|
454
|
-
self._check_sandbox_liveness()
|
455
460
|
self.interpreter.notebook.restart_kernel()
|
456
461
|
|
457
462
|
@tenacity.retry(
|
458
463
|
wait=tenacity.wait_exponential_jitter(),
|
459
|
-
stop=tenacity.stop_after_attempt(
|
460
|
-
|
461
|
-
|
464
|
+
stop=tenacity.stop_after_attempt(3),
|
465
|
+
retry=tenacity.retry_if_exception_type(
|
466
|
+
(
|
467
|
+
LocalProtocolError,
|
468
|
+
HttpxRemoteProtocolError,
|
469
|
+
HttpcoreRemoteProtocolError,
|
470
|
+
ConnectError,
|
471
|
+
SandboxException,
|
472
|
+
)
|
473
|
+
),
|
474
|
+
before_sleep=tenacity.before_sleep_log(_LOGGER, logging.INFO),
|
475
|
+
after=tenacity.after_log(_LOGGER, logging.INFO),
|
462
476
|
)
|
463
477
|
def exec_cell(self, code: str) -> Execution:
|
464
|
-
self._check_sandbox_liveness()
|
465
478
|
self.interpreter.set_timeout(_SESSION_TIMEOUT) # Extend the life of the sandbox
|
466
479
|
try:
|
467
|
-
|
480
|
+
_LOGGER.info(
|
481
|
+
f"Start code execution in remote sandbox {self.interpreter.sandbox_id}. Timeout: {_SESSION_TIMEOUT}. Code hash: {hash(code)}"
|
482
|
+
)
|
483
|
+
execution = self.interpreter.notebook.exec_cell(
|
484
|
+
code=code,
|
485
|
+
on_stdout=lambda msg: _LOGGER.info(msg),
|
486
|
+
on_stderr=lambda msg: _LOGGER.info(msg),
|
487
|
+
)
|
488
|
+
_LOGGER.info(
|
489
|
+
f"Finished code execution in remote sandbox {self.interpreter.sandbox_id}. Code hash: {hash(code)}"
|
490
|
+
)
|
468
491
|
return Execution.from_e2b_execution(execution)
|
492
|
+
except (
|
493
|
+
LocalProtocolError,
|
494
|
+
HttpxRemoteProtocolError,
|
495
|
+
HttpcoreRemoteProtocolError,
|
496
|
+
ConnectError,
|
497
|
+
SandboxException,
|
498
|
+
) as e:
|
499
|
+
raise e
|
469
500
|
except Exception as e:
|
470
501
|
raise RemoteSandboxExecutionError(
|
471
|
-
f"Failed executing code in remote sandbox due to {e}: {code}"
|
502
|
+
f"Failed executing code in remote sandbox ({self.interpreter.sandbox_id}) due to error '{type(e).__name__} {str(e)}', code: {code}"
|
472
503
|
) from e
|
473
504
|
|
505
|
+
@tenacity.retry(
|
506
|
+
wait=tenacity.wait_exponential_jitter(),
|
507
|
+
stop=tenacity.stop_after_attempt(3),
|
508
|
+
retry=tenacity.retry_if_exception_type(
|
509
|
+
(
|
510
|
+
LocalProtocolError,
|
511
|
+
HttpxRemoteProtocolError,
|
512
|
+
HttpcoreRemoteProtocolError,
|
513
|
+
ConnectError,
|
514
|
+
SandboxException,
|
515
|
+
)
|
516
|
+
),
|
517
|
+
before_sleep=tenacity.before_sleep_log(_LOGGER, logging.INFO),
|
518
|
+
after=tenacity.after_log(_LOGGER, logging.INFO),
|
519
|
+
)
|
474
520
|
def upload_file(self, file: Union[str, Path]) -> str:
|
475
|
-
self._check_sandbox_liveness()
|
476
521
|
file_name = Path(file).name
|
477
522
|
remote_path = f"/home/user/{file_name}"
|
478
523
|
with open(file, "rb") as f:
|
@@ -481,28 +526,18 @@ print(f"Vision Agent version: {va_version}")"""
|
|
481
526
|
return remote_path
|
482
527
|
|
483
528
|
def download_file(self, file_path: str) -> Path:
|
484
|
-
self._check_sandbox_liveness()
|
485
529
|
with tempfile.NamedTemporaryFile(mode="w+b", delete=False) as file:
|
486
530
|
file.write(self.interpreter.files.read(path=file_path, format="bytes"))
|
487
531
|
_LOGGER.info(f"File ({file_path}) is downloaded to: {file.name}")
|
488
532
|
return Path(file.name)
|
489
533
|
|
490
|
-
def _check_sandbox_liveness(self) -> None:
|
491
|
-
try:
|
492
|
-
alive = self.interpreter.is_running(request_timeout=2)
|
493
|
-
except Exception as e:
|
494
|
-
_LOGGER.error(
|
495
|
-
f"Failed to check the health of the remote sandbox ({self.interpreter.sandbox_id}) due to {e}. Consider the sandbox as dead."
|
496
|
-
)
|
497
|
-
alive = False
|
498
|
-
if not alive:
|
499
|
-
raise RemoteSandboxClosedError(
|
500
|
-
"Remote sandbox is closed unexpectedly. Please start a new VisionAgent instance."
|
501
|
-
)
|
502
|
-
|
503
534
|
@staticmethod
|
504
535
|
def _new_e2b_interpreter_impl(*args, **kwargs) -> E2BCodeInterpreterImpl: # type: ignore
|
505
|
-
|
536
|
+
template_name = os.environ.get("E2B_TEMPLATE_NAME", "nx3fagq7sgdliww9cvm3")
|
537
|
+
_LOGGER.info(
|
538
|
+
f"Creating a new E2BCodeInterpreter using template: {template_name}"
|
539
|
+
)
|
540
|
+
return E2BCodeInterpreterImpl(template=template_name, *args, **kwargs)
|
506
541
|
|
507
542
|
|
508
543
|
class LocalCodeInterpreter(CodeInterpreter):
|
vision_agent/utils/sim.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: vision-agent
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.95
|
4
4
|
Summary: Toolset for Vision Agent
|
5
5
|
Author: Landing AI
|
6
6
|
Author-email: dev@landing.ai
|
@@ -11,7 +11,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.11
|
12
12
|
Requires-Dist: anthropic (>=0.31.0,<0.32.0)
|
13
13
|
Requires-Dist: e2b (>=0.17.1,<0.18.0)
|
14
|
-
Requires-Dist: e2b-code-interpreter (==0.0.
|
14
|
+
Requires-Dist: e2b-code-interpreter (==0.0.11a17)
|
15
15
|
Requires-Dist: ipykernel (>=6.29.4,<7.0.0)
|
16
16
|
Requires-Dist: langsmith (>=0.1.58,<0.2.0)
|
17
17
|
Requires-Dist: moviepy (>=1.0.0,<2.0.0)
|
@@ -23,6 +23,7 @@ Requires-Dist: opencv-python (>=4.0.0,<5.0.0)
|
|
23
23
|
Requires-Dist: pandas (>=2.0.0,<3.0.0)
|
24
24
|
Requires-Dist: pillow (>=10.0.0,<11.0.0)
|
25
25
|
Requires-Dist: pillow-heif (>=0.16.0,<0.17.0)
|
26
|
+
Requires-Dist: pydantic (==2.7.4)
|
26
27
|
Requires-Dist: pydantic-settings (>=2.2.1,<3.0.0)
|
27
28
|
Requires-Dist: pytube (==15.0.0)
|
28
29
|
Requires-Dist: requests (>=2.0.0,<3.0.0)
|
@@ -3,7 +3,7 @@ vision_agent/agent/__init__.py,sha256=qpduQ9YufJQfMmG6jwKC2xmlbtR2qK8_1eQC1sGA9K
|
|
3
3
|
vision_agent/agent/agent.py,sha256=Bt8yhjCFXuRdZaHxKEesG40V09nWRt45sZluri1R3AA,575
|
4
4
|
vision_agent/agent/agent_utils.py,sha256=JXdl2xz14LKQAmScY-MIW23AD2WBFCsnI0JS6dAyj3Q,1412
|
5
5
|
vision_agent/agent/vision_agent.py,sha256=i_rNpc7faqHTifp2c9sQE4Js3qYUKuJeiqauTp90OlE,8417
|
6
|
-
vision_agent/agent/vision_agent_coder.py,sha256=
|
6
|
+
vision_agent/agent/vision_agent_coder.py,sha256=M8J5xE9uX8Nig1WmVmwLMeCSe0E6Bg3Mo5fPPcW_a-c,30246
|
7
7
|
vision_agent/agent/vision_agent_coder_prompts.py,sha256=a3R_vHlT2FW3-DSn4OWgzF9zEAx-uKM4ZaTi9Kn-K54,11116
|
8
8
|
vision_agent/agent/vision_agent_prompts.py,sha256=hjs-m4ZHR7HE1HtOeX_1rOvTQA2FMEAqEkaBbGPBYDo,6072
|
9
9
|
vision_agent/fonts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -15,15 +15,15 @@ vision_agent/tools/__init__.py,sha256=UNiaJAOt1C709gaJ-a9h9BzKnY5JmoEUpgKftsOnyP
|
|
15
15
|
vision_agent/tools/meta_tools.py,sha256=rmxgVzj-vJKeewHbue3qHru4sYsFLxlSZV-YH-eyH5w,13366
|
16
16
|
vision_agent/tools/prompts.py,sha256=V1z4YJLXZuUl_iZ5rY0M5hHc_2tmMEUKr0WocXKGt4E,1430
|
17
17
|
vision_agent/tools/tool_utils.py,sha256=XoB-iae8hHrBQgJd3fV6-UjZAkClysobUaOM17IcHuE,4597
|
18
|
-
vision_agent/tools/tools.py,sha256=
|
18
|
+
vision_agent/tools/tools.py,sha256=CWQY1sD-xtWchPrg_AJNAGH-k7UxrKIkiog8r0sx1Do,42446
|
19
19
|
vision_agent/utils/__init__.py,sha256=CW84HnhqI6XQVuxf2KifkLnSuO7EOhmuL09-gAymAak,219
|
20
20
|
vision_agent/utils/exceptions.py,sha256=isVH-SVL4vHj3q5kK4z7cy5_aOapAqHXWkpibfSNbUs,1659
|
21
|
-
vision_agent/utils/execute.py,sha256=
|
21
|
+
vision_agent/utils/execute.py,sha256=s43aUtuq7ZNjil2mxrddiz8EvvqlJwttkYlIiZouXqM,25125
|
22
22
|
vision_agent/utils/image_utils.py,sha256=y69wtNla0xHZ1h1x0-vv7nOyKUq69jtjSJBiDCn6EM0,7703
|
23
|
-
vision_agent/utils/sim.py,sha256=
|
23
|
+
vision_agent/utils/sim.py,sha256=7JvtWGN0Ik5ife3qQYWs7Fm3T8AnAXGFd5HnvDC15mQ,4433
|
24
24
|
vision_agent/utils/type_defs.py,sha256=oVFJcicB-s_09lqvn61u0A5ncZsTqZArZledXWbrrg0,1384
|
25
25
|
vision_agent/utils/video.py,sha256=rNmU9KEIkZB5-EztZNlUiKYN0mm_55A_2VGUM0QpqLA,8779
|
26
|
-
vision_agent-0.2.
|
27
|
-
vision_agent-0.2.
|
28
|
-
vision_agent-0.2.
|
29
|
-
vision_agent-0.2.
|
26
|
+
vision_agent-0.2.95.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
27
|
+
vision_agent-0.2.95.dist-info/METADATA,sha256=-OCOFe_UAKyI5sjDr6nYklJq5jwKZbLjwFkFMO-wrV8,10728
|
28
|
+
vision_agent-0.2.95.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
|
29
|
+
vision_agent-0.2.95.dist-info/RECORD,,
|
File without changes
|
File without changes
|