Spaces:
Sleeping
Sleeping
Umang Chaudhry
commited on
Commit
•
8e04782
1
Parent(s):
3ac6f08
Merge pull request #98 from vanderbilt-data-science/hf-struggle
Browse files- app.py +172 -57
- free_speech_app/DataLoadDb.py +12 -38
- free_speech_app/FreeSpeechPromptsResponses.py +65 -21
- requirements.txt +5 -4
app.py
CHANGED
@@ -1,20 +1,29 @@
|
|
1 |
import streamlit as st
|
2 |
import streamlit_authenticator as stauth
|
3 |
-
import
|
4 |
import yaml
|
5 |
from yaml.loader import SafeLoader
|
6 |
import os
|
|
|
7 |
|
8 |
from free_speech_app.DataLoadDb import *
|
9 |
from free_speech_app.FreeSpeechPromptsResponses import *
|
10 |
from langchain.chat_models import ChatOpenAI
|
11 |
|
12 |
-
#
|
13 |
-
|
|
|
14 |
|
15 |
-
#
|
16 |
-
|
17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
|
19 |
# Create an authenticator
|
20 |
authenticator = stauth.Authenticate(
|
@@ -25,25 +34,23 @@ authenticator = stauth.Authenticate(
|
|
25 |
config['preauthorized']
|
26 |
)
|
27 |
|
28 |
-
|
29 |
-
|
|
|
|
|
|
|
|
|
30 |
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
principles TEXT,
|
35 |
-
writing_style TEXT,
|
36 |
-
sources TEXT)''')
|
37 |
|
38 |
-
def
|
39 |
-
|
40 |
-
|
41 |
-
data = cursor.fetchone()
|
42 |
-
return data
|
43 |
|
44 |
-
|
45 |
-
|
46 |
-
conn.commit()
|
47 |
|
48 |
# If the user is authenticated
|
49 |
if authentication_status:
|
@@ -51,51 +58,157 @@ if authentication_status:
|
|
51 |
st.write(f'Welcome *{name}*')
|
52 |
|
53 |
# Sidebar for navigation
|
54 |
-
page = st.sidebar.
|
55 |
|
56 |
# Fetch user data from the database
|
57 |
user_data = get_user_data(username)
|
58 |
|
59 |
-
if page == "
|
60 |
-
|
|
|
|
|
61 |
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
|
|
|
|
|
|
|
|
66 |
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
# Check if the "Submit" button is clicked
|
71 |
-
if st.button("Submit"):
|
72 |
-
if api_input:
|
73 |
-
os.environ["OPENAI_API_KEY"] = api_input
|
74 |
-
chat_mdl = ChatOpenAI(model_name = 'gpt-3.5-turbo-16k', temperature=0.1)
|
75 |
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
# Output from function
|
83 |
-
st.text_area(label="Draft Response. Please edit here or prompt suggestions in the box below.", value=draft_response, height=350)
|
84 |
|
85 |
-
|
|
|
86 |
|
87 |
-
|
88 |
-
st.
|
89 |
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
|
|
|
|
|
|
94 |
|
95 |
-
|
96 |
-
|
97 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
98 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
elif authentication_status is False:
|
100 |
st.error('Username/password is incorrect')
|
101 |
|
@@ -103,10 +216,12 @@ elif authentication_status is None:
|
|
103 |
st.warning('Please enter your username and password')
|
104 |
|
105 |
try:
|
106 |
-
if authenticator.register_user('
|
107 |
-
st.success('User
|
108 |
except Exception as e:
|
109 |
st.error(e)
|
110 |
|
111 |
with open('config.yaml', 'w') as file:
|
112 |
yaml.dump(config, file, default_flow_style=False)
|
|
|
|
|
|
1 |
import streamlit as st
|
2 |
import streamlit_authenticator as stauth
|
3 |
+
from deta import Deta
|
4 |
import yaml
|
5 |
from yaml.loader import SafeLoader
|
6 |
import os
|
7 |
+
from cryptography.fernet import Fernet
|
8 |
|
9 |
from free_speech_app.DataLoadDb import *
|
10 |
from free_speech_app.FreeSpeechPromptsResponses import *
|
11 |
from langchain.chat_models import ChatOpenAI
|
12 |
|
13 |
+
#connect to/create Deta user database
|
14 |
+
deta = Deta(st.secrets["deta_key"])
|
15 |
+
db = deta.Base("user_data")
|
16 |
|
17 |
+
#fernet key (generated locally, stored in streamlit secrets)
|
18 |
+
fernet = Fernet(bytes(st.secrets["fernet_key"],'utf-8'))
|
19 |
+
|
20 |
+
#activeloop_token
|
21 |
+
os.environ["ACTIVELOOP_TOKEN"] = st.secrets["deeplake_key"]
|
22 |
+
|
23 |
+
config_drive = deta.Drive("passwords")
|
24 |
+
config = config_drive.get("config.yaml").read()
|
25 |
+
|
26 |
+
config = yaml.load(config, Loader=SafeLoader)
|
27 |
|
28 |
# Create an authenticator
|
29 |
authenticator = stauth.Authenticate(
|
|
|
34 |
config['preauthorized']
|
35 |
)
|
36 |
|
37 |
+
def get_user_data(user):
|
38 |
+
data = db.fetch().items
|
39 |
+
for person in data:
|
40 |
+
if person['key'] == user:
|
41 |
+
return person
|
42 |
+
return None
|
43 |
|
44 |
+
def encrypt(api_key: str, fernet) -> bytes:
|
45 |
+
"""Encrypt the API key."""
|
46 |
+
return fernet.encrypt(api_key.encode())
|
|
|
|
|
|
|
47 |
|
48 |
+
def decrypt(encrypted_api_key: bytes, fernet) -> str:
|
49 |
+
"""Decrypt the encrypted API key."""
|
50 |
+
return fernet.decrypt(encrypted_api_key).decode()
|
|
|
|
|
51 |
|
52 |
+
# Render the login module
|
53 |
+
name, authentication_status, username = authenticator.login('Login', 'main')
|
|
|
54 |
|
55 |
# If the user is authenticated
|
56 |
if authentication_status:
|
|
|
58 |
st.write(f'Welcome *{name}*')
|
59 |
|
60 |
# Sidebar for navigation
|
61 |
+
page = st.sidebar.radio("Choose a page", ["OpenAI API Key Setup", "Account Setup", "Respond to Post"])
|
62 |
|
63 |
# Fetch user data from the database
|
64 |
user_data = get_user_data(username)
|
65 |
|
66 |
+
if page == "Account Setup":
|
67 |
+
|
68 |
+
st.title("Account Setup")
|
69 |
+
st.markdown("Please use this page to provide your OpenAI API Key, Principles and Writing Style. **Please make sure to press the Save Changes button after providing the information.**")
|
70 |
|
71 |
+
|
72 |
+
# Input boxes with existing data
|
73 |
+
|
74 |
+
if 'api_key' not in st.session_state:
|
75 |
+
st.session_state.api_key = ""
|
76 |
+
api_input = st.text_input("OpenAI API Key", value=decrypt(user_data["api_key"].encode()[2:-1], fernet) if user_data and "api_key" in user_data else "", type="password")
|
77 |
+
encrypted_api_key = str(encrypt(api_input, fernet))
|
78 |
+
st.session_state.api_key = api_input
|
79 |
|
80 |
+
principles = st.text_input("My Principles", placeholder = "Enter the main principles of your life you wish this response to uphold", value=user_data["principles"] if user_data and "principles" in user_data else "")
|
81 |
+
writing_style = st.text_input("My Writing Style (Paste Examples)", placeholder = "Provide examples of your writing style here", value=user_data["writing_style"] if user_data and "writing_style" in user_data else "")
|
82 |
+
sources = st.text_input("Sources (Provide all sources you would like to use)", value=st.session_state.sources if 'sources' in st.session_state else '', key = 'sources_key')
|
|
|
|
|
|
|
|
|
|
|
83 |
|
84 |
+
# Update button
|
85 |
+
if st.button("Save Changes"):
|
86 |
+
db.put({"key": username, "principles": principles, "writing_style": writing_style, "sources": sources, "api_key": encrypted_api_key})
|
87 |
+
|
88 |
+
if page == "OpenAI API Key Setup":
|
89 |
+
st.title("OpenAI API Key Setup")
|
|
|
|
|
90 |
|
91 |
+
st.header('What is an API key?')
|
92 |
+
st.write('An API (Application Programming Interface) key is like a password that allows you to access certain functions or data from a website or service. Many sites use API keys to identify you and control access to their APIs.')
|
93 |
|
94 |
+
st.header('Why do you need an API key?')
|
95 |
+
st.write('API keys allow sites to track usage and prevent abuse of their services. They help keep things secure. When you request an API key, the site knows the calls are coming from you.')
|
96 |
|
97 |
+
image = 'free_speech_app/apikeyex.png'
|
98 |
+
st.header('How to get an OpenAI API key:')
|
99 |
+
st.write('1. Go to https://platform.openai.com/account/api-keys')
|
100 |
+
st.write('2. Log in or create an OpenAI account if you do not have one')
|
101 |
+
st.write('3. Click "Create new secret key" and give your key a name')
|
102 |
+
st.image(image, caption=None, width=None, use_column_width=None, clamp=False, channels="RGB", output_format="auto")
|
103 |
+
st.write('4. Copy the generated API key and keep it private like a password')
|
104 |
|
105 |
+
st.header('Using your API key')
|
106 |
+
st.write('When making calls to the OpenAI API, include your API key in the request headers or parameters to authenticate.')
|
107 |
+
st.code('headers = {"Authorization": f"Bearer {YOUR_API_KEY}"}')
|
108 |
+
|
109 |
+
st.warning('Treat your API key like a secret! Do not share it publicly.')
|
110 |
+
|
111 |
+
|
112 |
+
elif page == "Respond to Post":
|
113 |
+
st.title("Respond to Post")
|
114 |
+
|
115 |
+
left_col, right_col = st.columns(2)
|
116 |
+
|
117 |
+
# Input boxes
|
118 |
|
119 |
+
with right_col:
|
120 |
+
background_info = st.text_area("Background information on original post (references, relevant information, best practices for responding)", height = 700, value=st.session_state.background_info if 'background_info' in st.session_state else '', key = 'background_info_key')
|
121 |
+
|
122 |
+
with left_col:
|
123 |
+
original_post = st.text_area("Paste Original Post Here \n", height=100)
|
124 |
+
|
125 |
+
chat_mdl = None
|
126 |
+
draft_response = ''
|
127 |
+
|
128 |
+
# Check if the "Submit" button is clicked
|
129 |
+
if st.button("Submit"):
|
130 |
+
if st.session_state.api_key:
|
131 |
+
os.environ["OPENAI_API_KEY"] = st.session_state.api_key
|
132 |
+
# add condition to check for passphrase to allow use of DSI api key stored in secrets
|
133 |
+
if (os.environ["OPENAI_API_KEY"] == st.secrets["secret_passphrase"]):
|
134 |
+
os.environ["OPENAI_API_KEY"] = st.secrets["dsi_openai_key"]
|
135 |
+
chat_mdl = ChatOpenAI(model_name='gpt-4', temperature=0.1)
|
136 |
+
|
137 |
+
if chat_mdl is not None:
|
138 |
+
if user_data is None:
|
139 |
+
draft_response, background_text, sources_text = generate_custom_response(original_post, chat_mdl, "", "")
|
140 |
+
st.session_state.draft_response = draft_response.content
|
141 |
+
st.session_state.background_text = background_text
|
142 |
+
st.session_state.sources_text = sources_text
|
143 |
+
st.session_state.background_info = background_text
|
144 |
+
st.session_state.sources = sources_text
|
145 |
+
st.rerun()
|
146 |
+
else:
|
147 |
+
draft_response, background_text, sources_text = generate_custom_response(original_post, chat_mdl, user_data['principles'], user_data['writing_style'])
|
148 |
+
st.session_state.draft_response = draft_response.content
|
149 |
+
st.session_state.background_text = background_text
|
150 |
+
st.session_state.sources_text = sources_text
|
151 |
+
st.session_state.background_info = background_text
|
152 |
+
st.session_state.sources = sources_text
|
153 |
+
st.rerun()
|
154 |
+
|
155 |
+
|
156 |
+
# Ensure session state variables are initialized
|
157 |
+
if 'draft_response' not in st.session_state:
|
158 |
+
st.session_state.draft_response = ''
|
159 |
+
if 'regenerate_prompt' not in st.session_state:
|
160 |
+
st.session_state.regenerate_prompt = ''
|
161 |
+
|
162 |
+
# Output from function
|
163 |
+
response_textarea = st.text_area(
|
164 |
+
label="Draft Response. Please edit here or prompt suggestions in the box below.",
|
165 |
+
value=st.session_state.draft_response if 'draft_response' in st.session_state else '',
|
166 |
+
height=350,
|
167 |
+
key='draft_response_key'
|
168 |
+
)
|
169 |
+
|
170 |
+
# Initialization of the regeneration flag
|
171 |
+
if 'is_regenerating' not in st.session_state:
|
172 |
+
st.session_state.is_regenerating = False
|
173 |
+
|
174 |
+
# Check if the app is in the "regeneration" phase
|
175 |
+
if st.session_state.is_regenerating:
|
176 |
+
# Display the regenerated response explicitly
|
177 |
+
regenerate_prompt = st.text_area(
|
178 |
+
"Request a new draft",
|
179 |
+
value=st.session_state.regenerate_prompt,
|
180 |
+
placeholder="You may edit the regenerated draft directly above, or request further changes here.",
|
181 |
+
height=100,
|
182 |
+
key='regenerate_prompt_key'
|
183 |
+
)
|
184 |
+
# Reset the regeneration flag
|
185 |
+
st.session_state.is_regenerating = False
|
186 |
+
else:
|
187 |
+
# Normal behavior: display the text area for manual input
|
188 |
+
regenerate_prompt = st.text_area(
|
189 |
+
"Request a new draft",
|
190 |
+
placeholder="You may edit the draft directly above, or request a new draft with additional guidance here.",
|
191 |
+
height=100,
|
192 |
+
key='regenerate_prompt_key'
|
193 |
+
)
|
194 |
+
|
195 |
+
if (draft_response is not None) and (regenerate_prompt is not None):
|
196 |
+
if st.button("Regenerate"):
|
197 |
+
if st.session_state.api_key:
|
198 |
+
os.environ['OPENAI_API_KEY'] = st.session_state.api_key
|
199 |
+
# add condition to check for passphrase to allow use of DSI api key stored in secrets
|
200 |
+
if (os.environ["OPENAI_API_KEY"] == st.secrets["secret_passphrase"]):
|
201 |
+
os.environ["OPENAI_API_KEY"] = st.secrets["dsi_openai_key"]
|
202 |
+
chat_mdl = ChatOpenAI(model_name='gpt-4', temperature=0.1)
|
203 |
+
|
204 |
+
if chat_mdl is not None:
|
205 |
+
updated_response = regenerate_custom_response(chat_mdl, regenerate_prompt, st.session_state.draft_response).content
|
206 |
+
st.session_state.regenerate_prompt = updated_response
|
207 |
+
st.session_state.is_regenerating = True
|
208 |
+
|
209 |
+
st.rerun()
|
210 |
+
|
211 |
+
|
212 |
elif authentication_status is False:
|
213 |
st.error('Username/password is incorrect')
|
214 |
|
|
|
216 |
st.warning('Please enter your username and password')
|
217 |
|
218 |
try:
|
219 |
+
if authenticator.register_user('New User Registration', preauthorization=False):
|
220 |
+
st.success('User Registered Successfully! Please log in above.')
|
221 |
except Exception as e:
|
222 |
st.error(e)
|
223 |
|
224 |
with open('config.yaml', 'w') as file:
|
225 |
yaml.dump(config, file, default_flow_style=False)
|
226 |
+
|
227 |
+
config_drive.put("config.yaml", path = "config.yaml")
|
free_speech_app/DataLoadDb.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1 |
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/free-speech-stores.ipynb.
|
2 |
|
3 |
# %% auto 0
|
4 |
-
__all__ = ['setup_openai_api_key', '
|
5 |
|
6 |
-
# %% ../nbs/free-speech-stores.ipynb
|
7 |
# libraries required for functionality
|
8 |
import os
|
9 |
from getpass import getpass
|
@@ -17,49 +17,23 @@ from langchain.text_splitter import CharacterTextSplitter
|
|
17 |
from langchain.embeddings import OpenAIEmbeddings
|
18 |
from langchain.vectorstores import Chroma
|
19 |
|
20 |
-
# %% ../nbs/free-speech-stores.ipynb
|
21 |
def setup_openai_api_key():
|
22 |
openai_api_key = getpass()
|
23 |
os.environ["OPENAI_API_KEY"] = openai_api_key
|
24 |
|
25 |
-
# %% ../nbs/free-speech-stores.ipynb
|
26 |
import nltk
|
27 |
nltk.download('averaged_perceptron_tagger')
|
28 |
|
29 |
-
# %% ../nbs/free-speech-stores.ipynb
|
30 |
-
def
|
31 |
-
|
32 |
-
from google.colab import files
|
33 |
-
return True
|
34 |
-
except:
|
35 |
-
return False
|
36 |
-
|
37 |
-
def upload_docs():
|
38 |
-
|
39 |
-
if not is_google_colab():
|
40 |
-
raise ModuleNotFoundError('This function only works in Google Colab; local functionality not currently supported.')
|
41 |
-
|
42 |
-
# upload files if google colab
|
43 |
-
from google.colab import files
|
44 |
-
uploaded = files.upload()
|
45 |
-
file_list = []
|
46 |
-
|
47 |
-
for name, data in uploaded.items():
|
48 |
-
with open(name, 'wb') as f:
|
49 |
-
f.write(data)
|
50 |
-
print('saved file', name)
|
51 |
-
file_list.append(name)
|
52 |
-
return file_list
|
53 |
-
|
54 |
-
|
55 |
-
# %% ../nbs/free-speech-stores.ipynb 22
|
56 |
-
def setup_db(list_of_files, chunk_size=1000, chunk_overlap=5):
|
57 |
-
# set path to files
|
58 |
-
#paths = ["https://github.com/vanderbilt-data-science/free-speech-app/raw/9818f87679a82769ab6f90dba00801447b6e952c/response-resources/2307.04761_Understanding_counterspeech.pdf", "https://github.com/vanderbilt-data-science/free-speech-app/raw/main/response-resources/campaigns.docx", "https://github.com/vanderbilt-data-science/free-speech-app/raw/9818f87679a82769ab6f90dba00801447b6e952c/response-resources/samples.pdf"]
|
59 |
|
60 |
# set up loaders
|
61 |
loaders_list = []
|
62 |
-
for file_path in
|
|
|
63 |
loaders_list.append(UnstructuredFileLoader(file_path))
|
64 |
|
65 |
loader_all = MergedDataLoader(loaders=[loader for loader in loaders_list])
|
@@ -70,7 +44,7 @@ def setup_db(list_of_files, chunk_size=1000, chunk_overlap=5):
|
|
70 |
texts = text_splitter.split_documents(documents)
|
71 |
embeddings = OpenAIEmbeddings()
|
72 |
|
73 |
-
#
|
74 |
-
db =
|
75 |
|
76 |
-
return
|
|
|
1 |
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/free-speech-stores.ipynb.
|
2 |
|
3 |
# %% auto 0
|
4 |
+
__all__ = ['setup_openai_api_key', 'setup_db']
|
5 |
|
6 |
+
# %% ../nbs/free-speech-stores.ipynb 4
|
7 |
# libraries required for functionality
|
8 |
import os
|
9 |
from getpass import getpass
|
|
|
17 |
from langchain.embeddings import OpenAIEmbeddings
|
18 |
from langchain.vectorstores import Chroma
|
19 |
|
20 |
+
# %% ../nbs/free-speech-stores.ipynb 12
|
21 |
def setup_openai_api_key():
|
22 |
openai_api_key = getpass()
|
23 |
os.environ["OPENAI_API_KEY"] = openai_api_key
|
24 |
|
25 |
+
# %% ../nbs/free-speech-stores.ipynb 15
|
26 |
import nltk
|
27 |
nltk.download('averaged_perceptron_tagger')
|
28 |
|
29 |
+
# %% ../nbs/free-speech-stores.ipynb 27
|
30 |
+
def setup_db(local_path, hub_path, chunk_size=1000, chunk_overlap=5):
|
31 |
+
file_list = os.listdir(local_path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
|
33 |
# set up loaders
|
34 |
loaders_list = []
|
35 |
+
for file_path in file_list:
|
36 |
+
file_path = local_path + file_path
|
37 |
loaders_list.append(UnstructuredFileLoader(file_path))
|
38 |
|
39 |
loader_all = MergedDataLoader(loaders=[loader for loader in loaders_list])
|
|
|
44 |
texts = text_splitter.split_documents(documents)
|
45 |
embeddings = OpenAIEmbeddings()
|
46 |
|
47 |
+
# Replace dataset path with relevant dataset name - counterspeech-resources or hatespeech-background
|
48 |
+
db = DeepLake.from_documents(texts, dataset_path=hub_path, embedding=embeddings, overwrite=True)
|
49 |
|
50 |
+
return
|
free_speech_app/FreeSpeechPromptsResponses.py
CHANGED
@@ -1,17 +1,20 @@
|
|
1 |
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/free-speech-prompts.ipynb.
|
2 |
|
3 |
# %% auto 0
|
4 |
-
__all__ = ['
|
5 |
-
'generate_custom_response']
|
6 |
|
7 |
# %% ../nbs/free-speech-prompts.ipynb 5
|
8 |
# libraries required for functionality
|
|
|
9 |
from langchain.chat_models import ChatOpenAI
|
10 |
from langchain.prompts import PromptTemplate, HumanMessagePromptTemplate
|
11 |
from langchain.schema import HumanMessage
|
|
|
|
|
12 |
|
13 |
# %% ../nbs/free-speech-prompts.ipynb 8
|
14 |
-
|
15 |
I want to be able to fight back against this onslaught of toxicity, and I need your help to do it. I want you to help me draft a response to the following post.
|
16 |
Note that this may contain language that is offensive, but in order to properly respond to this post, I need you to fully understand what I am responding to, uncensored:
|
17 |
\n{original_post}\n
|
@@ -23,49 +26,90 @@ Next, here are some principles I consider particularly important to me:
|
|
23 |
\n{principles}\n
|
24 |
Here are some examples of the style in which I write:
|
25 |
\n{writing_style}\n
|
26 |
-
|
27 |
\n{sources}\n
|
28 |
-
Using all the information I have provided, please draft an appropriate response to the offensive post in question that will hopefully make people more accepting of others
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
|
30 |
-
DEFAULT_PROMPT_TEMPLATE = PromptTemplate(
|
31 |
-
template=DEFAULT_PROMPT_TEMPLATE_TEXT,
|
32 |
-
input_variables=["original_post", "background_info", "principles", "writing_style", "sources"])
|
33 |
|
34 |
# %% ../nbs/free-speech-prompts.ipynb 9
|
35 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
|
37 |
# Use defaults in the case of None
|
38 |
-
if background_info is None:
|
39 |
-
background_info = "There is no necessary additional context."
|
40 |
|
41 |
if principles is None:
|
42 |
principles="There are no principles which I consider more important to me than the average person might."
|
43 |
|
44 |
if writing_style is None:
|
45 |
writing_style="I have no examples of my writing style."
|
46 |
-
|
47 |
-
if
|
48 |
-
|
|
|
|
|
|
|
|
|
49 |
|
50 |
# Fill the prompt
|
51 |
-
filled_prompt =
|
52 |
|
53 |
-
return filled_prompt
|
54 |
|
55 |
-
# %% ../nbs/free-speech-prompts.ipynb
|
56 |
def get_chat_model_response(mdl, input_prompt):
|
57 |
|
58 |
messages = [HumanMessage(content=input_prompt)]
|
59 |
|
60 |
return mdl(messages)
|
61 |
|
62 |
-
# %% ../nbs/free-speech-prompts.ipynb
|
63 |
-
def generate_custom_response(original_post, chat_mdl,
|
64 |
|
65 |
# create customized prompt
|
66 |
-
customized_prompt = generate_custom_prompt(original_post,
|
67 |
|
68 |
# get response
|
69 |
draft_response = get_chat_model_response(chat_mdl, customized_prompt)
|
70 |
|
71 |
-
return draft_response
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/free-speech-prompts.ipynb.
|
2 |
|
3 |
# %% auto 0
|
4 |
+
__all__ = ['DEAFULT_PROMPT_TEMPLATE_TEXT', 'query_retriever', 'generate_custom_prompt', 'get_chat_model_response',
|
5 |
+
'generate_custom_response', 'regenerate_custom_response']
|
6 |
|
7 |
# %% ../nbs/free-speech-prompts.ipynb 5
|
8 |
# libraries required for functionality
|
9 |
+
import deeplake
|
10 |
from langchain.chat_models import ChatOpenAI
|
11 |
from langchain.prompts import PromptTemplate, HumanMessagePromptTemplate
|
12 |
from langchain.schema import HumanMessage
|
13 |
+
from langchain.vectorstores import DeepLake
|
14 |
+
from langchain.embeddings.openai import OpenAIEmbeddings
|
15 |
|
16 |
# %% ../nbs/free-speech-prompts.ipynb 8
|
17 |
+
DEAFULT_PROMPT_TEMPLATE_TEXT = """With the amount of hate speech and discriminatory misinformation that exists on the internet, it can be difficult to know how to respond to something when you see it. Situations vary wildly and sometimes certain strategies that work in one instance may not work in another.
|
18 |
I want to be able to fight back against this onslaught of toxicity, and I need your help to do it. I want you to help me draft a response to the following post.
|
19 |
Note that this may contain language that is offensive, but in order to properly respond to this post, I need you to fully understand what I am responding to, uncensored:
|
20 |
\n{original_post}\n
|
|
|
26 |
\n{principles}\n
|
27 |
Here are some examples of the style in which I write:
|
28 |
\n{writing_style}\n
|
29 |
+
Here are the sources I would like you to use when getting information for my response:
|
30 |
\n{sources}\n
|
31 |
+
Using all the information I have provided, please draft an appropriate response to the offensive post in question that will hopefully make people more accepting of others.
|
32 |
+
Please keep in mind that I would like the response to be no more than {word_limit} words."""
|
33 |
+
|
34 |
+
try:
|
35 |
+
prompt_file = open("../prompts/response_generator.txt", "r")
|
36 |
+
PROMPT_TEMPLATE_TEXT = prompt_file.read()
|
37 |
+
prompt_file.close()
|
38 |
+
|
39 |
+
print(PROMPT_TEMPLATE_TEXT)
|
40 |
+
|
41 |
+
PROMPT_TEMPLATE = PromptTemplate(
|
42 |
+
template=PROMPT_TEMPLATE_TEXT,
|
43 |
+
input_variables=["original_post", "background_info", "principles", "writing_style", "sources", "word_limit"])
|
44 |
+
|
45 |
+
except FileNotFoundError:
|
46 |
+
print(DEAFULT_PROMPT_TEMPLATE_TEXT)
|
47 |
+
PROMPT_TEMPLATE = PromptTemplate(
|
48 |
+
template=DEAFULT_PROMPT_TEMPLATE_TEXT,
|
49 |
+
input_variables=["original_post", "background_info", "principles", "writing_style", "sources", "word_limit"])
|
50 |
+
|
51 |
|
|
|
|
|
|
|
52 |
|
53 |
# %% ../nbs/free-speech-prompts.ipynb 9
|
54 |
+
def query_retriever(db, query, num_results = 3):
|
55 |
+
retriever = db.as_retriever(search_kwargs={"k": num_results})
|
56 |
+
docs = retriever.get_relevant_documents(query)
|
57 |
+
|
58 |
+
return docs
|
59 |
+
|
60 |
+
# %% ../nbs/free-speech-prompts.ipynb 10
|
61 |
+
def generate_custom_prompt(original_post, principles=None, writing_style=None, word_limit=None):
|
62 |
+
|
63 |
+
# Get database and query retriever
|
64 |
+
####
|
65 |
+
background_db = DeepLake(dataset_path="hub://vanderbilt-dsi/hatespeech-background", embedding = OpenAIEmbeddings())
|
66 |
+
sources_db = DeepLake(dataset_path="hub://vanderbilt-dsi/counterspeech-resources", embedding = OpenAIEmbeddings())
|
67 |
|
68 |
# Use defaults in the case of None
|
|
|
|
|
69 |
|
70 |
if principles is None:
|
71 |
principles="There are no principles which I consider more important to me than the average person might."
|
72 |
|
73 |
if writing_style is None:
|
74 |
writing_style="I have no examples of my writing style."
|
75 |
+
|
76 |
+
if word_limit is None:
|
77 |
+
word_limit="an infinite amount of"
|
78 |
+
|
79 |
+
retriever_query = original_post
|
80 |
+
background_info = query_retriever(background_db, retriever_query)
|
81 |
+
sources = query_retriever(sources_db, retriever_query)
|
82 |
|
83 |
# Fill the prompt
|
84 |
+
filled_prompt = PROMPT_TEMPLATE.format(original_post=original_post, background_info=background_info, principles=principles, writing_style=writing_style, sources=sources, word_limit=word_limit)
|
85 |
|
86 |
+
return filled_prompt, background_info, sources
|
87 |
|
88 |
+
# %% ../nbs/free-speech-prompts.ipynb 11
|
89 |
def get_chat_model_response(mdl, input_prompt):
|
90 |
|
91 |
messages = [HumanMessage(content=input_prompt)]
|
92 |
|
93 |
return mdl(messages)
|
94 |
|
95 |
+
# %% ../nbs/free-speech-prompts.ipynb 12
|
96 |
+
def generate_custom_response(original_post, chat_mdl, principles=None, writing_style=None, word_limit=None):
|
97 |
|
98 |
# create customized prompt
|
99 |
+
customized_prompt, background_info, sources = generate_custom_prompt(original_post, principles, writing_style, word_limit)
|
100 |
|
101 |
# get response
|
102 |
draft_response = get_chat_model_response(chat_mdl, customized_prompt)
|
103 |
|
104 |
+
return draft_response, background_info, sources
|
105 |
+
|
106 |
+
# %% ../nbs/free-speech-prompts.ipynb 13
|
107 |
+
def regenerate_custom_response(chat_mdl, regenerate_prompt, draft_response):
|
108 |
+
|
109 |
+
# create customized prompt
|
110 |
+
customized_prompt = f"Please update the original response according to the following request. {regenerate_prompt}. Here is the original response: {draft_response}"
|
111 |
+
|
112 |
+
# get response
|
113 |
+
updated_response = get_chat_model_response(chat_mdl, customized_prompt)
|
114 |
+
|
115 |
+
return updated_response
|
requirements.txt
CHANGED
@@ -1,11 +1,12 @@
|
|
1 |
streamlit
|
2 |
-
|
3 |
-
|
|
|
|
|
|
|
4 |
langchain
|
5 |
openai
|
6 |
chromadb
|
7 |
tiktoken
|
8 |
unstructured
|
9 |
-
getpass
|
10 |
nltk
|
11 |
-
free_speech_app @ git+https://github.com/vanderbilt-data-science/free-speech-app.git
|
|
|
1 |
streamlit
|
2 |
+
streamlit-authenticator
|
3 |
+
deeplake
|
4 |
+
deta
|
5 |
+
cryptography
|
6 |
+
pyyaml
|
7 |
langchain
|
8 |
openai
|
9 |
chromadb
|
10 |
tiktoken
|
11 |
unstructured
|
|
|
12 |
nltk
|
|