mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-03 01:40:21 +08:00
refactor: 全局适配 ApiFamily/EndpointKind 结构化标识体系
将新的 (ApiFamily, EndpointKind) / `family:kind` 签名体系应用到整个代码库: - API Handlers: 所有 adapter/handler 使用新的签名格式 - Services: provider, model, usage, cache, auth 等服务层适配 - Database: ProviderEndpoint 新增 api_family/endpoint_kind 字段 - Frontend: Provider 管理、Usage 表格等组件适配 - Tests: 更新所有相关测试用例
This commit is contained in:
@@ -10,14 +10,12 @@ from typing import Any
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from src.core.api_format import APIFormat
|
||||
from src.core.exceptions import ProviderNotAvailableException
|
||||
from src.core.logger import logger
|
||||
from src.models.database import ApiKey
|
||||
from src.services.cache.aware_scheduler import CacheAwareScheduler, ProviderCandidate
|
||||
|
||||
|
||||
|
||||
class CandidateResolver:
|
||||
"""
|
||||
候选解析器 - 负责获取和排序可用的 Provider 组合
|
||||
@@ -45,7 +43,7 @@ class CandidateResolver:
|
||||
|
||||
async def fetch_candidates(
|
||||
self,
|
||||
api_format: APIFormat,
|
||||
api_format: str,
|
||||
model_name: str,
|
||||
affinity_key: str,
|
||||
user_api_key: ApiKey | None = None,
|
||||
@@ -78,6 +76,12 @@ class CandidateResolver:
|
||||
provider_batch_size = 20
|
||||
global_model_id: str | None = None
|
||||
|
||||
logger.debug(
|
||||
"[CandidateResolver] fetch_candidates starting: model=%s, api_format=%s",
|
||||
model_name,
|
||||
api_format,
|
||||
)
|
||||
|
||||
while True:
|
||||
candidates, resolved_global_model_id = await self.cache_scheduler.list_all_candidates(
|
||||
db=self.db,
|
||||
@@ -91,6 +95,12 @@ class CandidateResolver:
|
||||
capability_requirements=capability_requirements,
|
||||
)
|
||||
|
||||
logger.debug(
|
||||
"[CandidateResolver] list_all_candidates batch: offset=%d, returned=%d candidates",
|
||||
provider_offset,
|
||||
len(candidates),
|
||||
)
|
||||
|
||||
if resolved_global_model_id and global_model_id is None:
|
||||
global_model_id = resolved_global_model_id
|
||||
|
||||
@@ -100,6 +110,11 @@ class CandidateResolver:
|
||||
all_candidates.extend(candidates)
|
||||
provider_offset += provider_batch_size
|
||||
|
||||
logger.debug(
|
||||
"[CandidateResolver] fetch_candidates completed: total=%d candidates",
|
||||
len(all_candidates),
|
||||
)
|
||||
|
||||
if not all_candidates:
|
||||
logger.error(f" [{request_id}] 没有找到任何可用的 Provider/Endpoint/Key 组合")
|
||||
request_type = "流式" if is_stream else "非流式"
|
||||
@@ -196,7 +211,9 @@ class CandidateResolver:
|
||||
candidate_record_map[(candidate_index, 0)] = record_id
|
||||
else:
|
||||
# max_retries 已从 Endpoint 迁移到 Provider(Endpoint 仍可能保留旧字段用于兼容)
|
||||
max_retries_for_candidate = int(provider.max_retries or 2) if candidate.is_cached else 1
|
||||
max_retries_for_candidate = (
|
||||
int(provider.max_retries or 2) if candidate.is_cached else 1
|
||||
)
|
||||
|
||||
for retry_index in range(max_retries_for_candidate):
|
||||
record_id = str(uuid.uuid4())
|
||||
@@ -226,7 +243,9 @@ class CandidateResolver:
|
||||
)
|
||||
self.db.flush()
|
||||
|
||||
logger.debug(f" [{request_id}] 批量插入完成: {len(candidate_records_to_insert)} 条记录")
|
||||
logger.debug(
|
||||
f" [{request_id}] 批量插入完成: {len(candidate_records_to_insert)} 条记录"
|
||||
)
|
||||
|
||||
return candidate_record_map
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ from typing import Any
|
||||
import httpx
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from src.core.api_format import APIFormat
|
||||
from src.core.api_format.signature import make_signature_key
|
||||
from src.core.exceptions import (
|
||||
ConcurrencyLimitError,
|
||||
ProviderAuthException,
|
||||
@@ -28,7 +28,7 @@ from src.core.logger import logger
|
||||
from src.models.database import Provider, ProviderAPIKey, ProviderEndpoint
|
||||
from src.services.cache.aware_scheduler import CacheAwareScheduler
|
||||
from src.services.health.monitor import health_monitor
|
||||
from src.services.provider.format import normalize_api_format
|
||||
from src.services.provider.format import normalize_endpoint_signature
|
||||
from src.services.rate_limit.adaptive_rpm import get_adaptive_rpm_manager
|
||||
from src.services.rate_limit.detector import RateLimitType, detect_rate_limit_type
|
||||
|
||||
@@ -561,7 +561,7 @@ class ErrorClassifier:
|
||||
endpoint: ProviderEndpoint,
|
||||
key: ProviderAPIKey,
|
||||
affinity_key: str,
|
||||
api_format: str | APIFormat,
|
||||
api_format: str,
|
||||
global_model_id: str,
|
||||
request_id: str | None,
|
||||
captured_key_concurrent: int | None,
|
||||
@@ -618,18 +618,11 @@ class ErrorClassifier:
|
||||
extra_data["error_response"] = error_response_text
|
||||
|
||||
# client_format:用于缓存亲和性/缓存失效(用户视角)
|
||||
client_format_str = (
|
||||
normalize_api_format(api_format).value
|
||||
if isinstance(api_format, (str, APIFormat))
|
||||
else str(api_format)
|
||||
)
|
||||
client_format_str = normalize_endpoint_signature(api_format)
|
||||
# provider_format:用于健康度/熔断 bucket(Provider 真实端点格式)
|
||||
provider_api_format = getattr(endpoint, "api_format", None)
|
||||
provider_format_str = (
|
||||
provider_api_format.value
|
||||
if isinstance(provider_api_format, APIFormat)
|
||||
else str(provider_api_format or client_format_str)
|
||||
).upper()
|
||||
fam = str(getattr(endpoint, "api_family", "")).strip().lower()
|
||||
kind = str(getattr(endpoint, "endpoint_kind", "")).strip().lower()
|
||||
provider_format_str = make_signature_key(fam, kind) if fam and kind else client_format_str
|
||||
|
||||
# 处理客户端请求错误(不应重试,不失效缓存,不记录健康失败)
|
||||
if isinstance(converted_error, UpstreamClientException):
|
||||
@@ -704,7 +697,7 @@ class ErrorClassifier:
|
||||
endpoint: ProviderEndpoint,
|
||||
key: ProviderAPIKey,
|
||||
affinity_key: str,
|
||||
api_format: str | APIFormat,
|
||||
api_format: str,
|
||||
global_model_id: str,
|
||||
captured_key_concurrent: int | None,
|
||||
elapsed_ms: int | None,
|
||||
@@ -737,18 +730,11 @@ class ErrorClassifier:
|
||||
)
|
||||
|
||||
# client_format:用于缓存亲和性/缓存失效(用户视角)
|
||||
client_format_str = (
|
||||
normalize_api_format(api_format).value
|
||||
if isinstance(api_format, (str, APIFormat))
|
||||
else str(api_format)
|
||||
)
|
||||
client_format_str = normalize_endpoint_signature(api_format)
|
||||
# provider_format:用于健康度/熔断 bucket(Provider 真实端点格式)
|
||||
provider_api_format = getattr(endpoint, "api_format", None)
|
||||
provider_format_str = (
|
||||
provider_api_format.value
|
||||
if isinstance(provider_api_format, APIFormat)
|
||||
else str(provider_api_format or client_format_str)
|
||||
).upper()
|
||||
fam = str(getattr(endpoint, "api_family", "")).strip().lower()
|
||||
kind = str(getattr(endpoint, "endpoint_kind", "")).strip().lower()
|
||||
provider_format_str = make_signature_key(fam, kind) if fam and kind else client_format_str
|
||||
|
||||
# 处理限流错误
|
||||
if isinstance(error, ProviderRateLimitException) and key:
|
||||
|
||||
@@ -21,19 +21,16 @@
|
||||
- 本类作为协调者,组合使用上述组件
|
||||
"""
|
||||
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, NoReturn
|
||||
|
||||
from collections.abc import Callable
|
||||
from typing import Any, NoReturn
|
||||
|
||||
import httpx
|
||||
from redis import Redis
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from src.config.settings import config
|
||||
from src.core.api_format import APIFormat
|
||||
from src.core.api_format.conversion.exceptions import FormatConversionError
|
||||
from src.core.error_utils import extract_error_message
|
||||
from src.core.exceptions import (
|
||||
@@ -51,7 +48,7 @@ from src.services.cache.aware_scheduler import (
|
||||
get_cache_aware_scheduler,
|
||||
)
|
||||
from src.services.message.thinking_rectifier import ThinkingRectifier
|
||||
from src.services.provider.format import normalize_api_format
|
||||
from src.services.provider.format import normalize_endpoint_signature
|
||||
from src.services.rate_limit.adaptive_rpm import get_adaptive_rpm_manager
|
||||
from src.services.rate_limit.concurrency_manager import get_concurrency_manager
|
||||
from src.services.request.candidate import RequestCandidateService
|
||||
@@ -172,7 +169,7 @@ class FallbackOrchestrator:
|
||||
|
||||
async def _fetch_all_candidates(
|
||||
self,
|
||||
api_format: APIFormat,
|
||||
api_format: str,
|
||||
model_name: str,
|
||||
affinity_key: str,
|
||||
user_api_key: ApiKey | None = None,
|
||||
@@ -256,7 +253,7 @@ class FallbackOrchestrator:
|
||||
user_api_key: ApiKey,
|
||||
request_func: Callable[..., Any],
|
||||
request_id: str | None,
|
||||
api_format: APIFormat,
|
||||
api_format: str,
|
||||
model_name: str,
|
||||
affinity_key: str,
|
||||
global_model_id: str,
|
||||
@@ -343,8 +340,11 @@ class FallbackOrchestrator:
|
||||
if not config.thinking_rectifier_enabled:
|
||||
logger.info(f" [{request_id}] Thinking 错误:整流器已禁用,终止重试")
|
||||
self._mark_thinking_error_failed(
|
||||
candidate_record_id, converted_error, elapsed_ms,
|
||||
captured_key_concurrent, serializable_extra_data
|
||||
candidate_record_id,
|
||||
converted_error,
|
||||
elapsed_ms,
|
||||
captured_key_concurrent,
|
||||
serializable_extra_data,
|
||||
)
|
||||
raise converted_error
|
||||
|
||||
@@ -352,8 +352,11 @@ class FallbackOrchestrator:
|
||||
if request_body_ref is None:
|
||||
logger.warning(f" [{request_id}] Thinking 错误:无法获取请求体引用,终止重试")
|
||||
self._mark_thinking_error_failed(
|
||||
candidate_record_id, converted_error, elapsed_ms,
|
||||
captured_key_concurrent, serializable_extra_data
|
||||
candidate_record_id,
|
||||
converted_error,
|
||||
elapsed_ms,
|
||||
captured_key_concurrent,
|
||||
serializable_extra_data,
|
||||
)
|
||||
raise converted_error
|
||||
|
||||
@@ -361,8 +364,11 @@ class FallbackOrchestrator:
|
||||
if request_body_ref.get("_rectified", False):
|
||||
logger.warning(f" [{request_id}] Thinking 错误:已整流仍失败,终止重试")
|
||||
self._mark_thinking_error_failed(
|
||||
candidate_record_id, converted_error, elapsed_ms,
|
||||
captured_key_concurrent, {**serializable_extra_data, "rectified": True}
|
||||
candidate_record_id,
|
||||
converted_error,
|
||||
elapsed_ms,
|
||||
captured_key_concurrent,
|
||||
{**serializable_extra_data, "rectified": True},
|
||||
)
|
||||
raise converted_error
|
||||
|
||||
@@ -383,8 +389,11 @@ class FallbackOrchestrator:
|
||||
# 标记当前尝试为失败(整流前的状态)
|
||||
# 注意:整流后重试会复用此记录 ID,成功时会覆盖为 success 状态
|
||||
self._mark_thinking_error_failed(
|
||||
candidate_record_id, converted_error, elapsed_ms,
|
||||
captured_key_concurrent, {**serializable_extra_data, "rectified": True}
|
||||
candidate_record_id,
|
||||
converted_error,
|
||||
elapsed_ms,
|
||||
captured_key_concurrent,
|
||||
{**serializable_extra_data, "rectified": True},
|
||||
)
|
||||
|
||||
# 返回 continue:在当前候选的重试循环中继续,使用整流后的请求体重试
|
||||
@@ -392,8 +401,11 @@ class FallbackOrchestrator:
|
||||
else:
|
||||
logger.warning(f" [{request_id}] Thinking 错误:无可整流内容")
|
||||
self._mark_thinking_error_failed(
|
||||
candidate_record_id, converted_error, elapsed_ms,
|
||||
captured_key_concurrent, serializable_extra_data
|
||||
candidate_record_id,
|
||||
converted_error,
|
||||
elapsed_ms,
|
||||
captured_key_concurrent,
|
||||
serializable_extra_data,
|
||||
)
|
||||
raise converted_error
|
||||
|
||||
@@ -425,7 +437,7 @@ class FallbackOrchestrator:
|
||||
retry_index: int,
|
||||
max_retries_for_candidate: int,
|
||||
affinity_key: str,
|
||||
api_format: APIFormat,
|
||||
api_format: str,
|
||||
global_model_id: str,
|
||||
request_id: str | None,
|
||||
attempt: int,
|
||||
@@ -506,9 +518,7 @@ class FallbackOrchestrator:
|
||||
"provider_id": str(provider.id),
|
||||
"provider_endpoint_id": str(endpoint.id),
|
||||
"provider_api_key_id": str(key.id),
|
||||
"api_format": (
|
||||
api_format.value if hasattr(api_format, "value") else str(api_format)
|
||||
),
|
||||
"api_format": str(api_format),
|
||||
}
|
||||
raise client_error
|
||||
else:
|
||||
@@ -588,9 +598,7 @@ class FallbackOrchestrator:
|
||||
"provider_id": str(provider.id),
|
||||
"provider_endpoint_id": str(endpoint.id),
|
||||
"provider_api_key_id": str(key.id),
|
||||
"api_format": (
|
||||
api_format.value if hasattr(api_format, "value") else str(api_format)
|
||||
),
|
||||
"api_format": str(api_format),
|
||||
}
|
||||
raise converted_error
|
||||
|
||||
@@ -662,7 +670,7 @@ class FallbackOrchestrator:
|
||||
user_api_key: ApiKey,
|
||||
model_name: str,
|
||||
is_stream: bool,
|
||||
api_format_enum: APIFormat,
|
||||
api_format: str,
|
||||
) -> None:
|
||||
"""创建 pending 状态的使用记录(用于实时状态追踪)"""
|
||||
if not request_id:
|
||||
@@ -681,7 +689,7 @@ class FallbackOrchestrator:
|
||||
api_key=user_api_key,
|
||||
model=model_name,
|
||||
is_stream=is_stream,
|
||||
api_format=api_format_enum.value,
|
||||
api_format=api_format,
|
||||
)
|
||||
except Exception as e:
|
||||
# 创建 pending 记录失败不应阻塞请求
|
||||
@@ -694,7 +702,7 @@ class FallbackOrchestrator:
|
||||
user_api_key: ApiKey,
|
||||
request_func: Callable[..., Any],
|
||||
request_id: str | None,
|
||||
api_format_enum: APIFormat,
|
||||
api_format: str,
|
||||
model_name: str,
|
||||
affinity_key: str,
|
||||
global_model_id: str,
|
||||
@@ -724,7 +732,7 @@ class FallbackOrchestrator:
|
||||
user_api_key=user_api_key,
|
||||
request_func=request_func,
|
||||
request_id=request_id,
|
||||
api_format_enum=api_format_enum,
|
||||
api_format=api_format,
|
||||
model_name=model_name,
|
||||
affinity_key=affinity_key,
|
||||
global_model_id=global_model_id,
|
||||
@@ -735,9 +743,9 @@ class FallbackOrchestrator:
|
||||
)
|
||||
|
||||
if result["success"]:
|
||||
response: tuple[
|
||||
Any, str, str | None, str | None, str | None, str | None
|
||||
] = result["response"]
|
||||
response: tuple[Any, str, str | None, str | None, str | None, str | None] = result[
|
||||
"response"
|
||||
]
|
||||
return response
|
||||
|
||||
# 更新计数器和错误信息
|
||||
@@ -746,14 +754,12 @@ class FallbackOrchestrator:
|
||||
if result.get("error"):
|
||||
last_error = result["error"]
|
||||
if result.get("should_raise") and last_error is not None:
|
||||
self._attach_metadata_to_error(
|
||||
last_error, last_candidate, model_name, api_format_enum
|
||||
)
|
||||
self._attach_metadata_to_error(last_error, last_candidate, model_name, api_format)
|
||||
raise last_error
|
||||
|
||||
# 所有组合都已尝试完毕,全部失败
|
||||
self._raise_all_failed_exception(
|
||||
request_id, max_attempts, last_candidate, model_name, api_format_enum, last_error
|
||||
request_id, max_attempts, last_candidate, model_name, api_format, last_error
|
||||
)
|
||||
|
||||
async def _try_candidate_with_retries(
|
||||
@@ -764,7 +770,7 @@ class FallbackOrchestrator:
|
||||
user_api_key: ApiKey,
|
||||
request_func: Callable[..., Any],
|
||||
request_id: str | None,
|
||||
api_format_enum: APIFormat,
|
||||
api_format: str,
|
||||
model_name: str,
|
||||
affinity_key: str,
|
||||
global_model_id: str,
|
||||
@@ -820,7 +826,7 @@ class FallbackOrchestrator:
|
||||
user_api_key=user_api_key,
|
||||
request_func=request_func,
|
||||
request_id=request_id,
|
||||
api_format=api_format_enum,
|
||||
api_format=api_format,
|
||||
model_name=model_name,
|
||||
affinity_key=affinity_key,
|
||||
global_model_id=global_model_id,
|
||||
@@ -839,7 +845,7 @@ class FallbackOrchestrator:
|
||||
retry_index=retry_index,
|
||||
max_retries_for_candidate=max_retries_for_candidate,
|
||||
affinity_key=affinity_key,
|
||||
api_format=api_format_enum,
|
||||
api_format=api_format,
|
||||
global_model_id=global_model_id,
|
||||
request_id=request_id,
|
||||
attempt=attempt_counter,
|
||||
@@ -886,7 +892,7 @@ class FallbackOrchestrator:
|
||||
error: Exception | None,
|
||||
candidate: ProviderCandidate | None,
|
||||
model_name: str,
|
||||
api_format_enum: APIFormat,
|
||||
api_format: str,
|
||||
) -> None:
|
||||
"""附加 candidate 信息到异常,以便记录 usage"""
|
||||
if not error or not candidate:
|
||||
@@ -915,7 +921,7 @@ class FallbackOrchestrator:
|
||||
provider_api_key_id=(
|
||||
getattr(existing_metadata, "provider_api_key_id", None) or str(candidate.key.id)
|
||||
),
|
||||
api_format=api_format_enum.value,
|
||||
api_format=api_format,
|
||||
)
|
||||
# 使用 setattr 避免类型检查错误
|
||||
setattr(error, "request_metadata", metadata)
|
||||
@@ -926,7 +932,7 @@ class FallbackOrchestrator:
|
||||
max_attempts: int,
|
||||
last_candidate: ProviderCandidate | None,
|
||||
model_name: str,
|
||||
api_format_enum: APIFormat,
|
||||
api_format: str,
|
||||
last_error: Exception | None = None,
|
||||
) -> NoReturn:
|
||||
"""所有组合都失败时抛出异常"""
|
||||
@@ -940,7 +946,7 @@ class FallbackOrchestrator:
|
||||
"provider_id": str(last_candidate.provider.id),
|
||||
"provider_endpoint_id": str(last_candidate.endpoint.id),
|
||||
"provider_api_key_id": str(last_candidate.key.id),
|
||||
"api_format": api_format_enum.value,
|
||||
"api_format": api_format,
|
||||
}
|
||||
|
||||
# 提取上游错误响应
|
||||
@@ -988,7 +994,7 @@ class FallbackOrchestrator:
|
||||
|
||||
async def execute_with_fallback(
|
||||
self,
|
||||
api_format: str | APIFormat,
|
||||
api_format: str,
|
||||
model_name: str,
|
||||
user_api_key: ApiKey,
|
||||
request_func: Callable[[Provider, ProviderEndpoint, ProviderAPIKey], Any],
|
||||
@@ -1002,7 +1008,7 @@ class FallbackOrchestrator:
|
||||
执行请求,并在失败时自动故障转移(缓存感知)
|
||||
|
||||
Args:
|
||||
api_format: API 格式(如 'CLAUDE', 'OPENAI')
|
||||
api_format: endpoint signature(如 'claude:chat', 'openai:cli')
|
||||
model_name: 模型名称
|
||||
user_api_key: 用户的 API Key对象
|
||||
request_func: 请求函数,接收 (provider, endpoint, key) 参数,返回响应
|
||||
@@ -1023,22 +1029,22 @@ class FallbackOrchestrator:
|
||||
# 准备执行上下文
|
||||
affinity_key = str(user_api_key.id)
|
||||
user_id = str(user_api_key.user_id)
|
||||
api_format_enum = normalize_api_format(api_format)
|
||||
api_format_norm = normalize_endpoint_signature(api_format)
|
||||
|
||||
logger.debug(
|
||||
f"[FallbackOrchestrator] execute_with_fallback 被调用: "
|
||||
f"api_format={api_format_enum.value}, model_name={model_name}, "
|
||||
f"api_format={api_format_norm}, model_name={model_name}, "
|
||||
f"request_id={request_id}, is_stream={is_stream}"
|
||||
)
|
||||
|
||||
# 创建 pending 状态的使用记录
|
||||
self._create_pending_usage_record(
|
||||
request_id, user_api_key, model_name, is_stream, api_format_enum
|
||||
request_id, user_api_key, model_name, is_stream, api_format_norm
|
||||
)
|
||||
|
||||
# 1. 收集所有候选(同时获取规范化的 global_model_id 用于缓存亲和性)
|
||||
all_candidates, global_model_id = await self._fetch_all_candidates(
|
||||
api_format=api_format_enum,
|
||||
api_format=api_format_norm,
|
||||
model_name=model_name,
|
||||
affinity_key=affinity_key,
|
||||
user_api_key=user_api_key,
|
||||
@@ -1064,7 +1070,7 @@ class FallbackOrchestrator:
|
||||
user_api_key=user_api_key,
|
||||
request_func=request_func,
|
||||
request_id=request_id,
|
||||
api_format_enum=api_format_enum,
|
||||
api_format=api_format_norm,
|
||||
model_name=model_name,
|
||||
affinity_key=affinity_key,
|
||||
global_model_id=global_model_id,
|
||||
|
||||
@@ -4,13 +4,11 @@
|
||||
负责执行单个候选请求
|
||||
"""
|
||||
|
||||
from typing import Any
|
||||
|
||||
from collections.abc import Callable
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from src.core.api_format import APIFormat
|
||||
from src.core.logger import logger
|
||||
from src.models.database import ApiKey
|
||||
from src.services.cache.aware_scheduler import CacheAwareScheduler, ProviderCandidate
|
||||
@@ -18,7 +16,6 @@ from src.services.request.candidate import RequestCandidateService
|
||||
from src.services.request.executor import RequestExecutor
|
||||
|
||||
|
||||
|
||||
class RequestDispatcher:
|
||||
"""
|
||||
请求分发器 - 负责执行单个候选请求
|
||||
@@ -56,7 +53,7 @@ class RequestDispatcher:
|
||||
user_api_key: ApiKey,
|
||||
request_func: Callable[..., Any],
|
||||
request_id: str | None,
|
||||
api_format: APIFormat,
|
||||
api_format: str,
|
||||
model_name: str,
|
||||
affinity_key: str,
|
||||
global_model_id: str,
|
||||
@@ -133,15 +130,12 @@ class RequestDispatcher:
|
||||
# 设置缓存亲和性
|
||||
if provider_supports_caching and self.cache_scheduler is not None:
|
||||
try:
|
||||
api_format_str = (
|
||||
api_format.value if isinstance(api_format, APIFormat) else api_format
|
||||
)
|
||||
await self.cache_scheduler.set_cache_affinity(
|
||||
affinity_key=affinity_key,
|
||||
provider_id=provider_id,
|
||||
endpoint_id=endpoint_id,
|
||||
key_id=key_id,
|
||||
api_format=api_format_str,
|
||||
api_format=api_format,
|
||||
global_model_id=global_model_id,
|
||||
ttl=provider_cache_ttl_seconds,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user