从零开始-用CSharp调用你的第一个大模型
抛开复杂的数学和神经网络架构,从软件开发者的视角来看,大语言模型可以简化为一个非常朴素的概念:
本质上,它是一个函数
输入(Prompt) → 大语言模型 → 输出(Completion)
你可以把它理解成一个超级强大的字符串到字符串的映射函数:
string Ask(string prompt) => … // 模型内部有数千亿参数在做这件事
给它一段文本(Prompt),它返回一段文本(Completion)。就这么简单。
但"简单"背后有几个关键特征:
特征 说明
概率性 同样的输入,每次输出可能不同——它是在"预测"下一个最可能的词
无状态 每次调用都是独立的,模型不会"记住"你上次问了什么
上下文依赖 输出质量完全取决于你给的输入(Prompt)有多好
Token驱动 模型不直接处理文字,而是把文字切分成Token(词元)来处理
什么是Token?
Token是大模型处理文本的基本单位。你可以粗略地理解为"一个词或一个词片段":
“你好世界” → [你, 好, 世, 界] (中文大约1个字 ≈ 1-2个Token)
“Hello World” → [Hello, World] (英文大约1个词 ≈ 1-1.5个Token)
Token很重要,因为:
API按Token计费:输入Token + 输出Token = 你的花费
模型有上下文窗口限制:比如8K、32K、128K Token,超过就处理不了
速度取决于Token:生成Token是逐个进行的,Token越多越慢
从「裸函数」到「对话API」
上面说的Ask(prompt)只是一个概念模型。实际上,大模型服务商提供的是更结构化的对话API。以OpenAI兼容协议(目前行业标准)为例,一次API调用由以下几个核心部分组成:
┌─────────────────────────────────────────────┐
│ 一次API请求的组成 │
├─────────────┬───────────────────────────────┤
│ model │ 用哪个模型(如glm-5.1) │
│ │ │
│ messages │ 对话消息列表: │
│ │ - system: 系统提示词(人设) │
│ │ - user: 用户说的话 │
│ │ - assistant: AI之前的回复 │
│ │ │
│ parameters │ 控制参数: │
│ │ - temperature: 创造性(0~1) │
│ │ - max_tokens: 最大输出长度 │
│ │ - top_p: 采样范围 │
└─────────────┴───────────────────────────────┘
Messages:对话的核心
messages是整个请求中最重要的部分。它不是简单的一段文字,而是一个结构化的消息列表,每条消息都有一个角色(role):
messages = [
{ role: “system”, content: “你是一个专业的编程助手” }, ← 告诉AI它是谁
{ role: “user”, content: “什么是递归?” }, ← 用户的问题
{ role: “assistant”, content: “递归是…” }, ← AI之前的回答
{ role: “user”, content: “能给个例子吗?” } ← 用户的追问
]
三种角色的分工:
角色 职责 比喻
System 定义AI的身份、行为规则、输出格式 相当于"岗位说明书"
User 用户的输入 相当于"客户的问题"
Assistant AI的历史回复 相当于"之前的回答记录"
关键认知:因为模型是无状态的,所以每次调用都要把完整的对话历史重新发一遍。这就是AI"记忆"的真相——不是模型记住了,而是你每次都帮它复习了一遍。
一次完整的请求-响应
理解了上面的概念,一次API调用的全貌就清晰了:
请求(你发给模型的):
{
“model”: “glm-5.1”,
“messages”: [
{ “role”: “system”, “content”: “你是一个有帮助的AI助手。” },
{ “role”: “user”, “content”: “用一句话解释什么是API。” }
],
“temperature”: 0.7,
“max_tokens”: 1024
}
响应(模型返回的):
{
“id”: “chatcmpl-xxx”,
“model”: “glm-5.1”,
“choices”: [{
“message”: {
“role”: “assistant”,
“content”: “API(应用程序编程接口)是一组定义软件组件之间如何交互的规则和协议。”
},
“finish_reason”: “stop”
}],
“usage”: {
“prompt_tokens”: 28,
“completion_tokens”: 35,
“total_tokens”: 63
}
}
响应的关键字段:
choices[0].message.content:模型的回复内容
finish_reason:为什么停止(stop=正常结束,length=达到长度限制)
usage:本次调用消耗的Token数
大模型能做什么?
理解了大模型的接口形式,我们再来看看它能做什么。本质上,大模型的能力可以归结为文本的理解与生成:
能力 示例
问答 “C#中async和await的作用是什么?”
创作 “写一篇关于微服务的博客大纲”
翻译 “把这段话翻译成英文:…”
摘要 “用100字总结这篇文章:…”
代码生成 “用C#写一个快速排序算法”
数据分析 “分析这段JSON数据的结构”
推理 “如果A>B,B>C,那么A和C的关系是?”
但大模型也有明确的局限:
局限 说明
知识截止 训练数据有截止日期,不知道最新的事
无法联网 不能搜索网页、查天气、查数据库
无法执行 不能运行代码、操作文件、发邮件
幻觉 可能一本正经地胡说八道
后面几篇文章,我们将逐一解决这些局限——通过记忆系统解决知识遗忘,通过Function Calling让AI学会调用工具,通过MCP协议让AI接入工具生态。
环境准备
理论讲完了,接下来进入实战。在开始之前,你需要:
去 https://open.bigmodel.cn/ 注册一个智谱AI账号,注册后会免费送一些Token,拿到你的API Key和接口地址
克隆本项目代码:https://github.com/MapleWithoutWords/AIStudyDemos
智谱提供OpenAI兼容协议接口,你也可以换成其他兼容的服务商(如DeepSeek、月之暗面等),只需修改baseUrl和apiKey即可。
动手实践:用C#调用大模型
环境准备就绪,打开项目中的 AICallConsole1 项目,配置好你的API Key后直接运行即可体验效果。下面我们来看看代码里做了什么。
C#中有两种方式调用大模型:
方式一:HttpClient直接调用——看透本质
大模型服务商几乎都遵循OpenAI兼容协议,本质上就是一个RESTful API。最直接的调用方式就是用HttpClient发送HTTP请求:
using var httpClient = new HttpClient();
httpClient.BaseAddress = new Uri(baseUrl);
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue(“Bearer”, apiKey);
var jsonContent = JsonSerializer.Serialize(new
{
model = “glm-5.1”,
messages = new[]
{
new { role = “system”, content = “你是一个有帮助的AI助手。” },
new { role = “user”, content = “你好,请介绍一下你自己。” }
},
temperature = 0.7,
max_tokens = 1024
});
var content = new StringContent(jsonContent, Encoding.UTF8, “application/json”);
var response = await httpClient.PostAsync(“chat/completions”, content);
var responseBody = await response.Content.ReadAsStringAsync();
关键点解析:
字段 说明
model 要调用的模型名称,如glm-5.1、gpt-4o等
messages 对话消息数组,包含system(系统提示词)和user(用户消息)
temperature 控制输出随机性,0-1之间,越高越"发散"
max_tokens 限制模型最大输出token数
chat/completions OpenAI兼容协议的标准端点
这种方式虽然原始,但它能让你完全理解请求和响应的原始结构。在生产环境中,我们更推荐使用SDK。
方式二:SDK调用——Microsoft.Extensions.AI.OpenAI
理解了HTTP裸调的原理后,我们来看看更优雅的SDK方式。
微软推出的 Microsoft.Extensions.AI 系列库采用了两层架构:
包名 职责
Microsoft.Extensions.AI 抽象层,定义 IChatClient、ChatMessage 等统一接口
Microsoft.Extensions.AI.OpenAI OpenAI适配层,提供 OpenAI.Chat.ChatClient 等具体实现
我们只需安装适配层包即可(它会自动引入抽象层):
using Microsoft.Extensions.AI;
IChatClient client =
new OpenAI.Chat.ChatClient(
model,
new ApiKeyCredential(apiKey),
new OpenAI.OpenAIClientOptions { Endpoint = new Uri(baseUrl) })
.AsIChatClient();
这里我们用 Microsoft.Extensions.AI.OpenAI 提供的 OpenAI.Chat.ChatClient 创建客户端,再通过 .AsIChatClient() 适配到 Microsoft.Extensions.AI 定义的抽象接口。这意味着——无论你用的是OpenAI、智谱GLM、DeepSeek还是其他兼容协议的服务商,代码几乎不用改。
构建交互式对话
有了客户端,我们来构建一个可以持续对话的控制台应用:
while (true)
{
Console.Write("\n你: ");
var userInput = Console.ReadLine();
if (string.IsNullOrWhiteSpace(userInput))
continue;
if (userInput.Equals("exit", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("再见!");
break;
}
List<ChatMessage> chatMessages =
[
new ChatMessage(ChatRole.System, "你是一个有用的AI助手,请用中文回答用户的问题。"),
new ChatMessage(ChatRole.User, userInput)
];
Console.Write("\nAI: ");
await foreach (var update in client.GetStreamingResponseAsync(chatMessages))
{
foreach (var item in update.Contents)
{
if (item is TextContent text)
{
Console.Write(text.Text);
}
}
}
}
理解消息角色
ChatMessage有三种核心角色:
System:系统提示词,定义AI的行为准则和人设
User:用户输入的消息
Assistant:AI的历史回复(后续讲记忆时会用到)
流式输出 vs 一次性响应
一次性响应
var response = await client.GetResponseAsync(chatMessages);
Console.WriteLine(response.Text);
简单直接,但需要等待模型生成完毕后才返回。对于长文本生成,用户会感到明显的等待。
流式响应(推荐)
await foreach (var update in client.GetStreamingResponseAsync(chatMessages))
{
foreach (var item in update.Contents)
{
if (item is TextReasoningContent textReasoning && isNeedReasoningContent)
{
Console.Write($“{textReasoning.Text}”);
}
else if (item is TextContent text)
{
Console.Write(text.Text);
}
else if (item is UsageContent usageContent)
{
Console.WriteLine(JsonSerializer.Serialize(usageContent.Details));
}
}
}
流式输出有三个内容类型需要注意:
类型 说明
TextReasoningContent 模型的"思考过程"(推理类模型如DeepSeek-R1会输出)
TextContent 最终的正文输出
UsageContent Token用量统计信息
流式输出的体验远优于等待完整响应——用户几乎可以实时看到AI的回答。
核心架构一览
用户输入
↓
构建 ChatMessage 列表 (System + User)
↓
IChatClient.GetStreamingResponseAsync()
↓
逐块接收 StreamingResponseUpdate
↓
解析 TextReasoningContent / TextContent / UsageContent
↓
实时输出到控制台
小结
这篇文章我们学习了:
大模型的本质:一个从字符串到字符串的映射函数,具有概率性、无状态、上下文依赖、Token驱动四大特征
对话API的组成:model + messages(system/user/assistant) + 控制参数
Token的概念:大模型处理文本的基本单位,直接影响成本和速度
大模型的能力与局限:能做问答、创作、翻译、推理,但无法联网、无法执行、有知识截止
环境准备:使用智谱AI服务商,通过UserSecrets安全管理API Key
两种调用方式:HttpClient裸调 vs SDK封装,前者帮助理解原理,后者用于生产
Microsoft.Extensions.AI 系列库:Microsoft.Extensions.AI(抽象层)+ Microsoft.Extensions.AI.OpenAI(适配层)的两层架构,一套代码兼容多个模型服务商
流式输出的实现细节和三种内容类型的区分
更多推荐




所有评论(0)