File size: 12,573 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
 
 
 
 
 
 
 
8596705
 
 
 
 
bee80d0
8596705
 
 
 
 
bee80d0
 
 
 
 
 
 
 
62dccbc
b9f50c4
13b0d84
 
 
 
b9f50c4
 
 
a7d9568
 
b9f50c4
a7d9568
b9f50c4
 
 
a7d9568
b9f50c4
 
 
a7d9568
b9f50c4
 
 
 
a7d9568
 
b9f50c4
 
 
 
a7d9568
b9f50c4
 
 
 
 
 
 
 
 
a7d9568
b9f50c4
13b0d84
 
 
 
a7d9568
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90ef643
a7d9568
 
 
 
 
 
 
 
90ef643
9e947fe
a7d9568
 
 
 
 
 
 
 
 
 
8596705
 
 
 
 
 
 
 
 
a7d9568
 
 
 
 
 
 
 
 
 
 
 
 
13b0d84
a7d9568
3c53d65
 
 
 
 
 
 
 
 
 
 
 
 
b9f50c4
a7d9568
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bee80d0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8596705
bee80d0
 
 
 
 
 
 
 
 
 
 
a7d9568
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
288
289
290
291
292
293
294
295
296
297
298
299
300
301
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()

    # Use Groq for defect analysis and rewriting
    defects_prompt = f"""List ONLY the major defects in the following requirement as comma-separated values (1-2 words each). Valid options: Ambiguity, Vagueness, Incompleteness, Volatility, Unverifiability. Do NOT add explanations:
    {requirement}
    Defects:"""
    defects = defects.split(":")[-1].strip() if ":" in defects else defects
    defects = defects.replace("Defects", "").strip()

    rewritten_prompt = f"""Rewrite the following requirement in 1-2 sentences to address defects. Start directly with "The project shall..." without preamble:
    {requirement}
    Improved:"""
    rewritten = rewritten.split(":")[-1].strip() if ":" in rewritten else rewritten
    rewritten = rewritten.replace("Rewritten", "").replace("Improved", "").strip()

    return {
        "Requirement": requirement,
        "Type": req_type,
        "Domain": domain,
        "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)
    pdf.rotate(45)
    pdf.text(60, 150, "AI Powered Requirement Analysis")
    pdf.rotate(0)

    # Add title and date/time
    pdf.set_font("Arial", 'B', 16)
    pdf.set_text_color(0, 0, 0)
    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 requirements analysis
    pdf.set_font("Arial", size=12)
    for i, result in enumerate(results, start=1):
        if pdf.get_y() > 250:
            pdf.add_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)

        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"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)

    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;
        }
        .defect-badge { 
            white-space: nowrap;
            margin: 0.2rem 0.3rem !important;
        }
        .improved-badge {
            line-height: 1.5;
            text-align: left;
            width: 100%;
        }
        .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-Powered Requirement Analysis System")
        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' }">
                                    πŸ“Œ Type: {result['Type']}
                                </div>
                                <div class="analysis-badge" style="background: #e8eaf6; color: #303f9f;">
                                    🏷️ Domain: {result['Domain']}
                                </div>
                            </div>
                            
                            <div style="margin: 1rem 0;">
                                <h4>πŸ”Ž Identified Issues</h4>
                                <div style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
                                    {''.join([f'<div class="analysis-badge defect-badge">⚠️ {d}</div>' 
                                            for d in result['Defects'].split(', ') if d.strip()])
                                </div>
                            </div>
                            
                            <div style="margin: 1rem 0;">
                                <h4>✨ Improved Version</h4>
                                <div class="analysis-badge improved-badge">
                                    πŸ“ {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 β€’ Final Year Project β€’ Computer Science Department</p>
            <p>πŸš€ Powered by Mistral AI & Groq β€’ πŸ› οΈ Developed by Team Four</p>
        </div>
    """, unsafe_allow_html=True)

if __name__ == "__main__":
    main()