mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2025-12-14 21:52:56 +08:00
- 【重构】LLM 服务核心架构:
- 引入中间件管道,统一处理请求生命周期(重试、密钥选择、日志、网络请求)。
- 适配器重构为组件化设计,分离配置映射、消息转换、响应解析和工具序列化逻辑。
- 移除 `with_smart_retry` 装饰器,其功能由中间件接管。
- 移除 `LLMToolExecutor`,工具执行逻辑集成到 `ToolInvoker`。
- 【功能】增强配置系统:
- `LLMGenerationConfig` 采用组件化结构(Core, Reasoning, Visual, Output, Safety, ToolConfig)。
- 新增 `GenConfigBuilder` 提供语义化配置构建方式。
- 新增 `LLMEmbeddingConfig` 用于嵌入专用配置。
- `CommonOverrides` 迁移并更新至新配置结构。
- 【功能】强化工具系统:
- 引入 `ToolInvoker` 实现更灵活的工具执行,支持回调与结构化错误。
- `function_tool` 装饰器支持动态 Pydantic 模型创建和依赖注入 (`ToolParam`, `RunContext`)。
- 平台原生工具支持 (`GeminiCodeExecution`, `GeminiGoogleSearch`, `GeminiUrlContext`)。
- 【功能】高级生成与嵌入:
- `generate_structured` 方法支持 In-Context Validation and Repair (IVR) 循环和 AutoCoT (思维链) 包装。
- 新增 `embed_query` 和 `embed_documents` 便捷嵌入 API。
- `OpenAIImageAdapter` 支持 OpenAI 兼容的图像生成。
- `SmartAdapter` 实现模型名称智能路由。
- 【重构】消息与类型系统:
- `LLMContentPart` 扩展支持更多模态和代码执行相关内容。
- `LLMMessage` 和 `LLMResponse` 结构更新,支持 `content_parts` 和思维链签名。
- 统一 `LLMErrorCode` 和用户友好错误消息,提供更详细的网络/代理错误提示。
- `pyproject.toml` 移除 `bilireq`,新增 `json_repair`。
- 【优化】日志与调试:
- 引入 `DebugLogOptions`,提供细粒度日志脱敏控制。
- 增强日志净化器,处理更多敏感数据和长字符串。
- 【清理】删除废弃模块:
- `zhenxun/services/llm/memory.py`
- `zhenxun/services/llm/executor.py`
- `zhenxun/services/llm/config/presets.py`
- `zhenxun/services/llm/types/content.py`
- `zhenxun/services/llm/types/enums.py`
- `zhenxun/services/llm/tools/__init__.py`
- `zhenxun/services/llm/tools/manager.py`
150 lines
3.9 KiB
Python
150 lines
3.9 KiB
Python
"""
|
|
Pydantic V1 & V2 兼容层模块
|
|
|
|
为 Pydantic V1 与 V2 版本提供统一的便捷函数与类,
|
|
包括 model_dump, model_copy, model_json_schema, parse_as 等。
|
|
"""
|
|
|
|
from datetime import datetime
|
|
from enum import Enum
|
|
from pathlib import Path
|
|
from typing import Any, TypeVar, get_args, get_origin
|
|
|
|
from nonebot.compat import (
|
|
PYDANTIC_V2,
|
|
model_dump,
|
|
model_fields,
|
|
type_validate_json,
|
|
type_validate_python,
|
|
)
|
|
from pydantic import BaseModel
|
|
import ujson as json
|
|
|
|
T = TypeVar("T", bound=BaseModel)
|
|
V = TypeVar("V")
|
|
|
|
|
|
__all__ = [
|
|
"PYDANTIC_V2",
|
|
"_dump_pydantic_obj",
|
|
"_is_pydantic_type",
|
|
"compat_computed_field",
|
|
"dump_json_safely",
|
|
"model_construct",
|
|
"model_copy",
|
|
"model_dump",
|
|
"model_dump_json",
|
|
"model_fields",
|
|
"model_json_schema",
|
|
"model_validate",
|
|
"parse_as",
|
|
"type_validate_json",
|
|
"type_validate_python",
|
|
]
|
|
|
|
|
|
def model_copy(
|
|
model: T, *, update: dict[str, Any] | None = None, deep: bool = False
|
|
) -> T:
|
|
"""
|
|
Pydantic `model.copy()` (v1) 和 `model.model_copy()` (v2) 的兼容函数。
|
|
"""
|
|
if PYDANTIC_V2:
|
|
return model.model_copy(update=update, deep=deep)
|
|
else:
|
|
update_dict = update or {}
|
|
return model.copy(update=update_dict, deep=deep)
|
|
|
|
|
|
def model_construct(model_class: type[T], **kwargs: Any) -> T:
|
|
"""
|
|
Pydantic `model_construct` (v2) 与 `construct` (v1) 的兼容函数。
|
|
"""
|
|
if PYDANTIC_V2:
|
|
return model_class.model_construct(**kwargs)
|
|
else:
|
|
return model_class.construct(**kwargs)
|
|
|
|
|
|
def model_validate(model_class: type[T], obj: Any) -> T:
|
|
"""
|
|
Pydantic 模型验证兼容函数。
|
|
"""
|
|
return type_validate_python(model_class, obj)
|
|
|
|
|
|
def model_dump_json(model: BaseModel, **kwargs: Any) -> str:
|
|
"""
|
|
Pydantic `model.json()` (v1) 和 `model.model_dump_json()` (v2) 的兼容函数。
|
|
"""
|
|
if PYDANTIC_V2:
|
|
return model.model_dump_json(**kwargs)
|
|
return model.json(**kwargs)
|
|
|
|
|
|
if PYDANTIC_V2:
|
|
from pydantic import computed_field as compat_computed_field
|
|
else:
|
|
compat_computed_field = property
|
|
|
|
|
|
def model_json_schema(model_class: type[BaseModel], **kwargs: Any) -> dict[str, Any]:
|
|
"""
|
|
Pydantic `Model.schema()` (v1) 和 `Model.model_json_schema()` (v2) 的兼容函数。
|
|
"""
|
|
if PYDANTIC_V2:
|
|
return model_class.model_json_schema(**kwargs)
|
|
return model_class.schema(by_alias=kwargs.get("by_alias", True))
|
|
|
|
|
|
def _is_pydantic_type(t: Any) -> bool:
|
|
"""
|
|
递归检查一个类型注解是否与 Pydantic BaseModel 相关。
|
|
"""
|
|
if t is None:
|
|
return False
|
|
origin = get_origin(t)
|
|
if origin:
|
|
return any(_is_pydantic_type(arg) for arg in get_args(t))
|
|
return isinstance(t, type) and issubclass(t, BaseModel)
|
|
|
|
|
|
def _dump_pydantic_obj(obj: Any) -> Any:
|
|
"""
|
|
递归地将一个对象内部的 Pydantic BaseModel 实例转换为字典。
|
|
支持单个实例、实例列表、实例字典等情况。
|
|
"""
|
|
if isinstance(obj, BaseModel):
|
|
return model_dump(obj)
|
|
if isinstance(obj, list):
|
|
return [_dump_pydantic_obj(item) for item in obj]
|
|
if isinstance(obj, dict):
|
|
return {key: _dump_pydantic_obj(value) for key, value in obj.items()}
|
|
return obj
|
|
|
|
|
|
parse_as = type_validate_python
|
|
|
|
|
|
def dump_json_safely(obj: Any, **kwargs) -> str:
|
|
"""
|
|
安全地将可能包含 Pydantic 特定类型 (如 Enum) 的对象序列化为 JSON 字符串。
|
|
"""
|
|
|
|
def default_serializer(o):
|
|
if isinstance(o, Enum):
|
|
return o.value
|
|
if isinstance(o, datetime):
|
|
return o.isoformat()
|
|
if isinstance(o, Path):
|
|
return str(o.as_posix())
|
|
if isinstance(o, set):
|
|
return list(o)
|
|
if isinstance(o, BaseModel):
|
|
return model_dump(o)
|
|
raise TypeError(
|
|
f"Object of type {o.__class__.__name__} is not JSON serializable"
|
|
)
|
|
|
|
return json.dumps(obj, default=default_serializer, **kwargs)
|