Umang Chaudhry commited on
Commit
329ead2
·
unverified ·
0 Parent(s):

Add files via upload

Browse files
README.md ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Future of Free Speech App.
2
+
3
+ In this project we’ll be creating a tool to empower people to respond to hate speech and misinformation only by creating an action dashboard that provides relevant background, and that drafts a response. that respects:
4
+
5
+ 1. The principles of the Future of Free Speech program
6
+
7
+ 2. The principles of the responder
8
+
9
+ 3. Background information on the original post
10
+
11
+ 4. Guidance on possible best responses to the original post (e.g. counter information)
12
+
13
+ 5. Style and preferences of the responder
14
+
15
+ ## Access to Beta Version Here
16
+ https://free-speech.streamlit.app/
17
+
18
+ ### Draft Main Screen
19
+ ![image](https://github.com/vanderbilt-data-science/free-speech-app/assets/5521243/9cb9dbd4-fa8d-4f18-bb7e-85fb7076f23a)
20
+
21
+ ### Draft Principles and Sources Screen
22
+ ![image](https://github.com/vanderbilt-data-science/free-speech-app/assets/5521243/95b932d8-20fb-4f94-aadb-aec71590f882)
23
+
24
+
25
+
26
+ Students who are particularly interested in this:
27
+ Eleanor Beers
28
+ Katrina Rbeiz
29
+ Sovann Chang
30
+
31
+ ## Features
32
+
33
+ - The prototype solution could be a stand-alone dashboard application into which the responder would cut-and-paste the post to which they would like to respond.
34
+ - Brainstorming ideas in the [Google drive](https://drive.google.com/drive/folders/1XvUthVpeZJ449nAEjeCPwvKy9v3oEHPd?usp=sharing)
35
+
36
+ ## Getting Started
37
+
38
+
39
+ ## Contributing
40
+
41
+ To contribute to the project, please fork the repository and submit a pull request. Our community is supportive, and we provide training and classes if you're new to any of the frameworks used in the project. Everyone is welcome to contribute, as we believe participating in data science and AI projects is an excellent way to learn.
42
+
43
+ ### How to Contribute
44
+ With `nbdev` it will always try to run every single cell of anything in the `nbs` directory. Yes, I definitely mean that it tries to execute every cell in a notebook unless you tell it not to. We tell it not to. To do this, in every new "source" notebook created in `nbs`, you need to include as a **raw** cell:
45
+ ```
46
+ ---
47
+ skip_exec: true
48
+ ---
49
+ ```
50
+ This suppresses tests. Now, it executes nothing. There's no model building, no nothing.
51
+
52
+ #### Setup
53
+ Make sure you've followed the instructions above for setup with `nbdev_install_hooks`
54
+
55
+ #### Passing GH Actions
56
+ Locally, you'll do whatever edits that you're after to finish your issue. Generally, after you've saved all of your changes locally (before you add/commit), you will run (at the command line when you're about to do all of your git operations):
57
+ ```
58
+ nbdev_prepare
59
+ ```
60
+ Now, this is when you add and commit changed files. Keep an eye out for any of the files in the `free_speech_app` module, e.g., `_modidx.py` or any new modules you have created. Make sure you add and commit them as well in this commit. Don't miss any! `nbdev_prepare` strips out metadata, builds the library (so it matches the source notebooks), runs tests, and creates docs. We're just casually avoiding the last 2 things.
61
+
62
+ This is going to help you pass your GH Actions by preparing your repo locally. If you would fail any Actions, it will tell you why they've failed locally before pushing to GH. However, for unknown reasons, sometimes you pass the `nbdev_prepare` locally while somehow failing the GH Actions remotely? If that's the case, here's some troubleshooting help.
63
+
64
+ If you're failing actions, this basically means:
65
+ * Detected unstripped out notebooks: you need to run `nbdev_prepare` which strips out all of the metadata
66
+ * Something about the library not matching the source notebooks: you need to run `nbdev_prepare` which converts your source notebooks into the modules. **Also, make sure that you have added and committed all of the .py files that you've generated or have been changed**.
67
+ * Something about nbdev_install_hooks: run `nbdev_install_hooks`
68
+ * Something about tests failed or the GH Actions log seems to look like it's trying to run code: You need to add or fix the raw code cell with `skip_exec=true` and the `yaml triple line indicators` above in all of the notebooks. Run `nbdev_prepare` and it will error out on some notebook. That tells you where you need to add that raw code cell.
69
+ * If none of these are true, your local version of nbdev might differ from the one used in GH Actions. If that's the case, hop on over to pyPI to see if there has been a recent update.
70
+
71
+ ## Community Guidelines
72
+
73
+ We aim to create a welcoming and inclusive community where everyone can feel comfortable and valued, regardless of skill level, background, ability, or identity. To ensure a positive atmosphere, please adhere to our code of conduct and community guidelines.
74
+
75
+ ## Meetings
76
+
77
+ [Zoom Link](https://vanderbilt.zoom.us/j/93382420275?pwd=Z0xrSFZJelcrY1ZCNk9xQ3A1R3Irdz09 )
78
+ - Sprint Planning: 9:30am Mondays
79
+ - Backlog Grooming: 11am Thursdays
80
+ - Retrospective: 9:30am Fridays
81
+ - Demos: Fridays at 3 pm
82
+
83
+ ## Additional Resources
84
+
85
+ - LangChain documentation
86
+ - Introduction to transformers and generative AI on our [YouTube channel](https://www.youtube.com/channel/UC8C2_3L5gR9qLmL7rmb2BdQ)
87
+ - AI Summer and AI Winter sessions (free and open to all)
88
+
89
+ ## Reporting Issues
90
+
91
+ If you encounter a bug, please submit an issue and label it with "Bug." To escalate the issue, email [[email protected]](mailto:[email protected]).
92
+
93
+ ## Contact Information
94
+
95
+ - Organization: Data Science Institute at Vanderbilt University and Future of Free Speech Program
96
+ - Main Email: [[email protected]](mailto:[email protected])
97
+ - Staff Lead: [[email protected]](mailto:[email protected])
98
+ - Staff Lead: [[email protected]](mailto:[email protected])
99
+ Data Scientists
100
+ - Eleanor Beers
101
+ - Katrina Rbeiz
102
+ - Sovann Chang
103
+
104
+
105
+ Remember to replace "Staff lead and email" with the actual name and email address of the staff lead.
106
+
107
+ ## Red Team Observations
108
+ [redteam.md](https://github.com/vanderbilt-data-science/free-speech-app/files/12718272/redteam.md)
109
+
110
+
apikeyex.png ADDED
app.py ADDED
@@ -0,0 +1,227 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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(
30
+ config['credentials'],
31
+ config['cookie']['name'],
32
+ config['cookie']['key'],
33
+ config['cookie']['expiry_days'],
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:
57
+ authenticator.logout('Logout', 'main', key='unique_key')
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
+
215
+ elif authentication_status is None:
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")
config.yaml ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ cookie:
2
+ expiry_days: 0
3
+ key: some_signature_key
4
+ name: some_cookie_name
5
+ credentials:
6
+ usernames:
7
+ umang2:
8
9
+ name: Umang Chaudhry
10
+ password: $2b$12$me2dX2o/2lD1JBHEqzq7PegGsM32S.3SS4kOyMf2Oh/jUz5GbvHAG
11
+ umangchaudhry:
12
13
+ name: Umang Chaudhry
14
+ password: $2b$12$Q.TJFPp9dcyEIpzlVtQeluYMsEIx//ei0tx7cMKBm/aNqOGaezSfi
15
+ preauthorized:
16
+ emails:
17
free_speech_app/DataLoadDb.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
10
+
11
+ from langchain.chains import RetrievalQA
12
+ from langchain.llms import OpenAI
13
+ from langchain.prompts import PromptTemplate
14
+ from langchain.document_loaders import UnstructuredFileLoader
15
+ from langchain.document_loaders.merge import MergedDataLoader
16
+ 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 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])
40
+
41
+ # Split and embed docs
42
+ documents = loader_all.load()
43
+ text_splitter = CharacterTextSplitter(chunk_size=chunk_size, chunk_overlap=chunk_overlap)
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 ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
21
+ In helping me respond to this post, there are some things you may want to consider. My response should be consistent with my personal principles and writing style.
22
+ There may be additional information that would be useful for you to understand the context of the original post, and there may be specific sources I would like you to use when coming up with information for the response.
23
+ Firstly, here is some additional context related to the original post:
24
+ \n{background_info}\n
25
+ Next, here are some principles I consider particularly important to me:
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 ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
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