2025-11-29 23:10:13
摘要:一、自定义工作流事件
1. 为什么需要自定义事件?
场景
内置事件
自定义事件
粒度
Executor 级别
业务逻辑级别
语义
系统通用 (调用、完成)
业务特定 (审核通过、风险预警)
数据
执行元数据
业务数据 (敏感词、风险分数)
监控
技术监控
业务监控 + 审计
前端
通用进度条
具体业务状态展示
2. 自定义事件类定义
基本定义模式:自定义事件本质上就是继承 WorkflowEvent 的普通 C# 类。让我们从最简单的开始:
/// summary
/// 表示检测到敏感词的事件
/// /summary
public class SensitiveWordDetectedEvent : WorkflowEvent
{
public SensitiveWordDetectedEvent(string word, int position) : base(data: null) // 可以传递简单数据到 base
{
Word = word;
Position = position;
}
public string Word { get; }
public int Position { get; }
}
设计原则
DO (推荐做法):
类名以 Event 结尾,语义清晰
使用只读属性 ({ get; }),确保事件不可变
添加 XML 注释说明事件的业务含义
属性类型尽量简单(string, int, DateTime 等可序列化类型)
DON'T (避免做法):
不要在事件类中包含方法逻辑
不要引用不可序列化的对象(如 DbContext, HttpClient)
不要使用可变属性({ get; set; })
不要在构造函数中执行耗时操作
3. 携带复杂数据的事件
当需要传递更复杂的业务数据时,有两种设计模式:
模式 1: 使用属性传递结构化数据
/// summary
/// 风险评估完成事件
/// /summary
public class RiskAssessmentCompletedEvent : WorkflowEvent
{
public RiskAssessmentCom……
阅读全文
2025-11-22 10:34:18
摘要:一、工作流基础
1. 什么是 Workflow Orchestration
在企业级 AI 应用开发中,我们经常面临以下挑战:
单个 Agent 难以处理复杂任务:一个 Agent 无法同时擅长需求分析、代码生成、测试等多个领域
业务逻辑与 AI 调用耦合:复杂的条件判断、循环、并发控制分散在代码各处
流程难以可视化和维护:多步骤的 AI 处理流程缺乏清晰的结构
缺乏统一的状态管理:多个步骤之间的数据传递和状态共享容易出错
Workflow Orchestration (工作流编排) 正是为了解决这些问题而生:
模块化设计:将复杂任务拆分为独立的 Executor 和 Agent
清晰的流程定义:使用 Builder API 构建可读、可维护的流程图
灵活的流程控制:支持条件分支、循环迭代、并发执行等复杂模式
统一的状态管理:内置 WorkflowContext 管理跨步骤的状态和数据
实时流式反馈:通过事件机制实时监控工作流的执行进度
MAF Workflow 位于应用层和 Agent 层之间,负责:
编排多个 Agent:决定 Agent 的执行顺序、条件和并发策略
管理数据流:在 Agent 和 Executor 之间传递数据
监控执行状态:实时报告工作流的执行进度和结果
错误处理:统一处理执行过程中的异常和重试逻辑
2. Workflow 的核心构建块
Workflow 由以下三个核心概念组成:
Executor (执行器) - 处理单元:Executor 是工作流的基本处理单元,负责执行具体的业务逻辑。
特点:
强类型输入:TInput 定义接收的数据类型
强类型输出:TOutput 定义返回的数据类型
纯逻辑处理:可以是数据转换、验证、格式化等任何操作
Agent 也是 Executor:AIAgent 可以直接作为 Executor 使用
示例用途:
文本转换 (大写、反转、清理)
数据验证 (格式检查、安全过滤)
结果聚合 (合并多个输出)
AI 调用 (通过 Agent)
public abstract class ExecutorTInput, TOutput : Executor
{
public abstract ValueTaskTOutput HandleAsync(
TInput i……
阅读全文
2025-11-15 18:12:48
摘要:一、自定义 Agent 的实现
1. 场景分析
在大多数场景下,使用 chatClient.CreateAIAgent() 创建的标准 Agent 已经足够强大。但在某些特殊场景下,自定义 Agent 实现能带来更大的价值:
场景 1:规则引擎替代 AI(成本优化)
问题:客服系统每天处理数万次重复性问题(营业时间?,退货流程?),每次调用 AI 模型都会产生成本。
解决方案:自定义 Agent 使用 FAQ 知识库进行关键词匹配,只在无法匹配时才调用 AI。
收益:
成本降低 70-90%(高频简单问题零成本)
响应速度提升 10 倍(无需等待 AI 推理)
答案一致性更高(预定义标准答案)
场景 2:遗留系统集成(ERP/CRM/工作流引擎)
问题:企业内部有成熟的审批工作流引擎,需要将其包装为 Agent 供统一调度。
解决方案:自定义 Agent 作为适配器,将工作流引擎的 API 转换为 Agent 接口。
收益:
无缝集成现有系统(无需重构)
复用企业级规则引擎(审批、权限、流程)
数据安全可控(不发送敏感数据到外部 AI)
场景 3:测试模拟(Mock Agent)
问题:开发和测试环境中,不希望调用真实 AI 模型(成本、稳定性、可预测性)。
解决方案:自定义 Agent 返回固定或可配置的测试数据。
收益:
单元测试更可靠(确定性输出)
开发环境零成本
CI/CD 管道更快(无需等待 AI 响应)
场景 4:混合模式(规则 + AI)
问题:希望结合规则引擎的确定性和 AI 的灵活性。
解决方案:自定义 Agent 先尝试规则匹配,失败后转发给 AI Agent。
收益:
平衡成本与效果
灵活的分流策略(按优先级、置信度)
逐步优化规则库(分析 AI 处理的高频问题)
对比: 标准 Agent vs 自定义 Agent
特性
ChatClientAgent(标准)
自定义 Agent
说明
创建方式
chatClient.CreateAIAgent()
继承 AIAgent 抽象类
标准方式更简单
开发复杂度
低
高
自定义需实现所有核心方法
灵活性
受限于 IChatClient 能力
完全可控
自定义可实现任意逻辑
成本
按 Token 计费……
阅读全文
2025-11-08 18:03:58
摘要:一、自定义文件消息存储
1. ChatMessageStore 架构概览
classDiagram
class ChatMessageStore {
abstract>>
#IChatReducer? ChatReducer
+AddMessagesAsync(messages)
+GetMessagesAsync()
+ClearAsync()
+Serialize()
+Deserialize(state)
}
class InMemoryChatMessageStore {
-List~ChatMessage~ _messages
+AddMessagesAsync()
+GetMessagesAsync()
+ClearAsync()
}
class FileChatMessageStore {
-string _filePath
-SemaphoreSlim _lock
+AddMessagesAsync()
+GetMessagesAsync()
+ClearAsync()
}
class RedisChatMessageStore {
-IConnectionMultiplexer _redis
+AddMessagesAsync()
+GetMessagesAsync()
+ClearAsync()
}
ChatMessageStore |-- InMemoryChatMessageStore
ChatMessageStore |-- FileChatMessageStore
ChatMessageStore |-- RedisChatMessageStore
ChatMessageStore 抽象类核心方法职责
方法
职责
使用场景
AddMessagesAsync
添加新消……
阅读全文
2025-11-01 19:31:17
摘要:一、第一个智能体
1. 什么是 MAF
Microsoft Agent Framework (MAF) 是微软推出的企业级 AI Agent 开发框架,构建在 Microsoft.Extensions.AI (MEAI) 之上,提供了构建生产级 AI Agent 所需的完整能力。
Agent vs ChatClient - 什么时候用 Agent?
特性
IChatClient
AIAgent
定位
底层 AI 调用抽象
高级智能体封装
状态管理
无状态,每次调用独立
内置对话线程 (AgentThread)
身份定义
需要手动在每次调用中传入 System Message
固定的 Instructions 和 Name
工具管理
需要手动配置 ChatOptions.Tools
Agent 级别统一管理工具
使用场景
构建自定义 AI 功能,单次对话场景
企业级对话系统,多轮交互场景
简单来说:
ChatClient 就像一个纯函数:给定输入,返回输出,不保留状态
Agent 就像一个有记忆的助手: 有固定身份、能记住上下文、能使用工具
2. MAF 的核心概念
MAF 围绕以下核心概念构建:
AIAgent - 智能代理:Agent 是具有特定身份和能力的智能实体,包含:
Name (名称):Agent 的唯一标识
Instructions (指令):Agent 的系统提示词,定义其行为和角色
Tools (工具):Agent 可以调用的函数工具集合
AgentThread - 对话线程:每个 Agent 可以有多个对话线程,每个线程维护独立的对话历史:
自动管理消息历史
支持序列化/反序列化 (持久化)
线程隔离,互不干扰
AgentRun - 执行实例:每次调用 Agent 都会创建一个 Run:
同步调用:RunAsync() → 返回完整响应
流式调用:RunStreamingAsync() → 返回增量更新流
3. 快速开始
让我们通过创建一个口语教练 Agent 来快速入门 MAF。
// 步骤 1: 获取底层获取 ChatClient
var chatClient = ChatClientFactory.GetQwenClient();
// 步骤 2: 创建口语教……
阅读全文
2025-10-25 11:20:48
摘要:一、自定义传输协议
我们已经知道 MCP 的 Stdio 和 HTTP 传输协议了,今天我们深入探索一下 InMemory Transport(进程内传输)的实现原理,以及如何创建自定义传输协议。InMemory Transport 特别适合单进程内的 MCP 通信、单元测试和高性能场景。
1. InMemory Transport 原理
InMemory Transport 是一种在单进程内实现 MCP Client 和 Server 通信的传输方式。它使用内存中的数据结构(如 Pipe、Channel)进行消息传递,避免了跨进程通信的开销。
主要优势:
高性能:无需序列化到文件或网络,直接在内存中传递消息
易于测试:非常适合编写单元测试,不依赖外部进程或网络
同步控制:Client 和 Server 在同一进程,便于调试和状态管理
零依赖:不需要启动外部进程或监听端口
实现原理:InMemory Transport 基于 Pipe(管道)实现双向通信:
创建两个 Pipe:
clientToServerPipe:Client → Server 方向
serverToClientPipe:Server → Client 方向
连接读写端:
Client 写入 clientToServerPipe.Writer,Server 读取 clientToServerPipe.Reader
Server 写入 serverToClientPipe.Writer,Client 读取 serverToClientPipe.Reader
消息序列化:
使用 JSON-RPC 格式序列化消息
每条消息以换行符 \n 分隔
sequenceDiagram
participant C as McpClient
participant CTP as clientToServerPipe
participant STP as serverToClientPipe
participant S as McpServer
Note over C,S: 初始化连接
C->>CTP: Write (Request)
CTP->>S: Read (Request)
S->>STP: Wr……
阅读全文
2025-10-18 12:28:24
摘要:一、MCP 协议基础
1. 协议概述
MCP 是一个基于 JSON-RPC 2.0 的应用层协议,专为 AI 应用程序设计。它定义了:
标准化消息格式:统一的请求/响应/通知结构
能力协商机制:Client 和 Server 协商支持的功能
双向通信:支持请求-响应和异步通知
错误处理:标准化的错误代码和异常处理
MCP 协议栈
MCP 协议建立在 JSON-RPC 2.0 之上,提供了额外的语义和约定:
┌─────────────────────────────────────────┐
│ AI Application Layer │ ← 使用 MCP 的应用
├─────────────────────────────────────────┤
│ MCP Protocol Layer (Application) │ ← MCP 协议语义
│ (Tools, Resources, Prompts, etc.) │
├─────────────────────────────────────────┤
│ JSON-RPC 2.0 Layer │ ← 基础 RPC 协议
├─────────────────────────────────────────┤
│ Transport Layer (Stdio/HTTP) │ ← 传输机制
└─────────────────────────────────────────┘
核心设计原则
原则
说明
示例
标准化
统一的协议格式
所有工具调用使用 tools/call 方法
协商式
能力协商机制
Client 和 Server 协商支持的功能
双向通信
支持请求和通知
Server 可以主动发送日志通知
类型安全
JSON Schema 验证
参数和返回值都有明确的类型定义
可扩展
支持自定义扩展
可以添加自定义 Capabilities
MCP vs 其他协议
协议
用途
MCP 的优势
REST API
通用 Web 服务
MCP 专为 AI 上下文设计,支持工具发现和类型安全
gRPC
高性能 RPC
MCP ……
阅读全文
2025-10-11 11:08:26
摘要:一、函数调用进阶用法
1. FunctionInvokingChatClient 深入解析
FunctionInvokingChatClient 是 MEAI 中负责函数调用的核心中间件。当我们调用 UseFunctionInvocation() 时,实际上是在管道中插入了这个强大的中间件,它会自动处理模型的函数调用请求。
工作原理与执行流程
FunctionInvokingChatClient 作为装饰器包装底层的 IChatClient,拦截对话请求并自动处理函数调用循环:
发送初始请求:将用户消息和可用工具传递给模型
检测函数调用:模型返回时,检查响应中是否包含 FunctionCallContent
执行函数:自动调用被请求的函数,获取执行结果
回传结果:将函数结果作为 FunctionResultContent 添加到对话历史
继续迭代:再次调用模型,让它基于函数结果生成最终回答
返回响应:直到模型不再请求函数调用,返回最终答案
这个循环过程完全自动化,开发者无需手动管理函数调用状态。
用户消息 → 模型(发现需要调用函数) → 执行函数 → 模型(基于结果) → 最终答案
↑_______________________________________________|
(自动迭代,最多 MaximumIterationsPerRequest 次)
核心配置选项
通过 UseFunctionInvocation(configure: options = ) 可以访问 FunctionInvokingChatClient 的配置选项。以下是各属性的详细说明:
AdditionalTools(全局工具集)
用途:注册跨所有请求共享的工具,无需每次在 ChatOptions.Tools 中重复指定
适用场景:系统级工具(如时间、日期、日志)
与 ChatOptions.Tools 的关系:两者会合并,AdditionalTools 优先级更低
AllowConcurrentInvocation(并发调用)
用途:允许模型在单次响应中并发调用多个函数
性能优势:多个独立函数可并行执行,显著减少等待时间
注意事项:确保工具函数是线程安全的
示例场景:同时查询多个城市的天气
MaximumIterati……
阅读全文
2025-10-04 17:26:05
摘要:一、M.E.AI概述
1. 引言
Microsoft.Extensions.AI (MEAI) 定位于.NET 生态系统的 AI 功能基础抽象层,提供如 IChatClient 和 IEmbeddingGenerator 等核心接口,旨在统一和简化.NET 应用与各类 AI 服务的集成方式 。
Microsoft.Extensions.AI (MEAI) 是一系列旨在为.NET 开发者提供与各种人工智能服务进行集成和交互的统一方法的库 。它的核心目标是提供一组通用的抽象,从而简化.NET 应用程序中生成式 AI 组件的表示,并实现与不同 AI 服务的无缝集成和互操作性。 MEAI 的核心功能主要围绕两个关键接口展开:ChatClient 和 IEmbeddingGeneratorTInput, TEmbedding。
2. MEAI 的核心功能和优势
IChatClient:用于与聊天型 AI 服务交互的客户端接口,支持多模态消息传递和流式响应。
IEmbeddingGeneratorTInput, TEmbedding:用于生成向量嵌入的通用接口,支持多种输入类型。
依赖注入 (DI) 和中间件支持:利用.NET 的成熟 DI 和中间件模式,简化组件集成。 这使得开发者可以轻松地将自动函数工具调用、遥测和缓存等功能集成到应用程序中。
服务无关性:MEAI 的设计目标是实现与特定 AI 服务的解耦,使得开发者可以在不同的 AI 提供商之间轻松切换,而无需修改应用代码。 这不仅提高了代码的可移植性,还简化了测试和模拟过程。
多模态支持:IChatClient 接口支持文本、图像和音频等多种消息类型,满足现代 AI 应用的需求。
流式响应:IChatClient 支持流式响应,允许应用程序逐步处理来自 AI 服务的输出,提升用户体验。
扩展性:MEAI 的设计允许开发者为不同的 AI 服务实现自定义的客户端和嵌入生成器,促进生态系统的多样化和创新。
与 Semantic Kernel 的集成:MEAI 提供了与 Semantic Kernel 的无缝集成,允许开发者利用 SK 的高级功能,同时享受 MEAI 提供的统一接口和抽象。
与 Microsoft Agent Framework 的集成:MEAI 还与 Microsoft Agent Framework ……
阅读全文
2025-09-20 20:49:45
摘要:一、理论基础
1. RAG 概述
RAG:检索增强生成技术,我们先用一个例子来介绍一下什么是检索增强生成。
想象一下,你是一个很聪明的小学生,但你的知识都记在脑子里。如果老师问你一个很难的问题,比如:“恐龙是怎么消失的?”。你可能记得一些,但不完整。
这时候老师说:“来,我们开卷考!你可以去书架上查百科全书,然后再回答。”
RAG 就是这样:
你有大脑(AI 的记忆)→ 你本来就知道很多事。
但遇到不知道的问题→ 你先跑去“书库”(数据库、网络等)快速查找相关的资料。
把查到的资料和你原来的知识合在一起,用你自己的话给出一个更好的答案。
所以,RAG 就是:先查资料,再结合自己的知识回答问题。这样就不会瞎编,答案更准确、更新鲜!是不是很像写作业时“先翻书,再总结”呢?
企业应用使用大模型时,至少会遇到下面2个问题:
大模型一旦训练结束,它就不会在知道结束时间之后发生的事了,也就是它有时效性缺失
另外,通用的大模型是使用公共数据来训练的,它没有企业私有的数据,也就是私有领域空白
为了解决上面2类问题,我们可以使用 RAG 技术,为模型提供一个图书馆,也就是通常说的企业知识库。
2. RAG 工作流程
在让 LLM 回答问题之前,先去外部知识库中检索相关的信息,然后将检索到的信息作为参考资料喂给LLM,让它基于资料生成答案。RAG 分为2个阶段:
索引阶段:后台异步运行的数据处理流程,将文本转换为向量,构建语义索引。
检索与生成阶段:能够在线实时响应用户请求的流程
ETL(提取、转换、加载)流:
加载:格式解析、编码标准化、元数据提取;
分割:LLM的上下文窗口有限,所以需要递归字符分割,分割可能造成语义不完整,所以在分割的2段语句通常会添加重叠窗口;
嵌入:人类语言翻译成机器语言,使用嵌入模型,将文本转换为高维向量,即高维的语义空间,后续可以使用余弦相似度 -1 ~ 1进行检索;
存储:将文本块内容、向量数据、元数据,持久化存储到向量数据库。
3. 嵌入模型选型
我们把文本转换成高维向量时,需要使用嵌入模型,那如何选择嵌入模型呢?
我们先看一下都有哪些选择:
闭源厂商云端模型 API:
优势:接入成本低、弹性扩展
劣势:数据隐私风险、长期成本不可控、网络延迟
开源模型本地私有化:
优势:绝对的数据安全、零增量成本、高性能与低延迟
劣……
阅读全文