使用CompleteChatStreamingAsync流式响应时AzureChatCitation无法获取
流式模式下获取Azure OpenAI on your data的引用(Citations)
在流式响应场景中,Azure OpenAI的引用信息不会随每个文本片段返回,而是会在最后一个流式更新包中携带。你的代码问题在于过早跳过了可能包含上下文的片段,且没有正确捕获最终的上下文数据。
关键修复点
- 移除
if (chatUpdate.Role.HasValue) continue;的判断:这个判断会跳过包含Assistant角色的最终响应片段,而引用信息正是在这个片段里。 - 在遍历所有流式更新时持续捕获非null的上下文,确保最终拿到包含引用的完整数据。
修改后的代码
AzureOpenAIClient azureClient = new( new Uri(_endpoint), new AzureKeyCredential(_apiKey)); ChatClient chatClient = azureClient.GetChatClient(_deploymentName); ChatCompletionOptions options = new() { Temperature = (float)temperature, MaxTokens = maxTokens, FrequencyPenalty = (float)frequencyPenalty, PresencePenalty = (float)presencePenalty }; options.AddDataSource(new AzureSearchChatDataSource() { Endpoint = new Uri(_searchEndpoint), IndexName = _searchIndex, Authentication = DataSourceAuthentication.FromApiKey(_searchKey), VectorizationSource = Azure.AI.OpenAI.Chat.DataSourceVectorizer.FromDeploymentName("text-embedding-ada-002") }); var chatUpdates = chatClient.CompleteChatStreamingAsync( [ new UserChatMessage(fullInput), ], options); AzureChatMessageContext onYourDataContext = null; var streamedContentParts = new List<string>(); await foreach (var chatUpdate in chatUpdates) { // 处理流式文本内容,返回给前端 foreach (var contentPart in chatUpdate.ContentUpdate) { var jsonResponse = JsonSerializer.Serialize(new { Text = contentPart.Text }); streamedContentParts.Add(contentPart.Text); yield return jsonResponse; } // 捕获当前更新的上下文,仅保留非null结果 var currentContext = chatUpdate.GetAzureMessageContext(); if (currentContext != null) { onYourDataContext = currentContext; } } // 输出并处理引用信息 if (onYourDataContext?.Citations != null) { foreach (AzureChatCitation citation in onYourDataContext.Citations) { Console.Write($"Citation: {citation.Content}"); // 此处可将引用的文档链接、标题等信息返回给前端 } }
说明
- 流式响应的结构中,前几个包仅包含文本片段(ContentUpdate),最后一个包会携带完整的角色标识(Role=Assistant)以及对应的上下文数据(含Citations)。
- 移除Role判断的跳过逻辑后,才能捕获到包含引用信息的最终更新包。
- 遍历过程中持续更新上下文变量,确保最终拿到的是完整的引用数据。
内容的提问来源于stack exchange,提问作者satyayy_
相关产品推荐
相关产品推荐

