修改OpenAI原格式的转发逻辑和参数

This commit is contained in:
2025-11-23 18:17:00 +08:00
parent 5875ffe671
commit 8019b24b61
3 changed files with 89 additions and 44 deletions
+50 -18
View File
@@ -9,6 +9,7 @@ using LMS.Repository.Model;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Net;
using System.Net.Http.Headers;
using System.Text;
@@ -238,15 +239,16 @@ public class ForwardWordService(ApplicationDbContext context, IHttpClientFactory
#endregion
#region OpenAI
public async Task<HttpResponseMessage> ForwardWordStreamRaw(ForwardModel request)
public async Task<HttpResponseMessage> ForwardWordStreamRaw(ForwardModelOpenAI request)
{
// --- 1. 基础校验 (保持原有逻辑) ---
if (string.IsNullOrEmpty(request.Word)) throw new Exception("参数错误");
if (string.IsNullOrWhiteSpace(request.OpenAIBodyString))
{
throw new Exception("OpenAIBodyString 不能为空");
}
if (string.IsNullOrEmpty(request.GptUrl)) throw new Exception("请求的url为空");
var allowedUrls = new[] {
"https://ark.cn-beijing.volces.com",
"https://api.moonshot.cn",
"https://laitool.net",
"https://api.laitool.cc",
"https://laitool.cc",
@@ -266,6 +268,24 @@ public class ForwardWordService(ApplicationDbContext context, IHttpClientFactory
throw new Exception("机器码不存在或已过期");
}
// ================= 2. JSON 结构解析与校验 =================
JObject jsonBody;
try
{
jsonBody = JObject.Parse(request.OpenAIBodyString);
}
catch (JsonReaderException)
{
throw new Exception("OpenAIBodyString 不是有效的 JSON 格式");
}
// 检查 messages 是否存在且为数组
var messages = jsonBody["messages"] as JArray;
if (messages == null || messages.Count == 0)
{
throw new Exception("请求体结构错误: 缺少 'messages' 数组");
}
// --- 2. 获取提示词预设 (保持原有逻辑) ---
Prompt? prompt = await _context.Prompt.FirstOrDefaultAsync(x => x.PromptTypeId == request.PromptTypeId && x.Id == request.PromptId);
if (prompt == null)
@@ -273,23 +293,35 @@ public class ForwardWordService(ApplicationDbContext context, IHttpClientFactory
throw new Exception("FindPromptStringFail"); // 建议使用具体错误码
}
// --- 3. 手动构建 OpenAI 格式的请求体 ---
// SDK 帮你做了这一步,现在我们要自己做,以便获得原始流
var payload = new
// ================= 4. 替换逻辑 (System) =================
// 遍历寻找 role 为 system 的消息
var systemMsg = messages.FirstOrDefault(m => m["role"]?.ToString() == "system");
if (systemMsg != null)
{
model = request.Model,
messages = new List<object>
// 没有数据 默认为 "{{SYSTEM}}"
var content = systemMsg["content"]?.ToString() ?? "{{SYSTEM}}";
// 检查是否包含占位符 "{{SYSTEM}}"
if (content.Contains("{{SYSTEM}}"))
{
// 替换占位符为真实的 promptString
systemMsg["content"] = content.Replace("{{SYSTEM}}", prompt.PromptString);
}
}
else
{
new { role = "system", content = prompt.PromptString },
new { role = "user", content = request.Word }
},
stream = true, // 必须开启流式
// max_tokens = 2000, // 如果有需要可以加其他参数
// temperature = 0.7
};
throw new Exception("缺少 system 消息节点");
}
var jsonContent = JsonConvert.SerializeObject(payload, new JsonSerializerSettings { ContractResolver = new LowercaseContractResolver() });
var httpContent = new StringContent(jsonContent, Encoding.UTF8, "application/json");
// ================= 5. 强制修正关键字段 =================
// 强制使用 C# 模型类中指定的 Model,或者校验两者是否一致 (这里选择覆盖,以 C# 参数为准)
jsonBody["model"] = request.Model;
// 强制开启流式
jsonBody["stream"] = true;
var finalJsonContent = jsonBody.ToString(Formatting.None);
//var jsonContent = JsonConvert.SerializeObject(finalJsonContent, new JsonSerializerSettings { ContractResolver = new LowercaseContractResolver() });
var httpContent = new StringContent(finalJsonContent, Encoding.UTF8, "application/json");
// --- 4. 发起 HTTP 请求 ---
var client = _httpClientFactory.CreateClient(); // 或者直接 new HttpClient();