这是本系列的第一篇,专门写给已经会 C# 语法、但刚接触 AI 编程的你。
如果你写 C# 没问题(变量、using、异步 async/await、foreach 都懂),但一听到"大模型""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、再把回答拿回来"的一层封装。想明白这一点,就不用把它想得太玄。
二、我们要做什么(总览)
目标非常朴素:写一个小控制台程序,做三件事:
- 读取你的 DeepSeek 密钥和想用的模型;
- 创建一个"讲笑话"的 Agent;
- 分别用普通方式和流式方式让它讲同一个海盗笑话,把结果打印到屏幕。
整个程序只有 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
- 打开 DeepSeek 开放平台,注册并登录;
- 在"API Keys"页面点"创建密钥",会生成一串以
sk-开头的字符串; - 立刻复制保存,页面关闭后通常无法再次查看完整 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 指令",作用是引入命名空间,这样代码里才能直接写AIAgent、OpenAIClient这些类型,否则得写全称。项目开了"隐式 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-flash 或 deepseek-v4-pro,别用已废弃的 deepseek-chat。 |
| 一直连不上 / 超时 | 网络问题或被墙 | 确认能访问 https://api.deepseek.com;公司网络可能需代理。 |
| 构建报错找不到类型 | 依赖没还原 | 先 dotnet restore 再 dotnet 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_tools、03_multi_turn、04_memory等
参考资料
- Microsoft Agent Framework 的 OpenAI 扩展(
Microsoft.Agents.AI.OpenAI) - DeepSeek 官方 API 文档(中文):https://api-docs.deepseek.com/zh-cn/
- 参考博文:《MAF快速入门(1)化繁为简的AGENT创建范式》— EdisonZhou(cnblogs)