forked from Azure/gpt-rag-orchestrator
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathsetup.py
More file actions
241 lines (211 loc) · 8.93 KB
/
setup.py
File metadata and controls
241 lines (211 loc) · 8.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
import logging
import time
import requests
import argparse
import json
from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient
logging.getLogger("azure").setLevel(logging.WARNING)
def call_search_api(
search_service,
search_api_version,
resource_type,
resource_name,
method,
credential,
body=None,
):
"""
Calls the Azure Search API with the specified parameters.
Args:
search_service (str): The name of the Azure Search service.
search_api_version (str): The version of the Azure Search API to use.
resource_type (str): The type of resource to access (e.g. "indexes", "docs").
resource_name (str): The name of the resource to access.
method (str): The HTTP method to use (either "get" or "put").
credential (TokenCredential): An instance of a TokenCredential class that can provide an access token.
body (dict, optional): The JSON payload to include in the request body (for "put" requests).
Returns:
None
Raises:
ValueError: If the specified HTTP method is not "get" or "put".
HTTPError: If the response status code is 400 or greater.
"""
# get the token
token = credential.get_token("https://search.azure.com/.default").token
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
# 'api-key': SEARCH_API_KEY
}
search_endpoint = f"https://{search_service}.search.windows.net/{resource_type}/{resource_name}?api-version={search_api_version}"
response = None
try:
if method not in ["get", "put"]:
logging.error(f"Invalid method {method} ")
if method == "get":
response = requests.get(search_endpoint, headers=headers)
elif method == "put":
response = requests.put(search_endpoint, headers=headers, json=body)
if response is not None:
status_code = response.status_code
if status_code >= 400:
logging.error(
f"Error when calling search API {method} {resource_type} {resource_name}. Code: {status_code}. Reason: {response.reason}"
)
response_text_dict = json.loads(response.text)
logging.error(
f"Error when calling search API {method} {resource_type} {resource_name}. Message: {response_text_dict['error']['message']}"
)
else:
logging.info(
f"Successfully called search API {method} {resource_type} {resource_name}. Code: {status_code}."
)
except Exception as e:
error_message = str(e)
logging.error(
f"Error when calling search API {method} {resource_type} {resource_name}. Error: {error_message}"
)
return response
def get_function_key(subscription_id, resource_group, function_app_name, credential):
"""
Returns an API key for the given function.
Parameters:
subscription_id (str): The subscription ID.
resource_group (str): The resource group name.
function_app_name (str): The name of the function app.
credential (str): The credential to use.
Returns:
str: A unique key for the function.
"""
logging.info("Obtaining function key after creating or updating its value.")
accessToken = (
f"Bearer {credential.get_token('https://management.azure.com/.default').token}"
)
# Get key
requestUrl = f"https://management.azure.com/subscriptions/{subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.Web/sites/{function_app_name}/functions/orc/keys/mykey?api-version=2022-03-01"
requestHeaders = {"Authorization": accessToken, "Content-Type": "application/json"}
data = {"properties": {}}
response = requests.put(requestUrl, headers=requestHeaders, data=json.dumps(data))
response_json = json.loads(response.content.decode("utf-8"))
try:
function_key = response_json["properties"]["value"]
except Exception as e:
function_key = None
logging.error(f"Error when getting function key. Details: {str(e)}.")
return function_key
def execute_setup(
subscription_id,
resource_group,
function_app_name,
key_vault_name,
enable_managed_identities,
enable_env_credentials,
):
"""
This function performs the necessary steps to set up the orchestrator component.
Args:
subscription_id (str): The subscription ID of the Azure subscription to use.
resource_group (str): The name of the resource group containing the solution resources.
function_app_name (str): The name of the function app to use.
key_vault_name (Str): The key vault name
enable_managed_identities (bool): Whether to use managed identities to run the setup.
enable_env_credentials (bool): Whether to use environment credentials to run the setup.
Returns:
None
"""
logging.info(f"Getting function app {function_app_name} properties.")
credential = DefaultAzureCredential(
logging_enable=True,
exclude_managed_identity_credential=not enable_managed_identities,
exclude_environment_credential=not enable_env_credentials,
)
function_endpoint = f"https://{function_app_name}.azurewebsites.net"
logging.info(f"Function endpoint: {function_endpoint}")
###########################################################################
# Get function key and store into key vault
###########################################################################
function_key = get_function_key(
subscription_id, resource_group, function_app_name, credential
)
if function_key is None:
logging.error(
f"Could not get function key. Please make sure the function {function_app_name}/orc is deployed before running this script."
)
exit()
# Create a SecretClient object
vault_url = f"https://{key_vault_name}.vault.azure.net"
secret_client = SecretClient(vault_url=vault_url, credential=credential)
# Store the secret in the key vault
secret_client.set_secret("orchestrator-host--functionKey", function_key)
def main(
subscription_id=None,
resource_group=None,
function_app_name=None,
key_vault_name=None,
enable_managed_identities=False,
enable_env_credentials=False,
):
"""
Sets up a chunking function app in Azure.
Args:
subscription_id (str, optional): The subscription ID to use. If not provided, the user will be prompted to enter it.
resource_group (str, optional): The resource group to use. If not provided, the user will be prompted to enter it.
function_app_name (str, optional): The name of the function app. If not provided, the user will be prompted to enter it.
enable_managed_identities (bool, optional): Whether to use managed identities to run the setup.
enable_env_credentials (bool, optional): Whether to use environment credentials to run the setup.
"""
logging.basicConfig(
level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
)
logging.info("Starting setup.")
if subscription_id is None:
subscription_id = input("Enter subscription ID: ")
if resource_group is None:
resource_group = input("Enter resource group: ")
if function_app_name is None:
function_app_name = input("Enter function app name: ")
if key_vault_name is None:
key_vault_name = input("Enter key vault name: ")
start_time = time.time()
execute_setup(
subscription_id,
resource_group,
function_app_name,
key_vault_name,
enable_managed_identities,
enable_env_credentials,
)
response_time = time.time() - start_time
logging.info(f"Finished setup. {round(response_time,2)} seconds")
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Script to do orchestrator component setup."
)
parser.add_argument("-s", "--subscription_id", help="Subscription ID")
parser.add_argument("-r", "--resource_group", help="Resource group")
parser.add_argument("-f", "--function_app_name", help="Function app name")
parser.add_argument("-k", "--key_vault_name", help="Key vault name")
parser.add_argument(
"-i",
"--enable_managed_identities",
action="store_true",
default=False,
help="Enable managed identities",
)
parser.add_argument(
"-e",
"--enable_env_credentials",
action="store_true",
default=False,
help="Enable environment credentials",
)
args = parser.parse_args()
main(
subscription_id=args.subscription_id,
resource_group=args.resource_group,
function_app_name=args.function_app_name,
key_vault_name=args.key_vault_name,
enable_managed_identities=args.enable_managed_identities,
enable_env_credentials=args.enable_env_credentials,
)