LMS.service/LMS.service/Service/ForwardWordService.cs

284 lines
11 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using LMS.DAO;
using LMS.Repository.DB;
using LMS.Repository.Forward;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using static LMS.Common.Enums.ResponseCodeEnum;
using System.Net;
using System.Text;
using LMS.Repository.Model;
using Betalgo.Ranul.OpenAI.Managers;
using Betalgo.Ranul.OpenAI;
using Betalgo.Ranul.OpenAI.ObjectModels.RequestModels;
using LMS.Common.Extensions;
namespace LMS.service.Service;
public class ForwardWordService(ApplicationDbContext context)
{
private readonly ApplicationDbContext _context = context;
#region
/// <summary>
/// 转发OpenAi格式的请求 非流
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<ActionResult<APIResponseModel<object>>> ForwardWord(ForwardModel request)
{
try
{
// 要校验机器码,但是目前不需要
if (request.Word == null || request.Word == "")
{
return APIResponseModel<object>.CreateErrorResponseModel(ResponseCode.ParameterError);
}
// 获取提示词预设
Prompt? prompt = await _context.Prompt.FirstOrDefaultAsync(x => x.PromptTypeId == request.PromptTypeId && x.Id == request.PromptId);
if (prompt == null)
{
return APIResponseModel<object>.CreateErrorResponseModel(ResponseCode.FindPromptStringFail);
}
// 开始拼接请求体
using HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + request.ApiKey);
string json = JsonConvert.SerializeObject(new
{
model = request.Model,
temperature = 0.3,
messages = new List<OpenAI.RequestMessage>
{
new OpenAI.RequestMessage
{
role = "system",
content = prompt.PromptString
},
new OpenAI.RequestMessage
{
role = "user",
content = request.Word
}
}
});
// 判断请求的url是不是满足条件
if (string.IsNullOrEmpty(request.GptUrl))
{
throw new Exception("请求的url为空");
}
if (!request.GptUrl.StartsWith("https://ark.cn-beijing.volces.com") && !request.GptUrl.StartsWith("https://api.moonshot.cn") && !request.GptUrl.StartsWith("https://laitool.net") && !request.GptUrl.StartsWith("https://api.laitool.cc") && !request.GptUrl.StartsWith("https://laitool.cc"))
{
throw new Exception("请求的url不合法");
}
client.Timeout = Timeout.InfiniteTimeSpan;
var response = await client.PostAsync(request.GptUrl, new StringContent(json, Encoding.UTF8, "application/json"));
// 判断返回的状态码
if (response.StatusCode != HttpStatusCode.OK)
{
// 读取响应体
string responseContent = await response.Content.ReadAsStringAsync();
return APIResponseModel<object>.CreateErrorResponseModel(ResponseCode.ForwardWordFail, responseContent, "请求失败");
}
var content = await response.Content.ReadAsStringAsync();
// 序列化一下
return APIResponseModel<object>.CreateSuccessResponseModel(content);
}
catch (Exception e)
{
return APIResponseModel<object>.CreateErrorResponseModel(ResponseCode.SystemError, e.Message);
}
}
#endregion
#region
/// <summary>
/// 流式转发
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public async IAsyncEnumerable<string> ForwardWordStream(ForwardModel request)
{
// 要校验机器码,但是目前不需要
if (request.Word == null || request.Word == "")
{
throw new Exception("参数错误");
}
// 判断请求的url是不是满足条件
if (string.IsNullOrEmpty(request.GptUrl))
{
throw new Exception("请求的url为空");
}
if (!request.GptUrl.StartsWith("https://ark.cn-beijing.volces.com") && !request.GptUrl.StartsWith("https://api.moonshot.cn") && !request.GptUrl.StartsWith("https://laitool.net") && !request.GptUrl.StartsWith("https://api.laitool.cc") && !request.GptUrl.StartsWith("https://laitool.cc"))
{
throw new Exception("请求的url不合法");
}
// 获取提示词预设
Prompt? prompt = await _context.Prompt.FirstOrDefaultAsync(x => x.PromptTypeId == request.PromptTypeId && x.Id == request.PromptId);
if (prompt == null)
{
throw new Exception(ResponseCode.FindPromptStringFail.GetResult());
}
var openAiService = new OpenAIService(new OpenAIOptions()
{
ApiKey = request.ApiKey,
BaseDomain = request.GptUrl,
});
var completionResult = openAiService.ChatCompletion.CreateCompletionAsStream(new ChatCompletionCreateRequest
{
Messages = new List<ChatMessage>
{
ChatMessage.FromSystem(prompt.PromptString),
ChatMessage.FromUser(request.Word)
},
Model = request.Model,
Stream = true
});
await foreach (var completion in completionResult)
{
if (completion.Successful)
{ // 这边只返回数据,不返回全部的数据结构了
yield return completion.Choices.First().Message.Content ?? "";
}
else
{
if (completion.Error == null)
{
throw new Exception("Unknown Error");
}
throw new Exception($"{completion.Error.Code}: {completion.Error.Message}");
}
}
}
#endregion
#region Post
/// <summary>
/// 简单的转发接口
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<ActionResult<APIResponseModel<object>>> SimpleTransfer(SimpleTransferModel request)
{
try
{
// 开始拼接请求体
using HttpClient client = new();
if (request.url.StartsWith("https://api.laitool.net"))
{
//client.DefaultRequestHeaders.Add("Authorization", "Bearer " + request.APIKey);
client.DefaultRequestHeaders.Add("mj-api-secret", request.APIKey);
}
else
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + request.APIKey);
}
// 判断请求的url是不是满足条件
if (string.IsNullOrEmpty(request.url))
{
throw new Exception("请求的url为空");
}
if (!request.url.StartsWith("https://ark.cn-beijing.volces.com")
&& !request.url.StartsWith("https://api.moonshot.cn")
&& !request.url.StartsWith("https://laitool.net")
&& !request.url.StartsWith("https://api.laitool.net")
&& !request.url.StartsWith("https://api.laitool.cc")
&& !request.url.StartsWith("https://laitool.cc"))
{
throw new Exception("请求的url不支持转发");
}
client.Timeout = Timeout.InfiniteTimeSpan;
var response = await client.PostAsync(request.url, new StringContent(request.dataString, Encoding.UTF8, "application/json"));
// 判断返回的状态码
if (response.StatusCode != HttpStatusCode.OK && response.StatusCode != HttpStatusCode.Created)
{
if (response.StatusCode == HttpStatusCode.Unauthorized)
{
return APIResponseModel<object>.CreateErrorResponseModel(ResponseCode.ForwardWordFail, "responseCode: 401", "请求失败");
}
// 读取响应体
string responseContent = await response.Content.ReadAsStringAsync();
return APIResponseModel<object>.CreateErrorResponseModel(ResponseCode.ForwardWordFail, responseContent, "请求失败");
}
var content = await response.Content.ReadAsStringAsync();
return APIResponseModel<object>.CreateSuccessResponseModel(content);
}
catch (Exception e)
{
return APIResponseModel<object>.CreateErrorResponseModel(ResponseCode.SystemError, e.Message);
}
}
#endregion
#region Get直接转发接口
internal async Task<ActionResult<APIResponseModel<object>>> GetTransfer(GetTransferModel getTransferModel)
{
try
{
// 开始拼接请求体
using HttpClient client = new();
if (getTransferModel.url.StartsWith("https://api.laitool.net"))
{
client.DefaultRequestHeaders.Add("mj-api-secret", getTransferModel.APIKey);
}
else
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + getTransferModel.APIKey);
}
// 判断请求的url是不是满足条件
if (string.IsNullOrEmpty(getTransferModel.url))
{
throw new Exception("请求的url为空");
}
if (!getTransferModel.url.StartsWith("https://ark.cn-beijing.volces.com")
&& !getTransferModel.url.StartsWith("https://api.moonshot.cn")
&& !getTransferModel.url.StartsWith("https://laitool.net")
&& !getTransferModel.url.StartsWith("https://api.laitool.net")
&& !getTransferModel.url.StartsWith("https://api.laitool.cc")
&& !getTransferModel.url.StartsWith("https://laitool.cc"))
{
throw new Exception("请求的url不支持转发");
}
client.Timeout = Timeout.InfiniteTimeSpan;
var response = await client.GetAsync(getTransferModel.url);
// 判断返回的状态码
if (response.StatusCode != HttpStatusCode.OK && response.StatusCode != HttpStatusCode.Created)
{
// 读取响应体
string responseContent = await response.Content.ReadAsStringAsync();
return APIResponseModel<object>.CreateErrorResponseModel(ResponseCode.ForwardWordFail, responseContent, "请求失败");
}
var content = await response.Content.ReadAsStringAsync();
// 序列化一下
return APIResponseModel<object>.CreateSuccessResponseModel(content);
}
catch (Exception e)
{
return APIResponseModel<object>.CreateErrorResponseModel(ResponseCode.SystemError, e.Message);
}
}
#endregion
}