chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import sys
|
||||
import time
|
||||
from typing import Annotated
|
||||
|
||||
from semantic_kernel.connectors.ai.function_choice_behavior import FunctionChoiceBehavior
|
||||
from semantic_kernel.connectors.ai.open_ai.services.open_ai_chat_completion import OpenAIChatCompletion
|
||||
from semantic_kernel.connectors.ai.prompt_execution_settings import PromptExecutionSettings
|
||||
from semantic_kernel.functions.kernel_arguments import KernelArguments
|
||||
from semantic_kernel.functions.kernel_function_decorator import kernel_function
|
||||
from semantic_kernel.kernel import Kernel
|
||||
|
||||
# This sample demonstrates how the kernel will execute functions in parallel.
|
||||
# The output of this sample should look similar to the following:
|
||||
#
|
||||
# [2024-09-11 10:15:35.070 INFO] processing 2 tool calls in parallel.
|
||||
# The employee with ID 123 is named John Doe and they are 30 years old.
|
||||
# Time elapsed: 11.96s
|
||||
#
|
||||
# The mock plugin simulates a long-running operation to fetch the employee's name and age.
|
||||
# When you run the sample, you should see the total execution time is less than the sum
|
||||
# of the two function calls because the kernel executes the functions in parallel.
|
||||
|
||||
# This concept example shows how to handle both streaming and non-streaming responses
|
||||
# To toggle the behavior, set the following flag accordingly:
|
||||
stream = True
|
||||
|
||||
|
||||
def set_up_logging():
|
||||
"""Set up logging to verify the kernel execute the functions in parallel"""
|
||||
root_logger = logging.getLogger()
|
||||
root_logger.setLevel(logging.INFO)
|
||||
|
||||
handler = logging.StreamHandler(sys.stdout)
|
||||
handler.setLevel(logging.INFO)
|
||||
handler.setFormatter(
|
||||
logging.Formatter("[%(asctime)s.%(msecs)03d %(levelname)s] %(message)s", datefmt="%Y-%m-%d %H:%M:%S"),
|
||||
)
|
||||
# Print only the logs from the chat completion client to reduce the output of the sample
|
||||
handler.addFilter(lambda record: record.name == "semantic_kernel.connectors.ai.chat_completion_client_base")
|
||||
|
||||
root_logger.addHandler(handler)
|
||||
|
||||
|
||||
class EmployeePlugin:
|
||||
"""A mock plugin to simulate a plugin that fetches employee information"""
|
||||
|
||||
@kernel_function(name="get_name", description="Find the name of the employee by the id")
|
||||
async def get_name(
|
||||
self, id: Annotated[str, "The ID of the employee"]
|
||||
) -> Annotated[str, "The name of the employee"]:
|
||||
# Simulate a long-running operation
|
||||
await asyncio.sleep(10)
|
||||
return "John Doe"
|
||||
|
||||
@kernel_function(name="get_age", description="Get the age of the employee by the id")
|
||||
async def get_age(self, id: Annotated[str, "The ID of the employee"]) -> Annotated[int, "The age of the employee"]:
|
||||
# Simulate a long-running operation
|
||||
await asyncio.sleep(10)
|
||||
return 30
|
||||
|
||||
|
||||
async def main():
|
||||
kernel = Kernel()
|
||||
kernel.add_service(OpenAIChatCompletion(service_id="open_ai"))
|
||||
kernel.add_plugin(EmployeePlugin(), "EmployeePlugin")
|
||||
|
||||
# With this query, the model will call the get_name and get_age functions in parallel.
|
||||
# Note that for certain queries, the model may choose to call the functions sequentially.
|
||||
# For example, if the available functions are `get_email_by_id` and `get_name_by_email`,
|
||||
# the model will not be able to call them in parallel because the second function depends
|
||||
# on the result of the first function.
|
||||
query = "What is the name and age of the employee of ID 123?"
|
||||
arguments = KernelArguments(
|
||||
settings=PromptExecutionSettings(
|
||||
# Set the function_choice_behavior to auto to let the model
|
||||
# decide which function to use, and let the kernel automatically
|
||||
# execute the functions.
|
||||
function_choice_behavior=FunctionChoiceBehavior.Auto(),
|
||||
)
|
||||
)
|
||||
|
||||
start = time.perf_counter()
|
||||
|
||||
if stream:
|
||||
async for result in kernel.invoke_prompt_stream(query, arguments=arguments):
|
||||
print(str(result[0]), end="")
|
||||
print()
|
||||
else:
|
||||
result = await kernel.invoke_prompt(query, arguments=arguments)
|
||||
print(result)
|
||||
|
||||
print(f"Time elapsed: {time.perf_counter() - start:.2f}s")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
set_up_logging()
|
||||
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user