dlflannery commited on
Commit
0ffb480
·
verified ·
1 Parent(s): 7ef4ab6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +113 -23
app.py CHANGED
@@ -26,6 +26,9 @@ import numpy as np
26
  from pylatexenc.latex2text import LatexNodes2Text
27
  import requests
28
  from urllib.parse import quote
 
 
 
29
 
30
  load_dotenv(override=True)
31
  key = os.getenv('OPENAI_API_KEY')
@@ -37,6 +40,7 @@ DEEPSEEK_KEY=os.getenv('DEEPSEEK_KEY')
37
  GROQ_KEY=os.getenv('GROQ_KEY')
38
  BRAVE_KEY=os.getenv('BRAVE_KEY')
39
  BRAVE_SEARCH_KEY=os.getenv('BRAVE_SEARCH_KEY')
 
40
 
41
  site = os.getenv('SITE')
42
  if site == 'local':
@@ -64,6 +68,12 @@ special_chat_types = ['math', 'logic']
64
 
65
  news_interval_choices = [("Day", "pd"), ("Week", "pw"), ("Month", "pm"), ("Year", "py")]
66
 
 
 
 
 
 
 
67
  def get_openai_file(file_id, container_id):
68
  url = f'https://api.openai.com/v1/containers/{container_id}/files/{file_id}/content'
69
  headers= {"Authorization": "Bearer " + key}
@@ -753,14 +763,8 @@ def updatePassword(txt):
753
  # ref = len(txt[ref:loc]) + len(frag)
754
  # return txt
755
 
756
- def get_response(prompt, previous_response_id, container_id):
757
- if prompt.casefold().find('code') > -1:
758
- instructions = '''
759
- You are a personal math tutor. When asked a math question,
760
- write and run code using the python tool to answer the question.
761
- '''
762
- else:
763
- instructions = '''
764
  You are a helpful assistant who knows how to browse the web for info and to write and run python
765
  code.
766
  '''
@@ -769,15 +773,47 @@ Do not use latex for math expressions in text output.
769
  If a chart, table or plot is produced, return it as an image.
770
  If a powerpoint slide is created, return it as an image but do not offer a download link.
771
  If the user asks you to output a file, You must include the file you generate in the annotation
772
- of the output text using a markdown url link in this format as an example: sandbox:/mnt/data/int100.txt
773
  '''
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
774
  response = Client().responses.create(
775
  model= "gpt-5-mini", #"gpt-5-mini", "o4-mini",
776
  tools=[{ "type": "web_search_preview" },
777
- { "type": "code_interpreter", "container": container_id}], # {'type': 'auto'}}],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
778
  previous_response_id=previous_response_id,
779
  instructions = instructions,
780
- input=prompt,
781
  reasoning ={
782
  "effort": "medium",
783
  "summary": "auto"
@@ -863,18 +899,28 @@ def chat(prompt, user_window, pwd_window, past, response, gptModel, uploaded_ima
863
  using_groq = False
864
  reasoning = False
865
  prompt = prompt.strip()
866
- if mode == 'Advanced': # and isBoss:
 
 
 
 
 
 
 
 
 
867
  if len(past) == 0:
868
- prev_id = None
869
  container_id = create_openai_container('My Container')
 
 
 
870
  else:
871
- (prev_id, container_id) = past[-1]
872
- past.pop()
873
- response = ''
874
  for item in past:
875
  response += item
876
  try:
877
- result = get_response(prompt, prev_id, container_id)
 
878
  except:
879
  return [[], "Sorry, there was an error getting the AI response",
880
  prompt, gptModel, uploaded_image_file, plot, image_out, file_out]
@@ -882,6 +928,7 @@ def chat(prompt, user_window, pwd_window, past, response, gptModel, uploaded_ima
882
  image_done = False
883
  ann_files = [] # (container_id, file_id, filename)
884
  code_files = [] # (container_id, file_id, filename)
 
885
  for output in result.output:
886
  if output.type == 'message':
887
  for content in output.content:
@@ -919,15 +966,53 @@ def chat(prompt, user_window, pwd_window, past, response, gptModel, uploaded_ima
919
  code_files.append((cont_id, file_id, file_name))
920
  except:
921
  pass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
922
  do_file_download = False
 
 
923
  if len(ann_files) > 0:
924
  (cont_id, file_id, file_name) = ann_files[-1]
 
925
  do_file_download = True
926
  elif len(code_files) > 0:
927
- (cont_id, file_id, file_name) = code_files[0]
928
- do_file_download = True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
929
  if do_file_download:
930
- ext = file_name.split('.')[-1]
931
  fpath = dataDir + user_window + '.' + ext
932
  try:
933
  data = get_openai_file(file_id, cont_id).content
@@ -938,6 +1023,10 @@ def chat(prompt, user_window, pwd_window, past, response, gptModel, uploaded_ima
938
  except:
939
  text += f'\nUnable to load code-generated file: {file_name}'
940
  # text += '\nIf a download link is given above, ignore it. Use the button below'
 
 
 
 
941
  out_text = "\n".join(line for line in text.splitlines() if
942
  'download' not in line.casefold())
943
  res = md("\n\n***YOU***: " + prompt + "\n\n***GPT***: " + out_text)
@@ -1289,10 +1378,10 @@ def show_help():
1289
  can edit what's to be spoken. Except: In a chat conversation, spoken dialog will only include
1290
  the latest prompt/response ("YOU:/GPT:") sequence.'''
1291
  return str(txt).replace('```', ' ').replace(' ', '&nbsp;&nbsp;').replace(' ', '&nbsp;&nbsp;').replace(' ', '&nbsp;&nbsp;').replace('\n','<br>')
1292
- def upload_image(prompt, user, password):
1293
  if not (user in unames and password == pwdList[unames.index(user)]):
1294
  return [gr.Image(visible=False, interactive=True), "Incorrect user name and/or password"]
1295
- if len(prompt) < 3:
1296
  return [gr.Image(visible=False, interactive=True), "You must provide prompt/instructions (what to do with the image)"]
1297
  return [gr.Image(visible=True, interactive=True), '']
1298
 
@@ -1518,7 +1607,8 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
1518
  button_do_image.click(fn=make_image, inputs=[prompt_window,user_window, password],outputs=[image_window, output_window])
1519
  image_window.change(fn=delete_image, inputs=[user])
1520
  help_button.click(fn=show_help, outputs=output_window)
1521
- button_get_image.click(fn=upload_image,inputs = [prompt_window, user, password], outputs = [image_window2, output_window])
 
1522
  image_window2.upload(fn=load_image, inputs=[image_window2, user], outputs=[uploaded_image_file, output_window])
1523
  mode.change(fn=mode_change, inputs=mode,outputs=news_period)
1524
  pwd_window.blur(updatePassword, inputs = pwd_window, outputs = [password, pwd_window, mode])
 
26
  from pylatexenc.latex2text import LatexNodes2Text
27
  import requests
28
  from urllib.parse import quote
29
+ import geo_distance
30
+ import geo_locate
31
+
32
 
33
  load_dotenv(override=True)
34
  key = os.getenv('OPENAI_API_KEY')
 
40
  GROQ_KEY=os.getenv('GROQ_KEY')
41
  BRAVE_KEY=os.getenv('BRAVE_KEY')
42
  BRAVE_SEARCH_KEY=os.getenv('BRAVE_SEARCH_KEY')
43
+ LOCATIONID_KEY=os.getenv('LOCATIONID_KEY')
44
 
45
  site = os.getenv('SITE')
46
  if site == 'local':
 
68
 
69
  news_interval_choices = [("Day", "pd"), ("Week", "pw"), ("Month", "pm"), ("Year", "py")]
70
 
71
+ def get_distance(addr1, addr2):
72
+ (lat1, lon1) = geo_locate.get_geo_coords(addr1, LOCATIONID_KEY)
73
+ (lat2, lon2) = geo_locate.get_geo_coords(addr2, LOCATIONID_KEY)
74
+ distance = geo_distance.great_circle_distance_miles(lat1, lon1, lat2, lon2)
75
+ return distance
76
+
77
  def get_openai_file(file_id, container_id):
78
  url = f'https://api.openai.com/v1/containers/{container_id}/files/{file_id}/content'
79
  headers= {"Authorization": "Bearer " + key}
 
763
  # ref = len(txt[ref:loc]) + len(frag)
764
  # return txt
765
 
766
+ def get_response(inputs, previous_response_id, container_id, image_file):
767
+ instructions = '''
 
 
 
 
 
 
768
  You are a helpful assistant who knows how to browse the web for info and to write and run python
769
  code.
770
  '''
 
773
  If a chart, table or plot is produced, return it as an image.
774
  If a powerpoint slide is created, return it as an image but do not offer a download link.
775
  If the user asks you to output a file, You must include the file you generate in the annotation
776
+ of the output text.
777
  '''
778
+ if image_file != '':
779
+ with open(image_file, 'rt') as fp:
780
+ b64data = fp.read()
781
+ inputs.append(
782
+ {
783
+ "role": "user",
784
+ "content": [
785
+ {
786
+ "type": "input_image",
787
+ "image_url": f'data:image/jpeg;base64, {b64data}',
788
+ }
789
+ ]
790
+ }
791
+ )
792
+
793
  response = Client().responses.create(
794
  model= "gpt-5-mini", #"gpt-5-mini", "o4-mini",
795
  tools=[{ "type": "web_search_preview" },
796
+ { "type": "code_interpreter", "container": container_id}, #{'type': 'auto'}},
797
+ {"type": "function", "name": "get_distance",
798
+ "description": "get calculated straight-line (great-circle) distance between two locations or addresses.",
799
+ "parameters": {
800
+ "type": "object", "properties": {
801
+ "addr1": {
802
+ "type": "string",
803
+ "description": "The street address or other designation of a location.",
804
+ },
805
+ "addr2": {
806
+ "type": "string",
807
+ "description": "The street address or other designation of a location.",
808
+ },
809
+ },
810
+ "required": ["addr1", "addr2"],
811
+ },
812
+ },
813
+ ],
814
  previous_response_id=previous_response_id,
815
  instructions = instructions,
816
+ input=inputs,
817
  reasoning ={
818
  "effort": "medium",
819
  "summary": "auto"
 
899
  using_groq = False
900
  reasoning = False
901
  prompt = prompt.strip()
902
+ need_turn = True
903
+ responses = []
904
+ inputs = []
905
+ prev_id = None
906
+ if mode == "Advanced":
907
+ if len(past):
908
+ (prev_id, container_id) = past.pop()
909
+ past = []
910
+ while mode == 'Advanced' and need_turn:
911
+ need_turn = False
912
  if len(past) == 0:
 
913
  container_id = create_openai_container('My Container')
914
+ inputs.append(
915
+ {"role": "user", "content": f"{prompt}"}
916
+ )
917
  else:
918
+ (prev_id, container_id) = past.pop()
 
 
919
  for item in past:
920
  response += item
921
  try:
922
+ result = get_response(inputs, prev_id, container_id, uploaded_image_file)
923
+ uploaded_image_file = ''
924
  except:
925
  return [[], "Sorry, there was an error getting the AI response",
926
  prompt, gptModel, uploaded_image_file, plot, image_out, file_out]
 
928
  image_done = False
929
  ann_files = [] # (container_id, file_id, filename)
930
  code_files = [] # (container_id, file_id, filename)
931
+ text = '??? AI returned no text for this query'
932
  for output in result.output:
933
  if output.type == 'message':
934
  for content in output.content:
 
966
  code_files.append((cont_id, file_id, file_name))
967
  except:
968
  pass
969
+ elif output.type == 'function_call':
970
+ if output.name == 'get_distance':
971
+ args = json.loads(output.arguments)
972
+ distance = get_distance(args['addr1'], args['addr2'])
973
+ inputs.append({
974
+ "type": "function_call_output",
975
+ "call_id": f"{output.call_id}",
976
+ "output": f"{float(distance):.2f}",
977
+ } )
978
+ need_turn = True
979
+ continue
980
+ elif output.type == 'image_generation_call':
981
+ if result and not image_done:
982
+ image_done = True;
983
+ image_data = base64.b64decode(result)
984
+ fpath = dataDir + user_window + '.png'
985
+ with open(fpath,'wb') as fp:
986
+ fp.write(image_data)
987
+ image_out = gr.Image(visible=True, value=fpath)
988
  do_file_download = False
989
+ ext = ''
990
+ backup_image = None
991
  if len(ann_files) > 0:
992
  (cont_id, file_id, file_name) = ann_files[-1]
993
+ ext = file_name.split('.')[-1].casefold()
994
  do_file_download = True
995
  elif len(code_files) > 0:
996
+ for i in range(len(code_files)):
997
+ (cont_id, file_id, file_name) = code_files[i]
998
+ if file_name.casefold().find('access') >= 0:
999
+ continue
1000
+ ext = file_name.split('.')[-1].casefold()
1001
+ if ext == 'png':
1002
+ if not image_done:
1003
+ backup_image = code_files[i]
1004
+ else:
1005
+ do_file_download = True
1006
+ break
1007
+ if not do_file_download and not image_done and backup_image:
1008
+ (cont_id, file_id, file_name) = backup_image
1009
+ fpath = dataDir + user_window + '.png'
1010
+ image_data = get_openai_file(file_id, cont_id).content
1011
+ with open(fpath,'wb') as fp:
1012
+ fp.write(image_data)
1013
+ image_out = gr.Image(visible=True, value=fpath)
1014
+
1015
  if do_file_download:
 
1016
  fpath = dataDir + user_window + '.' + ext
1017
  try:
1018
  data = get_openai_file(file_id, cont_id).content
 
1023
  except:
1024
  text += f'\nUnable to load code-generated file: {file_name}'
1025
  # text += '\nIf a download link is given above, ignore it. Use the button below'
1026
+ if need_turn:
1027
+ # past.append(md(prompt))
1028
+ past.append((result.id, container_id))
1029
+ continue
1030
  out_text = "\n".join(line for line in text.splitlines() if
1031
  'download' not in line.casefold())
1032
  res = md("\n\n***YOU***: " + prompt + "\n\n***GPT***: " + out_text)
 
1378
  can edit what's to be spoken. Except: In a chat conversation, spoken dialog will only include
1379
  the latest prompt/response ("YOU:/GPT:") sequence.'''
1380
  return str(txt).replace('```', ' ').replace(' ', '&nbsp;&nbsp;').replace(' ', '&nbsp;&nbsp;').replace(' ', '&nbsp;&nbsp;').replace('\n','<br>')
1381
+ def upload_image(prompt, user, password, mode):
1382
  if not (user in unames and password == pwdList[unames.index(user)]):
1383
  return [gr.Image(visible=False, interactive=True), "Incorrect user name and/or password"]
1384
+ if len(prompt) < 3 and mode != 'Advanced':
1385
  return [gr.Image(visible=False, interactive=True), "You must provide prompt/instructions (what to do with the image)"]
1386
  return [gr.Image(visible=True, interactive=True), '']
1387
 
 
1607
  button_do_image.click(fn=make_image, inputs=[prompt_window,user_window, password],outputs=[image_window, output_window])
1608
  image_window.change(fn=delete_image, inputs=[user])
1609
  help_button.click(fn=show_help, outputs=output_window)
1610
+ button_get_image.click(fn=upload_image,inputs = [prompt_window, user, password, mode],
1611
+ outputs = [image_window2, output_window])
1612
  image_window2.upload(fn=load_image, inputs=[image_window2, user], outputs=[uploaded_image_file, output_window])
1613
  mode.change(fn=mode_change, inputs=mode,outputs=news_period)
1614
  pwd_window.blur(updatePassword, inputs = pwd_window, outputs = [password, pwd_window, mode])