fix: 8个严重bug修复 - 预测引擎从空壳恢复为全功能
修复清单: 1. jyotish_engine.py: 缺少 List 类型导入 (NameError崩溃) 2. cmd_predict: 传给EventPredictionModel的ascendant是str不是dict 3. cmd_predict: 未传入dasha/congregation/vivah_saham/chara_dasha数据 4. Dasha timeline: MD的is_current字段未设置 5. event_prediction_model: status检查不兼容中英混合格式 6. event_prediction_model: Dasha数据格式不匹配(current_dasha vs current_mahadasha) 7. event_prediction_model: Chara Dasha key名不匹配(dasha_sequence vs dasha_list) 8. cmd_predict: 序列化缺少confidence/dasha_signals/transit_signals字段 修复前: predict命令直接fallback到空壳,所有事件概率30%,0信号 修复后: marriage=43%(1静态+1Dasha), career=54%(3Dasha)
This commit is contained in:
@@ -252,11 +252,13 @@ class EventPredictionModel:
|
|||||||
if ph == h and pn in target_karakas:
|
if ph == h and pn in target_karakas:
|
||||||
pd = self.chart.get('planets', {}).get(pn, {})
|
pd = self.chart.get('planets', {}).get(pn, {})
|
||||||
status = pd.get('status', '')
|
status = pd.get('status', '')
|
||||||
if status == 'exalted':
|
# 支持"擢升(Exalted)"、"落陷(Debilitated)"、"入庙(Own Sign)"等中英混合格式
|
||||||
|
status_lower = status.lower() if status else ''
|
||||||
|
if 'exalted' in status_lower or '擢升' in status:
|
||||||
result['signals'].append(f'Karaka {pn}在{h}宫擢升')
|
result['signals'].append(f'Karaka {pn}在{h}宫擢升')
|
||||||
elif status == 'own_sign':
|
elif 'own' in status_lower or '入庙' in status:
|
||||||
result['signals'].append(f'Karaka {pn}在{h}宫入庙')
|
result['signals'].append(f'Karaka {pn}在{h}宫入庙')
|
||||||
elif status == 'debilitated':
|
elif 'debilitated' in status_lower or '落陷' in status:
|
||||||
result['signals'].append(f'Karaka {pn}在{h}宫落陷(负面)')
|
result['signals'].append(f'Karaka {pn}在{h}宫落陷(负面)')
|
||||||
|
|
||||||
# 2. 行星聚集分析(使用 congregation_data)
|
# 2. 行星聚集分析(使用 congregation_data)
|
||||||
@@ -309,8 +311,24 @@ class EventPredictionModel:
|
|||||||
|
|
||||||
# ── 2a. Vimshottari Dasha ──
|
# ── 2a. Vimshottari Dasha ──
|
||||||
if self.dasha:
|
if self.dasha:
|
||||||
# 当前 Mahadasha
|
# 适配 full-reading 输出格式:current_dasha.lord + current_dasha.antardasha[]
|
||||||
|
md_lord = ''
|
||||||
|
ad_lord = ''
|
||||||
|
|
||||||
|
# 方式1:current_dasha 格式(full-reading输出)
|
||||||
|
current_md = self.dasha.get('current_dasha')
|
||||||
|
if current_md and isinstance(current_md, dict):
|
||||||
|
md_lord = current_md.get('lord', '')
|
||||||
|
# 从 antardasha 列表中找 is_current=True 的
|
||||||
|
for ad in current_md.get('antardasha', []):
|
||||||
|
if ad.get('is_current'):
|
||||||
|
ad_lord = ad.get('lord', '')
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# 方式2:current_mahadasha / current_antardasha 格式
|
||||||
md_lord = self.dasha.get('current_mahadasha', {}).get('lord', '')
|
md_lord = self.dasha.get('current_mahadasha', {}).get('lord', '')
|
||||||
|
ad_lord = self.dasha.get('current_antardasha', {}).get('lord', '')
|
||||||
|
|
||||||
if md_lord:
|
if md_lord:
|
||||||
md_house = self.planet_houses.get(md_lord, 0)
|
md_house = self.planet_houses.get(md_lord, 0)
|
||||||
# MD 主星是否关联目标宫位
|
# MD 主星是否关联目标宫位
|
||||||
@@ -326,8 +344,6 @@ class EventPredictionModel:
|
|||||||
if self.house_lords.get(h) == md_lord:
|
if self.house_lords.get(h) == md_lord:
|
||||||
signals.append(f'当前MD {md_lord}是{h}宫主(目标宫)')
|
signals.append(f'当前MD {md_lord}是{h}宫主(目标宫)')
|
||||||
|
|
||||||
# 当前 Antardasha
|
|
||||||
ad_lord = self.dasha.get('current_antardasha', {}).get('lord', '')
|
|
||||||
if ad_lord:
|
if ad_lord:
|
||||||
ad_house = self.planet_houses.get(ad_lord, 0)
|
ad_house = self.planet_houses.get(ad_lord, 0)
|
||||||
if ad_house in target_houses:
|
if ad_house in target_houses:
|
||||||
@@ -339,28 +355,30 @@ class EventPredictionModel:
|
|||||||
|
|
||||||
# MD+AD 组合信号(高权重)
|
# MD+AD 组合信号(高权重)
|
||||||
if md_lord and ad_lord:
|
if md_lord and ad_lord:
|
||||||
if ad_house in target_houses and md_house in target_houses:
|
md_house2 = self.planet_houses.get(md_lord, 0)
|
||||||
|
if ad_house in target_houses and md_house2 in target_houses:
|
||||||
signals.append(f'★ MD+AD双激活目标宫位({md_lord}+{ad_lord})')
|
signals.append(f'★ MD+AD双激活目标宫位({md_lord}+{ad_lord})')
|
||||||
|
|
||||||
# ── 2b. Chara Dasha (Jaimini) ──
|
# ── 2b. Chara Dasha (Jaimini) ──
|
||||||
if self.chara_dasha:
|
if self.chara_dasha:
|
||||||
cd_list = self.chara_dasha.get('dasha_list', [])
|
# 适配实际格式:dasha_sequence[] 或 dasha_list[]
|
||||||
|
cd_list = self.chara_dasha.get('dasha_sequence') or self.chara_dasha.get('dasha_list', [])
|
||||||
if cd_list:
|
if cd_list:
|
||||||
# 当前 Chara Mahadasha
|
# 当前 Chara Mahadasha(第一个条目)
|
||||||
current_cd = cd_list[0] if cd_list else {}
|
current_cd = cd_list[0] if cd_list else {}
|
||||||
cd_sign = current_cd.get('sign', '')
|
cd_sign = current_cd.get('sign', '')
|
||||||
cd_lord = SIGN_LORDS.get(cd_sign, '')
|
cd_lord = current_cd.get('lord', '') or SIGN_LORDS.get(cd_sign, '')
|
||||||
cd_house = self.planet_houses.get(cd_lord, 0)
|
cd_house = self.planet_houses.get(cd_lord, 0)
|
||||||
|
|
||||||
if cd_house in target_houses:
|
if cd_house in target_houses:
|
||||||
signals.append(f'当前Chara Dasha {cd_sign}({cd_lord})在{cd_house}宫(目标宫)')
|
signals.append(f'当前Chara Dasha {cd_sign}({cd_lord})在{cd_house}宫(目标宫)')
|
||||||
|
|
||||||
# Chara Antardasha
|
# Chara Antardasha
|
||||||
antardashas = current_cd.get('antardashas', [])
|
antardashas = current_cd.get('antardashas') or current_cd.get('antardasha', [])
|
||||||
if antardashas:
|
if antardashas:
|
||||||
current_ad = antardashas[0] if antardashas else {}
|
current_ad = antardashas[0] if antardashas else {}
|
||||||
ad_sign = current_ad.get('sign', '')
|
ad_sign = current_ad.get('sign', '')
|
||||||
ad_lord_name = SIGN_LORDS.get(ad_sign, '')
|
ad_lord_name = current_ad.get('lord', '') or SIGN_LORDS.get(ad_sign, '')
|
||||||
ad_h = self.planet_houses.get(ad_lord_name, 0)
|
ad_h = self.planet_houses.get(ad_lord_name, 0)
|
||||||
if ad_h in target_houses:
|
if ad_h in target_houses:
|
||||||
signals.append(f'Chara AD {ad_sign}({ad_lord_name})在{ad_h}宫(目标宫)')
|
signals.append(f'Chara AD {ad_sign}({ad_lord_name})在{ad_h}宫(目标宫)')
|
||||||
|
|||||||
+21
-11
@@ -43,7 +43,7 @@ import csv
|
|||||||
import math
|
import math
|
||||||
import sqlite3
|
import sqlite3
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from typing import Dict
|
from typing import Dict, List
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# 路径常量
|
# 路径常量
|
||||||
@@ -219,7 +219,7 @@ def cmd_dasha(args):
|
|||||||
for i in range(9):
|
for i in range(9):
|
||||||
lord = DASHA_ORDER[(si + i) % 9]; years = DASHA_YEARS[lord]
|
lord = DASHA_ORDER[(si + i) % 9]; years = DASHA_YEARS[lord]
|
||||||
end_dt = dt + timedelta(days=years * 365.25)
|
end_dt = dt + timedelta(days=years * 365.25)
|
||||||
timeline.append({"lord": lord, "lord_cn": PLANET_CN[lord], "start": dt.strftime("%Y-%m-%d"), "end": end_dt.strftime("%Y-%m-%d"), "years": years})
|
timeline.append({"lord": lord, "lord_cn": PLANET_CN[lord], "start": dt.strftime("%Y-%m-%d"), "end": end_dt.strftime("%Y-%m-%d"), "years": years, "is_current": False})
|
||||||
dt = end_dt
|
dt = end_dt
|
||||||
|
|
||||||
today = datetime.strptime(args.today, "%Y-%m-%d") if args.today else datetime.now()
|
today = datetime.strptime(args.today, "%Y-%m-%d") if args.today else datetime.now()
|
||||||
@@ -227,6 +227,7 @@ def cmd_dasha(args):
|
|||||||
for d in timeline:
|
for d in timeline:
|
||||||
ds = datetime.strptime(d["start"], "%Y-%m-%d"); de = datetime.strptime(d["end"], "%Y-%m-%d")
|
ds = datetime.strptime(d["start"], "%Y-%m-%d"); de = datetime.strptime(d["end"], "%Y-%m-%d")
|
||||||
if ds <= today < de:
|
if ds <= today < de:
|
||||||
|
d["is_current"] = True
|
||||||
total_days = (de - ds).days; li = DASHA_ORDER.index(d["lord"])
|
total_days = (de - ds).days; li = DASHA_ORDER.index(d["lord"])
|
||||||
sub = []; sdt = ds
|
sub = []; sdt = ds
|
||||||
for j in range(9):
|
for j in range(9):
|
||||||
@@ -313,16 +314,21 @@ def cmd_predict(args):
|
|||||||
try:
|
try:
|
||||||
sys.path.insert(0, SCRIPT_DIR)
|
sys.path.insert(0, SCRIPT_DIR)
|
||||||
from event_prediction_model import EventPredictionModel
|
from event_prediction_model import EventPredictionModel
|
||||||
asc_sign = chart.get("ascendant", {}).get("sign", "Unknown")
|
# 直接传完整chart数据给EventPredictionModel(v5.0需要ascendant dict和planets dict)
|
||||||
planets = chart.get("planets", {})
|
# 同时从 full-reading 输出中提取所有模块数据传入(v5.1修复:之前丢失dasha/congregation等)
|
||||||
# 构建模型需要的行星简化数据
|
modules = chart.get("modules", {})
|
||||||
planet_positions = {}
|
model = EventPredictionModel(
|
||||||
for pn, pd in planets.items():
|
chart_data={
|
||||||
if isinstance(pd, dict) and 'house' in pd:
|
"ascendant": chart.get("ascendant", {}),
|
||||||
planet_positions[pn] = {'sign': pd.get('sign', ''), 'house': pd.get('house', 0)}
|
"planets": chart.get("planets", {}),
|
||||||
model = EventPredictionModel(chart_data={"ascendant": asc_sign, "planets": planet_positions})
|
},
|
||||||
|
dasha_data=modules.get("dasha"),
|
||||||
|
congregation_data=modules.get("congregation"),
|
||||||
|
vivah_saham_data=modules.get("vivah_saham"),
|
||||||
|
chara_dasha_data=modules.get("jaimini", {}).get("chara_dasha"),
|
||||||
|
)
|
||||||
raw_preds = model.predict_all_events()
|
raw_preds = model.predict_all_events()
|
||||||
# 将 Prediction dataclass 转为可序列化 dict
|
# 将 Prediction dataclass 转为可序列化 dict(v5.1补充缺失字段)
|
||||||
predictions = []
|
predictions = []
|
||||||
for p in raw_preds:
|
for p in raw_preds:
|
||||||
predictions.append({
|
predictions.append({
|
||||||
@@ -330,9 +336,13 @@ def cmd_predict(args):
|
|||||||
"description": p.description,
|
"description": p.description,
|
||||||
"probability": p.probability,
|
"probability": p.probability,
|
||||||
"risk_level": str(p.risk_level.value) if hasattr(p.risk_level, 'value') else str(p.risk_level),
|
"risk_level": str(p.risk_level.value) if hasattr(p.risk_level, 'value') else str(p.risk_level),
|
||||||
|
"confidence": str(p.confidence.value) if hasattr(p.confidence, 'value') else str(p.confidence),
|
||||||
"timing": p.timing,
|
"timing": p.timing,
|
||||||
"key_factors": p.key_factors,
|
"key_factors": p.key_factors,
|
||||||
"recommendations": p.recommendations,
|
"recommendations": p.recommendations,
|
||||||
|
"dasha_signals": p.dasha_signals,
|
||||||
|
"transit_signals": p.transit_signals,
|
||||||
|
"timing_windows": p.timing_windows,
|
||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
"method": "三层验证法(EventPredictionModel规则引擎)",
|
"method": "三层验证法(EventPredictionModel规则引擎)",
|
||||||
|
|||||||
Reference in New Issue
Block a user