vision-agent 0.2.94__tar.gz → 0.2.96__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {vision_agent-0.2.94 → vision_agent-0.2.96}/PKG-INFO +3 -2
- {vision_agent-0.2.94 → vision_agent-0.2.96}/pyproject.toml +3 -2
- {vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/tools/tools.py +34 -10
- {vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/utils/execute.py +71 -36
- {vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/utils/sim.py +1 -0
- {vision_agent-0.2.94 → vision_agent-0.2.96}/LICENSE +0 -0
- {vision_agent-0.2.94 → vision_agent-0.2.96}/README.md +0 -0
- {vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/__init__.py +0 -0
- {vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/agent/__init__.py +0 -0
- {vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/agent/agent.py +0 -0
- {vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/agent/agent_utils.py +0 -0
- {vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/agent/vision_agent.py +0 -0
- {vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/agent/vision_agent_coder.py +0 -0
- {vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/agent/vision_agent_coder_prompts.py +0 -0
- {vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/agent/vision_agent_prompts.py +0 -0
- {vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/fonts/__init__.py +0 -0
- {vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/fonts/default_font_ch_en.ttf +0 -0
- {vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/lmm/__init__.py +0 -0
- {vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/lmm/lmm.py +0 -0
- {vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/lmm/types.py +0 -0
- {vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/tools/__init__.py +0 -0
- {vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/tools/meta_tools.py +0 -0
- {vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/tools/prompts.py +0 -0
- {vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/tools/tool_utils.py +0 -0
- {vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/utils/__init__.py +0 -0
- {vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/utils/exceptions.py +0 -0
- {vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/utils/image_utils.py +0 -0
- {vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/utils/type_defs.py +0 -0
- {vision_agent-0.2.94 → vision_agent-0.2.96}/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.
|
3
|
+
Version: 0.2.96
|
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)
|
@@ -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.
|
7
|
+
version = "0.2.96"
|
8
8
|
description = "Toolset for Vision Agent"
|
9
9
|
authors = ["Landing AI <dev@landing.ai>"]
|
10
10
|
readme = "README.md"
|
@@ -35,11 +35,12 @@ rich = "^13.7.1"
|
|
35
35
|
langsmith = "^0.1.58"
|
36
36
|
ipykernel = "^6.29.4"
|
37
37
|
e2b = "^0.17.1"
|
38
|
-
e2b-code-interpreter = "0.0.
|
38
|
+
e2b-code-interpreter = "0.0.11a17"
|
39
39
|
tenacity = "^8.3.0"
|
40
40
|
pillow-heif = "^0.16.0"
|
41
41
|
pytube = "15.0.0"
|
42
42
|
anthropic = "^0.31.0"
|
43
|
+
pydantic = "2.7.4"
|
43
44
|
|
44
45
|
[tool.poetry.group.dev.dependencies]
|
45
46
|
autoflake = "1.*"
|
@@ -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
|
@@ -107,6 +106,7 @@ def grounding_dino(
|
|
107
106
|
"visual_grounding" if model_size == "large" else "visual_grounding_tiny"
|
108
107
|
),
|
109
108
|
"kwargs": {"box_threshold": box_threshold, "iou_threshold": iou_threshold},
|
109
|
+
"function_name": "grounding_dino",
|
110
110
|
}
|
111
111
|
data: Dict[str, Any] = send_inference_request(request_data, "tools")
|
112
112
|
return_data = []
|
@@ -162,6 +162,7 @@ def owl_v2(
|
|
162
162
|
"image": image_b64,
|
163
163
|
"tool": "open_vocab_detection",
|
164
164
|
"kwargs": {"box_threshold": box_threshold, "iou_threshold": iou_threshold},
|
165
|
+
"function_name": "owl_v2",
|
165
166
|
}
|
166
167
|
data: Dict[str, Any] = send_inference_request(request_data, "tools")
|
167
168
|
return_data = []
|
@@ -226,6 +227,7 @@ def grounding_sam(
|
|
226
227
|
"image": image_b64,
|
227
228
|
"tool": "visual_grounding_segment",
|
228
229
|
"kwargs": {"box_threshold": box_threshold, "iou_threshold": iou_threshold},
|
230
|
+
"function_name": "grounding_sam",
|
229
231
|
}
|
230
232
|
data: Dict[str, Any] = send_inference_request(request_data, "tools")
|
231
233
|
return_data = []
|
@@ -365,6 +367,7 @@ def loca_zero_shot_counting(image: np.ndarray) -> Dict[str, Any]:
|
|
365
367
|
data = {
|
366
368
|
"image": image_b64,
|
367
369
|
"tool": "zero_shot_counting",
|
370
|
+
"function_name": "loca_zero_shot_counting",
|
368
371
|
}
|
369
372
|
resp_data = send_inference_request(data, "tools")
|
370
373
|
resp_data["heat_map"] = np.array(b64_to_pil(resp_data["heat_map"][0]))
|
@@ -400,6 +403,7 @@ def loca_visual_prompt_counting(
|
|
400
403
|
"image": image_b64,
|
401
404
|
"prompt": bbox_str,
|
402
405
|
"tool": "few_shot_counting",
|
406
|
+
"function_name": "loca_visual_prompt_counting",
|
403
407
|
}
|
404
408
|
resp_data = send_inference_request(data, "tools")
|
405
409
|
resp_data["heat_map"] = np.array(b64_to_pil(resp_data["heat_map"][0]))
|
@@ -429,6 +433,7 @@ def florencev2_roberta_vqa(prompt: str, image: np.ndarray) -> str:
|
|
429
433
|
"image": image_b64,
|
430
434
|
"prompt": prompt,
|
431
435
|
"tool": "image_question_answering_with_context",
|
436
|
+
"function_name": "florencev2_roberta_vqa",
|
432
437
|
}
|
433
438
|
|
434
439
|
answer = send_inference_request(data, "tools")
|
@@ -458,6 +463,7 @@ def git_vqa_v2(prompt: str, image: np.ndarray) -> str:
|
|
458
463
|
"image": image_b64,
|
459
464
|
"prompt": prompt,
|
460
465
|
"tool": "image_question_answering",
|
466
|
+
"function_name": "git_vqa_v2",
|
461
467
|
}
|
462
468
|
|
463
469
|
answer = send_inference_request(data, "tools")
|
@@ -488,6 +494,7 @@ def clip(image: np.ndarray, classes: List[str]) -> Dict[str, Any]:
|
|
488
494
|
"prompt": ",".join(classes),
|
489
495
|
"image": image_b64,
|
490
496
|
"tool": "closed_set_image_classification",
|
497
|
+
"function_name": "clip",
|
491
498
|
}
|
492
499
|
resp_data = send_inference_request(data, "tools")
|
493
500
|
resp_data["scores"] = [round(prob, 4) for prob in resp_data["scores"]]
|
@@ -515,6 +522,7 @@ def vit_image_classification(image: np.ndarray) -> Dict[str, Any]:
|
|
515
522
|
data = {
|
516
523
|
"image": image_b64,
|
517
524
|
"tool": "image_classification",
|
525
|
+
"function_name": "vit_image_classification",
|
518
526
|
}
|
519
527
|
resp_data = send_inference_request(data, "tools")
|
520
528
|
resp_data["scores"] = [round(prob, 4) for prob in resp_data["scores"]]
|
@@ -542,6 +550,7 @@ def vit_nsfw_classification(image: np.ndarray) -> Dict[str, Any]:
|
|
542
550
|
data = {
|
543
551
|
"image": image_b64,
|
544
552
|
"tool": "nsfw_image_classification",
|
553
|
+
"function_name": "vit_nsfw_classification",
|
545
554
|
}
|
546
555
|
resp_data = send_inference_request(data, "tools")
|
547
556
|
resp_data["scores"] = round(resp_data["scores"], 4)
|
@@ -568,6 +577,7 @@ def blip_image_caption(image: np.ndarray) -> str:
|
|
568
577
|
data = {
|
569
578
|
"image": image_b64,
|
570
579
|
"tool": "image_captioning",
|
580
|
+
"function_name": "blip_image_caption",
|
571
581
|
}
|
572
582
|
|
573
583
|
answer = send_inference_request(data, "tools")
|
@@ -596,6 +606,7 @@ def florencev2_image_caption(image: np.ndarray, detail_caption: bool = True) ->
|
|
596
606
|
"image": image_b64,
|
597
607
|
"tool": "florence2_image_captioning",
|
598
608
|
"detail_caption": detail_caption,
|
609
|
+
"function_name": "florencev2_image_caption",
|
599
610
|
}
|
600
611
|
|
601
612
|
answer = send_inference_request(data, "tools")
|
@@ -631,6 +642,7 @@ def florencev2_object_detection(image: np.ndarray) -> List[Dict[str, Any]]:
|
|
631
642
|
data = {
|
632
643
|
"image": image_b64,
|
633
644
|
"tool": "object_detection",
|
645
|
+
"function_name": "florencev2_object_detection",
|
634
646
|
}
|
635
647
|
|
636
648
|
answer = send_inference_request(data, "tools")
|
@@ -687,6 +699,7 @@ def detr_segmentation(image: np.ndarray) -> List[Dict[str, Any]]:
|
|
687
699
|
data = {
|
688
700
|
"image": image_b64,
|
689
701
|
"tool": "panoptic_segmentation",
|
702
|
+
"function_name": "detr_segmentation",
|
690
703
|
}
|
691
704
|
|
692
705
|
answer = send_inference_request(data, "tools")
|
@@ -729,6 +742,7 @@ def depth_anything_v2(image: np.ndarray) -> np.ndarray:
|
|
729
742
|
data = {
|
730
743
|
"image": image_b64,
|
731
744
|
"tool": "generate_depth",
|
745
|
+
"function_name": "depth_anything_v2",
|
732
746
|
}
|
733
747
|
|
734
748
|
answer = send_inference_request(data, "tools")
|
@@ -760,6 +774,7 @@ def generate_soft_edge_image(image: np.ndarray) -> np.ndarray:
|
|
760
774
|
data = {
|
761
775
|
"image": image_b64,
|
762
776
|
"tool": "generate_hed",
|
777
|
+
"function_name": "generate_soft_edge_image",
|
763
778
|
}
|
764
779
|
|
765
780
|
answer = send_inference_request(data, "tools")
|
@@ -792,6 +807,7 @@ def dpt_hybrid_midas(image: np.ndarray) -> np.ndarray:
|
|
792
807
|
data = {
|
793
808
|
"image": image_b64,
|
794
809
|
"tool": "generate_normal",
|
810
|
+
"function_name": "dpt_hybrid_midas",
|
795
811
|
}
|
796
812
|
|
797
813
|
answer = send_inference_request(data, "tools")
|
@@ -823,6 +839,7 @@ def generate_pose_image(image: np.ndarray) -> np.ndarray:
|
|
823
839
|
data = {
|
824
840
|
"image": image_b64,
|
825
841
|
"tool": "generate_pose",
|
842
|
+
"function_name": "generate_pose_image",
|
826
843
|
}
|
827
844
|
|
828
845
|
answer = send_inference_request(data, "tools")
|
@@ -863,6 +880,7 @@ def template_match(
|
|
863
880
|
"image": image_b64,
|
864
881
|
"template": template_image_b64,
|
865
882
|
"tool": "template_match",
|
883
|
+
"function_name": "template_match",
|
866
884
|
}
|
867
885
|
|
868
886
|
answer = send_inference_request(data, "tools")
|
@@ -1044,15 +1062,21 @@ def save_video(
|
|
1044
1062
|
if fps <= 0:
|
1045
1063
|
_LOGGER.warning(f"Invalid fps value: {fps}. Setting fps to 4 (default value).")
|
1046
1064
|
fps = 4
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1065
|
+
|
1066
|
+
if not output_video_path:
|
1067
|
+
output_video_path = tempfile.NamedTemporaryFile(
|
1068
|
+
suffix=".mp4", delete=False
|
1069
|
+
).name
|
1070
|
+
|
1071
|
+
height, width, layers = frames[0].shape if frames else (0, 0, 0)
|
1072
|
+
fourcc = cv2.VideoWriter_fourcc(*"mp4v") # type: ignore
|
1073
|
+
video = cv2.VideoWriter(output_video_path, fourcc, fps, (width, height))
|
1074
|
+
for frame in frames:
|
1075
|
+
video.write(cv2.cvtColor(frame, cv2.COLOR_RGB2BGR))
|
1076
|
+
video.release()
|
1077
|
+
|
1078
|
+
_save_video_to_result(output_video_path)
|
1079
|
+
return output_video_path
|
1056
1080
|
|
1057
1081
|
|
1058
1082
|
def _save_video_to_result(video_uri: str) -> None:
|
@@ -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):
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{vision_agent-0.2.94 → vision_agent-0.2.96}/vision_agent/agent/vision_agent_coder_prompts.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|