Skip to content

Commit af2c762

Browse files
adeprezmbrunel
andauthored
Add endpoints to compute and execute custom actions (#615)
* agent-studio api * feat: add knowledge * fix: allow None action in ActionWrapper * feat: add export step to knowledge * chore: format --------- Co-authored-by: Matthias BRUNEL <[email protected]>
1 parent 6e5c3f2 commit af2c762

File tree

6 files changed

+94
-6
lines changed

6 files changed

+94
-6
lines changed

lavague-integrations/drivers/lavague-drivers-selenium/lavague/drivers/selenium/base.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
NoPageException,
2626
)
2727

28+
from lavague.sdk.action.navigation import WebNavigationAction, NavigationCommand
29+
from lavague.sdk.action import ActionStatus
2830
from selenium.common.exceptions import (
2931
NoSuchElementException,
3032
TimeoutException,

lavague-sdk/lavague/sdk/action/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from lavague.sdk.action.base import (
22
Action,
3+
Instruction,
4+
EngineType,
35
ActionType,
46
ActionStatus,
57
ActionParser,

lavague-sdk/lavague/sdk/action/base.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ class ActionType(str, Enum):
1414
EXTRACTION = "web_extraction"
1515

1616

17+
class EngineType(str, Enum):
18+
NAVIGATION = "Navigation Engine"
19+
EXTRACTION = "Element Extraction Engine"
20+
CONTROLS = "Navigation Controls"
21+
COMPLETE = "COMPLETE"
22+
23+
1724
T = TypeVar("T")
1825

1926

@@ -55,6 +62,12 @@ def parse(self, action_dict: Dict) -> Action:
5562
return Action.parse(action_dict)
5663

5764

65+
class Instruction(BaseModel):
66+
chain_of_toughts: str
67+
engine: EngineType
68+
engine_instruction: str
69+
70+
5871
class UnhandledTypeException(Exception):
5972
pass
6073

lavague-sdk/lavague/sdk/base_driver/base.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ def execute(self, action: NavigationOutput) -> None:
6767
raise NotImplementedError(
6868
f"Action {action.navigation_command} not implemented"
6969
)
70+
self.wait_for_idle()
7071

7172
@abstractmethod
7273
def destroy(self) -> None:

lavague-sdk/lavague/sdk/client.py

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
from typing import Any, Optional, Tuple
33

44
import requests
5-
from lavague.sdk.action import DEFAULT_PARSER, ActionParser
5+
from lavague.sdk.action import DEFAULT_PARSER, ActionParser, Instruction
66
from lavague.sdk.trajectory import Trajectory
77
from lavague.sdk.trajectory.controller import TrajectoryController
8-
from lavague.sdk.trajectory.model import StepCompletion
8+
from lavague.sdk.trajectory.model import StepCompletion, StepKnowledge
99
from lavague.sdk.utilities.config import LAVAGUE_API_BASE_URL, get_config, is_flag_true
1010
from PIL import Image, ImageFile
1111
from pydantic import BaseModel
@@ -86,7 +86,30 @@ def next_step(self, run_id: str) -> StepCompletion:
8686
f"/runs/{run_id}/step",
8787
"POST",
8888
)
89-
return StepCompletion.model_validate_json(content)
89+
return StepCompletion.from_data(content)
90+
91+
def generate_instruction(self, run_id: str) -> Instruction:
92+
content = self.request_api(
93+
f"/runs/{run_id}/step/instruction",
94+
"POST",
95+
)
96+
return Instruction.model_validate_json(content)
97+
98+
def generate_action(self, run_id: str, instruction: Instruction) -> StepCompletion:
99+
content = self.request_api(
100+
f"/runs/{run_id}/step/action",
101+
"POST",
102+
instruction.model_dump(),
103+
)
104+
return StepCompletion.from_data(content)
105+
106+
def execute_action(self, run_id: str, action: StepKnowledge) -> StepCompletion:
107+
content = self.request_api(
108+
f"/runs/{run_id}/step/execution",
109+
"POST",
110+
action.model_dump(),
111+
)
112+
return StepCompletion.from_data(content)
90113

91114
def stop(self, run_id: str) -> None:
92115
self.request_api(

lavague-sdk/lavague/sdk/trajectory/model.py

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from enum import Enum
22
from typing import Any, Dict, List, Tuple, Optional
33
from pydantic import BaseModel, SerializeAsAny
4-
from lavague.sdk.action import Action
4+
from lavague.sdk.action import Action, ActionParser, Instruction
55
from lavague.sdk.action.base import DEFAULT_PARSER
66
from pydantic import model_validator
7+
from pydantic_core import from_json
78

89

910
class RunStatus(str, Enum):
@@ -60,7 +61,53 @@ def write_to_file(self, file_path: str):
6061
file.write(json_model)
6162

6263

63-
class StepCompletion(BaseModel):
64-
run_status: RunStatus
64+
class ActionWrapper(BaseModel):
6565
action: Optional[Action]
66+
67+
@classmethod
68+
def from_data(
69+
cls,
70+
data: str | bytes | bytearray,
71+
parser: ActionParser = DEFAULT_PARSER,
72+
):
73+
obj = from_json(data)
74+
return cls.from_dict(obj, parser)
75+
76+
@classmethod
77+
def from_dict(
78+
cls,
79+
data: Dict,
80+
parser: ActionParser = DEFAULT_PARSER,
81+
):
82+
action = data.get("action")
83+
action = parser.parse(action) if action else None
84+
return cls.model_validate({**data, "action": action})
85+
86+
@model_validator(mode="before")
87+
@classmethod
88+
def deserialize_action(cls, values: Dict[str, Any]) -> Dict[str, Any]:
89+
if "action" in values:
90+
action_data = values["action"]
91+
if (
92+
action_data
93+
and not isinstance(action_data, Action)
94+
and "action_type" in action_data
95+
):
96+
action_class = DEFAULT_PARSER.engine_action_builders.get(
97+
action_data["action_type"], Action
98+
)
99+
deserialized_action = action_class.parse(action_data)
100+
values["action"] = deserialized_action
101+
return values
102+
103+
104+
class StepKnowledge(ActionWrapper):
105+
instruction: Instruction
106+
107+
108+
class StepCompletion(ActionWrapper):
109+
run_status: RunStatus
66110
run_mode: RunMode
111+
112+
def to_knowledge(self, instruction: Instruction) -> StepKnowledge:
113+
return StepKnowledge(instruction=instruction, action=self.action)

0 commit comments

Comments
 (0)