Skip to content

About

MingLi Agent: verifiable Chinese astrology reasoning system

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

87 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MingLi Agent(命理智能体)

可验证的命理推理系统 · Verifiable Chinese Astrology Reasoning System

不是「会算命的聊天机器人」。排盘由确定性引擎算,结论必须能追到命盘要素与规则出处, 每一句典籍断语都要能在固化底本里逐字找到。


项目定位

  • 确定性排盘 —— 排盘交给 sxtwl(寿星天文历),不让模型算命盘
  • 规则引擎 —— 81 条规则:68 条结构层(由可执行定义表唯一确定)+ 13 条典籍层(带逐字引文)
  • 证据链追踪 —— 每条结论的每个条件都能追到具体命盘要素,断环会被 Critic 拦下
  • 可验证的引证体系 —— 典籍断语挂在固化底本上,改一个字就装配失败
  • 流派透明 —— 分歧并列披露,不投票选一个「真答案」
  • 不做预测 —— 信号是结构描述,强度是证据等级而非事件概率
  • 持续评估 —— 30 案例 × 6 条行为不变量,可当回归门禁

当前状态

项 实测值
全量测试 1022 passed
规则总数 81(结构层 68 + 典籍层 13)
API 接口 12 个
评估门禁 30/30 passed
ruff 干净
mypy 3 errors,全在未改动的 engines/bazi/sxtwl_provider.py(sxtwl 的 C 扩展无类型存根)

已可运行:python -m api.server 起服务与界面,输入生辰即得命盘、证据链、 审查结果与流年时间轴。


核心架构

                         用户 / API / Web UI
                                ↓
                        MingLiService(应用服务层)
                                ↓
        ┌───────────────────────┼───────────────────────┐
        ↓                       ↓                       ↓
   Bazi Engine             Knowledge                Time Engine
   engines/bazi            knowledge/               engines/bazi
   sxtwl 确定性排盘         规则库 + 引证体系          time_engine
        ↓                       ↓                       ↓
   四柱 / 藏干 / 十神      81 条规则 + 底本         流年 / 大运 / 流月
   纳音 / 地支关系         逐字引文 + URN                  ↓
        └───────────────────────┼───────────────────────┘
                                ↓
                    Evidence Layer  ★核心创新
              事实 → 条件追踪 → 证据链 → 强度算式
                                ↓
                      AnalystAgent(模板 或 provider 出稿)
                                ↓
                         CriticAgent(独立复核)
                                ↓
                    结论 + 证据强度 + 冲突 + 审查结果

证据链的每一跳:结论 → 规则 → 条件的期望值与实际值 → 命盘要素出处。 最后那一跳(source,如 chart.pillars.month)是「可追溯」落地的位置 —— 没有它,用户只能看到「规则要求正官」,看不到「正官来自月支藏干」。


核心创新一:证据层(Evidence Layer)

传统做法

命盘 → LLM → 「你今年财运不错」

MingLi Agent

命盘
 ↓  确定性排盘(sxtwl)
四柱 己巳 丁丑 丁酉 丙午,日主丁
 ↓  事实提取(不带吉凶)
事实:日主有根 / 月支本气为食神 / 四支六害丑午 ...
 ↓  规则匹配(81 条,条件逐条追踪)
命中 13 条:STRUCT_ROOT_001、STRUCT_PATTERN_001 ...
 ↓  证据链(事实 + 规则 + 条件取值 + 命盘出处)
 ↓  强度算式(支持量凹饱和 − 冲突扣减)
结论(证据强度 0.79 —— 这是证据等级,不是事件概率)

用户能清楚看到:这个结论基于哪些规则?每条规则的哪个条件被什么命盘事实满足? 证据有多厚?不同流派怎么看?哪些依据还没校核过?

强度为什么不用「置信度均值」:均值完全不看命中条数 —— 命中 3 条和 20 条会得到 同一个分数。这里用 raw / (raw + K) 凹饱和:对条数单调递增、边际递减, 且永远到不了 1.0 —— 结构层证据再厚也只是「命盘里有什么」,不该被读成「结论几乎确定」。


核心创新二:可验证的引证体系

典籍断语最大的风险不是写错,是无从核对 —— 一句「《滴天髓》云……」可能是转抄的 二手话术。所以引文不是自由文本,而是一条能在固化底本里逐字定位的引用。

规范引用标识(Canonical Citation URN)

urn:divination:bazi:sanmingtonghui:ws761697:j8.liujia_ri.jiachen_jiazi
     └─ 系统 ─┘ └书┘ └── 版本 ──┘ └卷.篇.条┘

version 段是刻意加的:同一部书有多个本子,共用 URN 会让反查回来的是错的元数据。

两级哈希

  • text_sha256 —— 我们归一化后的正文,用来发现本地篡改
  • source_revision_sha1 —— 上游 MediaWiki 的修订哈希,用来发现上游漂移

底本角色

角色 含义 可引用
base 底本,引文逐字回对的对象 ✅
collation 同一部书的另一传本,用于核异文 ❌
reserve 已固化、尚无消费方 ❌

Corpus.citation() 拒绝任何非 base 的 URN —— 「两份都不可引、只有底本可引」的 门禁立得住,异文核对的结论才可信。

五条加载期守卫

一条原子写错不会抛异常,只会静默地永远匹配不上,或者更糟 —— 匹配上了但断错了。 所以装配期一次性挡住:

  1. 逐字定位 —— exact_quote 必须在底本里逐字找得到(繁体转简体也算失败)
  2. 键存在 —— 条件键必须在事实词表 FACT_SCHEMA 内
  3. 元数据一致 —— 引用元数据与底本记录相符
  4. 角色门禁 —— 非 base 不可引
  5. 引文限制必须落进条件 —— 引文说了「申月」,条件里就必须有 month_branch

第五条来自一次真实事故:录甲辰日时「申月,煞星㑹印,俱貴」漏写了 month_branch, 引文逐字对得上、键都在词表、元数据也一致 —— 前四条一条都没拦,而 predicate 对任何月份都命中。前四条守的是「引文可核、键存在、元数据一致」, 没有一条问「引文说过的限制有没有落进条件」。

完整性自查

Corpus.problems() 校验两份正文的 sha256 与篇章表标签。哈希不符时不再做派生检查 —— 拿一份「不知道被改成了什么」的文本去核篇名,报出来的「篇名找不到」只是哈希不符的副产品, 却会把诊断指向别的地方。


功能特性

排盘

四柱干支、藏干、十神、纳音、地支关系(六合/六冲/六害/相破/自刑/三刑)、五行计数。 年月柱按节气精确时刻分界(不是日期零点);支持历史夏令时;晚子时口径显式可选。

规则库

81 条规则,每条带来源、流派、类别、主题、置信度、校核状态。

  • 结构层 68 条 —— 十神有根/虚透、两种格局命名法、月令、日主强弱、五行缺失与偏旺、 地支关系。由 engines/bazi 的定义表唯一确定,跑一遍代码就能证伪,不需要文献背书。
  • 典籍层 13 条 —— 《三命通會》卷八「六甲日甲子時斷」,每条带 URN、逐字引文、 底本与版本、可打开的出处地址。

两种格局命名法并列收录(本气定格 / 透干定格),它们只在月支本气不透而中气余气透干时 给出不同格局名 —— 那是真实分歧,系统并列输出,不投票。

流年与大运时间轴

  • 流年 —— 干支对日主的十神、该十神在四支有没有根、流年支与命盘四支的结构关系(冲太岁等)
  • 大运 —— 顺逆按阳年男/阴年女顺行;起运数到相邻的节(不是下一个立春); 三日折一年折算到日
  • 流月 —— 由「节」划界,一个干支年恰好十二个月

输出形如 2028年,信号:财星坐流年、六合巳、相破巳,证据强度0.44 —— 不是「2028 年你会发财」。区别不在措辞,在产出物本身:这一层没有任何一处 给出必然性判断,因为信号的定义就是「命盘里出现了什么结构」。

大运需要性别:顺逆规则不同流派有分歧,缺性别时只算流年、不猜默认方向。

多主题并发分析

POST /api/analyze/multi 一次分析多个主题,服务端并发执行。

  • 命盘只算一次,扇出点在它之后,各主题共享同一张不可变命盘
  • 主题之间无跨主题依赖,依赖图只有一层 —— 不需要 DAG 调度器
  • 故障隔离:单个主题失败不影响其余,失败项以 ok=false 如实带回原因
  • 实测 4 主题 12 次 provider 调用:0.84s vs 串行估算 3.00s(3.6x)

诚实口径:确定性路径是纯 CPU 的,Python 的 GIL 让线程拿不到 CPU 并行度, 所以收益主要是故障隔离与故障定位;注入真 LLM 后每个主题是一次网络调用, 线程池这时才真正并行。

独立复核与审查

  • CriticAgent 独立复算结论引用的规则是否都在证据链内,越界引用会披露
  • 契约层 只给模型证据链(不含原始命盘与全量规则库),只接受 rule_ids 与 text 两个键
  • 契约本身可通过 GET /api/llm/contract 审计 —— 只写在源码注释里的契约等于没有契约

Web 界面

static/index.html 单文件、无框架、无构建步骤。输入生辰 → 看命盘、证据链、 审查结果、流年时间轴。古典规则额外展示书名、底本、逐字原文与可点开的出处地址。


安装与运行

# 创建虚拟环境并安装依赖
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

# 跑测试
pytest tests/

# 启动服务与 Web 界面(在仓库根目录执行)
python -m api.server
# 然后打开 http://127.0.0.1:8000

界面:输入生辰 → 看命盘、证据链、审查结果、流年时间轴。接口文档在 /docs。

评估(回归门禁)

python evaluation/runner.py          # 人读报告
python evaluation/runner.py --json   # 机器可读

跑 10 个金标准案例 × 3 个主题,检查六条系统行为不变量:

  1. 证据链不断环
  2. 审查通过
  3. 结论不越界引用
  4. 不下确定性判断
  5. 强度在 [0, 1) 内
  6. 结果可复现(同一输入两次逐字段相同)

第 6 条尤其值得单独评:它单点测不出来,而一旦哪一层悄悄引入了顺序依赖, 症状是「偶尔不一样」,靠人工跑几次发现不了。

退出码非 0 表示有未过项,可直接当门禁用。

评的不是「排盘准不准」 —— 那已由 tests/test_bazi_golden.py 用 sxtwl 与 lunar-python 两套独立实现交叉确认,比任何自建评估都严格。

新增一条典籍原子

python scripts/atom_checklist.py                       # 四处同步状态一览
python scripts/atom_checklist.py --suggest-witness ID  # 为规则找见证命盘

加一条原子要同步动四处:原子 JSON、事实提取、独立复核的 audit_fact_map、 见证命盘 RULE_WITNESS。后三处都在测试文件里,而改原子的人盯着的是第一个 —— 这个脚本把那四处的状态一次摆出来。


API 接口

12 个接口,完整描述在 /docs(Swagger UI)与 /openapi.json。

方法 路径 说明
GET /api/health 健康检查,返回当前排盘 provider
POST /api/chart 排盘:四柱、藏干、十神、纳音、地支关系
POST /api/analyze 按问题分析:事实、证据链、强度算式、审查结果
POST /api/analyze/multi 多主题并发分析,故障隔离
POST /api/timeline 流年时间轴(带性别则含大运)
GET /api/topics 已登记的分析主题及其别名
GET /api/rules 规则库,可按流派/类别/层级/校核状态过滤
GET /api/rules/stats 规则库统计
GET /api/rules/{rule_id} 单条规则详情
GET /api/schools 流派清单与已知分歧点
GET /api/classics/backlog 典籍层待录入清单及阻塞原因
GET /api/llm/contract 推理层与模型之间的提示契约

错误约定:输入不合法、超出历法库支持范围、provider 不可用时一律返回 422, detail 为可直接展示给用户的中文说明;不存在的资源返回 404。不返回 500 堆栈。


已知边界

  • 大运需要性别。顺逆规则不同流派有分歧,缺性别时只算流年、不猜默认方向。 启用后结果带 approximate: true(三日折一年)。
  • LLM provider 未接线。默认走确定性模板出稿,离线可运行;契约见 GET /api/llm/contract。要接真 provider 就注入一个,接口只有 complete(request) -> str。
  • 典籍层只覆盖《三命通會》卷八「六甲日甲子時斷」(13 条)。其余条目 被阻塞在「拿到可核验底本」这一步,见 GET /api/classics/backlog。
  • 紫微斗数排盘引擎未做。engines/ 下只有 bazi/;没有引擎,那批规则的 条件无处落地。底本已固化挂 role=reserve,等引擎到位。
  • MingLi-Bench / fate-bench 未集成。当前评估是自建的行为不变量检查, 不是命理知识题准确率,因此不给出准确率数字。
  • 主题层的断语覆盖不均。事业/婚姻/健康/财运四个主题目前只有公共结构层证据 (status=base_only),结论不构成对该主题的判断,coverage_note 里写了原因。

最近的变更

时间轴引擎(Phase 6 收口)

  • 新增 knowledge/flow_facts.py:流年/大运对日主的十神、有根判定、与四支的结构关系。 两条轴共用一份实现,只靠轴名前缀区分。
  • 新增 knowledge/time_windows.py:TimeWindow / Signal / analyze_period。 信号由事实直接命名并带 source 可回溯;主题过滤用显式声明的表。
  • 强度公式内核提为 score_support,本命局与时间轴共用同一算式 —— 「本命局 0.62,2028 年 0.48」要有意义,两边必须是同一种东西。
  • 接入 POST /api/timeline,Phase 6 的代码从死代码变成可用端点。

多主题并发

  • MingLiService.analyze_multi():命盘只算一次,扇出点在它之后; analyze 拆出「吃已算好命盘」的内核,两条路径共用,不另写一份。
  • 标准库 ThreadPoolExecutor,不建队列、不建消息总线 —— 进程内传不可变 dataclass 就够。
  • 故障隔离 + POST /api/analyze/multi。

引证体系与典籍层首批规则

  • 固化公版底本(《三命通會》卷八,欽定四庫全書本),两级哈希 + 永久链接。
  • knowledge/urn.py:Canonical Citation URN。
  • 五条加载期守卫(含新增的第五条「引文说过的限制必须落进条件」)。
  • 甲辰日甲子时七条断语解除暂缓,规则 68 → 81,destiny 主题 6 → 13 条。
  • Corpus.problems() 完整性自查补厚到各 5 条测试。

Web 界面

  • static/index.html 单文件,无框架无构建;python -m api.server 即起。
  • 全程 textContent 不用 innerHTML —— 结论、规则原文、书名来自语料, 生辰来自用户输入,拼 HTML 字符串等于自己开一个注入口。

评估门禁

  • evaluation/runner.py:10 金标准案例 × 3 主题 × 6 条行为不变量。
  • 评估器自身可被证伪:每条不变量都喂一份故意违规的 payload 断言报错。

测试与工具

  • scripts/atom_checklist.py:新增原子的收口清单,四处同步从靠人记得变成可查。
  • 见证命盘独占性检查:一张见证盘只该命中它见证的那条规则,多命中的要显式登记。

技术栈

运行依赖(requirements.txt)

依赖 用途
sxtwl==2.0.7 排盘历法底座(寿星天文历,C 扩展)
lunar_python==1.4.8 仅用于差分测试交叉校验,不参与生产排盘
fastapi / uvicorn API 服务
pydantic 请求与响应模型
pytest 测试
rich 终端输出
requests / python-dotenv 语料抓取与配置

其余

  • 前端 —— 原生 HTML + CSS + JS 单文件,无框架、无构建步骤
  • 存储 —— 语料用 JSON + 纯文本固化在仓库内(corpus/canonical/); 运行日志用 JSONL。没有数据库:规则库是代码,语料是固化文件, 两者都不需要运行时存储

为什么没有 PostgreSQL / Redis / React / LangChain

规划早期列过这些,实际做下来不需要:规则库与语料都是版本化的静态资产 (要的是可 diff、可复核,不是可查询),界面只需一个页面(引入构建步骤 就多一类构建故障),而模型调用被刻意收窄成一个 complete(request) -> str —— 接口越窄,能绕过证据链的地方就越少。


执行计划

完整计划见 MINGLI_PLAN.md。各 Phase 验收报告见 PHASE0_REPORT.md … PHASE6_REPORT.md。

Phase 0-3:核心能力 ✅

  • 调研 GitHub 优质项目、制定执行计划
  • 排盘引擎(sxtwl,10 个双实现交叉确认的 golden case)
  • 规则库(81 条:结构层 68 + 典籍层 13)
  • Evidence Layer(条件追踪、主题覆盖、可审计强度算式)

Phase 4-6:推理与时间轴 ✅

  • Reasoning Agent(确定性模板 / provider 出稿双路径)
  • Critic Agent(独立复核 + 多轮修正闭环)
  • Time Engine(流年、大运、流月、事件窗口)

Phase 7:评估体系 🚧

  • 自建评估(30 案例 × 6 条行为不变量,可当门禁)
  • MingLi-Bench 集成(160 道命理知识题)
  • fate-bench 集成(295 个历史人物事件)

Phase 8-10:产品化 🚧

  • 用户记忆系统(历史提问、命盘档案)
  • Web UI
  • RESTful API(12 个接口)

Phase 11-15:扩展能力

  • 紫微斗数(底本已固化挂 reserve,缺排盘引擎)
  • 流月接入事件窗口(卡在「月柱十神怎么取」这个流派分歧)
  • 合婚分析 / 择吉系统 / MCP Server

Phase 16-20:生产就绪

  • 性能优化、安全加固、多语言、移动端

设计原则

  1. 计算与推理分离 —— 模型不负责计算,只负责理解问题与解释证据
  2. 证据前置 —— 先有事实和规则,再有结论
  3. 可验证高于可读 —— 引文必须逐字可回溯,宁可留白也不写「大概是这样」
  4. 流派透明 —— 不同流派的判断差异必须明确告知用户
  5. 不做预测 —— 输出结构信号与证据等级,不输出必然性判断
  6. 本地优先 —— 核心计算可离线运行,不依赖外部服务
  7. 接口越窄越安全 —— 能绕过证据链的地方越少越好
  8. 诚实留白 —— 没有可核验底本时拒绝录入,并说明卡在哪一步

验收标准

每个 Phase 完成后输出十节报告:

  1. 修改了什么 2. 为什么修改 3. 文件清单 4. 数据结构 5. API
  2. 测试结果 7. 构建结果 8. 已知问题 9. 未实现功能 10. 下一阶段建议

变异探针纪律:关键守卫撤掉后必须有测试变红。探针脚本开跑前先验基线干净 —— 基线红着时「抓住」没有意义,分不清红是变异造成的还是本来就在红。


参考项目

  • HeiGe-SuanMing —— 多引擎系统(八字+紫微+梅花+六爻+奇门)。 本项目取其 tests/test_paipan.py 的排盘预期做外部口径对照 (见 tests/test_bazi_heige_acceptance.py),未集成为引擎 —— 生产排盘走 SxtwlBaziProvider。
  • lunar_python —— 第二实现,仅用于差分测试交叉校验
  • DestinyLinker/MingLi-Bench —— 命理 LLM 评估基准(待集成)
  • shunshi-ai/fate-bench —— 历史人物事件验证(待集成)
  • SylarLong/iztro —— 紫微斗数排盘库(待评估)

贡献指南

欢迎贡献:

  1. 典籍底本 —— 提供可核验的公有领域文本与版本信息
  2. 规则原子 —— 按 scripts/extract_atoms.py 产出待审队列,人工写转述
  3. 边界用例 —— 历法边界(节气时刻、夏令时、晚子时、闰月)
  4. 流派依据 —— 有出处支撑的分歧点
  5. Bug 修复

新增规则前请先跑 python scripts/atom_checklist.py,它会告诉你四处里还缺哪几处。


许可证

MIT License


联系方式

  • GitHub Issues:问题反馈
  • Discussions:技术讨论

致谢

感谢以下项目的启发与参考:

  • HeiGe-SuanMing —— 排盘口径的外部对照来源
  • sxtwl / 寿星天文历 —— 确定性历法底座
  • lunar_python —— 差分测试的第二实现
  • MingLi-Bench / fate-bench —— 评估基准的思路
  • iztro —— 紫微斗数排盘的可选实现

当前状态:Phase 0-6 完成,Phase 7/8/10 部分完成;系统可完整运行 —— 排盘、规则、证据链、审查、流年时间轴、并发多主题分析、Web 界面与评估门禁全部就绪。

下一步:接入真 LLM provider;集成 MingLi-Bench / fate-bench; 流月接入事件窗口(需先定「月柱十神怎么取」的流派口径)。

About

MingLi Agent: verifiable Chinese astrology reasoning system

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages