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:
@@ -147,11 +147,11 @@ static $OJ_MENU_NEWS=true;
|
|||||||
|
|
||||||
/* LLM AI Review - AI错误点评功能 */
|
/* LLM AI Review - AI错误点评功能 */
|
||||||
static $OJ_LLM_ENABLED=false; // 总开关,设为true开启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_URL="https://api.minimaxi.com/anthropic/v1/messages"; // API地址(MiniMax Anthropic兼容格式)
|
||||||
static $OJ_LLM_API_KEY=""; // 填入你的API Key
|
static $OJ_LLM_API_KEY="sk-cp-w571CJpA_6WP5P6b_xGVbjOqXOGBWTQsiNY9xxAPambouIhD7ic3GHIoWce0ON_Y7Q0rVLzBWtgwwS8cQVUxS1guBxYkPJoJ33q0jEcx0Qei60bx5La4fB4"; // 填入你的MiniMax API Key
|
||||||
static $OJ_LLM_MODEL="gpt-4o-mini"; // 模型名称
|
static $OJ_LLM_MODEL="MiniMax-M2.7"; // 模型名称,如 MiniMax-M2.7 / MiniMax-M2.5 / MiniMax-M2.5-highspeed
|
||||||
static $OJ_LLM_MAX_TOKENS=1024; // 最大输出token数
|
static $OJ_LLM_MAX_TOKENS=65536; // 最大输出token数
|
||||||
static $OJ_LLM_TIMEOUT=30; // 请求超时(秒)
|
static $OJ_LLM_TIMEOUT=60; // 请求超时(秒),LLM响应较慢建议60秒
|
||||||
static $OJ_LLM_SYSTEM_PROMPT=""; // 自定义系统prompt,留空使用内置默认
|
static $OJ_LLM_SYSTEM_PROMPT=""; // 自定义系统prompt,留空使用内置默认
|
||||||
|
|
||||||
require_once(dirname(__FILE__) . "/pdo.php");
|
require_once(dirname(__FILE__) . "/pdo.php");
|
||||||
|
|||||||
@@ -140,25 +140,26 @@ if (!empty($reference_code)) {
|
|||||||
$user_prompt .= "\n请分析学生的错误,给出启发性的提示和引导,帮助学生自己发现问题并改正。\n";
|
$user_prompt .= "\n请分析学生的错误,给出启发性的提示和引导,帮助学生自己发现问题并改正。\n";
|
||||||
|
|
||||||
// ---- 8. 调用 LLM API ----
|
// ---- 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 : "";
|
$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;
|
$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)) {
|
if (empty($api_key)) {
|
||||||
echo json_encode(["error" => "API Key未配置"], JSON_UNESCAPED_UNICODE);
|
echo json_encode(["error" => "API Key未配置"], JSON_UNESCAPED_UNICODE);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---- Anthropic API 兼容格式 ----
|
||||||
$request_body = json_encode([
|
$request_body = json_encode([
|
||||||
"model" => $model,
|
"model" => $model,
|
||||||
"messages" => [
|
|
||||||
["role" => "system", "content" => $system_prompt],
|
|
||||||
["role" => "user", "content" => $user_prompt]
|
|
||||||
],
|
|
||||||
"max_tokens" => $max_tokens,
|
"max_tokens" => $max_tokens,
|
||||||
"temperature" => 0.7
|
"system" => $system_prompt,
|
||||||
|
"temperature" => 1.0,
|
||||||
|
"messages" => [
|
||||||
|
["role" => "user", "content" => $user_prompt]
|
||||||
|
]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$ch = curl_init($api_url);
|
$ch = curl_init($api_url);
|
||||||
@@ -167,7 +168,8 @@ curl_setopt_array($ch, [
|
|||||||
CURLOPT_POSTFIELDS => $request_body,
|
CURLOPT_POSTFIELDS => $request_body,
|
||||||
CURLOPT_HTTPHEADER => [
|
CURLOPT_HTTPHEADER => [
|
||||||
"Content-Type: application/json",
|
"Content-Type: application/json",
|
||||||
"Authorization: Bearer " . $api_key
|
"x-api-key: " . $api_key,
|
||||||
|
"anthropic-version: 2023-06-01"
|
||||||
],
|
],
|
||||||
CURLOPT_RETURNTRANSFER => true,
|
CURLOPT_RETURNTRANSFER => true,
|
||||||
CURLOPT_TIMEOUT => $timeout,
|
CURLOPT_TIMEOUT => $timeout,
|
||||||
@@ -190,13 +192,20 @@ if ($http_code !== 200) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$resp_data = json_decode($response, true);
|
$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);
|
echo json_encode(["error" => "API返回格式异常"], JSON_UNESCAPED_UNICODE);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
$review_text = $resp_data['choices'][0]['message']['content'];
|
|
||||||
|
|
||||||
// ---- 9. 缓存结果 ----
|
// ---- 9. 缓存结果 ----
|
||||||
// 自动建表(首次调用时)
|
// 自动建表(首次调用时)
|
||||||
pdo_query("CREATE TABLE IF NOT EXISTS `llm_review` (
|
pdo_query("CREATE TABLE IF NOT EXISTS `llm_review` (
|
||||||
|
|||||||
Reference in New Issue
Block a user