chore: import upstream snapshot with attribution
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run

This commit is contained in:
wehub-resource-sync
2026-07-13 13:21:23 +08:00
commit b957a53def
5423 changed files with 863745 additions and 0 deletions
@@ -0,0 +1,197 @@
{
"openapi": "3.0.1",
"info": {
"title": "Light Bulb API",
"version": "v1"
},
"servers": [
{
"url": "https://127.0.0.1"
}
],
"paths": {
"/Lights/{id}": {
"get": {
"operationId": "GetLightById",
"tags": [
"Lights"
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"style": "simple",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "Success"
}
}
},
"put": {
"operationId": "PutLightById",
"tags": [
"Lights"
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"style": "simple",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ChangeStateRequest"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/ChangeStateRequest"
}
},
"application/*+json": {
"schema": {
"$ref": "#/components/schemas/ChangeStateRequest"
}
}
}
},
"responses": {
"200": {
"description": "Success"
}
}
},
"delete": {
"operationId": "DeleteLightById",
"tags": [
"Lights"
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"style": "simple",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "Success"
}
}
}
},
"/Lights": {
"get": {
"operationId": "GetLights",
"tags": [
"Lights"
],
"parameters": [
{
"name": "roomId",
"in": "query",
"style": "form",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "Success"
}
}
},
"post": {
"operationId": "CreateLights",
"tags": [
"Lights"
],
"parameters": [
{
"name": "roomId",
"in": "query",
"style": "form",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "lightName",
"in": "query",
"style": "form",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Success"
}
}
}
}
},
"components": {
"schemas": {
"ChangeStateRequest": {
"type": "object",
"properties": {
"isOn": {
"type": "boolean",
"description": "Specifies whether the light is turned on or off."
},
"hexColor": {
"type": "string",
"description": "The hex color code for the light.",
"nullable": true
},
"brightness": {
"enum": [
"Low",
"Medium",
"High"
],
"type": "string",
"description": "The brightness level of the light."
},
"fadeDurationInMilliseconds": {
"type": "integer",
"description": "Duration for the light to fade to the new state, in milliseconds.",
"format": "int32"
},
"scheduledTime": {
"type": "string",
"description": "The time at which the change should occur.",
"format": "date-time"
}
},
"additionalProperties": false,
"description": "Represents a request to change the state of the light."
}
}
}
}
@@ -0,0 +1,10 @@
{
"messages": [
{
"content": "Can you help me tell the time in Seattle right now?",
"role": "user"
}
],
"stream": false,
"model": "gpt-4.1-nano"
}
@@ -0,0 +1,18 @@
{
"messages": [
{
"content": "Can you help me tell the time in Seattle right now?",
"role": "user"
},
{
"content": "Sure! The time in Seattle is currently 3:00 PM.",
"role": "assistant"
},
{
"content": "What about New York?",
"role": "user"
}
],
"stream": false,
"model": "gpt-4.1-nano"
}
@@ -0,0 +1,7 @@
name: getTimes
description: Gets the time in various cities.
template: |
<message role="user">Can you help me tell the time in Seattle right now?</message>
<message role="assistant">Sure! The time in Seattle is currently 3:00 PM.</message>
<message role="user">What about New York?</message>
template_format: handlebars
@@ -0,0 +1,7 @@
name: getTimes
description: Gets the time in various cities.
template: |
<message role="user">Can you help me tell the time in Seattle right now?</message>
<message role="assistant">Sure! The time in Seattle is currently 3:00 PM.</message>
<message role="user">What about New York?</message>
template_format: jinja2
@@ -0,0 +1,10 @@
{
"messages": [
{
"content": "Can you help me tell the time in Seattle right now?",
"role": "user"
}
],
"stream": false,
"model": "gpt-4.1-nano"
}
@@ -0,0 +1,14 @@
{
"messages": [
{
"content": "The current time is Sun, 04 Jun 1989 12:11:13 GMT",
"role": "system"
},
{
"content": "Can you help me tell the time in Seattle right now?",
"role": "user"
}
],
"stream": false,
"model": "gpt-4.1-nano"
}
@@ -0,0 +1,10 @@
{
"messages": [
{
"content": "Can you help me tell the time in Seattle right now?",
"role": "user"
}
],
"stream": false,
"model": "gpt-4.1-nano"
}
@@ -0,0 +1,9 @@
name: getTimeInCity
description: Gets the time in a specified city.
template: |
<message role="user">Can you help me tell the time in {{$city}} right now?</message>
template_format: semantic-kernel
input_variables:
- name: city
description: City for which time is desired
default: Seattle
@@ -0,0 +1,5 @@
name: getSeattleTime
description: Gets the time in Seattle.
template: |
<message role="user">Can you help me tell the time in Seattle right now?</message>
template_format: semantic-kernel
@@ -0,0 +1,834 @@
# Copyright (c) Microsoft. All rights reserved.
import contextlib
import datetime
import json
import logging
import os
from collections.abc import AsyncGenerator
from typing import Literal
import httpx
import pytest
import pytest_asyncio
from openai import AsyncOpenAI
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion, OpenAISettings
from semantic_kernel.functions.kernel_arguments import KernelArguments
from semantic_kernel.functions.kernel_function import KernelFunction
from semantic_kernel.functions.kernel_function_decorator import kernel_function
from semantic_kernel.functions.kernel_function_from_method import KernelFunctionFromMethod
from semantic_kernel.functions.kernel_function_from_prompt import KernelFunctionFromPrompt
from semantic_kernel.kernel import Kernel
from semantic_kernel.prompt_template.prompt_template_config import PromptTemplateConfig
logger = logging.getLogger(__name__)
OPENAI_MODEL_ID = "gpt-4.1-nano"
# region Test Prompts
simple_prompt = "Can you help me tell the time in Seattle right now?"
sk_simple_prompt = "Can you help me tell the time in {{$city}} right now?"
hb_simple_prompt = "Can you help me tell the time in {{city}} right now?"
j2_simple_prompt = "Can you help me tell the time in {{city}} right now?"
sk_prompt = '<message role="system">The current time is {{Time.Now}}</message><message role="user">Can you help me tell the time in {{$city}} right now?</message>' # noqa: E501
hb_prompt = '<message role="system">The current time is {{Time-Now}}</message><message role="user">Can you help me tell the time in {{city}} right now?</message>' # noqa: E501
j2_prompt = '<message role="system">The current time is {{Time_Now()}}</message><message role="user">Can you help me tell the time in {{city}} right now?</message>' # noqa: E501
# endregion
# region Custom Logging Class
class LoggingTransport(httpx.AsyncBaseTransport):
def __init__(self, inner=None):
self.inner = inner or httpx.AsyncHTTPTransport()
self.request_headers = {}
self.request_content = None
self.response_headers = {}
self.response_content = None
async def handle_async_request(self, request: httpx.Request) -> httpx.Response:
self.request_headers = dict(request.headers)
self.request_content = request.content.decode("utf-8") if request.content else None
logger.info(f"Request URL: {request.url}")
logger.info(f"Request Headers: {self.request_headers}")
logger.info(f"Request Content: {self.request_content}")
response = await self.inner.handle_async_request(request)
raw_response_bytes = await response.aread()
self.response_headers = dict(response.headers)
self.response_content = raw_response_bytes.decode(response.encoding or "utf-8", errors="replace")
logger.info(f"Response Headers: {self.response_headers}")
logger.info(f"Response Content: {self.response_content}")
headers_without_encoding = {k: v for k, v in response.headers.items() if k.lower() != "content-encoding"}
return httpx.Response(
status_code=response.status_code,
headers=headers_without_encoding,
content=raw_response_bytes,
request=request,
extensions=response.extensions,
)
class LoggingAsyncClient(httpx.AsyncClient):
def __init__(self, *args, **kwargs):
transport = kwargs.pop("transport", None)
self.logging_transport = LoggingTransport(transport or httpx.AsyncHTTPTransport())
super().__init__(*args, **kwargs, transport=self.logging_transport)
@property
def request_headers(self):
return self.logging_transport.request_headers
@property
def request_content(self):
return self.logging_transport.request_content
@property
def response_headers(self):
return self.logging_transport.response_headers
@property
def response_content(self):
return self.logging_transport.response_content
# endregion
# region Test Helper Methods
@pytest_asyncio.fixture
async def async_clients() -> AsyncGenerator[tuple[AsyncOpenAI, LoggingAsyncClient], None]:
openai_settings = OpenAISettings()
logging_async_client = LoggingAsyncClient()
async with AsyncOpenAI(
api_key=openai_settings.api_key.get_secret_value(), http_client=logging_async_client
) as client:
yield client, logging_async_client
async def run_prompt(
kernel: Kernel,
is_inline: bool = False,
is_streaming: bool = False,
template_format: Literal[
"semantic-kernel",
"handlebars",
"jinja2",
] = None,
prompt: str = None,
arguments: KernelArguments = None,
prompt_template_config: PromptTemplateConfig = None,
):
if is_inline:
if is_streaming:
try:
async for _ in kernel.invoke_prompt_stream(
function_name="func_test_stream",
plugin_name="plugin_test",
prompt=prompt,
arguments=arguments,
template_format=template_format,
prompt_template_config=prompt_template_config,
):
pass
except NotImplementedError:
pass
else:
await kernel.invoke_prompt(
function_name="func_test",
plugin_name="plugin_test_stream",
prompt=prompt,
arguments=arguments,
template_format=template_format,
prompt_template_config=prompt_template_config,
)
else:
function = KernelFunctionFromPrompt(
function_name="test_func",
plugin_name="test_plugin",
prompt=prompt,
template_format=template_format,
prompt_template_config=prompt_template_config,
)
await run_function(kernel, is_streaming, function=function, arguments=arguments)
async def run_function(
kernel: Kernel,
is_streaming: bool = False,
function: KernelFunction | None = None,
arguments: KernelArguments | None = None,
):
if is_streaming:
try:
async for _ in kernel.invoke_stream(function=function, arguments=arguments):
pass
except NotImplementedError:
pass
else:
await kernel.invoke(function=function, arguments=arguments)
class City:
def __init__(self, name):
self.name = name
# endregion
# region Test Prompt With Chat Roles
@pytest.mark.parametrize(
"is_inline, is_streaming, template_format, prompt",
[
pytest.param(
True,
False,
"semantic-kernel",
'<message role="user">Can you help me tell the time in Seattle right now?</message><message role="assistant">Sure! The time in Seattle is currently 3:00 PM.</message><message role="user">What about New York?</message>', # noqa: E501
id="sk_inline_non_streaming",
),
pytest.param(
True,
True,
"semantic-kernel",
'<message role="user">Can you help me tell the time in Seattle right now?</message><message role="assistant">Sure! The time in Seattle is currently 3:00 PM.</message><message role="user">What about New York?</message>', # noqa: E501
id="sk_inline_streaming",
),
pytest.param(
False,
False,
"semantic-kernel",
'<message role="user">Can you help me tell the time in Seattle right now?</message><message role="assistant">Sure! The time in Seattle is currently 3:00 PM.</message><message role="user">What about New York?</message>', # noqa: E501
id="sk_non_inline_non_streaming",
),
pytest.param(
False,
True,
"semantic-kernel",
'<message role="user">Can you help me tell the time in Seattle right now?</message><message role="assistant">Sure! The time in Seattle is currently 3:00 PM.</message><message role="user">What about New York?</message>', # noqa: E501
id="sk_non_inline_streaming",
),
pytest.param(
False,
False,
"handlebars",
'<message role="user">Can you help me tell the time in Seattle right now?</message><message role="assistant">Sure! The time in Seattle is currently 3:00 PM.</message><message role="user">What about New York?</message>', # noqa: E501
id="hb_non_inline_non_streaming",
),
pytest.param(
False,
True,
"handlebars",
'<message role="user">Can you help me tell the time in Seattle right now?</message><message role="assistant">Sure! The time in Seattle is currently 3:00 PM.</message><message role="user">What about New York?</message>', # noqa: E501
id="hb_non_inline_streaming",
),
pytest.param(
False,
False,
"jinja2",
'<message role="user">Can you help me tell the time in Seattle right now?</message><message role="assistant">Sure! The time in Seattle is currently 3:00 PM.</message><message role="user">What about New York?</message>', # noqa: E501
id="j2_non_inline_non_streaming",
),
pytest.param(
False,
True,
"jinja2",
'<message role="user">Can you help me tell the time in Seattle right now?</message><message role="assistant">Sure! The time in Seattle is currently 3:00 PM.</message><message role="user">What about New York?</message>', # noqa: E501
id="j2_non_inline_streaming",
),
],
)
async def test_prompt_with_chat_roles(
is_inline, is_streaming, template_format, prompt, async_clients: tuple[AsyncOpenAI, LoggingAsyncClient]
):
client, logging_async_client = async_clients
ai_service = OpenAIChatCompletion(
service_id="test",
ai_model_id=OPENAI_MODEL_ID,
async_client=client,
)
kernel = Kernel()
kernel.add_service(ai_service)
await run_prompt(
kernel=kernel,
is_inline=is_inline,
is_streaming=is_streaming,
template_format=template_format,
prompt=prompt,
)
request_content = logging_async_client.request_content
assert request_content is not None
response_content = logging_async_client.response_content
assert response_content is not None
obtained_object = json.loads(request_content)
assert obtained_object is not None
data_directory = os.path.join(os.path.dirname(__file__), "data", "prompt_with_chat_roles_expected.json")
with open(data_directory) as f:
expected = f.read()
expected_object = json.loads(expected)
assert expected_object is not None
if is_streaming:
expected_object["stream"] = True
expected_object["stream_options"] = {"include_usage": True}
assert obtained_object == expected_object
# endregion
# region Test Prompt With Complex Objects
@pytest.mark.parametrize(
"is_inline, is_streaming, template_format, prompt",
[
pytest.param(
False,
False,
"handlebars",
"Can you help me tell the time in {{city.name}} right now?",
id="hb_non_inline_non_streaming",
),
pytest.param(
False,
True,
"handlebars",
"Can you help me tell the time in {{city.name}} right now?",
id="hb_non_inline_streaming",
),
pytest.param(
False,
False,
"jinja2",
"Can you help me tell the time in {{city.name}} right now?",
id="j2_non_inline_non_streaming",
),
pytest.param(
False,
True,
"jinja2",
"Can you help me tell the time in {{city.name}} right now?",
id="j2_non_inline_streaming",
),
pytest.param(
True,
False,
"handlebars",
"Can you help me tell the time in {{city.name}} right now?",
id="hb_inline_non_streaming",
),
pytest.param(
True,
True,
"handlebars",
"Can you help me tell the time in {{city.name}} right now?",
id="hb_inline_streaming",
),
pytest.param(
True,
False,
"jinja2",
"Can you help me tell the time in {{city.name}} right now?",
id="j2_inline_non_streaming",
),
pytest.param(
True, True, "jinja2", "Can you help me tell the time in {{city.name}} right now?", id="j2_inline_streaming"
),
],
)
async def test_prompt_with_complex_objects(
is_inline, is_streaming, template_format, prompt, async_clients: tuple[AsyncOpenAI, LoggingAsyncClient]
):
client, logging_async_client = async_clients
ai_service = OpenAIChatCompletion(
service_id="default",
ai_model_id=OPENAI_MODEL_ID,
async_client=client,
)
kernel = Kernel()
kernel.add_service(ai_service)
await run_prompt(
kernel=kernel,
is_inline=is_inline,
is_streaming=is_streaming,
prompt=prompt,
template_format=template_format,
prompt_template_config=PromptTemplateConfig(
template=prompt, template_format=template_format, allow_dangerously_set_content=True
),
arguments=KernelArguments(city=City("Seattle")),
)
request_content = logging_async_client.request_content
assert request_content is not None
response_content = logging_async_client.response_content
assert response_content is not None
obtained_object = json.loads(request_content)
assert obtained_object is not None
data_directory = os.path.join(os.path.dirname(__file__), "data", "prompt_with_complex_objects_expected.json")
with open(data_directory) as f:
expected = f.read()
expected_object = json.loads(expected)
assert expected_object is not None
if is_streaming:
expected_object["stream"] = True
expected_object["stream_options"] = {"include_usage": True}
assert obtained_object == expected_object
# endregion
# region Test Prompt With Helper Functions
@pytest.mark.parametrize(
"is_inline, is_streaming, template_format, prompt",
[
pytest.param(True, False, "semantic-kernel", sk_prompt, id="sk_inline_non_streaming"),
pytest.param(True, True, "semantic-kernel", sk_prompt, id="sk_inline_streaming"),
pytest.param(False, False, "semantic-kernel", sk_prompt, id="sk_non_inline_non_streaming"),
pytest.param(False, True, "semantic-kernel", sk_prompt, id="sk_non_inline_streaming"),
pytest.param(
False,
False,
"handlebars",
hb_prompt,
id="hb_non_inline_non_streaming",
marks=pytest.mark.xfail(reason="Throws intermittent APIConnectionError errors"),
),
pytest.param(False, True, "handlebars", hb_prompt, id="hb_non_inline_streaming"),
pytest.param(False, False, "jinja2", j2_prompt, id="j2_non_inline_non_streaming"),
pytest.param(False, True, "jinja2", j2_prompt, id="j2_non_inline_streaming"),
],
)
async def test_prompt_with_helper_functions(
is_inline, is_streaming, template_format, prompt, async_clients: tuple[AsyncOpenAI, LoggingAsyncClient]
):
client, logging_async_client = async_clients
ai_service = OpenAIChatCompletion(
service_id="default",
ai_model_id=OPENAI_MODEL_ID,
async_client=client,
)
kernel = Kernel()
kernel.add_service(ai_service)
func = KernelFunctionFromMethod(
method=kernel_function(
lambda: datetime.datetime(1989, 6, 4, 12, 11, 13, tzinfo=datetime.timezone.utc).strftime(
"%a, %d %b %Y %H:%M:%S GMT"
),
name="Now",
),
plugin_name="Time",
)
kernel.add_function(plugin_name="Time", function=func)
await run_prompt(
kernel=kernel,
is_inline=is_inline,
is_streaming=is_streaming,
prompt=prompt,
template_format=template_format,
prompt_template_config=PromptTemplateConfig(
template=prompt, template_format=template_format, allow_dangerously_set_content=True
),
arguments=KernelArguments(city="Seattle"),
)
request_content = logging_async_client.request_content
assert request_content is not None
response_content = logging_async_client.response_content
assert response_content is not None
obtained_object = json.loads(request_content)
assert obtained_object is not None
data_directory = os.path.join(os.path.dirname(__file__), "data", "prompt_with_helper_functions_expected.json")
with open(data_directory) as f:
expected = f.read()
expected_object = json.loads(expected)
assert expected_object is not None
if is_streaming:
expected_object["stream"] = True
expected_object["stream_options"] = {"include_usage": True}
assert obtained_object == expected_object
# endregion
# region Test Prompt With Simple Variable
@pytest.mark.parametrize(
"is_inline, is_streaming, template_format, prompt",
[
pytest.param(True, False, "semantic-kernel", sk_simple_prompt, id="sk_inline_non_streaming"),
pytest.param(True, True, "semantic-kernel", sk_simple_prompt, id="sk_inline_streaming"),
pytest.param(False, False, "semantic-kernel", sk_simple_prompt, id="sk_non_inline_non_streaming"),
pytest.param(False, True, "semantic-kernel", sk_simple_prompt, id="sk_non_inline_streaming"),
pytest.param(False, False, "handlebars", hb_simple_prompt, id="hb_non_inline_non_streaming"),
pytest.param(False, True, "handlebars", hb_simple_prompt, id="hb_non_inline_streaming"),
pytest.param(False, False, "jinja2", j2_simple_prompt, id="j2_non_inline_non_streaming"),
pytest.param(False, True, "jinja2", j2_simple_prompt, id="j2_non_inline_streaming"),
],
)
async def test_prompt_with_simple_variable(
is_inline, is_streaming, template_format, prompt, async_clients: tuple[AsyncOpenAI, LoggingAsyncClient]
):
client, logging_async_client = async_clients
ai_service = OpenAIChatCompletion(
service_id="default",
ai_model_id=OPENAI_MODEL_ID,
async_client=client,
)
kernel = Kernel()
kernel.add_service(ai_service)
await run_prompt(
kernel=kernel,
is_inline=is_inline,
is_streaming=is_streaming,
template_format=template_format,
prompt=prompt,
arguments=KernelArguments(city="Seattle"),
)
request_content = logging_async_client.request_content
assert request_content is not None
response_content = logging_async_client.response_content
assert response_content is not None
obtained_object = json.loads(request_content)
assert obtained_object is not None
data_directory = os.path.join(os.path.dirname(__file__), "data", "prompt_with_simple_variable_expected.json")
with open(data_directory) as f:
expected = f.read()
expected_object = json.loads(expected)
assert expected_object is not None
if is_streaming:
expected_object["stream"] = True
expected_object["stream_options"] = {"include_usage": True}
assert obtained_object == expected_object
# endregion
# region Test Simple Prompt
@pytest.mark.parametrize(
"is_inline, is_streaming, template_format, prompt",
[
pytest.param(True, False, "semantic-kernel", simple_prompt, id="sk_inline_non_streaming"),
pytest.param(True, True, "semantic-kernel", simple_prompt, id="sk_inline_streaming"),
pytest.param(False, False, "semantic-kernel", simple_prompt, id="sk_non_inline_non_streaming"),
pytest.param(False, True, "semantic-kernel", simple_prompt, id="sk_non_inline_streaming"),
pytest.param(False, False, "handlebars", simple_prompt, id="hb_non_inline_non_streaming"),
pytest.param(False, True, "handlebars", simple_prompt, id="hb_non_inline_streaming"),
pytest.param(False, False, "jinja2", simple_prompt, id="j2_non_inline_non_streaming"),
pytest.param(False, True, "jinja2", simple_prompt, id="j2_non_inline_streaming"),
],
)
async def test_simple_prompt(
is_inline, is_streaming, template_format, prompt, async_clients: tuple[AsyncOpenAI, LoggingAsyncClient]
):
client, logging_async_client = async_clients
ai_service = OpenAIChatCompletion(
service_id="default",
ai_model_id=OPENAI_MODEL_ID,
async_client=client,
)
kernel = Kernel()
kernel.add_service(ai_service)
await run_prompt(
kernel=kernel,
is_inline=is_inline,
is_streaming=is_streaming,
template_format=template_format,
prompt=prompt,
)
request_content = logging_async_client.request_content
assert request_content is not None
response_content = logging_async_client.response_content
assert response_content is not None
obtained_object = json.loads(request_content)
assert obtained_object is not None
data_directory = os.path.join(os.path.dirname(__file__), "data", "prompt_simple_expected.json")
with open(data_directory) as f:
expected = f.read()
expected_object = json.loads(expected)
assert expected_object is not None
if is_streaming:
expected_object["stream"] = True
expected_object["stream_options"] = {"include_usage": True}
assert obtained_object == expected_object
# endregion
# region Test YAML Prompts
@pytest.mark.parametrize(
"is_streaming, prompt_path, expected_result_path",
[
pytest.param(
False, "simple_prompt_test.yaml", "prompt_simple_expected.json", id="simple_prompt_test_non_streaming"
),
pytest.param(True, "simple_prompt_test.yaml", "prompt_simple_expected.json", id="simple_prompt_test_streaming"),
pytest.param(
False,
"prompt_with_chat_roles_test_hb.yaml",
"prompt_with_chat_roles_expected.json",
id="prompt_with_chat_roles_test_hb_non_streaming",
),
pytest.param(
True,
"prompt_with_chat_roles_test_hb.yaml",
"prompt_with_chat_roles_expected.json",
id="prompt_with_chat_roles_test_hb_streaming",
),
pytest.param(
False,
"prompt_with_chat_roles_test_j2.yaml",
"prompt_with_chat_roles_expected.json",
id="prompt_with_chat_roles_test_j2_non_streaming",
),
pytest.param(
True,
"prompt_with_chat_roles_test_j2.yaml",
"prompt_with_chat_roles_expected.json",
id="prompt_with_chat_roles_test_j2_streaming",
),
pytest.param(
False,
"prompt_with_simple_variable_test.yaml",
"prompt_with_simple_variable_expected.json",
id="prompt_with_simple_variable_non_streaming",
),
pytest.param(
True,
"prompt_with_simple_variable_test.yaml",
"prompt_with_simple_variable_expected.json",
id="prompt_with_simple_variable_streaming",
),
],
)
async def test_yaml_prompt(
is_streaming,
prompt_path,
expected_result_path,
kernel: Kernel,
async_clients: tuple[AsyncOpenAI, LoggingAsyncClient],
):
client, logging_async_client = async_clients
ai_service = OpenAIChatCompletion(
service_id="default",
ai_model_id=OPENAI_MODEL_ID,
async_client=client,
)
kernel.add_service(ai_service)
prompt_dir = os.path.join(os.path.dirname(__file__), "data", f"{prompt_path}")
with open(prompt_dir) as f:
prompt_str = f.read()
function = KernelFunctionFromPrompt.from_yaml(yaml_str=prompt_str, plugin_name="yaml_plugin")
await run_function(kernel=kernel, is_streaming=is_streaming, function=function)
request_content = logging_async_client.request_content
assert request_content is not None
response_content = logging_async_client.response_content
assert response_content is not None
obtained_object = json.loads(request_content)
assert obtained_object is not None
data_directory = os.path.join(os.path.dirname(__file__), "data", f"{expected_result_path}")
with open(data_directory) as f:
expected = f.read()
expected_object = json.loads(expected)
assert expected_object is not None
if is_streaming:
expected_object["stream"] = True
expected_object["stream_options"] = {"include_usage": True}
assert obtained_object == expected_object
# endregion
# region Test OpenAPI Plugin Load
async def setup_openapi_function_call(kernel: Kernel, function_name, arguments):
from semantic_kernel.connectors.openapi_plugin import OpenAPIFunctionExecutionParameters
openapi_spec_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data", "light_bulb_api.json")
request_details = None
async def mock_request(request: httpx.Request):
nonlocal request_details
if request.method in ["POST", "PUT"]:
request_body = None
if request.content:
request_body = request.content.decode()
elif request.stream:
try:
stream_content = await request.stream.read()
if stream_content:
request_body = stream_content.decode()
except Exception:
request_body = None
request_details = {
"method": request.method,
"url": str(request.url),
"body": request_body,
"headers": dict(request.headers),
}
else:
request_details = {"method": request.method, "url": str(request.url), "params": dict(request.url.params)}
transport = httpx.MockTransport(mock_request)
async with httpx.AsyncClient(transport=transport) as client:
plugin = kernel.add_plugin_from_openapi(
plugin_name="LightControl",
openapi_document_path=openapi_spec_file,
execution_settings=OpenAPIFunctionExecutionParameters(
http_client=client,
server_url_validation_allowed_base_urls=["https://127.0.0.1"],
),
)
assert plugin is not None
with contextlib.suppress(Exception):
# It is expected that the API call will fail, ignore
await run_function(kernel=kernel, is_streaming=False, function=plugin[function_name], arguments=arguments)
return request_details
async def test_openapi_get_lights(kernel: Kernel):
request_content = await setup_openapi_function_call(
kernel, function_name="GetLights", arguments=KernelArguments(roomId=1)
)
assert request_content is not None
assert request_content.get("method") == "GET"
assert request_content.get("url") == "https://127.0.0.1/Lights?roomId=1"
assert request_content.get("params") == {"roomId": "1"}
async def test_openapi_get_light_by_id(kernel: Kernel):
request_content = await setup_openapi_function_call(
kernel, function_name="GetLightById", arguments=KernelArguments(id=1)
)
assert request_content is not None
assert request_content.get("method") == "GET"
assert request_content.get("url") == "https://127.0.0.1/Lights/1"
async def test_openapi_delete_light_by_id(kernel: Kernel):
request_content = await setup_openapi_function_call(
kernel, function_name="DeleteLightById", arguments=KernelArguments(id=1)
)
assert request_content is not None
assert request_content.get("method") == "DELETE"
assert request_content.get("url") == "https://127.0.0.1/Lights/1"
async def test_openapi_create_lights(kernel: Kernel):
request_content = await setup_openapi_function_call(
kernel, function_name="CreateLights", arguments=KernelArguments(roomId=1, lightName="disco")
)
assert request_content is not None
assert request_content.get("method") == "POST"
assert request_content.get("url") == "https://127.0.0.1/Lights?roomId=1&lightName=disco"
async def test_openapi_put_light_by_id(kernel: Kernel):
request_content = await setup_openapi_function_call(
kernel, function_name="PutLightById", arguments=KernelArguments(id=1, hexColor="11EE11")
)
assert request_content is not None
assert request_content.get("method") == "PUT"
assert request_content.get("url") == "https://127.0.0.1/Lights/1"
assert request_content.get("body") == '{"hexColor":"11EE11"}'
# endregion