老胡
发布于 2026-09-23 / 2 阅读
0
0

MAF 快速上手(1)Hello Agent:用 C# 连上 DeepSeek 讲个笑话

这是本系列的第一篇,专门写给已经会 C# 语法、但刚接触 AI 编程的你。

如果你写 C# 没问题(变量、using、异步 async/awaitforeach 都懂),但一听到"大模型""Agent""API""流式输出"就发懵,别慌,本篇就是为你写的。我们会从零把一个最小可运行的 AI 程序跑起来:用 C# 写一段代码,让 DeepSeek 这个大模型给我们讲一个海盗笑话。

示例源码位于:dotnet/samples/01-get-started/01_hello_agent/


一、先搞懂几个 AI 编程里的"新朋友"

AI 编程里很多名词看起来吓人,其实都不复杂。先花两分钟过一遍,后面代码就全看得懂了。

名词大白话解释
大模型(LLM)一个被喂了海量文本训练出来的"超级文字接龙机器"。你给它一段话(提示词),它接着往下生成文字。DeepSeek、GPT 都是大模型。
API应用程序接口。你不用自己造大模型,只要按它规定的格式发一个网络请求,它就返回结果。相当于"打电话给模型公司,让它帮你干活"。
Endpoint(端点 / 地址)API 的网址。DeepSeek 的地址是 https://api.deepseek.com。就像你要打电话得先知道对方号码。
API Key(密钥)你的"账号密码 / 门禁卡"。每次调用 API 都要带上它,服务商才知道是谁在调用、该扣谁的钱。千万别把 Key 发到网上或提交到代码仓库。
模型名(model)同一家公司也可能提供多个模型。DeepSeek 当前推荐 deepseek-flash(快、便宜),另有 deepseek-v4-pro(更强)。就像同一品牌的不同配置。
Agent(智能体)在 MAF 里,Agent 就是把"人设 + 模型调用"打包好的一个对象。你给它一句话,它内部去调模型、拿结果。本篇的 Agent 人设是"讲笑话高手"。
流式输出(Streaming)普通调用要等模型全部想完才一次性返回;流式调用是模型想到一句就发一句,像打字机一样逐字蹦出来,体验更流畅。

Agent 在本篇里不是什么神秘东西。它就是把"提示词发给 DeepSeek、再把回答拿回来"的一层封装。想明白这一点,就不用把它想得太玄。


二、我们要做什么(总览)

目标非常朴素:写一个小控制台程序,做三件事:

  1. 读取你的 DeepSeek 密钥和想用的模型;
  2. 创建一个"讲笑话"的 Agent;
  3. 分别用普通方式流式方式让它讲同一个海盗笑话,把结果打印到屏幕。

整个程序只有 30 来行,跑通它,你就正式入了 AI 编程的门。


三、环境准备

项目说明
开发语言C#(本篇假设你已掌握基础语法)
目标框架.NET 10.0(项目文件里 TargetFrameworks=net10.0
需要的 SDK安装 .NET 10 SDK
关键依赖Microsoft.Extensions.AI.OpenAI(OpenAI 官方 .NET SDK 的 MAF 适配层)、Microsoft.Agents.AI.OpenAI(MAF 提供的 OpenAI 扩展)
运行平台Windows / Linux / macOS 都行

Microsoft.Agents.AI(简称 MAF,Microsoft Agent Framework)就是我们用的"框架",它把调模型的繁琐细节封装好了,让你只管"创建 Agent"和"调用"这两步。


四、第一步:拿到你的 DeepSeek API Key

  1. 打开 DeepSeek 开放平台,注册并登录;
  2. 在"API Keys"页面点"创建密钥",会生成一串以 sk- 开头的字符串;
  3. 立刻复制保存,页面关闭后通常无法再次查看完整 Key。

这就是你后面程序里要用的 DEEPSEEK_API_KEY。它相当于你的"调用额度钥匙"。


五、第二步:配置环境变量

程序不从代码里硬写密钥,而是从环境变量读取。好处是:密钥不进代码、不进仓库,安全;换机器只改环境变量即可。

我们需要设置两个环境变量:

变量名必填说明默认值
DEEPSEEK_API_KEY必填上一步拿到的密钥无,缺失程序会报错退出
DEEPSEEK_MODEL可选想用的模型名deepseek-flash

Windows(PowerShell):

$env:DEEPSEEK_API_KEY = "sk-你的key"
$env:DEEPSEEK_MODEL = "deepseek-flash"

Linux / macOS(终端):

export DEEPSEEK_API_KEY="sk-你的key"
export DEEPSEEK_MODEL="deepseek-flash"

用上面命令设置的环境变量只在当前终端窗口有效。关掉重开就要重新设。想永久生效,可把它们写进系统环境变量或 shell 配置文件(如 .zshrc)。


六、第三步:读懂核心代码(逐行讲)

下面是 Program.cs 的完整内容。我们一行一行拆,重点解释"为什么这么写"。

// Copyright (c) Microsoft. All rights reserved.

// 这是注释:本示例用 MAF 的 OpenAI 扩展,连一个 OpenAI 兼容的后端(这里用 DeepSeek)。

using Microsoft.Agents.AI;   // 引入 MAF 核心:我们要用到的 AIAgent 类型就在这里
using OpenAI;                // 引入 OpenAI SDK:OpenAIClient、OpenAIClientOptions 在这里
using OpenAI.Chat;           // 引入聊天相关:ChatClient、以及把 ChatClient 变成 Agent 的扩展方法
using System.ClientModel;    // 引入 ApiKeyCredential:用来装你的密钥

// ① 读取密钥:从环境变量取。如果是 null(没设置),就抛异常并终止程序。
//    ?? 是 C# 的"空合并"运算符:左边为空就用右边。
var apiKey = Environment.GetEnvironmentVariable("DEEPSEEK_API_KEY")
    ?? throw new InvalidOperationException("未设置环境变量 DEEPSEEK_API_KEY。");
// ② 读取模型名:没设置就默认用 deepseek-flash(官方推荐)。
var model = Environment.GetEnvironmentVariable("DEEPSEEK_MODEL") ?? "deepseek-flash";

// ③ 创建 OpenAI 客户端,关键是指定 Endpoint 指向 DeepSeek 的地址(而不是 OpenAI 官网)。
//    ApiKeyCredential 就是把字符串密钥包成一个安全的凭据对象。
OpenAIClient openAIClient = new(
    new ApiKeyCredential(apiKey),
    new OpenAIClientOptions { Endpoint = new Uri("https://api.deepseek.com") });

// ④ 拿"聊天客户端":告诉它用哪个模型。ChatClient 实现了 MAF 统一的接口。
ChatClient chatClient = openAIClient.GetChatClient(model);
// ⑤ 把聊天客户端"包装"成一个 Agent,并设定人设(instructions)和名字(name)。
AIAgent agent = chatClient.AsAIAgent(instructions: "你是一个擅长讲笑话的助手。", name: "笑话大王");

// ⑥ 普通调用:把提示词丢给 Agent,await 等它把整段笑话想完,一次性打印。
Console.WriteLine(await agent.RunAsync("给我讲一个关于海盗的笑话。"));

// ⑦ 流式调用:同一个提示词,但模型想到一句就返回一句,用 foreach 逐段打印。
await foreach (var update in agent.RunStreamingAsync("给我讲一个关于海盗的笑话。"))
{
    Console.WriteLine(update);
}

初学者常问的几个点:

  • await 是什么? 调模型是"网络请求",要等网络返回。await 表示"这里先让出线程去等结果,拿到再继续"。配合 async 方法使用,MAF 的 RunAsync 等方法都返回可等待的任务。
  • using 那几行是干嘛的? 叫"using 指令",作用是引入命名空间,这样代码里才能直接写 AIAgentOpenAIClient 这些类型,否则得写全称。项目开了"隐式 using",基础的 System 等已自动引入,这几行是额外需要的。
  • 为什么 DeepSeek 能用 OpenAI 的 SDK? 因为 DeepSeek 提供了与 OpenAI 兼容的接口格式。所以我们只需把"服务器地址"从 OpenAI 换成 DeepSeek,其余代码完全一样,这正是 MAF + OpenAI SDK 的便利之处。
  • AsAIAgent 做了啥? 它把"聊天客户端"包成 MAF 标准的 AIAgent。之后无论是普通调用还是流式调用,都用同一套 RunAsync / RunStreamingAsync 接口,与具体后端无关。

本篇用的是本地 Agent:人设和调用都写在你这段程序里,DeepSeek 服务端并不会记住你创建过这个 Agent。对入门来说这是最简单的做法。


七、运行与结果

在示例目录下执行:

cd d:\gitee\agent-framework-main\dotnet\samples\01-get-started\01_hello_agent
dotnet run

如果你已经设好环境变量并联网,控制台会先打印普通调用的完整笑话,再流式地把同一笑话逐段输出一遍。

如果报错,先别急,跳到下一节的"常见问题"对照排查。


八、常见问题(新手排雷)

现象可能原因处理建议
提示 未设置环境变量 DEEPSEEK_API_KEY环境变量没设或设错窗口回到第五节,确认当前终端窗口已 export/$env 设置成功(可在终端 echo $env:DEEPSEEK_API_KEY 验证)。
报 401 / 认证失败Key 错了或复制不完整检查 sk- 开头是否完整、有无多余空格。
报模型不存在用了旧模型名用官方最新名 deepseek-flashdeepseek-v4-pro,别用已废弃的 deepseek-chat
一直连不上 / 超时网络问题或被墙确认能访问 https://api.deepseek.com;公司网络可能需代理。
构建报错找不到类型依赖没还原dotnet restoredotnet build

九、动手改造(练手)

跑通后,试试改这几个地方,立刻看到不同效果:

  • 换人设:把 instructions 改成 "You are a helpful Chinese travel assistant."(中文旅游助手),提示词也换成中文。
  • 换模型:设 DEEPSEEK_MODEL=deepseek-v4-pro,体验更强的模型(可能更慢/更贵)。
  • 换问题:改 RunAsync(...)RunStreamingAsync(...) 里的英文提示词,比如 "用一句话解释什么是人工智能。"
  • 换后端:把 Endpoint 改成别的 OpenAI 兼容服务(本地 Ollama、硅基流动等),就能无缝迁移,Agent 代码一行不用动。

十、小结

恭喜,你已经用 C# 跑通了第一个 AI 程序!本篇你学到了:

  • AI 编程里的几个核心名词(API / Endpoint / API Key / 模型 / Agent / 流式);
  • 如何申请并安全地用环境变量注入 DeepSeek 密钥;
  • OpenAIClient 指向 DeepSeek,再用 AsAIAgent 包装成 Agent;
  • 普通调用与流式调用两种姿势。

下一篇,我们会在它基础上玩多轮对话和函数调用(让 Agent 能调用你的 C# 方法),敬请期待。

示例源码

  • 本示例:dotnet/samples/01-get-started/01_hello_agent/Program.cs
  • 系列参考:同目录 02_add_tools03_multi_turn04_memory

参考资料

  • Microsoft Agent Framework 的 OpenAI 扩展(Microsoft.Agents.AI.OpenAI
  • DeepSeek 官方 API 文档(中文):https://api-docs.deepseek.com/zh-cn/
  • 参考博文:《MAF快速入门(1)化繁为简的AGENT创建范式》— EdisonZhou(cnblogs)

评论