Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -2,6 +2,7 @@
|
|
2 |
import json
|
3 |
import base64
|
4 |
import os
|
|
|
5 |
|
6 |
import streamlit as st
|
7 |
from langchain.llms import OpenAI
|
@@ -15,6 +16,14 @@ from langchain.text_splitter import CharacterTextSplitter
|
|
15 |
from langchain_community.vectorstores import Chroma
|
16 |
from langchain_community.embeddings import OpenAIEmbeddings
|
17 |
import pandas as pd
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
|
19 |
|
20 |
# Initialize session states
|
@@ -30,7 +39,6 @@ if "rfp_details" not in st.session_state:
|
|
30 |
st.session_state["rfp_details"] = ""
|
31 |
if "is_data_processed" not in st.session_state:
|
32 |
st.session_state["is_data_processed"] = False
|
33 |
-
|
34 |
if "user_stories" not in st.session_state:
|
35 |
st.session_state["user_stories"] = ""
|
36 |
if "user_stories_json" not in st.session_state:
|
@@ -49,6 +57,52 @@ Incorporate the provided context and any relevant information from the chat hist
|
|
49 |
Human: {input}
|
50 |
Assistant:"""
|
51 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
user_story_template = """Given the project details with the following parameters:
|
53 |
|
54 |
**Project Name:** {project_name}
|
@@ -56,7 +110,7 @@ user_story_template = """Given the project details with the following parameters
|
|
56 |
**RFP details:**
|
57 |
{rfp_details}
|
58 |
|
59 |
-
As a business analyst, analyze the given RFP details to delineate epics for the project. Break down the epics into features and features into individual requirements, adhering to the agile software development INVEST principles. Subsequently, generate user stories for each requirement. Ensure each story follows the "As a, I want to, So that" format and strictly avoid combining stories together.
|
60 |
|
61 |
**Examples**
|
62 |
|
@@ -88,11 +142,11 @@ As a business analyst, analyze the given RFP details to delineate epics for the
|
|
88 |
|
89 |
3. Feature 3: Account Security Enhancements
|
90 |
- Story 1:
|
91 |
-
- As a security-conscious user, I want the platform to
|
92 |
- Story 2:
|
93 |
-
- As a user who values privacy, I want the platform to automatically log me out after
|
94 |
- Story 3:
|
95 |
-
- As a user concerned about account recovery, I want the platform to offer
|
96 |
"""
|
97 |
|
98 |
summary_template = """Given the project details with the following parameters:
|
@@ -142,8 +196,28 @@ json_structure = {
|
|
142 |
}
|
143 |
|
144 |
|
|
|
|
|
145 |
def clear_rfp_data():
|
146 |
st.session_state.clear()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
147 |
|
148 |
|
149 |
# rfp summary creater
|
@@ -155,14 +229,13 @@ summary_prompt = PromptTemplate(
|
|
155 |
|
156 |
summary_chain = LLMChain(
|
157 |
llm=OpenAI(model_name='gpt-3.5-turbo-16k', temperature=0.7,
|
158 |
-
api_key=
|
159 |
prompt=summary_prompt,
|
160 |
verbose="true",
|
161 |
)
|
162 |
|
163 |
# process rfp data from pdf file
|
164 |
|
165 |
-
|
166 |
def process_rfp_data(project_name, file):
|
167 |
if project_name and file:
|
168 |
loader = PdfReader(file)
|
@@ -176,7 +249,7 @@ def process_rfp_data(project_name, file):
|
|
176 |
texts = text_splitter.split_text(
|
177 |
st.session_state["rfp_details"])
|
178 |
st.session_state["vectorstore"] = Chroma().from_texts(texts, embedding=OpenAIEmbeddings(
|
179 |
-
openai_api_key=
|
180 |
st.session_state.project_name = project_name
|
181 |
st.session_state["rfp_summary"] = summary_chain.run(
|
182 |
{"project_name": st.session_state["project_name"], "rfp_details": st.session_state["rfp_details"]})
|
@@ -193,7 +266,7 @@ bot_prompt = PromptTemplate(
|
|
193 |
|
194 |
bot_chain = LLMChain(
|
195 |
llm=OpenAI(model_name='gpt-3.5-turbo-16k', temperature=0.7,
|
196 |
-
api_key=
|
197 |
prompt=bot_prompt,
|
198 |
verbose="true",
|
199 |
)
|
@@ -222,7 +295,7 @@ user_story_prompt = PromptTemplate(
|
|
222 |
|
223 |
user_story_chain = LLMChain(
|
224 |
llm=OpenAI(model_name='gpt-3.5-turbo-16k', temperature=0.7,
|
225 |
-
api_key=
|
226 |
prompt=user_story_prompt,
|
227 |
verbose="true",
|
228 |
)
|
@@ -236,7 +309,7 @@ json_prompt_template = PromptTemplate(
|
|
236 |
|
237 |
json_chain = LLMChain(
|
238 |
llm=OpenAI(model_name='gpt-3.5-turbo-16k', temperature=0.7,
|
239 |
-
api_key=
|
240 |
prompt=json_prompt_template,
|
241 |
verbose="true",
|
242 |
)
|
@@ -284,6 +357,8 @@ def main():
|
|
284 |
'Home', 'RFP Bot', 'User Stories', "Summary"], icons=['house','list-task', 'book', 'book'])
|
285 |
if st.session_state["is_data_processed"] == True:
|
286 |
st.button('Clear RFP Data', on_click=clear_rfp_data)
|
|
|
|
|
287 |
|
288 |
if menu_choice == 'Home':
|
289 |
with st.form("my_form"):
|
@@ -342,5 +417,53 @@ def main():
|
|
342 |
'Plesase Process RFP Details to access this feature', icon="⚠️")
|
343 |
|
344 |
|
345 |
-
if __name__ ==
|
346 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
import json
|
3 |
import base64
|
4 |
import os
|
5 |
+
import re
|
6 |
|
7 |
import streamlit as st
|
8 |
from langchain.llms import OpenAI
|
|
|
16 |
from langchain_community.vectorstores import Chroma
|
17 |
from langchain_community.embeddings import OpenAIEmbeddings
|
18 |
import pandas as pd
|
19 |
+
from textwrap import dedent
|
20 |
+
from streamlit_oauth import OAuth2Component
|
21 |
+
|
22 |
+
|
23 |
+
openai_api_key = os.environ.get('OPENAI_API_KEY')
|
24 |
+
CLIENT_ID = os.environ.get("CLIENT_ID")
|
25 |
+
CLIENT_SECRET = os.environ.get("CLIENT_SECRET")
|
26 |
+
REDIRECT_URI = os.environ.get("REDIRECT_URI")
|
27 |
|
28 |
|
29 |
# Initialize session states
|
|
|
39 |
st.session_state["rfp_details"] = ""
|
40 |
if "is_data_processed" not in st.session_state:
|
41 |
st.session_state["is_data_processed"] = False
|
|
|
42 |
if "user_stories" not in st.session_state:
|
43 |
st.session_state["user_stories"] = ""
|
44 |
if "user_stories_json" not in st.session_state:
|
|
|
57 |
Human: {input}
|
58 |
Assistant:"""
|
59 |
|
60 |
+
# user_story_template = """Given the project details with the following parameters:
|
61 |
+
|
62 |
+
# **Project Name:** {project_name}
|
63 |
+
|
64 |
+
# **RFP details:**
|
65 |
+
# {rfp_details}
|
66 |
+
|
67 |
+
# As a business analyst, analyze the given RFP details to delineate epics for the project. Break down the epics into features and features into individual requirements, adhering to the agile software development INVEST principles. Subsequently, generate user stories for each requirement. Ensure each story follows the "As a, I want to, So that" format and strictly avoid combining stories together.
|
68 |
+
|
69 |
+
# **Examples**
|
70 |
+
|
71 |
+
# 1. Epic: User Authentication and Account Security Enhancements
|
72 |
+
|
73 |
+
# 1. Feature 1: User Registration
|
74 |
+
# - Story 1:
|
75 |
+
# - As a user, I want to provide my basic information, such as name and email address during sign-up, so that the platform can create a personalized account for me.
|
76 |
+
# - Story 2:
|
77 |
+
# - As a user, I want the sign-up form to include a CAPTCHA verification step, so that the system can prevent automated bots from creating fake accounts.
|
78 |
+
# - Story 3:
|
79 |
+
# - As a user, I want the sign-up form to include optional fields for additional profile information, so that I can customize my account based on my interests.
|
80 |
+
# - Story 4:
|
81 |
+
# - As a user, I want the platform to clearly communicate its data usage and privacy policy during the sign-up process, so that I can make an informed decision before creating an account.
|
82 |
+
|
83 |
+
# 2. Feature 2: User Authentication
|
84 |
+
# - Story 1:
|
85 |
+
# - As a registered user, I want to log in securely with my credentials, so that I can access personalized account information.
|
86 |
+
# - Story 2:
|
87 |
+
# - As a registered user, I want the login page to feature a "Forgot Password" link, so that I can easily initiate the password recovery process if needed.
|
88 |
+
# - Story 3:
|
89 |
+
# - As a user concerned about account security, I want the platform to send a notification email whenever my account is accessed from a new device, so that I can be aware of any potential unauthorized access.
|
90 |
+
# - Story 4:
|
91 |
+
# - As a returning user, I want the option to enable two-factor authentication (2FA) for an extra layer of security during the login process, so that my account remains protected.
|
92 |
+
# - Story 5:
|
93 |
+
# - As a user striving for a seamless experience, I want the platform to offer a "Stay Logged In" option during login, so that I don't have to enter my credentials every time I revisit the site.
|
94 |
+
# - Story 6:
|
95 |
+
# - As a user with multiple devices, I want the ability to log out remotely from any active sessions through the account settings, so that I can maintain control over my account access.
|
96 |
+
|
97 |
+
# 3. Feature 3: Account Security Enhancements
|
98 |
+
# - Story 1:
|
99 |
+
# - As a security-conscious user, I want the platform to regularly prompt me to update my password and provide guidance on creating a secure password to enhance the overall security of my account.
|
100 |
+
# - Story 2:
|
101 |
+
# - As a user who values privacy, I want the platform to automatically log me out after a period of inactivity, ensuring that my account is secure even if I forget to log out manually.
|
102 |
+
# - Story 3:
|
103 |
+
# - As a user concerned about account recovery, I want the platform to offer multiple secure account recovery options, such as email verification and phone number verification, to ensure I can regain access to my account if needed.
|
104 |
+
# """
|
105 |
+
|
106 |
user_story_template = """Given the project details with the following parameters:
|
107 |
|
108 |
**Project Name:** {project_name}
|
|
|
110 |
**RFP details:**
|
111 |
{rfp_details}
|
112 |
|
113 |
+
As a business analyst, analyze the given RFP details to delineate epics for the project. Break down the epics into features and features into individual requirements, adhering to the agile software development INVEST principles (where I refers to Independent (not dependent on other work deliverables), N refers to Negotiable (allows for best practices), V refers to valuable (provides working functionality), E refers to Estimable (allows clear work estimates), S refers to Small (sized for the team's sprint), T refers to Testable (can be measured to ensure it meets customer expectations)). Subsequently, generate user stories for each requirement. Ensure each story follows the "As a, I want to, So that" format and strictly avoid combining stories together.
|
114 |
|
115 |
**Examples**
|
116 |
|
|
|
142 |
|
143 |
3. Feature 3: Account Security Enhancements
|
144 |
- Story 1:
|
145 |
+
- As a security-conscious user, I want the platform to prompt me every 15 days to update my password and provide guidance on creating a secure password to enhance the overall security of my account.
|
146 |
- Story 2:
|
147 |
+
- As a user who values privacy, I want the platform to automatically log me out after 5 minutes of inactivity, ensuring that my account is secure even if I forget to log out manually.
|
148 |
- Story 3:
|
149 |
+
- As a user concerned about account recovery, I want the platform to offer email verification and phone number verification account recovery options, to ensure I can regain access to my account if needed.
|
150 |
"""
|
151 |
|
152 |
summary_template = """Given the project details with the following parameters:
|
|
|
196 |
}
|
197 |
|
198 |
|
199 |
+
#function to create a new rfp and clear the existing rfp data
|
200 |
+
|
201 |
def clear_rfp_data():
|
202 |
st.session_state.clear()
|
203 |
+
|
204 |
+
#function to logout user from app
|
205 |
+
|
206 |
+
def log_out_user():
|
207 |
+
st.session_state.clear()
|
208 |
+
st.rerun()
|
209 |
+
|
210 |
+
#function to validate the email
|
211 |
+
|
212 |
+
def validate_email(email):
|
213 |
+
# Define the pattern for the company email
|
214 |
+
pattern = r'^[a-zA-Z]+@coffeebeans\.io$'
|
215 |
+
|
216 |
+
# Use the re.match function to check if the email matches the pattern
|
217 |
+
match = re.match(pattern, email)
|
218 |
+
|
219 |
+
# Return True if there is a match, indicating a valid email
|
220 |
+
return match is not None
|
221 |
|
222 |
|
223 |
# rfp summary creater
|
|
|
229 |
|
230 |
summary_chain = LLMChain(
|
231 |
llm=OpenAI(model_name='gpt-3.5-turbo-16k', temperature=0.7,
|
232 |
+
api_key= openai_api_key),
|
233 |
prompt=summary_prompt,
|
234 |
verbose="true",
|
235 |
)
|
236 |
|
237 |
# process rfp data from pdf file
|
238 |
|
|
|
239 |
def process_rfp_data(project_name, file):
|
240 |
if project_name and file:
|
241 |
loader = PdfReader(file)
|
|
|
249 |
texts = text_splitter.split_text(
|
250 |
st.session_state["rfp_details"])
|
251 |
st.session_state["vectorstore"] = Chroma().from_texts(texts, embedding=OpenAIEmbeddings(
|
252 |
+
openai_api_key=openai_api_key))
|
253 |
st.session_state.project_name = project_name
|
254 |
st.session_state["rfp_summary"] = summary_chain.run(
|
255 |
{"project_name": st.session_state["project_name"], "rfp_details": st.session_state["rfp_details"]})
|
|
|
266 |
|
267 |
bot_chain = LLMChain(
|
268 |
llm=OpenAI(model_name='gpt-3.5-turbo-16k', temperature=0.7,
|
269 |
+
api_key= openai_api_key),
|
270 |
prompt=bot_prompt,
|
271 |
verbose="true",
|
272 |
)
|
|
|
295 |
|
296 |
user_story_chain = LLMChain(
|
297 |
llm=OpenAI(model_name='gpt-3.5-turbo-16k', temperature=0.7,
|
298 |
+
api_key= openai_api_key),
|
299 |
prompt=user_story_prompt,
|
300 |
verbose="true",
|
301 |
)
|
|
|
309 |
|
310 |
json_chain = LLMChain(
|
311 |
llm=OpenAI(model_name='gpt-3.5-turbo-16k', temperature=0.7,
|
312 |
+
api_key= openai_api_key),
|
313 |
prompt=json_prompt_template,
|
314 |
verbose="true",
|
315 |
)
|
|
|
357 |
'Home', 'RFP Bot', 'User Stories', "Summary"], icons=['house','list-task', 'book', 'book'])
|
358 |
if st.session_state["is_data_processed"] == True:
|
359 |
st.button('Clear RFP Data', on_click=clear_rfp_data)
|
360 |
+
if "auth" in st.session_state:
|
361 |
+
st.button('Log out', on_click=log_out_user)
|
362 |
|
363 |
if menu_choice == 'Home':
|
364 |
with st.form("my_form"):
|
|
|
417 |
'Plesase Process RFP Details to access this feature', icon="⚠️")
|
418 |
|
419 |
|
420 |
+
if __name__ == "__main__":
|
421 |
+
if "auth" not in st.session_state:
|
422 |
+
st.title("SIGN UP TO ACCESS THE APP!")
|
423 |
+
AUTHORIZE_ENDPOINT = "https://accounts.google.com/o/oauth2/v2/auth"
|
424 |
+
TOKEN_ENDPOINT = "https://oauth2.googleapis.com/token"
|
425 |
+
REVOKE_ENDPOINT = "https://oauth2.googleapis.com/revoke"
|
426 |
+
|
427 |
+
# create a button to start the OAuth2 flow
|
428 |
+
oauth2 = OAuth2Component(
|
429 |
+
CLIENT_ID,
|
430 |
+
CLIENT_SECRET,
|
431 |
+
AUTHORIZE_ENDPOINT,
|
432 |
+
TOKEN_ENDPOINT,
|
433 |
+
TOKEN_ENDPOINT,
|
434 |
+
REVOKE_ENDPOINT,
|
435 |
+
)
|
436 |
+
result = oauth2.authorize_button(
|
437 |
+
name="Continue with Google",
|
438 |
+
icon="https://www.google.com.tw/favicon.ico",
|
439 |
+
redirect_uri="https://huggingface.co/spaces/coffeebeans-ai/rfp_to_story",
|
440 |
+
scope="openid email profile",
|
441 |
+
key="google",
|
442 |
+
height=600,
|
443 |
+
width=500,
|
444 |
+
extras_params={"prompt": "consent", "access_type": "offline"},
|
445 |
+
use_container_width=False,
|
446 |
+
pkce="S256",
|
447 |
+
)
|
448 |
+
|
449 |
+
if result:
|
450 |
+
# decode the id_token jwt and get the user's email address
|
451 |
+
id_token = result["token"]["id_token"]
|
452 |
+
# verify the signature is an optional step for security
|
453 |
+
payload = id_token.split(".")[1]
|
454 |
+
# add padding to the payload if needed
|
455 |
+
payload += "=" * (-len(payload) % 4)
|
456 |
+
payload = json.loads(base64.b64decode(payload))
|
457 |
+
email = payload["email"]
|
458 |
+
st.session_state["auth"] = email
|
459 |
+
st.session_state["token"] = result["token"]
|
460 |
+
is_valid = validate_email(st.session_state["auth"])
|
461 |
+
|
462 |
+
if is_valid:
|
463 |
+
st.rerun()
|
464 |
+
else:
|
465 |
+
st.warning("Unauthorized. you are not authorized to access this app.")
|
466 |
+
|
467 |
+
else:
|
468 |
+
main()
|
469 |
+
|