iisadia commited on
Commit
a7d9568
Β·
verified Β·
1 Parent(s): b9f50c4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +163 -186
app.py CHANGED
@@ -7,73 +7,12 @@ from datetime import datetime
7
  import groq
8
 
9
  # API keys (replace with your keys or use environment variables)
10
- mistral_api_key = os.getenv("MISTRAL_API_KEY", "gz6lDXokxgR6cLY72oomALWcm7vhjRzQ")
11
- groq_api_key = os.getenv("GROQ_API_KEY", "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")
12
 
13
  # Initialize Groq client
14
  groq_client = groq.Client(api_key=groq_api_key)
15
 
16
- # Custom CSS for professional styling
17
- st.markdown("""
18
- <style>
19
- .main {
20
- background-color: #f8f9fa;
21
- }
22
- .stTextArea textarea {
23
- border: 2px solid #4a4e69;
24
- border-radius: 10px;
25
- padding: 15px !important;
26
- }
27
- .stButton button {
28
- background-color: #4a4e69;
29
- color: white;
30
- border: none;
31
- padding: 12px 30px;
32
- border-radius: 8px;
33
- font-size: 16px;
34
- font-weight: bold;
35
- transition: all 0.3s ease;
36
- width: 100%;
37
- }
38
- .stButton button:hover {
39
- background-color: #3a3e59;
40
- transform: scale(1.02);
41
- }
42
- .report-title {
43
- color: #4a4e69;
44
- font-size: 2.5em;
45
- text-align: center;
46
- padding: 20px;
47
- border-bottom: 3px solid #4a4e69;
48
- margin-bottom: 30px;
49
- }
50
- .requirement-card {
51
- background: white;
52
- border-radius: 15px;
53
- padding: 25px;
54
- margin: 15px 0;
55
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
56
- border-left: 5px solid #4a4e69;
57
- }
58
- .sidebar .sidebar-content {
59
- background-color: #4a4e69;
60
- color: white;
61
- }
62
- .metric-box {
63
- background: white;
64
- padding: 15px;
65
- border-radius: 10px;
66
- margin: 10px 0;
67
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
68
- }
69
- .stSpinner > div {
70
- display: flex;
71
- justify-content: center;
72
- align-items: center;
73
- }
74
- </style>
75
- """, unsafe_allow_html=True)
76
-
77
  # Function to call Mistral API
78
  def call_mistral_api(prompt):
79
  url = "https://api.mistral.ai/v1/chat/completions"
@@ -89,13 +28,13 @@ def call_mistral_api(prompt):
89
  }
90
  try:
91
  response = requests.post(url, headers=headers, json=payload)
92
- response.raise_for_status() # Raise an error for bad status codes
93
  return response.json()['choices'][0]['message']['content']
94
  except requests.exceptions.HTTPError as err:
95
- if response.status_code == 429: # Rate limit exceeded
96
  st.warning("Rate limit exceeded. Please wait a few seconds and try again.")
97
- time.sleep(5) # Wait for 5 seconds before retrying
98
- return call_mistral_api(prompt) # Retry the request
99
  return f"HTTP Error: {err}"
100
  except Exception as err:
101
  return f"Error: {err}"
@@ -104,7 +43,7 @@ def call_mistral_api(prompt):
104
  def call_groq_api(prompt):
105
  try:
106
  response = groq_client.chat.completions.create(
107
- model="llama-3.3-70b-versatile", # Correct model name
108
  messages=[
109
  {"role": "user", "content": prompt}
110
  ]
@@ -114,7 +53,7 @@ def call_groq_api(prompt):
114
  st.error(f"Error: {err}")
115
  return f"Error: {err}"
116
 
117
- # Function to analyze a single requirement using both models
118
  def analyze_requirement(requirement):
119
  # Use Mistral for classification and domain identification
120
  type_prompt = f"Classify the following requirement as Functional or Non-Functional in one word:\n\n{requirement}\n\nType:"
@@ -146,31 +85,30 @@ def generate_pdf_report(results):
146
 
147
  # Add watermark
148
  pdf.set_font("Arial", 'B', 50)
149
- pdf.set_text_color(230, 230, 230) # Light gray color for watermark
150
- pdf.rotate(45) # Rotate the text for watermark effect
151
  pdf.text(60, 150, "AI Powered Requirement Analysis")
152
- pdf.rotate(0) # Reset rotation
153
 
154
  # Add title and date/time
155
  pdf.set_font("Arial", 'B', 16)
156
- pdf.set_text_color(0, 0, 0) # Black color for title
157
  pdf.cell(200, 10, txt="AI Powered Requirement Analysis and Defect Detection", ln=True, align='C')
158
  pdf.set_font("Arial", size=12)
159
  pdf.cell(200, 10, txt=f"Report Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", ln=True, align='C')
160
- pdf.ln(10) # Add some space
161
 
162
  # Add requirements analysis
163
  pdf.set_font("Arial", size=12)
164
  for i, result in enumerate(results, start=1):
165
- if pdf.get_y() > 250: # If the content is near the bottom of the page
166
- pdf.add_page() # Add a new page
167
  pdf.set_font("Arial", 'B', 16)
168
  pdf.cell(200, 10, txt="AI Powered Requirement Analysis and Defect Detection", ln=True, align='C')
169
  pdf.set_font("Arial", size=12)
170
  pdf.cell(200, 10, txt=f"Report Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", ln=True, align='C')
171
- pdf.ln(10) # Add some space
172
 
173
- # Add requirement details
174
  pdf.set_font("Arial", 'B', 14)
175
  pdf.multi_cell(200, 10, txt=f"Requirement R{i}: {result['Requirement']}", align='L')
176
  pdf.set_font("Arial", size=12)
@@ -179,128 +117,167 @@ def generate_pdf_report(results):
179
  pdf.multi_cell(200, 10, txt=f"Defects: {result['Defects']}", align='L')
180
  pdf.multi_cell(200, 10, txt=f"Rewritten: {result['Rewritten']}", align='L')
181
  pdf.multi_cell(200, 10, txt="-" * 50, align='L')
182
- pdf.ln(5) # Add some space between requirements
183
 
184
  pdf_output = "requirements_report.pdf"
185
  pdf.output(pdf_output)
186
  return pdf_output
187
 
188
- # Streamlit app with enhanced UI
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
  def main():
190
- # Sidebar with team info
191
- with st.sidebar:
192
- st.markdown("<h1 style='color: white; text-align: center;'>Team Details</h1>", unsafe_allow_html=True)
193
- st.markdown("""
194
- <div style='background: rgba(255,255,255,0.1); padding: 15px; border-radius: 10px; margin: 15px 0;'>
195
- <h3 style='color: white; margin-bottom: 10px;'>πŸ‘©πŸ’» Team Members</h3>
196
- <p style='color: white;'>Sadia<br>Areeba<br>Rabbia<br>Tesmia</p>
197
- </div>
198
- """, unsafe_allow_html=True)
199
  st.markdown("""
200
- <div style='background: rgba(255,255,255,0.1); padding: 15px; border-radius: 10px;'>
201
- <h3 style='color: white; margin-bottom: 10px;'>πŸ€– AI Models</h3>
202
- <p style='color: white;'>Mistral (Classification)<br>Groq (Defect Analysis)</p>
 
 
 
203
  </div>
204
  """, unsafe_allow_html=True)
 
205
 
206
- # Main content area
207
- col1, col2, col3 = st.columns([1,6,1])
208
- with col2:
209
- st.markdown("<h1 class='report-title'>AI Requirement Analyzer</h1>", unsafe_allow_html=True)
210
-
211
- # Input section
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  with st.container():
213
- st.markdown("### πŸ“ Enter Requirements")
214
- input_text = st.text_area(
215
- "Enter your requirements (one per line or separated by periods):",
216
- height=200,
217
- label_visibility="collapsed"
218
- )
219
-
220
- # Analysis button
221
- if st.button("πŸ” Analyze Requirements", key="analyze_btn"):
222
- if not input_text.strip():
223
- st.warning("⚠️ Please enter requirements before analyzing")
224
- else:
225
- with st.spinner("πŸ”Ž Analyzing requirements..."):
226
- requirements = [req.strip() for req in input_text.replace("\n", ".").split(".") if req.strip()]
227
- results = []
228
- progress_bar = st.progress(0)
229
- for i, req in enumerate(requirements):
230
- results.append(analyze_requirement(req.strip()))
231
- progress_bar.progress((i+1)/len(requirements))
232
-
233
- # Display results
234
- st.success("βœ… Analysis Complete!")
235
- st.markdown("---")
236
- st.markdown("## πŸ“Š Analysis Results")
237
-
238
- # Summary metrics
239
- col1, col2, col3 = st.columns(3)
240
- with col1:
241
- st.markdown(f"""
242
- <div class='metric-box'>
243
- <h3>πŸ“„ Total Requirements</h3>
244
- <h2>{len(results)}</h2>
245
- </div>
246
- """, unsafe_allow_html=True)
247
- with col2:
248
- types = [res['Type'] for res in results]
249
- st.markdown(f"""
250
- <div class='metric-box'>
251
- <h3>πŸ“Š Functional/Non-Functional</h3>
252
- <h2>{types.count('Functional')}/{types.count('Non-Functional')}</h2>
253
  </div>
254
- """, unsafe_allow_html=True)
255
- with col3:
256
- domains = len(set([res['Domain'] for res in results]))
257
- st.markdown(f"""
258
- <div class='metric-box'>
259
- <h3>🌍 Unique Domains</h3>
260
- <h2>{domains}</h2>
261
  </div>
262
- """, unsafe_allow_html=True)
263
-
264
- # Detailed results
265
- st.markdown("---")
266
- for i, result in enumerate(results, start=1):
267
- with st.container():
268
- st.markdown(f"""
269
- <div class='requirement-card'>
270
- <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
271
- <h3>πŸ”– Requirement R{i}</h3>
272
- <span style="font-size: 0.9em; color: #666;">{result['Domain']} Domain</span>
273
- </div>
274
- <p style="color: #444; margin-bottom: 15px;">{result['Requirement']}</p>
275
- <div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 15px;">
276
- <div style="background: #f8f9fa; padding: 10px; border-radius: 8px;">
277
- <h4>πŸ“Œ Type</h4>
278
- <p>{result['Type']}</p>
279
- </div>
280
- <div style="background: #f8f9fa; padding: 10px; border-radius: 8px;">
281
- <h4>⚠️ Defects</h4>
282
- <p>{result['Defects']}</p>
283
- </div>
284
- <div style="background: #f8f9fa; padding: 10px; border-radius: 8px;">
285
- <h4>✏️ Improved Version</h4>
286
- <p>{result['Rewritten']}</p>
287
- </div>
288
- </div>
289
  </div>
290
- """, unsafe_allow_html=True)
291
-
292
- # PDF Download
293
- st.markdown("---")
294
- st.markdown("## πŸ“€ Export Results")
295
- pdf_report = generate_pdf_report(results)
296
- with open(pdf_report, "rb") as f:
297
- st.download_button(
298
- label="πŸ“₯ Download Full Report (PDF)",
299
- data=f,
300
- file_name="requirements_report.pdf",
301
- mime="application/pdf",
302
- help="Download comprehensive PDF report with all analysis details"
303
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
304
 
305
  if __name__ == "__main__":
306
  main()
 
7
  import groq
8
 
9
  # API keys (replace with your keys or use environment variables)
10
+ mistral_api_key = os.getenv("MISTRAL_API_KEY", "your_mistral_key_here")
11
+ groq_api_key = os.getenv("GROQ_API_KEY", "your_groq_key_here")
12
 
13
  # Initialize Groq client
14
  groq_client = groq.Client(api_key=groq_api_key)
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  # Function to call Mistral API
17
  def call_mistral_api(prompt):
18
  url = "https://api.mistral.ai/v1/chat/completions"
 
28
  }
29
  try:
30
  response = requests.post(url, headers=headers, json=payload)
31
+ response.raise_for_status()
32
  return response.json()['choices'][0]['message']['content']
33
  except requests.exceptions.HTTPError as err:
34
+ if response.status_code == 429:
35
  st.warning("Rate limit exceeded. Please wait a few seconds and try again.")
36
+ time.sleep(5)
37
+ return call_mistral_api(prompt)
38
  return f"HTTP Error: {err}"
39
  except Exception as err:
40
  return f"Error: {err}"
 
43
  def call_groq_api(prompt):
44
  try:
45
  response = groq_client.chat.completions.create(
46
+ model="llama3-70b-8192",
47
  messages=[
48
  {"role": "user", "content": prompt}
49
  ]
 
53
  st.error(f"Error: {err}")
54
  return f"Error: {err}"
55
 
56
+ # Function to analyze a single requirement
57
  def analyze_requirement(requirement):
58
  # Use Mistral for classification and domain identification
59
  type_prompt = f"Classify the following requirement as Functional or Non-Functional in one word:\n\n{requirement}\n\nType:"
 
85
 
86
  # Add watermark
87
  pdf.set_font("Arial", 'B', 50)
88
+ pdf.set_text_color(230, 230, 230)
89
+ pdf.rotate(45)
90
  pdf.text(60, 150, "AI Powered Requirement Analysis")
91
+ pdf.rotate(0)
92
 
93
  # Add title and date/time
94
  pdf.set_font("Arial", 'B', 16)
95
+ pdf.set_text_color(0, 0, 0)
96
  pdf.cell(200, 10, txt="AI Powered Requirement Analysis and Defect Detection", ln=True, align='C')
97
  pdf.set_font("Arial", size=12)
98
  pdf.cell(200, 10, txt=f"Report Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", ln=True, align='C')
99
+ pdf.ln(10)
100
 
101
  # Add requirements analysis
102
  pdf.set_font("Arial", size=12)
103
  for i, result in enumerate(results, start=1):
104
+ if pdf.get_y() > 250:
105
+ pdf.add_page()
106
  pdf.set_font("Arial", 'B', 16)
107
  pdf.cell(200, 10, txt="AI Powered Requirement Analysis and Defect Detection", ln=True, align='C')
108
  pdf.set_font("Arial", size=12)
109
  pdf.cell(200, 10, txt=f"Report Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", ln=True, align='C')
110
+ pdf.ln(10)
111
 
 
112
  pdf.set_font("Arial", 'B', 14)
113
  pdf.multi_cell(200, 10, txt=f"Requirement R{i}: {result['Requirement']}", align='L')
114
  pdf.set_font("Arial", size=12)
 
117
  pdf.multi_cell(200, 10, txt=f"Defects: {result['Defects']}", align='L')
118
  pdf.multi_cell(200, 10, txt=f"Rewritten: {result['Rewritten']}", align='L')
119
  pdf.multi_cell(200, 10, txt="-" * 50, align='L')
120
+ pdf.ln(5)
121
 
122
  pdf_output = "requirements_report.pdf"
123
  pdf.output(pdf_output)
124
  return pdf_output
125
 
126
+ # Custom CSS for professional styling
127
+ st.markdown("""
128
+ <style>
129
+ .main {
130
+ background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
131
+ }
132
+ .stApp {
133
+ max-width: 1200px;
134
+ margin: 0 auto;
135
+ padding: 2rem;
136
+ }
137
+ .header {
138
+ text-align: center;
139
+ padding: 2rem;
140
+ background: white;
141
+ border-radius: 15px;
142
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
143
+ margin-bottom: 2rem;
144
+ }
145
+ .requirement-card {
146
+ background: white;
147
+ padding: 1.5rem;
148
+ border-radius: 10px;
149
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
150
+ margin-bottom: 1.5rem;
151
+ transition: transform 0.2s;
152
+ }
153
+ .requirement-card:hover {
154
+ transform: translateY(-3px);
155
+ }
156
+ .analysis-badge {
157
+ padding: 0.5rem 1rem;
158
+ border-radius: 20px;
159
+ font-weight: 500;
160
+ margin: 0.3rem;
161
+ }
162
+ .download-btn {
163
+ width: 100%;
164
+ padding: 1rem;
165
+ font-size: 1.1rem;
166
+ margin-top: 2rem;
167
+ }
168
+ .type-functional { background: #e8f5e9; color: #2e7d32; }
169
+ .type-non-functional { background: #fff3e0; color: #ef6c00; }
170
+ .defect-badge { background: #ffebee; color: #c62828; }
171
+ .improved-badge { background: #e3f2fd; color: #1565c0; }
172
+ </style>
173
+ """, unsafe_allow_html=True)
174
+
175
  def main():
176
+ # Professional Header Section
177
+ with st.container():
178
+ st.markdown('<div class="header">', unsafe_allow_html=True)
179
+ st.title("πŸ“ AI-Powered Requirement Analysis System")
 
 
 
 
 
180
  st.markdown("""
181
+ <div style="margin: 1.5rem 0;">
182
+ <div style="font-size: 1.2rem; color: #4a4a4a;">Automated Requirement Classification, Defect Detection & Optimization</div>
183
+ <div style="display: flex; justify-content: center; gap: 1rem; margin: 1rem 0;">
184
+ <div style="padding: 0.5rem 1rem; background: #f0f2f6; border-radius: 20px;">Team: Sadia, Areeba, Rabbia, Tesmia</div>
185
+ <div style="padding: 0.5rem 1rem; background: #f0f2f6; border-radius: 20px;">Mistral + Groq API</div>
186
+ </div>
187
  </div>
188
  """, unsafe_allow_html=True)
189
+ st.markdown('</div>', unsafe_allow_html=True)
190
 
191
+ # Input Section
192
+ with st.container():
193
+ st.subheader("πŸ“₯ Input Requirements")
194
+ input_text = st.text_area(
195
+ "Enter your software requirements (one per line or separated by periods):",
196
+ height=200,
197
+ placeholder="Example:\nThe system shall allow users to reset their password via email verification.\nThe interface must load within 2 seconds of user interaction...",
198
+ help="Enter each requirement on a new line or separate with periods."
199
+ )
200
+
201
+ # Analysis Section
202
+ if st.button("πŸš€ Start Analysis", type="primary", use_container_width=True):
203
+ if not input_text.strip():
204
+ st.warning("⚠️ Please enter requirements to analyze")
205
+ else:
206
+ with st.spinner("πŸ” Analyzing requirements..."):
207
+ requirements = [req.strip() for req in input_text.replace("\n", ".").split(".") if req.strip()]
208
+ results = []
209
+
210
+ progress_bar = st.progress(0)
211
+ for i, req in enumerate(requirements):
212
+ results.append(analyze_requirement(req))
213
+ progress_bar.progress((i+1)/len(requirements))
214
+
215
+ st.success("βœ… Analysis Completed!")
216
+ time.sleep(0.5)
217
+ st.session_state.results = results
218
+
219
+ # Display Results
220
+ if 'results' in st.session_state:
221
+ st.subheader("πŸ“Š Analysis Results")
222
  with st.container():
223
+ for i, result in enumerate(st.session_state.results, 1):
224
+ with st.expander(f"Requirement #{i}: {result['Requirement'][:50]}...", expanded=True):
225
+ st.markdown(f"""
226
+ <div class="requirement-card">
227
+ <div style="margin-bottom: 1.5rem;">
228
+ <div class="analysis-badge { 'type-functional' if 'functional' in result['Type'].lower() else 'type-non-functional' }">
229
+ πŸ“Œ Type: {result['Type']}
230
+ </div>
231
+ <div class="analysis-badge" style="background: #e8eaf6; color: #303f9f;">
232
+ 🏷️ Domain: {result['Domain']}
233
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
  </div>
235
+
236
+ <div style="margin: 1rem 0;">
237
+ <h4>πŸ”Ž Identified Issues</h4>
238
+ <div style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
239
+ {''.join([f'<div class="analysis-badge defect-badge">⚠️ {d}</div>'
240
+ for d in result['Defects'].split(', ')])}
241
+ </div>
242
  </div>
243
+
244
+ <div style="margin: 1rem 0;">
245
+ <h4>✨ Improved Version</h4>
246
+ <div class="analysis-badge improved-badge">
247
+ πŸ“ {result['Rewritten']}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
248
  </div>
249
+ </div>
250
+ </div>
251
+ """, unsafe_allow_html=True)
252
+
253
+ # PDF Report Section
254
+ st.subheader("πŸ“€ Generate Report")
255
+ with st.container():
256
+ col1, col2 = st.columns([3, 2])
257
+ with col1:
258
+ st.info("πŸ’‘ Click below to generate a comprehensive PDF report with all analysis details")
259
+ with col2:
260
+ if st.button("πŸ“„ Generate PDF Report", type="secondary", use_container_width=True):
261
+ with st.spinner("Generating PDF..."):
262
+ pdf_report = generate_pdf_report(st.session_state.results)
263
+ with open(pdf_report, "rb") as f:
264
+ st.download_button(
265
+ label="⬇️ Download Full Report",
266
+ data=f,
267
+ file_name="Requirement_Analysis_Report.pdf",
268
+ mime="application/pdf",
269
+ use_container_width=True,
270
+ type="primary"
271
+ )
272
+
273
+ # Footer
274
+ st.markdown("---")
275
+ st.markdown("""
276
+ <div style="text-align: center; color: #666; margin-top: 3rem;">
277
+ <p>AI-Powered Requirement Analysis System β€’ Final Year Project β€’ Computer Science Department</p>
278
+ <p>πŸš€ Powered by Mistral AI & Groq β€’ πŸ› οΈ Developed by Team Four</p>
279
+ </div>
280
+ """, unsafe_allow_html=True)
281
 
282
  if __name__ == "__main__":
283
  main()