Skip to content

Commit

Permalink
few more changes in prompt to prevent functuion calling hallucination…
Browse files Browse the repository at this point in the history
… and updating new tests
  • Loading branch information
Shriyansh Agnihotri committed Jan 30, 2025
1 parent f3fd97c commit 3340470
Show file tree
Hide file tree
Showing 14 changed files with 322 additions and 375 deletions.
1 change: 1 addition & 0 deletions .github/workflows/main-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ jobs:
env:
LLM_MODEL_NAME: ${{ secrets.LLM_MODEL_NAME }}
LLM_MODEL_API_KEY: ${{ secrets.LLM_MODEL_API_KEY }}
GEO_API_KEY: ${{ secrets.GEO_API_KEY }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/main-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
env:
LLM_MODEL_NAME: ${{ secrets.LLM_MODEL_NAME }}
LLM_MODEL_API_KEY: ${{ secrets.LLM_MODEL_API_KEY }}
GEO_API_KEY: ${{ secrets.GEO_API_KEY }}
ENABLE_TELEMETRY: 0
AUTO_MODE: 1
steps:
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/non-main-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ on:
LLM_MODEL_API_KEY:
description: "LLM Model API Key (required)"
required: true
GEO_API_KEY:
description: "GEO_API_KEY for geo test (optional)"
required: false

env:
POETRY_VERSION: "1.8.3"
Expand All @@ -26,6 +29,7 @@ jobs:
env:
LLM_MODEL_NAME: ${{ github.event.inputs.LLM_MODEL_NAME }}
LLM_MODEL_API_KEY: ${{ github.event.inputs.LLM_MODEL_API_KEY }}
GEO_API_KEY: ${{ github.event.inputs.GEO_API_KEY }}
ENABLE_TELEMETRY: 0
AUTO_MODE: 1
steps:
Expand Down
621 changes: 280 additions & 341 deletions poetry.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ playwright-recaptcha = "^0.5.1"
junit2html = "^31.0.2"
aiohttp = "^3.11.7"
inflection = "^0.5.1"
autogen = {extras = ["ollama", "long-context", "graph", "anthropic", "groq", "gemini", "lmm", "mistral", "bedrock", "gemini"], version = "^0.7.2"}
autogen = {extras = ["ollama", "long-context", "graph", "anthropic", "groq", "gemini", "lmm", "mistral", "bedrock", "gemini"], version = "^0.7.3"}

[tool.poetry.group.dev.dependencies]
pytest = "^8.3.3"
Expand Down
3 changes: 3 additions & 0 deletions tests/test_feature_execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ def test_feature_execution(feature_folder: str) -> None:
load_env_in_dict["MODE"] = "debug"
load_env_in_dict["ENABLE_TELEMETRY"] = "0"
load_env_in_dict["AUTO_MODE"] = "1"
load_env_in_dict["TOKEN_VERBOSE"] = "true"
load_env_in_dict["GEO_PROVIDER"] = "maps_co"
load_env_in_dict["LOAD_EXTRA_TOOLS"] = "true"
load_env_in_dict["LANG"] = "en_US.UTF-8"

# Execute Hercules with the updated .env file
Expand Down
4 changes: 2 additions & 2 deletions tests/test_features/signupDelete/signupDelete.feature
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ Feature: User Signup and Account Deletion
And selects the checkbox "Sign up for our newsletter!"
And selects the checkbox "Receive special offers from our partners!"
And the user has filled in the account information
And the user fills in additional details, Use the first record from the test data to fill all possible fields on the UI.
And the user fills in additional details, Use the first record from the test data to fill all possible fields on the UI. if data dosen't match with UI find a substitute.
And clicks the "Create Account" button
And the "ACCOUNT CREATED!" message should be visible
And the user has created an account
And the user clicks the "Continue" button, the user is first record from test data.
Then the "Logged in as [Email]" message should be visible
Then the "Logged in as [Email]" or "Logged in as [Name]" message should be visible

Scenario: Delete the account
Given the user is logged in as a new user, via record 1 from test data, use email instead of username
Expand Down
3 changes: 2 additions & 1 deletion testzeus_hercules/core/agents/browser_nav_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ class BrowserNavAgent(BaseNavAgent):
9. Match input field requirements
10. Request clarification when needed
11. "md" attribute is a number identifier.
12. FUNCTION/TOOL CALLING PARAMETERS SHOULD BE FOLLOWED STRICTLY.
12. FUNCTION/TOOL CALLING PARAMETERS SHOULD BE FOLLOWED STRICTLY, IT SHOULD NOT BE NO PARAMETER PASS DURING FUNCTION CALL.
13. IF FUNCTION CALL FAILS FOR PYDANTIC VALIDATION, SOLVE IT AND RETRIGGER.
## Response Format
Success with Data:
Expand Down
6 changes: 2 additions & 4 deletions testzeus_hercules/core/extra_tools/drag_and_drop_tool.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import asyncio
from dataclasses import dataclass
from typing import Annotated

from testzeus_hercules.config import get_global_conf
from testzeus_hercules.core.playwright_manager import PlaywrightManager
from testzeus_hercules.core.tools.click_using_selector import SelectorEntry
from testzeus_hercules.core.tools.tool_registry import tool
from testzeus_hercules.telemetry import EventData, EventType, add_event
from testzeus_hercules.utils.logger import logger


@tool(agent_names=["browser_nav_agent"], description="Performs drag and drop operation between source (using md) and target (using any valid selector).", name="drag_and_drop")
async def drag_and_drop(
source_selector: Annotated[SelectorEntry, "Source element selector using md attribute, eg: [md='114']"],
source_selector: Annotated[str, "Source element selector using md attribute, eg: [md='114']"],
target_selector: Annotated[str, "Target element selector using any valid Playwright selector (CSS, XPath, etc.)"],
wait_before_execution: Annotated[float, "Wait time before drag and drop"] = 0.0,
) -> Annotated[str, "Drag and drop operation result"]:
Expand All @@ -27,7 +25,7 @@ async def drag_and_drop(
Returns:
- Success message if the operation was successful, error message otherwise
"""
query_selector = source_selector.query_selector
query_selector = source_selector
if "md=" not in query_selector:
query_selector = f"[md='{query_selector}']"

Expand Down
8 changes: 4 additions & 4 deletions testzeus_hercules/core/tools/dropdown_using_selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
async def select_option(
entry: Annotated[
dict,
"Object containing 'query_selector' (selector query using md attribute e.g. [md='114'] md is ID) and 'value' (the value or text of the option to select).",
"dict containing'query_selector' (selector query using md attribute e.g. [md='114'] md is ID) and 'value' (the value or text of the option to select).",
]
) -> Annotated[str, "Explanation of the outcome of dropdown/spinner selection."]:
"""
Expand All @@ -30,7 +30,7 @@ async def select_option(
It uses the Playwright library to interact with the browser and perform the selection operation.
Args:
entry (SelectOptionEntry): An object containing 'query_selector' (selector query using md attribute)
entry (SelectOptionEntry): An dict containing'query_selector' (selector query using md attribute)
and 'value' (the value or text of the option to select).
Returns:
Expand Down Expand Up @@ -227,8 +227,8 @@ async def do_select_option(page: Page, selector: str, option_value: str) -> dict
)
async def bulk_select_option(
entries: Annotated[
List[dict],
"List of objects containing 'query_selector' and 'value' key-value pairs, Object containing 'query_selector' (selector query using md attribute e.g. [md='114'] md is ID) and 'value' (the value or text of the option to select).",
List,
"List of dictionaries containing 'query_selector' and 'value' key-value pairs, dict containing 'query_selector' (selector query using md attribute e.g. [md='114'] md is ID) and 'value' (the value or text of the option to select).",
]
) -> Annotated[
List[dict],
Expand Down
8 changes: 4 additions & 4 deletions testzeus_hercules/core/tools/enter_date_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
async def set_date_time_value(
entry: Annotated[
dict,
"An object containing 'query_selector' (selector query using md attribute e.g. [md='114'] md is ID) and 'value' (the value to set in the input element).",
"An dict containing'query_selector' (selector query using md attribute e.g. [md='114'] md is ID) and 'value' (the value to set in the input element).",
]
) -> Annotated[str, "Operation result"]:
"""
Expand All @@ -36,7 +36,7 @@ async def set_date_time_value(
identified by the given selector. It uses the Playwright library to interact with the browser.
Args:
entry (SetInputValueEntry): An object containing 'query_selector' (selector query using md attribute)
entry (SetInputValueEntry): An dict containing'query_selector' (selector query using md attribute)
and 'value' (the value to set in the input element).
Returns:
Expand Down Expand Up @@ -139,8 +139,8 @@ async def do_set_date_time_value(page: Page, selector: str, input_value: str) ->
)
async def bulk_set_date_time_value(
entries: Annotated[
List[dict],
"List of objects containing 'query_selector' and 'value' key-value pairs, Object containing 'query_selector' (selector query using md attribute e.g. [md='114'] md is ID) and 'value' (the value or text of the option to select).",
List,
"List of dictionaries containing 'query_selector' and 'value' key-value pairs, dict containing 'query_selector' (selector query using md attribute e.g. [md='114'] md is ID) and 'value' (the value or text of the option to select).",
] # noqa: UP006
) -> Annotated[
List[dict],
Expand Down
14 changes: 7 additions & 7 deletions testzeus_hercules/core/tools/enter_text_using_selector.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import asyncio
import inspect
import traceback
from typing import Annotated, List
from typing import Annotated, Dict, List

from playwright.async_api import Page
from testzeus_hercules.config import get_global_conf # Add this import
Expand Down Expand Up @@ -80,7 +80,7 @@ async def custom_fill_element(page: Page, selector: str, text_to_enter: str) ->
async def entertext(
entry: Annotated[
dict,
"An object containing 'query_selector' (selector query using md attribute e.g. [md='114'] md is ID) and 'text' (text to enter on the element).",
"An dict containing'query_selector' (selector query using md attribute e.g. [md='114'] md is ID) and 'text' (text to enter on the element).",
]
) -> Annotated[str, "Text entry result"]:
"""
Expand All @@ -91,7 +91,7 @@ async def entertext(
The function supports both direct setting of the 'value' property and simulating keyboard typing.
Args:
entry (EnterTextEntry): An object containing 'query_selector' (selector query using md attribute)
entry (EnterTextEntry): An dict containing'query_selector' (selector query using md attribute)
and 'text' (text to enter on the element).
Returns:
Expand Down Expand Up @@ -234,12 +234,12 @@ async def do_entertext(page: Page, selector: str, text_to_enter: str, use_keyboa
@tool(
agent_names=["browser_nav_agent"],
name="bulk_enter_text",
description="Enters text into multiple DOM elements using a bulk operation. An object containing 'query_selector' (selector query using md attribute e.g. [md='114'] md is ID) and 'text' (text to enter on the element). ALL TOOL ARGUMENTS ARE MANDATORY",
description="Enters text into multiple DOM elements using a bulk operation. An dict containing'query_selector' (selector query using md attribute e.g. [md='114'] md is ID) and 'text' (text to enter on the element). ALL TOOL ARGUMENTS ARE MANDATORY",
)
async def bulk_enter_text(
entries: Annotated[
List[dict],
"List of objects containing 'query_selector' and 'text' key-value pairs, Object containing 'query_selector' (selector query using md attribute e.g. [md='114'] md is ID) and 'value' (the value or text of the option to select). MANDATORY FIELD",
List,
"List of dictionaries containing 'query_selector' and 'text' key-value pairs, dict containing 'query_selector' (selector query using md attribute e.g. [md='114'] md is ID) and 'value' (the value or text of the option to select). MANDATORY FIELD",
]
) -> Annotated[
List[str],
Expand All @@ -253,7 +253,7 @@ async def bulk_enter_text(
The function internally calls the 'entertext' function to perform the text entry operation for each entry.
Args:
entries: List of objects containing 'query_selector' and 'text'.
entries: List of dictionaries containing 'query_selector' and 'text'.
Returns:
List of results from the entertext operation for each entry.
Expand Down
12 changes: 6 additions & 6 deletions testzeus_hercules/core/tools/set_slider_value.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ async def custom_set_slider_value(page: Page, selector: str, value_to_set: float
async def setslider(
entry: Annotated[
dict,
"An object containing 'query_selector' (selector query using md attribute e.g. [md='114'] md is ID) and 'value' (numeric value to set on the slider).",
"An dict containing'query_selector' (selector query using md attribute e.g. [md='114'] md is ID) and 'value' (numeric value to set on the slider).",
]
) -> Annotated[str, "Explanation of the outcome of this operation."]:
"""
Expand All @@ -89,7 +89,7 @@ async def setslider(
It uses the Playwright library to interact with the browser and perform the operation.
Args:
entry (SetSliderEntry): An object containing 'query_selector' (selector query using md attribute)
entry (SetSliderEntry): An dict containing'query_selector' (selector query using md attribute)
and 'value' (numeric value to set on the slider).
Returns:
Expand Down Expand Up @@ -186,13 +186,13 @@ async def do_setslider(page: Page, selector: str, value_to_set: float) -> dict[s

@tool(
agent_names=["browser_nav_agent"],
description="Bulk set values in multiple range slider DOM fields. To be used when there are multiple sliders to be set on the same page. Sets values in the DOM elements matching the given md attribute value. The input will receive a list of objects containing the DOM query selector and the value to set. This will only set the values and not perform any additional actions. Returns each selector and the result for attempting to set the slider values. ALL TOOL ARGUMENTS ARE MANDATORY",
description="Bulk set values in multiple range slider DOM fields. To be used when there are multiple sliders to be set on the same page. Sets values in the DOM elements matching the given md attribute value. The input will receive a List of dictionaries containing the DOM query selector and the value to set. This will only set the values and not perform any additional actions. Returns each selector and the result for attempting to set the slider values. ALL TOOL ARGUMENTS ARE MANDATORY",
name="bulk_set_slider",
)
async def bulk_set_slider(
entries: Annotated[
List[dict],
"List of objects, each containing 'query_selector' and 'value'. Object containing 'query_selector' (selector query using md attribute e.g. [md='114'] md is ID) and 'value' (the value or text of the option to select). MANDATORY FIELD",
List,
"List of dictionaries, each containing 'query_selector' and 'value'. dict containing 'query_selector' (selector query using md attribute e.g. [md='114'] md is ID) and 'value' (the value or text of the option to select). MANDATORY FIELD",
] # noqa: UP006
) -> Annotated[
List[dict],
Expand All @@ -206,7 +206,7 @@ async def bulk_set_slider(
The function internally calls the 'setslider' function to perform the operation for each entry.
Args:
entries: List of objects, each containing 'query_selector' and 'value'.
entries: List of dictionaries, each containing 'query_selector' and 'value'.
Returns:
List of dictionaries, each containing 'query_selector' and the result of the operation.
Expand Down
10 changes: 5 additions & 5 deletions testzeus_hercules/core/tools/upload_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
async def upload_file(
entry: Annotated[
dict,
"object containing 'query_selector' (selector query using md attribute e.g. [md='114'] md is ID) and 'file_path' (the path to the file to upload).",
"dict containing 'query_selector' (selector query using md attribute e.g. [md='114'] md is ID) and 'file_path' (the path to the file to upload).",
]
) -> Annotated[str, "Explanation of the outcome of this operation."]:
"""
Expand All @@ -31,7 +31,7 @@ async def upload_file(
It uses the Playwright library to interact with the browser.
Args:
entry (dict[str, str]): An object containing 'query_selector' (selector query using md attribute)
entry (dict[str, str]): An dict containing'query_selector' (selector query using md attribute)
and 'file_path' (the path to the file to upload).
Returns:
Expand Down Expand Up @@ -137,8 +137,8 @@ async def do_upload_file(page: Page, selector: str, file_path: str) -> dict[str,
)
async def bulk_upload_file(
entries: Annotated[
List[dict],
"List of objects, each containing 'query_selector' and 'file_path'. Object containing 'query_selector' (selector query using md attribute e.g. [md='114'] md is ID) and 'value' (the value or text of the option to select). MANDATORY FIELD",
List,
"List of dictionaries, each containing 'query_selector' and 'file_path'. dict containing 'query_selector' (selector query using md attribute e.g. [md='114'] md is ID) and 'value' (the value or text of the option to select). MANDATORY FIELD",
] # noqa: UP006
) -> Annotated[
List[dict],
Expand All @@ -152,7 +152,7 @@ async def bulk_upload_file(
The function internally calls the 'upload_file' function to perform the operation for each entry.
Args:
entries: List of objects, each containing 'query_selector' and 'file_path'.
entries: List of dictionaries, each containing 'query_selector' and 'file_path'.
Returns:
List of dictionaries, each containing 'query_selector' and the result of the operation.
Expand Down

0 comments on commit 3340470

Please sign in to comment.