|
@@ -388,6 +388,94 @@ namespace OASystem.API.OAMethodLib.DeepSeekAPI
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ /// 流式 chat
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ /// <param name="question">问题</param>
|
|
|
|
|
+ /// <param name="model">模型名称</param>
|
|
|
|
|
+ /// <param name="temperature">温度参数</param>
|
|
|
|
|
+ /// <param name="maxTokens">最大token数</param>
|
|
|
|
|
+ /// <returns>聊天响应</returns>
|
|
|
|
|
+ public async IAsyncEnumerable<string> ChatStreamAsync(string question, string model = "deepseek-chat", float temperature = 0.7f, int maxTokens = 4000)
|
|
|
|
|
+ {
|
|
|
|
|
+ var messageContent = new List<object>
|
|
|
|
|
+ {
|
|
|
|
|
+ new { type = "text", text = question }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ var request = new DeepSeekChatWithFilesRequest
|
|
|
|
|
+ {
|
|
|
|
|
+ Model = model,
|
|
|
|
|
+ Messages = new List<FileMessage>
|
|
|
|
|
+ {
|
|
|
|
|
+ new FileMessage
|
|
|
|
|
+ {
|
|
|
|
|
+ Role = "user",
|
|
|
|
|
+ Content = messageContent
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ Stream = true,
|
|
|
|
|
+ Temperature = temperature,
|
|
|
|
|
+ MaxTokens = maxTokens,
|
|
|
|
|
+ TopP = 0.9M,
|
|
|
|
|
+ FrequencyPenalty = 0.2M,
|
|
|
|
|
+ PresencePenalty = 0.1M,
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ var jsonContent = JsonSerializer.Serialize(request, new JsonSerializerOptions
|
|
|
|
|
+ {
|
|
|
|
|
+ PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ _httpClient.Timeout = TimeSpan.FromMinutes(10);
|
|
|
|
|
+
|
|
|
|
|
+ using var requestMsg = new HttpRequestMessage(HttpMethod.Post, "chat/completions")
|
|
|
|
|
+ {
|
|
|
|
|
+ Content = new StringContent(jsonContent, Encoding.UTF8, "application/json")
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ using var response = await _httpClient.SendAsync(requestMsg, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
|
|
|
|
|
+ response.EnsureSuccessStatusCode();
|
|
|
|
|
+
|
|
|
|
|
+ using var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
|
|
|
|
+ using var reader = new StreamReader(responseStream, Encoding.UTF8);
|
|
|
|
|
+
|
|
|
|
|
+ string? line;
|
|
|
|
|
+ while ((line = await reader.ReadLineAsync().ConfigureAwait(false)) != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (string.IsNullOrWhiteSpace(line))
|
|
|
|
|
+ continue;
|
|
|
|
|
+ if (!line.StartsWith("data: ", StringComparison.Ordinal))
|
|
|
|
|
+ continue;
|
|
|
|
|
+
|
|
|
|
|
+ var data = line["data: ".Length..];
|
|
|
|
|
+ if (data == "[DONE]")
|
|
|
|
|
+ yield break;
|
|
|
|
|
+
|
|
|
|
|
+ string? deltaText = null;
|
|
|
|
|
+ try
|
|
|
|
|
+ {
|
|
|
|
|
+ using var jsonDoc = JsonDocument.Parse(data);
|
|
|
|
|
+ if (!jsonDoc.RootElement.TryGetProperty("choices", out var choices) || choices.GetArrayLength() == 0)
|
|
|
|
|
+ continue;
|
|
|
|
|
+ if (!choices[0].TryGetProperty("delta", out var delta))
|
|
|
|
|
+ continue;
|
|
|
|
|
+ if (delta.TryGetProperty("content", out var contentVal))
|
|
|
|
|
+ {
|
|
|
|
|
+ var text = contentVal.GetString();
|
|
|
|
|
+ if (!string.IsNullOrEmpty(text))
|
|
|
|
|
+ deltaText = text;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (System.Text.Json.JsonException)
|
|
|
|
|
+ {
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (deltaText != null)
|
|
|
|
|
+ yield return deltaText;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/// <summary>
|
|
/// <summary>
|
|
|
/// 等待文件处理完成
|
|
/// 等待文件处理完成
|
|
|
/// </summary>
|
|
/// </summary>
|