improved on sops generations on questions and added bot suggestion

This commit is contained in:
2024-09-16 23:38:33 +00:00
parent cd8f499f97
commit 47a274741f
10 changed files with 228 additions and 21 deletions
+4 -2
View File
@@ -32,7 +32,7 @@ def generate_questions_from_sop():
input_data = request.get_json()
# Validate required fields
required_fields = ['sops', 'assessment_type', 'frequency_type', 'duration']
required_fields = ['sops', 'assessment_type', 'frequency_type', 'duration',"roles_data"]
for field in required_fields:
if field not in input_data:
return jsonify({"error": "Missing data", "message": f"'{field}' is required."}), 400
@@ -43,13 +43,15 @@ def generate_questions_from_sop():
assessment_type = input_data['assessment_type']
frequency_type = input_data['frequency_type']
duration = input_data['duration']
roles_data = input_data["roles_data"]
# Prepare the data for the generator
generator_input = {
"sops": json.dumps(sops), # Convert SOPs to JSON string
"assessment_type": assessment_type,
"frequency_type": frequency_type,
"duration": duration
"duration": duration,
"roles_data":roles_data
}
# Call the generator to create questions
+27 -1
View File
@@ -19,7 +19,7 @@ def allowed_file(filename):
"""Check if the file has an allowed extension."""
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@sops_bp.route('/personal_assessment/get_roles', methods=['POST'])
@sops_bp.route('/personal_assessment/get_roles_from_doc', methods=['POST'])
def get_roles():
# Check if the post request has the file part
if 'document' not in request.files:
@@ -62,6 +62,29 @@ def get_roles():
@sops_bp.route('/personal_assessment/get_roles_from_questionnaire', methods=['POST'])
def get_roles_questionnaire():
# Check if the post request has the file part
questionnaire_data = request.json
# Validate the required fields in the questionnaire data
if not questionnaire_data.get('vision') or not questionnaire_data.get('roles') or not questionnaire_data.get('responsibilities'):
return jsonify({
"error": "Missing required fields",
"message": "Please provide 'vision', 'roles', and 'responsibilities' in the request body."
}), 400
generator = SopPersonalAssessment()
roles = generator.generate_roles_from_questionnaire(questionnaire_data)
if not roles:
return jsonify({"error": "No roles found", "message": "No roles were extracted from the questionnaire."}), 404
return jsonify({"roles": roles, "message": "Roles successfully extracted from the questionnaire."}), 200
@sops_bp.route('/personal_assessment/generate_sops_from_doc', methods=['POST'])
def generate_sops():
@@ -180,6 +203,8 @@ def generate_sops_by_roles_and_areas():
@sops_bp.route('/executive/generate_sop_mission_from_vision', methods=['POST'])
def generate_executive_sops_from_doc():
"""
@@ -411,6 +436,7 @@ def get_roles_for_reference_workers():
return jsonify({"error": "Processing error", "message": f"An error occurred while processing the request: {str(e)}"}), 500
@sops_bp.route('/manager/generate_sop_workers_doc', methods=['POST'])
def generate_sop_workers_doc():
try:
+1
View File
@@ -5,6 +5,7 @@ class Question(BaseModel):
assigned_to: str
role: str
questions: str
area_tag:str
class AssementQuestion(BaseModel):
number: int
+1
View File
@@ -3,6 +3,7 @@ from typing import List, Optional
class Categories(BaseModel):
must: Optional[List[str]] = Field(default_factory=list)
shall: Optional[List[str]] = Field(default_factory=list)
will: Optional[List[str]] = Field(default_factory=list)
+54 -8
View File
@@ -15,12 +15,14 @@ def get_questions_prompt():
frequency number: (e.g., day 3, week 2, biweekly 1)
total duration: (e.g., 6 weeks, 12 days)
SOPs of the assessment:
roles_data e.g [{"position""test position","mame":"name of staff"}]
Instructions:
1. Review the SOPs of the assessment and generate questions for the workers based on the frequency type, frequency number, and topic areas.
1. Review the SOPs of the assessment and generate questions for the workers based on the frequency type, frequency number, and topic areas and roles data provided
2. Regardless of the assement type, always use 1,2,3 for the frequency numbering, nothing else
3. All questions are "yes" or "no" questions nothing extra
3. All questions are "yes" or "no" questions nothing extra and precise ,not long
4. Generate a total of at least 20 questions all rounda based on the sops and roles for each frequency number
Example response:
questions
@@ -31,20 +33,64 @@ def get_questions_prompt():
"frequency_number": "2",
"questions": [
{
"assigned_to": "person name or role",
"role": "person role or name",
"assigned_to": "name",
"role": "person role",
"question": "e.g., Is the internal project team being followed according to the SOP?"
"area_tag":"timeline"
}
]
] ## up to at least 20 questions
},
{
"frequency_number": "3",
"questions": [
{
"assigned_to": "person name or role",
"role": "person role or name",
"question": "e.g., Have communication protocols been followed for the task at hand?"
"assigned_to": "name",
"role": "person role",
"question": "e.g., Have communication protocols been followed for the task at hand?".
"area_tag":"communication"
} ## up to at least 20 questions
]
}
]
}
"""
return prompt
def get_questions_prompt_v2():
prompt = """
You are tasked with generating assessment questions for workers based on their SOPs. These questions should vary by assessment type (daily, weekly, biweekly), frequency number (e.g., day 2, week 3), and total duration (e.g., 6 weeks).
Guidelines:
1. Generate yes/no questions relevant to each worker's SOP based on their role.
2. Use frequency numbers as 1, 2, 3, etc., regardless of the type.
3. Tag each question with its topic area (e.g., communication, timeline).
4. The questions should evolve in detail as assessments progress over time.
Example response:
{
"questions": [
{
"frequency_number": "2",
"questions": [
{
"assigned_to": "John",
"role": "Data Analyst",
"question": "Is the dataset being cleaned according to the SOP?",
"area_tag": "data quality"
}
]
},
{
"frequency_number": "3",
"questions": [
{
"assigned_to": "Jane",
"role": "Data Scientist",
"question": "Are predictive models tested for accuracy before deployment?",
"area_tag": "model validation"
}
]
}
+54 -2
View File
@@ -13,6 +13,20 @@ def get_sop_extraction_from_doc():
Provide the extracted sections exactly as they appear in the document.'''
def get_roles_extraction_from_questionnaire():
return '''Your task is to extract the "Roles" from the provided questionnaire responses.
You must identify and categorize the roles based on the information provided.
Instructions:
1. **Roles**: Extract the roles mentioned in the questionnaire.
2. **Vision**: If applicable, extract the vision of the company or organization as it relates to the roles.
3. **Mission**: If applicable, extract the mission of the company or organization as it relates to the roles.
4. **Role-specific SOPs**:
- Identify any role-specific Standard Operating Procedures (SOPs) mentioned in the questionnaire.
- If SOPs for the role are not explicitly stated, infer them from the context, but only if there is clear evidence within the questionnaire. Do not generate or assume SOPs that are not directly supported by the information provided.
- If no roles or SOPs are found, return an empty list for each category.
Provide the extracted roles and any relevant sections exactly as they appear in the questionnaire.'''
def get_sop_personalassessment_from_questionnaire():
return '''Your task is to generate Standard Operating Procedures (SOPs) based on the responses to the questionnaire provided.
@@ -44,9 +58,11 @@ def get_sop_personalassessment_from_area_role(role,areas,sop_types):
Empty Lists: If no SOPs are generated, return an empty list for each category.
Format: The SOPs should be direct and concise.
"""
def get_sop_executive_from_vision_goals(executive):
return f"""Your task is to generate Standard Operating Procedures (SOPs) for executives namely:{executive} based on the provided vision and goals/mission.
return f"""Your task is to generate Standard Operating Procedures (SOPs) for the executive namely: {executive}, based on the provided vision and goals/mission.
You must extract and categorize the SOPs into three categories: "must," "shall," and "will."
Instructions:
@@ -59,7 +75,12 @@ def get_sop_executive_from_vision_goals(executive):
- If SOPs are not explicitly mentioned, infer them from the context of the vision and goals, but only if there is clear evidence. Do not generate or assume SOPs that are not directly supported by the information provided.
- If no SOPs can be generated, return an empty list for each category.
Provide the generated SOPs based on the vision and goals, focusing on executive-level responsibilities and actions."""
4. If the executive is specified as "Admin," meaning there is a single executive managing all workers and projects, use the vision and mission to generate SOPs.
5. Ensure that the generated SOPs can mention the company name if known from the document for better clarity.
6. For any exceutive provided , make sure sops is generated if mission and vision is provided
Provide the generated SOPs based on the vision and goals, focusing on executive-level responsibilities and actions"""
def get_vision_mission_extraction_from_doc():
return """Extract vision and mission statements from the document:
@@ -88,6 +109,7 @@ def get_vision_mission_extraction_from_doc():
- If SOPs for managers are not explicitly stated, infer them from the context provided by the executives, but only if there is clear evidence within the document.
- Do not generate or assume SOPs that are not directly supported by the document or the executive directives.
- If no SOPs are found for managers, return an empty list for each category.
- add header as the starting statment of the sop depending on who the sop is pointing too e.g "Under the inmsights amd control of the develpopment the admin:"
Provide the extracted sections exactly as they appear in the document.
'''
@@ -293,3 +315,33 @@ def get_sop_for_department_workers():
]
}
'''
def get_sop_for_department_workers():
return '''Generate SOPs for each worker under the unique department based on the information the workers info provided
Instructions:
1. Focus on the provided department and manager role.
2. Categorize SOPs into "must," "shall," and "will."
3. SOPs should be actionable and relevant to the worker's duties.
4. If no SOPs can be generated, return empty lists for each category.
5. Use the provided document and the workers and department information to generate the SOP.
6. If the provided document cannot provide SOPs for a specific worker stated, then return an empty list for the SOP for that worker.
Example forma
{
"departments": [
{
"name": "Department A",
"managers": [
{
"name": "Worker A",
"must": ["Conduct weekly meetings"],
"shall": ["Submit monthly reports"],
"will": ["Improve efficiency"]
}
]
}
]
}
'''
+4 -1
View File
@@ -22,6 +22,7 @@ class QuestionsGenerator:
assessment_type = input_data['assessment_type']
frequency_type = input_data['frequency_type']
total_duration = input_data['duration']
roles_data = input_data["roles_data"]
# Chunk the SOPs into smaller pieces
chunk_size = 1000 # Define your chunk size
@@ -47,7 +48,8 @@ class QuestionsGenerator:
{"role": "user", "content": f"Assessment Type: {assessment_type}"},
{"role": "user", "content": f"Frequency Type: {frequency_type}"},
{"role": "user", "content": f"Current Frequency Number to generate : {frequency_label}"},
{"role": "user", "content": f"Duration: {total_duration}"}
{"role": "user", "content": f"Duration: {total_duration}"},
{"role": "user", "content": f"roles data : {roles_data}"}
],
response_format=AssementQuestion, # Use the updated response schema
max_tokens=4096,
@@ -55,6 +57,7 @@ class QuestionsGenerator:
)
questions = json.loads(response.choices[0].message.content)
print(f"Generated questions: {questions}")
all_questions.append({
"frequency_number": frequency_label,
"questions": questions
+29
View File
@@ -321,3 +321,32 @@ class DocumentParser:
except json.JSONDecodeError:
return False
def extract_sops_for_managers_by_department(self, docs,depts_wmanagers):
"""
Extract sops for managers from the document.
:param docs: List of document chunks
:return: Dictionary containing departments, their managers,
"""
try:
docs_text = self._extract_text_from_docs(docs)
prompt = get_sop_for_department_workers() # 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": f"Mangers information: {depts_wmanagers}"},
{"role": "user", "content": [{"type": "text", "text": text} for text in docs_text]}
],
response_format=ManagerWithSOPs, # Use the updated response schema
max_tokens=4096,
temperature=0.1
)
return json.loads(response.choices[0].message.content)
except json.JSONDecodeError:
return False
+35 -3
View File
@@ -108,6 +108,37 @@ class SopPersonalAssessment:
except:
return False
def generate_roles_from_questionnaire(self, questionnaire_data: List[dict]) -> Roles_response:
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}''',
}
],
response_format=Roles_response,
max_tokens=1024,
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
class SopGeneratorExecutive:
@@ -116,7 +147,7 @@ class SopGeneratorExecutive:
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:
def extract_sops_from_executive_vision_goals_doc(self, data: dict,executive:str) -> SOPsResponse:
"""
Extracts SOPs categorized into 'must,' 'shall,' and 'will' based on executive vision and goals.
@@ -126,11 +157,12 @@ class SopGeneratorExecutive:
try:
vision = data.get("vision", "No vision provided")
goals = data.get("goals", "No goals provided")
goals = data.get("mission", "No goals provided")
prompt = get_sop_executive_from_vision_goals(executives)
prompt = get_sop_executive_from_vision_goals(executive)
user_content = f'''
Find the mission and vision provided below
Vision: {vision}
Goals: {goals}
'''
+17 -2
View File
@@ -25,7 +25,7 @@ response2 = bot.predict_next_n_assessment(
)
print(f"Predictions {response2}")
'''
from src.services.chatbot import Chatbot
company_info = {
@@ -40,8 +40,23 @@ response = bot.predict_based_on_past_assessment(
companyid="testid"
)
print(f"Result: {response}")
print(f"Result: {response}")'''
from src.services.sop_document_parser import DocumentParser
from src.utils.document_loader import load_document
path = r"/root/ds_erp_ai/data/raw/test_sop.pdf"
parser = DocumentParser()
workers_department = [
{"name": "sales", "workers": ["sales manager"]},
{"name": "development", "workers": ["deployment officer"]}
]
res = parser.extract_sops_for_workers_by_department(
docs=load_document(path), # Load the document for processing
depts_workers=workers_department
)
print(res)