deploy: auto commit server changes 2026-06-11 18:41:54

This commit is contained in:
hajimi
2026-06-11 18:41:54 +08:00
parent a6bccbb651
commit 9fb80f951a
81 changed files with 205 additions and 102 deletions
+127 -24
View File
@@ -120,7 +120,86 @@ class DeepSeekClient
? $this->buildResponsesEndpoint($baseUrl)
: $this->buildChatEndpoint($baseUrl);
$timeout = $this->resolveTimeout($options['timeout'] ?? null);
$retryTimes = $this->resolveRetryTimes($options['retry_times'] ?? null);
$retrySleepMs = $this->resolveRetrySleepMs($options['retry_sleep_ms'] ?? null);
$lastResult = null;
for ($attempt = 0; $attempt <= $retryTimes; $attempt++) {
$transport = $this->sendHttpRequest($endpoint, $payload, $apiKey, $timeout);
$response = (string) ($transport['response'] ?? '');
$httpCode = (int) ($transport['http_code'] ?? 0);
$error = (string) ($transport['error'] ?? '');
$costMs = (int) ((microtime(true) - $startTime) * 1000);
if ($error !== '') {
$lastResult = $this->buildFailureResult(
'cURL错误: ' . $error,
$payload,
$providerLabel,
$costMs,
$attempt
);
if ($this->shouldRetry($attempt, $retryTimes, $httpCode, $error)) {
$this->sleepBeforeRetry($attempt, $retrySleepMs);
continue;
}
return $lastResult;
}
$data = json_decode($response, true);
if (!is_array($data)) {
$errMsg = json_last_error() === JSON_ERROR_NONE ? '响应JSON结构异常' : '响应不是有效JSON';
if ($httpCode > 0) {
$errMsg .= '(HTTP ' . $httpCode . ')';
}
$lastResult = $this->buildFailureResult(
$providerLabel . ' 返回异常: ' . $errMsg,
$payload,
$providerLabel,
$costMs,
$attempt
);
if ($this->shouldRetry($attempt, $retryTimes, $httpCode, '')) {
$this->sleepBeforeRetry($attempt, $retrySleepMs);
continue;
}
return $lastResult;
}
$content = $wireApi === 'responses' ? $this->extractResponsesContent($data) : ($data['choices'][0]['message']['content'] ?? '');
if ($httpCode !== 200 || $content === '') {
$errMsg = $data['error']['message'] ?? ('HTTP ' . $httpCode);
$lastResult = $this->buildFailureResult(
$providerLabel . ' 返回异常: ' . $errMsg,
$payload,
$providerLabel,
$costMs,
$attempt
);
if ($this->shouldRetry($attempt, $retryTimes, $httpCode, '')) {
$this->sleepBeforeRetry($attempt, $retrySleepMs);
continue;
}
return $lastResult;
}
$tokens = $data['usage']['total_tokens'] ?? (($data['usage']['input_tokens'] ?? 0) + ($data['usage']['output_tokens'] ?? 0));
return [
'success' => true,
'content' => $content,
'tokens' => $tokens,
'cost_ms' => $costMs,
'model' => $payload['model'],
'provider_label' => $providerLabel,
];
}
return $lastResult ?: ['success' => false, 'error' => $providerLabel . ' 返回异常: 未知错误', 'tokens' => 0, 'cost_ms' => (int) ((microtime(true) - $startTime) * 1000), 'model' => $payload['model'], 'provider_label' => $providerLabel];
}
protected function sendHttpRequest(string $endpoint, array $payload, string $apiKey, int $timeout): array
{
$ch = curl_init($endpoint);
curl_setopt_array($ch, [
CURLOPT_POST => true,
@@ -136,43 +215,55 @@ class DeepSeekClient
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$httpCode = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
$costMs = (int) ((microtime(true) - $startTime) * 1000);
return [
'response' => $response === false ? '' : (string) $response,
'http_code' => $httpCode,
'error' => (string) $error,
];
}
if ($error) {
return ['success' => false, 'error' => 'cURL错误: ' . $error, 'tokens' => 0, 'cost_ms' => $costMs, 'model' => $payload['model'], 'provider_label' => $providerLabel];
protected function buildFailureResult(string $error, array $payload, string $providerLabel, int $costMs, int $attempt): array
{
if ($attempt > 0) {
$error .= ',已重试' . $attempt . '次';
}
$data = json_decode((string) $response, true);
if (!is_array($data)) {
$errMsg = json_last_error() === JSON_ERROR_NONE ? '响应JSON结构异常' : '响应不是有效JSON';
if ($httpCode > 0) {
$errMsg .= '(HTTP ' . $httpCode . ')';
}
return ['success' => false, 'error' => $providerLabel . ' 返回异常: ' . $errMsg, 'tokens' => 0, 'cost_ms' => $costMs, 'model' => $payload['model'], 'provider_label' => $providerLabel];
}
$content = $wireApi === 'responses' ? $this->extractResponsesContent($data) : ($data['choices'][0]['message']['content'] ?? '');
if ($httpCode !== 200 || $content === '') {
$errMsg = $data['error']['message'] ?? ('HTTP ' . $httpCode);
return ['success' => false, 'error' => $providerLabel . ' 返回异常: ' . $errMsg, 'tokens' => 0, 'cost_ms' => $costMs, 'model' => $payload['model'], 'provider_label' => $providerLabel];
}
$tokens = $data['usage']['total_tokens'] ?? (($data['usage']['input_tokens'] ?? 0) + ($data['usage']['output_tokens'] ?? 0));
return [
'success' => true,
'content' => $content,
'tokens' => $tokens,
'success' => false,
'error' => $error,
'tokens' => 0,
'cost_ms' => $costMs,
'model' => $payload['model'],
'provider_label' => $providerLabel,
];
}
protected function shouldRetry(int $attempt, int $retryTimes, int $httpCode, string $curlError): bool
{
if ($attempt >= $retryTimes) {
return false;
}
if ($curlError !== '') {
return true;
}
return $httpCode === 429 || ($httpCode >= 500 && $httpCode <= 599);
}
protected function sleepBeforeRetry(int $attempt, int $sleepMs): void
{
if ($sleepMs <= 0) {
return;
}
usleep($sleepMs * 1000 * max(1, $attempt + 1));
}
protected function buildChatPayload(array $messages, array $options): array
{
return [
@@ -317,6 +408,18 @@ class DeepSeekClient
return max(30, min($value, 300));
}
protected function resolveRetryTimes($retryTimes): int
{
$value = $retryTimes === null ? (int) AiConfig::getVal('ai_request_retry_times', '1') : (int) $retryTimes;
return max(0, min($value, 3));
}
protected function resolveRetrySleepMs($retrySleepMs): int
{
$value = $retrySleepMs === null ? (int) AiConfig::getVal('ai_request_retry_sleep_ms', '600') : (int) $retrySleepMs;
return max(0, min($value, 5000));
}
/**
* 发送请求并解析JSON结果
*/