无法使用c#反序列化http请求的响应

问题描述 投票:0回答:1

我当前正在调用 HTTP 服务并获取返回的数据。该查询是调用 Azure Open AI 的聊天完成 API 的结果。

供参考

[webappurl]/openai/deployments/gpt35turbo/extensions/chat/completions?api-version=2023-06-01-preview

我使用 HTTP 客户端方法的原因是我连接到我自己的数据源而不是所有数据源。 Azure.AI.OpenAI(0.7 Beta)的当前实现似乎还没有数据源的属性,尽管预览文档中提到了这一点。

我从 HTTP 请求返回的一些响应粘贴在下面(使用 Fiddler 获得),其格式如下。

data: {
    "id": "**removed**",
    "model": "gpt-35-turbo",
    "created": 1694376472,
    "object": "chat.completion.chunk",
    "choices": [
        {
            "index": 0,
            "messages": [
                {
                    "delta": {
                        "role": "tool",
                        "content": "{\"citations\": [{\"content\": \"** removed ** "
                    },
                    "index": 0,
                    "end_turn": false
                }
            ],
            "finish_reason": null
        }
    ]
}

data: {
    "id": "**removed**",
    "model": "gpt-35-turbo",
    "created": 1694376472,
    "object": "chat.completion.chunk",
    "choices": [
        {
            "index": 0,
            "messages": [
                {
                    "delta": {
                        "role": "assistant"
                    },
                    "index": 1,
                    "end_turn": false
                }
            ],
            "finish_reason": null
        }
    ]
}

data: {
    "id": "**removed**",
    "model": "gpt-35-turbo",
    "created": 1694376472,
    "object": "chat.completion.chunk",
    "choices": [
        {
            "index": 0,
            "messages": [
                {
                    "delta": {
                        "content": ""
                    },
                    "index": 1,
                    "end_turn": false
                }
            ],
            "finish_reason": null
        }
    ]
}

然后我有以下代码来发出请求并处理响应。

HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, client.BaseAddress);

var content = new StringContent(body, Encoding.UTF8, "application/json");
request.Content = content;

var response = await client.SendAsync(request).ConfigureAwait(false);
response.EnsureSuccessStatusCode();

string responseBody = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

CompletionResponse completionResponse = new CompletionResponse();
completionResponse = JsonSerializer.Deserialize<CompletionResponse>(responseBody);

我的模型的类文件包含以下内容

public class CompletionResponse
{
    [JsonPropertyName("choices")]
    public List<ChatGPTChoice>? Choices
    {
        get;
        set;
    }

    [JsonPropertyName("usage")]
    public ChatGPTUsage? Usage
    {
        get;
        set;
    }
}

public class ChatGPTUsage
{
    [JsonPropertyName("prompt_tokens")]
    public int PromptTokens
    {
        get;
        set;
    }

    [JsonPropertyName("completion_token")]
    public int CompletionTokens
    {
        get;
        set;
    }

    [JsonPropertyName("total_tokens")]
    public int TotalTokens
    {
        get;
        set;
    }
}

[DebuggerDisplay("Text = {Text}")]
public class ChatGPTChoice
{
    [JsonPropertyName("text")]
    public string? Text
    {
        get;
        set;
    }
}

当我运行应用程序时,我到达上面的最后一行并得到:

System.Text.Json.JsonException:“d”是值的无效开头。路径: $ |行号: 0 |内联字节位置:0。 ---> System.Text.Json.JsonReaderException:“d”是值的无效开头。行号: 0 |字节位置内联:0.

如果我获取响应并将其粘贴到 JSON 文档中,我会得到以下 Expected a JSON object, array orliteral.json。在我看来,响应不包含 JSON,但我不明白它给了我什么(我不是专家)。

这可能是一个愚蠢的错误,但任何指示都非常感激。

我参考了这个视频 https://www.youtube.com/watch?v=Bfls6P7IaDE

c# botframework azure-openai openaiembeddings
1个回答
0
投票

JSON 语法要求所有属性名称都用引号引起来。响应以

data:
开头,这不是有效的 JSON。之后的所有内容(从第一个
{
开始)似乎都是有效的 JSON,应与您的 DTO 匹配。

简单的解决方案是跳过初始标签并反序列化其余标签:

if (responseBody.StartsWith("data:"))
    responseBody = responseBody[5..].TrimStart();

接下来,您的 DTO 与示例中的实际 JSON 格式不匹配。您需要修复

ChatGPTChoice
类以更好地反映结构,每个类对应于
messages
数组项和每条消息的
delta
记录。你现在所拥有的永远无法捕捉到细节。

© www.soinside.com 2019 - 2024. All rights reserved.