From a1f8898176df31566f23d120d3b5a8eb964990d3 Mon Sep 17 00:00:00 2001 From: UtkarshMishra-Microsoft Date: Tue, 3 Dec 2024 21:05:44 +0530 Subject: [PATCH] Add code quality workflow in app.py --- app.py | 140 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 82 insertions(+), 58 deletions(-) diff --git a/app.py b/app.py index 64ad55d8..e8684079 100644 --- a/app.py +++ b/app.py @@ -17,22 +17,19 @@ from openai import AsyncAzureOpenAI from azure.search.documents import SearchClient from azure.core.credentials import AzureKeyCredential -from azure.identity.aio import ( - DefaultAzureCredential, - get_bearer_token_provider -) +from azure.identity.aio import DefaultAzureCredential, get_bearer_token_provider from backend.auth.auth_utils import get_authenticated_user_details from backend.security.ms_defender_utils import get_msdefender_user_json from backend.history.cosmosdbservice import CosmosConversationClient from backend.settings import ( app_settings, - MINIMUM_SUPPORTED_AZURE_OPENAI_PREVIEW_API_VERSION + MINIMUM_SUPPORTED_AZURE_OPENAI_PREVIEW_API_VERSION, ) from backend.utils import ( format_as_ndjson, format_stream_response, format_non_streaming_response, - ChatType + ChatType, ) bp = Blueprint("routes", __name__, static_folder="static", template_folder="static") @@ -48,9 +45,7 @@ def create_app(): @bp.route("/") async def index(): return await render_template( - "index.html", - title=app_settings.ui.title, - favicon=app_settings.ui.favicon + "index.html", title=app_settings.ui.title, favicon=app_settings.ui.favicon ) @@ -76,8 +71,7 @@ async def assets(path): frontend_settings = { "auth_enabled": app_settings.base_settings.auth_enabled, "feedback_enabled": ( - app_settings.chat_history and - app_settings.chat_history.enable_feedback + app_settings.chat_history and app_settings.chat_history.enable_feedback ), "ui": { "title": app_settings.ui.title, @@ -110,8 +104,8 @@ def init_openai_client(): # Endpoint if ( - not app_settings.azure_openai.endpoint and - not app_settings.azure_openai.resource + not app_settings.azure_openai.endpoint + and not app_settings.azure_openai.resource ): raise ValueError( "AZURE_OPENAI_ENDPOINT or AZURE_OPENAI_RESOURCE is required" @@ -154,19 +148,25 @@ def init_openai_client(): azure_openai_client = None raise e + def init_ai_search_client(): client = None - + try: endpoint = app_settings.datasource.endpoint key_credential = app_settings.datasource.key index_name = app_settings.datasource.index - client = SearchClient(endpoint=endpoint, index_name=index_name, credential=AzureKeyCredential(key_credential)) + client = SearchClient( + endpoint=endpoint, + index_name=index_name, + credential=AzureKeyCredential(key_credential), + ) return client except Exception as e: logging.exception("Exception in Azure AI Client initialization", e) raise e + def init_cosmosdb_client(): cosmos_conversation_client = None if app_settings.chat_history: @@ -198,36 +198,39 @@ def init_cosmosdb_client(): def prepare_model_args(request_body, request_headers): - chat_type = None if "chat_type" in request_body: - chat_type = ChatType.BROWSE if not (request_body["chat_type"] and request_body["chat_type"] == "template") else ChatType.TEMPLATE - - + chat_type = ( + ChatType.BROWSE + if not ( + request_body["chat_type"] and request_body["chat_type"] == "template" + ) + else ChatType.TEMPLATE + ) + request_messages = request_body.get("messages", []) - + messages = [] if not app_settings.datasource: messages = [ { "role": "system", - "content": app_settings.azure_openai.system_message if chat_type == ChatType.BROWSE or not chat_type else app_settings.azure_openai.template_system_message + "content": app_settings.azure_openai.system_message + if chat_type == ChatType.BROWSE or not chat_type + else app_settings.azure_openai.template_system_message, } ] for message in request_messages: if message: - messages.append( - { - "role": message["role"], - "content": message["content"] - } - ) + messages.append({"role": message["role"], "content": message["content"]}) user_json = None - if (MS_DEFENDER_ENABLED): + if MS_DEFENDER_ENABLED: authenticated_user_details = get_authenticated_user_details(request_headers) - user_json = get_msdefender_user_json(authenticated_user_details, request_headers) + user_json = get_msdefender_user_json( + authenticated_user_details, request_headers + ) model_args = { "messages": messages, @@ -235,24 +238,25 @@ def prepare_model_args(request_body, request_headers): "max_tokens": app_settings.azure_openai.max_tokens, "top_p": app_settings.azure_openai.top_p, "stop": app_settings.azure_openai.stop_sequence, - "stream": app_settings.azure_openai.stream if chat_type == ChatType.BROWSE else False, + "stream": app_settings.azure_openai.stream + if chat_type == ChatType.BROWSE + else False, "model": app_settings.azure_openai.model, - "user": user_json + "user": user_json, } if app_settings.datasource: model_args["extra_body"] = { "data_sources": [ - app_settings.datasource.construct_payload_configuration( - request=request - ) + app_settings.datasource.construct_payload_configuration(request=request) ] } # change role information if template chat if chat_type == ChatType.TEMPLATE: - model_args["extra_body"]["data_sources"][0]["parameters"]["role_information"] = app_settings.azure_openai.template_system_message - + model_args["extra_body"]["data_sources"][0]["parameters"][ + "role_information" + ] = app_settings.azure_openai.template_system_message model_args_clean = copy.deepcopy(model_args) if model_args_clean.get("extra_body"): @@ -297,17 +301,21 @@ async def send_chat_request(request_body, request_headers): filtered_messages = [] messages = request_body.get("messages", []) for message in messages: - if message.get("role") != 'tool': + if message.get("role") != "tool": filtered_messages.append(message) - - request_body['messages'] = filtered_messages + + request_body["messages"] = filtered_messages model_args = prepare_model_args(request_body, request_headers) try: azure_openai_client = init_openai_client() - raw_response = await azure_openai_client.chat.completions.with_raw_response.create(**model_args) + raw_response = ( + await azure_openai_client.chat.completions.with_raw_response.create( + **model_args + ) + ) response = raw_response.parse() - apim_request_id = raw_response.headers.get("apim-request-id") + apim_request_id = raw_response.headers.get("apim-request-id") except Exception as e: logging.exception("Exception in send_chat_request") raise e @@ -324,17 +332,25 @@ async def complete_chat_request(request_body, request_headers): async def stream_chat_request(request_body, request_headers): response, apim_request_id = await send_chat_request(request_body, request_headers) history_metadata = request_body.get("history_metadata", {}) - + async def generate(): async for completionChunk in response: - yield format_stream_response(completionChunk, history_metadata, apim_request_id) + yield format_stream_response( + completionChunk, history_metadata, apim_request_id + ) return generate() async def conversation_internal(request_body, request_headers): try: - chat_type = ChatType.BROWSE if not (request_body["chat_type"] and request_body["chat_type"] == "template") else ChatType.TEMPLATE + chat_type = ( + ChatType.BROWSE + if not ( + request_body["chat_type"] and request_body["chat_type"] == "template" + ) + else ChatType.TEMPLATE + ) if app_settings.azure_openai.stream and chat_type == ChatType.BROWSE: result = await stream_chat_request(request_body, request_headers) response = await make_response(format_as_ndjson(result)) @@ -816,7 +832,8 @@ async def ensure_cosmos(): ) else: return jsonify({"error": "CosmosDB is not working"}), 500 - + + @bp.route("/section/generate", methods=["POST"]) async def generate_section_content(): request_json = await request.get_json() @@ -824,16 +841,17 @@ async def generate_section_content(): # verify that section title and section description are provided if "sectionTitle" not in request_json: return jsonify({"error": "sectionTitle is required"}), 400 - + if "sectionDescription" not in request_json: return jsonify({"error": "sectionDescription is required"}), 400 - + content = await generate_section_content(request_json, request.headers) return jsonify({"section_content": content}), 200 except Exception as e: logging.exception("Exception in /section/generate") return jsonify({"error": str(e)}), 500 + @bp.route("/document/") async def get_document(filepath): try: @@ -843,6 +861,7 @@ async def get_document(filepath): logging.exception("Exception in /document/") return jsonify({"error": str(e)}), 500 + async def generate_title(conversation_messages): ## make sure the messages are sorted by _ts descending title_prompt = app_settings.azure_openai.title_prompt @@ -856,7 +875,10 @@ async def generate_title(conversation_messages): try: azure_openai_client = init_openai_client(use_data=False) response = await azure_openai_client.chat.completions.create( - model=app_settings.azure_openai.model, messages=messages, temperature=1, max_tokens=64 + model=app_settings.azure_openai.model, + messages=messages, + temperature=1, + max_tokens=64, ) title = json.loads(response.choices[0].message.content)["title"] @@ -864,6 +886,7 @@ async def generate_title(conversation_messages): except Exception as e: return messages[-2]["content"] + async def generate_section_content(request_body, request_headers): prompt = f"""{app_settings.azure_openai.generate_section_content_prompt} @@ -871,20 +894,19 @@ async def generate_section_content(request_body, request_headers): Section Description: {request_body['sectionDescription']} """ - messages = [ - { - "role": "system", - "content": app_settings.azure_openai.system_message - } - ] + messages = [{"role": "system", "content": app_settings.azure_openai.system_message}] messages.append({"role": "user", "content": prompt}) - - request_body['messages'] = messages + + request_body["messages"] = messages model_args = prepare_model_args(request_body, request_headers) try: azure_openai_client = init_openai_client() - raw_response = await azure_openai_client.chat.completions.with_raw_response.create(**model_args) + raw_response = ( + await azure_openai_client.chat.completions.with_raw_response.create( + **model_args + ) + ) response = raw_response.parse() except Exception as e: @@ -892,7 +914,8 @@ async def generate_section_content(request_body, request_headers): raise e return response.choices[0].message.content - + + def retrieve_document(filepath): try: search_client = init_ai_search_client() @@ -907,4 +930,5 @@ def retrieve_document(filepath): logging.exception("Exception in retrieve_document") raise e + app = create_app()