尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

WPF + Semantic Kernel 实现流式输出

WPF + Semantic Kernel 实现流式输出
📅 发布时间:2026/7/4 20:18:06

打字机效果完整代码

一、什么是流式输出

普通AI调用:
等待 → 等待 → 等待 → 一次性返回全部结果

流式输出:
开始返回 → 逐字/逐词输出 → 像打字机一样

用户体验差距非常明显。
这也是为什么 ChatGPT 用打字机效果,
而不是等全部生成完再显示。


二、Semantic Kernel 流式输出 API

核心方法是:

GetStreamingChatMessageContentsAsync

和普通调用的对比:

// 普通调用(一次性返回)
var result = await chatService
.GetChatMessageContentAsync(history);
string content = result.Content;

// 流式调用(逐块返回)
await foreach (var chunk in chatService
.GetStreamingChatMessageContentsAsync(history))
{
string piece = chunk.Content; // 每次一小块
}


三、在服务层封装流式方法

使用 IAsyncEnumerable 作为返回类型,
配合 yield return 逐块返回内容:

using System.Runtime.CompilerServices;

public async IAsyncEnumerable SummarizeStreamAsync(
string content,
[EnumeratorCancellation] CancellationToken ct = default)
{
var history = new ChatHistory();
history.AddUserMessage($“请总结以下内容:\n{content}”);

await foreach (var chunk in _chatService! .GetStreamingChatMessageContentsAsync( history, cancellationToken: ct)) { if (!string.IsNullOrEmpty(chunk.Content)) yield return chunk.Content; }

}

注意事项:

  1. 必须加 [EnumeratorCancellation] 特性
    才能正确处理取消操作
  2. 过滤空 chunk,避免UI无意义刷新
  3. CancellationToken 要透传,
    支持用户取消

四、在 WPF 里实时更新 UI

关键点:
流式输出在后台线程产生数据,
需要用 Progress 或者直接更新
绑定属性来刷新UI。

因为 ObservableCollection 和
INotifyPropertyChanged 的绑定属性
在 WPF 里可以跨线程更新
(只要是通过属性setter更新的):

// 在处理循环里
var sb = new StringBuilder();

await foreach (var chunk in
_aiService.SummarizeStreamAsync(content, ct))
{
sb.Append(chunk);

// 直接更新绑定属性,WPF自动刷新UI item.Result = sb.ToString();

}

item.Status = ProcessStatus.Completed;


五、完整测试代码(控制台版)

先用控制台验证流式输出效果:

using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;

var builder = Kernel.CreateBuilder();
builder.AddOpenAIChatCompletion(
modelId: “deepseek-ai/DeepSeek-V3”,
apiKey: “你的硅基流动Key”,
endpoint: new Uri(“https://api.siliconflow.cn/v1”)
);

var kernel = builder.Build();
var chatService =
kernel.GetRequiredService();

var history = new ChatHistory();
history.AddUserMessage(“用200字介绍一下人工智能的发展历史”);

Console.WriteLine(“流式输出开始:”);

await foreach (var chunk in chatService
.GetStreamingChatMessageContentsAsync(history))
{
if (!string.IsNullOrEmpty(chunk.Content))
Console.Write(chunk.Content); // 不换行,逐字追加
}

Console.WriteLine(“\n完成”);


六、踩过的坑

坑1:忘记加 [EnumeratorCancellation]

IAsyncEnumerable 方法里如果有
CancellationToken 参数,
必须加 [EnumeratorCancellation] 特性,
否则取消操作不会正确传递。

// ❌ 错误
public async IAsyncEnumerable StreamAsync(
CancellationToken ct = default)

// ✅ 正确
public async IAsyncEnumerable StreamAsync(
[EnumeratorCancellation] CancellationToken ct = default)

坑2:chunk.Content 可能为 null 或空

流式返回的每个 chunk
Content 属性可能是 null 或空字符串,
必须过滤:

// ❌ 不过滤,可能空字符串刷新UI
yield return chunk.Content;

// ✅ 过滤空值
if (!string.IsNullOrEmpty(chunk.Content))
yield return chunk.Content;

坑3:StringBuilder 要在循环外声明

// ❌ 每次chunk都新建,结果只有最后一块
await foreach (var chunk in …)
{
var sb = new StringBuilder(); // 错误位置
sb.Append(chunk.Content);
item.Result = sb.ToString();
}

// ✅ 循环外声明,累积所有内容
var sb = new StringBuilder(); // 正确位置
await foreach (var chunk in …)
{
sb.Append(chunk.Content);
item.Result = sb.ToString();
}


七、效果对比

普通调用:
处理10秒钟 → 结果突然全部出现
用户:不知道有没有在运行,很焦虑

流式输出:
开始后立刻看到文字蹦出来
用户:直观感受到AI在工作,体验好很多


八、完整项目

这是我做的「文省事」AI文档批量处理工具
里用到的核心技术。

工具功能:
批量生成文档摘要
批量提取关键信息
支持PDF/Word/TXT
结果导出Excel

感兴趣的可以咸鱼搜索「文省事」。

如果本文对你有帮助,点个赞🙏
后续持续更新C# + AI实战内容。

相关新闻

  • 无人机植被绿化巡检数据集与YOLOv8分割模型实战
  • 【下一代智慧养老:架构与实战连载】全书目录
  • PCF8591与PIC18F45K50的ADC/DAC信号处理实战

最新新闻

  • go-stock快速上手:AI赋能的本地化股票分析平台完整指南
  • Cosmos-Transfer1-DiffusionRenderer API参考:核心模块与函数详细文档
  • 为什么选择Genome?探索Swift中失败驱动映射的完整解决方案
  • 10个实用p5示例教程:让你的Python代码动起来
  • 5个核心技巧:使用BeeRef高效管理视觉参考素材的完整指南
  • 火山引擎Coding Plan抢购难?开发者API调用成本控制与多模型切换实战指南

日新闻

  • STM32F745VG与MC6470 IMU的高性能姿态控制系统设计
  • 机器不消费,人何以生存
  • AI项目操作手册编写规范与最佳实践

周新闻

  • Windows字体自定义终极方案:No!! MeiryoUI完全指南
  • Deepin Boot Maker:告别命令行,3分钟制作Linux启动盘的智能解决方案
  • Plain Craft Launcher 2:重新定义你的Minecraft游戏体验

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号