12、Function Calling按需返回JSON

12、Function Calling按需返回JSON

结构化的Json 输出

在与人工智能模型交互时,尤其是在一致性、清晰度和准确性很重要的场景中,输出必须是可预测的。OpenAI 在 gpt-35就可以通过response_format={ "type": "json_object" } 来要求模型使用Json Mode(json 模式)返回响应,虽然 JSON 模式仍然受支持,但在可能的情况下,建议使用结构化输出,与 JSON Mode 一样,结构化输出会生成有效的 JSON,但它还有一个额外的好处,即可以约束模型使用特定的 JSON Schema。JSON Schema 确保响应具有良好的结构,遵循特定的格式,并且可以被系统轻松反序列化。在构建依赖特定格式进行进一步处理的应用程序时,这种结构至关重要。

目前大多数模型都已支持Json Schema ,但在实际使用时,可能由于模型不同而表现各异,使用时请注意区分。

目前SK中指定response_format 仍为实验功能,因此需要忽略警告:#pragma warning disable SKEXP0010

1
2
3
4
5
6
7
8
9
10
//通过引入Config/PrepareEnvWithDI.cs文件来快速安装依赖包并导入已抽象的类文件,然后注册并激活AI 服务:

#!import Config/PrepareEnvWithDI.cs

using PolyglotKernel= Microsoft.DotNet.Interactive.Kernel;// 引入交互式的内核命名空间,以便用户输入
// var aiProviderCode = await PolyglotKernel.GetInputAsync("请输入AI服务提供商编码:");
var aiProviderCode = "azure-openai";

var kernel = GetKernel(aiProviderCode);
var chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();

仅要求返回Json 结构响应

1
2
3
4
5
6
7
8
9
10
11
#pragma warning disable SKEXP0010

using Microsoft.SemanticKernel.Connectors.OpenAI;

var executionSettings = new OpenAIPromptExecutionSettings
{
ResponseFormat = "json_object"
};
var result = await kernel.InvokePromptAsync("有史以来最受欢迎五大香港电影?使用Json格式返回",new(executionSettings));
result.Display();
Console.WriteLine(result);

通过查询日志,可以看到实际发送的请求数据包如下:

1
2
3
4
5
6
7
8
9
10
11
12
{
"response_format": {
"type": "json_object"
},
"messages": [
{
"role": "user",
"content": "有史以来最受欢迎五大香港电影?使用Json格式返回"
}
],
"model": "gpt-4o"
}

返回特定Json 结构的响应

在SK 中可以通过OpenAIPromptExecutionSettings.ResponseFormat 来指定期望的Json Schema,而Json Schema 可以有两种方式来定义。接下来就假设我们想让模型告诉我们有史以来最受欢迎的十大香港电影分别说明。

注意:JSON Schema中的一些关键字在 OpenAI 的结构化输出中尚未得到支持。例如,当响应格式类型包含DateTime、DateTimeOffset、DateOnly、TimeSpan、TimeOnly、Uri类型的属性时,JSON Schema将不被接受。临时的解决方法是将这些属性定义为字符串。

通过强类型的类来指定

这种方式是最简便快捷的,即提前定义好类文件,然后让SK 根据对应的类类型自动生成Json Schema,并且使用相同的类型反序列化模型响应并处理其属性。

首先定义好期望的返回模型如下所示:

然后通过指定 OpenAIPromptExecutionSettings.ResponseFormat = typeof(MovieResult) 来指定Json Schema。

查看日志,看下具体的请求数据包:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
{
"response_format": {
"json_schema": {
"name": "MovieResult",
"strict": true,
"schema": {
"type": "object",
"properties": {
"Movies": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"properties": {
"Title": {
"type": [
"string",
"null"
]
},
"Director": {
"type": [
"string",
"null"
]
},
"ReleaseYear": {
"type": "integer"
},
"Rating": {
"type": "number"
},
"IsAvailableOnStreaming": {
"type": "boolean"
},
"Tags": {
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
}
},
"additionalProperties": false,
"required": [
"Title",
"Director",
"ReleaseYear",
"Rating",
"IsAvailableOnStreaming",
"Tags"
]
}
}
},
"additionalProperties": false,
"required": [
"Movies"
]
}
},
"type": "json_schema"
},
"messages": [
{
"role": "user",
"content": "有史以来最受欢迎的五大香港电影?"
}
],
"model": "gpt-4o"
}

通过字符串来指定

除了通过强类型的类进行Json Schema的定义外,SK 也支持直接通过字符串进行指定,这种方法很灵活,因为它允许在字符串中指定每个属性及其类型,这意味着 JSON Schema可以存储在单独的文件中,以提高可重用性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
using OpenAI.Chat;

ChatResponseFormat chatResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat(
jsonSchemaFormatName: "movie_result",
jsonSchema: BinaryData.FromString("""
{
"type": "object",
"properties": {
"Movies": {
"type": "array",
"items": {
"type": "object",
"properties": {
"Title": { "type": "string" },
"Director": { "type": "string" },
"ReleaseYear": { "type": "integer" },
"Rating": { "type": "number" },
"IsAvailableOnStreaming": { "type": "boolean" },
"Tags": { "type": "array", "items": { "type": "string" } }
},
"required": ["Title", "Director", "ReleaseYear", "Rating", "IsAvailableOnStreaming", "Tags"],
"additionalProperties": false
}
}
},
"required": ["Movies"],
"additionalProperties": false
}
"""),
jsonSchemaIsStrict : true);

具体的请求数据包如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
{
"response_format": {
"json_schema": {
"name": "movie_result",
"strict": true,
"schema": {
"type": "object",
"properties": {
"Movies": {
"type": "array",
"items": {
"type": "object",
"properties": {
"Title": {
"type": "string"
},
"Director": {
"type": "string"
},
"ReleaseYear": {
"type": "integer"
},
"Rating": {
"type": "number"
},
"IsAvailableOnStreaming": {
"type": "boolean"
},
"Tags": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"Title",
"Director",
"ReleaseYear",
"Rating",
"IsAvailableOnStreaming",
"Tags"
],
"additionalProperties": false
}
}
},
"required": [
"Movies"
],
"additionalProperties": false
}
},
"type": "json_schema"
},
"messages": [
{
"role": "user",
"content": "有史以来最受欢迎的五大香港电影?"
}
],
"model": "gpt-4o"
}
作者

步步为营

发布于

2025-04-11

更新于

2025-04-11

许可协议