2025-11-05
C#
00

目录

项目概述与技术栈
环境准备与项目设置
创建项目并安装依赖
获取API密钥
完整代码实现
代码详解
初始化与配置
聊天循环实现
流式响应处理
历史管理机制
自定义与扩展示例
修改AI人格设定
部署与最佳实践
API密钥安全管理
常见问题与解决方案
API调用失败
响应超时
总结

在AI快速发展的时代,越来越多的开发者希望将智能对话功能集成到自己的应用中。本文将详细介绍如何使用C#和Microsoft Semantic Kernel框架连接DeepSeek AI服务,构建一个功能完善的聊天应用。文章包含完整代码示例和详细注释,适合有基础C#知识的开发者学习。这个库NB的就是支持所有大模型,不过有些地方要调整一下。

项目概述与技术栈

我们将构建一个控制台应用程序,支持以下功能:

  • 与DeepSeek AI进行自然语言对话
  • 流式响应显示(打字机效果)
  • 会话历史管理
  • 完善的错误处理

使用的核心技术和库:

  • C# 10+
  • .NET 6/7/8
  • Microsoft Semantic Kernel
  • OpenAI C# SDK (用于连接DeepSeek API)
  • Microsoft.Extensions.Hosting

环境准备与项目设置

创建项目并安装依赖

首先,创建一个新的控制台应用程序,并安装必要的NuGet包:

Bash
dotnet add package Microsoft.SemanticKernel dotnet add package Microsoft.SemanticKernel.Connectors.OpenAI dotnet add package Microsoft.Extensions.Hosting

获取API密钥

需要获取DeepSeek API的访问密钥,可以通过DeepSeek官方网站注册获取。

完整代码实现

下面是一个完整的聊天应用实现,包含详细注释:

C#
using Microsoft.SemanticKernel.ChatCompletion; using Microsoft.SemanticKernel; using System.Net.Http; using OpenAI; using System.ClientModel; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Configuration; using OpenAI.Chat; using System.Collections.Generic; using System.Text; namespace AppMultimodal { internal class Program { // 最大保存的对话轮数,防止历史记录过长 private const int MaxConversationTurns = 10; static async Task Main(string[] args) { try { // 使用Host Builder模式配置应用 var builder = Host.CreateApplicationBuilder(args); // 从配置文件或环境变量加载API密钥 // 实际使用时请替换为自己的API密钥或通过环境变量配置 builder.Configuration.AddEnvironmentVariables(); var apiKey = builder.Configuration["OpenAI:ApiKey"] ?? "sk-替换为你的API密钥"; // 配置OpenAI客户端凭证 var openAIClientCredential = new ApiKeyCredential(apiKey); var openAIClientOption = new OpenAIClientOptions { // 这里使用DeepSeek的API端点 Endpoint = new Uri("https://api.deepseek.com/v1") }; // 创建OpenAI客户端 var openaiClient = new OpenAIClient(openAIClientCredential, openAIClientOption); // 注册服务,指定模型名称 builder.Services.AddOpenAIChatCompletion("deepseek-chat", openaiClient); var host = builder.Build(); // 启动聊天循环 await RunChatLoopAsync(openaiClient); } catch (Exception ex) { // 全局异常处理 Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"发生错误: {ex.Message}"); Console.ResetColor(); } } /// <summary> /// 运行聊天主循环,处理用户输入并获取AI响应 /// </summary> static async Task RunChatLoopAsync(OpenAIClient openaiClient) { Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("DeepSeek: 你好,有什么是我能帮你的吗?"); // 初始化聊天历史 List<ChatMessage> chatHistory = new List<ChatMessage>(); var systemContent = ChatMessage.CreateSystemMessage("你是我的助手"); chatHistory.Add(systemContent); // 设置聊天参数 var settingOptions = new ChatCompletionOptions { MaxOutputTokenCount = 2048, // 限制输出长度 Temperature = 0.7f, // 控制回答的创造性,值越高创造性越强 }; // 获取聊天客户端 var client = openaiClient.GetChatClient("deepseek-chat"); // 聊天循环 while (true) { Console.ForegroundColor = ConsoleColor.Yellow; Console.Write("你: "); var userInput = Console.ReadLine(); // 空输入退出 if (string.IsNullOrEmpty(userInput)) break; // 处理用户消息 await ProcessUserMessageAsync(userInput, chatHistory, client, settingOptions); } } /// <summary> /// 处理用户输入消息,发送到AI并获取响应 /// </summary> static async Task ProcessUserMessageAsync(string userInput, List<ChatMessage> chatHistory, OpenAI.Chat.ChatClient client, ChatCompletionOptions options) { try { // 添加用户消息到历史 var inputMsg = ChatMessage.CreateUserMessage(userInput); chatHistory.Add(inputMsg); // 管理对话历史长度,防止内存溢出 ManageChatHistorySize(chatHistory); Console.ForegroundColor = ConsoleColor.White; Console.Write("DeepSeek: "); // 流式接收并显示回复 var response = StreamAndDisplayResponse(client, chatHistory, options); // 添加助手回复到历史 var assistantMsg = ChatMessage.CreateAssistantMessage(response); chatHistory.Add(assistantMsg); } catch (Exception ex) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"处理消息时出错: {ex.Message}"); Console.ResetColor(); } } /// <summary> /// 流式获取并显示AI响应,实现打字机效果 /// </summary> static string StreamAndDisplayResponse(OpenAI.Chat.ChatClient client, List<ChatMessage> chatHistory, ChatCompletionOptions options) { // 使用流式API获取响应 var clientResult = client.CompleteChatStreaming(chatHistory, options); StringBuilder sb = new StringBuilder(); try { // 遍历流式响应的每个部分 foreach (var item in clientResult) { var text = item.ContentUpdate.FirstOrDefault()?.Text ?? string.Empty; sb.Append(text); Console.Write(text); // 实时显示,创造打字机效果 } Console.WriteLine(); return sb.ToString(); } catch (Exception ex) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"\n获取回复时出错: {ex.Message}"); Console.ResetColor(); return $"抱歉,获取回复时发生错误。"; } } /// <summary> /// 管理聊天历史大小,防止过长导致token超限或内存问题 /// </summary> static void ManageChatHistorySize(List<ChatMessage> chatHistory) { // 保留系统消息和最近的对话 if (chatHistory.Count > MaxConversationTurns * 2 + 1) // +1 是为系统消息 { // 保留系统消息 var systemMsg = chatHistory[0]; // 移除最早的用户-助手对话对 chatHistory.RemoveRange(1, 2); // 确保系统消息仍在第一位 if (chatHistory[0] != systemMsg) { chatHistory.Insert(0, systemMsg); } } } } }

image.png

代码详解

初始化与配置

C#
var builder = Host.CreateApplicationBuilder(args); // 从配置或环境变量加载API密钥 builder.Configuration.AddEnvironmentVariables(); var apiKey = builder.Configuration["OpenAI:ApiKey"] ?? "sk-替换为你的API密钥"; // 配置OpenAI客户端 var openAIClientCredential = new ApiKeyCredential(apiKey); var openAIClientOption = new OpenAIClientOptions { Endpoint = new Uri("https://api.deepseek.com/v1") };

这段代码使用Host Builder模式配置应用,从环境变量或默认值获取API密钥,并设置DeepSeek的API端点。

聊天循环实现

C#
static async Task RunChatLoopAsync(OpenAIClient openaiClient) { // 初始化聊天历史 List<ChatMessage> chatHistory = new List<ChatMessage>(); var systemContent = ChatMessage.CreateSystemMessage("你是我的助手"); chatHistory.Add(systemContent); // ...聊天循环代码... }

此方法初始化聊天历史并设置系统提示,这决定了AI助手的行为和角色定位。您可以根据需要修改系统提示,例如"你是一位专业的客服代表"或"你是一位编程导师"等。

流式响应处理

C#
static string StreamAndDisplayResponse(OpenAI.Chat.ChatClient client, List<ChatMessage> chatHistory, ChatCompletionOptions options) { var clientResult = client.CompleteChatStreaming(chatHistory, options); StringBuilder sb = new StringBuilder(); foreach (var item in clientResult) { var text = item.ContentUpdate.FirstOrDefault()?.Text ?? string.Empty; sb.Append(text); Console.Write(text); // 实时显示 } // ...其余代码... }

这段代码实现了流式响应处理,让AI回复像人类一样逐字显示,而不是一次性返回全部内容。这种交互更自然,特别是对于长回复。

历史管理机制

C#
static void ManageChatHistorySize(List<ChatMessage> chatHistory) { if (chatHistory.Count > MaxConversationTurns * 2 + 1) { // 保留系统消息 var systemMsg = chatHistory[0]; // 移除最早的对话 chatHistory.RemoveRange(1, 2); // ...确保系统消息位置... } }

这个方法确保聊天历史不会无限增长,通过限制保留的对话轮数,防止token超限和内存问题。

自定义与扩展示例

修改AI人格设定

可以通过更改系统消息来定制AI的行为风格:

C#
// 技术顾问 var systemContent = ChatMessage.CreateSystemMessage( "你是一位资深的技术顾问,专注于C#和.NET开发。提供专业、简洁和实用的建议。"); // 创意写作助手 var systemContent = ChatMessage.CreateSystemMessage( "你是一位创意写作助手,善于提供生动、有创意的表达和新颖的想法。");

部署与最佳实践

API密钥安全管理

生产环境中,应避免在代码中硬编码API密钥,建议:

  1. 使用环境变量存储密钥
  2. 使用用户机密管理(User Secrets)
  3. 使用Azure Key Vault等专业密钥管理服务

常见问题与解决方案

API调用失败

如果遇到API调用失败:

  1. 检查API密钥是否有效
  2. 验证网络连接
  3. 确认DeepSeek API端点是否正确
  4. 检查请求是否符合API限制

响应超时

对于长时间无响应的情况:

C#
// 添加超时设置 var openAIClientOption = new OpenAIClientOptions { Endpoint = new Uri("https://api.deepseek.com/v1"), NetworkTimeout = TimeSpan.FromSeconds(60) // 设置60秒超时 };

总结

本文详细介绍了如何使用C#和Semantic Kernel框架构建DeepSeek AI聊天应用。从基础设置到高级功能,提供了全面的指导和代码示例。通过本教程,开发者可以快速构建自己的AI聊天应用,并根据需求进行定制和扩展。

无论是构建客服机器人、智能助手还是创意写作工具,这套框架都能提供稳固的技术基础。希望本文对您的AI开发之旅有所帮助!


如有问题或建议,欢迎在评论区留言交流!

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!