共计 5676 个字符,预计需要花费 15 分钟才能阅读完成。
背景痛点
Web 版 ChatGPT 虽然功能强大,但在 Windows 环境下存在诸多不便:

- 缺乏系统级集成 :无法接收后台通知,每次对话都需要主动打开浏览器
- 历史记录管理薄弱 :对话数据存储在云端,无法离线查看或快速检索
- 功能扩展受限 :难以调用本地硬件(如麦克风)或系统 API(如文件操作)
- 性能依赖网络 :每次请求都需要完整的网络往返,响应速度受制于服务器状态
技术选型
WPF vs WinForms vs WinUI 3
- WPF:
- 成熟稳定,但设计理念较旧
- 高性能渲染,但现代功能支持有限
-
适合需要复杂数据绑定的传统应用
-
WinForms:
- 开发速度快,但界面定制能力弱
- 简单的拖拽式设计,但难以实现复杂交互
-
适合快速原型开发
-
WinUI 3(推荐选择):
- 微软最新 UI 框架,原生支持 Fluent Design
- 更好的性能优化和现代功能支持
- 与 Windows 11 深度集成,长期维护有保障
核心实现
API 异步调用实现
public class OpenAIService
{
private readonly HttpClient _httpClient;
private readonly string _apiKey;
public OpenAIService(string apiKey)
{_httpClient = new HttpClient();
_apiKey = apiKey;
}
public async Task<string> GetCompletionAsync(string prompt, CancellationToken cancellationToken)
{var request = new HttpRequestMessage(HttpMethod.Post, "https://api.openai.com/v1/completions");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _apiKey);
var requestBody = new
{
model = "text-davinci-003",
prompt,
max_tokens = 150
};
request.Content = new StringContent(JsonSerializer.Serialize(requestBody), Encoding.UTF8, "application/json");
var response = await _httpClient.SendAsync(request, cancellationToken);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();}
}
MVVM 模式集成
public class ChatViewModel : INotifyPropertyChanged
{
private readonly OpenAIService _openAIService;
private string _currentMessage;
private ObservableCollection<ChatMessage> _messages;
public event PropertyChangedEventHandler PropertyChanged;
public string CurrentMessage
{
get => _currentMessage;
set
{
_currentMessage = value;
OnPropertyChanged();}
}
public ObservableCollection<ChatMessage> Messages
{
get => _messages;
set
{
_messages = value;
OnPropertyChanged();}
}
public ICommand SendCommand {get;}
public ChatViewModel(OpenAIService openAIService)
{
_openAIService = openAIService;
Messages = new ObservableCollection<ChatMessage>();
SendCommand = new RelayCommand(async () => await SendMessageAsync());
}
private async Task SendMessageAsync()
{if (string.IsNullOrWhiteSpace(CurrentMessage)) return;
var userMessage = new ChatMessage {Sender = "You", Content = CurrentMessage};
Messages.Add(userMessage);
CurrentMessage = string.Empty;
try
{var response = await _openAIService.GetCompletionAsync(userMessage.Content, CancellationToken.None);
var botMessage = new ChatMessage {Sender = "AI", Content = response};
Messages.Add(botMessage);
}
catch (Exception ex)
{// 错误处理}
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
本地加密存储
public class SecureStorageService
{
private readonly string _filePath;
private readonly byte[] _encryptionKey;
public SecureStorageService(string filePath, string passphrase)
{
_filePath = filePath;
using var sha256 = SHA256.Create();
_encryptionKey = sha256.ComputeHash(Encoding.UTF8.GetBytes(passphrase));
}
public async Task SaveAsync(string data)
{using var aes = Aes.Create();
aes.Key = _encryptionKey;
using var encryptor = aes.CreateEncryptor();
using var fileStream = new FileStream(_filePath, FileMode.Create);
await using var cryptoStream = new CryptoStream(fileStream, encryptor, CryptoStreamMode.Write);
await using var streamWriter = new StreamWriter(cryptoStream);
await streamWriter.WriteAsync(data);
}
public async Task<string> LoadAsync()
{if (!File.Exists(_filePath)) return null;
using var aes = Aes.Create();
aes.Key = _encryptionKey;
using var fileStream = new FileStream(_filePath, FileMode.Open);
using var decryptor = aes.CreateDecryptor();
await using var cryptoStream = new CryptoStream(fileStream, decryptor, CryptoStreamMode.Read);
using var streamReader = new StreamReader(cryptoStream);
return await streamReader.ReadToEndAsync();}
}
性能优化
响应延迟监控
-
实现请求计时器:
var stopwatch = Stopwatch.StartNew(); var response = await _httpClient.SendAsync(request, cancellationToken); stopwatch.Stop(); LogRequestDuration(stopwatch.ElapsedMilliseconds); -
设置超时限制:
_httpClient.Timeout = TimeSpan.FromSeconds(30); -
实现自动重试机制:
public async Task<string> GetCompletionWithRetryAsync(string prompt, int maxRetries = 3) { int retryCount = 0; while (true) { try {return await GetCompletionAsync(prompt, CancellationToken.None); } catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.TooManyRequests && retryCount < maxRetries) { retryCount++; await Task.Delay(1000 * retryCount); // 指数退避 } } }
本地缓存策略
- 实现对话历史缓存:
public class ChatCache {private readonly List<ChatMessage> _cachedMessages = new(); private readonly int _maxCacheSize = 50; public void AddMessage(ChatMessage message) {_cachedMessages.Add(message); if (_cachedMessages.Count > _maxCacheSize) {_cachedMessages.RemoveAt(0); } } public IEnumerable<ChatMessage> GetRecentMessages(int count = 10) {return _cachedMessages.TakeLast(count); } }
避坑指南
API 密钥安全
- 不要硬编码密钥
-
使用 Windows 凭据管理器:
var credential = new Credential { Target = "ChatGPT_API_Key", Username = "API_Key", Password = "your_api_key_here", Type = CredentialType.Generic }; credential.Save(); -
运行时动态加载:
var credential = Credential.Load("ChatGPT_API_Key"); var apiKey = credential.Password;
上下文长度处理
-
智能截断算法:
public string TruncateToTokenLimit(string text, int maxTokens = 2048) { // 简单实现:按字符数估算 const int avgCharsPerToken = 4; int maxChars = maxTokens * avgCharsPerToken; return text.Length <= maxChars ? text : text[..maxChars] + "..."; } -
分块处理长文本:
public IEnumerable<string> ChunkText(string text, int chunkSize = 1000) {for (int i = 0; i < text.Length; i += chunkSize) {yield return text.Substring(i, Math.Min(chunkSize, text.Length - i)); } }
扩展功能
语音输入集成
- 添加 Windows.Media.SpeechRecognition 引用
- 实现语音识别:
public async Task<string> RecognizeSpeechAsync() {var speechRecognizer = new SpeechRecognizer(); await speechRecognizer.CompileConstraintsAsync(); var result = await speechRecognizer.RecognizeAsync(); return result.Text; }
系统通知
- 使用 Windows.UI.Notifications API
- 创建 Toast 通知:
public void ShowNotification(string title, string message) {var toastContent = new ToastContentBuilder() .AddText(title) .AddText(message) .GetToastContent(); var toast = new ToastNotification(toastContent.GetXml()); ToastNotificationManager.CreateToastNotifier().Show(toast); }
总结
通过 WinUI 3 构建 ChatGPT 客户端,我们实现了比 Web 版本更好的用户体验和系统集成。关键点包括:可靠的 API 调用封装、响应式 UI 设计、数据安全存储和性能优化。未来可以考虑增加插件系统、多账户支持和离线模式等功能扩展。
正文完
发表至: 未分类
近两天内
