deploy: auto commit server changes 2026-06-11 18:41:54
This commit is contained in:
@@ -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结果
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user