feat: 切换 AI 点评至 Anthropic 兼容 API(MiniMax)

- 将默认 LLM API 地址改为 MiniMax Anthropic 兼容格式
- 更新默认模型为 MiniMax-M2.7,max_tokens 改为 65536,超时改为 60 秒
- 请求体改为 Anthropic 格式:system prompt 提到顶层,temperature 调整为 1.0
- HTTP 头改用 x-api-key 和 anthropic-version
- 响应解析适配 Anthropic 返回的 content 数组结构
This commit is contained in:
2026-05-29 16:10:50 +08:00
parent b95ede457e
commit d60458ad35
2 changed files with 26 additions and 17 deletions

View File

@@ -147,11 +147,11 @@ static $OJ_MENU_NEWS=true;
/* LLM AI Review - AI错误点评功能 */
static $OJ_LLM_ENABLED=false; // 总开关设为true开启AI点评
static $OJ_LLM_API_URL="https://api.openai.com/v1/chat/completions"; // API地址兼容OpenAI格式)
static $OJ_LLM_API_KEY=""; // 填入你的API Key
static $OJ_LLM_MODEL="gpt-4o-mini"; // 模型名称
static $OJ_LLM_MAX_TOKENS=1024; // 最大输出token数
static $OJ_LLM_TIMEOUT=30; // 请求超时(秒)
static $OJ_LLM_API_URL="https://api.minimaxi.com/anthropic/v1/messages"; // API地址MiniMax Anthropic兼容格式)
static $OJ_LLM_API_KEY="sk-cp-w571CJpA_6WP5P6b_xGVbjOqXOGBWTQsiNY9xxAPambouIhD7ic3GHIoWce0ON_Y7Q0rVLzBWtgwwS8cQVUxS1guBxYkPJoJ33q0jEcx0Qei60bx5La4fB4"; // 填入你的MiniMax API Key
static $OJ_LLM_MODEL="MiniMax-M2.7"; // 模型名称,如 MiniMax-M2.7 / MiniMax-M2.5 / MiniMax-M2.5-highspeed
static $OJ_LLM_MAX_TOKENS=65536; // 最大输出token数
static $OJ_LLM_TIMEOUT=60; // 请求超时(秒)LLM响应较慢建议60秒
static $OJ_LLM_SYSTEM_PROMPT=""; // 自定义系统prompt留空使用内置默认
require_once(dirname(__FILE__) . "/pdo.php");

View File

@@ -140,25 +140,26 @@ if (!empty($reference_code)) {
$user_prompt .= "\n请分析学生的错误,给出启发性的提示和引导,帮助学生自己发现问题并改正。\n";
// ---- 8. 调用 LLM API ----
$api_url = isset($OJ_LLM_API_URL) ? $OJ_LLM_API_URL : "https://api.openai.com/v1/chat/completions";
$api_url = isset($OJ_LLM_API_URL) ? $OJ_LLM_API_URL : "https://api.minimaxi.com/anthropic/v1/messages";
$api_key = isset($OJ_LLM_API_KEY) ? $OJ_LLM_API_KEY : "";
$model = isset($OJ_LLM_MODEL) ? $OJ_LLM_MODEL : "gpt-4o-mini";
$model = isset($OJ_LLM_MODEL) ? $OJ_LLM_MODEL : "MiniMax-M2.5";
$max_tokens = isset($OJ_LLM_MAX_TOKENS) ? intval($OJ_LLM_MAX_TOKENS) : 1024;
$timeout = isset($OJ_LLM_TIMEOUT) ? intval($OJ_LLM_TIMEOUT) : 30;
$timeout = isset($OJ_LLM_TIMEOUT) ? intval($OJ_LLM_TIMEOUT) : 60;
if (empty($api_key)) {
echo json_encode(["error" => "API Key未配置"], JSON_UNESCAPED_UNICODE);
exit;
}
// ---- Anthropic API 兼容格式 ----
$request_body = json_encode([
"model" => $model,
"messages" => [
["role" => "system", "content" => $system_prompt],
["role" => "user", "content" => $user_prompt]
],
"max_tokens" => $max_tokens,
"temperature" => 0.7
"system" => $system_prompt,
"temperature" => 1.0,
"messages" => [
["role" => "user", "content" => $user_prompt]
]
]);
$ch = curl_init($api_url);
@@ -167,7 +168,8 @@ curl_setopt_array($ch, [
CURLOPT_POSTFIELDS => $request_body,
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"Authorization: Bearer " . $api_key
"x-api-key: " . $api_key,
"anthropic-version: 2023-06-01"
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => $timeout,
@@ -190,13 +192,20 @@ if ($http_code !== 200) {
}
$resp_data = json_decode($response, true);
if (!$resp_data || !isset($resp_data['choices'][0]['message']['content'])) {
// Anthropic 响应格式: content 是一个数组,取 type=text 的块
$review_text = "";
if ($resp_data && isset($resp_data['content']) && is_array($resp_data['content'])) {
foreach ($resp_data['content'] as $block) {
if (isset($block['type']) && $block['type'] === 'text' && isset($block['text'])) {
$review_text .= $block['text'];
}
}
}
if (empty($review_text)) {
echo json_encode(["error" => "API返回格式异常"], JSON_UNESCAPED_UNICODE);
exit;
}
$review_text = $resp_data['choices'][0]['message']['content'];
// ---- 9. 缓存结果 ----
// 自动建表(首次调用时)
pdo_query("CREATE TABLE IF NOT EXISTS `llm_review` (