Skip to content

Commit d30250f

Browse files
authoredJun 18, 2024
Python: custom service selector sample (microsoft#6802)
### Motivation and Context <!-- Thank you for your contribution to the semantic-kernel repo! Please help reviewers and future users, providing the following information: 1. Why is this change required? 2. What problem does it solve? 3. What scenario does it contribute to? 4. If it fixes an open issue, please link to the issue here. --> ### Description <!-- Describe your changes, the overall approach, the underlying design. These notes will help understanding how your code works. Thanks! --> ### Contribution Checklist <!-- Before submitting this PR, please make sure: --> - [ ] The code builds clean without any errors or warnings - [ ] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [ ] All unit tests pass, and I have added new tests where possible - [ ] I didn't break anyone 😄
1 parent ecb9ae5 commit d30250f

File tree

3 files changed

+76
-0
lines changed

3 files changed

+76
-0
lines changed
 

‎python/samples/concepts/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ This section contains code snippets that demonstrate the usage of Semantic Kerne
1717
| PromptTemplates | Using [`Templates`](https://github.com/microsoft/semantic-kernel/blob/main/python/semantic_kernel/prompt_template/prompt_template_base.py) with parametrization for `Prompt` rendering |
1818
| RAG | Different ways of `RAG` (Retrieval-Augmented Generation) |
1919
| Search | Using search services information |
20+
| Service Selector | Shows how to create and use a custom service selector class. |
2021
| Setup | How to setup environment variables for Semantic Kernel |
2122
| TextGeneration | Using [`TextGeneration`](https://github.com/microsoft/semantic-kernel/blob/main/python/semantic_kernel/connectors/ai/text_completion_client_base.py) capable service with models |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Copyright (c) Microsoft. All rights reserved.
2+
3+
from semantic_kernel.connectors.ai.open_ai.services.azure_chat_completion import AzureChatCompletion
4+
from semantic_kernel.connectors.ai.open_ai.services.open_ai_chat_completion import OpenAIChatCompletion
5+
from semantic_kernel.connectors.ai.prompt_execution_settings import PromptExecutionSettings
6+
from semantic_kernel.const import DEFAULT_SERVICE_NAME
7+
from semantic_kernel.contents.chat_history import ChatHistory
8+
from semantic_kernel.functions.kernel_arguments import KernelArguments
9+
from semantic_kernel.functions.kernel_function import KernelFunction
10+
from semantic_kernel.kernel import Kernel
11+
from semantic_kernel.kernel_types import AI_SERVICE_CLIENT_TYPE
12+
from semantic_kernel.services.ai_service_client_base import AIServiceClientBase
13+
from semantic_kernel.services.ai_service_selector import AIServiceSelector
14+
from semantic_kernel.services.kernel_services_extension import KernelServicesExtension
15+
16+
17+
class CustomServiceSelector(AIServiceSelector):
18+
def select_ai_service(
19+
self,
20+
kernel: "KernelServicesExtension",
21+
function: "KernelFunction",
22+
arguments: "KernelArguments",
23+
type_: type[AI_SERVICE_CLIENT_TYPE] | tuple[type[AI_SERVICE_CLIENT_TYPE], ...] | None = None,
24+
) -> tuple["AIServiceClientBase", "PromptExecutionSettings"]:
25+
execution_settings_dict = arguments.execution_settings or {}
26+
if func_exec_settings := getattr(function, "prompt_execution_settings", None):
27+
for id, settings in func_exec_settings.items():
28+
if id not in execution_settings_dict:
29+
execution_settings_dict[id] = settings
30+
if not execution_settings_dict:
31+
from semantic_kernel.connectors.ai.prompt_execution_settings import PromptExecutionSettings
32+
33+
execution_settings_dict = {DEFAULT_SERVICE_NAME: PromptExecutionSettings()}
34+
35+
gpt_4_settings = {
36+
service_name: settings
37+
for service_name, settings in execution_settings_dict.items()
38+
if "gpt-4" in service_name
39+
}
40+
if gpt_4_settings:
41+
service_id = list(gpt_4_settings.keys())[0]
42+
service = kernel.get_service(service_id, type=type_)
43+
service_settings = service.get_prompt_execution_settings_from_settings(gpt_4_settings[service_id])
44+
return service, service_settings
45+
return super().select_ai_service(kernel, function, arguments, type_)
46+
47+
48+
kernel = Kernel(ai_service_selector=CustomServiceSelector())
49+
kernel.add_service(AzureChatCompletion(service_id="gpt-4o"))
50+
kernel.add_service(OpenAIChatCompletion(service_id="gpt-3.5-turbo", ai_model_id="gpt-3.5-turbo"))
51+
52+
kernel.add_function(
53+
plugin_name="selector",
54+
function_name="select_ai_service",
55+
prompt="Always respond with your name. {{$chat_history}}",
56+
prompt_execution_settings={
57+
"gpt-4o": PromptExecutionSettings(service_id="gpt-4o", max_tokens=200, temperature=0.0),
58+
"gpt-3.5-turbo": PromptExecutionSettings(service_id="gpt-3.5-turbo", max_tokens=400, temperature=1.0),
59+
},
60+
)
61+
62+
63+
async def main():
64+
chat_history = ChatHistory()
65+
chat_history.add_user_message("I'm Eduard.")
66+
result = await kernel.invoke(plugin_name="selector", function_name="select_ai_service", chat_history=chat_history)
67+
print(result)
68+
69+
70+
if __name__ == "__main__":
71+
import asyncio
72+
73+
asyncio.run(main())

‎python/tests/samples/test_concepts.py

+2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
from samples.concepts.prompt_templates.template_language import main as template_language
4040
from samples.concepts.rag.rag_with_text_memory_plugin import main as rag_with_text_memory_plugin
4141
from samples.concepts.search.bing_search_plugin import main as bing_search_plugin
42+
from samples.concepts.service_selector.custom_service_selector import main as custom_service_selector
4243
from tests.samples.test_samples_utils import retry
4344

4445
concepts = [
@@ -79,6 +80,7 @@
7980
param(rag_with_text_memory_plugin, [], id="rag_with_text_memory_plugin"),
8081
param(bing_search_plugin, [], id="bing_search_plugin"),
8182
param(azure_chat_image_input, [], id="azure_chat_image_input"),
83+
param(custom_service_selector, [], id="custom_service_selector"),
8284
]
8385

8486

0 commit comments

Comments
 (0)