src/dfcx_scrapi/agent_extract/intents.py (82 lines of code) (raw):

"""Intent 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 json import os from dfcx_scrapi.agent_extract import common, types class Intents: """Intent processing methods and functions.""" def __init__(self): self.common = common.Common() @staticmethod def parse_lang_code(lang_code_path: str) -> str: """Extract the language_code from the given file path.""" first_parse = lang_code_path.split("/")[-1] lang_code = first_parse.split(".")[0] return lang_code @staticmethod def build_lang_code_paths(intent: types.Intent): """Builds dict of lang codes and file locations. The language_codes and paths for each file are stored in a dictionary inside of the Intent dataclass. This dict is access later to process each file and provide reporting based on each language code. """ root_dir = intent.dir_path + "/trainingPhrases" for lang_file in os.listdir(root_dir): lang_code = lang_file.split(".")[0] lang_code_path = f"{root_dir}/{lang_file}" intent.training_phrases[lang_code] = {"file_path": lang_code_path} @staticmethod def build_intent_path_list(agent_local_path: str): """Builds a list of dirs, each representing an Intent directory. Ex: /path/to/agent/intents/<intent_dir> This dir path can be used to find the next level of information in the directory by appending the appropriate next dir structures like: - <intent_name>.json, for the Intent object metadata - /trainingPhrases, for the Training Phrases dir """ root_dir = agent_local_path + "/intents" intent_paths = [] for intent_dir in os.listdir(root_dir): intent_dir_path = f"{root_dir}/{intent_dir}" intent_paths.append(intent_dir_path) return intent_paths def process_intent_metadata( self, intent: types.Intent): """Process the metadata file for a single Intent.""" intent.metadata_file = f"{intent.dir_path}/{intent.display_name}.json" try: with open(intent.metadata_file, "r", encoding="UTF-8") as meta_file: intent.data = json.load(meta_file) intent.resource_id = intent.data.get("name", None) intent.labels = intent.data.get("labels", None) intent.description = intent.data.get("description", None) intent.parameters = intent.data.get("parameters", None) meta_file.close() except FileNotFoundError: pass def process_language_codes( self, intent: types.Intent, stats: types.AgentData): """Process all training phrase lang_code files.""" for lang_code in intent.training_phrases: tp_file = intent.training_phrases[lang_code]["file_path"] if not self.common.check_lang_code(lang_code, stats): continue with open(tp_file, "r", encoding="UTF-8") as tps: data = json.load(tps) data["name"] = f"{stats.agent_id}/intents/{intent.resource_id}" data["display_name"] = intent.display_name data["labels"] = intent.labels data["description"] = intent.description data["parameters"] = intent.parameters stats.intents.append(data) stats.total_training_phrases += len(data["trainingPhrases"]) tps.close() return stats def process_training_phrases( self, intent: types.Intent, stats: types.AgentData): """Process the Training Phrase dir for a single Intent.""" if "trainingPhrases" in os.listdir(intent.dir_path): self.build_lang_code_paths(intent) stats = self.process_language_codes(intent, stats) return stats def process_intent(self, intent: types.Intent, stats: types.AgentData): """Process a single Intent directory and associated files.""" intent.display_name = self.common.parse_filepath( intent.dir_path, "intent") intent.display_name = self.common.clean_display_name( intent.display_name) self.process_intent_metadata(intent) stats = self.process_training_phrases(intent, stats) stats.total_intents += 1 return stats def process_intents_directory( self, agent_local_path: str, stats: types.AgentData): """Processing the top level Intents Dir in the JSON Package structure. The following files/dirs exist under the `intents` dir: - <intent_display_name> Directory - trainingPhrases - <language-code>.json - <intent_display_name> Object In Dialogflow CX, the Training Phrases of each Intent are stored in individual .json files by language code under each Intent Display Name. In this method, we will process all Intent dirs, including the training phrase files and metadata objects for each Intent. """ # Create a list of all Intent paths to iter through intent_paths = self.build_intent_path_list(agent_local_path) stats.intents = [] for intent_path in intent_paths: intent = types.Intent() intent.dir_path = intent_path stats = self.process_intent(intent, stats) full_intent_id = f"{stats.agent_id}/intents/{intent.resource_id}" stats.intents_map[intent.display_name] = full_intent_id return stats