Skip to content

Commit

Permalink
Remove retry_mechanism
Browse files Browse the repository at this point in the history
  • Loading branch information
TaoChenOSU committed Dec 13, 2024
1 parent ed58607 commit f96f52c
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 90 deletions.
103 changes: 103 additions & 0 deletions python/samples/concepts/filtering/retry_with_filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Copyright (c) Microsoft. All rights reserved.

import asyncio
import logging
from collections.abc import Callable, Coroutine
from typing import Any

from samples.concepts.setup.chat_completion_services import Services, get_chat_completion_service_and_request_settings
from semantic_kernel import Kernel
from semantic_kernel.connectors.ai.function_choice_behavior import FunctionChoiceBehavior
from semantic_kernel.contents import ChatHistory
from semantic_kernel.filters import FunctionInvocationContext
from semantic_kernel.filters.filter_types import FilterTypes
from semantic_kernel.functions import kernel_function

# This sample shows how to use a filter for retrying a function invocation.
# This sample requires the following components:
# - a ChatCompletionService: This component is responsible for generating responses to user messages.
# - a ChatHistory: This component is responsible for keeping track of the chat history.
# - a Kernel: This component is responsible for managing plugins and filters.
# - a mock plugin: This plugin contains a function that simulates a call to an external service.
# - a filter: This filter retries the function invocation if it fails.

logger = logging.getLogger(__name__)

# The maximum number of retries for the filter
MAX_RETRIES = 3


class WeatherPlugin:
MAX_FAILURES = 2

def __init__(self):
self._invocation_count = 0

@kernel_function(name="GetWeather", description="Get the weather of the day at the current location.")
def get_wather(self) -> str:
"""Get the weather of the day at the current location.
Simulates a call to an external service to get the weather.
This function is designed to fail a certain number of times before succeeding.
"""
if self._invocation_count < self.MAX_FAILURES:
self._invocation_count += 1
print(f"Number of attempts: {self._invocation_count}")
raise Exception("Failed to get the weather")

return "Sunny"


async def retry_filter(
context: FunctionInvocationContext,
next: Callable[[FunctionInvocationContext], Coroutine[Any, Any, None]],
) -> None:
"""A filter that retries the function invocation if it fails.
The filter uses a binary exponential backoff strategy to retry the function invocation.
"""
for i in range(MAX_RETRIES):
try:
await next(context)
return
except Exception as e:
logger.warning(f"Failed to execute the function: {e}")
backoff = 2**i
logger.info(f"Sleeping for {backoff} seconds before retrying")


async def main() -> None:
kernel = Kernel()
# Register the plugin to the kernel
kernel.add_plugin(WeatherPlugin(), plugin_name="WeatherPlugin")
# Add the filter to the kernel as a function invocation filter
# A function invocation fileter is called during when the kernel executes a function

Check warning on line 74 in python/samples/concepts/filtering/retry_with_filters.py

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"fileter" should be "filter".
kernel.add_filter(FilterTypes.FUNCTION_INVOCATION, retry_filter)

chat_history = ChatHistory()
chat_history.add_user_message("What is the weather today?")

chat_completion_service, request_settings = get_chat_completion_service_and_request_settings(Services.OPENAI)
# Need to set the function choice behavior to auto such that the
# service will automatically invoke the function in the response.
request_settings.function_choice_behavior = FunctionChoiceBehavior.Auto()

response = await chat_completion_service.get_chat_message_content(
chat_history=chat_history,
settings=request_settings,
# Need to pass the kernel to the chat completion service so that it has access to the plugins and filters
kernel=kernel,
)

print(response)

# Sample output:
# Number of attempts: 1
# Failed to execute the function: Failed to get the weather
# Number of attempts: 2
# Failed to execute the function: Failed to get the weather
# The weather today is Sunny


if __name__ == "__main__":
asyncio.run(main())
13 changes: 3 additions & 10 deletions python/semantic_kernel/kernel.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
from semantic_kernel.functions.kernel_plugin import KernelPlugin
from semantic_kernel.kernel_types import AI_SERVICE_CLIENT_TYPE, OneOrMany
from semantic_kernel.prompt_template.const import KERNEL_TEMPLATE_FORMAT_NAME
from semantic_kernel.reliability.kernel_reliability_extension import KernelReliabilityExtension
from semantic_kernel.services.ai_service_selector import AIServiceSelector
from semantic_kernel.services.kernel_services_extension import KernelServicesExtension
from semantic_kernel.utils.naming import generate_random_ascii_name
Expand All @@ -52,7 +51,7 @@
logger: logging.Logger = logging.getLogger(__name__)


class Kernel(KernelFilterExtension, KernelFunctionExtension, KernelServicesExtension, KernelReliabilityExtension):
class Kernel(KernelFilterExtension, KernelFunctionExtension, KernelServicesExtension):
"""The Kernel of Semantic Kernel.
This is the main entry point for Semantic Kernel. It provides the ability to run
Expand All @@ -65,8 +64,6 @@ class Kernel(KernelFilterExtension, KernelFunctionExtension, KernelServicesExten
plugins: A dict with the plugins registered with the Kernel, from KernelFunctionExtension.
services: A dict with the services registered with the Kernel, from KernelServicesExtension.
ai_service_selector: The AI service selector to be used by the kernel, from KernelServicesExtension.
retry_mechanism: The retry mechanism to be used by the kernel, from KernelReliabilityExtension.
"""

def __init__(
Expand All @@ -84,12 +81,8 @@ def __init__(
plugins: The plugins to be used by the kernel, will be rewritten to a dict with plugin name as key
services: The services to be used by the kernel, will be rewritten to a dict with service_id as key
ai_service_selector: The AI service selector to be used by the kernel,
default is based on order of execution settings.
**kwargs: Additional fields to be passed to the Kernel model,
these are limited to retry_mechanism and function_invoking_handlers
and function_invoked_handlers, the best way to add function_invoking_handlers
and function_invoked_handlers is to use the add_function_invoking_handler
and add_function_invoked_handler methods.
default is based on order of execution settings.
**kwargs: Additional fields to be passed to the Kernel model, these are limited to filters.
"""
args = {
"services": services,
Expand Down
Empty file.
18 changes: 0 additions & 18 deletions python/semantic_kernel/reliability/kernel_reliability_extension.py

This file was deleted.

31 changes: 0 additions & 31 deletions python/semantic_kernel/reliability/pass_through_without_retry.py

This file was deleted.

26 changes: 0 additions & 26 deletions python/semantic_kernel/reliability/retry_mechanism_base.py

This file was deleted.

6 changes: 1 addition & 5 deletions python/tests/unit/kernel/test_kernel.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,7 @@
from semantic_kernel.contents import ChatMessageContent
from semantic_kernel.contents.chat_history import ChatHistory
from semantic_kernel.contents.function_call_content import FunctionCallContent
from semantic_kernel.exceptions import (
KernelFunctionAlreadyExistsError,
KernelServiceNotFoundError,
)
from semantic_kernel.exceptions import KernelFunctionAlreadyExistsError, KernelServiceNotFoundError
from semantic_kernel.exceptions.content_exceptions import FunctionCallInvalidArgumentsException
from semantic_kernel.exceptions.kernel_exceptions import (
KernelFunctionNotFoundError,
Expand Down Expand Up @@ -50,7 +47,6 @@ def test_init():
assert kernel.ai_service_selector is not None
assert kernel.plugins is not None
assert kernel.services is not None
assert kernel.retry_mechanism is not None
assert kernel.function_invocation_filters is not None
assert kernel.prompt_rendering_filters is not None

Expand Down

0 comments on commit f96f52c

Please sign in to comment.