文章目录
-
- 一、开篇:为啥要写这篇文章
- 二、准备工作:别急着写代码
-
- [2.1 先搞个API Key](#2.1 先搞个API Key)
- [2.2 创建项目](#2.2 创建项目)
- [2.3 装NuGet包](#2.3 装NuGet包)
- [三、基础调用:先让整个"Hello AI"](#三、基础调用:先让整个"Hello AI")
-
- [3.1 最简单的聊天](#3.1 最简单的聊天)
- [3.2 流式输出](#3.2 流式输出)
- 四、进阶玩法:让AI真正"会做事"
-
- [4.1 什么是Function Calling](#4.1 什么是Function Calling)
- [4.2 实战:做个计算器插件](#4.2 实战:做个计算器插件)
- [4.3 注册插件并让AI使用](#4.3 注册插件并让AI使用)
- [4.4 更实用的例子:天气查询](#4.4 更实用的例子:天气查询)
- 五、对话上下文管理
-
- [5.1 为啥需要上下文](#5.1 为啥需要上下文)
- [5.2 上下文长度限制](#5.2 上下文长度限制)
- 六、国内大模型怎么调
-
- [6.1 用DeepSeek](#6.1 用DeepSeek)
- [6.2 用阿里云通义千问](#6.2 用阿里云通义千问)
- [6.3 用Azure OpenAI(企业首选)](#6.3 用Azure OpenAI(企业首选))
- 七、踩坑实录
-
- [7.1 网络问题](#7.1 网络问题)
- [7.2 Token计算](#7.2 Token计算)
- [7.3 超时设置](#7.3 超时设置)
- 八、完整实战:做个智能客服
- 九、写在最后
P.S. 目前国内还是很缺AI人才的,希望更多人能真正加入到AI行业,共同促进行业进步,增强我国的AI竞争力。想要系统学习AI知识的朋友可以看看我精心打磨的教程 http://blog.csdn.net/jiangjunshow http://blog.csdn.net/jiangjunshow/article/details/77338485,教程通俗易懂,高中生都能看懂,还有各种段子风趣幽默,从深度学习基础原理到各领域实战应用都有讲解,我22年的AI积累全在里面了。注意,教程仅限真正想入门AI的朋友,否则看看零散的博文就够了。
一、开篇:为啥要写这篇文章
兄弟们,说实话啊,我搞AI这22年,见过太多奇葩事了。
前几天有个做.NET开发的老弟找我,说公司领导让他把ChatGPT接进项目里。他一脸懵,问我:"哥,C#咋调大模型啊?网上资料乱七八糟的..."
我当时就笑了。这问题太典型了!
你看啊,现在市面上讲Python调OpenAI的文章满天飞,但C#的?少得可怜!好像咱们.NET开发者不配玩AI似的...
扯淡!
C#调大模型不但能干,而且干得贼漂亮。微软自家就是搞AI的,Semantic Kernel这玩意儿就是亲儿子,稳定得一匹。
今天我就把我这些年踩过的坑、试过的路,一股脑儿全倒给你们。
二、准备工作:别急着写代码
2.1 先搞个API Key
这事儿简单,但必须得说。
OpenAI官网注册一个账号,去API页面复制你的Key。注意啊,这Key就跟你的银行卡密码一样,千万别往GitHub上扔!
我一般放环境变量里:
bash
# Windows
setx OPENAI_API_KEY "sk-你的密钥"
# 或者代码里读取
string apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY");
2.2 创建项目
Visual Studio新建一个控制台项目,.NET 8就行。别整那些花里胡哨的,先跑通再说。
bash
dotnet new console -n CSharpLLMDemo
cd CSharpLLMDemo
2.3 装NuGet包
这里有好几条路可以走,我给你列清楚:
方案A:直接用OpenAI官方SDK(最简单)
bash
dotnet add package OpenAI --version 2.0.0
方案B:用Semantic Kernel(推荐,功能最强)
bash
dotnet add package Microsoft.SemanticKernel --version 1.0.0
dotnet add package Microsoft.SemanticKernel.Connectors.OpenAI --version 1.0.0
方案C:用Microsoft.Extensions.AI(最新最潮)
bash
dotnet add package Microsoft.Extensions.AI --version 9.0.0
我主要讲方案B,Semantic Kernel。为啥?因为这才是工业级的玩法!
三、基础调用:先让整个"Hello AI"
3.1 最简单的聊天
来,上代码:
csharp
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;
class Program
{
static async Task Main(string[] args)
{
// 1. 创建Kernel
var builder = Kernel.CreateBuilder();
builder.AddOpenAIChatCompletion(
modelId: "gpt-4o-mini", // 这个模型便宜又好用
apiKey: Environment.GetEnvironmentVariable("OPENAI_API_KEY")!
);
var kernel = builder.Build();
// 2. 获取聊天服务
var chatService = kernel.GetRequiredService<IChatCompletionService>();
// 3. 开聊!
var history = new ChatHistory();
history.AddSystemMessage("你是一个幽默的AI助手,说话要带梗");
history.AddUserMessage("你好,给我讲个程序员笑话");
var response = await chatService.GetChatMessageContentAsync(history);
Console.WriteLine($"AI说:{response.Content}");
}
}
运行结果大概长这样:
AI说:为啥程序员总是分不清圣诞节和万圣节?
因为 31 OCT = 25 DEC!
(八进制的31等于十进制的25,懂的人自然懂...)
看到没?就这么几行代码,AI就跟你聊上了。
3.2 流式输出
上面的代码有个问题:要等AI全部想完了才给你显示。如果回复很长,用户会以为程序卡死了...
改成流式输出:
csharp
var history = new ChatHistory();
history.AddUserMessage("写一篇关于C#的500字短文");
await foreach (var chunk in chatService.GetStreamingChatMessageContentsAsync(history))
{
Console.Write(chunk.Content); // 来一个字符就显示一个
}
用户体验瞬间起飞!就像看AI在打字一样,爽得很。
四、进阶玩法:让AI真正"会做事"
4.1 什么是Function Calling
兄弟们,重点来了啊!
大模型有个毛病:它只会"说话",不会"做事"。
你问它"1234567除以7654321等于多少",它可能会瞎猜一个答案。为啥?因为它没有计算器!
Function Calling就是解决这个问题的。简单说:你给AI一堆工具(函数),让它自己决定什么时候用哪个。
4.2 实战:做个计算器插件
来,看这段代码:
csharp
using Microsoft.SemanticKernel;
using System.ComponentModel;
public class CalculatorPlugin
{
[KernelFunction("add_numbers")]
[Description("将两个数字相加")]
public int AddNumbers(
[Description("第一个数字")] int a,
[Description("第二个数字")] int b)
{
Console.WriteLine($"[计算器被调用] {a} + {b}");
return a + b;
}
[KernelFunction("divide_numbers")]
[Description("将第一个数字除以第二个数字")]
public double DivideNumbers(
[Description("被除数")] double a,
[Description("除数")] double b)
{
Console.WriteLine($"[计算器被调用] {a} / {b}");
return a / b;
}
}
注意那两个特性标签:
[KernelFunction]:标记这个方法可以被AI调用[Description]:告诉AI这个方法是干嘛的
4.3 注册插件并让AI使用
csharp
// 1. 注册插件
builder.Plugins.AddFromType<CalculatorPlugin>();
var kernel = builder.Build();
// 2. 配置让AI自动调用工具
var settings = new OpenAIPromptExecutionSettings
{
ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions,
Temperature = 0.1 // 准确度优先,别乱发挥
};
// 3. 创建带配置的函数
var func = kernel.CreateFunctionFromPrompt(
"用户问题:{input}",
settings
);
// 4. 提问
var result = await kernel.InvokeAsync(func, new KernelArguments
{
["input"] = "1234567除以7654321等于多少?精确到5位小数"
});
Console.WriteLine(result);
运行结果:
[计算器被调用] 1234567 / 7654321
AI说:1234567除以7654321等于0.16129
看到没?AI发现自己不会算,就调用了我们的计算器!这才是真正的智能嘛。
4.4 更实用的例子:天气查询
光会算数有啥用?来整点实际的:
csharp
public class WeatherPlugin
{
[KernelFunction("get_weather")]
[Description("获取指定城市的当前天气")]
public string GetWeather(
[Description("城市名称,比如'北京'、'上海'")] string city)
{
// 这里调真实的天气API,我先模拟一下
var random = new Random();
var temp = random.Next(15, 35);
var conditions = new[] { "晴天", "多云", "小雨", "阴天" };
var condition = conditions[random.Next(conditions.Length)];
return $"{city}当前天气:{condition},温度{temp}°C";
}
}
注册进去,然后问AI:
csharp
var result = await kernel.InvokeAsync(func, new KernelArguments
{
["input"] = "我想去北京旅游,那边天气怎么样?"
});
AI会自动提取出"北京"这个城市名,然后调用GetWeather函数!
五、对话上下文管理
5.1 为啥需要上下文
AI有个特点:它"记性不好"。每次调用都是独立的,它不记得你之前说过啥。
所以得用ChatHistory来保存对话记录:
csharp
var history = new ChatHistory();
history.AddSystemMessage("你是专业客服,态度要好");
while (true)
{
Console.Write("用户:");
var input = Console.ReadLine();
if (input == "exit") break;
history.AddUserMessage(input);
var response = await chatService.GetChatMessageContentAsync(history);
Console.WriteLine($"AI:{response.Content}");
history.AddAssistantMessage(response.Content!); // 关键!把AI回复也存起来
}
这样AI就能记住之前的对话了,体验跟ChatGPT一样丝滑。
5.2 上下文长度限制
但要注意啊,GPT-4o-mini最多支持128K tokens。超过这个限制,就得删掉一些老消息。
csharp
// 简单的截断策略:保留最近10轮对话
if (history.Count > 20) // 10轮 = 20条消息(用户+AI各10条)
{
// 保留System消息,删除最老的用户/AI消息对
var systemMessage = history.FirstOrDefault(m => m.Role == AuthorRole.System);
history.Clear();
if (systemMessage != null) history.Add(systemMessage);
}
六、国内大模型怎么调
6.1 用DeepSeek
OpenAI的API国内访问不稳定,而且贵!DeepSeek便宜多了。
csharp
builder.AddOpenAIChatCompletion(
modelId: "deepseek-chat",
apiKey: "你的DeepSeek Key",
endpoint: new Uri("https://api.deepseek.com") // 关键!改端点
);
6.2 用阿里云通义千问
csharp
builder.AddOpenAIChatCompletion(
modelId: "qwen-turbo",
apiKey: "你的阿里云Key",
endpoint: new Uri("https://dashscope.aliyuncs.com/compatible-mode/v1")
);
6.3 用Azure OpenAI(企业首选)
csharp
builder.AddAzureOpenAIChatCompletion(
deploymentName: "gpt-4", // 你的部署名
endpoint: "https://你的资源名.openai.azure.com/",
apiKey: "你的Azure Key"
);
Semantic Kernel的好处就是:换模型只需要改配置,业务代码完全不用动!
七、踩坑实录
7.1 网络问题
国内访问OpenAI API,十有八九会超时。解决方案:
- 用国内的大模型(DeepSeek、文心一言、通义千问)
- 用代理(自己想办法)
- 用Azure OpenAI(微软在国内有节点)
7.2 Token计算
每次调用都要花钱,得心里有数:
csharp
var response = await chatService.GetChatMessageContentAsync(history);
// 查看用了多少token
if (response.Metadata?.TryGetValue("Usage", out var usage) == true)
{
Console.WriteLine($"Prompt tokens: {usage.PromptTokens}");
Console.WriteLine($"Completion tokens: {usage.CompletionTokens}");
Console.WriteLine($"Total tokens: {usage.TotalTokens}");
}
GPT-4o-mini的价格是:输入0.15美元/百万token,输出0.6美元/百万token。便宜得很!
7.3 超时设置
默认超时可能不够,特别是生成长文本的时候:
csharp
var httpClient = new HttpClient { Timeout = TimeSpan.FromMinutes(5) };
var builder = Kernel.CreateBuilder();
builder.AddOpenAIChatCompletion(
modelId: "gpt-4o-mini",
apiKey: apiKey,
httpClient: httpClient // 传进去
);
八、完整实战:做个智能客服
来,把上面的知识点串起来,写个完整的例子:
csharp
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;
class Program
{
static async Task Main(string[] args)
{
// 1. 初始化Kernel
var builder = Kernel.CreateBuilder();
builder.AddOpenAIChatCompletion(
modelId: "gpt-4o-mini",
apiKey: Environment.GetEnvironmentVariable("OPENAI_API_KEY")!
);
// 2. 注册业务插件
builder.Plugins.AddFromType<OrderPlugin>();
builder.Plugins.AddFromType<ProductPlugin>();
var kernel = builder.Build();
var chatService = kernel.GetRequiredService<IChatCompletionService>();
// 3. 设置系统人设
var history = new ChatHistory();
history.AddSystemMessage("""
你是某电商平台的智能客服,名字叫"小智"。
你的职责是:
1. 回答用户关于商品的咨询
2. 帮用户查询订单状态
3. 处理退换货申请
说话要亲切自然,多用表情符号😊
遇到不懂的问题,诚实告诉用户你会转接人工客服
""");
// 4. 配置工具调用
var settings = new OpenAIPromptExecutionSettings
{
ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions
};
// 5. 开始对话
Console.WriteLine("小智:您好!我是智能客服小智,有什么可以帮您的吗?😊");
while (true)
{
Console.Write("\n用户:");
var input = Console.ReadLine();
if (string.IsNullOrWhiteSpace(input)) continue;
if (input.ToLower() == "exit") break;
history.AddUserMessage(input);
var response = await chatService.GetChatMessageContentAsync(
history,
settings,
kernel
);
Console.WriteLine($"\n小智:{response.Content}");
history.AddAssistantMessage(response.Content!);
}
}
}
// 订单查询插件
public class OrderPlugin
{
[KernelFunction("query_order")]
[Description("根据订单号查询订单状态")]
public string QueryOrder(
[Description("订单号,格式为ORD开头的一串数字")] string orderId)
{
// 实际项目中查数据库
var mockData = new Dictionary<string, string>
{
["ORD12345"] = "订单状态:已发货,预计明天送达📦",
["ORD67890"] = "订单状态:处理中,正在打包..."
};
return mockData.GetValueOrDefault(orderId, "未找到该订单,请检查订单号");
}
}
// 商品查询插件
public class ProductPlugin
{
[KernelFunction("search_product")]
[Description("根据关键词搜索商品")]
public string SearchProduct(
[Description("搜索关键词,比如'手机'、'耳机'")] string keyword)
{
// 实际项目中查ES或数据库
if (keyword.Contains("手机"))
return "为您找到以下手机:\n1. iPhone 15 Pro - ¥7999\n2. 小米14 - ¥3999";
return $"抱歉,暂时没有与'{keyword}'相关的商品";
}
}
运行效果:
小智:您好!我是智能客服小智,有什么可以帮您的吗?😊
用户:我想查一下订单ORD12345
小智:好的,我帮您查一下...🔍
[插件被调用] query_order: ORD12345
小智:您的订单状态:已发货,预计明天送达📦
用户:你们有什么手机推荐
小智:为您找到以下手机:
1. iPhone 15 Pro - ¥7999
2. 小米14 - ¥3999
看到没?AI自动识别了用户的意图,调用了对应的插件!这就是Agent的雏形啊兄弟们!
九、写在最后
说实话,写这篇文章的时候,我挺感慨的。
22年前我开始搞AI的时候,哪有这么方便的API啊。那时候写个神经网络,C++代码几千行,调参调到头秃...
现在呢?几行C#代码就能跟GPT-4对话,还能让它帮你干活。技术的进步真的太快了!
但我也发现一个问题:很多.NET开发者还在观望,觉得AI是Python的天下。这想法得改改了!
微软在AI这块的布局很深,Semantic Kernel、ML.NET、ONNX Runtime...全是给.NET开发者准备的武器。咱们不能守着金山要饭吃啊!
最后送大家一句话:
别问能不能做,问就是能做。C#调大模型,稳得一批!
有啥问题评论区见,我看到都会回。咱们一起进步!
P.S. 目前国内还是很缺AI人才的,希望更多人能真正加入到AI行业,共同促进行业进步,增强我国的AI竞争力。想要系统学习AI知识的朋友可以看看我精心打磨的教程 [http://blog.csdn.net/jiangjunshow\],(http://blog.csdn.net/jiangjunshow/article/details/77338485)教程通俗易懂,高中生都能看懂,还有各种段子风趣幽默,从深度学习基础原理到各领域实战应用都有讲解,我22年的AI积累全在里面了。注意,教程仅限真正想入门AI的朋友,否则看看零散的博文就够了。