File size: 12,515 Bytes
13b0d84
 
 
 
 
 
 
 
b9f50c4
bbcebab
 
13b0d84
 
 
 
b9f50c4
13b0d84
 
 
 
 
 
 
 
b9f50c4
 
 
13b0d84
 
 
a7d9568
13b0d84
b9f50c4
a7d9568
b9f50c4
a7d9568
 
b9f50c4
13b0d84
 
 
b9f50c4
13b0d84
 
 
a7d9568
b9f50c4
 
 
13b0d84
 
 
b9f50c4
13b0d84
 
a7d9568
13b0d84
bee80d0
 
 
 
 
 
 
019bd86
 
 
 
bee80d0
3c29a3b
 
bee80d0
3c29a3b
 
bee80d0
 
 
 
 
019bd86
bee80d0
 
 
62dccbc
600d7ee
0dd0355
13b0d84
 
0dd0355
 
2861eea
b9f50c4
2861eea
 
 
 
 
 
b9f50c4
2861eea
 
b9f50c4
2861eea
 
b9f50c4
2861eea
 
b9f50c4
2861eea
 
b9f50c4
2861eea
b9f50c4
2861eea
 
b9f50c4
0dd0355
 
 
 
 
 
 
 
 
 
 
b9f50c4
0dd0355
 
 
13b0d84
a7d9568
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90ef643
a7d9568
 
 
 
 
 
 
 
90ef643
3c29a3b
a7d9568
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13b0d84
a7d9568
3c53d65
 
a3569ed
3c53d65
 
a3569ed
3c53d65
 
 
 
 
 
 
b9f50c4
a7d9568
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3c29a3b
a7d9568
 
 
 
3c29a3b
a7d9568
 
 
 
bee80d0
 
 
 
 
 
 
 
 
 
9ab88db
bee80d0
 
9ab88db
bee80d0
019bd86
 
 
77fef6a
9ab88db
bee80d0
77fef6a
9ab88db
bee80d0
 
 
 
a7d9568
600d7ee
0dd0355
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a7d9568
7a18fc3
 
 
 
 
 
 
 
c87b45b
 
 
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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
import streamlit as st
import requests
from fpdf import FPDF
import os
import time
from datetime import datetime
import groq

# API keys (replace with your keys or use environment variables)
mistral_api_key = os.getenv("MISTRAL_API_KEY", "gz6lDXokxgR6cLY72oomALWcm7vhjRzQ")
groq_api_key = os.getenv("GROQ_API_KEY", "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")

# Initialize Groq client
groq_client = groq.Client(api_key=groq_api_key)

# Function to call Mistral API
def call_mistral_api(prompt):
    url = "https://api.mistral.ai/v1/chat/completions"
    headers = {
        "Authorization": f"Bearer {mistral_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()
        return response.json()['choices'][0]['message']['content']
    except requests.exceptions.HTTPError as err:
        if response.status_code == 429:
            st.warning("Rate limit exceeded. Please wait a few seconds and try again.")
            time.sleep(5)
            return call_mistral_api(prompt)
        return f"HTTP Error: {err}"
    except Exception as err:
        return f"Error: {err}"

# Function to call Groq API
def call_groq_api(prompt):
    try:
        response = groq_client.chat.completions.create(
            model="llama3-70b-8192",
            messages=[
                {"role": "user", "content": prompt}
            ]
        )
        return response.choices[0].message.content
    except Exception as err:
        st.error(f"Error: {err}")
        return f"Error: {err}"

# Function to analyze a single requirement
def analyze_requirement(requirement):
    # Use Mistral for classification and domain identification
    type_prompt = f"Classify the following requirement as Functional or Non-Functional in one word:\n\n{requirement}\n\nType:"
    req_type = call_mistral_api(type_prompt).strip()

    domain_prompt = f"Classify the domain for the following requirement in one word (e.g., E-commerce, Education, etc.):\n\n{requirement}\n\nDomain:"
    domain = call_mistral_api(domain_prompt).strip()

    stakeholder_prompt = f"""Identify key major stakeholders for this requirement. Provide a comma-separated list of roles.
    Examples: Users, Administrators, Developers, Security Team. Requirement:\n\n{requirement}\n\nStakeholders:"""
    stakeholders = call_groq_api(stakeholder_prompt).strip()
    
    # Use Groq for defect analysis and rewriting
    defects_prompt = f"""List ONLY the major defects in the following requirement (e.g., Ambiguity, Incompleteness, etc.) in 1-2 words each:\n\n{requirement}\n\nDefects:"""
    defects = call_groq_api(defects_prompt).strip()

    rewritten_prompt = f"""Rewrite the following requirement in 1-2 sentences to address the defects:\n\n{requirement}\n\nRewritten:"""
    rewritten = call_groq_api(rewritten_prompt).strip()

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

# Function to generate a PDF report
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", 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):
        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", 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"Domain: {result['Domain']}", align='L')
        pdf.multi_cell(200, 10, txt=f"Stakeholders: {result['Stakeholders']}", 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

# Custom CSS for professional styling
st.markdown("""
    <style>
        .main {
            background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
        }
        .stApp {
            max-width: 1200px;
            margin: 0 auto;
            padding: 2rem;
        }
        .header {
            text-align: center;
            padding: 2rem;
            background: white;
            border-radius: 15px;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
            margin-bottom: 2rem;
            border: 1px solid #e0e0e0;
        }
        .requirement-card {
            background: white;
            padding: 1.5rem;
            border-radius: 10px;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
            margin-bottom: 1.5rem;
            transition: transform 0.2s;
            color: #333333;

        }
        .requirement-card:hover {
            transform: translateY(-3px);
        }
        .analysis-badge {
            padding: 0.5rem 1rem;
            border-radius: 20px;
            font-weight: 500;
            margin: 0.3rem;
        }
        .download-btn {
            width: 100%;
            padding: 1rem;
            font-size: 1.1rem;
            margin-top: 2rem;
        }
        .type-functional { background: #e8f5e9; color: #2e7d32; }
        .type-non-functional { background: #fff3e0; color: #ef6c00; }
        .defect-badge { background: #ffebee; color: #c62828; }
        .improved-badge { background: #e3f2fd; color: #1565c0; }
    </style>
""", unsafe_allow_html=True)

def main():
    # Professional Header Section
    with st.container():
        st.markdown('<div class="header">', unsafe_allow_html=True)
        st.title("πŸ“ AI-Based Requirement Defect Detection Using Large Language Models (LLMs)")
        st.markdown("""
            <div style="margin: 1.5rem 0;">
                <div style="font-size: 1.2rem; color: #4a4a4a;">Automated Requirement Classification, Defect Detection & Optimization</div>
                <div style="display: flex; justify-content: center; gap: 1rem; margin: 1rem 0;">
                    <div style="padding: 0.5rem 1rem; background: #f0f2f6;color: black; border-radius: 20px;">Team: Sadia, Areeba, Rabbia, Tesmia</div>
                    <div style="padding: 0.5rem 1rem; background: #f0f2f6; color: black; border-radius: 20px;">Mistral + Groq API</div>
                </div>
            </div>
        """, unsafe_allow_html=True)
        st.markdown('</div>', unsafe_allow_html=True)

    # Input Section
    with st.container():
        st.subheader("πŸ“₯ Input Requirements")
        input_text = st.text_area(
            "Enter your software requirements (one per line or separated by periods):",
            height=200,
            placeholder="Example:\nThe system shall allow users to reset their password via email verification.\nThe interface must load within 2 seconds of user interaction...",
            help="Enter each requirement on a new line or separate with periods."
        )

    # Analysis Section
    if st.button("πŸš€ Start Analysis", type="primary", use_container_width=True):
        if not input_text.strip():
            st.warning("⚠️ Please enter requirements to analyze")
        else:
            with st.spinner("πŸ” Analyzing requirements..."):
                requirements = [req.strip() for req in input_text.replace("\n", ".").split(".") if req.strip()]
                results = []

                progress_bar = st.progress(0)
                for i, req in enumerate(requirements):
                    results.append(analyze_requirement(req))
                    progress_bar.progress((i+1)/len(requirements))

                st.success("βœ… Analysis Completed!")
                time.sleep(0.5)
                st.session_state.results = results

    # Display Results
    if 'results' in st.session_state:
        st.subheader("πŸ“Š Analysis Results")
        with st.container():
            for i, result in enumerate(st.session_state.results, 1):
                with st.expander(f"Requirement #{i}: {result['Requirement'][:50]}...", expanded=True):
                    st.markdown(f"""
                        <div class="requirement-card">
                            <div style="margin-bottom: 1.5rem;">
                                <div class="analysis-badge { 'type-functional' if 'functional' in result['Type'].lower() else 'type-non-functional' }">
                                    πŸ“Œ <b>Type:</b> {result['Type']}
                                </div>
                                <div class="analysis-badge" style="background: #e8eaf6; color: #303f9f;">
                                    🏷️ <b>Domain:</b> {result['Domain']}
                                </div>
                                <div class="analysis-badge" style="background: #e0f2f1; color: #00796b;">
                                    πŸ‘₯ <b>Stakeholders:</b> {result['Stakeholders']}
                                </div>
                                <div class="analysis-badge" style="background: #b39ddb; color: purple;">
                                    πŸ”Ž <b>Identified Defects:</b><br> Explanation: {result['Defects']}
                                </div>
                                <div class="analysis-badge" style="background: #8c9eff; color: blue;">
                                    ✨ <b>Improved Version:</b><br> Explanation: {result['Rewritten']}
                                </div>
                            </div>
                        </div>
                    """, unsafe_allow_html=True)

        # PDF Report Section
        st.subheader("πŸ“€ Generate Report")
        with st.container():
            col1, col2 = st.columns([3, 2])
            with col1:
                st.info("πŸ’‘ Click below to generate a comprehensive PDF report with all analysis details")
            with col2:
                if st.button("πŸ“„ Generate PDF Report", type="secondary", use_container_width=True):
                    with st.spinner("Generating PDF..."):
                        pdf_report = generate_pdf_report(st.session_state.results)
                        with open(pdf_report, "rb") as f:
                            st.download_button(
                                label="⬇️ Download Full Report",
                                data=f,
                                file_name="Requirement_Analysis_Report.pdf",
                                mime="application/pdf",
                                use_container_width=True,
                                type="primary"
                            )

    # Footer
    st.markdown("---")
    st.markdown("""
        <div style="text-align: center; color: #666; margin-top: 3rem;">
            <p>AI-Powered Requirement Analysis System</p>
            <p>πŸš€ Powered by Mistral AI & Groq β€’ πŸ› οΈ Developed by Team Four</p>
        </div>
    """, unsafe_allow_html=True)

if __name__ == "__main__":
    main()