File size: 7,479 Bytes
cbe7195
fc8383a
 
6577f0c
367325c
7d587e9
fc8383a
5315b13
 
ccb31be
5315b13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f9f1fdb
 
 
 
 
5315b13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f9f1fdb
 
 
 
 
5315b13
 
 
 
 
 
ccb31be
cbe7195
 
e8a4040
 
7d587e9
fc8383a
395ca0b
 
cbe7195
395ca0b
 
 
cbe7195
5315b13
cbe7195
 
395ca0b
cbe7195
 
 
 
 
 
 
 
58d0306
ccb5208
f9f1fdb
 
 
 
 
ccb5208
 
cbe7195
 
 
 
 
 
 
 
 
 
 
 
f9f1fdb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
import streamlit as st
import requests
from fpdf import FPDF
import os
import time
from datetime import datetime

# Mistral API key (replace with your key or use environment variable)
api_key = os.getenv("MISTRAL_API_KEY", "gz6lDXokxgR6cLY72oomALWcm7vhjRzQ")

# Function to call Mistral API with rate limit handling
def call_mistral_api(prompt):
    url = "https://api.mistral.ai/v1/chat/completions"
    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json"
    }
    payload = {
        "model": "mistral-medium",
        "messages": [
            {"role": "user", "content": prompt}
        ]
    }
    try:
        response = requests.post(url, headers=headers, json=payload)
        response.raise_for_status()  # Raise an error for bad status codes
        return response.json()['choices'][0]['message']['content']
    except requests.exceptions.HTTPError as err:
        if response.status_code == 429:  # Rate limit exceeded
            st.warning("Rate limit exceeded. Please wait a few seconds and try again.")
            time.sleep(5)  # Wait for 5 seconds before retrying
            return call_mistral_api(prompt)  # Retry the request
        return f"HTTP Error: {err}"
    except Exception as err:
        return f"Error: {err}"

# Function to analyze a single requirement
def analyze_requirement(requirement):
    # Detect requirement type
    type_prompt = f"Classify the following requirement as Functional or Non-Functional:\n\n{requirement}\n\nType:"
    req_type = call_mistral_api(type_prompt)

    # Identify stakeholders
    stakeholders_prompt = f"Identify the stakeholders for the following requirement:\n\n{requirement}\n\nStakeholders:"
    stakeholders = call_mistral_api(stakeholders_prompt)

    # Classify domain
    domain_prompt = f"Classify the domain for the following requirement (e.g., Bank, Healthcare, etc.):\n\n{requirement}\n\nDomain:"
    domain = call_mistral_api(domain_prompt)

    # Detect defects
    defects_prompt = f"""Analyze the following requirement and identify ONLY MAJOR defects (e.g., Ambiguity, Incompleteness, etc.). 
    If the requirement is clear and complete, respond with 'No defects.' 
    Requirement: {requirement}
    Defects:"""
    defects = call_mistral_api(defects_prompt)

    # Rewrite requirement
    rewritten = rewrite_requirement(requirement, defects)

    return {
        "Requirement": requirement,
        "Type": req_type,
        "Stakeholders": stakeholders,
        "Domain": domain,
        "Defects": defects,
        "Rewritten": rewritten
    }

# Function to rewrite requirement concisely
def rewrite_requirement(requirement, defects):
    if "no defects" in defects.lower():
        return "No modification needed."

    # If defects are found, generate a concise and clear rewritten requirement
    prompt = f"""Rewrite the following requirement to address the defects listed below. Ensure the rewritten requirement is clear, concise, and free of defects. It should be no more than 1-2 sentences.
    
    Original Requirement: {requirement}
    
    Defects: {defects}
    
    Rewritten Requirement:"""
    response = call_mistral_api(prompt)
    return response.strip()

# Function to generate a PDF report with professional formatting
def generate_pdf_report(results):
    pdf = FPDF()
    pdf.add_page()
    pdf.set_font("Arial", size=12)

    # Add watermark
    pdf.set_font("Arial", 'B', 50)
    pdf.set_text_color(230, 230, 230)  # Light gray color for watermark
    pdf.rotate(45)  # Rotate the text for watermark effect
    pdf.text(60, 150, "AI Powered Requirement Analysis")
    pdf.rotate(0)  # Reset rotation

    # Add title and date/time
    pdf.set_font("Arial", 'B', 16)
    pdf.set_text_color(0, 0, 0)  # Black color for title
    pdf.cell(200, 10, txt="AI Powered Requirement Analysis and Defect Detection using LLM Model Mistral", ln=True, align='C')
    pdf.set_font("Arial", size=12)
    pdf.cell(200, 10, txt=f"Report Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", ln=True, align='C')
    pdf.ln(10)  # Add some space

    # Add requirements analysis
    pdf.set_font("Arial", size=12)
    for i, result in enumerate(results, start=1):
        # Check if we need a new page
        if pdf.get_y() > 250:  # If the content is near the bottom of the page
            pdf.add_page()  # Add a new page
            pdf.set_font("Arial", 'B', 16)
            pdf.cell(200, 10, txt="AI Powered Requirement Analysis and Defect Detection using LLM Model Mistral", ln=True, align='C')
            pdf.set_font("Arial", size=12)
            pdf.cell(200, 10, txt=f"Report Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", ln=True, align='C')
            pdf.ln(10)  # Add some space

        # Add requirement details
        pdf.set_font("Arial", 'B', 14)
        pdf.multi_cell(200, 10, txt=f"Requirement R{i}: {result['Requirement']}", align='L')
        pdf.set_font("Arial", size=12)
        pdf.multi_cell(200, 10, txt=f"Type: {result['Type']}", align='L')
        pdf.multi_cell(200, 10, txt=f"Stakeholders: {result['Stakeholders']}", align='L')
        pdf.multi_cell(200, 10, txt=f"Domain: {result['Domain']}", align='L')
        pdf.multi_cell(200, 10, txt=f"Defects: {result['Defects']}", align='L')
        pdf.multi_cell(200, 10, txt=f"Rewritten: {result['Rewritten']}", align='L')
        pdf.multi_cell(200, 10, txt="-" * 50, align='L')
        pdf.ln(5)  # Add some space between requirements

    pdf_output = "requirements_report.pdf"
    pdf.output(pdf_output)
    return pdf_output

# Streamlit app
def main():
    st.title("AI Powered Requirement Analysis and Defect Detection using Large Language Model Mistral")
    st.markdown("**Team Name:** Sadia, Areeba, Rabbia, Tesmia")
    st.markdown("**Model:** Mistral")

    # Input requirements manually
    input_text = st.text_area("Enter your requirements (one per line or separated by periods):")
    requirements = []
    if input_text:
        # Split by periods or newlines
        requirements = [req.strip() for req in input_text.replace("\n", ".").split(".") if req.strip()]

    # Analyze requirements
    if st.button("Analyze Requirements"):
        if not requirements:
            st.warning("Please enter requirements.")
        else:
            results = []
            for req in requirements:
                if req.strip():  # Ignore empty lines
                    results.append(analyze_requirement(req.strip()))

            # Display results
            st.subheader("Analysis Results")
            for i, result in enumerate(results, start=1):
                st.write(f"### Requirement R{i}: {result['Requirement']}")
                st.write(f"**Type:** {result['Type']}")
                st.write(f"**Stakeholders:** {result['Stakeholders']}")
                st.write(f"**Domain:** {result['Domain']}")
                st.write(f"**Defects:** {result['Defects']}")
                st.write(f"**Rewritten:** {result['Rewritten']}")
                st.write("---")

            # Generate and download PDF report
            pdf_report = generate_pdf_report(results)
            with open(pdf_report, "rb") as f:
                st.download_button(
                    label="Download PDF Report",
                    data=f,
                    file_name="requirements_report.pdf",
                    mime="application/pdf"
                )

# Run the app
if __name__ == "__main__":
    main()