基于 Microsoft Agent Framework 集成 DeepSeek 大模型的实践

一、前言

Microsoft Agent Framework(简称 Agent Framework)发布已有一段时间。在"观望"(摸鱼)一阵后,在老板的"鼓励"下,我们果断将多个 AI 微服务从 Semantic Kernel(SK) 迁移至 Agent Framework。

本文记录迁移过程中总结的工程化用法与实践经验,供同行参考。

二、Agent Framework 是什么?

Agent Framework 是微软在 Semantic Kernel 之后推出的新一代智能体(Agent)开发框架,可视为 SK 的"进化版":

  • 核心理念相似,但 API 更直观、更现代化;

  • 原生支持 多智能体协作(Multi-Agent);

  • 更契合当前 LLM 应用向"智能体系统"演进的趋势。

💡 如果你曾被 SK 的 Kernel/Skill/Function/Context 嵌套结构折磨过,Agent Framework 会让你眼前一亮。

三、与 Semantic Kernel 的关键对比

维度 Semantic Kernel Agent Framework
结构设计 抽象层级多(Skill/Function),复用困难 直接定义 Agent 类,职责清晰
Prompt 管理 依赖 YAML/JSON 模板 + Template Function 直接传入 instructions,逻辑与提示分离自然
多 Agent 协作 需手动实现消息传递 内置线程(Thread)机制,天然支持多 Agent 通信
工具集成 手动注册函数为插件 支持 MCP 工具、自定义 AITool,开箱即用

四、工程化使用姿势

4.1 单一职责:每个任务一个 Agent

摒弃 SK 中"一个 Kernel 打天下"的模式,采用 一个任务对应一个 Agent 的设计:

  • 职责单一,便于测试与维护;

  • 通过 IOC 容器注册,像普通服务一样注入使用。

示例:公司名称抽取 Agent

csharp 复制代码
public class CompanyExtractionAgent : BaseAgentFunction, ICompanyExtractionAgent
{
    private readonly AIAgent _agent;

    public CompanyExtractionAgent(IOptions<LLMConfiguration> config)
    {
        var client = new OpenAIClient(...);
        var chatClient = client.GetChatClient(config.Value.Model);
        _agent = chatClient.CreateAIAgent(instructions: 
            "你是一个信息抽取助手,请从文本中提取所有公司名称,必须返回合法 JSON 数组...");
    }

    public async Task<List<string>> ExtractCompanyNamesAsync(string filePath)
    {
        // 分块处理文档 → 调用 Agent → 解析 JSON → 合并结果
    }
}

4.2 给 Agent 装上"手和眼":集成 MCP 工具

4.2.1 注册 MCP 客户端(如 Playwright 浏览器)

csharp 复制代码
public static async Task AddMcpClientAsync(this IServiceCollection services, bool headless)
{
    var transport = new StdioClientTransport(new StdioClientTransportOptions
    {
        Name = "PlaywrightMCP",
        Command = "npx",
        Arguments = new List<string> { "@playwright/mcp", "--headless", ... }
    });
    var mcpClient = await McpClient.CreateAsync(transport);
    services.AddSingleton(mcpClient);
}

4.2.2 使用 MCP 工具的 Agent

csharp 复制代码
public class CompanyInfoQueryAgent : BaseAgentFunction, ICompanyInfoQueryAgent
{
    public CompanyInfoQueryAgent(IOptions<LLMConfiguration> config, McpClient mcpClient)
    {
        var tools = (await mcpClient.ListToolsAsync()).Cast<AITool>().ToList();
        _agent = chatClient.CreateAIAgent(
            instructions: "你拥有网络访问能力,请使用 MCP 工具查询公司公开信息...",
            tools: tools
        );
    }

    public async Task<CompanyInfo?> QueryCompanyInfoAsync(string companyName) { ... }
}

4.3 自定义函数工具(Function Tool)

4.3.1 编写工具类

csharp 复制代码
public class CompanyInfoTool : AITool
{
    public async Task<string> QueryCompanyInfoAsync(string companyName)
    {
        return await _httpClient.GetStringAsync($"https://api.example.com/company/{companyName}");
    }
}

4.3.2 注册到 Agent

csharp 复制代码
_agent = chatClient.CreateAIAgent(
    instructions: "请使用工具查询公司信息",
    tools: new List<AITool> { _companyInfoTool }
);

4.4 记忆功能(Memory / Thread)

Agent Framework 通过 Thread 实现对话记忆:

csharp 复制代码
// 保存对话状态
var serialized = thread.Serialize(JsonSerializerOptions.Web).GetRawText();
await File.WriteAllTextAsync("thread.json", serialized);

// 恢复对话
var json = await File.ReadAllTextAsync("thread.json");
var restoredThread = _agent.DeserializeThread(JsonSerializer.Deserialize<JsonElement>(json));
var response = await _agent.RunAsync("继续...", restoredThread);

✅ 支持持久化到数据库、Redis 等,实现跨会话记忆。

五、踩坑与注意事项

5.1 Endpoint 配置差异

框架 正确 Endpoint 格式
Semantic Kernel https://api.deepseek.com/v1
Agent Framework https://api.deepseek.com (无 /v1)

⚠️ 多数国产模型 API(如 DeepSeek、Moonshot)在 Agent Framework 中需去掉路径后缀。

5.2 结构化输出(Structured Output)

推荐使用 ChatResponseFormat.ForJsonSchema 强制模型输出合规 JSON:

csharp 复制代码
var schema = AIJsonUtilities.CreateJsonSchema(typeof(CompanyInfo));
var chatOptions = new ChatOptions
{
    ResponseFormat = ChatResponseFormat.ForJsonSchema(schema, "CompanyInfo", "结构化公司信息"),
    Tools = tools
};

_agent = chatClient.CreateAIAgent(new ChatClientAgentOptions
{
    Instructions = "...",
    ChatOptions = chatOptions
});

❗ 注意:部分国产模型(如 DeepSeek)虽文档声称支持 response_format: { "type": "json_object" },但实际调用可能报错。建议先验证模型兼容性。

六、总结

Agent Framework 相比 Semantic Kernel:

  • 结构更清晰:Agent 即服务,天然契合微服务架构;

  • 开发更高效:减少模板代码,Prompt 与逻辑解耦;

  • 扩展更灵活:MCP、自定义工具、记忆、多 Agent 协作一应俱全。

尽管在国产模型适配上仍有小坑,但整体体验显著优于 SK,强烈推荐新项目直接采用 Agent Framework。

最佳实践

  • 一个任务 = 一个 Agent

  • 工具解耦、通过 DI 注入

  • 利用 Thread 实现上下文记忆

  • 优先使用结构化输出保障数据可靠性

关键词

Microsoft Agent Framework、Semantic Kernel、AI Agent、MCP、多智能体、结构化输出、.NET AI 开发

www.cnblogs.com/daibitx/p/1...

最后

如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。

也可以加入微信公众号 DotNet技术匠 社区,与其他热爱技术的同行一起交流心得,共同成长!

优秀是一种习惯,欢迎大家留言学习!

相关推荐
aqi002 小时前
鸿蒙版本的电子书阅读APP开放源码啦
android·华为·ai编程·harmonyos·鸿蒙
代码什么用3 小时前
Spring基础使用
java·后端·spring
明月_清风3 小时前
Deno 终局来了:从挑战 Node 到被 Cloudflare 收编
前端·后端·node.js
蜗牛互联网4 小时前
Java 17 HttpClient调用文件转写API的超时与失败回退
java·人工智能·后端
小虎AI生活5 小时前
把重复工作流派给 AI 的完整方法:四样要素、固定熟手与定时任务
aigc·ai编程
用户69371750013846 小时前
2026,程序员的时代拐点到了
android·前端·后端
用户5563525560566 小时前
[避坑] AI工具雷达避坑 | agent-browser的真实问题
ai编程
惜鸟6 小时前
从源码看 pi 的上下文管理:原始数据永久保留,模型视角按需裁剪
后端
量化分析码农6 小时前
【Python量化策略评估体系 #05】极端行情扛得住吗?2008/2015/2020 三场景压力测试
后端
十年Java程序媛6 小时前
Java 接口和抽象类对比|Java8 新特性,抛弃老旧八股,正确选型
java·spring boot·后端