@@ -69,6 +69,31 @@ def create_app():
6969 app .register_blueprint (bp )
7070 app .config ["TEMPLATES_AUTO_RELOAD" ] = True
7171 app .config ['PROVIDE_AUTOMATIC_OPTIONS' ] = True
72+
73+ @app .after_serving
74+ async def shutdown ():
75+ """
76+ Perform any cleanup tasks after the app stops serving requests.
77+ """
78+ print ("Shutting down the application..." , flush = True )
79+ try :
80+ # Clean up agent instances
81+ await BrowseAgentFactory .delete_agent ()
82+ await TemplateAgentFactory .delete_agent ()
83+ await SectionAgentFactory .delete_agent ()
84+
85+ # clear app state
86+ if hasattr (app , 'browse_agent' ) or hasattr (app , 'template_agent' ) or hasattr (app , 'section_agent' ):
87+ app .browse_agent = None
88+ app .template_agent = None
89+ app .section_agent = None
90+
91+ track_event_if_configured ("ApplicationShutdown" , {"status" : "success" })
92+ except Exception as e :
93+ logging .exception ("Error during application shutdown" )
94+ track_event_if_configured ("ApplicationShutdownError" , {"status" : "error" })
95+ raise e
96+
7297 return app
7398
7499
@@ -248,10 +273,15 @@ async def send_chat_request(request_body, request_headers) -> AsyncGenerator[Dic
248273 run_id = None
249274 streamed_titles = set ()
250275 doc_mapping = {}
276+ thread = None
251277 # Browse
252278 if request_body ["chat_type" ] == "browse" :
253279 try :
254- browse_agent_data = await BrowseAgentFactory .get_browse_agent (system_instruction = app_settings .azure_openai .system_message )
280+ # Create browse agent if it doesn't exist
281+ if getattr (app , "browse_agent" , None ) is None :
282+ app .browse_agent = await BrowseAgentFactory .get_agent ()
283+
284+ browse_agent_data = app .browse_agent
255285 browse_project_client = browse_agent_data ["client" ]
256286 browse_agent = browse_agent_data ["agent" ]
257287
@@ -283,10 +313,18 @@ async def send_chat_request(request_body, request_headers) -> AsyncGenerator[Dic
283313
284314 if delta_text and delta_text .value :
285315 answer ["answer" ] += delta_text .value
286- yield {
287- "answer" : convert_citation_markers (delta_text .value , doc_mapping ),
288- "citations" : json .dumps (answer ["citations" ])
289- }
316+
317+ # check if citation markers are present
318+ has_citation_markers = bool (re .search (r'【(\d+:\d+)†source】' , delta_text .value ))
319+ if has_citation_markers :
320+ yield {
321+ "answer" : convert_citation_markers (delta_text .value , doc_mapping ),
322+ "citations" : json .dumps (answer ["citations" ])
323+ }
324+ else :
325+ yield {
326+ "answer" : delta_text .value
327+ }
290328
291329 if delta_text and delta_text .annotations :
292330 for annotation in delta_text .annotations :
@@ -305,10 +343,11 @@ async def send_chat_request(request_body, request_headers) -> AsyncGenerator[Dic
305343 if run_id :
306344 await extract_citations_from_run_steps (browse_project_client , thread .id , run_id , answer , streamed_titles )
307345
308- yield {
309- # "answer": answer["answer"],
310- "citations" : json .dumps (answer ["citations" ])
311- }
346+ has_final_citation_markers = bool (re .search (r'【(\d+:\d+)†source】' , answer ["answer" ]))
347+ if has_final_citation_markers :
348+ yield {
349+ "citations" : json .dumps (answer ["citations" ])
350+ }
312351
313352 else :
314353 run = await browse_project_client .agents .runs .create_and_process (
@@ -324,12 +363,19 @@ async def send_chat_request(request_body, request_headers) -> AsyncGenerator[Dic
324363 async for msg in messages :
325364 if msg .role == MessageRole .AGENT and msg .text_messages :
326365 answer ["answer" ] = msg .text_messages [- 1 ].text .value
327- answer ["answer" ] = convert_citation_markers (answer ["answer" ], doc_mapping )
328366 break
329- yield {
330- "answer" : answer ["answer" ],
331- "citations" : json .dumps (answer ["citations" ])
332- }
367+
368+ has_citation_markers = bool (re .search (r'【(\d+:\d+)†source】' , answer ["answer" ]))
369+
370+ if has_citation_markers :
371+ yield {
372+ "answer" : convert_citation_markers (answer ["answer" ], doc_mapping ),
373+ "citations" : json .dumps (answer ["citations" ])
374+ }
375+ else :
376+ yield {
377+ "answer" : answer ["answer" ]
378+ }
333379 finally :
334380 if thread :
335381 print (f"Deleting browse thread: { thread .id } " , flush = True )
@@ -338,7 +384,19 @@ async def send_chat_request(request_body, request_headers) -> AsyncGenerator[Dic
338384 # Generate Template
339385 else :
340386 try :
341- template_agent_data = await TemplateAgentFactory .get_template_agent (system_instruction = app_settings .azure_openai .template_system_message )
387+ # Create template agent if it doesn't exist
388+ if getattr (app , "template_agent" , None ) is None :
389+ app .template_agent = await TemplateAgentFactory .get_agent ()
390+
391+ # Create section_agent if missing; log errors without stopping flow
392+ try :
393+ if getattr (app , "section_agent" , None ) is None :
394+ app .section_agent = await SectionAgentFactory .get_agent ()
395+ except Exception as e :
396+ logging .exception ("Error initializing Section Agent" , e )
397+ raise e
398+
399+ template_agent_data = app .template_agent
342400 template_project_client = template_agent_data ["client" ]
343401 template_agent = template_agent_data ["agent" ]
344402
@@ -1032,7 +1090,7 @@ async def ensure_cosmos():
10321090 success , err = await cosmos_conversation_client .ensure ()
10331091 if not cosmos_conversation_client or not success :
10341092 if err :
1035- track_event_if_configured ("CosmosEnsureFailed" , err )
1093+ track_event_if_configured ("CosmosEnsureFailed" , { "error" : err } )
10361094 return jsonify ({"error" : err }), 422
10371095 return jsonify ({"error" : "CosmosDB is not configured or not working" }), 500
10381096
@@ -1193,11 +1251,17 @@ async def get_section_content(request_body, request_headers):
11931251 messages .append ({"role" : "user" , "content" : user_prompt })
11941252
11951253 request_body ["messages" ] = messages
1254+ thread = None
1255+ response_text = ""
11961256
11971257 try :
11981258 # Use Foundry SDK for section content generation
11991259 track_event_if_configured ("Foundry_sdk_for_section" , {"status" : "success" })
1200- section_agent_data = await SectionAgentFactory .get_sections_agent (system_instruction = app_settings .azure_openai .generate_section_content_prompt )
1260+ # Create section agent if not already created
1261+ if getattr (app , "section_agent" , None ) is None :
1262+ app .section_agent = await SectionAgentFactory .get_agent ()
1263+
1264+ section_agent_data = app .section_agent
12011265 section_project_client = section_agent_data ["client" ]
12021266 section_agent = section_agent_data ["agent" ]
12031267
0 commit comments