Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
@@ -7,19 +7,12 @@ import json
|
|
7 |
from jinja2 import Template
|
8 |
import requests
|
9 |
|
10 |
-
# Initialize OpenAI
|
11 |
-
openai.api_key = os.environ.get('OPENAI_API_KEY')
|
12 |
-
|
13 |
# Configuration variables
|
14 |
airtable_api_key = os.environ.get('AIRTABLE_API_KEY')
|
15 |
|
16 |
-
# Airtable table names
|
17 |
-
policies_table_name = 'tbla6PC65qZfqdJhE'
|
18 |
-
prompts_table_name = 'tblYIZEB8m6JkGDEP'
|
19 |
-
qalog_table_name = 'tbl4oNgFPWM5xH1XO'
|
20 |
examples_table_name = 'tblu7sraOEmRgEGkp'
|
21 |
-
|
22 |
-
|
23 |
|
24 |
# Define the style and content for the response field
|
25 |
label_text = "NILI Response"
|
@@ -28,9 +21,6 @@ background_color = "white"
|
|
28 |
border_radius = "10px"
|
29 |
response_label = f'<span style="display: inline-block; position: relative; z-index: var(--layer-4); border: solid var(--block-title-border-width) var(--block-title-border-color); border-radius: var(--block-title-radius); background: var(--block-title-background-fill); padding: var(--block-title-padding); color: var(--block-title-text-color); font-weight: var(--block-title-text-weight); font-size: var(--block-title-text-size); line-height: var(--line-sm); margin-bottom: var(--spacing-lg);">{label_text}</span>'
|
30 |
|
31 |
-
#Airtable Base ID
|
32 |
-
base_id = 'appcUK3hUWC7GM2Kb'
|
33 |
-
|
34 |
#Name of the prompt temlate record
|
35 |
#prompt_name = "NILI_v1"
|
36 |
|
@@ -44,133 +34,6 @@ headers = {
|
|
44 |
"Accept": "application/json",
|
45 |
}
|
46 |
|
47 |
-
def set_defaults(request: gr.Request):
|
48 |
-
|
49 |
-
if request.username:
|
50 |
-
print(request.username)
|
51 |
-
else:
|
52 |
-
print("No User Name")
|
53 |
-
|
54 |
-
return
|
55 |
-
|
56 |
-
#Function to trim prompts....not used
|
57 |
-
def prompt_trim(prompt: str) -> str:
|
58 |
-
lines = prompt.split('\n')
|
59 |
-
trimmed = '\n'.join([l.strip() for l in lines])
|
60 |
-
return trimmed
|
61 |
-
|
62 |
-
#Get the policies for the selected schools and concatenate them.
|
63 |
-
def get_policies(user_school):
|
64 |
-
|
65 |
-
airtable_endpoint = f'https://api.airtable.com/v0/{base_id}/{policies_table_name}'
|
66 |
-
|
67 |
-
# Parameters for the API request to filter by 'school' field and retrieve 'policy_text'
|
68 |
-
params = {
|
69 |
-
'filterByFormula': f'school = "{user_school}"',
|
70 |
-
'fields[]': 'policy_text' # Replace with the name of your field
|
71 |
-
}
|
72 |
-
|
73 |
-
# Initialize an empty string to store concatenated policies
|
74 |
-
concatenated_policies = ''
|
75 |
-
|
76 |
-
#print(params)
|
77 |
-
|
78 |
-
try:
|
79 |
-
# Send a GET request to the Airtable API
|
80 |
-
response = requests.get(airtable_endpoint, headers=headers, params=params)
|
81 |
-
|
82 |
-
# Check if the request was successful (status code 200)
|
83 |
-
if response.status_code == 200:
|
84 |
-
# Parse the JSON response
|
85 |
-
data = response.json()
|
86 |
-
|
87 |
-
# Check if there are records in the response
|
88 |
-
if data.get('records'):
|
89 |
-
|
90 |
-
# Extract the 'policy_text' values from each record and concatenate them
|
91 |
-
for record in data['records']:
|
92 |
-
policy_text = record['fields']['policy_text']
|
93 |
-
if concatenated_policies:
|
94 |
-
concatenated_policies += "\n----------\n"
|
95 |
-
concatenated_policies += policy_text
|
96 |
-
|
97 |
-
else:
|
98 |
-
print("No records found in the 'policies' table for the selected schools.")
|
99 |
-
else:
|
100 |
-
print(f"Failed to retrieve data. Status code: {response.status_code}")
|
101 |
-
except Exception as e:
|
102 |
-
print(f"An error occurred: {str(e)}")
|
103 |
-
|
104 |
-
#print(concatenated_policies)
|
105 |
-
|
106 |
-
return concatenated_policies
|
107 |
-
|
108 |
-
#Get a list of School Name from the policies for the UI dropdown
|
109 |
-
def get_schools():
|
110 |
-
|
111 |
-
airtable_endpoint = f'https://api.airtable.com/v0/{base_id}/{policies_table_name}'
|
112 |
-
|
113 |
-
# Parameters for the API request to select only the 'school' field
|
114 |
-
params = {
|
115 |
-
'filterByFormula': f'app = "{app}"',
|
116 |
-
'fields[]': 'school', # Replace with the name of your field
|
117 |
-
'sort[0][field]': 'school', # Sort by the 'school' field
|
118 |
-
'sort[0][direction]': 'asc', # Sort in ascending order
|
119 |
-
}
|
120 |
-
|
121 |
-
schools = []
|
122 |
-
|
123 |
-
try:
|
124 |
-
# Send a GET request to the Airtable API
|
125 |
-
response = requests.get(airtable_endpoint, headers=headers, params=params)
|
126 |
-
|
127 |
-
# Check if the request was successful (status code 200)
|
128 |
-
if response.status_code == 200:
|
129 |
-
# Parse the JSON response
|
130 |
-
data = response.json()
|
131 |
-
|
132 |
-
# Check if there are records in the response
|
133 |
-
if data.get('records'):
|
134 |
-
# Extract the 'school' values from each record
|
135 |
-
schools = [record['fields']['school'] for record in data['records']]
|
136 |
-
|
137 |
-
|
138 |
-
else:
|
139 |
-
print("No records found in the 'policies' table.")
|
140 |
-
else:
|
141 |
-
print(f"Failed to retrieve data. Status code: {response.status_code}")
|
142 |
-
except Exception as e:
|
143 |
-
print(f"An error occurred: {str(e)}")
|
144 |
-
|
145 |
-
return schools
|
146 |
-
|
147 |
-
#Get the designated prompt template record
|
148 |
-
def get_prompt(header, template_content):
|
149 |
-
|
150 |
-
airtable_endpoint = f'https://api.airtable.com/v0/{base_id}/{prompts_table_name}'
|
151 |
-
|
152 |
-
params = {
|
153 |
-
'filterByFormula': "prompt_name='NILI_v1'"
|
154 |
-
}
|
155 |
-
|
156 |
-
response = requests.get(airtable_endpoint, headers=headers, params=params)
|
157 |
-
|
158 |
-
# Check for errors
|
159 |
-
response.raise_for_status()
|
160 |
-
|
161 |
-
data = response.json()
|
162 |
-
|
163 |
-
# Check if there is at least one record matching the condition
|
164 |
-
if data.get('records'):
|
165 |
-
# Get the first record (there should be only one)
|
166 |
-
record = data['records'][0]['fields']
|
167 |
-
|
168 |
-
# Assign system_prompt and user_prompt to variables
|
169 |
-
header = record.get('system_prompt', '')
|
170 |
-
template_content = record.get('user_prompt', '')
|
171 |
-
|
172 |
-
return header, template_content
|
173 |
-
|
174 |
|
175 |
def get_examples():
|
176 |
|
@@ -201,216 +64,23 @@ def get_examples():
|
|
201 |
|
202 |
return ui_examples
|
203 |
|
204 |
-
def append_to_at_qalog(your_role, school_selection, output_format, input_text, gpt_response,response_time,question_cost,prompt_tokens,completion_tokens):
|
205 |
-
|
206 |
-
airtable_endpoint = f'https://api.airtable.com/v0/{base_id}/{qalog_table_name}'
|
207 |
-
|
208 |
-
# Organize data for Airtable
|
209 |
-
new_fields = {
|
210 |
-
'your_role': str(your_role),
|
211 |
-
'school_selection': str(school_selection),
|
212 |
-
'output_format': str(output_format),
|
213 |
-
'input_text': str(input_text),
|
214 |
-
'gpt_response': str(gpt_response),
|
215 |
-
'response_time': str(response_time),
|
216 |
-
'question_cost': question_cost,
|
217 |
-
'user_name': str(logged_in_user),
|
218 |
-
'prompt_tokens': prompt_tokens,
|
219 |
-
'completion_tokens': completion_tokens
|
220 |
-
}
|
221 |
-
|
222 |
-
data = {
|
223 |
-
'fields': new_fields
|
224 |
-
}
|
225 |
-
try:
|
226 |
-
# Post data to Airtable
|
227 |
-
response = requests.post(airtable_endpoint, headers=headers, json=data)
|
228 |
-
|
229 |
-
# Check for errors
|
230 |
-
response.raise_for_status()
|
231 |
-
|
232 |
-
except requests.exceptions.HTTPError as http_error:
|
233 |
-
# Handle the HTTP error (e.g., log it or display an error message)
|
234 |
-
print(f"HTTP error occurred: {http_error}")
|
235 |
-
|
236 |
-
except Exception as e:
|
237 |
-
# Handle exceptions, log errors, or raise them as needed
|
238 |
-
print(f"An error occurred: {str(e)}")
|
239 |
-
|
240 |
-
#Chatbot Function
|
241 |
-
def chatbot(school_ddss,input_text):
|
242 |
-
|
243 |
-
start_time = datetime.datetime.now()
|
244 |
-
|
245 |
-
school_text = school_ddss
|
246 |
-
|
247 |
-
# Read the Hydrated policies
|
248 |
-
policies = get_policies(school_text)
|
249 |
-
|
250 |
-
template_content = ''
|
251 |
-
header = ''
|
252 |
-
|
253 |
-
header, template_content = get_prompt(header, template_content)
|
254 |
-
|
255 |
-
header_template = Template(header)
|
256 |
-
|
257 |
-
#merged_header = header_template.render(your_role=your_role)
|
258 |
-
merged_header = header_template.render(your_role=user_user_role)
|
259 |
-
|
260 |
-
# Create a Jinja2 template from the content
|
261 |
-
template = Template(template_content)
|
262 |
-
|
263 |
-
# Render the template with the policy JSON
|
264 |
-
analysis_input = template.render(policies=policies, question=input_text,format=user_output_format,your_role=user_user_role)
|
265 |
-
trimmed_input = prompt_trim(analysis_input)
|
266 |
-
|
267 |
-
response = openai.ChatCompletion.create(
|
268 |
-
model="gpt-4",
|
269 |
-
temperature=0,
|
270 |
-
messages=[
|
271 |
-
{
|
272 |
-
"role": "system",
|
273 |
-
"content": merged_header
|
274 |
-
},
|
275 |
-
{
|
276 |
-
"role": "user",
|
277 |
-
"content": analysis_input
|
278 |
-
}
|
279 |
-
]
|
280 |
-
)
|
281 |
-
|
282 |
-
gpt_response = response.choices[0].message["content"]
|
283 |
-
|
284 |
-
tokens_used = response.usage
|
285 |
-
question_cost = (tokens_used.get('total_tokens', 0) / 1000) * .03
|
286 |
-
prompt_tokens = tokens_used.get('prompt_tokens',)
|
287 |
-
completion_tokens = tokens_used.get('completion_tokens', 0)
|
288 |
-
|
289 |
-
end_time = datetime.datetime.now()
|
290 |
-
response_time = end_time - start_time
|
291 |
-
|
292 |
-
append_to_at_qalog(user_user_role, school_text, user_output_format, input_text, gpt_response, response_time,
|
293 |
-
question_cost, prompt_tokens, completion_tokens)
|
294 |
-
|
295 |
-
return {nili_response_html: gpt_response}
|
296 |
-
|
297 |
-
def log_login(username):
|
298 |
-
|
299 |
-
airtable_endpoint = f'https://api.airtable.com/v0/{base_id}/{user_log_table_name}'
|
300 |
-
|
301 |
-
# Organize data for Airtable
|
302 |
-
new_fields = {
|
303 |
-
'user_name': str(username),
|
304 |
-
'app': str(app)
|
305 |
-
}
|
306 |
-
|
307 |
-
data = {
|
308 |
-
'fields': new_fields
|
309 |
-
}
|
310 |
-
|
311 |
-
try:
|
312 |
-
# Post data to Airtable
|
313 |
-
response = requests.post(airtable_endpoint, headers=headers, json=data)
|
314 |
-
|
315 |
-
# Check for errors
|
316 |
-
response.raise_for_status()
|
317 |
-
|
318 |
-
except requests.exceptions.HTTPError as http_error:
|
319 |
-
# Handle the HTTP error (e.g., log it or display an error message)
|
320 |
-
print(f"HTTP error occurred: {http_error}")
|
321 |
-
|
322 |
-
except Exception as e:
|
323 |
-
# Handle exceptions, log errors, or raise them as needed
|
324 |
-
print(f"An error occurred: {str(e)}")
|
325 |
-
|
326 |
-
|
327 |
-
def login_auth(username, password):
|
328 |
-
|
329 |
-
airtable_endpoint = f'https://api.airtable.com/v0/{base_id}/{users_table_name}'
|
330 |
-
|
331 |
-
# Query the 'users' table to check for a match with the provided username and password
|
332 |
-
params = {
|
333 |
-
'filterByFormula': f'AND(user_name = "{username}", password = "{password}")'
|
334 |
-
}
|
335 |
-
|
336 |
-
response = requests.get(airtable_endpoint, headers=headers, params=params)
|
337 |
-
|
338 |
-
if response.status_code == 200:
|
339 |
-
data = response.json()
|
340 |
-
#If the matching user/password record is found:
|
341 |
-
if data.get('records'):
|
342 |
-
|
343 |
-
user_details = data['records'][0]['fields']
|
344 |
-
|
345 |
-
log_login(username)
|
346 |
-
|
347 |
-
#Set the global logged_in_user variable. This used in the append_to_at_qalog function to track what user asked the question
|
348 |
-
global logged_in_user,user_user_role, user_output_format, user_school
|
349 |
-
user_user_role = user_details.get('user_role')
|
350 |
-
user_output_format = user_details.get('output_format')
|
351 |
-
user_school = user_details.get('school_name', [None])[0]
|
352 |
-
logged_in_user = username
|
353 |
-
|
354 |
-
return True
|
355 |
-
|
356 |
-
print(f"Invalid user/password combination")
|
357 |
-
|
358 |
-
return False
|
359 |
-
|
360 |
#Gradio UI
|
361 |
-
#CIMStheme = gr.themes.Soft().set(button_primary_background_fill='#6562F4',body_background_fill='#e6effc')
|
362 |
CIMStheme = gr.themes.Soft().set(button_primary_background_fill='#6562F4')
|
363 |
|
364 |
-
# Initialize an empty list to store the examples
|
365 |
-
#ui_examples = []
|
366 |
-
|
367 |
-
school_selection = []
|
368 |
-
#username_text = ""
|
369 |
-
|
370 |
-
#Gets the school for the school selection DD
|
371 |
-
schools = get_schools()
|
372 |
-
|
373 |
-
#This code runs first before the login screen, so if there's no login screen used, this sets the logged_in_user. Otherwise it is set in the login function.
|
374 |
-
logged_in_user = 'admin'
|
375 |
-
#global user_user_role, user_output_format, user_school
|
376 |
-
user_user_role = "Student Athlete"
|
377 |
-
user_output_format = "Table"
|
378 |
-
#user_school = []
|
379 |
-
|
380 |
with gr.Blocks(CIMStheme) as iface:
|
381 |
-
#with gr.Row():
|
382 |
-
#with gr.Column():
|
383 |
-
#gr.Image(label="Logo",value="CIMS Logo Purple.png",height=100,show_download_button=False,interactive=False,show_label=False,elem_id="logo",container=False)
|
384 |
with gr.Row():
|
385 |
with gr.Column():
|
386 |
gr.Markdown(value="<H2 style='text-align: center;'>NILI - Powered by CIMS.AI</h2>")
|
387 |
-
with gr.Row():
|
388 |
-
with gr.Column(variant='panel'):
|
389 |
-
school_ddss = gr.components.Dropdown(schools, multiselect=False, info="Select your school.", label="School")
|
390 |
with gr.Row():
|
391 |
with gr.Column(variant='panel'):
|
392 |
question_tbox= gr.components.Textbox(lines=3, placeholder="Enter your question here", label="NIL Question",info="Depending the scope of your question, results may take 30-60 sec.",interactive=True)
|
393 |
with gr.Row(variant='panel'):
|
394 |
with gr.Column():
|
395 |
examples_cmpt= gr.Examples(examples=get_examples(),inputs=question_tbox,label="Sample NIL questions - Click to select one")
|
396 |
-
with gr.Row():
|
397 |
-
with gr.Column():
|
398 |
-
submit_btn = gr.components.Button(value="Submit", size='sm', variant="primary")
|
399 |
-
with gr.Row():
|
400 |
-
with gr.Column(variant='panel'):
|
401 |
-
response_label_md = gr.components.Markdown(response_label)
|
402 |
-
nili_response_html = gr.components.HTML(label="NILI Response")
|
403 |
-
submit_btn.click(fn=chatbot,inputs=[school_ddss, question_tbox],
|
404 |
-
outputs=[nili_response_html])
|
405 |
with gr.Row():
|
406 |
with gr.Column():
|
407 |
gr.Markdown(value="[Ask Questions/Provide Feedback](https://discord.com/channels/1168589934244929647/1168589934244929650)")
|
408 |
with gr.Row():
|
409 |
with gr.Column():
|
410 |
gr.HTML('<center><i>© 2023 Collegiate Influencer Marketing Systems, Inc.</i><br>CIMS.AI, CIMS.AI logo, NILI, NILI logo, and EzNIL are trademarks of Collegiate Influencer Marketing Systems, Inc.</center>')
|
411 |
-
|
412 |
-
#iface.load(fn=set_defaults)
|
413 |
-
|
414 |
-
#iface.launch(auth=login_auth, auth_message= "Enter your username and password that you received from CIMS.AI. To request a login, please email 'info@cims.ai'")
|
415 |
-
#iface.launch(auth=("admin","admin"))
|
416 |
iface.launch()
|
|
|
7 |
from jinja2 import Template
|
8 |
import requests
|
9 |
|
|
|
|
|
|
|
10 |
# Configuration variables
|
11 |
airtable_api_key = os.environ.get('AIRTABLE_API_KEY')
|
12 |
|
|
|
|
|
|
|
|
|
13 |
examples_table_name = 'tblu7sraOEmRgEGkp'
|
14 |
+
#Airtable Base ID
|
15 |
+
base_id = 'appcUK3hUWC7GM2Kb'
|
16 |
|
17 |
# Define the style and content for the response field
|
18 |
label_text = "NILI Response"
|
|
|
21 |
border_radius = "10px"
|
22 |
response_label = f'<span style="display: inline-block; position: relative; z-index: var(--layer-4); border: solid var(--block-title-border-width) var(--block-title-border-color); border-radius: var(--block-title-radius); background: var(--block-title-background-fill); padding: var(--block-title-padding); color: var(--block-title-text-color); font-weight: var(--block-title-text-weight); font-size: var(--block-title-text-size); line-height: var(--line-sm); margin-bottom: var(--spacing-lg);">{label_text}</span>'
|
23 |
|
|
|
|
|
|
|
24 |
#Name of the prompt temlate record
|
25 |
#prompt_name = "NILI_v1"
|
26 |
|
|
|
34 |
"Accept": "application/json",
|
35 |
}
|
36 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
|
38 |
def get_examples():
|
39 |
|
|
|
64 |
|
65 |
return ui_examples
|
66 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
#Gradio UI
|
|
|
68 |
CIMStheme = gr.themes.Soft().set(button_primary_background_fill='#6562F4')
|
69 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
with gr.Blocks(CIMStheme) as iface:
|
|
|
|
|
|
|
71 |
with gr.Row():
|
72 |
with gr.Column():
|
73 |
gr.Markdown(value="<H2 style='text-align: center;'>NILI - Powered by CIMS.AI</h2>")
|
|
|
|
|
|
|
74 |
with gr.Row():
|
75 |
with gr.Column(variant='panel'):
|
76 |
question_tbox= gr.components.Textbox(lines=3, placeholder="Enter your question here", label="NIL Question",info="Depending the scope of your question, results may take 30-60 sec.",interactive=True)
|
77 |
with gr.Row(variant='panel'):
|
78 |
with gr.Column():
|
79 |
examples_cmpt= gr.Examples(examples=get_examples(),inputs=question_tbox,label="Sample NIL questions - Click to select one")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
with gr.Row():
|
81 |
with gr.Column():
|
82 |
gr.Markdown(value="[Ask Questions/Provide Feedback](https://discord.com/channels/1168589934244929647/1168589934244929650)")
|
83 |
with gr.Row():
|
84 |
with gr.Column():
|
85 |
gr.HTML('<center><i>© 2023 Collegiate Influencer Marketing Systems, Inc.</i><br>CIMS.AI, CIMS.AI logo, NILI, NILI logo, and EzNIL are trademarks of Collegiate Influencer Marketing Systems, Inc.</center>')
|
|
|
|
|
|
|
|
|
|
|
86 |
iface.launch()
|