Add: Return outlier deals in analysis responses
Feature: - New parameter `include_outlier_deals` (default=True) in: - filter_deals_for_analysis() - calculate_deal_statistics() - get_valuation_comparables() MCP tool - get_deal_statistics() MCP tool Behavior: - When ON: response includes `outlier_deals` field with removed deals - LLM can see what was filtered out, answer questions about it - Maintains full transparency on outlier removal Terminology fixed: - "outlier_deals" = deals removed as outliers (clearer than "filtered_deals") - "filtered deals" = deals that PASSED filtering - Added to OutlierReport model All 311 tests pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -874,7 +874,10 @@ class GovmapClient:
|
||||
|
||||
# Statistics methods (delegate to statistics module)
|
||||
def calculate_deal_statistics(
|
||||
self, deals: List[Deal], iqr_multiplier: Optional[float] = None
|
||||
self,
|
||||
deals: List[Deal],
|
||||
iqr_multiplier: Optional[float] = None,
|
||||
include_outlier_deals: bool = True,
|
||||
) -> DealStatistics:
|
||||
"""
|
||||
Calculate statistical aggregations on deal data.
|
||||
@@ -884,11 +887,14 @@ class GovmapClient:
|
||||
Args:
|
||||
deals: List of Deal model instances
|
||||
iqr_multiplier: Override IQR multiplier for outlier detection (optional)
|
||||
include_outlier_deals: If True (default), include removed outliers in report
|
||||
|
||||
Returns:
|
||||
DealStatistics model with comprehensive metrics
|
||||
"""
|
||||
return statistics.calculate_deal_statistics(deals, iqr_multiplier=iqr_multiplier)
|
||||
return statistics.calculate_deal_statistics(
|
||||
deals, iqr_multiplier=iqr_multiplier, include_outlier_deals=include_outlier_deals
|
||||
)
|
||||
|
||||
def _calculate_std_dev(self, values: List[float]) -> float:
|
||||
"""
|
||||
|
||||
@@ -196,6 +196,7 @@ class OutlierReport(BaseModel):
|
||||
outlier_indices: Indices of removed deals in original list
|
||||
method_used: Outlier detection method ("iqr", "percent", "none")
|
||||
parameters: Configuration parameters used for detection
|
||||
filtered_deals: The actual deals that were filtered out (optional)
|
||||
"""
|
||||
|
||||
total_deals: int = Field(..., description="Total deals before filtering")
|
||||
@@ -205,6 +206,9 @@ class OutlierReport(BaseModel):
|
||||
parameters: Dict[str, Any] = Field(
|
||||
default_factory=dict, description="Detection parameters used"
|
||||
)
|
||||
outlier_deals: Optional[List["Deal"]] = Field(
|
||||
None, description="Deals that were removed as outliers (if requested)"
|
||||
)
|
||||
|
||||
|
||||
class DealStatistics(BaseModel):
|
||||
|
||||
@@ -177,6 +177,7 @@ def filter_deals_for_analysis(
|
||||
config: Optional[GovmapConfig] = None,
|
||||
metric: str = "price_per_sqm",
|
||||
iqr_multiplier: Optional[float] = None,
|
||||
include_outlier_deals: bool = True,
|
||||
) -> Tuple[List[Deal], Dict[str, Any]]:
|
||||
"""
|
||||
Filter deals to remove outliers based on configuration.
|
||||
@@ -196,11 +197,13 @@ def filter_deals_for_analysis(
|
||||
metric: Which metric to apply statistical outlier detection to
|
||||
Options: "price_per_sqm", "deal_amount"
|
||||
iqr_multiplier: Override IQR multiplier (optional, uses config value if not provided)
|
||||
include_outlier_deals: If True, include the removed outlier deals in the report
|
||||
(default: True, allows LLM to see what was filtered out)
|
||||
|
||||
Returns:
|
||||
Tuple of:
|
||||
- Filtered list of deals
|
||||
- Outlier report dict with details on what was filtered
|
||||
- Filtered list of deals (deals that PASSED filtering)
|
||||
- Outlier report dict with details on what was filtered out (includes outlier_deals if requested)
|
||||
"""
|
||||
if config is None:
|
||||
config = get_config()
|
||||
@@ -333,6 +336,7 @@ def filter_deals_for_analysis(
|
||||
# Filter deals
|
||||
filtered_deals = [deal for i, deal in enumerate(deals) if not filters_to_remove[i]]
|
||||
outlier_indices = [i for i, should_remove in enumerate(filters_to_remove) if should_remove]
|
||||
outlier_deals = [deal for i, deal in enumerate(deals) if filters_to_remove[i]]
|
||||
|
||||
# Create outlier report
|
||||
report = {
|
||||
@@ -357,4 +361,8 @@ def filter_deals_for_analysis(
|
||||
},
|
||||
}
|
||||
|
||||
# Include outlier deals if requested
|
||||
if include_outlier_deals and outlier_deals:
|
||||
report["outlier_deals"] = outlier_deals
|
||||
|
||||
return filtered_deals, report
|
||||
|
||||
@@ -152,7 +152,10 @@ def _calculate_basic_stats(deals: List[Deal]) -> Dict:
|
||||
|
||||
|
||||
def calculate_deal_statistics(
|
||||
deals: List[Deal], config: Optional[GovmapConfig] = None, iqr_multiplier: Optional[float] = None
|
||||
deals: List[Deal],
|
||||
config: Optional[GovmapConfig] = None,
|
||||
iqr_multiplier: Optional[float] = None,
|
||||
include_outlier_deals: bool = True,
|
||||
) -> DealStatistics:
|
||||
"""
|
||||
Calculate statistical aggregations on deal data with optional outlier filtering.
|
||||
@@ -165,12 +168,14 @@ def calculate_deal_statistics(
|
||||
deals: List of Deal model instances
|
||||
config: Configuration object (optional, uses global config if not provided)
|
||||
iqr_multiplier: Override IQR multiplier (optional, uses config value if not provided)
|
||||
include_outlier_deals: If True (default), include the removed outlier deals in the outlier report
|
||||
This allows LLMs to see what was filtered out
|
||||
|
||||
Returns:
|
||||
DealStatistics model with comprehensive metrics, including:
|
||||
- Original statistics (calculated on all deals)
|
||||
- Filtered statistics (calculated after outlier removal, if enabled)
|
||||
- Outlier report (details on what was filtered, if enabled)
|
||||
- Outlier report (details on what was filtered out, including outlier_deals if requested)
|
||||
|
||||
Raises:
|
||||
ValueError: If deals is not a valid list
|
||||
@@ -204,7 +209,11 @@ def calculate_deal_statistics(
|
||||
):
|
||||
# Filter deals for analysis (primarily targeting price_per_sqm outliers)
|
||||
filtered_deals, report_dict = filter_deals_for_analysis(
|
||||
deals, config, metric="price_per_sqm", iqr_multiplier=iqr_multiplier
|
||||
deals,
|
||||
config,
|
||||
metric="price_per_sqm",
|
||||
iqr_multiplier=iqr_multiplier,
|
||||
include_outlier_deals=include_outlier_deals,
|
||||
)
|
||||
|
||||
# Create OutlierReport model
|
||||
|
||||
Reference in New Issue
Block a user