Skip to content

Commit

Permalink
Add code quality workflow in app.py
Browse files Browse the repository at this point in the history
  • Loading branch information
UtkarshMishra-Microsoft committed Dec 3, 2024
1 parent 0dd3d92 commit a1f8898
Showing 1 changed file with 82 additions and 58 deletions.
140 changes: 82 additions & 58 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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
)


Expand All @@ -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,
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -198,61 +198,65 @@ 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,
"temperature": app_settings.azure_openai.temperature,
"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"):
Expand Down Expand Up @@ -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
Expand All @@ -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))
Expand Down Expand Up @@ -816,24 +832,26 @@ 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()
try:
# 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/<filepath>")
async def get_document(filepath):
try:
Expand All @@ -843,6 +861,7 @@ async def get_document(filepath):
logging.exception("Exception in /document/<filepath>")
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
Expand All @@ -856,43 +875,47 @@ 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"]
return title
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}
Section Title: {request_body['sectionTitle']}
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:
logging.exception("Exception in send_chat_request")
raise e

return response.choices[0].message.content



def retrieve_document(filepath):
try:
search_client = init_ai_search_client()
Expand All @@ -907,4 +930,5 @@ def retrieve_document(filepath):
logging.exception("Exception in retrieve_document")
raise e


app = create_app()

0 comments on commit a1f8898

Please sign in to comment.