Files
semantic-kernel/python/semantic_kernel/functions/kernel_parameter_metadata.py
T
Eduard van ValkenburgandTao Chen c8b4094835 Python: Introducing vector and text search (#9345)
### 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.
-->

This PR does the following things:
- Introduces TextSearch abstractions, including implementation for Bing
- This consists of the TextSearch class, which implements three public
search methods, and handles the internals, the search methods are:
'search' returns a string, 'get_text_search_results' returns a
TextSearchResult object and 'get_search_results' returns a object native
to the search service (i.e. BingWebPages for Bing)
- This also has a method called "create_{search_method}' which returns a
KernelFunction based on the search method. This function can be adapted
by setting the parameters and has several adaptability options and
allows you to create a RAG pipeline easily with custom names and
descriptions of both the functions and the parameters!
- Introduces VectorSearch abstractions, including implementation for
Azure AI Search
- This consists of a VectorStoreBase class which handles all the
internal and three public interfaces, vectorized_search (supply a
vector), vectorizable_text_search (supply a string that get's vectorized
downstream), vector_text_search (supply a string), each vector store
record collection can pick and choose which ones they need to support by
importing one or more next to the VectorSearchBase class.
- Introduces VectorStoreTextSearch as a way to leverage text search
against vector stores
- Since this builds on TextSearch this is now the best way to create a
super powerfull RAG setup with your own data model!
- Adds all the related classes, samples and tests for the above.
- Also reorders the data folder, which might cause some slight breaking
changes for the few stores that have the new vector store model.
- Adds additional IndexKinds and DistanceFunctions to stay in sync with
dotnet.
- Renames VolatileStore and VolatileCollection to InMemoryVectorStore
and InMemoryVectorCollection.

Closes #6832 #6833


### Contribution Checklist

<!-- Before submitting this PR, please make sure: -->

- [x] The code builds clean without any errors or warnings
- [x] 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
- [x] All unit tests pass, and I have added new tests where possible
- [ ] I didn't break anyone 😄

---------

Co-authored-by: Tao Chen <[email protected]>
2024-11-06 13:22:50 +00:00

63 lines
2.5 KiB
Python

# Copyright (c) Microsoft. All rights reserved.
from typing import Any
from pydantic import Field, model_validator
from semantic_kernel.kernel_pydantic import KernelBaseModel
from semantic_kernel.schema.kernel_json_schema_builder import KernelJsonSchemaBuilder
from semantic_kernel.utils.validation import FUNCTION_PARAM_NAME_REGEX
class KernelParameterMetadata(KernelBaseModel):
"""The kernel parameter metadata."""
name: str | None = Field(..., pattern=FUNCTION_PARAM_NAME_REGEX)
description: str | None = Field(None)
default_value: Any | None = None
type_: str | None = Field("str", alias="type")
is_required: bool | None = False
type_object: Any | None = None
schema_data: dict[str, Any] | None = None
include_in_function_choices: bool = True
@model_validator(mode="before")
@classmethod
def form_schema(cls, data: Any) -> Any:
"""Create a schema for the parameter metadata."""
if isinstance(data, dict) and data.get("schema_data") is None:
type_object = data.get("type_object", None)
type_ = data.get("type_", None)
default_value = data.get("default_value", None)
description = data.get("description", None)
inferred_schema = cls.infer_schema(type_object, type_, default_value, description)
data["schema_data"] = inferred_schema
return data
@classmethod
def infer_schema(
cls,
type_object: type | None = None,
parameter_type: str | None = None,
default_value: Any | None = None,
description: str | None = None,
structured_output: bool = False,
) -> dict[str, Any] | None:
"""Infer the schema for the parameter metadata."""
schema = None
if type_object is not None:
schema = KernelJsonSchemaBuilder.build(type_object, description, structured_output)
elif parameter_type is not None:
string_default = str(default_value) if default_value is not None else None
if string_default and string_default.strip():
needs_space = bool(description and description.strip())
description = (
f"{description}{' ' if needs_space else ''}(default value: {string_default})"
if description
else f"(default value: {string_default})"
)
schema = KernelJsonSchemaBuilder.build_from_type_name(parameter_type, description)
return schema