4545
4646
4747def create_app ():
48+ """
49+ Create and configure the Quart application instance.
50+
51+ Returns:
52+ Quart: Configured Quart application instance
53+ """
4854 app = Quart (__name__ )
4955 app .register_blueprint (bp )
5056 app .config ["TEMPLATES_AUTO_RELOAD" ] = True
@@ -68,18 +74,39 @@ async def shutdown():
6874
6975@bp .route ("/" )
7076async def index ():
77+ """
78+ Render the main index page.
79+
80+ Returns:
81+ Rendered HTML template for the index page
82+ """
7183 return await render_template (
7284 "index.html" , title = app_settings .ui .title , favicon = app_settings .ui .favicon
7385 )
7486
7587
7688@bp .route ("/favicon.ico" )
7789async def favicon ():
90+ """
91+ Serve the favicon.ico file.
92+
93+ Returns:
94+ Static favicon file
95+ """
7896 return await bp .send_static_file ("favicon.ico" )
7997
8098
8199@bp .route ("/assets/<path:path>" )
82100async def assets (path ):
101+ """
102+ Serve static assets from the assets directory.
103+
104+ Args:
105+ path: Path to the asset file
106+
107+ Returns:
108+ Static asset file
109+ """
83110 return await send_from_directory ("static/assets" , path )
84111
85112
@@ -111,6 +138,15 @@ async def assets(path):
111138
112139
113140def init_cosmosdb_client ():
141+ """
142+ Initialize and configure the CosmosDB conversation client.
143+
144+ Returns:
145+ CosmosConversationClient: Configured CosmosDB client or None if not configured
146+
147+ Raises:
148+ Exception: If there's an error during CosmosDB initialization
149+ """
114150 cosmos_conversation_client = None
115151 if app_settings .chat_history :
116152 try :
@@ -146,6 +182,16 @@ def init_cosmosdb_client():
146182
147183# Conversion of citation markers
148184def convert_citation_markers (text , doc_mapping ):
185+ """
186+ Convert citation markers in text to numbered citations.
187+
188+ Args:
189+ text: Text containing citation markers
190+ doc_mapping: Dictionary mapping citation keys to citation numbers
191+
192+ Returns:
193+ str: Text with converted citation markers
194+ """
149195 def replace_marker (match ):
150196 key = match .group (1 )
151197 if key not in doc_mapping :
@@ -156,6 +202,20 @@ def replace_marker(match):
156202
157203
158204async def send_chat_request (request_body , request_headers ) -> AsyncGenerator [Dict [str , Any ], None ]:
205+ """
206+ Send a chat request to the appropriate agent based on chat type.
207+
208+ Args:
209+ request_body: Request body containing messages and chat type
210+ request_headers: HTTP request headers
211+
212+ Yields:
213+ Dict[str, Any]: Response chunks containing answer and citations
214+
215+ Raises:
216+ ValueError: If agent name is not configured
217+ Exception: If there's an error during chat request processing
218+ """
159219 filtered_messages = []
160220 messages = request_body .get ("messages" , [])
161221 for message in messages :
@@ -340,6 +400,16 @@ async def send_chat_request(request_body, request_headers) -> AsyncGenerator[Dic
340400
341401
342402async def complete_chat_request (request_body , request_headers ):
403+ """
404+ Complete a non-streaming chat request.
405+
406+ Args:
407+ request_body: Request body containing messages and metadata
408+ request_headers: HTTP request headers
409+
410+ Returns:
411+ Formatted non-streaming response
412+ """
343413 # response, apim_request_id = await send_chat_request(request_body, request_headers)
344414 response = None
345415 history_metadata = request_body .get ("history_metadata" , {})
@@ -351,6 +421,16 @@ async def complete_chat_request(request_body, request_headers):
351421
352422
353423async def stream_chat_request (request_body , request_headers ):
424+ """
425+ Stream a chat request with real-time response chunks.
426+
427+ Args:
428+ request_body: Request body containing messages and metadata
429+ request_headers: HTTP request headers
430+
431+ Returns:
432+ AsyncGenerator: Generator yielding formatted stream response chunks
433+ """
354434 track_event_if_configured ("StreamChatRequestStart" , {
355435 "has_history_metadata" : "history_metadata" in request_body
356436 })
@@ -365,6 +445,16 @@ async def generate():
365445
366446
367447async def conversation_internal (request_body , request_headers ):
448+ """
449+ Internal handler for conversation requests.
450+
451+ Args:
452+ request_body: Request body containing messages and chat type
453+ request_headers: HTTP request headers
454+
455+ Returns:
456+ JSON response with conversation result or error
457+ """
368458 try :
369459 chat_type = (
370460 ChatType .BROWSE
@@ -408,6 +498,12 @@ async def conversation_internal(request_body, request_headers):
408498
409499@bp .route ("/conversation" , methods = ["POST" ])
410500async def conversation ():
501+ """
502+ Handle POST requests to the /conversation endpoint.
503+
504+ Returns:
505+ JSON response with conversation result or error
506+ """
411507 if not request .is_json :
412508 track_event_if_configured ("InvalidRequestFormat" , {
413509 "status_code" : 415 ,
@@ -421,6 +517,12 @@ async def conversation():
421517
422518@bp .route ("/frontend_settings" , methods = ["GET" ])
423519def get_frontend_settings ():
520+ """
521+ Get frontend configuration settings.
522+
523+ Returns:
524+ JSON response with frontend settings or error
525+ """
424526 try :
425527 return jsonify (frontend_settings ), 200
426528 except Exception as e :
@@ -435,6 +537,12 @@ def get_frontend_settings():
435537# Conversation History API #
436538@bp .route ("/history/generate" , methods = ["POST" ])
437539async def add_conversation ():
540+ """
541+ Generate a new conversation and add user message to history.
542+
543+ Returns:
544+ JSON response with conversation result or error
545+ """
438546 authenticated_user = get_authenticated_user_details (request_headers = request .headers )
439547 user_id = authenticated_user ["user_principal_id" ]
440548
@@ -510,6 +618,12 @@ async def add_conversation():
510618
511619@bp .route ("/history/update" , methods = ["POST" ])
512620async def update_conversation ():
621+ """
622+ Update conversation history with assistant messages.
623+
624+ Returns:
625+ JSON response with success status or error
626+ """
513627 authenticated_user = get_authenticated_user_details (request_headers = request .headers )
514628 user_id = authenticated_user ["user_principal_id" ]
515629
@@ -572,6 +686,12 @@ async def update_conversation():
572686
573687@bp .route ("/history/message_feedback" , methods = ["POST" ])
574688async def update_message ():
689+ """
690+ Update feedback for a specific message.
691+
692+ Returns:
693+ JSON response with success status or error
694+ """
575695 authenticated_user = get_authenticated_user_details (request_headers = request .headers )
576696 user_id = authenticated_user ["user_principal_id" ]
577697 cosmos_conversation_client = init_cosmosdb_client ()
@@ -637,6 +757,12 @@ async def update_message():
637757
638758@bp .route ("/history/delete" , methods = ["DELETE" ])
639759async def delete_conversation ():
760+ """
761+ Delete a conversation and all its messages.
762+
763+ Returns:
764+ JSON response with success status or error
765+ """
640766 # get the user id from the request headers
641767 authenticated_user = get_authenticated_user_details (request_headers = request .headers )
642768 user_id = authenticated_user ["user_principal_id" ]
@@ -693,6 +819,12 @@ async def delete_conversation():
693819
694820@bp .route ("/history/list" , methods = ["GET" ])
695821async def list_conversations ():
822+ """
823+ List all conversations for the authenticated user.
824+
825+ Returns:
826+ JSON response with list of conversations or error
827+ """
696828 offset = request .args .get ("offset" , 0 )
697829 authenticated_user = get_authenticated_user_details (request_headers = request .headers )
698830 user_id = authenticated_user ["user_principal_id" ]
@@ -727,6 +859,12 @@ async def list_conversations():
727859
728860@bp .route ("/history/read" , methods = ["POST" ])
729861async def get_conversation ():
862+ """
863+ Get a specific conversation and its messages.
864+
865+ Returns:
866+ JSON response with conversation details and messages or error
867+ """
730868 authenticated_user = get_authenticated_user_details (request_headers = request .headers )
731869 user_id = authenticated_user ["user_principal_id" ]
732870
@@ -802,6 +940,12 @@ async def get_conversation():
802940
803941@bp .route ("/history/rename" , methods = ["POST" ])
804942async def rename_conversation ():
943+ """
944+ Rename a conversation by updating its title.
945+
946+ Returns:
947+ JSON response with updated conversation or error
948+ """
805949 authenticated_user = get_authenticated_user_details (request_headers = request .headers )
806950 user_id = authenticated_user ["user_principal_id" ]
807951
@@ -873,6 +1017,12 @@ async def rename_conversation():
8731017
8741018@bp .route ("/history/delete_all" , methods = ["DELETE" ])
8751019async def delete_all_conversations ():
1020+ """
1021+ Delete all conversations and messages for the authenticated user.
1022+
1023+ Returns:
1024+ JSON response with success status or error
1025+ """
8761026 # get the user id from the request headers
8771027 authenticated_user = get_authenticated_user_details (request_headers = request .headers )
8781028 user_id = authenticated_user ["user_principal_id" ]
@@ -934,6 +1084,12 @@ async def delete_all_conversations():
9341084
9351085@bp .route ("/history/clear" , methods = ["POST" ])
9361086async def clear_messages ():
1087+ """
1088+ Clear all messages in a specific conversation.
1089+
1090+ Returns:
1091+ JSON response with success status or error
1092+ """
9371093 # get the user id from the request headers
9381094 authenticated_user = get_authenticated_user_details (request_headers = request .headers )
9391095 user_id = authenticated_user ["user_principal_id" ]
@@ -974,6 +1130,12 @@ async def clear_messages():
9741130
9751131@bp .route ("/history/ensure" , methods = ["GET" ])
9761132async def ensure_cosmos ():
1133+ """
1134+ Ensure CosmosDB is properly configured and working.
1135+
1136+ Returns:
1137+ JSON response with configuration status or error
1138+ """
9771139 if not app_settings .chat_history :
9781140 return jsonify ({"error" : "CosmosDB is not configured" }), 404
9791141
@@ -1018,6 +1180,12 @@ async def ensure_cosmos():
10181180
10191181@bp .route ("/section/generate" , methods = ["POST" ])
10201182async def generate_section_content ():
1183+ """
1184+ Generate content for a document section.
1185+
1186+ Returns:
1187+ JSON response with generated section content or error
1188+ """
10211189 request_json = await request .get_json ()
10221190 try :
10231191 # verify that section title and section description are provided
@@ -1046,6 +1214,12 @@ async def generate_section_content():
10461214# Fetch content from Azure Search API
10471215@bp .route ("/fetch-azure-search-content" , methods = ["POST" ])
10481216async def fetch_azure_search_content ():
1217+ """
1218+ Fetch content from Azure Search API using a provided URL.
1219+
1220+ Returns:
1221+ JSON response with fetched content or error
1222+ """
10491223 try :
10501224 request_json = await request .get_json ()
10511225 url = request_json .get ("url" )
@@ -1189,8 +1363,7 @@ async def get_section_content(request_body, request_headers):
11891363 tool_choice = "auto" ,
11901364 store = True ,
11911365 ) as chat_agent :
1192- thread = chat_agent .get_new_thread ()
1193- result = await chat_agent .run (messages = user_prompt , thread = thread )
1366+ result = await chat_agent .run (messages = user_prompt )
11941367 response_text = str (result ) if result is not None else ""
11951368
11961369 # Remove citation markers from section content
0 commit comments