You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

66 lines
1.8 KiB

  1. import 'dart:convert';
  2. import 'dart:io';
  3. class Deepseek {
  4. final String apiKey;
  5. Deepseek({required this.apiKey});
  6. Stream<String> chat(String prompt) async* {
  7. final client = HttpClient();
  8. try {
  9. final request = await client
  10. .postUrl(Uri.parse('https://api.deepseek.com/chat/completions'));
  11. // 设置流式请求头
  12. request.headers
  13. ..set('Content-Type', 'application/json')
  14. ..set('Authorization', 'Bearer $apiKey')
  15. ..set('Accept', 'text/event-stream');
  16. // 构建请求体
  17. final requestBody = jsonEncode({
  18. 'model': 'deepseek-chat',
  19. 'stream': true,
  20. 'messages': [
  21. {'role': 'user', 'content': prompt}
  22. ]
  23. });
  24. // 写入请求体
  25. request.add(utf8.encode(requestBody));
  26. final response = await request.close();
  27. // 检查状态码
  28. if (response.statusCode != 200) {
  29. throw Exception('API请求失败: ${response.statusCode}');
  30. }
  31. // 处理流数据
  32. String buffer = '';
  33. await for (final chunk in response.transform(utf8.decoder)) {
  34. buffer += chunk;
  35. // 分割完整事件(假设使用SSE格式)
  36. while (buffer.contains('\n\n')) {
  37. final eventEnd = buffer.indexOf('\n\n');
  38. final event = buffer.substring(0, eventEnd);
  39. buffer = buffer.substring(eventEnd + 2);
  40. if (event.startsWith('data: ')) {
  41. final dataContent = event.substring(6);
  42. // 增加有效性检查
  43. if (dataContent == '[DONE]') {
  44. // print('流式传输结束');
  45. continue; // 跳过特殊结束标记
  46. }
  47. final jsonData = jsonDecode(event.substring(6));
  48. yield jsonData['choices'][0]['delta']['content'];
  49. }
  50. }
  51. }
  52. } finally {
  53. client.close();
  54. }
  55. }
  56. }