added manager and execuytive generator
This commit is contained in:
Binary file not shown.
+71
-7
@@ -1,9 +1,8 @@
|
|||||||
import os
|
import os
|
||||||
from flask import Blueprint, request, jsonify, current_app
|
from flask import Blueprint, request, jsonify, current_app
|
||||||
from werkzeug.utils import secure_filename
|
from werkzeug.utils import secure_filename
|
||||||
|
from src.services.sop_generator import (SopPersonalAssessment,SopGeneratorExecutive)
|
||||||
from src.services.sop_generator import (SopGeneratorDocument,
|
from src.services.document_parser import DocumentParser
|
||||||
SopPersonalAssessment,SopGeneratorExecutive)
|
|
||||||
|
|
||||||
from src.utils.utils import delete_all_files_in_directory
|
from src.utils.utils import delete_all_files_in_directory
|
||||||
from src.utils.document_loader import load_document
|
from src.utils.document_loader import load_document
|
||||||
@@ -103,7 +102,7 @@ def generate_questions_from_sop():
|
|||||||
return jsonify({"error": "Document cannot extract SOPs", "message": status_check["message"]}), 400
|
return jsonify({"error": "Document cannot extract SOPs", "message": status_check["message"]}), 400
|
||||||
|
|
||||||
# Generate SOPs based on the roles provided
|
# Generate SOPs based on the roles provided
|
||||||
sop_generator = SopGeneratorDocument()
|
sop_generator = DocumentParser()
|
||||||
sops = sop_generator.generate_sops_from_doc(docs)
|
sops = sop_generator.generate_sops_from_doc(docs)
|
||||||
|
|
||||||
# Cleanup: Delete all files in the upload directory after processing
|
# Cleanup: Delete all files in the upload directory after processing
|
||||||
@@ -147,7 +146,7 @@ def generate_sops():
|
|||||||
docs = load_document(file_path)
|
docs = load_document(file_path)
|
||||||
|
|
||||||
# Generate SOPs based on the roles provided
|
# Generate SOPs based on the roles provided
|
||||||
sop_generator = SopGeneratorDocument()
|
sop_generator = DocumentParser()
|
||||||
sops = sop_generator.extract_sops_from_doc(docs)
|
sops = sop_generator.extract_sops_from_doc(docs)
|
||||||
# Cleanup: Delete all files in the upload directory after processing
|
# Cleanup: Delete all files in the upload directory after processing
|
||||||
delete_all_files_in_directory(upload_folder)
|
delete_all_files_in_directory(upload_folder)
|
||||||
@@ -277,7 +276,7 @@ def generate_executive_sops_from_doc():
|
|||||||
# Use the utility function to generate docs from the file
|
# Use the utility function to generate docs from the file
|
||||||
docs = load_document(file_path)
|
docs = load_document(file_path)
|
||||||
|
|
||||||
sop_doc = SopGeneratorDocument()
|
sop_doc = DocumentParser()
|
||||||
vision_mission = sop_doc.extract_vision_mission(docs)
|
vision_mission = sop_doc.extract_vision_mission(docs)
|
||||||
|
|
||||||
if not vision_mission:
|
if not vision_mission:
|
||||||
@@ -380,4 +379,69 @@ def generate_sops_from_questionnaire():
|
|||||||
return jsonify({"sops": serializable_result, "message": "SOPs successfully generated from questionnaire."}), 200
|
return jsonify({"sops": serializable_result, "message": "SOPs successfully generated from questionnaire."}), 200
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return jsonify({"error": "Processing error", "message": f"An error occurred while processing the request: {str(e)}"}), 500
|
return jsonify({"error": "Processing error", "message": f"An error occurred while processing the request: {str(e)}"}), 500
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@sops_bp.route('/executive/get_roles_doc', methods=['POST'])
|
||||||
|
def generate_sops_from_questionnaire():
|
||||||
|
try:
|
||||||
|
# Retrieve form data
|
||||||
|
reference_roles = request.get_json().get('reference_roles') # List of reference roles in JSON format
|
||||||
|
document = request.files.get('document') # The uploaded document
|
||||||
|
|
||||||
|
if not reference_roles or not document:
|
||||||
|
return jsonify({"error": "Missing data", "message": "Reference roles or document not provided."}), 400
|
||||||
|
|
||||||
|
# Use extractor to extract roles from the document
|
||||||
|
extractor = DocumentParser()
|
||||||
|
extracted_data = extractor.extract_departments_and_managers_workers([document])
|
||||||
|
|
||||||
|
if not extracted_data:
|
||||||
|
return jsonify({"error": "Extraction error", "message": "No roles were extracted from the document."}), 400
|
||||||
|
|
||||||
|
# Extract all managers with their name, title (position), and classification (role: PRP or SRP)
|
||||||
|
extracted_managers = []
|
||||||
|
for department in extracted_data['departments']:
|
||||||
|
extracted_managers.extend([{
|
||||||
|
'name': manager['name'],
|
||||||
|
'position': manager.get('position', 'Unknown Position'), # Assuming title is the position
|
||||||
|
'role': manager.get('classification', 'Unknown Role') # PRP or SRP classification
|
||||||
|
} for manager in department['managers']])
|
||||||
|
|
||||||
|
# Prepare assigned, unassigned, and unavailable managers
|
||||||
|
assigned_managers = [manager for manager in extracted_managers if manager['name'] in reference_roles]
|
||||||
|
unassigned_managers = [{'name': role, 'position': 'Reference Role', 'role': 'N/A'} for role in reference_roles if role not in [manager['name'] for manager in extracted_managers]]
|
||||||
|
unavailable_managers = [manager for manager in extracted_managers if manager['name'] not in reference_roles]
|
||||||
|
|
||||||
|
# Return the results with detailed manager information
|
||||||
|
return jsonify({
|
||||||
|
"assigned_roles": assigned_managers,
|
||||||
|
"unassigned_roles": unassigned_managers,
|
||||||
|
"unavailable_roles": unavailable_managers
|
||||||
|
}), 200
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({"error": "Processing error", "message": f"An error occurred while processing the request: {str(e)}"}), 500
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
assigned_roles = [role for role in reference_roles if role in extracted_roles]
|
||||||
|
unassigned_roles = [role for role in reference_roles if role not in extracted_roles]
|
||||||
|
unavailable_roles = [role for role in extracted_roles if role not in reference_roles]
|
||||||
|
|
||||||
|
# Return the results
|
||||||
|
return jsonify({
|
||||||
|
"assigned_roles": assigned_roles,
|
||||||
|
"unassigned_roles": unassigned_roles,
|
||||||
|
"unavailable_roles": unavailable_roles
|
||||||
|
}), 200
|
||||||
|
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({"error": "Processing error", "message": f"An error occurred while processing the request: {str(e)}"}), 500
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -35,17 +35,26 @@ class Categories(BaseModel):
|
|||||||
class ExecutivesSops(BaseModel):
|
class ExecutivesSops(BaseModel):
|
||||||
executive_sops: List[RoleSops]
|
executive_sops: List[RoleSops]
|
||||||
|
|
||||||
class ManagerialRole(BaseModel):
|
class Manager(BaseModel):
|
||||||
title: str
|
name: str
|
||||||
responsibilities: List[str]
|
position: str
|
||||||
|
role: str
|
||||||
|
responsibilities: List[str] = Field(default_factory=list)
|
||||||
|
|
||||||
|
class Worker(BaseModel):
|
||||||
|
name: str
|
||||||
|
position: str
|
||||||
|
responsibilities: List[str] = Field(default_factory=list)
|
||||||
|
|
||||||
class Department(BaseModel):
|
class Department(BaseModel):
|
||||||
name: str
|
name: str
|
||||||
managerial_roles: List[ManagerialRole]
|
managers: List[Manager] = Field(default_factory=list) # Updated to managers
|
||||||
|
workers: List[Worker] = Field(default_factory=list) # New field for workers
|
||||||
|
|
||||||
class DepartmentsAndRolesResponse(BaseModel):
|
class DepartmentsAndWorkersResponse(BaseModel):
|
||||||
departments: List[Department]
|
departments: List[Department]
|
||||||
|
|
||||||
|
|
||||||
class ManagerSOPs(BaseModel):
|
class ManagerSOPs(BaseModel):
|
||||||
must: List[str] = Field(default_factory=list)
|
must: List[str] = Field(default_factory=list)
|
||||||
shall: List[str] = Field(default_factory=list)
|
shall: List[str] = Field(default_factory=list)
|
||||||
@@ -60,4 +69,7 @@ class DepartmentManagerSOPs(BaseModel):
|
|||||||
managers: List[ManagerWithSOPs]
|
managers: List[ManagerWithSOPs]
|
||||||
|
|
||||||
class ExecutiveManagerSOPsResponse(BaseModel):
|
class ExecutiveManagerSOPsResponse(BaseModel):
|
||||||
departments: List[DepartmentManagerSOPs]
|
departments: List[DepartmentManagerSOPs]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+56
-9
@@ -93,31 +93,45 @@ def get_vision_mission_extraction_from_doc():
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_departments_and_roles_extraction_prompt():
|
def get_departments_managers_workers_extraction_prompt():
|
||||||
return """
|
return """
|
||||||
Extract departments and their senior managerial roles from the document.
|
Extract departments, their managers, and workers from the document.
|
||||||
Include only managerial positions (e.g., Department Head, Director, Manager).
|
For each department, include the managers (e.g., Department Head, Director, Manager) and their key responsibilities.
|
||||||
For each role, list 2-3 key responsibilities.
|
Additionally, for each department, extract the workers and their positions, and list 1-2 key responsibilities for each worker.
|
||||||
Do not add any departments or roles that are not explicitly mentioned in the document.
|
Do not add any departments, managers, or workers that are not explicitly mentioned in the document.
|
||||||
|
Managers: Include the managers (e.g., Department Head, Manager), their role , and key responsibilities.
|
||||||
|
- **PRP (Primary Responsible Person)**: A manager who has primary responsibility for decision-making and overseeing operations.
|
||||||
|
- **SRP (Secondary Responsible Person)**: A manager who supports the PRP, often assisting with tasks and providing backup in decision-making.
|
||||||
|
|
||||||
Format as JSON:
|
Format as JSON:
|
||||||
{
|
{
|
||||||
"departments": [
|
"departments": [
|
||||||
{
|
{
|
||||||
"name": "Department Name",
|
"name": "Department Name",
|
||||||
"managerial_roles": [
|
"managers": [
|
||||||
{
|
{
|
||||||
"title": "Managerial Role Title",
|
"name": "Manager Name",
|
||||||
|
"position": "manager Position",
|
||||||
|
"role": "PRP or SRP", # The classification field either PRP or SRP
|
||||||
|
"responsibilities": ["Key Responsibility 1", "Key Responsibility 2"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"workers": [
|
||||||
|
{
|
||||||
|
"name": "Worker Name",
|
||||||
|
"position": "Worker Position",
|
||||||
"responsibilities": ["Key Responsibility 1", "Key Responsibility 2"]
|
"responsibilities": ["Key Responsibility 1", "Key Responsibility 2"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
If no departments or roles are found in the document, return an empty list for departments.
|
If no departments, managers, or workers are found in the document, return an empty list for departments.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_sop_for_department_managers():
|
def get_sop_for_department_managers():
|
||||||
return '''Generate Standard Operating Procedures (SOPs) for the specified managerial role in the given department.
|
return '''Generate Standard Operating Procedures (SOPs) for the specified managerial role in the given department.
|
||||||
|
|
||||||
@@ -186,4 +200,37 @@ def get_sop_executive_from_questionnaire():
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
Ensure that each specified department has its own set of SOPs.
|
Ensure that each specified department has its own set of SOPs.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
def generate_llm_comparison_prompt(reference_roles, extracted_managers):
|
||||||
|
reference_roles_str = ', '.join(reference_roles)
|
||||||
|
extracted_managers_str = '\n'.join([f"- {manager['name']} (Position: {manager['position']}, Role: {manager['role']})" for manager in extracted_managers])
|
||||||
|
|
||||||
|
prompt = f"""
|
||||||
|
You are tasked with comparing a list of reference roles with the extracted roles from a document.
|
||||||
|
|
||||||
|
Reference roles:
|
||||||
|
[{reference_roles_str}]
|
||||||
|
|
||||||
|
Extracted roles:
|
||||||
|
{extracted_managers_str}
|
||||||
|
|
||||||
|
Please classify the roles into the following categories:
|
||||||
|
1. **Assigned Roles**: Roles that are found in both the reference list and the extracted list.
|
||||||
|
2. **Unassigned Roles**: Roles that are found in the reference list but not in the extracted list.
|
||||||
|
3. **Unavailable Roles**: Roles that are found in the extracted list but not in the reference list.
|
||||||
|
|
||||||
|
Return the result in the following JSON format:
|
||||||
|
{
|
||||||
|
"assigned_roles": [
|
||||||
|
{"name": "Role Name", "position": "Role Position", "role": "PRP or SRP"}
|
||||||
|
],
|
||||||
|
"unassigned_roles": [
|
||||||
|
{"name": "Role Name", "position": "Reference Role"}
|
||||||
|
],
|
||||||
|
"unavailable_roles": [
|
||||||
|
{"name": "Role Name", "position": "Role Position", "role": "PRP or SRP"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
return prompt
|
||||||
|
|||||||
@@ -0,0 +1,197 @@
|
|||||||
|
import os
|
||||||
|
import json
|
||||||
|
from openai import OpenAI
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
from typing import List, Dict, Optional
|
||||||
|
from src.prompts.sops import *
|
||||||
|
from src.models.response_schemas import *
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
|
||||||
|
#SopGeneratorDocument
|
||||||
|
class DocumentParser:
|
||||||
|
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
|
||||||
|
|
||||||
|
def extract_vision_mission(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_vision_mission_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=VisionMissionResponse,
|
||||||
|
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
|
||||||
|
|
||||||
|
'''def extract_departments_and_managers(self, docs):
|
||||||
|
"""
|
||||||
|
Extract departments and managerial roles from the document.
|
||||||
|
|
||||||
|
:param docs: List of document chunks
|
||||||
|
:return: Dictionary containing departments and their managerial roles
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
docs_text = self._extract_text_from_docs(docs)
|
||||||
|
prompt = get_departments_and_roles_extraction_prompt()
|
||||||
|
|
||||||
|
response = self.client.beta.chat.completions.parse(
|
||||||
|
model=self.model,
|
||||||
|
messages=[
|
||||||
|
{"role": "system", "content": prompt},
|
||||||
|
{"role": "user", "content": [{"type": "text", "text": text} for text in docs_text]}
|
||||||
|
],
|
||||||
|
response_format=DepartmentsAndRolesResponse,
|
||||||
|
max_tokens=4096,
|
||||||
|
temperature=0.1
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
return json.loads(response.choices[0].message.content)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
return False'''
|
||||||
|
|
||||||
|
|
||||||
|
def extract_departments_and_managers_workers(self, docs):
|
||||||
|
"""
|
||||||
|
Extract departments, managers, and workers from the document.
|
||||||
|
|
||||||
|
:param docs: List of document chunks
|
||||||
|
:return: Dictionary containing departments, their managers, and workers.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
docs_text = self._extract_text_from_docs(docs)
|
||||||
|
prompt = get_departments_managers_workers_extraction_prompt() # Update your prompt to handle managers and workers
|
||||||
|
|
||||||
|
response = self.client.beta.chat.completions.parse(
|
||||||
|
model=self.model,
|
||||||
|
messages=[
|
||||||
|
{"role": "system", "content": prompt},
|
||||||
|
{"role": "user", "content": [{"type": "text", "text": text} for text in docs_text]}
|
||||||
|
],
|
||||||
|
response_format=DepartmentsAndWorkersResponse, # Use the updated response schema
|
||||||
|
max_tokens=4096,
|
||||||
|
temperature=0.1
|
||||||
|
)
|
||||||
|
|
||||||
|
return json.loads(response.choices[0].message.content)
|
||||||
|
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def generate_sops_(self, docs, reference_roles):
|
||||||
|
try:
|
||||||
|
# First, extract departments and managers from the document
|
||||||
|
sop_doc = DocumentParser()
|
||||||
|
departments_and_roles = sop_doc.extract_departments_and_managers(docs)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Prepare extracted roles (only managers)
|
||||||
|
extracted_managers = []
|
||||||
|
for department in departments_and_roles['departments']:
|
||||||
|
extracted_managers.extend([
|
||||||
|
{
|
||||||
|
'name': manager['name'],
|
||||||
|
'position': manager.get('title', 'Unknown Position'),
|
||||||
|
'role': manager.get('classification', 'Unknown Role') # PRP or SRP classification
|
||||||
|
}
|
||||||
|
for manager in department['managerial_roles']
|
||||||
|
])
|
||||||
|
|
||||||
|
# Generate prompt for the LLM to compare reference roles with extracted roles
|
||||||
|
prompt = generate_llm_comparison_prompt(reference_roles, extracted_managers)
|
||||||
|
|
||||||
|
# Send prompt to the LLM for comparison
|
||||||
|
response = self.client.beta.chat.completions.parse(
|
||||||
|
model=self.model,
|
||||||
|
messages=[
|
||||||
|
{"role": "system", "content": "You are a role comparison assistant."},
|
||||||
|
{"role": "user", "content": prompt}
|
||||||
|
],
|
||||||
|
max_tokens=1024,
|
||||||
|
temperature=0.1
|
||||||
|
)
|
||||||
|
|
||||||
|
# Parse LLM response (assuming it returns a structured JSON with assigned, unassigned, and unavailable roles)
|
||||||
|
comparison_result = json.loads(response.choices[0].message.content)
|
||||||
|
|
||||||
|
# Return the result as a JSON response
|
||||||
|
return jsonify(comparison_result), 200
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({"error": "Processing error", "message": f"An error occurred: {str(e)}"}), 500
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
+155
-113
@@ -5,117 +5,9 @@ from pydantic import BaseModel, Field
|
|||||||
from typing import List, Dict, Optional
|
from typing import List, Dict, Optional
|
||||||
from src.prompts.sops import *
|
from src.prompts.sops import *
|
||||||
from src.models.response_schemas import *
|
from src.models.response_schemas import *
|
||||||
|
from src.services.document_parser import DocumentParser
|
||||||
class SopGeneratorDocument:
|
from dotenv import load_dotenv
|
||||||
def __init__(self):
|
load_dotenv()
|
||||||
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
|
|
||||||
|
|
||||||
def extract_vision_mission(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_vision_mission_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=VisionMissionResponse,
|
|
||||||
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
|
|
||||||
|
|
||||||
def extract_departments_and_managers(self, docs):
|
|
||||||
"""
|
|
||||||
Extract departments and managerial roles from the document.
|
|
||||||
|
|
||||||
:param docs: List of document chunks
|
|
||||||
:return: Dictionary containing departments and their managerial roles
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
docs_text = self._extract_text_from_docs(docs)
|
|
||||||
prompt = get_departments_and_roles_extraction_prompt()
|
|
||||||
|
|
||||||
response = self.client.beta.chat.completions.parse(
|
|
||||||
model=self.model,
|
|
||||||
messages=[
|
|
||||||
{"role": "system", "content": prompt},
|
|
||||||
{"role": "user", "content": [{"type": "text", "text": text} for text in docs_text]}
|
|
||||||
],
|
|
||||||
response_format=DepartmentsAndRolesResponse,
|
|
||||||
max_tokens=4096,
|
|
||||||
temperature=0.1
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
return json.loads(response.choices[0].message.content)
|
|
||||||
except json.JSONDecodeError:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -271,7 +163,155 @@ class SopGeneratorExecutive:
|
|||||||
def generate_sops_for_department_managers(self, docs):
|
def generate_sops_for_department_managers(self, docs):
|
||||||
try:
|
try:
|
||||||
# First, extract departments and managers
|
# First, extract departments and managers
|
||||||
sop_doc = SopGeneratorDocument()
|
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,
|
||||||
|
max_tokens=1024,
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
def generate_sops_from_questionnaire(self, questionnaire_data: dict, executives: List[str], managers: List[str], departments: List[str]):
|
||||||
|
try:
|
||||||
|
prompt = get_sop_executive_from_questionnaire()
|
||||||
|
|
||||||
|
# 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 SOPs based on this questionnaire:\n{user_content}\n\nExecutives to consider: {', '.join(executives)}\nManagers to consider: {', '.join(managers)}\nDepartments to consider: {', '.join(departments)}"}
|
||||||
|
],
|
||||||
|
response_format={"type": "json_object"},
|
||||||
|
max_tokens=4096,
|
||||||
|
temperature=0.1
|
||||||
|
)
|
||||||
|
|
||||||
|
sops_data = json.loads(response.choices[0].message.content)
|
||||||
|
|
||||||
|
# Process executive SOPs
|
||||||
|
executive_sops = {}
|
||||||
|
for executive in executives:
|
||||||
|
if executive in sops_data['executives']:
|
||||||
|
executive_sops[executive] = Categories(**sops_data['executives'][executive])
|
||||||
|
else:
|
||||||
|
executive_sops[executive] = Categories()
|
||||||
|
|
||||||
|
# Process department manager SOPs
|
||||||
|
departments_with_sops = []
|
||||||
|
for dept_name in departments:
|
||||||
|
dept_data = next((d for d in sops_data['departments'] if d['name'].lower() == dept_name.lower()), None)
|
||||||
|
if dept_data:
|
||||||
|
managers_with_sops = [
|
||||||
|
ManagerWithSOPs(
|
||||||
|
title=manager,
|
||||||
|
sops=ManagerSOPs(**dept_data['managers'])
|
||||||
|
)
|
||||||
|
for manager in managers
|
||||||
|
|
||||||
|
]
|
||||||
|
if managers_with_sops:
|
||||||
|
departments_with_sops.append(DepartmentManagerSOPs(
|
||||||
|
name=dept_name,
|
||||||
|
managers=managers_with_sops
|
||||||
|
))
|
||||||
|
|
||||||
|
return {
|
||||||
|
"executive_sops": executive_sops,
|
||||||
|
"department_sops": ExecutiveManagerSOPsResponse(departments=departments_with_sops)
|
||||||
|
}
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error in generate_sops_from_questionnaire: {str(e)}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
def extract_sops_from_executive_vision_goals_doc(self, data: dict,executives:List) -> SOPsResponse:
|
||||||
|
"""
|
||||||
|
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")
|
||||||
|
goals = data.get("goals", "No goals provided")
|
||||||
|
|
||||||
|
prompt = get_sop_executive_from_vision_goals(executives)
|
||||||
|
|
||||||
|
user_content = f'''
|
||||||
|
Vision: {vision}
|
||||||
|
Goals: {goals}
|
||||||
|
'''
|
||||||
|
|
||||||
|
response = self.client.beta.chat.completions.parse(
|
||||||
|
model=self.model,
|
||||||
|
messages=[
|
||||||
|
{
|
||||||
|
"role": "system",
|
||||||
|
"content": f'''{prompt}'''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": user_content,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
response_format=Categories,
|
||||||
|
max_tokens=2048,
|
||||||
|
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
|
||||||
|
sop_doc = DocumentParser()
|
||||||
departments_and_roles = sop_doc.extract_departments_and_managers(docs)
|
departments_and_roles = sop_doc.extract_departments_and_managers(docs)
|
||||||
|
|
||||||
if not departments_and_roles or not departments_and_roles.get('departments'):
|
if not departments_and_roles or not departments_and_roles.get('departments'):
|
||||||
@@ -363,5 +403,7 @@ class SopGeneratorExecutive:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error in generate_sops_from_questionnaire: {str(e)}")
|
print(f"Error in generate_sops_from_questionnaire: {str(e)}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,81 +1,14 @@
|
|||||||
from src.services.sop_generator import SopGeneratorDocument, SopGeneratorExecutive
|
from src.services.sop_generator import SopGeneratorExecutive
|
||||||
from src.utils.document_loader import load_document
|
from src.utils.document_loader import load_document
|
||||||
|
from src.services.document_parser import DocumentParser
|
||||||
file_path = "/root/ds_erp_ai/data/raw/document.doc"
|
from src.services.sop_generator import SopGeneratorExecutive
|
||||||
|
file_path = r"C:\Users\User\Desktop\Blessing_AI\MKD\test_erp_ai\erp_ai\test\erp_ai\data\raw\document.doc"
|
||||||
docs = load_document(file_path)
|
docs = load_document(file_path)
|
||||||
sop_doc = SopGeneratorDocument()
|
|
||||||
sop_executive = SopGeneratorExecutive()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# Test the generate_sops_from_questionnaire function
|
SOP = DocumentParser()
|
||||||
questionnaire_data = {
|
so = SopGeneratorExecutive()
|
||||||
"organizational_vision": {
|
info = SOP.extract_departments_and_managers_workers(docs)
|
||||||
"question_1_answer": "Our vision is to lead the market in innovative product solutions.",
|
print(info)
|
||||||
"question_2_answer": "We see our organization contributing by expanding into new regions and enhancing service quality.",
|
|
||||||
"question_3_answer": "The key elements of our vision focus on scalability, customer satisfaction, and technological advancement."
|
|
||||||
},
|
|
||||||
"organizational_strategic_goals": {
|
|
||||||
"question_1_answer": "The strategic direction is to increase market share and improve operational efficiency.",
|
|
||||||
"question_2_answer": "We aim to achieve a 20% reduction in operating costs by streamlining internal processes.",
|
|
||||||
"question_3_answer": "The process aligns with our goal to reduce costs while maintaining high product quality."
|
|
||||||
},
|
|
||||||
"departmental_strategic_goals": {
|
|
||||||
"sales_department_answer": "Increase sales by 15% in the next fiscal year through better lead generation and customer retention.",
|
|
||||||
"finance_department_answer": "Ensure a balanced budget by optimizing resource allocation and reducing overhead costs."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
executives = ["CEO", "COO"]
|
|
||||||
managers = ["Sales Manager", "Finance Manager"]
|
|
||||||
|
|
||||||
sops_from_questionnaire = sop_executive.generate_sops_from_questionnaire(questionnaire_data, executives, managers)
|
|
||||||
|
|
||||||
if sops_from_questionnaire:
|
|
||||||
print("Generated SOPs from Questionnaire:")
|
|
||||||
|
|
||||||
# Print Executive SOPs
|
|
||||||
print("\nExecutive SOPs:")
|
|
||||||
for executive, sops in sops_from_questionnaire["executive_sops"].items():
|
|
||||||
print(f" {executive}:")
|
|
||||||
print(" Must SOPs:")
|
|
||||||
for sop in sops.must:
|
|
||||||
print(f" - {sop}")
|
|
||||||
print(" Shall SOPs:")
|
|
||||||
for sop in sops.shall:
|
|
||||||
print(f" - {sop}")
|
|
||||||
print(" Will SOPs:")
|
|
||||||
for sop in sops.will:
|
|
||||||
print(f" - {sop}")
|
|
||||||
|
|
||||||
# Print Department Manager SOPs
|
|
||||||
print("\nDepartment Manager SOPs:")
|
|
||||||
for department in sops_from_questionnaire["department_sops"].departments:
|
|
||||||
print(f" Department: {department.name}")
|
|
||||||
for manager in department.managers:
|
|
||||||
print(f" Manager: {manager.title}")
|
|
||||||
print(" Must SOPs:")
|
|
||||||
for sop in manager.sops.must:
|
|
||||||
print(f" - {sop}")
|
|
||||||
print(" Shall SOPs:")
|
|
||||||
for sop in manager.sops.shall:
|
|
||||||
print(f" - {sop}")
|
|
||||||
print(" Will SOPs:")
|
|
||||||
for sop in manager.sops.will:
|
|
||||||
print(f" - {sop}")
|
|
||||||
else:
|
|
||||||
print("Failed to generate SOPs from questionnaire.")
|
|
||||||
|
|
||||||
# You can keep the previous tests if you want
|
|
||||||
departments_and_roles = sop_doc.extract_departments_and_managers(docs)
|
|
||||||
if departments_and_roles:
|
|
||||||
print("\nExtracted Departments and Roles:")
|
|
||||||
for department in departments_and_roles.get('departments', []):
|
|
||||||
print(f"\nDepartment: {department['name']}")
|
|
||||||
for role in department.get('managerial_roles', []):
|
|
||||||
print(f" Role: {role['title']}")
|
|
||||||
print(f" Responsibilities: {', '.join(role['responsibilities'])}")
|
|
||||||
else:
|
|
||||||
print("Failed to extract departments and roles.")
|
|
||||||
|
|
||||||
v_ms = sop_doc.extract_vision_mission(docs)
|
|
||||||
print(f"\nVision and Mission: {v_ms}")
|
|
||||||
|
|||||||
Reference in New Issue
Block a user