Spaces:
Sleeping
Sleeping
File size: 21,768 Bytes
6a9c9f9 |
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 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 |
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Requirements Generator and MoSCoW Prioritization\n",
"**Author:** Gael Sánchez\n",
"**LinkedIn:** www.linkedin.com/in/gaelsanchez\n",
"\n",
"This notebook generates and validates functional and non-functional software requirements from a natural language description, and classifies them using the MoSCoW prioritization technique.\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## What is a MoSCoW Matrix?\n",
"\n",
"The MoSCoW Matrix is a prioritization technique used in software development to categorize requirements based on their importance and urgency. The acronym stands for:\n",
"\n",
"- **Must Have** – Critical requirements that are essential for the system to function. \n",
"- **Should Have** – Important requirements that add significant value, but are not critical for initial delivery. \n",
"- **Could Have** – Nice-to-have features that can enhance the product, but are not necessary. \n",
"- **Won’t Have (for now)** – Low-priority features that will not be implemented in the current scope.\n",
"\n",
"This method helps development teams make clear decisions about what to focus on, especially when working with limited time or resources. It ensures that the most valuable and necessary features are delivered first, contributing to better project planning and stakeholder alignment.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## How it works\n",
"\n",
"This notebook uses the OpenAI library (via the Gemini API) to extract and validate software requirements from a natural language description. The workflow follows these steps:\n",
"\n",
"1. **Initial Validation** \n",
" The user provides a textual description of the software. The model evaluates whether the description contains enough information to derive meaningful requirements. Specifically, it checks if the description answers key questions such as:\n",
" \n",
" - What is the purpose of the software? \n",
" - Who are the intended users? \n",
" - What are the main features and functionalities? \n",
" - What platform(s) will it run on? \n",
" - How will data be stored or persisted? \n",
" - Is authentication/authorization needed? \n",
" - What technologies or frameworks will be used? \n",
" - What are the performance expectations? \n",
" - Are there UI/UX principles to follow? \n",
" - Are there external integrations or dependencies? \n",
" - Will it support offline usage? \n",
" - Are advanced features planned? \n",
" - Are there security or privacy concerns? \n",
" - Are there any constraints or limitations? \n",
" - What is the timeline or development roadmap?\n",
"\n",
" If the description lacks important details, the model requests the missing information from the user. This loop continues until the model considers the description complete.\n",
"\n",
"2. **Summarization** \n",
" Once validated, the model summarizes the software description, extracting its key aspects to form a concise and informative overview.\n",
"\n",
"3. **Requirements Generation** \n",
" Using the summary, the model generates a list of functional and non-functional requirements.\n",
"\n",
"4. **Requirements Validation** \n",
" A separate validation step checks if the generated requirements are complete and accurate based on the summary. If not, the model provides feedback, and the requirements are regenerated accordingly. This cycle repeats until the validation step approves the list.\n",
"\n",
"5. **MoSCoW Prioritization** \n",
" Finally, the validated list of requirements is classified using the MoSCoW prioritization technique, grouping them into:\n",
" \n",
" - Must have \n",
" - Should have \n",
" - Could have \n",
" - Won't have for now\n",
"\n",
"The output is a clear, structured requirements matrix ready for use in software development planning.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Example Usage\n",
"\n",
"### Input\n",
"\n",
"**Software Name:** Personal Task Manager \n",
"**Initial Description:** \n",
"This will be a simple desktop application that allows users to create, edit, mark as completed, and delete daily tasks. Each task will have a title, an optional description, a due date, and a status (pending or completed). The goal is to help users organize their activities efficiently, with an intuitive and minimalist interface.\n",
"\n",
"**Main Features:**\n",
"\n",
"- Add new tasks \n",
"- Edit existing tasks \n",
"- Mark tasks as completed \n",
"- Delete tasks \n",
"- Filter tasks by status or date\n",
"\n",
"**Additional Context Provided After Model Request:**\n",
"\n",
"- **Intended Users:** Individuals seeking to improve their daily productivity, such as students, remote workers, and freelancers. \n",
"- **Platform:** Desktop application for common operating systems. \n",
"- **Data Storage:** Tasks will be stored locally. \n",
"- **Authentication/Authorization:** A lightweight authentication layer may be included for data protection. \n",
"- **Technology Stack:** Cross-platform technologies that support a modern, functional UI. \n",
"- **Performance:** Expected to run smoothly with a reasonable number of active and completed tasks. \n",
"- **UI/UX:** Prioritizes a simple, modern user experience. \n",
"- **Integrations:** Future integration with calendar services is considered. \n",
"- **Offline Usage:** The application will work without an internet connection. \n",
"- **Advanced Features:** Additional features like notifications or recurring tasks may be added in future versions. \n",
"- **Security/Privacy:** User data privacy will be respected and protected. \n",
"- **Constraints:** Focus on simplicity, excluding complex features in the initial version. \n",
"- **Timeline:** Development planned in phases, starting with a functional MVP.\n",
"\n",
"### Output\n",
"\n",
"**MoSCoW Prioritization Matrix:**\n",
"\n",
"**Must Have**\n",
"- Task Creation: [The system needs to allow users to add tasks to be functional.] \n",
"- Task Editing: [Users must be able to edit tasks to correct mistakes or update information.] \n",
"- Task Completion: [Marking tasks as complete is a core function of a task management system.] \n",
"- Task Deletion: [Users need to be able to remove tasks that are no longer relevant.] \n",
"- Task Status: [Maintaining task status (pending/completed) is essential for tracking progress.] \n",
"- Data Persistence: [Tasks must be stored to be useful beyond a single session.] \n",
"- Performance: [The system needs to perform acceptably for a reasonable number of tasks.] \n",
"- Usability: [The system must be easy to use for all other functionalities to be useful.]\n",
"\n",
"**Should Have**\n",
"- Task Filtering by Status: [Filtering enhances usability and allows users to focus on specific tasks.] \n",
"- Task Filtering by Date: [Filtering by date helps manage deadlines.] \n",
"- User Interface Design: [A modern design improves user experience.] \n",
"- Platform Compatibility: [Running on common OSes increases adoption.] \n",
"- Data Privacy: [Important for user trust, can be gradually improved.] \n",
"- Security: [Basic protections are necessary, advanced features can wait.]\n",
"\n",
"**Could Have**\n",
"- Optional Authentication: [Enhances security but adds complexity.] \n",
"- Offline Functionality: [Convenient, but not critical for MVP.]\n",
"\n",
"**Won’t Have (for now)**\n",
"- N/A: [No features were excluded completely at this stage.]\n",
"\n",
"---\n",
"\n",
"This example demonstrates how the notebook takes a simple description and iteratively builds a complete and validated set of software requirements, ultimately organizing them into a MoSCoW matrix for development planning.\n"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"from dotenv import load_dotenv\n",
"from openai import OpenAI\n",
"from pydantic import BaseModel\n",
"import gradio as gr"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"load_dotenv(override=True)\n"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"gemini = OpenAI(\n",
" api_key=os.getenv(\"GOOGLE_API_KEY\"), \n",
" base_url=\"https://generativelanguage.googleapis.com/v1beta/openai/\"\n",
")\n",
" \n"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"class StandardSchema(BaseModel):\n",
" understood: bool\n",
" feedback: str\n",
" output: str"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"# This is the prompt to validate the description of the software product on the first step\n",
"system_prompt = f\"\"\"\n",
" You are a software analyst. the user will give you a description of a software product. Your task is to decide the description provided is complete and accurate and useful to derive requirements for the software.\n",
" If you decide the description is not complete or accurate, you should provide a kind message to the user listing the missing or incorrect information, and ask them to provide the missing information.\n",
" If you decide the description is complete and accurate, you should provide a summary of the description in a structured format. Only provide the summary, nothing else.\n",
" Ensure that the description answers the following questions:\n",
" - What is the purpose of the software?\n",
" - Who are the intended users?\n",
" - What are the main features and functionalities of the software?\n",
" - What platform(s) will it run on?\n",
" - How will data be stored or persisted?\n",
" - Is user authentication or authorization required?\n",
" - What technologies or frameworks will be used?\n",
" - What are the performance expectations?\n",
" - Are there any UI/UX design principles that should be followed?\n",
" - Are there any external integrations or dependencies?\n",
" - Will it support offline usage?\n",
" - Are there any planned advanced features?\n",
" - Are there any security or privacy considerations?\n",
" - Are there any constrains or limitations?\n",
" - What is the desired timeline or development roadmap?\n",
"\n",
" Respond in the following format:\n",
" \n",
" \"understood\": true only if the description is complete and accurate\n",
" \"feedback\": Instructions to the user to provide the missing or incorrect information.\n",
" \"output\": Summary of the description in a structured format, once the description is complete and accurate.\n",
" \n",
" \"\"\""
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"# This function is used to validate the description and provide feedback to the user.\n",
"# It receives the messages from the user and the system prompt.\n",
"# It returns the validation response.\n",
"\n",
"def validate_and_feedback(messages):\n",
"\n",
" validation_response = gemini.beta.chat.completions.parse(model=\"gemini-2.0-flash\", messages=messages, response_format=StandardSchema)\n",
" validation_response = validation_response.choices[0].message.parsed\n",
" return validation_response\n"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [],
"source": [
"# This function is used to validate the requirements and provide feedback to the model.\n",
"# It receives the description and the requirements.\n",
"# It returns the validation response.\n",
"\n",
"def validate_requirements(description, requirements):\n",
" validator_prompt = f\"\"\"\n",
" You are a software requirements reviewer.\n",
" Your task is to analyze a set of functional and non-functional requirements based on a given software description.\n",
"\n",
" Perform the following validation steps:\n",
"\n",
" Completeness: Check if all key features, fields, and goals mentioned in the description are captured as requirements.\n",
"\n",
" Consistency: Verify that all listed requirements are directly supported by the description. Flag anything that was added without justification.\n",
"\n",
" Clarity & Redundancy: Identify requirements that are vague, unclear, or redundant.\n",
"\n",
" Missing Elements: Highlight important elements from the description that were not translated into requirements.\n",
"\n",
" Suggestions: Recommend improvements or additional requirements that better align with the description.\n",
"\n",
" Answer in the following format:\n",
" \n",
" \"understood\": true only if the requirements are complete and accurate,\n",
" \"feedback\": Instructions to the generator to improve the requirements.\n",
" \n",
" Here's the software description:\n",
" {description}\n",
"\n",
" Here's the requirements:\n",
" {requirements}\n",
"\n",
" \"\"\"\n",
"\n",
" validator_response = gemini.beta.chat.completions.parse(model=\"gemini-2.0-flash\", messages=[{\"role\": \"user\", \"content\": validator_prompt}], response_format=StandardSchema)\n",
" validator_response = validator_response.choices[0].message.parsed\n",
" return validator_response\n"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [],
"source": [
"# This function is used to generate a rerun prompt for the requirements generator.\n",
"# It receives the description, the requirements and the feedback.\n",
"# It returns the rerun prompt.\n",
"\n",
"def generate_rerun_requirements_prompt(description, requirements, feedback):\n",
" return f\"\"\"\n",
" You are a software analyst. Based on the following software description, you generated the following list of functional and non-functional requirements. \n",
" However, the requirements validator rejected the list, with the following feedback. Please review the feedback and improve the list of requirements.\n",
"\n",
" ## Here's the description:\n",
" {description}\n",
"\n",
" ## Here's the requirements:\n",
" {requirements}\n",
"\n",
" ## Here's the feedback:\n",
" {feedback}\n",
" \"\"\""
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
"# This function generates the requirements based on the description.\n",
"def generate_requirements(description):\n",
" generator_prompt = f\"\"\"\n",
" You are a software analyst. Based on the following software description, generate a comprehensive list of both functional and non-functional requirements.\n",
"\n",
" The requirements must be clear, actionable, and written in concise natural language.\n",
"\n",
" Each requirement should describe exactly what the system must do or how it should behave, with enough detail to support MoSCoW prioritization and later transformation into user stories.\n",
"\n",
" Group the requirements into two sections: Functional Requirements and Non-Functional Requirements.\n",
"\n",
" Avoid redundancy. Do not include implementation details unless they are part of the expected behavior.\n",
"\n",
" Write in professional and neutral English.\n",
"\n",
" Output in Markdown format.\n",
"\n",
" Answer in the following format:\n",
"\n",
" \"understood\": true\n",
" \"output\": List of requirements\n",
"\n",
" ## Here's the description:\n",
" {description}\n",
"\n",
" ## Requirements:\n",
" \"\"\"\n",
"\n",
" requirements_response = gemini.beta.chat.completions.parse(model=\"gemini-2.0-flash\", messages=[{\"role\": \"user\", \"content\": generator_prompt}], response_format=StandardSchema)\n",
" requirements_response = requirements_response.choices[0].message.parsed\n",
" requirements = requirements_response.output\n",
"\n",
" requirements_valid = validate_requirements(description, requirements)\n",
" \n",
" # Validation loop\n",
" while not requirements_valid.understood:\n",
" rerun_requirements_prompt = generate_rerun_requirements_prompt(description, requirements, requirements_valid.feedback)\n",
" requirements_response = gemini.beta.chat.completions.parse(model=\"gemini-2.0-flash\", messages=[{\"role\": \"user\", \"content\": rerun_requirements_prompt}], response_format=StandardSchema)\n",
" requirements_response = requirements_response.choices[0].message.parsed\n",
" requirements = requirements_response.output\n",
" requirements_valid = validate_requirements(description, requirements)\n",
"\n",
" return requirements\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [],
"source": [
"# This function generates the MoSCoW priorization of the requirements.\n",
"# It receives the requirements.\n",
"# It returns the MoSCoW priorization.\n",
"\n",
"def generate_moscow_priorization(requirements):\n",
" priorization_prompt = f\"\"\"\n",
" You are a product analyst.\n",
" Based on the following list of functional and non-functional requirements, classify each requirement into one of the following MoSCoW categories:\n",
"\n",
" Must Have: Essential requirements that the system cannot function without.\n",
"\n",
" Should Have: Important requirements that add significant value but are not absolutely critical.\n",
"\n",
" Could Have: Desirable but non-essential features, often considered nice-to-have.\n",
"\n",
" Won’t Have (for now): Requirements that are out of scope for the current version but may be included in the future.\n",
"\n",
" For each requirement, place it under the appropriate category and include a brief justification (1–2 sentences) explaining your reasoning.\n",
"\n",
" Format your output using Markdown, like this:\n",
"\n",
" ## Must Have\n",
" - [Requirement]: [Justification]\n",
"\n",
" ## Should Have\n",
" - [Requirement]: [Justification]\n",
"\n",
" ## Could Have\n",
" - [Requirement]: [Justification]\n",
"\n",
" ## Won’t Have (for now)\n",
" - [Requirement]: [Justification]\n",
"\n",
" ## Here's the requirements:\n",
" {requirements}\n",
" \"\"\"\n",
"\n",
" priorization_response = gemini.beta.chat.completions.parse(model=\"gemini-2.0-flash\", messages=[{\"role\": \"user\", \"content\": priorization_prompt}], response_format=StandardSchema)\n",
" priorization_response = priorization_response.choices[0].message.parsed\n",
" priorization = priorization_response.output\n",
" return priorization\n",
"\n",
"\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [],
"source": [
"def chat(message, history):\n",
" messages = [{\"role\": \"system\", \"content\": system_prompt}] + history + [{\"role\": \"user\", \"content\": message}]\n",
"\n",
" validation =validate_and_feedback(messages)\n",
"\n",
" if not validation.understood:\n",
" print('retornando el feedback')\n",
" return validation.feedback\n",
" else:\n",
" requirements = generate_requirements(validation.output)\n",
" moscow_prioritization = generate_moscow_priorization(requirements)\n",
" return moscow_prioritization\n",
" "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"gr.ChatInterface(chat, type=\"messages\").launch()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.1"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
|