Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix functions_view.py #1213

Merged
merged 9 commits into from
Jun 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion python/semantic_kernel/skill_definition/functions_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,17 @@ def is_semantic(self, skill_name: str, function_name: str) -> bool:
return as_sf

def is_native(self, skill_name: str, function_name: str) -> bool:
return not self.is_semantic(skill_name, function_name)
as_sf = self._semantic_functions.get(skill_name, [])
as_sf = any(f.name == function_name for f in as_sf)

as_nf = self._native_functions.get(skill_name, [])
as_nf = any(f.name == function_name for f in as_nf)

if as_sf and as_nf:
raise KernelException(
KernelException.ErrorCodes.AmbiguousImplementation,
f"There are 2 functions with the same name: {function_name}."
f"One is native and the other semantic.",
)

return as_nf
152 changes: 152 additions & 0 deletions python/tests/unit/skill_definition/test_functions_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# Copyright (c) Microsoft. All rights reserved.

import pytest
awharrison-28 marked this conversation as resolved.
Show resolved Hide resolved
from semantic_kernel.kernel_exception import KernelException
from semantic_kernel.skill_definition.function_view import FunctionView
from semantic_kernel.skill_definition.functions_view import FunctionsView, FunctionView


def test_add_semantic_function():
view = FunctionView(
name="function1",
skill_name="skill1",
description="Semantic function",
parameters=[],
is_semantic=True,
is_asynchronous=True,
)
functions_view = FunctionsView()
functions_view.add_function(view)
semantic_functions = functions_view._semantic_functions.get("skill1")
assert len(semantic_functions) == 1
assert semantic_functions[0] == view


def test_add_native_function():
view = FunctionView(
name="function2",
skill_name="skill2",
description="Native function",
parameters=[],
is_semantic=False,
is_asynchronous=True,
)
functions_view = FunctionsView()
functions_view.add_function(view)
native_functions = functions_view._native_functions.get("skill2")
assert len(native_functions) == 1
assert native_functions[0] == view


def test_add_multiple_functions():
semantic_function = FunctionView(
name="function1",
skill_name="skill1",
description="Semantic function",
parameters=[],
is_semantic=True,
is_asynchronous=True,
)
native_function = FunctionView(
name="function2",
skill_name="skill2",
description="Native function",
parameters=[],
is_semantic=False,
is_asynchronous=True,
)
functions_view = FunctionsView()
functions_view.add_function(semantic_function)
functions_view.add_function(native_function)
semantic_functions = functions_view._semantic_functions.get("skill1")
native_functions = functions_view._native_functions.get("skill2")
assert len(semantic_functions) == 1
assert semantic_functions[0] == semantic_function
assert len(native_functions) == 1
assert native_functions[0] == native_function


def test_is_semantic():
semantic_function = FunctionView(
name="function1",
skill_name="skill1",
description="Semantic function",
parameters=[],
is_semantic=True,
is_asynchronous=True,
)
native_function = FunctionView(
name="function2",
skill_name="skill2",
description="Native function",
parameters=[],
is_semantic=False,
is_asynchronous=True,
)
functions_view = FunctionsView()
functions_view.add_function(semantic_function)
functions_view.add_function(native_function)
assert functions_view.is_semantic("skill1", "function1") is True
assert functions_view.is_semantic("skill2", "function2") is False
assert functions_view.is_semantic("skill1", "unregistered_function") is False


def test_is_native():
semantic_function = FunctionView(
name="function1",
skill_name="skill1",
description="Semantic function",
parameters=[],
is_semantic=True,
is_asynchronous=True,
)
native_function = FunctionView(
name="function2",
skill_name="skill2",
description="Native function",
parameters=[],
is_semantic=False,
is_asynchronous=True,
)
functions_view = FunctionsView()
functions_view.add_function(semantic_function)
functions_view.add_function(native_function)
assert functions_view.is_native("skill1", "function1") is False
assert functions_view.is_native("skill2", "function2") is True
assert functions_view.is_native("skill2", "unregistered_function") is False


def test_ambiguous_implementation():
semantic_function = FunctionView(
name="function1",
skill_name="skill1",
description="Semantic function",
parameters=[],
is_semantic=True,
is_asynchronous=True,
)
native_function = FunctionView(
name="function1",
skill_name="skill1",
description="Native function",
parameters=[],
is_semantic=False,
is_asynchronous=True,
)
functions_view = FunctionsView()
functions_view.add_function(semantic_function)
functions_view.add_function(native_function)

with pytest.raises(KernelException) as exc_info:
functions_view.is_semantic("skill1", "function1")

assert (
exc_info.value.error_code == KernelException.ErrorCodes.AmbiguousImplementation
)

with pytest.raises(KernelException) as exc_info:
functions_view.is_native("skill1", "function1")

assert (
exc_info.value.error_code == KernelException.ErrorCodes.AmbiguousImplementation
)