fix: apply A1/A2/A3 to the live services/ copy and ship it in the backend image
backend/routers/analyze.py imports services.* (root package), not backend.services.* - so the earlier A1/A2/A3 edits landed in an unused duplicate. Also COPY/mount services/ so the container can start at all (ModuleNotFoundError: No module named services).
This commit is contained in:
@@ -4,6 +4,7 @@ Integrates geo_service zones and scoring_service rankings.
|
||||
"""
|
||||
import os
|
||||
import json
|
||||
import logging
|
||||
from typing import Dict, List, Optional
|
||||
from pydantic import BaseModel
|
||||
import httpx
|
||||
@@ -11,6 +12,8 @@ import httpx
|
||||
from .geo_service import build_search_zones
|
||||
from .scoring_service import WeightedScorer
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PrimaryZone(BaseModel):
|
||||
priority: int
|
||||
@@ -63,7 +66,7 @@ async def analyze_case(case_data: dict) -> AnalysisResult:
|
||||
return await analyze_with_claude(case_data, api_key)
|
||||
except Exception as e:
|
||||
# Логируем ошибку и переходим на fallback
|
||||
print(f"Claude API unavailable: {e}. Using fallback scoring service.")
|
||||
logger.warning(f"Claude API unavailable: {e}. Using fallback scoring service.")
|
||||
|
||||
# Fallback: используем только scoring_service
|
||||
return await analyze_with_fallback(case_data)
|
||||
@@ -108,7 +111,7 @@ async def analyze_with_claude(case_data: dict, api_key: str) -> AnalysisResult:
|
||||
zones_data += f"лес {zone['forest_pct']}%, "
|
||||
zones_data += f"дороги {zone['road_density']} км/км²\n"
|
||||
except Exception as e:
|
||||
print(f"Geo/scoring service error: {e}")
|
||||
logger.warning(f"Geo/scoring service error: {e}")
|
||||
|
||||
# Формируем промпт на русском языке
|
||||
prompt = f"""Ты — эксперт по поисково-спасательным операциям (ПСО) МЧС Республики Беларусь. Проанализируй следующий случай пропажи человека и дай структурированные рекомендации.
|
||||
@@ -154,7 +157,7 @@ async def analyze_with_claude(case_data: dict, api_key: str) -> AnalysisResult:
|
||||
"content-type": "application/json"
|
||||
},
|
||||
json={
|
||||
"model": "claude-sonnet-4-20250514",
|
||||
"model": "claude-sonnet-5",
|
||||
"max_tokens": 4096,
|
||||
"messages": [
|
||||
{
|
||||
@@ -244,7 +247,7 @@ async def analyze_with_fallback(case_data: dict) -> AnalysisResult:
|
||||
search_radius_km = scorer.distance_multiplier * 2.0
|
||||
|
||||
except Exception as e:
|
||||
print(f"Geo/scoring service error in fallback: {e}")
|
||||
logger.warning(f"Geo/scoring service error in fallback: {e}")
|
||||
|
||||
# Если зоны не построены, используем базовые
|
||||
if not primary_zones:
|
||||
|
||||
@@ -118,6 +118,8 @@ def get_terrain_coefficient(terrain: str) -> float:
|
||||
Returns:
|
||||
Terrain coefficient (0.0 - 1.0)
|
||||
"""
|
||||
if not terrain:
|
||||
return 0.5
|
||||
terrain_lower = terrain.lower()
|
||||
|
||||
terrain_map = {
|
||||
@@ -155,6 +157,8 @@ def get_time_of_day_coefficient(time_of_day: str) -> float:
|
||||
Returns:
|
||||
Time coefficient (0.0 - 1.0)
|
||||
"""
|
||||
if not time_of_day:
|
||||
return 1.0
|
||||
time_lower = time_of_day.lower()
|
||||
|
||||
if 'ночь' in time_lower:
|
||||
@@ -175,6 +179,8 @@ def get_weather_coefficient(weather: str) -> float:
|
||||
Returns:
|
||||
Weather coefficient (0.0 - 1.0)
|
||||
"""
|
||||
if not weather:
|
||||
return 1.0
|
||||
weather_lower = weather.lower()
|
||||
|
||||
if 'ливень' in weather_lower or 'сильный дождь' in weather_lower:
|
||||
|
||||
Reference in New Issue
Block a user