2024-08-31 01:29:39 +00:00
|
|
|
import os
|
|
|
|
|
import json
|
|
|
|
|
from openai import OpenAI
|
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
from typing import List, Dict, Optional
|
2024-09-05 02:59:01 +00:00
|
|
|
from src.prompts.sops import *
|
2024-09-10 02:51:31 +01:00
|
|
|
from src.models.sop_response_schemas import *
|
2024-09-10 01:00:08 +01:00
|
|
|
from src.services.sop_document_parser import DocumentParser
|
2024-09-09 14:03:14 +01:00
|
|
|
from dotenv import load_dotenv
|
2025-01-31 15:59:51 +00:00
|
|
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
|
|
|
from typing import List, Dict
|
|
|
|
|
import json
|
|
|
|
|
from openai import OpenAI
|
|
|
|
|
import os
|
|
|
|
|
import time
|
|
|
|
|
from collections import deque
|
2024-09-09 14:03:14 +01:00
|
|
|
load_dotenv()
|
2024-09-06 01:48:32 +00:00
|
|
|
|
2024-09-05 02:59:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
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"
|
2025-01-31 15:59:51 +00:00
|
|
|
self.rpm_limit = 3 # Requests per minute limit
|
|
|
|
|
self.batch_size = 3 # Process 3 roles at a time
|
|
|
|
|
self.retry_delays = [4, 8, 16, 32]
|
2024-09-05 02:59:01 +00:00
|
|
|
|
|
|
|
|
# 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,
|
2024-09-25 21:40:08 +00:00
|
|
|
max_tokens=16000,
|
2024-09-05 02:59:01 +00:00
|
|
|
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
|
|
|
|
|
|
2025-01-31 15:59:51 +00:00
|
|
|
|
|
|
|
|
def generate_sops_by_role_and_area(self, roles,qna) -> RoleSops:
|
2024-09-05 02:59:01 +00:00
|
|
|
|
|
|
|
|
try:
|
2025-01-31 15:59:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
MODEL = "gpt-4o-mini"
|
|
|
|
|
prompt = get_sop_personalassessment_from_area_rolev2()
|
2024-09-05 02:59:01 +00:00
|
|
|
response = self.client.beta.chat.completions.parse(
|
2025-01-31 15:59:51 +00:00
|
|
|
model=MODEL,
|
2024-09-05 02:59:01 +00:00
|
|
|
messages=[
|
|
|
|
|
{
|
|
|
|
|
"role": "system",
|
|
|
|
|
"content": f'''{prompt}
|
|
|
|
|
''',
|
2025-01-31 15:59:51 +00:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"role": "user",
|
|
|
|
|
"content": f'''povided Roles Data {roles}
|
|
|
|
|
''',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"role": "user",
|
|
|
|
|
"content": f'''Extra question and answers for more context {qna}
|
|
|
|
|
''',
|
2024-09-05 02:59:01 +00:00
|
|
|
}
|
|
|
|
|
],
|
2025-01-31 15:59:51 +00:00
|
|
|
response_format=RoleSopssLists,
|
|
|
|
|
max_tokens=6000,
|
2024-09-05 02:59:01 +00:00
|
|
|
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
|
2025-01-31 15:59:51 +00:00
|
|
|
|
|
|
|
|
return extracted_text["sops"]
|
2024-09-05 02:59:01 +00:00
|
|
|
|
2025-01-31 15:59:51 +00:00
|
|
|
except Exception as e:
|
|
|
|
|
print(f"Error occurred: {str(e)}")
|
2024-09-05 02:59:01 +00:00
|
|
|
return False
|
2024-09-16 23:38:33 +00:00
|
|
|
|
2025-01-31 15:59:51 +00:00
|
|
|
|
2025-05-12 21:55:50 +00:00
|
|
|
def generate_roles_from_questionnaire(self, questionnaire_data: List[dict],role_slug:str) -> Roles_response:
|
2024-09-16 23:38:33 +00:00
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# List of areas: ["communication", "development", etc.]
|
|
|
|
|
|
|
|
|
|
prompt = get_roles_extraction_from_questionnaire()
|
|
|
|
|
response = self.client.beta.chat.completions.parse(
|
|
|
|
|
model=self.model,
|
|
|
|
|
messages=[
|
|
|
|
|
{
|
|
|
|
|
"role": "system",
|
|
|
|
|
"content": f'''{prompt}''',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"role": "user",
|
|
|
|
|
"content": f'''Questionairre data : {questionnaire_data}''',
|
2025-05-12 21:55:50 +00:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"role": "user",
|
|
|
|
|
"content": f'''Role slug to consider : {role_slug}''',
|
2024-09-16 23:38:33 +00:00
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
response_format=Roles_response,
|
2025-05-12 21:55:50 +00:00
|
|
|
max_tokens=4096,
|
2024-09-16 23:38:33 +00:00
|
|
|
temperature=0.1
|
|
|
|
|
)
|
|
|
|
|
extracted_text = json.loads(response.choices[0].message.content)
|
|
|
|
|
# You can customize this to generate roles based on the questionnaire data
|
|
|
|
|
|
|
|
|
|
return extracted_text
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"Error occurred: {str(e)}")
|
|
|
|
|
return False
|
2024-09-05 02:59:01 +00:00
|
|
|
|
|
|
|
|
|
2024-09-06 01:48:32 +00:00
|
|
|
|
|
|
|
|
class SopGeneratorExecutive:
|
|
|
|
|
def __init__(self):
|
|
|
|
|
self.api_key = os.getenv("OPENAI_API_KEY")
|
|
|
|
|
self.client = OpenAI(api_key=self.api_key)
|
|
|
|
|
self.model = "gpt-4o-mini"
|
|
|
|
|
|
2024-09-16 23:38:33 +00:00
|
|
|
def extract_sops_from_executive_vision_goals_doc(self, data: dict,executive:str) -> SOPsResponse:
|
2024-09-06 01:48:32 +00:00
|
|
|
"""
|
|
|
|
|
Extracts SOPs categorized into 'must,' 'shall,' and 'will' based on executive vision and goals.
|
|
|
|
|
|
|
|
|
|
:param data: A dictionary containing vision and goals.
|
|
|
|
|
:return: SOPsResponse containing the SOPs for executives
|
|
|
|
|
"""
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
|
|
vision = data.get("vision", "No vision provided")
|
2024-09-16 23:38:33 +00:00
|
|
|
goals = data.get("mission", "No goals provided")
|
2024-09-06 01:48:32 +00:00
|
|
|
|
2024-09-16 23:38:33 +00:00
|
|
|
prompt = get_sop_executive_from_vision_goals(executive)
|
2024-09-06 01:48:32 +00:00
|
|
|
|
|
|
|
|
user_content = f'''
|
2024-09-16 23:38:33 +00:00
|
|
|
Find the mission and vision provided below
|
2024-09-06 01:48:32 +00:00
|
|
|
Vision: {vision}
|
|
|
|
|
Goals: {goals}
|
2025-01-31 15:59:51 +00:00
|
|
|
|
2024-09-06 01:48:32 +00:00
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
response = self.client.beta.chat.completions.parse(
|
|
|
|
|
model=self.model,
|
|
|
|
|
messages=[
|
|
|
|
|
{
|
|
|
|
|
"role": "system",
|
|
|
|
|
"content": f'''{prompt}'''
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"role": "user",
|
|
|
|
|
"content": user_content,
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
response_format=Categories,
|
2024-09-25 21:40:08 +00:00
|
|
|
max_tokens=16000,
|
2024-09-06 01:48:32 +00:00
|
|
|
temperature=0.1
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
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_for_department_managers(self, docs):
|
|
|
|
|
try:
|
|
|
|
|
# First, extract departments and managers
|
2024-09-09 14:03:14 +01:00
|
|
|
sop_doc = DocumentParser()
|
|
|
|
|
departments_and_roles = sop_doc.extract_departments_and_managers_workers(docs)
|
|
|
|
|
|
|
|
|
|
if not departments_and_roles or not departments_and_roles.get('departments'):
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
departments_with_sops = []
|
|
|
|
|
|
|
|
|
|
for department in departments_and_roles['departments']:
|
|
|
|
|
managers_with_sops = []
|
|
|
|
|
for role in department['managers']:
|
|
|
|
|
prompt = get_sop_for_department_managers()
|
|
|
|
|
response = self.client.beta.chat.completions.parse(
|
|
|
|
|
model=self.model,
|
|
|
|
|
messages=[
|
|
|
|
|
{"role": "system", "content": prompt},
|
|
|
|
|
{"role": "user", "content": f"Generate SOPs for {role['position']} in {department['name']} department."}
|
|
|
|
|
],
|
|
|
|
|
response_format=ManagerSOPs,
|
2024-09-25 21:40:08 +00:00
|
|
|
max_tokens=16000,
|
2024-09-09 14:03:14 +01:00
|
|
|
temperature=0.1
|
|
|
|
|
)
|
|
|
|
|
manager_sops = json.loads(response.choices[0].message.content)
|
|
|
|
|
managers_with_sops.append(ManagerWithSOPs(title=role['position'], sops=manager_sops))
|
|
|
|
|
|
|
|
|
|
departments_with_sops.append(DepartmentManagerSOPs(
|
|
|
|
|
name=department['name'],
|
|
|
|
|
managers=managers_with_sops
|
|
|
|
|
))
|
|
|
|
|
|
|
|
|
|
return ExecutiveManagerSOPsResponse(departments=departments_with_sops)
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"Error in generate_sops_for_department_managers: {str(e)}")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
2025-01-31 15:59:51 +00:00
|
|
|
def generate_sops_from_questionnaire(self, questionnaire_data: dict, executives: List[str]):
|
2024-09-09 14:03:14 +01:00
|
|
|
try:
|
2025-01-31 15:59:51 +00:00
|
|
|
print("Generating SOPs from questionnaire...")
|
2024-09-09 14:03:14 +01:00
|
|
|
prompt = get_sop_executive_from_questionnaire()
|
2025-01-31 15:59:51 +00:00
|
|
|
print(f"Prompt: {prompt}")
|
2024-09-09 14:03:14 +01:00
|
|
|
|
|
|
|
|
# Prepare the questionnaire data for the prompt
|
|
|
|
|
user_content = json.dumps(questionnaire_data, indent=2)
|
2025-01-31 15:59:51 +00:00
|
|
|
print(f"User content: {user_content}")
|
2024-09-09 14:03:14 +01:00
|
|
|
|
|
|
|
|
response = self.client.beta.chat.completions.parse(
|
|
|
|
|
model=self.model,
|
|
|
|
|
messages=[
|
|
|
|
|
{"role": "system", "content": prompt},
|
2025-01-31 15:59:51 +00:00
|
|
|
{"role": "user", "content": f"Generate SOPs based on this questionnaire response:\n{user_content}\n\nExecutives to consider: {', '.join(executives)}"}
|
2024-09-09 14:03:14 +01:00
|
|
|
],
|
|
|
|
|
response_format={"type": "json_object"},
|
2024-09-25 21:40:08 +00:00
|
|
|
max_tokens=16000,
|
2024-09-09 14:03:14 +01:00
|
|
|
temperature=0.1
|
|
|
|
|
)
|
|
|
|
|
|
2025-01-31 15:59:51 +00:00
|
|
|
print("Response received from API.")
|
2024-09-09 14:03:14 +01:00
|
|
|
sops_data = json.loads(response.choices[0].message.content)
|
2025-01-31 15:59:51 +00:00
|
|
|
print(f"SOPs data: {sops_data}")
|
2024-09-09 14:03:14 +01:00
|
|
|
|
|
|
|
|
# Process executive SOPs
|
|
|
|
|
|
|
|
|
|
return {
|
2025-01-31 15:59:51 +00:00
|
|
|
"response": sops_data
|
2024-09-09 14:03:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"Error in generate_sops_from_questionnaire: {str(e)}")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
2025-01-31 15:59:51 +00:00
|
|
|
def generate_vision_mission_from_questionnaire(self, questionnaire_data: dict):
|
|
|
|
|
"""
|
|
|
|
|
Generate vision and mission based on the questionnaire data provided in the request body.
|
|
|
|
|
The request body is expected to contain plain-text information for vision and mission."""
|
|
|
|
|
try:
|
|
|
|
|
print("Generating vsion and mission from questionnaire...")
|
|
|
|
|
prompt = get_vision_mission_extraction_from_questionnaire_executive()
|
|
|
|
|
print(f"Prompt: {prompt}")
|
|
|
|
|
|
|
|
|
|
# Prepare the questionnaire data for the prompt
|
|
|
|
|
user_content = json.dumps(questionnaire_data, indent=2)
|
|
|
|
|
print(f"User content: {user_content}")
|
|
|
|
|
|
|
|
|
|
response = self.client.beta.chat.completions.parse(
|
|
|
|
|
model=self.model,
|
|
|
|
|
messages=[
|
|
|
|
|
{"role": "system", "content": prompt},
|
|
|
|
|
{"role": "user", "content": f"questionnaire response:\n{user_content}"}
|
|
|
|
|
],
|
|
|
|
|
response_format=VisionMissionResponse2,
|
|
|
|
|
max_tokens=16000,
|
|
|
|
|
temperature=0.1
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
print("Response received from API.")
|
|
|
|
|
response = json.loads(response.choices[0].message.content)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return response
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"Error in generate_sops_from_questionnaire: {str(e)}")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def generate_dept_goals_from_questionnaire(self, questionnaire_data):
|
|
|
|
|
try:
|
|
|
|
|
print("Generating SOPs from questionnaire...")
|
|
|
|
|
prompt = get_dept_vision_mission_extraction_from_questionaiire()
|
|
|
|
|
print(f"Prompt: {prompt}")
|
|
|
|
|
|
|
|
|
|
# Prepare the questionnaire data for the prompt
|
|
|
|
|
user_content = json.dumps(questionnaire_data, indent=2)
|
|
|
|
|
|
|
|
|
|
response = self.client.beta.chat.completions.parse(
|
|
|
|
|
model=self.model,
|
|
|
|
|
messages=[
|
|
|
|
|
{"role": "system", "content": prompt},
|
|
|
|
|
{"role": "user", "content": f"Generate based on this questionnaire response:\n{user_content}\n"}
|
|
|
|
|
],
|
|
|
|
|
response_format=DeptGoalsVisssion,
|
|
|
|
|
max_tokens=16000,
|
|
|
|
|
temperature=0.1
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
print("Response received from API.")
|
|
|
|
|
sops_data = json.loads(response.choices[0].message.content)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Process executive SOPs
|
|
|
|
|
|
|
|
|
|
return sops_data
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"Error in generate_sops_from_questionnaire: {str(e)}")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
def generate_sops_from_questionnaire2(self, questionnaire_data: dict):
|
|
|
|
|
try:
|
|
|
|
|
print("Generating SOPs from questionnaire...")
|
|
|
|
|
prompt = get_sop_executive_from_questionnaire2()
|
|
|
|
|
print(f"Prompt: {prompt}")
|
|
|
|
|
|
|
|
|
|
# Prepare the questionnaire data for the prompt
|
|
|
|
|
user_content = json.dumps(questionnaire_data, indent=2)
|
|
|
|
|
print(f"User content: {user_content}")
|
|
|
|
|
|
|
|
|
|
response = self.client.beta.chat.completions.parse(
|
|
|
|
|
model=self.model,
|
|
|
|
|
messages=[
|
|
|
|
|
{"role": "system", "content": prompt},
|
|
|
|
|
{"role": "user", "content": f"Generate SOPs based on this questionnaire response:\n{user_content}\n"}
|
|
|
|
|
],
|
|
|
|
|
response_format={"type": "json_object"},
|
|
|
|
|
max_tokens=16000,
|
|
|
|
|
temperature=0.1
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
print("Response received from API.")
|
|
|
|
|
sops_data = json.loads(response.choices[0].message.content)
|
|
|
|
|
print(f"SOPs data: {sops_data}")
|
|
|
|
|
|
|
|
|
|
# Process executive SOPs
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
"response": sops_data
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"Error in generate_sops_from_questionnaire: {str(e)}")
|
|
|
|
|
return False
|
|
|
|
|
|
2024-09-09 14:03:14 +01:00
|
|
|
|
|
|
|
|
class SopGeneratorManager:
|
|
|
|
|
def __init__(self):
|
|
|
|
|
self.api_key = os.getenv("OPENAI_API_KEY")
|
|
|
|
|
self.client = OpenAI(api_key=self.api_key)
|
|
|
|
|
self.model = "gpt-4o-mini"
|
|
|
|
|
|
2024-09-06 01:48:32 +00:00
|
|
|
|
2024-09-10 02:51:31 +01:00
|
|
|
|
|
|
|
|
|
2024-09-10 01:00:08 +01:00
|
|
|
|