|
|
@@ -3843,9 +3843,10 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
|
|
|
private function resolveGptUpstreamError(\Exception $e)
|
|
|
{
|
|
|
// 同一个异常对象可能被内层与外层 catch 多次解析,而流式响应体只能读取一次,这里缓存解析结果
|
|
|
+ // 同时持有异常对象引用:spl_object_id 在对象回收后会被复用,仅凭 id 取值可能串到其他异常的数据
|
|
|
$cacheKey = spl_object_id($e);
|
|
|
- if (isset($this->gpt_upstream_error_cache[$cacheKey])) {
|
|
|
- return $this->gpt_upstream_error_cache[$cacheKey];
|
|
|
+ if (isset($this->gpt_upstream_error_cache[$cacheKey]) && $this->gpt_upstream_error_cache[$cacheKey]['exception'] === $e) {
|
|
|
+ return $this->gpt_upstream_error_cache[$cacheKey]['detail'];
|
|
|
}
|
|
|
|
|
|
$detail = [
|
|
|
@@ -3856,7 +3857,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
|
|
|
];
|
|
|
|
|
|
if (!($e instanceof \GuzzleHttp\Exception\BadResponseException) || !$e->getResponse()) {
|
|
|
- $this->gpt_upstream_error_cache[$cacheKey] = $detail;
|
|
|
+ $this->gpt_upstream_error_cache[$cacheKey] = ['exception' => $e, 'detail' => $detail];
|
|
|
return $detail;
|
|
|
}
|
|
|
|
|
|
@@ -3874,7 +3875,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
|
|
|
}
|
|
|
|
|
|
if ($content === '') {
|
|
|
- $this->gpt_upstream_error_cache[$cacheKey] = $detail;
|
|
|
+ $this->gpt_upstream_error_cache[$cacheKey] = ['exception' => $e, 'detail' => $detail];
|
|
|
return $detail;
|
|
|
}
|
|
|
|
|
|
@@ -3884,10 +3885,11 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
|
|
|
$decoded_error = is_array($decoded) ? getProp($decoded, 'error') : null;
|
|
|
if (is_array($decoded_error)) {
|
|
|
$detail['code'] = (string)getProp($decoded_error, 'code', '');
|
|
|
- $detail['message'] = (string)getProp($decoded_error, 'message', '');
|
|
|
+ // 上游 message 可能超长,截断后再用于模型翻译与展示,避免把整段报错送进模型
|
|
|
+ $detail['message'] = mb_substr((string)getProp($decoded_error, 'message', ''), 0, 1000);
|
|
|
}
|
|
|
|
|
|
- $this->gpt_upstream_error_cache[$cacheKey] = $detail;
|
|
|
+ $this->gpt_upstream_error_cache[$cacheKey] = ['exception' => $e, 'detail' => $detail];
|
|
|
return $detail;
|
|
|
}
|
|
|
|
|
|
@@ -3908,10 +3910,23 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
|
|
|
return '本集内容被上游模型的内容安全策略拦截,请调整剧本中过于血腥、暴力等敏感描述后重试,或改用其他模型';
|
|
|
}
|
|
|
|
|
|
+ // 其他上游报错复用全局错误映射(已知签名本地命中;未命中时由模型翻译并缓存)
|
|
|
if ($message !== '') {
|
|
|
+ $mapped = mapErrorMessage($message);
|
|
|
+ if ($mapped !== '' && $mapped !== '未知异常,请重试') {
|
|
|
+ return $mapped;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 映射不可用时保留上游原文,便于排查
|
|
|
return '上游模型返回错误(' . $status . '):' . mb_substr($message, 0, 300);
|
|
|
}
|
|
|
|
|
|
+ // 拿不到上游报文时,仅传输层异常(连接失败、超时等)交给全局映射兜底
|
|
|
+ if ($e instanceof \GuzzleHttp\Exception\GuzzleException) {
|
|
|
+ return mapErrorMessage($e->getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 业务异常(如参数校验)保持原有文案,避免被模型翻译后丢失关键信息
|
|
|
return '处理请求时发生异常: ' . $e->getMessage();
|
|
|
}
|
|
|
|