【deepseek实战】绿色好用,不断网

devtools/2025/2/5 20:18:21/
aidu_pl">

前言

        最佳deepseek火热网络,我也开发一款windows的电脑端,接入了deepseek,基本是复刻了网页端,还加入一些特色功能。

        助力国内AI,发出自己的热量

        说一下开发过程和内容的使用吧。


ain-toc" name="tableOfContents">目录

一、介绍

二、具体工作

        1.1、引用

        1.2、主界面

        1.3、主界面布局

        1.4 、消息类

        1.5 、设置

三、运行图示 

四、总结

五、下载


 

一、介绍

  •    目标:个人桌面AI助手,避免与专属API冲突,因为官网一些原因断网,自己接入API,确保能上deepseek。
    先上图,确定是否需要使用:
  • 软件是免费的,自己用自己的key或者别人的key,没有key可以联系我

 

二、具体工作

        1.1、引用

        dotnet8.0

  <TargetFramework>net8.0-windows</TargetFramework>

        PackageReference 

    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" /><PackageReference Include="System.Drawing.Common" Version="8.0.0" /><PackageReference Include="System.Speech" Version="8.0.0" /><PackageReference Include="Spire.Doc" Version="12.8.0" />

            Newtonsoft.Json 编译和反编译API信息
            System.Drawing 绘制库,画界面主要
            System.Speech 语音接入
            Spire.Doc 文档使用

        这几个引用根据自己需要添加

        1.2、主界面

        信息处理,分为及时信息和二次信息处理,这样能对文本信息进行个人需要处理

private async Task<ChatMessage> StreamResponseAsync(string apiKey, List<ChatMessage> chatHistory, string language, CancellationToken cancellationToken)
{var deepseekService = new DeepseekService(currentUser, _printService);var messages = chatHistory.Select(m => new ChatMessage{Role = m.Role,MessageType = m.MessageType,Content = m.Content}).ToList();try{var typingDelay = TimeSpan.FromMilliseconds(50);var buffer = new StringBuilder();var responseMessage = new ChatMessage{Role = "assistant",MessageType = MessageType.Answer,Content = string.Empty,WrappedContent = string.Empty};// 创建响应消息但不立即添加到历史记录var responseIndex = _displayHistory .Count;// 实时处理流式响应 - deepseek输出开始var charCount = 0;var tempBuffer = new StringBuilder();await foreach (var chunk in deepseekService.StreamChatResponseAsync(apiKey, messages, language).WithCancellation(cancellationToken)){if (string.IsNullOrEmpty(chunk) || _isStopping || cancellationToken.IsCancellationRequested) {// Immediately return if stoppingreturn new ChatMessage{Role = "assistant",MessageType = MessageType.Answer,Content = "对话已终止",WrappedContent = "对话已终止"};}tempBuffer.Append(chunk);charCount += chunk.Length;// 每20个字符更新一次显示if (charCount >= 20){buffer.Append(tempBuffer.ToString());tempBuffer.Clear();charCount = 0;await Dispatcher.InvokeAsync(() => {responseMessage.Content = buffer.ToString();responseMessage.WrappedContent = WrapText(responseMessage.Content+"\n回答完成1",ChatHistoryRichTextBox?.ActualWidth - 20 ?? ChatMessage.DefaultBorderWidth);// 更新_curchat_curchatMesg = responseMessage;// 只在第一次更新时添加消息if (_displayHistory .Count == responseIndex) {_displayHistory .Add(responseMessage);} else {_displayHistory [responseIndex] = responseMessage;}UpdateChatHistoryDisplayList(_displayHistory);});          await Task.Delay(typingDelay);}}// 处理剩余不足20字符的内容if (tempBuffer.Length > 0){buffer.Append(tempBuffer.ToString());await Dispatcher.InvokeAsync(() => {responseMessage.Content = buffer.ToString() ;responseMessage.WrappedContent = WrapText(responseMessage.Content+"\n回答完成2",ChatHistoryRichTextBox?.ActualWidth - 20 ?? ChatMessage.DefaultBorderWidth);          // 更新_curchat_curchatMesg = responseMessage;_displayHistory [responseIndex] = responseMessage;UpdateChatHistoryDisplayList(_displayHistory);});}// deepseek输出完成 - 流式响应结束// 进行最后的换行检查await Dispatcher.InvokeAsync(() => {responseMessage.WrappedContent = WrapText(responseMessage.Content+"\n回答完成3", ChatHistoryRichTextBox?.ActualWidth - 20 ?? ChatMessage.DefaultBorderWidth);// 更新_curchat_curchatMesg = responseMessage;_displayHistory [responseIndex] = responseMessage;UpdateChatHistoryDisplayList(_displayHistory);});return responseMessage;}catch (Exception ex){return new ChatMessage{Role = "assistant",MessageType = MessageType.Answer,Content = $"Error: {ex.Message}",WrappedContent = $"Error: {ex.Message}"};}finally{// 清空输入框InputTextBox.Text = string.Empty;}
}

        1.3、主界面布局
<Window x:Class="AIzhushou.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="clr-namespace:AIzhushou.Converters"Title="智能聊天助手" Height="820" Width="420" MinHeight="800" MinWidth="400"WindowStartupLocation="Manual"Background="#333333" ResizeMode="CanResizeWithGrip"><Window.Resources><ResourceDictionary><ResourceDictionary.MergedDictionaries><ResourceDictionary Source="/Styles.xaml"/></ResourceDictionary.MergedDictionaries><local:EndMarkVisibilityConverter x:Key="EndMarkVisibilityConverter"/><local:MathConverter x:Key="MathConverter"/></ResourceDictionary></Window.Resources><Viewbox Stretch="Uniform"><Grid Width="420" Height="760" Background="#333333"><Grid.ColumnDefinitions><ColumnDefinition Width="63*"/><ColumnDefinition Width="337*"/></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition Height="Auto"/><RowDefinition Height="*"/><RowDefinition Height="Auto"/><RowDefinition Height="Auto"/><RowDefinition Height="Auto"/></Grid.RowDefinitions><!-- Top Buttons --><DockPanel Grid.Row="0" Grid.Column="1" Margin="265,0,20,5" Width="88"><Button  x:Name="setting" Style="{StaticResource MainButtonStyle}"Click="setting_Click" Height="40" Width="40" RenderTransformOrigin="0.5,0.5"DockPanel.Dock="Right"><Image Source="pack://application:,,,/AIzhushou;component/Img/icons8-home-page-50.png" Width="30" Height="30"/></Button></DockPanel><!-- Chat History Label --><Label Style="{StaticResource SectionLabelStyle}" Content="聊天记录" Margin="22,0,0,0" Grid.ColumnSpan="2" VerticalAlignment="Center"/><!-- Chat History RichTextBox --><Border Grid.Row="1" Style="{StaticResource ChatBorderStyle}" HorizontalAlignment="Left"Grid.ColumnSpan="2" Margin="15,0,0,10"><Border.Resources><Style TargetType="ScrollViewer" BasedOn="{StaticResource CustomScrollViewerStyle}" /></Border.Resources><RichTextBox x:Name="ChatHistoryRichTextBox" Style="{StaticResource ChatHistoryRichTextBoxStyle}"Loaded="ChatHistoryRichTextBox_Loaded" Width="380" Margin="-10,0,0,0"><RichTextBox.Resources><!-- 设置 Paragraph 的 Margin --><Style TargetType="Paragraph"><Setter Property="Margin" Value="0"/></Style></RichTextBox.Resources></RichTextBox></Border><!-- New Conversation Button --><StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Left" Margin="0,10,0,10" Grid.Column="1"><!--<Button x:Name="FreshButton" Style="{StaticResource FreshButtonStyle}" Click="freshButton_Click" Height="36" Width="120"><Button.Content><StackPanel Orientation="Horizontal"><Image Source="pack://application:,,,/AIzhushou;component/Img/icons8-refresh-96.png" Width="20" Height="20" Margin="0,0,5,0"/><TextBlock Text="刷新刚才回答" VerticalAlignment="Center" Foreground="#4d6bfe"/></StackPanel></Button.Content></Button>--><Button x:Name="NewConversationButton" Style="{StaticResource NewConversationButtonStyle}"Click="NewConversationButton_Click" Margin="90,0,5,0" Height="36" Width="120"><Button.Content><StackPanel Orientation="Horizontal"><Image Source="pack://application:,,,/AIzhushou;component/Img/icons8-talk-64.png" Width="20" Height="20" Margin="0,0,5,0"/><TextBlock Text="开启新对话" VerticalAlignment="Center" Foreground="#4d6bfe"/></StackPanel></Button.Content></Button></StackPanel><!-- Input Label --><Label Grid.Row="3" Style="{StaticResource SectionLabelStyle}" Content="输入消息" Margin="22,0,0,0" Grid.ColumnSpan="2" VerticalAlignment="Center"/><!-- Input Section --><Grid Grid.Row="4" HorizontalAlignment="Left" VerticalAlignment="Bottom"Margin="22,0,0,-10" Width="378" Grid.ColumnSpan="2"><Grid.ColumnDefinitions><ColumnDefinition Width="*"/><ColumnDefinition Width="Auto"/></Grid.ColumnDefinitions><!-- Input TextBox --><TextBox x:Name="InputTextBox" Grid.Column="0"Style="{StaticResource InputTextBoxStyle}"TextWrapping="Wrap" AcceptsReturn="True"KeyDown="InputTextBox_KeyDown"PreviewKeyDown="InputTextBox_KeyDown"/><!-- Send Button --><Border Grid.Column="1" Style="{StaticResource SendButtonBorderStyle}" Margin="10,0,0,0"><Button x:Name="SendButton" Style="{StaticResource SendButtonStyle}"Content="发送" Click="SendButton_Click" IsEnabled="True"/></Border></Grid></Grid></Viewbox>
</Window>

        1.4 、消息类

        设计这个是为了对消息类对API的信息进行存入和处理

 public enum MessageType{Question,Answer}public class ChatMessage{public static double DefaultBorderWidth { get; set; } = 300;public string Role { get; set; }public string Content { get; set; }public string WrappedContent { get; set; }public double BorderWidth { get; set; } = DefaultBorderWidth;public Brush BackgroundColor { get; set; }public Brush TextColor { get; set; }public DateTime Timestamp { get; set; }    public MessageType MessageType { get; set; }public ChatMessage(){Role = string.Empty;Content = string.Empty;WrappedContent = string.Empty;Timestamp = DateTime.Now;BackgroundColor = Brushes.White;TextColor = Brushes.Black;}public ChatMessage(string content, string wrappedContent, double borderWidth) : this(){Content = content;WrappedContent = wrappedContent;BorderWidth = borderWidth;}}

 


        1.5 、设置

        API KEY这里是必须填写的,不填写是无法进行问题的回答

这里是代码

private void SaveButton_Click(object sender, RoutedEventArgs e)
{// 更新用户信息currentUser.Username = UsernameTextBox.Text;currentUser.Password = PasswordBox.Password;currentUser.AiUrl = AiUrlTextBox.Text;currentUser.ModelUrl = ModelUrlTextBox.Text;currentUser.ApiKey = ApiKeyTextBox.Text == "请输入deepseek的API keys" ? string.Empty : ApiKeyTextBox.Text;// 保存语言设置var selectedLanguage = ((ComboBoxItem)LanguageComboBox.SelectedItem).Content.ToString();string languageCode = selectedLanguage == "中文" ? "zh-CN" : "en-US";AppSettings.Instance.DefaultLanguage = languageCode;AppSettings.Instance.SaveLanguageSettings(languageCode);// 保存复制选项设置//AppSettings.Instance.CopyCurrent = CopyCurrentRadio.IsChecked == true;AppSettings.Instance.Save();// 保存到配置文件string configPath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),"AIzhushou","config.json");// 确保目录存在var directoryPath = System.IO.Path.GetDirectoryName(configPath);if (string.IsNullOrEmpty(directoryPath)){throw new InvalidOperationException("无法确定配置文件的目录路径");}System.IO.Directory.CreateDirectory(directoryPath);// 序列化保存string json = Newtonsoft.Json.JsonConvert.SerializeObject(currentUser);System.IO.File.WriteAllText(configPath, json);MessageBox.Show("设置保存成功", "提示", MessageBoxButton.OK, MessageBoxImage.Information);this.Close();
}

 


三、运行图示 


四、总结

  •    实测了windows c#版本和python版本, c#版比python版本的性能更好,可能C#是微软亲儿子原因?
  •    一定用要异步处理,没有什么特别需要
  •    AI里面,deepseek是真的强
  •    如果需要提供协助,可以私信我

写着写着就这么多了,可能不是特别全,不介意费时就看看吧。有时间还会接着更新。


五、下载

        AI助手项目下载


http://www.ppmy.cn/devtools/156366.html

相关文章

携程Android开发面试题及参考答案

在项目中,给别人发的动态点赞功能是如何实现的? 数据库设计:首先要在数据库中为动态表添加一个点赞字段,用于记录点赞数量,同时可能需要一个点赞关系表,记录用户与动态之间的点赞关联,包括点赞时间等信息。界面交互:在 Android 界面上,为点赞按钮设置点击事件监听器。…

202周日复盘(159)本周回顾

1、当日总结。 定价相关内容&#xff0c;学习与思考。 第一性原理&#xff0c;分析游戏成本的构成。 ------------- 2、周总结 大思路&#xff0c;细节设计都有进展&#xff0c;每天都挖坑与加工。 a 学习游戏思想 任天堂游戏研发四大标准&#xff0c;创新&#xff0c;直…

通信易懂唠唠SOME/IP——SOME/IP消息格式

SOME/IP是Scalable service-Oriented MiddlewarE over IP (SOME/IP)的缩写&#xff0c;基于IP的可扩展面向服务的中间件。广泛应用于汽车行业嵌入式通信。 它是基于服务的&#xff0c;服务可以由0个或多个Event,Method,Field组成。 Event是一种单向的数据传输&#xff0c;在数…

登录认证(5):过滤器:Filter

统一拦截 上文我们提到&#xff08;登录认证&#xff08;4&#xff09;&#xff1a;令牌技术&#xff09;&#xff0c;现在大部分项目都使用JWT令牌来进行会话跟踪&#xff0c;来完成登录功能。有了JWT令牌可以标识用户的登录状态&#xff0c;但是完整的登录逻辑如图所示&…

Qt网络相关

“ 所有生而孤独的人&#xff0c;葆有的天真 ” 为了⽀持跨平台, QT对⽹络编程的 API 也进⾏了重新封装。本章会上手一套基于QT的网络通信编写。 UDP Socket 在使用Qt进行网络编程前&#xff0c;需要在Qt项目中的.pro文件里添加对应的网络模块( network ). QT core gui net…

【Redis】主从模式,哨兵,集群

主从复制 单点问题&#xff1a; 在分布式系统中&#xff0c;如果某个服务器程序&#xff0c;只有一个节点&#xff08;也就是一个物理服务器&#xff09;来部署这个服务器程序的话&#xff0c;那么可能会出现以下问题&#xff1a; 1.可用性问题&#xff1a;如果这个机器挂了…

手写单层RNN网络,后续更新

文章目录 1. 原理2. pytorch 源码&#xff0c;只是测试版&#xff0c;后续持续优化 1. 原理 根据如下公式&#xff0c;简单的手写实现单层的RNN神经网络&#xff0c;加强代码功能和对网络的理解能力 2. pytorch 源码&#xff0c;只是测试版&#xff0c;后续持续优化 import…

力扣面试150 长度最小的子数组 滑动窗口

Problem: 209. 长度最小的子数组 参考题解 滑动窗口 class Solution {public int minSubArrayLen(int target, int[] nums) {int n nums.length;int ans n 1;int sum 0; // 子数组元素和int left 0; // 子数组左端点for (int right 0; right < n; right) { // 枚举…