diff --git a/data/raw/coding_task_completion_document.pdf b/data/raw/coding_task_completion_document.pdf new file mode 100644 index 0000000..eb08e59 --- /dev/null +++ b/data/raw/coding_task_completion_document.pdf @@ -0,0 +1,81 @@ +%PDF-1.3 +3 0 obj +<> +endobj +4 0 obj +<> +stream +xmOo0 L^agG'Ljd|KEPD +YB!#Q$A:)vB;#AM0Zc:pl+Z8 MMDh$؆f85O8"H5M(t@jә7gÑBq&2Irwbtݤ߮o +Y3pn:}¬,DXwVL ɑEM%ͣ ψ@a|xt<3:50PA 2i$=33@RuOCerp2{VdWID |[ZGÁJF_ y^jx!* +endstream +endobj +1 0 obj +<> +endobj +5 0 obj +<> +endobj +6 0 obj +<> +endobj +2 0 obj +<< +/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] +/Font << +/F1 5 0 R +/F2 6 0 R +>> +/XObject << +>> +>> +endobj +7 0 obj +<< +/Producer (PyFPDF 1.7.2 http://pyfpdf.googlecode.com/) +/CreationDate (D:20240910213710) +>> +endobj +8 0 obj +<< +/Type /Catalog +/Pages 1 0 R +/OpenAction [3 0 R /FitH null] +/PageLayout /OneColumn +>> +endobj +xref +0 9 +0000000000 65535 f +0000000606 00000 n +0000000890 00000 n +0000000009 00000 n +0000000087 00000 n +0000000693 00000 n +0000000794 00000 n +0000001004 00000 n +0000001113 00000 n +trailer +<< +/Size 9 +/Root 8 0 R +/Info 7 0 R +>> +startxref +1216 +%%EOF diff --git a/src/api/app.py b/src/api/app.py index e18c868..8d580b6 100644 --- a/src/api/app.py +++ b/src/api/app.py @@ -2,6 +2,7 @@ import os from flask import Flask from src.api.routes.sops import sops_bp from src.api.routes.questions import qs_b +from src.api.routes.chatbot import bot def create_app(): app = Flask(__name__) @@ -9,6 +10,7 @@ def create_app(): # Register the blueprint with the desired prefix app.register_blueprint(sops_bp, url_prefix='/api/v1/sop') app.register_blueprint(qs_b,url_prefix='/api/v1/qs') + app.register_blueprint(bot,url_prefix='/api/v1/bot') # Set up the upload folder configuration inside the src directory UPLOAD_FOLDER = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../uploads') diff --git a/src/api/routes/chatbot.py b/src/api/routes/chatbot.py new file mode 100644 index 0000000..56b35d1 --- /dev/null +++ b/src/api/routes/chatbot.py @@ -0,0 +1,61 @@ +import os +from flask import Blueprint, request, jsonify, current_app +from werkzeug.utils import secure_filename +from src.services.chatbot import Chatbot +from src.utils.utils import delete_all_files_in_directory +from src.utils.document_loader import load_document + + +# Initialize the Blueprint +bot = Blueprint('chatbot', __name__) + +# Allowed file extensions +ALLOWED_EXTENSIONS = {'pdf', 'doc', 'docx'} + +def allowed_file(filename): + """Check if the file has an allowed extension.""" + return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS + +@bot.route('/validate_worker_document', methods=['POST']) +def validate_worker_document(): + try: + # Retrieve form data + question = request.form.get('question') + file = request.files.get('document') + + if not question or not file: + return jsonify({"error": "Missing data", "message": "Question or document not provided."}), 400 + + if file.filename == '': + return jsonify({"error": "No selected file", "message": "No file was selected for upload."}), 400 + + if file and allowed_file(file.filename): + # Secure the file name and save it + filename = secure_filename(file.filename) + upload_folder = current_app.config['UPLOAD_FOLDER'] + file_path = os.path.join(upload_folder, filename) + file.save(file_path) + + # Load the document for processing + docs = load_document(file_path) + + # Instantiate the chatbot service + chatbot = Chatbot() + + # Validate the worker's response using the provided document + validation_result = chatbot.validate_worker(question, docs) + + if not validation_result: + return jsonify({"error": "Validation failed", "message": "Validation process failed."}), 400 + + # Clean up uploaded file (optional) + os.remove(file_path) + + # Return the validation result + return jsonify({"result": validation_result["result"]}), 200 + + else: + return jsonify({"error": "Invalid file", "message": "File format not supported."}), 400 + + except Exception as e: + return jsonify({"error": "Internal Server Error", "message": str(e)}), 500 diff --git a/src/models/bot_response_schema.py b/src/models/bot_response_schema.py new file mode 100644 index 0000000..22b0560 --- /dev/null +++ b/src/models/bot_response_schema.py @@ -0,0 +1,7 @@ + +from pydantic import BaseModel +from typing import List, Dict + +class ValidateWorker(BaseModel): + result:str + \ No newline at end of file diff --git a/src/prompts/chatbot.py b/src/prompts/chatbot.py new file mode 100644 index 0000000..847f3ee --- /dev/null +++ b/src/prompts/chatbot.py @@ -0,0 +1,18 @@ +def validate_worker_prompt() -> str: + return """ + You are a worker in the company "Validate" where you are asked a specific yes or no question: + + The worker's response: "Yes" + + Since the worker answered "Yes," they are required to submit a document to justify their answer. + + Your role is to analyze the question being asked, review the document the worker uploaded, and verify whether the worker's answer is valid or not. + The goal is to assess the document's content to see if it aligns with the worker's claim of "Yes." + + response format + if not validated return "not validated" + { + result:"validated" + } + """ + \ No newline at end of file diff --git a/src/services/chatbot.py b/src/services/chatbot.py new file mode 100644 index 0000000..d9cffbd --- /dev/null +++ b/src/services/chatbot.py @@ -0,0 +1,66 @@ +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.prompts.chatbot import * +from src.models.sop_response_schemas import * +from src.models.bot_response_schema import * +from dotenv import load_dotenv +load_dotenv() + + +#SopGeneratorDocument +class Chatbot: + 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_text_from_docs(self, docs): + """Extract text content from document objects.""" + return [doc.page_content for doc in docs] + # Existing methods... + + def validate_worker(self, question, docs) -> VisionMissionResponse: + """ + This method is responsible for validating the worker's response ("yes" or "no") using the provided document(s). + The system generates a prompt, extracts document content, and validates the response using the GPT-4 model. + + :param question: The yes/no question asked to the worker. + :param docs: A list of document(s) uploaded by the worker. + :return: VisionMissionResponse containing the validated result or None if an error occurs. + """ + try: + docs_text = self._extract_text_from_docs(docs) + prompt = validate_worker_prompt() + response = self.client.beta.chat.completions.parse( + model=self.model, + messages=[ + { + "role": "system", + "content": f'''{prompt} The document is uploaded next.''' + }, + { + "role": "user", + "content": f"Question :{question}", + }, + { + "role": "user", + "content": [{"type": "text", "text": text} for text in docs_text], + } + ], + response_format=ValidateWorker, + 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 Exception as e: + print(f"An error occurred: {e}") + return None diff --git a/test.py b/test.py index c176cd9..4cbb3f2 100644 --- a/test.py +++ b/test.py @@ -1,72 +1,16 @@ -import json -from src.services.questions_generator import QuestionsGenerator +# Example usage of the Chatbot class: +from src.services.chatbot import Chatbot +from src.utils.document_loader import load_document +if __name__ == "__main__": + chatbot = Chatbot() -# Mocking the SOPs input as described in your example -mock_sops_input = { - "sops": { - "departments": [ - { - "name": "Accounts Receivable", - "workers": [ - { - "name": "Angela Lewis", - "position": "AR Director", - "sops": { - "must": [], - "shall": [], - "will": [] - } - }, - { - "name": "Jamie Vega", - "position": "AR Supervisor", - "sops": { - "must": [ - "Provide escalation information to the AR Director if additional escalations are needed." - ], - "shall": [], - "will": [] - } - }, - { - "name": "Jessica Merzougui", - "position": "AR Supervisor", - "sops": { - "must": [ - "Provide escalation information to the AR Director if additional escalations are needed." - ], - "shall": [], - "will": [] - } - }, - { - "name": "Deniece Santos", - "position": "AR Analyst", - "sops": { - "must": [], - "shall": [], - "will": [] - } - } - ] - } - ] - } -} + # Example inputs + path = r"C:\Users\User\Desktop\Blessing_AI\MKD\test_erp_ai\erp_ai\test\erp_ai\data\raw\coding_task_completion_document.pdf" -# Defining the full input data including additional parameters -input_data = { - "sops": json.dumps(mock_sops_input), # Convert SOPs to JSON string format - "assessment_type": "progress", # Set the assessment type - "frequency_type": "weekly", # Set the frequency type (daily, weekly, etc.) - "duration": 4 # Set the duration (number of frequency cycles, e.g., 4 weeks) -} + question = "Have you completed Task X?" + user_input = "Yes" + docs = load_document(path) -# Initialize the QuestionsGenerator -generator = QuestionsGenerator() - -# Invoke the generate_questions method with the mock input -questions_response = generator.generate_questions(input_data) - -# Print the generated questions response -print(json.dumps(questions_response, indent=4)) + # Validate the worker's answer using the provided document + validation_result = chatbot.validate_worker(question, docs) + print(validation_result) \ No newline at end of file