惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Tor Project blog
T
The Blog of Author Tim Ferriss
WordPress大学
WordPress大学
H
Help Net Security
酷 壳 – CoolShell
酷 壳 – CoolShell
宝玉的分享
宝玉的分享
博客园 - 司徒正美
Jina AI
Jina AI
雷峰网
雷峰网
博客园_首页
博客园 - 三生石上(FineUI控件)
G
Google Developers Blog
MongoDB | Blog
MongoDB | Blog
Hugging Face - Blog
Hugging Face - Blog
The Cloudflare Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Forbes - Security
Forbes - Security
T
Threatpost
V
Visual Studio Blog
A
Arctic Wolf
Microsoft Azure Blog
Microsoft Azure Blog
Security Latest
Security Latest
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
P
Privacy & Cybersecurity Law Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Spread Privacy
Spread Privacy
N
News and Events Feed by Topic
Vercel News
Vercel News
爱范儿
爱范儿
The GitHub Blog
The GitHub Blog
NISL@THU
NISL@THU
Hacker News - Newest:
Hacker News - Newest: "LLM"
T
The Exploit Database - CXSecurity.com
P
Proofpoint News Feed
PCI Perspectives
PCI Perspectives
博客园 - 【当耐特】
IT之家
IT之家
S
Secure Thoughts
Engineering at Meta
Engineering at Meta
阮一峰的网络日志
阮一峰的网络日志
Cisco Talos Blog
Cisco Talos Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
月光博客
月光博客
Latest news
Latest news
小众软件
小众软件
Attack and Defense Labs
Attack and Defense Labs
I
Intezer
Y
Y Combinator Blog
The Last Watchdog
The Last Watchdog
大猫的无限游戏
大猫的无限游戏

博客园 - 「圣杰」

.NET+AI | Harness | MAF 1.4 发布,Harness Engineering 如约而至,智能体工程化更进一步 Microsoft Agent Framework 1.0 正式发布:Agent Skills 补齐后,.NET AI Agent 开发真正进入工程化时代 .NET+AI | Workflow | 核心概念速通(1) .NET+AI | 基于 Microsoft Agent Framework 一步步集成 Agent Skills,让你的 AI Agent 更智能 未来已来 | 写给 .NET 开发者的 2025 年度总结 从 MCP 到 Agent Skills,AI Ready 的 .NET 10 正当时 .NET+AI | Agent | 人机协作(9) .NET+AI | MEAI | 自定义中间件(8) .NET+AI | MEAI | 会话缓存(6) .NET+AI | MEAI | ChatOptions 详解(5) AI 时代,.NET 开发者是向左还是向右? .NET+AI | MEAI | Function Caling 实操(4) .NET+AI | MEAI | Function Calling 基础(3) .NET+AI | MEAI | 提示工程基础(2) .NET+AI | MEAI | .NET 平台的 AI 底座 (1) .NET 搞 AI 不行? ​微软 AI Agent三剑客:AutoGen、Semantic Kernel与MEAI的协同演进 .NET+AI | eShopSupport 知多少 .NET + AI | Semantic Kernel vs Microsoft.Extensions.AI 极客时间上新 .NET + AI 体系课
.NET+AI | MEAI | 上下文压缩(7)
「圣杰」 · 2025-11-29 · via 博客园 - 「圣杰」

Chat Reducer:让 AI 对话突破上下文限制

一句话简介

Microsoft.Extensions.AI 的 Chat Reducer 通过智能压缩策略,在保持对话质量的前提下,有效控制上下文长度、降低成本并提升性能。


🎯 核心价值

  • 突破限制:解决 LLM 上下文窗口限制(如 GPT-4 的 8K/32K tokens)
  • 成本优化:减少输入 token,显著降低 API 调用成本
  • 性能提升:缩短上下文长度,加快模型推理速度
  • 智能压缩:保留关键信息,自动过滤冗余历史消息

📝 为什么需要 Chat Reducer?

在多轮对话场景中,我们面临三大挑战:

挑战 问题 Chat Reducer 方案
上下文限制 超出模型限制导致请求失败 智能压缩到安全范围
成本失控 输入 token 越多费用越高 过滤冗余,只保留必要信息
性能下降 过长上下文增加推理时间 减少处理负担,提升响应速度

典型场景:

  • 💬 长时间客服对话(用户反复咨询)
  • 🏥 医疗咨询(需要完整病史)
  • ⚖️ 法律咨询(案情细节不能丢失)
  • 🎓 教育辅导(需要追踪学习进度)

🏗️ 两种压缩策略

1. MessageCountingChatReducer(计数压缩器)

通过限制消息数量来控制对话长度。

核心特性:

  • 🔧 始终保留第一条系统消息
  • 🔧 保留最近 N 条用户/助手消息
  • 🔧 自动排除函数调用相关消息
  • 🔧 零延迟,无额外 API 成本

适用场景:

  • 客服机器人(只关注最近几轮)
  • 快速问答系统
  • 技术支持(问题独立,不需长期上下文)

2. SummarizingChatReducer(摘要压缩器)

利用 AI 自动生成摘要压缩历史对话。

核心特性:

  • 🔧 超过阈值时自动调用 AI 生成摘要
  • 🔧 摘要存储在 AdditionalProperties
  • 🔧 渐进式压缩(新摘要包含旧摘要)
  • 🔧 保留完整语义上下文

适用场景:

  • 医疗咨询(完整病史重要)
  • 法律咨询(案情细节关键)
  • 教育辅导(长期进度追踪)

💻 快速开始

1. 使用计数压缩器

using Microsoft.Extensions.AI;

// 创建压缩器,保留最近 3 条消息
var countingReducer = new MessageCountingChatReducer(targetCount: 3);

// 集成到 Chat Client
var client = baseChatClient.AsBuilder()
    .UseChatReducer(reducer: countingReducer)
    .Build();

// 正常使用,自动压缩
var response = await client.GetResponseAsync(messages);

工作原理:

原始消息(13条)              压缩后(4条)
[System] 你是助手           [System] 你是助手
[User] 问题1                
[Assistant] 回答1           
[User] 问题2               
[Assistant] 回答2           
...                        [User] 问题5
[User] 问题5                [Assistant] 回答5
[Assistant] 回答5           [User] 问题6
[User] 问题6

2. 使用摘要压缩器

// 创建摘要压缩器
// targetCount: 保留最近 2 条消息
// threshold: 超过 targetCount + threshold 时触发摘要
var summarizingReducer = new SummarizingChatReducer(
    chatClient: baseChatClient,
    targetCount: 2,
    threshold: 1  // 超过 3 条时触发
);

// 集成到 Chat Client
var client = baseChatClient.AsBuilder()
    .UseChatReducer(reducer: summarizingReducer)
    .Build();

工作原理:

原始消息(7条)                    压缩后(4条)
[System] 你是医疗助手            [System] 你是医疗助手
[User] 我头痛                    [Summary] 患者主诉头痛,
[Assistant] 可能是压力...                  睡眠不足,已建议休息
[User] 我睡眠不足                [User] 我眼睛干涩
[Assistant] 建议保证睡眠          [Assistant] 使用人工泪液...
[User] 我眼睛干涩
[Assistant] 使用人工泪液...

🔧 高级配置

1. 自定义摘要提示词

var reducer = new SummarizingChatReducer(baseChatClient, targetCount: 2);

// 设置领域专用摘要提示词
reducer.SummarizationPrompt = """
请为以下医疗咨询对话生成简洁的临床摘要(不超过3句话):

要求:
- 提取患者主诉症状和时长
- 记录已提供的初步建议
- 保留关键医学信息
- 使用专业医学术语

格式: 【患者主诉】症状 | 【已知信息】背景 | 【初步建议】建议
""";

2. 参数调优建议

MessageCountingChatReducer:

策略 参数配置 适用场景
保守策略 targetCount: 10 上下文敏感场景
均衡策略 targetCount: 5 一般对话
激进策略 targetCount: 2 成本优先

SummarizingChatReducer:

策略 参数配置 效果
频繁摘要 threshold: 0 每次超过立即摘要
延迟摘要 threshold: 3 减少 API 调用

3. 与其他中间件组合

var client = baseChatClient.AsBuilder()
    .UseChatReducer(reducer: summarizingReducer)  // 先压缩
    .UseFunctionInvocation()                       // 再处理函数
    .Build();

⚠️ 注意: Reducer 应放在管道前端,确保在调用 API 前完成压缩。


🏢 选择策略指南

场景对比表

场景 推荐 Reducer 原因
客服机器人 MessageCounting 只需最近几轮,历史价值低
技术支持 MessageCounting 问题独立,不需长期上下文
医疗咨询 Summarizing 需完整病史,摘要保证连续性
法律咨询 Summarizing 案情细节重要,不能丢失
教育辅导 Summarizing 学习进度需长期追踪
快速问答 MessageCounting 对话简短,不需复杂摘要

性能与成本对比

对比项 MessageCounting Summarizing
额外 API 调用 ✅ 无 ❌ 每次摘要 1 次
延迟 ✅ 0ms ⚠️ 1-3 秒
语义完整性 ⚠️ 可能丢失 ✅ 保留
成本 ✅ 低 ⚠️ 中等
适用场景 短期对话 长期对话

💡 优化技巧: 使用较小模型(如 GPT-3.5)专门用于摘要生成,降低成本。


💡 最佳实践

1. 函数调用消息自动保护

两种 Reducer 都会自动排除函数调用相关消息,避免破坏上下文:

// 这些消息会被自动跳过,不计入 targetCount
- FunctionCallContent
- FunctionResultContent

2. 多用户场景

为每个用户会话创建独立消息列表,共享 Reducer 实例:

// 全局共享的 Reducer(无状态)
var sharedReducer = new MessageCountingChatReducer(5);

// 每个用户独立的消息历史
var user1Messages = new List<ChatMessage>();
var user2Messages = new List<ChatMessage>();

3. 自定义 Reducer

实现 IChatReducer 接口创建自定义压缩逻辑:

public class CustomReducer : IChatReducer
{
    public Task<IEnumerable<ChatMessage>> ReduceAsync(
        IEnumerable<ChatMessage> messages, 
        CancellationToken cancellationToken)
    {
        // 自定义压缩逻辑
        var reduced = messages
            .Where(m => /* 自定义条件 */)
            .TakeLast(5);
        
        return Task.FromResult(reduced);
    }
}

⚠️ 注意事项

1. 原始消息不会被修改

ReduceAsync() 返回新列表,原始列表保持不变。如需审计,可在本地保留完整历史:

var allMessages = new List<ChatMessage>();      // 完整历史
var reducedMessages = await reducer.ReduceAsync(allMessages);
// allMessages 仍包含所有消息

2. 摘要压缩的信息损失

摘要依赖 LLM 理解能力,可能会:

  • ✅ 保留主要事实和语义
  • ⚠️ 丢失细微情感、口语化表达
  • ⚠️ 潜在的理解偏差

建议: 关键信息(订单号、金额)结合数据库存储,不完全依赖摘要。


3. 流式响应支持

Reducer 完全支持流式场景,在开始传输前自动完成压缩:

await foreach (var update in client.GetStreamingResponseAsync(messages))
{
    Console.Write(update.Text);
}

🎯 总结

  • 两种策略: MessageCounting(快速简单) vs Summarizing(语义完整)
  • 一行集成: 通过 UseChatReducer() 轻松启用
  • 灵活配置: 支持自定义提示词、参数调优、自定义实现
  • 生产就绪: 自动处理函数调用、支持流式、多用户安全

选择建议:

  • 💬 短期对话、成本敏感 → MessageCountingChatReducer
  • 🏥 长期咨询、语义重要 → SummarizingChatReducer