11import logging
22from typing import Any , Optional
3+ from urllib .parse import urlparse
34
45from azure .storage .blob .aio import ContainerClient as AsyncContainerClient
56from openai import AsyncAzureOpenAI
@@ -84,19 +85,19 @@ def __init__(
8485
8586 self ._kernel = Kernel ()
8687
87- service_id = "chat"
88+ self . _service_id = "chat"
8889
8990 self ._kernel .add_service (
9091 AzureChatCompletion (
91- service_id = service_id , deployment_name = self ._deployment_name , async_client = self ._async_client
92+ service_id = self . _service_id , deployment_name = self ._deployment_name , async_client = self ._async_client
9293 ),
9394 )
9495
9596 self ._plugin_name = plugin_name
96- self ._kernel .import_plugin_from_object (plugin , plugin_name )
97+ self ._kernel .add_plugin (plugin , plugin_name )
9798
9899 self ._execution_settings = AzureChatPromptExecutionSettings (
99- service_id = service_id ,
100+ service_id = self . _service_id ,
100101 ai_model_id = self ._deployment_name ,
101102 max_tokens = max_tokens ,
102103 temperature = temperature ,
@@ -136,16 +137,36 @@ async def send_prompt_async(self, *, prompt_request: PromptRequestResponse) -> P
136137 template = request .converted_value ,
137138 name = self ._plugin_name ,
138139 template_format = "semantic-kernel" ,
139- execution_settings = self ._execution_settings ,
140+ execution_settings = { self ._service_id : self . _execution_settings } ,
140141 )
141- processing_function = self ._kernel .create_function_from_prompt (
142+ processing_function = self ._kernel .add_function (
142143 function_name = "processingFunc" , plugin_name = self ._plugin_name , prompt_template_config = prompt_template_config
143144 )
144- processing_output = await self ._kernel .invoke (processing_function )
145- processing_output = str (processing_output )
145+ processing_output = await self ._kernel .invoke (processing_function ) # type: ignore
146+ if processing_output is None :
147+ raise ValueError ("Processing function returned None unexpectedly." )
148+ try :
149+ inner_content = processing_output .get_inner_content ()
150+
151+ if (
152+ not hasattr (inner_content , "choices" )
153+ or not isinstance (inner_content .choices , list )
154+ or not inner_content .choices
155+ ):
156+ raise ValueError ("Invalid response: 'choices' is missing or empty." )
157+
158+ first_choice = inner_content .choices [0 ]
159+
160+ if not hasattr (first_choice , "message" ) or not hasattr (first_choice .message , "content" ):
161+ raise ValueError ("Invalid response: 'message' or 'content' is missing in choices[0]." )
162+
163+ processing_output = first_choice .message .content
164+
165+ except AttributeError as e :
166+ raise ValueError (f"Unexpected structure in processing_output: { e } " )
146167 logger .info (f'Received the following response from the prompt target "{ processing_output } "' )
147168
148- response = construct_response_from_request (request = request , response_text_pieces = [processing_output ])
169+ response = construct_response_from_request (request = request , response_text_pieces = [str ( processing_output ) ])
149170 return response
150171
151172 def _validate_request (self , * , prompt_request : PromptRequestResponse ) -> None :
@@ -182,16 +203,17 @@ async def _create_container_client_async(self) -> None:
182203 """Creates an asynchronous ContainerClient for Azure Storage. If a SAS token is provided via the
183204 AZURE_STORAGE_ACCOUNT_SAS_TOKEN environment variable or the init sas_token parameter, it will be used
184205 for authentication. Otherwise, a delegation SAS token will be created using Entra ID authentication."""
206+ container_url , _ = self ._parse_url ()
185207 try :
186208 sas_token : str = default_values .get_required_value (
187209 env_var_name = self .SAS_TOKEN_ENVIRONMENT_VARIABLE , passed_value = self ._sas_token
188210 )
189211 logger .info ("Using SAS token from environment variable or passed parameter." )
190212 except ValueError :
191213 logger .info ("SAS token not provided. Creating a delegation SAS token using Entra ID authentication." )
192- sas_token = await AzureStorageAuth .get_sas_token (self . _container_url )
214+ sas_token = await AzureStorageAuth .get_sas_token (container_url )
193215 self ._storage_client = AsyncContainerClient .from_container_url (
194- container_url = self . _container_url ,
216+ container_url = container_url ,
195217 credential = sas_token ,
196218 )
197219
@@ -204,8 +226,10 @@ async def download_async(self) -> str:
204226 await self ._create_container_client_async ()
205227
206228 all_blobs = ""
229+ # Parse the Azure Storage Blob URL to extract components
230+ _ , blob_prefix = self ._parse_url ()
207231 async with self ._storage_client as client :
208- async for blob in client .list_blobs ():
232+ async for blob in client .list_blobs (name_starts_with = blob_prefix ):
209233 logger .info (f"Downloading Azure storage blob { blob .name } " )
210234 blob_client = client .get_blob_client (blob = blob .name )
211235 blob_data = await blob_client .download_blob ()
@@ -223,11 +247,21 @@ async def delete_blobs_async(self):
223247 await self ._create_container_client_async ()
224248 logger .info ("Deleting all blobs in the container." )
225249 try :
250+ _ , blob_prefix = self ._parse_url ()
226251 async with self ._storage_client as client :
227- async for blob in client .list_blobs ():
252+ async for blob in client .list_blobs (name_starts_with = blob_prefix ):
228253 print ("blob name is given as" , blob .name )
229254 await client .get_blob_client (blob = blob .name ).delete_blob ()
230255 logger .info (f"Deleted blob: { blob .name } " )
231256 except Exception as ex :
232257 logger .exception (msg = f"An error occurred while deleting blobs: { ex } " )
233258 raise
259+
260+ def _parse_url (self ):
261+ """Parses the Azure Storage Blob URL to extract components."""
262+ parsed_url = urlparse (self ._container_url )
263+ path_parts = parsed_url .path .split ("/" )
264+ container_name = path_parts [1 ]
265+ blob_prefix = "/" .join (path_parts [2 :])
266+ container_url = f"https://{ parsed_url .netloc } /{ container_name } "
267+ return container_url , blob_prefix
0 commit comments