fix: 修复历史卦象列表无法显示及六爻解卦提示词逻辑错误

后端 Pydantic schema 添加 Hant 繁体字段支持(guaNameHant,
targetGuaNameHant, spiritNameHant, relationNameHant),解决
DerivedDivinationData extra=forbid 拒绝 AI 输出的繁体字段导致
agent_output 解析失败、历史记录为空的问题。

六爻解卦提示词修复:增加静卦五行生克链分析、假破假空降权、
六冲中性判断、用神核对防捏造、空亡数据对照等硬约束。

前端 Dart model 同步添加 Hant 字段(反向兼容,缺省为空字符串)。

其他:硬币翻转动画修复、弹窗单按钮居中、起卦按钮布局调整、
繁体 l10n 清理、pre-commit 排除集成测试。
This commit is contained in:
qzl
2026-04-14 12:37:19 +08:00
parent 97976b20bf
commit 55bac03eb0
14 changed files with 126 additions and 313 deletions
@@ -22,17 +22,19 @@ _WORKER_HARD_CONSTRAINTS = """\
严禁跳过取用神直接下结论。
严禁多核心用神混合判签;一问多意时只取一个主用神。
严禁仅凭单一因素判吉凶。
严禁将旬空月破机械等同凶;须辨真假及是否可解除。
严禁将旬空月破机械等同凶;须辨真假及是否可解除;假破假空须大幅降权,不得与真破真空同等对待
严禁将有救应的卦直接断死,严禁表面顺利后续败坏的卦直判上吉。
严禁脱离爻位证据给建议。
严禁夸大确定性;吉凶并见或证据冲突时须说明边界。"""
严禁夸大确定性;吉凶并见或证据冲突时须说明边界。
严禁捏造或臆断未提供的数据:所有爻位属性(六亲、天干地支、五行、世应、动爻)、空亡范围、月破等事实判断,必须严格对照用户消息中给出的数据,不得凭记忆或推断添加、修改、遗漏。用神是否现于卦中,须逐爻核对六亲名称后确认,不得跳过核对直接宣称用神不现。
静卦不得因无动爻而判为无生扶;静爻之间仍存在五行生克链,须逐一梳理原神→用神的静爻生扶路径。"""
_WORKER_PROCEDURE = """\
第1步[取用神]:根据问题类型定唯一主用神并述理由。用神不现时须查伏神、飞神、变爻引出、暗动提拔,不可直接判弱判无
第1步[取用神]:根据问题类型定唯一主用神并述理由。用神前须逐爻核对六亲名称,确认用神是否明现于卦中;若确实不现,再查伏神、飞神、变爻引出、暗动提拔,不可跳过核对直接判用神不现
第2步[主判]:先看用神旺衰(月建日辰生扶克泄耗),再看世应与用神关系(生合冲克墓绝),再看动爻是生扶还是克耗用神,给事情定底色(偏吉/偏凶/杂局)。
第2步[主判]:先看用神旺衰(月建日辰生扶克泄耗),再看世应与用神关系(生合冲克墓绝),再看动爻是生扶还是克耗用神,给事情定底色(偏吉/偏凶/杂局)。静卦无动爻时,须梳理静爻之间五行生克链(原神→用神、忌神→用神等)作为生扶或克耗的依据,不可因"无动爻"而忽略静爻生克。
第3步[修正]:必查原神忌神仇神发动对用神根气的影响;必查动变质量(回头生克、化进退空破墓绝)必查伏神飞神飞克提拔;必查合冲刑害六冲六合反吟伏吟;必查旬空月破辨真假(真空/假空、真破/假破、值日/出旬/逢合/冲起/填实);修正是对主判底色做升降,不可脱离主判单独下结论。
第3步[修正]:必查原神忌神仇神发动对用神根气的影响;静卦须查原神静爻对用神的生扶链是否通畅。必查动变质量(回头生克、化进退空破墓绝)必查伏神飞神飞克提拔;用神明现时无须查伏神。必查合冲刑害六冲六合反吟伏吟;六冲不等于凶:六冲主快、主动、主变,短期求事反利速决,须结合用神旺衰与问题类型综合判断,不得将六冲一律断为散耗凶象。必查旬空月破辨真假(真空/假空、真破/假破、值日/出旬/逢合/冲起/填实):假破须对照日辰或动爻是否有生扶解救,有救则大幅降权(假破近似无害),无救方可按真破论;空亡范围必须严格对照用户消息中给出的年/月/日/时空亡数据逐条核实,不得臆断或遗漏。修正是对主判底色做升降,不可脱离主判单独下结论。
第4步[签级]:只允许 上上签/中上签/中下签/下下签。先定底档再升降:
- 初判:偏吉→中上签,偏凶→中下签,杂局→据用神受益或受损孰重落中上/中下。
+5
View File
@@ -29,7 +29,9 @@ class YaoDetail(BaseModel):
position: int = Field(ge=1, le=6)
spirit_name: str = Field(alias="spiritName", min_length=1)
spirit_name_hant: str = Field(alias="spiritNameHant", default="")
relation_name: str = Field(alias="relationName", min_length=1)
relation_name_hant: str = Field(alias="relationNameHant", default="")
tigan_name: str = Field(alias="tiganName", min_length=1)
element_name: str = Field(alias="elementName", min_length=1)
is_yang: bool = Field(alias="isYang")
@@ -42,6 +44,7 @@ class FushenDetail(BaseModel):
position: int = Field(ge=1, le=6)
relation_name: str = Field(alias="relationName", min_length=1)
relation_name_hant: str = Field(alias="relationNameHant", default="")
tigan_name: str = Field(alias="tiganName", min_length=1)
element_name: str = Field(alias="elementName", min_length=1)
@@ -94,9 +97,11 @@ class DerivedDivinationData(BaseModel):
alias="changedBinaryCode", min_length=6, max_length=6
)
gua_name: str = Field(alias="guaName", min_length=2)
gua_name_hant: str = Field(alias="guaNameHant", default="")
upper_name: str = Field(alias="upperName", min_length=1)
lower_name: str = Field(alias="lowerName", min_length=1)
target_gua_name: str = Field(alias="targetGuaName", min_length=2)
target_gua_name_hant: str = Field(alias="targetGuaNameHant", default="")
world_position: int = Field(alias="worldPosition", ge=1, le=6)
response_position: int = Field(alias="responsePosition", ge=1, le=6)
has_changing_yao: bool = Field(alias="hasChangingYao")
+12
View File
@@ -14,6 +14,18 @@ from core.config.settings import config
from core.db.session import AsyncSessionLocal
def pytest_configure(config): # noqa: ARG001
config.addinivalue_line(
"markers", "integration: integration test requiring live backend"
)
def pytest_collection_modifyitems(items):
for item in items:
if "integration" in item.nodeid:
item.add_marker(pytest.mark.integration)
@pytest.fixture(scope="session")
def api_base_url() -> str:
return os.environ.get("ERYAO_TEST_BASE_URL", "http://localhost:5775")