Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/agent checking #104

Merged
merged 86 commits into from
Aug 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
5ace003
Create agent_checker_util.py
SeanScripts Dec 9, 2022
91688f4
Update notes
SeanScripts Dec 9, 2022
332517d
Add utility ID conversion functions
SeanScripts Dec 9, 2022
824007d
Add function get_test_case_results
SeanScripts Dec 9, 2022
444ad71
Add maps
SeanScripts Dec 9, 2022
df4b671
Simplify conversions
SeanScripts Dec 9, 2022
c6b3271
Add docstrings
SeanScripts Dec 9, 2022
da3a4f1
Include imports
SeanScripts Dec 9, 2022
8a4d730
Fix references and missing imports
SeanScripts Dec 9, 2022
d70e7c4
Create functions for finding reachable pages
SeanScripts Dec 9, 2022
9c76cdf
Fix tabbing and imports
SeanScripts Dec 9, 2022
5ac69a8
Implement get_page
SeanScripts Dec 9, 2022
a8efb12
Get flow and page data
SeanScripts Dec 9, 2022
8414538
Fix page data
SeanScripts Dec 9, 2022
e158d61
Fix find_unreachable_pages function and dependencies
SeanScripts Dec 9, 2022
0bda9bb
Clean up agent_checker_util.py
SeanScripts Dec 9, 2022
5ea1851
Lint fixes
SeanScripts Dec 9, 2022
bdfa66f
Optimize agent data loading
SeanScripts Dec 14, 2022
feb6b8b
Clean up excess indents in find_reachable_pages_rec with a couple of …
SeanScripts Dec 16, 2022
b02781f
Minor linting
SeanScripts Dec 16, 2022
6c925a5
More minor linting
SeanScripts Dec 16, 2022
8416c0a
Use early return to remove one indentation layer in find_reachable_pa…
SeanScripts Dec 16, 2022
6c4fecd
Clean up repeated code with new function get_new_presets
SeanScripts Dec 16, 2022
3af4212
Lint fixes
SeanScripts Dec 16, 2022
45a5dff
Debug data mapping
SeanScripts Dec 16, 2022
6217286
Correct negation logic error
SeanScripts Dec 16, 2022
6816535
Fix typo in function name
SeanScripts Dec 16, 2022
e997b51
Add functions find_all_reachable_pages and find_all_unreachable_pages
SeanScripts Dec 16, 2022
743020c
Create function find_reachable_intents
SeanScripts Dec 28, 2022
b6644dc
Create functions find_all_(un)reachable_intents
SeanScripts Dec 28, 2022
6646ac4
Fix function name typo
SeanScripts Dec 28, 2022
268d267
Prevent checking transitions to other flows as if they are pages
SeanScripts Dec 28, 2022
cd46afc
Debug find_all_reachable_intents
SeanScripts Dec 28, 2022
2b97bf0
Move get_test_case_results_df to TestCases
SeanScripts Dec 29, 2022
40152c9
Switch to parameter dictionary
SeanScripts Jan 4, 2023
c8c4437
Fix some bugs with parameter dict and simplify error checking
SeanScripts Jan 4, 2023
7a80ce5
Fix logic error in parameter dict
SeanScripts Jan 5, 2023
2d99b5e
Create additional recursion helper function
SeanScripts Jan 5, 2023
2625b33
Create helper function for meta-pages
SeanScripts Jan 5, 2023
ec4de15
Lint fixes
SeanScripts Jan 5, 2023
9f554e0
Clean up style and make compatible with Python 3.8
SeanScripts Jan 9, 2023
f4a4109
Continue cleaning up style
SeanScripts Jan 9, 2023
f6ed7f8
Lint fixes
SeanScripts Jan 9, 2023
7db4f35
Clean up and add delays for API limits
SeanScripts Jan 30, 2023
3bc51a7
Use flow display name instead of optional choice to use flow ID
SeanScripts Jan 30, 2023
51eb98b
Fix bug introduced before when trying to refactor is_initial
SeanScripts Jan 31, 2023
d61af59
Optimize API calls
SeanScripts Feb 9, 2023
27cdf8d
Clean up conditions and fix map init bug
SeanScripts Feb 9, 2023
0e08b80
Lint fixes
SeanScripts Feb 9, 2023
657f7ee
Clean up test cases and create process_test_cases function
SeanScripts Feb 9, 2023
ba5c20e
Change exception types
SeanScripts Feb 9, 2023
b11dc4a
Simplify convert_page for v1.6 and remove unused functions in agent_c…
SeanScripts Feb 9, 2023
eee3d99
Add agent checker util unit tests
SeanScripts Jul 10, 2023
96916f1
Return page list instead of set; update test fixtures
SeanScripts Jul 10, 2023
51a95a4
Lint fixes
SeanScripts Jul 10, 2023
6470738
Finish rebase and lint fixes
SeanScripts Jul 10, 2023
601101f
fix: refactor to match import standards
kmaphoenix Aug 19, 2023
f510f0b
chore: resort code
kmaphoenix Aug 19, 2023
f98ddd3
fix: refactor process_test_case
kmaphoenix Aug 19, 2023
1500f71
fix: refactor get_test_case_results_df
kmaphoenix Aug 19, 2023
9a36968
fix: Lint fixes
kmaphoenix Aug 19, 2023
a6a27d2
fix: make agent_id required init arg
kmaphoenix Aug 20, 2023
47e68d5
feat: Implement additional export_agent options
kmaphoenix Aug 20, 2023
83fcd48
feat: add get_flow_page_map method
kmaphoenix Aug 21, 2023
1fcf35c
chore: update gitignore
kmaphoenix Aug 21, 2023
f6bffdd
feat: adding agent_extract feature for offline processing
kmaphoenix Aug 21, 2023
dbbf9fe
feat: add test case parsing
kmaphoenix Aug 22, 2023
96f98e2
fix: linting
kmaphoenix Aug 22, 2023
3e4934c
feat: Implement graph structure
kmaphoenix Aug 22, 2023
5a66d8b
feat: refactor graph recursion into extract class for finding graph d…
kmaphoenix Aug 24, 2023
8d26316
fix: re sort AgentData class; add new fields and types
kmaphoenix Aug 24, 2023
cc75794
fix: lint fixes
kmaphoenix Aug 24, 2023
63e1356
fix: formatting
kmaphoenix Aug 24, 2023
c117219
feat: add processing for intents; cleanup old code
kmaphoenix Aug 25, 2023
81a7859
fix: add logging; handle lros; add lang_code support
kmaphoenix Aug 25, 2023
be7fd26
fix: added dir cleanup to avoid local file conflicts
kmaphoenix Aug 25, 2023
5f035d7
fix: fixed display_name parsing for Intents/Entity Types
kmaphoenix Aug 25, 2023
c739920
fix: add lang_code support; fix class type outputs
kmaphoenix Aug 25, 2023
66f7578
feat: implement recursion method for finding reachable pages in graph
kmaphoenix Aug 25, 2023
f676476
fix: lint fixes
kmaphoenix Aug 25, 2023
66361c7
chore: reverting tests due to testing refactor coming soon
kmaphoenix Aug 25, 2023
a750daf
fix: modify active_intents type for downstream processing
kmaphoenix Aug 25, 2023
85aa288
feat: refactor df code; implement get_unreachable_intents
kmaphoenix Aug 25, 2023
67cf893
fix: lint fixes
kmaphoenix Aug 25, 2023
da42187
chore: comment cleanup; unused code cleanup
kmaphoenix Aug 27, 2023
c4edde8
fix: linting
kmaphoenix Aug 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
.ipynb_checkpoints
*scratch.ipynb
*scratch.py
tmp/

# IPython
profile_default/
Expand Down
Empty file.
146 changes: 146 additions & 0 deletions src/dfcx_scrapi/agent_extract/agents.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
"""Agent processing methods and functions."""

# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import logging
import time
import os
import shutil
from typing import Dict

from dfcx_scrapi.core import agents
from dfcx_scrapi.core import operations
from dfcx_scrapi.core import scrapi_base
from dfcx_scrapi.agent_extract import graph
from dfcx_scrapi.agent_extract import flows
from dfcx_scrapi.agent_extract import intents
from dfcx_scrapi.agent_extract import entity_types
from dfcx_scrapi.agent_extract import test_cases
from dfcx_scrapi.agent_extract import webhooks
from dfcx_scrapi.agent_extract import gcs_utils
from dfcx_scrapi.agent_extract import types

# logging config
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)-8s %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)

class Agents(scrapi_base.ScrapiBase):
"""Agent Metadata methods and functions."""
def __init__(
self,
agent_id: str,
lang_code: str = "en",
creds_path: str = None,
creds_dict: Dict = None,
creds=None,
scope=False
):
super().__init__(
creds_path=creds_path,
creds_dict=creds_dict,
creds=creds,
scope=scope,
)
self.agent_id = agent_id
self.lang_code = lang_code
self._core_agents = agents.Agents(creds=creds)
self.gcs = gcs_utils.GcsUtils()
self.flows = flows.Flows()
self.intents = intents.Intents()
self.etypes = entity_types.EntityTypes()
self.webhooks = webhooks.Webhooks()
self.tcs = test_cases.TestCases()
self.ops = operations.Operations()

@staticmethod
def prep_local_dir(agent_local_path: str):
"""Prepare the local directory for agent zip file."""
if os.path.isdir(agent_local_path):
logging.info("Cleaning up old directory...")
shutil.rmtree(agent_local_path)
logging.info(f"Making temp directory: {agent_local_path}")
os.mkdir(agent_local_path)
else:
os.mkdir(agent_local_path)

def await_lro(self, lro: str):
"""Wait for long running operation to complete."""
try:
i = 0
while not self.ops.get_lro(lro).done:
time.sleep(1)
i += 1
if i == 20:
break

except UserWarning:
print("LRO Failed.")

return True

def export_agent(self, agent_id: str, gcs_bucket_uri: str,
environment_display_name: str = None):
"""Handle the agent export, LRO and logging."""
export_start = time.time()
logging.info("Exporting agent...")
lro = self._core_agents.export_agent(
agent_id=agent_id,gcs_bucket_uri=gcs_bucket_uri, data_format="JSON",
environment_display_name=environment_display_name)


self.await_lro(lro)
logging.info("Export Complete.")
logging.debug(f"EXPORT: {time.time() - export_start}")

def download_and_extract(self, agent_local_path: str, gcs_bucket_uri: str):
"""Handle download from GCS and extracting ZIP file."""
if not os.path.exists(agent_local_path):
os.makedirs(agent_local_path)

download_start = time.time()
logging.info("Downloading agent file from GCS Bucket...")
agent_file = self.gcs.download_gcs(
gcs_path=gcs_bucket_uri, local_path=agent_local_path)
logging.info("Download complete.")
logging.debug(f"DOWNLOAD: {time.time() - download_start}")

self.gcs.unzip(agent_file, agent_local_path)


def process_agent(self, agent_id: str, gcs_bucket_uri: str,
environment_display_name: str = None):
"""Process the specified Agent for offline data gathering."""
agent_local_path = "tmp/agent"
self.prep_local_dir(agent_local_path)
self.export_agent(agent_id, gcs_bucket_uri, environment_display_name)
self.download_and_extract(agent_local_path, gcs_bucket_uri)

logging.info("Processing Agent...")
data = types.AgentData()
data.graph = graph.Graph()
data.lang_code = self.lang_code
data.agent_id = agent_id
data = self.flows.process_flows_directory(agent_local_path, data)
data = self.intents.process_intents_directory(agent_local_path, data)
data = self.etypes.process_entity_types_directory(
agent_local_path, data)
data = self.webhooks.process_webhooks_directory(agent_local_path, data)
data = self.tcs.process_test_cases_directory(agent_local_path, data)
logging.info("Processing Complete.")

return data
80 changes: 80 additions & 0 deletions src/dfcx_scrapi/agent_extract/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"""Common methods and helper functions used throughout library."""

# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import logging
import re
from dfcx_scrapi.agent_extract import types

# logging config
logging.basicConfig(
level=logging.INFO,
format="%(message)s",
)

class Common:
"""Common methods and helper functions used throughout library."""

@staticmethod
def parse_filepath(in_path: str, resource_type: str) -> str:
"""Parse file path to provide quick reference for resource."""

regex_map = {
"flow": r".*\/flows\/([^\/]*)",
"page": r".*\/pages\/([^\/]*)\.",
"entity_type": r".*\/entityTypes\/([^\/]*)",
"intent": r".*\/intents\/([^\/]*)",
"route_group": r".*\/transitionRouteGroups\/([^\/]*)",
"webhook": r".*\/webhooks\/([^\/]*)\."
}
resource_name = re.match(regex_map[resource_type], in_path).groups()[0]

return resource_name

@staticmethod
def clean_display_name(display_name: str):
"""Replace cspecial haracters from map for the given display name."""
patterns = {
"%22": '"',
"%23": "#",
"%24": "$",
"%26": "&",
"%27": "'",
"%28": "(",
"%29": ")",
"%2b": "+",
"%2c": ",",
"%2f": "/",
"%3a": ":",
"%3c": "<",
"%3d": "=",
"%3e": ">",
"%3f": "?",
"%5b": "[",
"%5d": "]",
"%e2%80%9c": "“",
"%e2%80%9d": "”",
}

for key, value in patterns.items():
if key in display_name:
display_name = display_name.replace(key, value)

return display_name

@staticmethod
def check_lang_code(lang_code: str, stats: types.AgentData):
"""Check to see if file lang_code matches user input lang_code."""
return stats.lang_code == lang_code
Loading