Download apps/documents/services/placeholders/context_builder.py from jun2024/fc: direct link, hf CLI and curl.
- Browser
- Download file 7.79 kB
-
https://huggingface.co/spaces/jun2024/fc/resolve/main/apps/documents/services/placeholders/context_builder.py
- Command line
-
hf download hf://spaces/jun2024/fc/apps/documents/services/placeholders/context_builder.py
-
curl -L -o context_builder.py https://huggingface.co/spaces/jun2024/fc/resolve/main/apps/documents/services/placeholders/context_builder.py
7.79 kB
| """Business logic services.""" | |
| from __future__ import annotations | |
| import logging | |
| from typing import Any | |
| from django.utils.translation import gettext_lazy as _ | |
| from apps.core.exceptions import ValidationException | |
| from .fallback import ( | |
| PLACEHOLDER_FALLBACK_VALUE, | |
| ensure_required_placeholders, | |
| get_service_placeholder_keys, | |
| normalize_service_result, | |
| ) | |
| from .registry import PlaceholderRegistry | |
| from .types import PlaceholderContextData | |
| logger = logging.getLogger(__name__) | |
| class EnhancedContextBuilder: | |
| """增强的上下文构建器""" | |
| def __init__(self, registry: PlaceholderRegistry | None = None) -> None: | |
| """ | |
| 初始化上下文构建器 | |
| Args: | |
| registry: 占位符注册表实例,如果为 None 则使用默认实例 | |
| """ | |
| self.registry = registry or PlaceholderRegistry() | |
| def build_context( | |
| self, context_data: PlaceholderContextData, required_placeholders: list[str] | None = None | |
| ) -> dict[str, Any]: | |
| """ | |
| 构建完整的替换词上下文 | |
| Args: | |
| context_data: 原始数据(contract, clients 等) | |
| required_placeholders: 可选,仅生成指定的占位符 | |
| Returns: | |
| 完整的占位符上下文字典 | |
| """ | |
| if not context_data: | |
| logger.warning("上下文数据为空") | |
| return {} | |
| context_data = self._normalize_context_data(context_data) | |
| context: dict[str, Any] = {} | |
| services = self._get_relevant_services(required_placeholders) | |
| for service in services: | |
| service_keys = get_service_placeholder_keys(service) | |
| try: | |
| service_result = service.generate(context_data) | |
| normalized_result = normalize_service_result(service_result, expected_keys=service_keys) | |
| if normalized_result: | |
| context.update(normalized_result) | |
| logger.debug("服务 %s 生成了 %s 个占位符", service.name, len(normalized_result)) | |
| except Exception as e: | |
| logger.error( | |
| "占位符服务执行失败: %s", | |
| service.name, | |
| extra={ | |
| "service_name": service.name, | |
| "error": str(e), | |
| "context_keys": list(context_data.keys()), | |
| }, | |
| exc_info=True, | |
| ) | |
| context.update(dict.fromkeys(service_keys, PLACEHOLDER_FALLBACK_VALUE)) | |
| # 继续执行其他服务,不中断整个流程 | |
| continue | |
| if context_data.get("supplementary_agreement"): | |
| key_map = { | |
| "补充协议委托人信息": "委托人信息", | |
| "补充协议委托人签名盖章信息": "委托人签名盖章信息", | |
| "补充协议委托人主体信息条款": "委托人主体信息条款", | |
| "补充协议委托人数量": "委托人数量", | |
| "补充协议对方当事人主体信息条款": "对方当事人主体信息条款", | |
| } | |
| for old_key, new_key in key_map.items(): | |
| if old_key in context: | |
| context[new_key] = context[old_key] | |
| final_context = ensure_required_placeholders(context, required_placeholders) | |
| logger.info("上下文构建完成,生成了 %s 个占位符", len(final_context)) | |
| return final_context | |
| def _normalize_context_data(self, context_data: PlaceholderContextData) -> PlaceholderContextData: | |
| """标准化上下文,对常见缺失键进行兜底补全.""" | |
| normalized: dict[str, Any] = dict(context_data) | |
| if normalized.get("case_id") is None: | |
| case_obj = normalized.get("case") | |
| case_id = getattr(case_obj, "id", None) | |
| if case_id is not None: | |
| normalized["case_id"] = case_id | |
| return normalized | |
| def build_contract_context(self, contract_id: int) -> dict[str, Any]: | |
| """ | |
| 为合同构建上下文(便捷方法) | |
| Args: | |
| contract_id: 合同 ID | |
| Returns: | |
| 完整的占位符上下文字典 | |
| Raises: | |
| ValidationException: 合同不存在或数据无效 | |
| """ | |
| try: | |
| # 验证合同存在性 | |
| # Requirements: 3.2 | |
| from apps.documents.services.infrastructure.wiring import get_contract_service | |
| contract_service = get_contract_service() | |
| contract_dto = contract_service.get_contract_internal(contract_id) | |
| if not contract_dto: | |
| raise ValidationException( | |
| message=_("合同不存在"), | |
| code="CONTRACT_NOT_FOUND", | |
| errors={"contract_id": f"ID 为 {contract_id} 的合同不存在"}, | |
| ) | |
| contract = contract_service.get_contract_model_internal(contract_id) | |
| if not contract: | |
| raise ValidationException( | |
| message=_("合同不存在"), | |
| code="CONTRACT_NOT_FOUND", | |
| errors={"contract_id": f"ID 为 {contract_id} 的合同不存在"}, | |
| ) | |
| # 构建上下文数据 | |
| context_data: PlaceholderContextData = {"contract": contract, "contract_id": contract_id} | |
| return self.build_context(context_data) | |
| except Exception as e: | |
| if isinstance(e, ValidationException): | |
| raise | |
| logger.error("构建合同上下文失败: %s", e, extra={"contract_id": contract_id}, exc_info=True) | |
| raise ValidationException( | |
| message=_("构建合同上下文失败"), | |
| code="CONTEXT_BUILD_ERROR", | |
| errors={"contract_id": f"合同 {contract_id} 上下文构建失败: {e!s}"}, | |
| ) from e | |
| def _get_relevant_services(self, required_placeholders: list[str] | None = None) -> Any: | |
| """ | |
| 获取相关的占位符服务 | |
| Args: required_placeholders: 需要的占位符键列表 | |
| Returns: | |
| 相关的服务实例列表 | |
| """ | |
| if not required_placeholders: | |
| # 如果没有指定占位符,返回所有服务 | |
| return self.registry.get_all_services() | |
| # 根据占位符键查找相关服务 | |
| relevant_services: list[Any] = [] | |
| for placeholder_key in required_placeholders: | |
| service = self.registry.get_service_for_placeholder(placeholder_key) | |
| if service and service not in relevant_services: | |
| relevant_services.append(service) | |
| return relevant_services | |
| def get_available_placeholders(self) -> dict[str, list[str]]: | |
| """ | |
| 获取所有可用的占位符按分类分组 | |
| Returns: | |
| 按分类分组的占位符字典 | |
| """ | |
| result: dict[str, Any] = {} | |
| services = self.registry.get_all_services() | |
| for service in services: | |
| category = service.category | |
| if category not in result: | |
| result[category] = [] | |
| result[category].extend(service.get_placeholder_keys()) | |
| return result | |
| def validate_placeholders(self, placeholder_keys: list[str]) -> dict[str, bool]: | |
| """ | |
| 验证占位符键是否可用 | |
| Args: | |
| placeholder_keys: 要验证的占位符键列表 | |
| Returns: | |
| 占位符键的可用性字典 | |
| """ | |
| result: dict[str, Any] = {} | |
| for key in placeholder_keys: | |
| service = self.registry.get_service_for_placeholder(key) | |
| result[key] = service is not None | |
| return result | |