server.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. # *********************************************************
  2. # * *
  3. # * This server is used to interface with frontend at *
  4. # * https://github.com/gorilla-llm/gorilla-react-frontend.*
  5. # * *
  6. # *********************************************************
  7. from fastapi import FastAPI, HTTPException, Request
  8. from main import ExecutionEngine, PythonAPIExecutor
  9. import re
  10. import requests
  11. from urllib.parse import quote, urlencode
  12. from google_auth_oauthlib.flow import InstalledAppFlow
  13. from fastapi.middleware.cors import CORSMiddleware
  14. import exec_engine.credentials.credentials_utils as credentials_utils
  15. from exec_engine.utils import SQL_Type, RESTful_Type, Filesystem_Type
  16. import json
  17. import base64
  18. app = FastAPI()
  19. app.add_middleware(
  20. CORSMiddleware,
  21. allow_origins=["*"],
  22. allow_credentials=True,
  23. allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
  24. allow_headers=["*"],
  25. )
  26. @app.options("/{path:path}")
  27. async def options_handler(request: Request, path: str):
  28. # This function intercepts OPTIONS requests and returns the appropriate response
  29. #return {"method": "OPTIONS"}
  30. return {}
  31. ########## GOOGLE AUTH ################################
  32. SCOPES = [
  33. "https://www.googleapis.com/auth/userinfo.email",
  34. "https://www.googleapis.com/auth/calendar.readonly",
  35. "openid",
  36. "https://www.googleapis.com/auth/gmail.compose" ,
  37. "https://www.googleapis.com/auth/userinfo.profile",
  38. "https://www.googleapis.com/auth/gmail.readonly",
  39. ]
  40. FRONTEND_GMAIL_CREDENTIAL_FILE = "authorizations/credentials/frontend_gmail_credentials.json"
  41. CLI_GMAIL_CREDENTIAL_FILE = "authorizations/credentials/gmail_credentials.json"
  42. frontend_flow = InstalledAppFlow.from_client_secrets_file(
  43. FRONTEND_GMAIL_CREDENTIAL_FILE, SCOPES)
  44. frontend_flow.redirect_uri = 'postmessage'
  45. cli_flow = InstalledAppFlow.from_client_secrets_file(
  46. CLI_GMAIL_CREDENTIAL_FILE, SCOPES)
  47. ########## GOOGLE AUTH END ##############################
  48. ########## CRED HELPER FUNCTIONS ######################
  49. def getGoogleCredsFrontend(code, redirect_uri):
  50. frontend_flow.fetch_token(code = code)
  51. return json.loads(frontend_flow.credentials.to_json())
  52. def getGoogleCredsCli(code, redirect_uri):
  53. cli_flow.redirect_uri = redirect_uri
  54. cli_flow.fetch_token(code = code)
  55. return json.loads(cli_flow.credentials.to_json())
  56. SLACK_CREDENTIAL_FILE = "authorizations/credentials/slack_credentials.json"
  57. def getSlackCreds(code, redirect_uri):
  58. with open(SLACK_CREDENTIAL_FILE) as json_file:
  59. client_data = json.load(json_file)["installed"]
  60. data = {"code": code,
  61. "client_id": client_data["client_id"],
  62. "client_secret": client_data["client_secret"],
  63. "redirect_uri":redirect_uri
  64. }
  65. headers = {"content-type": "application/x-www-form-urlencoded;"}
  66. r = requests.post("https://slack.com/api/oauth.v2.access",
  67. data=data,
  68. headers=headers)
  69. return {'token': r.json()['authed_user']['access_token']}
  70. DISCORD_CREDENTIAL_FILE = "authorizations/credentials/discord_credentials.json"
  71. def getDiscordCreds(code, redirect_uri):
  72. with open(DISCORD_CREDENTIAL_FILE) as json_file:
  73. client_data = json.load(json_file)["installed"]
  74. data = {"grant_type":"authorization_code", "code": code, "redirect_uri":redirect_uri}
  75. url = "https://discord.com/api/oauth2/token"
  76. headers = {"Content-Type": "application/x-www-form-urlencoded"}
  77. r = requests.post(url,
  78. data=data,
  79. headers=headers,
  80. auth=(client_data['client_id'], client_data['client_secret']))
  81. return {'token' : r.json()['access_token']}
  82. SPOTIFY_CREDENTIAL_FILE = "authorizations/credentials/spotify_credentials.json"
  83. def getSpotifyCreds(code, redirect_uri):
  84. with open(SPOTIFY_CREDENTIAL_FILE) as json_file:
  85. client_data = json.load(json_file)["installed"]
  86. data = {"code": code, "client_id":client_data['client_id'], "grant_type": 'authorization_code', "redirect_uri": redirect_uri}
  87. form_body = urlencode(data)
  88. url = "https://accounts.spotify.com/api/token"
  89. headers = {"content-type": "application/x-www-form-urlencoded", "Authorization": 'Basic ' + base64.b64encode((f"{client_data['client_id']}:{client_data['client_secret']}").encode()).decode()}
  90. r = requests.post(url,
  91. data=form_body,
  92. headers=headers)
  93. return {'token' : r.json()['access_token']}
  94. DROPBOX_CREDENTIAL_FILE = "authorizations/credentials/dropbox_credentials.json"
  95. def getDropboxCreds(code, redirect_uri):
  96. with open(DROPBOX_CREDENTIAL_FILE) as json_file:
  97. client_data = json.load(json_file)["installed"]
  98. data = {"code": code, "client_id":client_data['client_id'], 'client_secret' : client_data['client_secret'],"grant_type": 'authorization_code', "redirect_uri": redirect_uri}
  99. form_body = urlencode(data)
  100. url = client_data['token_uri']
  101. r = requests.post(url, data=form_body)
  102. return {'token' : r.json()['access_token']}
  103. GITHUB_CREDENTIAL_FILE = "authorizations/credentials/github_credentials.json"
  104. def getGithubCreds(code, redirect_uri):
  105. with open(GITHUB_CREDENTIAL_FILE) as json_file:
  106. client_data = json.load(json_file)["installed"]
  107. params = {
  108. "code": code,
  109. "client_id":client_data['client_id'],
  110. "client_secret" : client_data['client_secret'],
  111. "redirect_uri": redirect_uri
  112. }
  113. url = client_data['token_uri']
  114. headers = {'Accept': 'application/json'}
  115. r = requests.post(url, params=params, headers=headers)
  116. return {'token' : r.json()['access_token']}
  117. ########## CRED HELPER FUNCTIONS END ######################
  118. @app.post('/authorize') # takes in temp code from google oauth and returns creds
  119. async def authorize(request: Request):
  120. try:
  121. request_content = await request.json()
  122. code = request_content['code']
  123. service = request_content['service']
  124. redirect_uri = request_content['redirect_uri']
  125. if(service== 'gmail'):
  126. credentials = getGoogleCredsFrontend(code, redirect_uri)
  127. elif(service=='gmail-cli'):
  128. credentials = getGoogleCredsCli(code, redirect_uri)
  129. elif(service == 'slack'):
  130. credentials = getSlackCreds(code, redirect_uri)
  131. elif(service == 'discord'):
  132. credentials = getDiscordCreds(code, redirect_uri)
  133. elif(service == 'spotify'):
  134. credentials = getSpotifyCreds(code, redirect_uri)
  135. elif(service == 'dropbox'):
  136. credentials = getDropboxCreds(code, redirect_uri)
  137. elif(service == 'github'):
  138. credentials = getGithubCreds(code, redirect_uri)
  139. else:
  140. raise HTTPException(status_code=404, detail="Service Not Found")
  141. return credentials
  142. except Exception as e:
  143. print(e)
  144. raise HTTPException(status_code=500, detail="unable to execute with error message {e}".format(e=e))
  145. @app.post('/prompt')
  146. async def prompt_engine(request: Request):
  147. print("IN PROMPT")
  148. try:
  149. request_content = await request.json()
  150. creds = request_content['creds'] # burden on frontend to get the right cred
  151. prompt = request_content['prompt']
  152. engine = ExecutionEngine() # should we be making a new engine for each request?
  153. engine.api_executor = PythonAPIExecutor(engine.docker_sandbox)
  154. forward_call, backward_call = engine.gen_api_pair(prompt, api_type=RESTful_Type, credentials=creds, model="gpt-4-turbo-preview")
  155. return {"forward_call" : forward_call, "backward_call" : backward_call}
  156. except Exception as e:
  157. print(e)
  158. raise HTTPException(status_code=500, detail="unable to execute with error message {e}".format(e=e))
  159. @app.post('/execute')
  160. async def execute(request: Request):
  161. try:
  162. request_content = await request.json()
  163. forward_call = request_content['code']
  164. #creds = request_content['creds']
  165. engine = ExecutionEngine() # should we be making a new engine for each request?
  166. engine.api_executor = PythonAPIExecutor(engine.docker_sandbox)
  167. output = engine.api_executor.execute_api_call(forward_call)
  168. print(output)
  169. return output
  170. except Exception as e:
  171. print(e)
  172. raise HTTPException(status_code=500, detail="unable to execute with error message {e}".format(e=e))
  173. # if __name__ == "__main__":
  174. # import uvicorn
  175. # uvicorn.run(app, host="0.0.0.0", port=443, log_level="debug", reload=True)