semantic-kernel icon indicating copy to clipboard operation
semantic-kernel copied to clipboard

Native Python Function not returning correct result

Open riedgar-ms opened this issue 2 years ago • 6 comments

Describe the bug

I have written a native Python function, but it does not appear to be returning the expected value. Instead, it just returns its input

To Reproduce Steps to reproduce the behavior:

I have a file native_function.py which contains:

from semantic_kernel.skill_definition import sk_function


class PythonGroundingSkill:
    @sk_function(
        description="Extract contents of <json_block> tags",
        name="ParseJsonBlock",
    )
    def extract_json_block_from_text(self, text: str):
        start_tag = "<json_block>"
        end_tag = "</json_block>"
        i_0 = text.find(start_tag) + len(start_tag)
        i_1 = text.find(end_tag)

        extracted_text = text[i_0:i_1]
        print(f"=~=~=~=\n{extracted_text}\n=~=~=~=\n")

        return extracted_text

I then call it through the following file:

import semantic_kernel as sk
from semantic_kernel.connectors.ai.open_ai import AzureTextCompletion, OpenAITextCompletion

kernel = sk.Kernel()

useAzureOpenAI = True

# Configure AI service used by the kernel
if useAzureOpenAI:
    deployment, api_key, endpoint = sk.azure_openai_settings_from_dot_env()
    kernel.add_text_completion_service("dv", AzureTextCompletion(deployment, endpoint, api_key))
else:
    api_key, org_id = sk.openai_settings_from_dot_env()
    kernel.add_text_completion_service("dv", OpenAITextCompletion("text-davinci-003", api_key, org_id))

skills_directory = "../../skills"
groundingNativeFunctions = kernel.import_native_skill_from_directory(skills_directory, "GroundingSkill")


jsonblock_fetch = groundingNativeFunctions["ParseJsonBlock"]

function_result = jsonblock_fetch("something <json_block>[0, 1]</json_block> something else")

print(function_result.result)

I get output

=~=~=~=
[0, 1]
=~=~=~=

something <json_block>[0, 1]</json_block> something else

So internally, the function is doing the right thing (as seen from the =~=~ bits), but the returned value was the original string, not the return value of the function defined.

Expected behavior

If I return a value from a function, I would like to receive that value back.

Screenshots If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: Win11 / Python 3.11
  • IDE: [e.g. Visual Studio, VS Code]
  • NuGet Package Version [e.g. 0.1.0]

Additional context

Name: semantic-kernel
Version: 0.2.7.dev0
Summary:
Home-page:
Author: Microsoft
Author-email: [email protected]

riedgar-ms avatar May 18 '23 17:05 riedgar-ms

This behaviour would be consistent with the following being the only 'Python native' sample test function: https://github.com/microsoft/semantic-kernel/blob/11d77358ef5ba1be7eb7f26fee352a0a7761df59/python/tests/test_native_skills/TestNativeSkill/native_function.py

riedgar-ms avatar May 18 '23 18:05 riedgar-ms

I had similar issue today , can you try adding a return type hint ? e.g.

def extract_json_block_from_text(self, text: str): -> str

JTremb avatar May 18 '23 19:05 JTremb

Looking a bit more at this. When there is no return type it infers a DelegateTypes.Void.

  • It would probably be better to raise an exception in this case and infers Void when it's explicit.
  • DelegateTypes.Void should also not return $input

JTremb avatar May 18 '23 19:05 JTremb

OK, so changing the signature to -> str did indeed let it get back the right information.

However, when I try changing the return type to ->Union[Dict[str,Any], List[Any]] (which is what I'd like it to be long-term), it still doesn't work. Now, the function apparently isn't even in the dictionary. Why is this?

riedgar-ms avatar May 18 '23 19:05 riedgar-ms

Looking a bit more at this. When there is no return type it infers a DelegateTypes.Void.

  • It would probably be better to raise an exception in this case and infers Void when it's explicit.
  • DelegateTypes.Void should also not return $input

Given that type hints aren't usually required in Python and that -> None is allowable, I think raising an exception for a forgotten return value would be a very good idea.

riedgar-ms avatar May 18 '23 19:05 riedgar-ms

@mkarle can you take a look at this.

evchaki avatar May 18 '23 20:05 evchaki

Team triage: improve function signature detection

dluc avatar Jun 09 '23 17:06 dluc

OK, so changing the signature to -> str did indeed let it get back the right information.

However, when I try changing the return type to ->Union[Dict[str,Any], List[Any]] (which is what I'd like it to be long-term), it still doesn't work. Now, the function apparently isn't even in the dictionary. Why is this?

Even I am facing the same issue. I want my native function to return dict and list values as well, but it only returns string values.

aditi-l avatar Sep 22 '23 05:09 aditi-l

Right now you can only return None, str, and SKContext types. You can put dict and list values in the SKContext object though.

mkarle avatar Sep 22 '23 22:09 mkarle

Right now you can only return None, str, and SKContext types. You can put dict and list values in the SKContext object though.

Can you give an example of how to use SKContext for returning a JSON or a dict object in Python.

AliRaza190 avatar Nov 02 '23 11:11 AliRaza190