Coverage for src / local_deep_research / advanced_search_system / constraint_checking / base_constraint_checker.py: 59%
37 statements
« prev ^ index » next coverage.py v7.12.0, created at 2026-01-11 00:51 +0000
« prev ^ index » next coverage.py v7.12.0, created at 2026-01-11 00:51 +0000
1"""
2Base constraint checker for inheritance-based constraint checking system.
4This module provides the base interface and common functionality for
5constraint checking implementations.
6"""
8from abc import ABC, abstractmethod
9from dataclasses import dataclass
10from typing import Dict, List, Optional, Tuple
12from langchain_core.language_models import BaseChatModel
13from loguru import logger
15from ..candidates.base_candidate import Candidate
16from ..constraints.base_constraint import Constraint
19@dataclass
20class ConstraintCheckResult:
21 """Result of checking a candidate against all constraints."""
23 candidate: Candidate
24 total_score: float
25 constraint_scores: Dict[str, Dict]
26 should_reject: bool
27 rejection_reason: Optional[str]
28 detailed_results: List[Dict]
31class BaseConstraintChecker(ABC):
32 """
33 Base class for constraint checking implementations.
35 This provides the common interface and shared functionality that
36 all constraint checkers should implement.
37 """
39 def __init__(
40 self,
41 model: BaseChatModel,
42 evidence_gatherer=None, # Will be passed in from strategy
43 **kwargs,
44 ):
45 """
46 Initialize the base constraint checker.
48 Args:
49 model: Language model for evidence analysis
50 evidence_gatherer: Function to gather evidence (from strategy)
51 **kwargs: Additional parameters for specific implementations
52 """
53 self.model = model
54 self.evidence_gatherer = evidence_gatherer
56 @abstractmethod
57 def check_candidate(
58 self, candidate: Candidate, constraints: List[Constraint]
59 ) -> ConstraintCheckResult:
60 """
61 Check a candidate against all constraints.
63 Args:
64 candidate: The candidate to check
65 constraints: List of constraints to check against
67 Returns:
68 ConstraintCheckResult: Complete evaluation result
69 """
70 pass
72 @abstractmethod
73 def should_reject_candidate(
74 self, candidate: Candidate, constraint: Constraint, evidence_data: any
75 ) -> Tuple[bool, str]:
76 """
77 Determine if a candidate should be rejected for a specific constraint.
79 Args:
80 candidate: The candidate being evaluated
81 constraint: The constraint being checked
82 evidence_data: Evidence data (format depends on implementation)
84 Returns:
85 Tuple[bool, str]: (should_reject, reason)
86 """
87 pass
89 def _gather_evidence_for_constraint(
90 self, candidate: Candidate, constraint: Constraint
91 ) -> List[Dict]:
92 """Gather evidence for a constraint using the provided evidence gatherer."""
93 if self.evidence_gatherer:
94 return self.evidence_gatherer(candidate, constraint)
95 else:
96 logger.warning(
97 "No evidence gatherer provided - cannot gather evidence"
98 )
99 return []
101 def _log_constraint_result(
102 self,
103 candidate: Candidate,
104 constraint: Constraint,
105 score: float,
106 details: Dict,
107 ):
108 """Log constraint evaluation result."""
109 symbol = "✓" if score >= 0.8 else "○" if score >= 0.5 else "✗"
110 logger.info(
111 f"{symbol} {candidate.name} | {constraint.value}: {int(score * 100)}%"
112 )
114 def _calculate_weighted_score(
115 self, constraint_scores: List[float], weights: List[float]
116 ) -> float:
117 """Calculate weighted average score."""
118 if not constraint_scores or not weights:
119 return 0.0
120 return sum(
121 s * w for s, w in zip(constraint_scores, weights, strict=False)
122 ) / sum(weights)