From 67d30fbc6af781ba41ab656352ae6700a1db8bc0 Mon Sep 17 00:00:00 2001 From: kowshik Date: Thu, 5 Sep 2024 02:59:01 +0000 Subject: [PATCH] added sops generation for personal assessment --- data/raw/document.pdf | Bin 70797 -> 70797 bytes src/api/routes/sops.py | 143 +++++++++++++++++++------ src/models/response_schemas.py | 28 +++++ src/prompts/sops.py | 46 ++++++++ src/services/sop_generator.py | 186 ++++++++++++++++++++++++++++----- test.py | 36 +++++-- 6 files changed, 368 insertions(+), 71 deletions(-) create mode 100644 src/models/response_schemas.py create mode 100644 src/prompts/sops.py diff --git a/data/raw/document.pdf b/data/raw/document.pdf index 7527313126d76dbe615e9a3f5814830893686e59..3b0233957549ee42dac1573c95476bb6f2ece22f 100644 GIT binary patch delta 99 zcmeBO$XA2isb8|CiBSUjH11ED!a}yU= ZQxgM23u8wMX9Ht98$v3k9}s3d3jpe77{mYo delta 99 zcmeBO$ RoleSOPs: + def generate_sops_by_role_and_area(self, role: str, areas: str) -> RoleSops: response = self.client.beta.chat.completions.parse( model=self.model, messages=[ { "role": "system", - "content": f'''Your job is to generate Standard Operating Procedures (SOPs) for the role of "{role}" with a focus on the area "{area}" based on the following instructions: + "content": f'''Your job is to generate Standard Operating Procedures (SOPs) for the role of "{role}" with a focus on the areas "{areas}" based on the following instructions: Instructions: - Categorization: Organize the SOPs under three categories: "must," "shall," and "will." - Direct Instructions: The SOPs should directly address responsibilities, objectives, and challenges related to the area of "{area}" for the role of "{role}". + Categorization: Organize the SOPs under the selected categories: a checkboxex of the three categories "must" , "shall" and "will" + Direct Instructions: The SOPs should directly address responsibilities, objectives, and challenges related to the area of "{areas}" for the role of "{role}". Contextual Inference: If SOPs for the area are not explicitly stated, infer them from the role and area context provided. Empty Lists: If no SOPs are generated, return an empty list for each category. Format: The SOPs should be direct and concise. @@ -197,7 +178,7 @@ class SopGenerator: return json.loads(response.choices[0].message.content) - def generate_executive_sops_from_questionnaire(self, data: dict) -> RoleSOPs: + def generate_executive_sops_from_questionnaire(self, data: dict) -> RoleSops: """ Generate SOPs based on the answers from an executive questionnaire. @@ -242,7 +223,7 @@ class SopGenerator: ''', } ], - response_format=RoleSOPs, + response_format=RoleSops, max_tokens=1024, temperature=0.1 ) @@ -325,8 +306,6 @@ class SopGenerator: # Parse the response from the LLM extracted_text = json.loads(response.choices[0].message.content) - - print(F"extracted text:{extracted_text}") # Assuming the response contains fields for 'vision' and 'mission' (or 'goals') vision_section = extracted_text["vision"] mission_section = extracted_text["mission"] @@ -334,3 +313,152 @@ class SopGenerator: return vision_section, mission_section + + +class SopGeneratorDocument: + def __init__(self): + self.api_key = os.getenv("OPENAI_API_KEY") + self.client = OpenAI(api_key=self.api_key) + self.model = "gpt-4o-2024-08-06" + + def _extract_text_from_docs(self, docs): + """Extract text content from document objects.""" + return [doc.page_content for doc in docs] + # Existing methods... + + def extract_sops_from_doc(self, docs) -> VisionMissionResponse: + """ + Extracts Vision, Mission, and SOPs categorized into 'must,' 'shall,' and 'will' from the document. + + :param docs: The document(s) from which to extract information. + :return: VisionMissionResponse containing the vision, mission, and role-specific SOPs. + """ + + try: + docs_text = self._extract_text_from_docs(docs) + prompt = get_sop_extraction_from_doc() + response = self.client.beta.chat.completions.parse( + model=self.model, + messages=[ + { + "role": "system", + "content": f'''{prompt}''' + }, + { + "role": "user", + "content": [{"type": "text", "text": text} for text in docs_text], + } + ], + response_format=SOPsResponse, + max_tokens=4096, + temperature=0.1 + ) + + # Parse the response from the LLM + extracted_text = json.loads(response.choices[0].message.content) + + return extracted_text + + except: + return False + + + +class SopPersonalAssessment: + def __init__(self): + self.api_key = os.getenv("OPENAI_API_KEY") + self.client = OpenAI(api_key=self.api_key) + self.model = "gpt-4o-mini" + + # Existing methods... + + def extract_sops_from_questionnaire(self, questionnaire_data: dict) -> VisionMissionResponse: + """ + Extracts SOPs categorized into 'must,' 'shall,' and 'will' based on free-text questionnaire information. + + :param questionnaire_data: A dictionary containing plain text responses to the questionnaire. + :return: SOPsResponse containing the vision, mission, and role-specific SOPs + """ + + try: + # Extract the plain text answers from the questionnaire + vision = questionnaire_data.get("vision", "No vision provided") + roles = questionnaire_data.get("roles", "No roles provided") # This will be a plain text string + responsibilities = questionnaire_data.get("responsibilities", "No responsibilities provided") # Plain text string + project_details = questionnaire_data.get("project_details", "No additional project details provided") + + # Get the appropriate prompt for the questionnaire scenario + prompt = get_sop_personalassessment_from_questionnaire() + + # Combine the plain text data into a string to pass to the LLM + user_content = f''' + Vision: {vision} + Roles: {roles} + Responsibilities: {responsibilities} + Project Details: {project_details} + ''' + + # Send the combined plain text content to the LLM + response = self.client.beta.chat.completions.parse( + model=self.model, + messages=[ + { + "role": "system", + "content": f'''{prompt}''' + }, + { + "role": "user", + "content": user_content, + } + ], + response_format=SOPsResponse, + max_tokens=2048, + temperature=0.1 + ) + + # Parse the response from the LLM + extracted_text = json.loads(response.choices[0].message.content) + + return extracted_text + + except Exception as e: + print(f"Error occurred: {str(e)}") + return False + + + def generate_sops_by_role_and_area(self, roles: List[dict]) -> RoleSops: + + try: + sops_by_role = [] + for role_info in roles: + role = role_info['role'] + sop_types = role_info['sop_types'] # List of SOP types: ["will", "shall", "must"] + areas = role_info['areas'] # List of areas: ["communication", "development", etc.] + + + prompt = get_sop_personalassessment_from_area_role(role,areas,sop_types) + response = self.client.beta.chat.completions.parse( + model=self.model, + messages=[ + { + "role": "system", + "content": f'''{prompt} + ''', + } + ], + response_format=RoleSops, + max_tokens=1024, + temperature=0.1 + ) + extracted_text = json.loads(response.choices[0].message.content) + # You can customize this to generate SOPs based on the role, SOP types, and areas + sops_by_role.append(extracted_text) + + + + return sops_by_role + + except: + return False + + diff --git a/test.py b/test.py index 62ab249..8301929 100644 --- a/test.py +++ b/test.py @@ -1,21 +1,37 @@ from src.services.sop_generator import SopGenerator from src.utils.document_loader import load_document +from src.services.sop_generator import SopPersonalAssessment -file_path = "/root/ds_erp_ai/data/raw/test_sop.pdf" +file_path = "/root/ds_erp_ai/data/raw/document.doc" docs = load_document(file_path) -sop = SopGenerator() +from src.services.sop_generator import SopGeneratorDocument +sop = SopPersonalAssessment() if __name__ == "__main__": # Assuming 'sop' is an instance of SopGenerator and 'docs' is the loaded document content. - # Step 1: Get the roles from the document - roles = sop.get_roles(docs)["roles"] - print(f"Roles {roles}") - - sop_status = sop.check_role_sop(roles=roles, docs=docs) - print(sop_status) - roles = ["cloud engineer"] - sops = sop.generate_sops(roles=roles,docs=docs) + + roles = [ + { + "role": "Content Marketing Specialist", + "sop_types": ["will", "shall"], + "areas": ["communication", "development"] + }, + { + "role": "Digital Marketing Specialist", + "sop_types": ["must"], + "areas": ["finance", "project management"] + }, + { + "role": "Information Technology Officer", + "sop_types": ["shall", "must"], + "areas": ["development", "communication", "operations"] + } + ] + + + + sops = sop.generate_sops_by_role_and_area(roles) print(f"sops:{sops}")