.Net: Python: KernelJsonSchemaBuilder emits {"type": "object"} with no enum for typing.Literal parameters and fields
Maintainer thường phản hồi trong vòng 4 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 82/100
Hướng nghiên cứu
Đọc python/semantic_kernel/schema/kernel_json_schema_builder.py, tập trung vào handle_complex_type() và get_json_schema(). Trước tiên, hãy chạy các ví dụ trực tiếp của KernelJsonSchemaBuilder.build() và bản tái hiện kernel-function được cung cấp. Hoàn thành có nghĩa là các giá trị Literal tạo ra các schema enum có kiểu, bao gồm cả các trường hợp nullable và lồng trong list, thay vì các schema object.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
What happens
KernelJsonSchemaBuilder has no handling for typing.Literal. A parameter typed Literal["fast", "slow"] is advertised to the model as a bare {"type": "object"} with no enum. The model is told the argument is an object and is never told the allowed values.
This affects @kernel_function parameters, Pydantic model fields, and Literal nested inside list[...] or Optional[...].
Where
python/semantic_kernel/schema/kernel_json_schema_builder.py, KernelJsonSchemaBuilder.handle_complex_type() and get_json_schema().
Literal[...] has __args__, so build() sends it to handle_complex_type(). That method handles list, set, dict, tuple and Union, but not Literal, so it reaches the final fallback:
schema = cls.get_json_schema(parameter_type) # TYPE_MAPPING.get(Literal[...], "object")
TYPE_MAPPING has no entry for a Literal alias, so the default "object" is returned. build_enum_schema() already produces the right shape for Enum classes ({"type": ..., "enum": [...]}), but nothing does that for Literal.
Repro
Tested with semantic-kernel==1.44.1. I diffed kernel_json_schema_builder.py against current main and the file is identical.
import json
from typing import Annotated, Literal
from pydantic import BaseModel
from semantic_kernel import Kernel
from semantic_kernel.functions import kernel_function
from semantic_kernel.connectors.ai.function_calling_utils import kernel_function_metadata_to_function_call_format
class Opts(BaseModel):
level: Literal["low", "high"]
class Plugin:
@kernel_function(name="run")
def run(self, mode: Annotated[Literal["fast", "slow"], "speed mode"], opts: Annotated[Opts, "options"]) -> str:
return mode
k = Kernel(); k.add_plugin(Plugin(), "p")
fn = k.get_function("p", "run")
print(json.dumps(kernel_function_metadata_to_function_call_format(fn.metadata)["function"]["parameters"], indent=1))
Output:
{
"type": "object",
"properties": {
"mode": {"type": "object", "description": "speed mode"},
"opts": {
"type": "object",
"properties": {"level": {"type": "object"}},
"required": ["level"],
"description": "options"
}
},
"required": ["mode", "opts"]
}
Direct builder calls:
KernelJsonSchemaBuilder.build(Literal["fast", "slow"]) # {'type': 'object'}
KernelJsonSchemaBuilder.build(Optional[Literal["fast", "slow"]]) # {'type': ['object', 'null']}
KernelJsonSchemaBuilder.build(list[Literal["a", "b"]]) # {'type': 'array', 'items': {'type': 'object'}}
Expected
{"type": "string", "enum": ["fast", "slow"], "description": "speed mode"}
This is the same shape build_enum_schema() already returns for an Enum subclass. Optional[Literal[...]] should be nullable and list[Literal[...]] should have an enum on items.
Actual
{"type": "object"} with no allowed values. The model can emit any value, including a JSON object, and the kernel then tries to bind it to a str parameter. Tools that use Literal to constrain choices (a very common pattern) lose that constraint entirely.
Suggested fix
Add a Literal branch in handle_complex_type():
if origin is Literal:
values = list(args)
types = {TYPE_MAPPING.get(type(v), "string") for v in values}
schema = {"type": types.pop() if len(types) == 1 else sorted(types), "enum": values}
if description:
schema["description"] = description
return schema
The Optional[...] branch also needs to keep working with an enum schema (add None to the enum when making it nullable).
I searched open and closed issues and PRs for Literal, KernelJsonSchemaBuilder, and schema builder problems. #14239, #14241 and #14310 are about string forward references and only make sure Literal values are left alone while resolving them. #14482 and #14155 are about NoneType in unions. None of them adds Literal support.
- Ngôn ngữ chính
- C#
- Star
- 28.6k
- Fork
- 4.8k
- Merge trung bình
- 1 ngày 3 giờ
- Pull request đã merge (30 ngày)
- 16
Chuẩn bị môi trường
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của microsoft/semantic-kernel
-
python triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
microsoft/semantic-kernel#14512 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 4 ngày
-
python triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
microsoft/semantic-kernel#14491 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 4 ngày
-
python triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
microsoft/semantic-kernel#14490 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 4 ngày
-
Python: [Python] structured_outputs_transform reuses ChatHistory across calls (prompt pollution)Đang mởpython triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
microsoft/semantic-kernel#14483 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 4 ngày
-
.NET python triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
microsoft/semantic-kernel#14482 · 3 bình luận ·
Maintainer thường phản hồi trong vòng 4 ngày
Tất cả issue của microsoft/semantic-kernel
Issue tương tự
-
Money ExploitsĐang mởS: Untriaged
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
project-wayfarer/wayfarer-14#1628 ·
Maintainer thường phản hồi trong vòng 3 ngày
-
:watch: Not Triaged dotnet-target-version
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 85/100
Maintainer thường phản hồi trong vòng 1 ngày
-
copilot documentation
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
Maintainer thường phản hồi trong vòng 2 ngày
-
untriaged
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 86/100
dotnet/dotnet-api-docs#13124 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
agentic-workflows
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
Maintainer thường phản hồi trong vòng 1 ngày