@furongjun1999/dsh-memory 0.4.11 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (504) hide show
  1. package/README.md +16 -16
  2. package/codebuddy/CODEBUDDY.md +11 -3
  3. package/codebuddy/README.md +92 -90
  4. package/codebuddy/mcp.json +27 -27
  5. package/docs/GBrain/345/217/257/345/200/237/351/211/264/347/202/271_/347/201/265/346/236/242/350/220/275/347/202/271/344/272/244/346/216/245_20260919.md +169 -169
  6. package/docs/Pi/345/217/257/345/255/246/344/271/240/344/274/230/347/202/271_/347/201/265/346/236/242/345/244/247/350/204/221/346/224/271/350/277/233/344/272/244/346/216/245_20260915.md +144 -144
  7. package/docs/README.md +142 -111
  8. package/docs/discipline/harnesses.yaml +244 -226
  9. package/docs/discipline/templates/full.md.tmpl +61 -61
  10. package/docs/discipline/templates/rules.mdc.tmpl +68 -0
  11. package/docs/discipline/templates/skill.md.tmpl +23 -23
  12. package/docs/eval/AGI/344/270/203/347/273/264/350/257/204/345/210/206/346/212/245/345/221/212_md_cg_v1.0.md +299 -299
  13. package/docs/eval/AGI/344/270/203/347/273/264/350/257/204/345/210/206/346/212/245/345/221/212_md_cg_v2.0.md +239 -239
  14. package/docs/eval//345/256/236/351/252/214/346/226/271/346/241/210_/345/255/246/344/271/240/351/227/255/347/216/257AB/344/270/216/346/250/252/350/257/204_v1.0.md +174 -174
  15. package/docs/eval//346/250/252/350/257/204_/345/205/255/345/256/266100/351/242/230/344/270/255/350/213/261/345/217/214/346/237/245_v1.0.md +223 -223
  16. package/docs/{mdcg → hive}//344/273/244/347/211/214/344/270/216/350/247/222/350/211/262/346/235/203/350/201/214/345/210/206/347/246/273_v0.1.md +165 -160
  17. package/docs/hive//344/273/244/347/211/214/350/257/255/344/271/211/344/277/256/346/255/243_/344/273/262/350/243/201/344/275/215_v0.1.md +76 -0
  18. package/docs/{mdcg → hive}//345/255/220/344/273/243/347/220/206/351/205/215/347/275/256/346/240/207/345/207/206_v0.5.md +236 -236
  19. package/docs/hive//346/243/200/347/264/242/346/224/266/346/225/233/345/256/236/346/265/213/344/270/216S1b/350/256/276/350/256/241_v0.1.md +43 -43
  20. package/docs/hive//346/243/200/347/264/242/347/256/227/346/263/225/345/217/243/345/276/204/345/257/271/347/205/247_v0.1.md +85 -0
  21. package/docs/hive//346/243/200/347/264/242/350/267/257/345/276/204/344/270/216/350/256/244/347/237/245/347/273/223/346/236/204/345/245/221/347/272/246_v0.1.md +102 -102
  22. package/docs/hive//350/234/202/345/267/242M6_ingest/345/256/236/346/226/275/350/256/241/345/210/222_v0.1.md +47 -0
  23. package/docs/hive//350/234/202/345/267/242/345/217/214/345/256/236/344/276/213/344/272/222/351/252/214_/350/256/276/350/256/241/345/256/232/347/250/277.md +503 -503
  24. package/docs/hive//350/234/202/345/267/242/345/267/245/344/275/234/350/256/260/345/277/206_/351/241/271/347/233/256/350/256/241/345/210/222.md +85 -85
  25. package/docs/hive//350/234/202/345/267/242/350/256/276/350/256/241_/347/220/206/350/256/272/345/257/271/351/275/220_v0.1.md +191 -0
  26. package/docs/hive//350/234/202/345/267/242/350/277/255/344/273/243_/345/256/217/350/247/202/344/270/216/347/276/244/344/275/223/350/260/203/345/272/246_v0.1.md +90 -0
  27. package/docs/mdcg/D_meta_/345/267/245/347/250/213/345/214/226/346/226/271/346/241/210_v0.2.md +216 -216
  28. package/docs/mdcg/README/350/257/246/347/273/206/347/211/210_v0.4.10.md +646 -646
  29. package/docs/mdcg/lingshu_tutorial.html +14449 -14449
  30. package/docs/mdcg/release_v0.4.11.md +49 -0
  31. package/docs/mdcg/release_v0.4.5.md +55 -55
  32. package/docs/mdcg/tool_table_v0.3.0.md +117 -117
  33. package/docs/mdcg//345/205/250/345/272/223/344/273/243/347/240/201/350/257/204/345/256/241/344/270/216/346/235/241/344/273/266/345/214/226/346/263/250/351/207/212_/350/256/241/345/210/222_v0.1.md +600 -600
  34. package/docs/mdcg//345/212/237/350/203/275/350/260/203/347/224/250/346/230/240/345/260/204/350/241/250_v0.1.md +40 -40
  35. package/docs/mdcg//345/215/225/345/205/203/350/207/252/346/210/221/351/224/232/347/202/271_/347/263/273/347/273/237/346/217/220/347/244/272/350/257/215/346/240/207/345/207/206_v0.3.md +275 -275
  36. package/docs/mdcg//345/217/221/345/270/203/351/227/250/347/246/201/351/223/276_v0.1.md +54 -0
  37. package/docs/mdcg//346/272/220/347/240/201/347/272/247/346/236/266/346/236/204/345/256/241/350/256/241_GPT/346/211/271/350/257/204/345/257/271/347/205/247_v1.0.md +130 -130
  38. package/docs/mdcg//347/201/265/346/236/24282/345/267/245/345/205/267_/345/212/237/350/203/275/346/225/264/347/220/206/344/270/216/350/277/201/347/247/273/346/230/240/345/260/204_v0.1.md +278 -278
  39. package/docs/mdcg//347/201/265/346/236/242/350/256/260/345/277/206/345/212/250/350/257/215/345/215/217/350/256/256_v1.0-draft.md +172 -172
  40. package/docs/mdcg//347/274/272/345/217/243/345/215/225_P0/346/224/266/345/217/243_v0.1.md +270 -270
  41. package/docs/mdcg//350/256/244/347/237/245/345/233/276_G4-G8/347/274/272/345/217/243/350/243/201/345/256/232/345/215/225_v0.1.md +491 -491
  42. package/docs/mdcg//350/256/244/347/237/245/345/233/276_/346/235/241/344/273/266/347/251/272/351/227/264/345/220/210/346/210/220/344/270/216/347/224/237/346/225/210/346/235/241/344/273/266/345/217/243/345/276/204_v0.1.md +340 -340
  43. package/docs/mdcg//350/256/244/347/237/245/345/233/276_/347/264/242/345/274/225/344/270/216/345/267/245/347/250/213/350/247/204/350/214/203/345/214/226_/350/256/241/345/210/222_v0.1.md +588 -588
  44. package/docs/plans/GridWorld/346/234/200/345/260/217/351/227/255/347/216/257/350/247/204/346/240/274_v0.1.md +176 -176
  45. package/docs/plans//345/221/275/345/220/215/346/262/273/347/220/206_/351/241/271/347/233/256/350/256/241/345/210/222.md +81 -81
  46. package/docs/swarm//350/234/202/347/276/244/344/272/222/350/201/224_v0.1.md +704 -704
  47. package/docs/swarm//350/234/202/347/276/244/345/220/214/351/224/231/346/243/200/346/265/213/345/256/236/351/252/214/345/215/217/350/256/256_v0.1.md +242 -242
  48. package/docs/theory//345/215/225/347/272/277/347/250/213/344/270/216/346/263/250/346/204/217/345/212/233/351/233/206/344/270/255_/346/227/240/344/272/211/350/256/256/347/220/206/350/256/272/346/226/207/346/241/243_v1.0.md +129 -129
  49. package/docs/theory//345/271/266/345/217/221/345/277/205/347/204/266/346/200/247/347/220/206/350/256/272_v0.2.md +134 -134
  50. package/docs/theory//346/231/272/350/203/275/350/256/2723.4.md +5260 -5260
  51. package/docs/theory//346/246/202/345/277/265/345/210/206/345/261/202/345/257/271/351/275/220/350/241/250_v0.1.md +145 -145
  52. package/docs/theory//347/220/206/350/256/272_/346/234/272/345/210/266_/344/273/243/347/240/201_/345/256/236/351/252/214_/347/274/272/345/217/243/347/237/251/351/230/265_v0.1.md +144 -144
  53. package/docs/theory//347/220/206/350/256/272/344/273/223/346/213/206/345/210/206/344/270/216/347/231/275/347/256/261/347/237/245/350/257/206/345/272/223/345/206/205/350/277/201_v0.1.md +198 -198
  54. package/docs/theory//350/256/244/347/237/245/344/273/243/347/220/206/344/270/216/346/224/266/346/225/233/347/273/223/346/236/204_/346/235/241/344/273/266/350/256/272/351/207/215/346/236/204_v0.1.md +221 -221
  55. package/docs/world_model//344/270/226/347/225/214/346/250/241/345/236/213_/347/245/236/347/273/217/347/275/221/347/273/234/345/272/225/345/261/202/346/236/266/346/236/204_v1.0.md +237 -237
  56. package/docs//345/217/221/345/270/203/344/273/266/345/233/236/346/272/257/350/257/264/346/230/216_v0.1.md +82 -82
  57. package/docs//345/267/245/344/275/234/347/272/252/345/276/213_/350/256/244/347/237/245/345/233/276/346/235/241/347/233/256_v1.1.json +28 -2
  58. package/dsh/README.md +82 -82
  59. package/dsh/cordis.yml.example +139 -139
  60. package/dsh/update-lingshu.bat +11 -11
  61. package/lib/hooks.js +36 -2
  62. package/lib/lib/roleplay_web.js +427 -427
  63. package/md_cg/__init__.py +7 -7
  64. package/md_cg/audit.py +368 -368
  65. package/md_cg/autonomy.py +287 -287
  66. package/md_cg/backfill.py +1327 -1327
  67. package/md_cg/backfill_bigdomain.py +34 -34
  68. package/md_cg/bench6_arms.py +410 -410
  69. package/md_cg/bench6_common.py +230 -230
  70. package/md_cg/bench6_competitors.py +212 -212
  71. package/md_cg/bench_axis_domain.py +257 -257
  72. package/md_cg/bench_blind_comp.py +308 -308
  73. package/md_cg/bench_en_atoms_public.py +230 -230
  74. package/md_cg/bench_governance.py +348 -348
  75. package/md_cg/bench_lme_zh.py +410 -410
  76. package/md_cg/bench_locomo.py +121 -121
  77. package/md_cg/bench_locomo_zh.py +450 -450
  78. package/md_cg/bench_locomo_zh_public.py +147 -147
  79. package/md_cg/bench_longmem.py +112 -112
  80. package/md_cg/bench_membench.py +632 -632
  81. package/md_cg/bench_p0.py +149 -149
  82. package/md_cg/bench_progressive.py +287 -287
  83. package/md_cg/bench_role_views.py +238 -238
  84. package/md_cg/bench_task_ab.py +243 -243
  85. package/md_cg/bench_task_ab_llm.py +408 -408
  86. package/md_cg/bench_unified_en.py +204 -204
  87. package/md_cg/bench_zh_mad.py +601 -601
  88. package/md_cg/blindspot_tickets.py +123 -123
  89. package/md_cg/branches.py +285 -285
  90. package/md_cg/build_postings.py +73 -73
  91. package/md_cg/ccgc.py +1005 -948
  92. package/md_cg/census.py +132 -132
  93. package/md_cg/chain.py +300 -300
  94. package/md_cg/codeindex.py +531 -531
  95. package/md_cg/coldverify.py +292 -292
  96. package/md_cg/comment_gate.py +337 -337
  97. package/md_cg/cond_compose.py +190 -190
  98. package/md_cg/cond_facts.py +154 -154
  99. package/md_cg/cond_template.json +106 -106
  100. package/md_cg/condition_anchor.py +142 -142
  101. package/md_cg/conformance.py +726 -726
  102. package/md_cg/consistency.py +717 -717
  103. package/md_cg/consolidate.py +1536 -1439
  104. package/md_cg/corpus.py +110 -110
  105. package/md_cg/crosscheck.py +1097 -1097
  106. package/md_cg/crypto.py +437 -437
  107. package/md_cg/d_meta.py +310 -310
  108. package/md_cg/datapath.py +334 -334
  109. package/md_cg/docindex.py +473 -473
  110. package/md_cg/eval_common.py +575 -575
  111. package/md_cg/evidence.py +580 -580
  112. package/md_cg/evolution.py +477 -477
  113. package/md_cg/export.py +220 -220
  114. package/md_cg/forgetting.py +581 -581
  115. package/md_cg/fsutil.py +329 -329
  116. package/md_cg/hotcache.py +238 -214
  117. package/md_cg/hyperedge.py +251 -251
  118. package/md_cg/identity.py +390 -390
  119. package/md_cg/insight.py +500 -500
  120. package/md_cg/interop.py +199 -0
  121. package/md_cg/lexicon/build_cedict_en_zh.py +329 -329
  122. package/md_cg/lexicon/build_standard_en.py +171 -171
  123. package/md_cg/lexicon/expand_en_zh.py +211 -211
  124. package/md_cg/lifecycle.py +272 -272
  125. package/md_cg/linkref.py +280 -280
  126. package/md_cg/links.py +622 -622
  127. package/md_cg/mcp_server.py +129 -32
  128. package/md_cg/md_whitebox.py +345 -345
  129. package/md_cg/mdcg.py +176 -117
  130. package/md_cg/mdcos.py +79 -13
  131. package/md_cg/metacognition.py +591 -591
  132. package/md_cg/migrate.py +119 -119
  133. package/md_cg/migrate_aeis.py +221 -221
  134. package/md_cg/migrate_roleplay.py +293 -293
  135. package/md_cg/migrate_wisdom_graph.py +360 -360
  136. package/md_cg/mreview/__init__.py +25 -25
  137. package/md_cg/mreview/__main__.py +110 -110
  138. package/md_cg/mreview/bundle.py +178 -178
  139. package/md_cg/mreview/candidates.py +262 -262
  140. package/md_cg/mreview/govern.py +693 -693
  141. package/md_cg/mreview/locate.py +939 -939
  142. package/md_cg/mreview/pipeline.py +728 -728
  143. package/md_cg/mreview/rules/duplication.json +21 -21
  144. package/md_cg/mreview/rules/field_coverage.json +54 -54
  145. package/md_cg/mreview/rules/source_license.json +21 -21
  146. package/md_cg/mreview/rules/template_flow.json +21 -21
  147. package/md_cg/mreview/ruleset.py +252 -252
  148. package/md_cg/nodefile.py +575 -575
  149. package/md_cg/pooling.py +484 -472
  150. package/md_cg/postings.py +298 -298
  151. package/md_cg/predict.py +1100 -1100
  152. package/md_cg/progressive.py +123 -123
  153. package/md_cg/protect.py +272 -272
  154. package/md_cg/protocol/md_cg_gate.proto +33 -33
  155. package/md_cg/protocol.py +372 -372
  156. package/md_cg/provenance.py +582 -582
  157. package/md_cg/reach.py +453 -453
  158. package/md_cg/readcache.py +85 -0
  159. package/md_cg/refindex.py +833 -833
  160. package/md_cg/refine.py +604 -604
  161. package/md_cg/roleviews.py +89 -89
  162. package/md_cg/routing.py +365 -365
  163. package/md_cg/scrub.py +852 -852
  164. package/md_cg/security.py +274 -274
  165. package/md_cg/self_state.py +1029 -1029
  166. package/md_cg/selfreport.py +151 -151
  167. package/md_cg/semantic/__init__.py +10 -10
  168. package/md_cg/semantic/canonical.py +122 -122
  169. package/md_cg/semantic/en_normalizer.py +364 -364
  170. package/md_cg/semantic/en_zh_map.json +28694 -0
  171. package/md_cg/semantic/export_en_zh_map.py +64 -0
  172. package/md_cg/semantic/unify.py +45 -0
  173. package/md_cg/semantic/zh_en_atoms.py +139 -139
  174. package/md_cg/signer.py +562 -562
  175. package/md_cg/sources.py +815 -582
  176. package/md_cg/statushdr.py +179 -179
  177. package/md_cg/stg.py +48 -37
  178. package/md_cg/subgraph.py +729 -729
  179. package/md_cg/sustain.py +1138 -1138
  180. package/md_cg/tasks.py +470 -470
  181. package/md_cg/test_action_derive.py +203 -203
  182. package/md_cg/test_audit_rotate.py +270 -270
  183. package/md_cg/test_autonomy.py +143 -143
  184. package/md_cg/test_bench_governance.py +102 -102
  185. package/md_cg/test_blindspot_tickets.py +166 -166
  186. package/md_cg/test_branches.py +249 -249
  187. package/md_cg/test_ccg_perturb.py +184 -184
  188. package/md_cg/test_ccgc.py +433 -433
  189. package/md_cg/test_census_prune.py +81 -81
  190. package/md_cg/test_cond_compose_anchors.py +76 -76
  191. package/md_cg/test_cond_match.py +165 -165
  192. package/md_cg/test_condition_anchor.py +81 -81
  193. package/md_cg/test_d_meta.py +412 -412
  194. package/md_cg/test_datapath_root.py +199 -199
  195. package/md_cg/test_en_pipeline.py +166 -166
  196. package/md_cg/test_gain_gate.py +212 -212
  197. package/md_cg/test_health_scale.py +173 -173
  198. package/md_cg/test_hive_ingest.py +285 -0
  199. package/md_cg/test_hot_cold.py +215 -215
  200. package/md_cg/test_hyperedge.py +245 -245
  201. package/md_cg/test_i26_empty_first_write.py +116 -0
  202. package/md_cg/test_i27_e041_identity.py +128 -0
  203. package/md_cg/test_i28_hotcache_prodpath.py +122 -0
  204. package/md_cg/test_identity_attribution.py +147 -147
  205. package/md_cg/test_index_durability.py +224 -224
  206. package/md_cg/test_interop.py +93 -0
  207. package/md_cg/test_lifecycle.py +309 -309
  208. package/md_cg/test_linkref.py +306 -306
  209. package/md_cg/test_lock.py +43 -43
  210. package/md_cg/test_md_access_parity.py +255 -255
  211. package/md_cg/test_md_writepath.py +345 -345
  212. package/md_cg/test_mdstore_search_parity.py +160 -0
  213. package/md_cg/test_mr_m2.py +587 -587
  214. package/md_cg/test_mr_m3.py +710 -710
  215. package/md_cg/test_mr_m4.py +485 -485
  216. package/md_cg/test_p0.py +250 -250
  217. package/md_cg/test_p1.py +316 -316
  218. package/md_cg/test_p10_identity.py +173 -173
  219. package/md_cg/test_p11_consistency.py +233 -233
  220. package/md_cg/test_p12_metacognition.py +212 -212
  221. package/md_cg/test_p13_encryption.py +241 -241
  222. package/md_cg/test_p14_sustain.py +249 -249
  223. package/md_cg/test_p15_scrub.py +280 -280
  224. package/md_cg/test_p16_self_state.py +301 -301
  225. package/md_cg/test_p17_predict.py +354 -354
  226. package/md_cg/test_p18_whitebox.py +171 -171
  227. package/md_cg/test_p19_migrate_roleplay.py +149 -149
  228. package/md_cg/test_p20_evolution.py +315 -315
  229. package/md_cg/test_p21_tokens.py +293 -270
  230. package/md_cg/test_p22_theory.py +175 -175
  231. package/md_cg/test_p23_links.py +311 -311
  232. package/md_cg/test_p24_evidence.py +227 -227
  233. package/md_cg/test_p25_weights.py +156 -156
  234. package/md_cg/test_p26_refindex.py +416 -416
  235. package/md_cg/test_p27_docindex.py +765 -765
  236. package/md_cg/test_p28_refcheck.py +305 -305
  237. package/md_cg/test_p29_session_ingest_export.py +354 -333
  238. package/md_cg/test_p3.py +11 -2
  239. package/md_cg/test_p30_maintain.py +330 -330
  240. package/md_cg/test_p31_insight.py +534 -534
  241. package/md_cg/test_p32_backfill.py +298 -298
  242. package/md_cg/test_p33_ccg_wiring.py +293 -293
  243. package/md_cg/test_p34_crosscheck.py +331 -331
  244. package/md_cg/test_p35_conditioned_claim.py +252 -252
  245. package/md_cg/test_p36_kp_align.py +230 -230
  246. package/md_cg/test_p37_condition_space.py +248 -248
  247. package/md_cg/test_p38_concurrent_flush.py +102 -0
  248. package/md_cg/test_p38_contextualize.py +273 -273
  249. package/md_cg/test_p39_verify_flow.py +113 -0
  250. package/md_cg/test_p39_vision_evidence.py +369 -369
  251. package/md_cg/test_p40_refine_worklist.py +241 -241
  252. package/md_cg/test_p41_evolve_patrol.py +224 -224
  253. package/md_cg/test_p42_provenance.py +269 -269
  254. package/md_cg/test_p43_pooling.py +412 -398
  255. package/md_cg/test_p44_md_whitebox.py +231 -231
  256. package/md_cg/test_p45_session_identity.py +219 -219
  257. package/md_cg/test_p46_unit_scope.py +272 -272
  258. package/md_cg/test_p47_session_view.py +281 -0
  259. package/md_cg/test_p4_fuzzy.py +223 -223
  260. package/md_cg/test_p5_semantic.py +226 -226
  261. package/md_cg/test_p6_consolidate.py +440 -387
  262. package/md_cg/test_p7_goals_recent.py +202 -202
  263. package/md_cg/test_p8_subgraph_chain.py +200 -200
  264. package/md_cg/test_p9_forget_protect.py +231 -231
  265. package/md_cg/test_predict_beta.py +135 -135
  266. package/md_cg/test_preflight_failclosed.py +100 -100
  267. package/md_cg/test_progressive.py +146 -146
  268. package/md_cg/test_protocol.py +243 -243
  269. package/md_cg/test_reach.py +378 -378
  270. package/md_cg/test_reach_keys.py +201 -201
  271. package/md_cg/test_read_clip.py +141 -141
  272. package/md_cg/test_readcache_prodpath.py +155 -0
  273. package/md_cg/test_retr_gates_prodpath.py +140 -0
  274. package/md_cg/test_retr_s1.py +340 -340
  275. package/md_cg/test_retr_s1b.py +209 -209
  276. package/md_cg/test_retr_s3.py +194 -194
  277. package/md_cg/test_retr_s4.py +163 -163
  278. package/md_cg/test_retr_s5.py +200 -200
  279. package/md_cg/test_retr_s6.py +157 -157
  280. package/md_cg/test_retr_s7.py +384 -384
  281. package/md_cg/test_retr_s8_time.py +369 -316
  282. package/md_cg/test_retr_s9_edges.py +286 -286
  283. package/md_cg/test_retr_s9_entity_ctx.py +175 -175
  284. package/md_cg/test_review_conformance.py +367 -367
  285. package/md_cg/test_role_views.py +354 -354
  286. package/md_cg/test_sem_noise.py +242 -242
  287. package/md_cg/test_semantic_canonical.py +241 -241
  288. package/md_cg/test_subproc_encoding.py +192 -192
  289. package/md_cg/test_sustain_mutual.py +153 -153
  290. package/md_cg/test_tasks.py +409 -409
  291. package/md_cg/test_tool_face.py +189 -189
  292. package/md_cg/test_transfer.py +180 -180
  293. package/md_cg/test_trust.py +361 -361
  294. package/md_cg/test_twophase.py +286 -286
  295. package/md_cg/test_v14_fixes.py +397 -397
  296. package/md_cg/test_validity_filter.py +280 -280
  297. package/md_cg/test_verify_answer.py +138 -138
  298. package/md_cg/test_wisdom_md_store.py +292 -292
  299. package/md_cg/test_writelimit.py +197 -197
  300. package/md_cg/test_writepipe.py +214 -214
  301. package/md_cg/theory.py +273 -273
  302. package/md_cg/tokens.py +677 -663
  303. package/md_cg/tool_face.py +260 -260
  304. package/md_cg/trust.py +986 -950
  305. package/md_cg/twophase.py +231 -231
  306. package/md_cg/units.py +667 -667
  307. package/md_cg/vision_evidence.py +666 -666
  308. package/md_cg/weights.py +624 -624
  309. package/md_cg/whitebox.py +527 -527
  310. package/md_cg/whitebox_kb/__init__.py +37 -37
  311. package/md_cg/whitebox_kb/aeis_core/__init__.py +42 -42
  312. package/md_cg/whitebox_kb/aeis_core/semantic.py +280 -280
  313. package/md_cg/whitebox_kb/aeis_core/textutil.py +13 -13
  314. package/md_cg/whitebox_kb/engine.py +310 -310
  315. package/md_cg/whitebox_kb/seed_knowledge//346/231/272/350/203/275/350/256/2723.4.md +5260 -5260
  316. package/md_cg/whitebox_kb/wisdom/browser_units.py +2631 -2631
  317. package/md_cg/whitebox_kb/wisdom/causal_discover.py +432 -432
  318. package/md_cg/whitebox_kb/wisdom/chat_engine.py +1506 -1506
  319. package/md_cg/whitebox_kb/wisdom/code_solidified.json +6195 -6195
  320. package/md_cg/whitebox_kb/wisdom/compiler_code_units.py +3033 -3033
  321. package/md_cg/whitebox_kb/wisdom/condition_algebra.py +112 -112
  322. package/md_cg/whitebox_kb/wisdom/condition_frame.py +315 -315
  323. package/md_cg/whitebox_kb/wisdom/condition_kb.py +108 -108
  324. package/md_cg/whitebox_kb/wisdom/conflict_map.json +4445 -4445
  325. package/md_cg/whitebox_kb/wisdom/core/lexer.py +512 -512
  326. package/md_cg/whitebox_kb/wisdom/core/name_checker.py +1023 -1023
  327. package/md_cg/whitebox_kb/wisdom/cspmn.py +258 -258
  328. package/md_cg/whitebox_kb/wisdom/csre.py +264 -264
  329. package/md_cg/whitebox_kb/wisdom/danmaku_audit.py +252 -252
  330. package/md_cg/whitebox_kb/wisdom/distilled_condition_units.json +6417 -6417
  331. package/md_cg/whitebox_kb/wisdom/docs/WB-EVAL-20260902b.json +1950 -1950
  332. package/md_cg/whitebox_kb/wisdom/docs/WB-EVAL-20260902c.json +1296 -1296
  333. package/md_cg/whitebox_kb/wisdom/docs/whitebox_capability_graph_demo.json +59 -59
  334. package/md_cg/whitebox_kb/wisdom/graph_db_units.py +3089 -3089
  335. package/md_cg/whitebox_kb/wisdom/knowledge_points.py +318 -318
  336. package/md_cg/whitebox_kb/wisdom/md_access.py +470 -470
  337. package/md_cg/whitebox_kb/wisdom/md_store.py +276 -251
  338. package/md_cg/whitebox_kb/wisdom/migrate_wisdom.py +476 -476
  339. package/md_cg/whitebox_kb/wisdom/navigate.py +248 -248
  340. package/md_cg/whitebox_kb/wisdom/neural_retrieve.py +224 -224
  341. package/md_cg/whitebox_kb/wisdom/os_units.py +2735 -2735
  342. package/md_cg/whitebox_kb/wisdom/pattern_separation.py +376 -376
  343. package/md_cg/whitebox_kb/wisdom/prereq_map.json +364 -364
  344. package/md_cg/whitebox_kb/wisdom/python_code_units.py +2766 -2766
  345. package/md_cg/whitebox_kb/wisdom/role_solidified.json +7 -7
  346. package/md_cg/whitebox_kb/wisdom/route_memory.py +244 -244
  347. package/md_cg/whitebox_kb/wisdom/scene_reconstruction.py +148 -148
  348. package/md_cg/whitebox_kb/wisdom/snr_report.json +40 -40
  349. package/md_cg/whitebox_kb/wisdom/test_code_compose_domains.py +7541 -7541
  350. package/md_cg/whitebox_kb/wisdom/test_compiler_self_bootstrap.py +354 -354
  351. package/md_cg/whitebox_kb/wisdom/test_ecosystem_assembly.py +158 -158
  352. package/md_cg/whitebox_kb/wisdom/test_ecosystem_demos.py +193 -193
  353. package/md_cg/whitebox_kb/wisdom/test_graph_db.py +292 -292
  354. package/md_cg/whitebox_kb/wisdom/test_python_self_bootstrap.py +160 -160
  355. package/md_cg/whitebox_kb/wisdom/trigger_words_index.json +4366 -4366
  356. package/md_cg/whitebox_kb/wisdom/verifier.py +1297 -1297
  357. package/md_cg/writelimit.py +356 -356
  358. package/md_cg/writepipe.py +550 -542
  359. package/package.json +97 -96
  360. package/skills/plugin.json +54 -54
  361. package/skills/skills/designer-perspective/SKILL.md +158 -158
  362. package/skills/skills/designer-perspective/references/01-observation-position.md +66 -66
  363. package/skills/skills/designer-perspective/references/02-structure-recognition.md +62 -62
  364. package/skills/skills/designer-perspective/references/03-direction-judgment.md +55 -55
  365. package/skills/skills/designer-perspective/references/04-qualification-verdict.md +72 -72
  366. package/skills/skills/designer-perspective/references/05-condition-attribution.md +74 -74
  367. package/skills/skills/designer-perspective/scripts/designer.py +545 -545
  368. package/skills/skills/designer-perspective/tests/cases.jsonl +17 -17
  369. package/skills/skills/designer-perspective/tests/selftest.py +61 -61
  370. package/skills/skills/lingshu-browser/SKILL.md +60 -60
  371. package/skills/skills/lingshu-compiler/SKILL.md +56 -56
  372. package/skills/skills/lingshu-compiler/units/analyze-type-infer/SKILL.md +45 -45
  373. package/skills/skills/lingshu-compiler/units/check-name-real/SKILL.md +45 -45
  374. package/skills/skills/lingshu-compiler/units/compile-assign/SKILL.md +45 -45
  375. package/skills/skills/lingshu-compiler/units/compile-expr-tree/SKILL.md +45 -45
  376. package/skills/skills/lingshu-compiler/units/compile-full-pipeline/SKILL.md +45 -45
  377. package/skills/skills/lingshu-compiler/units/compile-func-def/SKILL.md +45 -45
  378. package/skills/skills/lingshu-compiler/units/compile-if-then/SKILL.md +45 -45
  379. package/skills/skills/lingshu-compiler/units/compile-logic-expr/SKILL.md +45 -45
  380. package/skills/skills/lingshu-compiler/units/compile-recursive/SKILL.md +45 -45
  381. package/skills/skills/lingshu-compiler/units/compile-scope/SKILL.md +45 -45
  382. package/skills/skills/lingshu-compiler/units/compile-type-check/SKILL.md +45 -45
  383. package/skills/skills/lingshu-compiler/units/compile-while/SKILL.md +45 -45
  384. package/skills/skills/lingshu-compiler/units/compiler-0010c4bf/SKILL.md +45 -45
  385. package/skills/skills/lingshu-compiler/units/compiler-0355bffb/SKILL.md +45 -45
  386. package/skills/skills/lingshu-compiler/units/compiler-0361708a/SKILL.md +45 -45
  387. package/skills/skills/lingshu-compiler/units/compiler-054a0414/SKILL.md +45 -45
  388. package/skills/skills/lingshu-compiler/units/compiler-05a1691a/SKILL.md +45 -45
  389. package/skills/skills/lingshu-compiler/units/compiler-05eeed1e/SKILL.md +45 -45
  390. package/skills/skills/lingshu-compiler/units/compiler-0622a1f6/SKILL.md +45 -45
  391. package/skills/skills/lingshu-compiler/units/compiler-08b54217/SKILL.md +45 -45
  392. package/skills/skills/lingshu-compiler/units/compiler-0a62b70c/SKILL.md +45 -45
  393. package/skills/skills/lingshu-compiler/units/compiler-0ab24d00/SKILL.md +45 -45
  394. package/skills/skills/lingshu-compiler/units/compiler-0e093688/SKILL.md +45 -45
  395. package/skills/skills/lingshu-compiler/units/compiler-0e82b966/SKILL.md +45 -45
  396. package/skills/skills/lingshu-compiler/units/compiler-0ee9b9b9/SKILL.md +45 -45
  397. package/skills/skills/lingshu-compiler/units/compiler-0f3787e6/SKILL.md +45 -45
  398. package/skills/skills/lingshu-compiler/units/compiler-1028685f/SKILL.md +45 -45
  399. package/skills/skills/lingshu-compiler/units/compiler-11897630/SKILL.md +45 -45
  400. package/skills/skills/lingshu-compiler/units/compiler-16661b9b/SKILL.md +45 -45
  401. package/skills/skills/lingshu-compiler/units/compiler-1f722303/SKILL.md +45 -45
  402. package/skills/skills/lingshu-compiler/units/compiler-25be1262/SKILL.md +45 -45
  403. package/skills/skills/lingshu-compiler/units/compiler-2a76ba07/SKILL.md +45 -45
  404. package/skills/skills/lingshu-compiler/units/compiler-2dbea54a/SKILL.md +45 -45
  405. package/skills/skills/lingshu-compiler/units/compiler-2df52f16/SKILL.md +45 -45
  406. package/skills/skills/lingshu-compiler/units/compiler-2ec2c9d2/SKILL.md +45 -45
  407. package/skills/skills/lingshu-compiler/units/compiler-2f8c8f39/SKILL.md +45 -45
  408. package/skills/skills/lingshu-compiler/units/compiler-38378ac7/SKILL.md +45 -45
  409. package/skills/skills/lingshu-compiler/units/compiler-39457d2e/SKILL.md +45 -45
  410. package/skills/skills/lingshu-compiler/units/compiler-39fb5926/SKILL.md +45 -45
  411. package/skills/skills/lingshu-compiler/units/compiler-47f4fbfa/SKILL.md +45 -45
  412. package/skills/skills/lingshu-compiler/units/compiler-4a8cd1f1/SKILL.md +45 -45
  413. package/skills/skills/lingshu-compiler/units/compiler-4b230b6b/SKILL.md +45 -45
  414. package/skills/skills/lingshu-compiler/units/compiler-4cbbda95/SKILL.md +45 -45
  415. package/skills/skills/lingshu-compiler/units/compiler-4d5a68ff/SKILL.md +45 -45
  416. package/skills/skills/lingshu-compiler/units/compiler-56dc9bdd/SKILL.md +45 -45
  417. package/skills/skills/lingshu-compiler/units/compiler-57e76ebe/SKILL.md +45 -45
  418. package/skills/skills/lingshu-compiler/units/compiler-61ff016b/SKILL.md +45 -45
  419. package/skills/skills/lingshu-compiler/units/compiler-63eae588/SKILL.md +45 -45
  420. package/skills/skills/lingshu-compiler/units/compiler-64c4224b/SKILL.md +45 -45
  421. package/skills/skills/lingshu-compiler/units/compiler-66377955/SKILL.md +45 -45
  422. package/skills/skills/lingshu-compiler/units/compiler-674ab4f6/SKILL.md +45 -45
  423. package/skills/skills/lingshu-compiler/units/compiler-6af76fd6/SKILL.md +45 -45
  424. package/skills/skills/lingshu-compiler/units/compiler-6d979db2/SKILL.md +45 -45
  425. package/skills/skills/lingshu-compiler/units/compiler-6de326c0/SKILL.md +45 -45
  426. package/skills/skills/lingshu-compiler/units/compiler-6f1c0eea/SKILL.md +45 -45
  427. package/skills/skills/lingshu-compiler/units/compiler-724d6c9b/SKILL.md +45 -45
  428. package/skills/skills/lingshu-compiler/units/compiler-7690177f/SKILL.md +45 -45
  429. package/skills/skills/lingshu-compiler/units/compiler-7b229a7d/SKILL.md +45 -45
  430. package/skills/skills/lingshu-compiler/units/compiler-7f471b3a/SKILL.md +45 -45
  431. package/skills/skills/lingshu-compiler/units/compiler-815cad08/SKILL.md +45 -45
  432. package/skills/skills/lingshu-compiler/units/compiler-83c61634/SKILL.md +45 -45
  433. package/skills/skills/lingshu-compiler/units/compiler-8c798c81/SKILL.md +45 -45
  434. package/skills/skills/lingshu-compiler/units/compiler-8dd747ac/SKILL.md +45 -45
  435. package/skills/skills/lingshu-compiler/units/compiler-90324d0a/SKILL.md +45 -45
  436. package/skills/skills/lingshu-compiler/units/compiler-94b8d72d/SKILL.md +45 -45
  437. package/skills/skills/lingshu-compiler/units/compiler-94f12231/SKILL.md +45 -45
  438. package/skills/skills/lingshu-compiler/units/compiler-95937c16/SKILL.md +45 -45
  439. package/skills/skills/lingshu-compiler/units/compiler-98a5625b/SKILL.md +45 -45
  440. package/skills/skills/lingshu-compiler/units/compiler-98b4c42f/SKILL.md +45 -45
  441. package/skills/skills/lingshu-compiler/units/compiler-98e3894a/SKILL.md +45 -45
  442. package/skills/skills/lingshu-compiler/units/compiler-9bdfe4b8/SKILL.md +45 -45
  443. package/skills/skills/lingshu-compiler/units/compiler-9d9b4e83/SKILL.md +45 -45
  444. package/skills/skills/lingshu-compiler/units/compiler-9f7be5ad/SKILL.md +45 -45
  445. package/skills/skills/lingshu-compiler/units/compiler-a6daf076/SKILL.md +45 -45
  446. package/skills/skills/lingshu-compiler/units/compiler-a7995a0c/SKILL.md +45 -45
  447. package/skills/skills/lingshu-compiler/units/compiler-a8399248/SKILL.md +45 -45
  448. package/skills/skills/lingshu-compiler/units/compiler-aabbd099/SKILL.md +45 -45
  449. package/skills/skills/lingshu-compiler/units/compiler-afe169d8/SKILL.md +45 -45
  450. package/skills/skills/lingshu-compiler/units/compiler-b0678bda/SKILL.md +45 -45
  451. package/skills/skills/lingshu-compiler/units/compiler-b09bd196/SKILL.md +45 -45
  452. package/skills/skills/lingshu-compiler/units/compiler-b1396e23/SKILL.md +45 -45
  453. package/skills/skills/lingshu-compiler/units/compiler-b9b31ce0/SKILL.md +45 -45
  454. package/skills/skills/lingshu-compiler/units/compiler-c10264a7/SKILL.md +45 -45
  455. package/skills/skills/lingshu-compiler/units/compiler-cb1e8e4b/SKILL.md +45 -45
  456. package/skills/skills/lingshu-compiler/units/compiler-ccafd438/SKILL.md +45 -45
  457. package/skills/skills/lingshu-compiler/units/compiler-cda9c262/SKILL.md +45 -45
  458. package/skills/skills/lingshu-compiler/units/compiler-ce648068/SKILL.md +45 -45
  459. package/skills/skills/lingshu-compiler/units/compiler-cf5776a4/SKILL.md +45 -45
  460. package/skills/skills/lingshu-compiler/units/compiler-d974e5d3/SKILL.md +45 -45
  461. package/skills/skills/lingshu-compiler/units/compiler-e3979fd3/SKILL.md +45 -45
  462. package/skills/skills/lingshu-compiler/units/compiler-eb1cf2b5/SKILL.md +45 -45
  463. package/skills/skills/lingshu-compiler/units/compiler-ecb30d5b/SKILL.md +45 -45
  464. package/skills/skills/lingshu-compiler/units/compiler-f8c8b24b/SKILL.md +45 -45
  465. package/skills/skills/lingshu-compiler/units/compiler-f99fedbe/SKILL.md +45 -45
  466. package/skills/skills/lingshu-compiler/units/compiler-fa8ff5f7/SKILL.md +45 -45
  467. package/skills/skills/lingshu-compiler/units/compiler-fe1b058d/SKILL.md +45 -45
  468. package/skills/skills/lingshu-compiler/units/lex-chinese-program/SKILL.md +45 -45
  469. package/skills/skills/lingshu-compiler/units/lex-dao-de-jing/SKILL.md +45 -45
  470. package/skills/skills/lingshu-compiler/units/lex-nine-chapters/SKILL.md +45 -45
  471. package/skills/skills/lingshu-compiler/units/vm-arithmetic/SKILL.md +45 -45
  472. package/skills/skills/lingshu-compiler/units/vm-array-ops/SKILL.md +45 -45
  473. package/skills/skills/lingshu-compiler/units/vm-closure-call/SKILL.md +45 -45
  474. package/skills/skills/lingshu-compiler/units/vm-closure-create/SKILL.md +45 -45
  475. package/skills/skills/lingshu-compiler/units/vm-compare/SKILL.md +45 -45
  476. package/skills/skills/lingshu-compiler/units/vm-cond-jump/SKILL.md +45 -45
  477. package/skills/skills/lingshu-compiler/units/vm-cond-space/SKILL.md +45 -45
  478. package/skills/skills/lingshu-compiler/units/vm-exception/SKILL.md +45 -45
  479. package/skills/skills/lingshu-compiler/units/vm-func-call/SKILL.md +45 -45
  480. package/skills/skills/lingshu-compiler/units/vm-loop-run/SKILL.md +45 -45
  481. package/skills/skills/lingshu-compiler/units/vm-profiling/SKILL.md +45 -45
  482. package/skills/skills/lingshu-compiler/units/vm-refcount/SKILL.md +45 -45
  483. package/skills/skills/lingshu-compiler/units/vm-run-loop/SKILL.md +45 -45
  484. package/skills/skills/lingshu-compiler/units/vm-short-circuit/SKILL.md +45 -45
  485. package/skills/skills/lingshu-compiler/units/vm-stack-guard/SKILL.md +45 -45
  486. package/skills/skills/lingshu-compiler/units/vm-stack-ops/SKILL.md +45 -45
  487. package/skills/skills/lingshu-compiler/units/vm-trust-accum/SKILL.md +45 -45
  488. package/skills/skills/lingshu-graph/SKILL.md +63 -63
  489. package/skills/skills/lingshu-net/SKILL.md +48 -48
  490. package/skills/skills/lingshu-os/SKILL.md +64 -64
  491. package/skills/skills/lingshu-pylang/SKILL.md +71 -71
  492. package/src/bridge.ts +401 -401
  493. package/src/hooks.ts +38 -2
  494. package/src/lib/datapath.ts +326 -326
  495. package/src/lib/mdcg_client.ts +413 -413
  496. package/src/lib/mutual.ts +428 -428
  497. package/src/lib/prompt_safety.ts +62 -62
  498. package/src/lib/python_path.ts +71 -71
  499. package/src/lib/roleplay_web.ts +932 -932
  500. package/src/lib/token_store.ts +192 -192
  501. package/src/tools.ts +212 -212
  502. package/zcode/AGENTS.md +11 -3
  503. package/zcode/README.md +41 -41
  504. /package/docs/{mdcg → hive}//344/270/273/344/273/243/347/220/206/345/255/220/344/273/243/347/220/206/350/256/260/345/277/206/346/236/266/346/236/204/350/256/276/350/256/241.md" +0 -0
@@ -1,411 +1,411 @@
1
- # -*- coding: utf-8 -*-
2
- """六系统横评(bench6)· 主进程臂:灵枢 / 纯向量 RAG + 统一评分。
3
-
4
- 四家 LLM 竞品(mem0/Graphiti/GraphRAG/Letta)依赖互斥,跑在各自 venv 的独立
5
- 脚本里(外部评测工作区的 bench6 适配脚本),只回吐 {qid: [id...]} 的 JSON;本模块
6
- 读回后与灵枢/向量臂走**同一个** bc.rows_from_hits → ec.summarize,保证六家同口径
7
- (排名判据复用 ec.first_evidence_rank,指标复用 ec.summarize,均不重造)。
8
-
9
- 灵枢三种检索口径(同一份中文层 + 英文原文,只变检索路):
10
- lex : 单词法路,且建库不加 tags/condition_space——复现公开参考量级
11
- (词法 hit@1≈0.936)的**回归锚**,用于确认本次口径没有漂移
12
- rrf4 : 四路 RRF(lexical,bucket,entity,graph)+ 传 context——用户选定口径
13
- rrf4_noref : 四路 RRF 不传 context——名义四路,量化条件约束路的净效应
14
-
15
- ## 为什么灵枢要建两个库而不是一个
16
- lex 臂必须与 `bench_locomo_zh_public.build_pool` **逐字同口径**(无 tags、无
17
- condition_space)才能作回归锚;而 rrf4 臂按用户口径要喂 entity 路(tags)与
18
- bucket 路(condition_space)。建库参数不同 → 目录不同 → 拆成两个 ROOT,避免
19
- "复用已建库"逻辑把两种口径混成一个。
20
-
21
- ## 诚实边界
22
- locomo-zh-500 是**单域**会话语料,且查询侧是**无情境标注**的关键词串。bucket 路
23
- 要求读写两侧 `route_key` 同构(routing.py 模块头「风险2」)——写侧有域、读侧
24
- 没有,故条件路由在本语料上预期无区分力。这一点由实测的桶健康度取证,不预设。
25
- """
26
- from __future__ import annotations
27
-
28
- import json
29
- import math
30
- import os
31
- import shutil
32
- import sys
33
- import time
34
- import urllib.error
35
- import urllib.request
36
-
37
- HERE = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
38
- for _p in (HERE, os.path.join(HERE, "md_cg")):
39
- if _p not in sys.path:
40
- sys.path.insert(0, _p)
41
-
42
- from md_cg import bench6_common as bc # noqa: E402
43
- from md_cg import eval_common as ec # noqa: E402
44
-
45
- ROOT_BASE = os.path.join(HERE, "_md_cg_eval_bench6") # .gitignore 的 /_md_cg_eval_*/ 已覆盖
46
-
47
- # 条件约束路的查询侧情境:所有题共用同一份默认情境(查询串本身无情境标注)。
48
- # 与建库侧 condition_space 同构 → route_key 两侧落在同一键上。这是 bucket 路能被
49
- # 开启的唯一合法构造方式;若查询侧能精确给出每题的场景/域,那已是使用 qrels 作弊。
50
- QUERY_CONTEXT = {
51
- "observation_position": "会话陈述",
52
- "observation_tool": "会话记录",
53
- "existence_constraint": "公开",
54
- }
55
-
56
-
57
- # 生效条件:形参 c 若提供映射接口,则取 c["zh_fields"](缺失或假值回落 {})再取其 "condition"(缺失或假值回落 {}),返回三槽 observation_position/observation_tool/existence_constraint,各自以 cond.get(中文键, "") 取值——中文键缺失时回落空串,键存在而值为 None 时结果即为 None(不回落)。
58
- def cond_of(c):
59
- """zh_fields.condition(中文三槽)→ mdcos 期望的英文槽名。
60
-
61
- 只映射 zh_fields 里**真实存在**的三槽,不臆造 time_window(写入侧会自行补)。
62
- """
63
- cond = (c.get("zh_fields") or {}).get("condition") or {}
64
- return {"observation_position": cond.get("观测位置", ""),
65
- "observation_tool": cond.get("观测工具", ""),
66
- "existence_constraint": cond.get("存在约束", "")}
67
-
68
-
69
- # 生效条件:形参 c 若提供映射接口,则 f = c["zh_fields"] 为假值(缺失/None/{})时当作 {},返回 [str(f["identity"] 或 "")] + [str(t) for t in (f["terms"] 或 [])]:identity 缺失或假值时首元素为空串(列表恒有 1 项),terms 缺失或假值时只有首元素。
70
- def tags_of(c):
71
- """喂 entity 路的裸词 tags = identity + terms。
72
-
73
- 刻意不加 `ent:` 前缀:`mdcos._path_entity` 的判据是 `t in query or query in t`,
74
- 带前缀的标签在自然查询下永不命中(既有实测教训)。也不加 `domain:`——那会
75
- 劫持 route_key 的 domain 分支,把 bucket 路变成按场景分桶,而查询侧无法复现
76
- 同一场景键(见模块头「诚实边界」)。
77
- """
78
- f = c.get("zh_fields") or {}
79
- return [str(f.get("identity") or "")] + [str(t) for t in (f.get("terms") or [])]
80
-
81
-
82
- # 生效条件:类无 __init__,实例化无需任何形参;其 describe_ingest(nids) 对任意 nids(含空)恒返回 [],而 reset()、add(nid, text)、search(query, k=5) 对任意实参一律抛 NotImplementedError。
83
- class Adapter:
84
- """统一适配接口。六家一律只回吐 id 列表,指标计算交回 bench6_common。"""
85
- name = "adapter"
86
-
87
- # 生效条件:无可选/必需形参,任何调用一律抛 NotImplementedError(基类接口桩)。
88
- def reset(self):
89
- raise NotImplementedError
90
-
91
- # 生效条件:对任意 nid 与 text 一律抛 NotImplementedError(形参不参与任何判断)。
92
- def add(self, nid, text):
93
- raise NotImplementedError
94
-
95
- # 生效条件:对任意 query 与任意 k(默认 5)一律抛 NotImplementedError,不返回结果。
96
- def search(self, query, k=5):
97
- raise NotImplementedError
98
-
99
- # 生效条件:对任意 nids(包括空列表或 None)都直接返回空列表 [],不读取任何存储。
100
- def describe_ingest(self, nids):
101
- """回读真实存储内容样本,用于取证「入库语言与入库形态」。"""
102
- return []
103
-
104
-
105
- # 生效条件:必须以 rows、variant、paths 三个必需形参构造(context 默认 None、with_meta 默认 False、rebuild 默认 False 可选),构造后 search(query, k=5) 是否向 search_rrf 传 context 由 context 是否为 None 决定,describe_ingest(nids)/bucket_health() 的取证内容取决于 variant 对应 root 库的索引状态。
106
- class LingshuAdapter(Adapter):
107
- """灵枢臂:进程内 MdCGOS。
108
-
109
- with_meta=True 时三口径共用一库(lex 需与公开脚本同库,故 lex 单独建)。
110
- """
111
-
112
- name = "lingshu"
113
-
114
- # 生效条件:root 固定为 os.path.join(ROOT_BASE, variant);rebuild 为真且 os.path.isdir(root) 为真时先 rmtree,索引中已有节点数 ≥ len(rows) 时直接 return(幂等复用、不写库),否则按 rows 逐条 add(with_meta 为真时同时补 tags=tags_of(c)、condition_space=cond_of(c))后 flush。
115
- def __init__(self, rows, variant, paths, context=None, with_meta=False,
116
- rebuild=False):
117
- from md_cg.bench_locomo_zh_public import body_of
118
- from md_cg.mdcos import MdCGOS
119
-
120
- self.variant = variant
121
- self.paths = tuple(paths)
122
- self.context = context
123
- self._body_of = body_of
124
- root = os.path.join(ROOT_BASE, variant)
125
- self.root = root
126
- if rebuild and os.path.isdir(root):
127
- shutil.rmtree(root, ignore_errors=True)
128
- self.cg = MdCGOS(root, autoflush=500)
129
- if len(self.cg.index["nodes"]) >= len(rows):
130
- return # 幂等复用
131
- t0 = time.time()
132
- for c in rows:
133
- kw = {}
134
- if with_meta:
135
- kw["tags"] = tags_of(c)
136
- kw["condition_space"] = cond_of(c)
137
- self.cg.add(c["id"], body_of(c), layer="knowledge",
138
- eval_src="bench6:locomo-zh-500",
139
- verification_basis="data", **kw)
140
- self.cg.flush()
141
- print(" [lingshu/%s] 建库 %d 节点 %.1fs"
142
- % (variant, len(self.cg.index["nodes"]), time.time() - t0))
143
-
144
- # 生效条件:给定 query 与 k(默认 5)即调用 self.cg.search_rrf(k=k、paths=self.paths、judge=False、record=False),仅当 self.context 不为 None 时附加 context 参数,返回每个结果 r 的 r[0]["id"] 组成的列表。
145
- def search(self, query, k=5):
146
- kw = {"context": self.context} if self.context is not None else {}
147
- res, _meta = self.cg.search_rrf(query, k=k, paths=self.paths,
148
- judge=False, record=False, **kw)
149
- return [r[0]["id"] for r in res]
150
-
151
- # 生效条件:只遍历 nids[:2],节点索引中 .get(nid) 为假值(缺失)的 nid 被跳过,其余按 os.path.join(self.cg.root, e["path"]) 读文件头 300 字符,抛 OSError 时 file_head 保持空串,输出各字段用 e.get(缺键为 None)。
152
- def describe_ingest(self, nids):
153
- """回读真实落盘内容(索引元数据 + 文件头),取证入库语言与形态。
154
-
155
- 不走 `cg.get`:其返回形状随层不同,且读缓存会介入;直接按索引 path 读
156
- 文件是最贴近"磁盘上真实存了什么"的取证方式。
157
- """
158
- out = []
159
- for nid in nids[:2]:
160
- e = self.cg.index["nodes"].get(nid)
161
- if not e:
162
- continue
163
- head = ""
164
- try:
165
- with open(os.path.join(self.cg.root, e["path"]), encoding="utf-8") as f:
166
- head = f.read()[:300]
167
- except OSError:
168
- pass
169
- out.append({"id": nid, "layer": e.get("layer"), "tags": e.get("tags"),
170
- "bucket": e.get("bucket"),
171
- "condition_space": e.get("condition_space"),
172
- "file_head": head})
173
- return out
174
-
175
- # 生效条件:无参数,遍历 self.cg.index["nodes"] 各节点的 e.get("bucket"),其缺失或为假值(None/空串等)时归入 "<none>" 计数,再把计数字典交 routing.bucket_health 并返回其结果。
176
- def bucket_health(self):
177
- """桶健康度自检(routing.bucket_health):取证条件路由是否有区分力。"""
178
- from md_cg import routing
179
- counts = {}
180
- for e in self.cg.index["nodes"].values():
181
- b = e.get("bucket") or "<none>"
182
- counts[b] = counts.get(b, 0) + 1
183
- return routing.bucket_health(counts)
184
-
185
-
186
- # 生效条件:无必需构造形参,base 为假值(None/空串)时先回落 os.environ["BENCH6_EMBED_BASE"]、再回落 "http://127.0.0.1:1234/v1" 并 rstrip("/"),model 为假值时回落 os.environ["BENCH6_EMBED_MODEL"]、再回落空串 "",timeout 缺省为 30。
187
- class VectorRagAdapter(Adapter):
188
- """纯向量 RAG 基线(零 LLM):英文原文直嵌入 + 余弦 Top-k。
189
-
190
- 作为**下界锚**:无结构化、无图、无实体/条件路。embedding 走本地
191
- 127.0.0.1:1234(OpenAI 兼容),与既有竞品探针同源,不引入新依赖。
192
- """
193
-
194
- name = "vector_rag"
195
-
196
- # 生效条件:base 依次按 base 形参 → os.environ.get("BENCH6_EMBED_BASE") → "http://127.0.0.1:1234/v1" 取值(每级为空串/None 均继续回落)再去掉尾部 "/",model 依次按 model 形参 → os.environ.get("BENCH6_EMBED_MODEL") → "" 取值(空串也回落),timeout 直接取形参(含 0),ids/vecs 置 []、_dim 置 0。
197
- def __init__(self, base=None, model=None, timeout=30):
198
- self.base = (base or os.environ.get("BENCH6_EMBED_BASE")
199
- or "http://127.0.0.1:1234/v1").rstrip("/")
200
- self.model = model or os.environ.get("BENCH6_EMBED_MODEL") or ""
201
- self.timeout = timeout
202
- self.ids = []
203
- self.vecs = []
204
- self._dim = 0
205
-
206
- # 生效条件:以 self.base + path 为 URL、method="POST"、JSON 编码的 payload 为 body、Content-Type: application/json、超时 self.timeout 发出请求,返回响应体按 UTF-8 解码后 json.loads 的对象。
207
- def _post(self, path, payload):
208
- req = urllib.request.Request(
209
- self.base + path, method="POST",
210
- data=json.dumps(payload).encode("utf-8"),
211
- headers={"Content-Type": "application/json"})
212
- with urllib.request.urlopen(req, timeout=self.timeout) as r:
213
- return json.loads(r.read().decode("utf-8"))
214
-
215
- # 生效条件:self.model 为真值时直接返回;否则请求 self.base + "/models",从 data.get("data") 筛出 id 非空的模型名列表,该列表为空时抛 RuntimeError,否则优先取名字含 embed/bge/gte/m3 的第一个,无匹配则取 ids[0],写入 self.model 后返回。
216
- def resolve_model(self):
217
- """未显式指定时,从 /models 取第一个 embedding 模型。"""
218
- if self.model:
219
- return self.model
220
- req = urllib.request.Request(self.base + "/models")
221
- with urllib.request.urlopen(req, timeout=15) as r:
222
- data = json.loads(r.read().decode("utf-8"))
223
- ids = [m.get("id") for m in (data.get("data") or []) if m.get("id")]
224
- if not ids:
225
- raise RuntimeError("embedding 服务未返回任何模型:%s" % self.base)
226
- # 优先明显是 embedding 的模型名
227
- for mid in ids:
228
- if any(k in mid.lower() for k in ("embed", "bge", "gte", "m3")):
229
- self.model = mid
230
- break
231
- else:
232
- self.model = ids[0]
233
- return self.model
234
-
235
- # 生效条件:对任意 text 以 self.model 调 _post("/embeddings", {"model":…, "input": text}),取 d["data"][0]["embedding"],令 self._dim 等于该向量长度并返回该向量。
236
- def embed(self, text):
237
- d = self._post("/embeddings", {"model": self.model, "input": text})
238
- v = d["data"][0]["embedding"]
239
- self._dim = len(v)
240
- return v
241
-
242
- # 生效条件:按 batch(默认 32)把 texts 切片,每片整批 POST /embeddings 成功时按 x.get("index", 0) 排序后依次收集 r["embedding"],该片抛任何异常时改为对片内每条调 self.embed 回退,self._dim 为 0 且有结果时置为最后一条向量长度,最后返回 out。
243
- def embed_many(self, texts, batch=32):
244
- """批量嵌入(服务不支持 batch 时逐条回退)。"""
245
- out = []
246
- for i in range(0, len(texts), batch):
247
- chunk = texts[i:i + batch]
248
- try:
249
- d = self._post("/embeddings", {"model": self.model, "input": chunk})
250
- rows = sorted(d["data"], key=lambda x: x.get("index", 0))
251
- out.extend([r["embedding"] for r in rows])
252
- except Exception:
253
- out.extend([self.embed(t) for t in chunk])
254
- if self._dim == 0 and out:
255
- self._dim = len(out[-1])
256
- return out
257
-
258
- # 生效条件:无前置;把 self.ids 与 self.vecs 同时清空(二者下标耦合,必须成对重置),self._dim 保留原值不动;
259
- def reset(self):
260
- self.ids, self.vecs = [], []
261
-
262
- # 生效条件:对任意 nid 与 text,把 nid 追加到 self.ids、把 self.embed(text) 的向量追加到 self.vecs,二者按下标一一对应,不查重、不返回。
263
- def add(self, nid, text):
264
- self.ids.append(nid)
265
- self.vecs.append(self.embed(text))
266
-
267
- # 生效条件:self.vecs 为空时直接返回 [];否则嵌入 query 并对每条候选计算余弦相似度(qn 或 vn 为 0 时用 1.0 兜底),按相似度降序、同分按 id 升序排序后返回前 k 个 nid。
268
- def search(self, query, k=5):
269
- if not self.vecs:
270
- return []
271
- qv = self.embed(query)
272
- qn = math.sqrt(sum(x * x for x in qv)) or 1.0
273
- scored = []
274
- for i, v in enumerate(self.vecs):
275
- vn = math.sqrt(sum(x * x for x in v)) or 1.0
276
- s = sum(a * b for a, b in zip(qv, v)) / (qn * vn)
277
- scored.append((s, self.ids[i]))
278
- scored.sort(key=lambda x: (-x[0], x[1]))
279
- return [nid for _s, nid in scored[:k]]
280
-
281
- # 生效条件:对任意 nids 都只取前 2 项(nids[:2]),各返回 {"id": nid, "form": "原样英文文本 → embedding", "lang": "en", "dim": self._dim},不读磁盘内容。
282
- def describe_ingest(self, nids):
283
- return [{"id": nid, "form": "原样英文文本 → embedding",
284
- "lang": "en", "dim": self._dim} for nid in nids[:2]]
285
-
286
-
287
- # ------------------------------------------------------------------ 套件与评分
288
-
289
- # 生效条件:lang 等于 "zh" 时逐题取 q["question_zh"],lang 为其它任何值(含 "en")时取 q["question_en"],对 questions 每项调 adapter.search(query, k=k),verbose 为真且序数能被 50 整除时打印进度,返回 {qid: 检索结果列表}。
290
- def run_suite(adapter, questions, lang, k=5, verbose=True):
291
- """一套查询语言跑一遍 → {qid: [id...]}(顺序即相关性降序)。"""
292
- key = "question_zh" if lang == "zh" else "question_en"
293
- hits, t0 = {}, time.time()
294
- for i, q in enumerate(questions, 1):
295
- hits[q["qid"]] = adapter.search(q[key], k=k)
296
- if verbose and i % 50 == 0:
297
- print(" [%s] %d/%d(%.0fs)" % (lang, i, len(questions),
298
- time.time() - t0))
299
- return hits
300
-
301
-
302
- # 生效条件:对 langs 中每个 lang 依次跑 run_suite(adapter, questions, lang, k=k)、bc.rows_from_hits 与 ec.summarize,结果写入 out["langs"][lang];最后取 questions 前 2 条的 qid 调 adapter.describe_ingest 存入 out["ingest_probe"] 并返回 out。
303
- def evaluate(arm, adapter, questions, k=5, langs=("zh", "en")):
304
- """一套库 × 两种查询语言 → 指标 + per-question 明细 + 回读取证。"""
305
- out = {"arm": arm, "k": k, "langs": {}}
306
- for lang in langs:
307
- hits = run_suite(adapter, questions, lang, k=k)
308
- rows = bc.rows_from_hits(questions, hits, k=k)
309
- s = ec.summarize(rows, k=k)
310
- out["langs"][lang] = {"summary": s, "rows": rows, "hits": hits}
311
- print(" [%s/%s] hit@1=%.1f%% hit@%d=%.1f%% MRR=%.4f"
312
- % (arm, lang, s["hit@1"] * 100, k, s["hit@%d" % k] * 100, s["mrr"]))
313
- out["ingest_probe"] = adapter.describe_ingest([q["qid"] for q in questions[:2]])
314
- return out
315
-
316
-
317
- # 生效条件:model 依次按 model 形参 → os.environ.get("BENCH6_EMBED_MODEL") → "text-embedding-bge-m3" 取值(形参为空串/None、环境变量缺失或为空串都会继续回落),随后 resolve_model(),再把 pool 中每条的 t["id"]、t["ingest"] 分别装进 vec.ids 与批量嵌入结果 vec.vecs 后返回 vec。
318
- def build_vector_rag(pool, model=None):
319
- """向量基线:池内英文原文批量嵌入(零 LLM、无结构化)。"""
320
- vec = VectorRagAdapter(model=model or os.environ.get("BENCH6_EMBED_MODEL")
321
- or "text-embedding-bge-m3")
322
- vec.resolve_model()
323
- t0 = time.time()
324
- vec.ids = [t["id"] for t in pool]
325
- vec.vecs = vec.embed_many([t["ingest"] for t in pool])
326
- print(" [vector_rag] 模型=%s dim=%d 嵌入 %d 条 %.0fs"
327
- % (vec.model, vec._dim, len(vec.vecs), time.time() - t0))
328
- return vec
329
-
330
-
331
- # 生效条件:argv 为 None 时取 sys.argv[1:],其中出现 "--rebuild" 则各臂以 rebuild=True 建库,非 "-" 开头的项构成 only 白名单,仅当 only 为空或臂名在 only 中时执行对应臂(only 为空时额外执行 2×2 消融块),跑完返回含 manifest/results/elapsed_s 的 payload。
332
- def main(argv=None):
333
- argv = sys.argv[1:] if argv is None else argv
334
- rebuild = "--rebuild" in argv
335
- only = [a for a in argv if not a.startswith("-")]
336
- t_all = time.time()
337
-
338
- data = bc.load()
339
- questions, pool, man = data["questions"], data["pool"], data["manifest"]
340
- print("[bench6] 题 %d / 池 %d(口径固化于 %s)"
341
- % (len(questions), len(pool), man["created_at"]))
342
-
343
- # 评测口径:与既有公开基准一致,否则与参考量级不可比(见 eval_common 注释)
344
- ec.unlock_global_cap()
345
- ec.use_jaccard()
346
-
347
- corpus_by_id = {c["id"]: c for c in ec.iter_jsonl(bc.CORPUS567)}
348
- rows = [corpus_by_id[t["id"]] for t in pool]
349
- results, table = {}, {}
350
-
351
- # 生效条件:形参 name 出现在外层 main 的 only 白名单中时返回 True;only 为空(假值)时对任何 name 都返回 True;only 非空且不含 name 时返回 False。
352
- def _want(name):
353
- return not only or name in only
354
-
355
- # (1) 灵枢单词法路 = 回归锚。建库刻意**不加** tags/condition_space,与
356
- # bench_locomo_zh_public.build_pool 逐字同口径;须复现 hit@1≈0.936,
357
- # 否则说明本次口径已漂移,后续所有四路数字都不可信。
358
- if _want("lingshu_lex"):
359
- lex = LingshuAdapter(rows, "lex", paths=("lexical",), with_meta=False,
360
- rebuild=rebuild)
361
- ec.install_read_cache(lex.cg)
362
- results["lingshu_lex"] = evaluate("lingshu_lex", lex, questions)
363
- table["灵枢·单词法"] = results["lingshu_lex"]["langs"]["zh"]["summary"]
364
-
365
- # (2) 灵枢四路:真开 bucket(传 context)vs 名义四路(不传),单变量对照。
366
- if _want("lingshu_rrf4"):
367
- rrf = LingshuAdapter(rows, "rrf4", paths=ec.PATHS, with_meta=True,
368
- rebuild=rebuild)
369
- ec.install_read_cache(rrf.cg)
370
- health = rrf.bucket_health()
371
- print(" [lingshu] 桶健康度 %s" % json.dumps(health, ensure_ascii=False))
372
- rrf.context = QUERY_CONTEXT
373
- results["lingshu_rrf4"] = evaluate("lingshu_rrf4", rrf, questions)
374
- rrf.context = None
375
- results["lingshu_rrf4_noref"] = evaluate("lingshu_rrf4_noref", rrf, questions)
376
- table["灵枢·四路(真开bucket)"] = results["lingshu_rrf4"]["langs"]["zh"]["summary"]
377
- table["灵枢·四路(名义)"] = results["lingshu_rrf4_noref"]["langs"]["zh"]["summary"]
378
- results["bucket_health"] = health
379
-
380
- # (2b) 2×2 消融:隔离「建库补 meta(tags/condition_space)」与「检索从 1 路变
381
- # 4 路」两个变量。rrf4(81%) 与 lex(99%) 之间混了这两个变量,不隔离就
382
- # 无法归因下降来自哪一侧。两个臂都复用已建好的库,只改检索参数,0 成本。
383
- if not only:
384
- rrf.paths = ("lexical",)
385
- results["lingshu_lex_meta"] = evaluate("lingshu_lex_meta", rrf, questions)
386
- rrf.paths = ec.PATHS # 复原
387
- lex.paths = ec.PATHS
388
- lex.context = QUERY_CONTEXT
389
- results["lingshu_rrf4_nometa"] = evaluate("lingshu_rrf4_nometa", lex, questions)
390
- lex.paths, lex.context = ("lexical",), None # 复原
391
- table["灵枢·词法+meta"] = results["lingshu_lex_meta"]["langs"]["zh"]["summary"]
392
- table["灵枢·四路(无meta)"] = results["lingshu_rrf4_nometa"]["langs"]["zh"]["summary"]
393
-
394
- # (3) 纯向量 RAG 基线(零 LLM,下界锚)
395
- if _want("vector_rag"):
396
- vec = build_vector_rag(pool)
397
- results["vector_rag"] = evaluate("vector_rag", vec, questions)
398
- table["纯向量RAG"] = results["vector_rag"]["langs"]["zh"]["summary"]
399
-
400
- payload = {"manifest": man, "results": results,
401
- "elapsed_s": round(time.time() - t_all, 1)}
402
- ec.save_result("bench6_arms_result.json", payload)
403
- if table:
404
- ec.print_table("bench6 主进程臂 · 中文查询(池 %d / 题 %d)"
405
- % (len(pool), len(questions)), table, k=5)
406
- print("\n[bench6] 主进程臂完成,用时 %.0fs" % (time.time() - t_all))
407
- return payload
408
-
409
-
410
- if __name__ == "__main__":
1
+ # -*- coding: utf-8 -*-
2
+ """六系统横评(bench6)· 主进程臂:灵枢 / 纯向量 RAG + 统一评分。
3
+
4
+ 四家 LLM 竞品(mem0/Graphiti/GraphRAG/Letta)依赖互斥,跑在各自 venv 的独立
5
+ 脚本里(外部评测工作区的 bench6 适配脚本),只回吐 {qid: [id...]} 的 JSON;本模块
6
+ 读回后与灵枢/向量臂走**同一个** bc.rows_from_hits → ec.summarize,保证六家同口径
7
+ (排名判据复用 ec.first_evidence_rank,指标复用 ec.summarize,均不重造)。
8
+
9
+ 灵枢三种检索口径(同一份中文层 + 英文原文,只变检索路):
10
+ lex : 单词法路,且建库不加 tags/condition_space——复现公开参考量级
11
+ (词法 hit@1≈0.936)的**回归锚**,用于确认本次口径没有漂移
12
+ rrf4 : 四路 RRF(lexical,bucket,entity,graph)+ 传 context——用户选定口径
13
+ rrf4_noref : 四路 RRF 不传 context——名义四路,量化条件约束路的净效应
14
+
15
+ ## 为什么灵枢要建两个库而不是一个
16
+ lex 臂必须与 `bench_locomo_zh_public.build_pool` **逐字同口径**(无 tags、无
17
+ condition_space)才能作回归锚;而 rrf4 臂按用户口径要喂 entity 路(tags)与
18
+ bucket 路(condition_space)。建库参数不同 → 目录不同 → 拆成两个 ROOT,避免
19
+ "复用已建库"逻辑把两种口径混成一个。
20
+
21
+ ## 诚实边界
22
+ locomo-zh-500 是**单域**会话语料,且查询侧是**无情境标注**的关键词串。bucket 路
23
+ 要求读写两侧 `route_key` 同构(routing.py 模块头「风险2」)——写侧有域、读侧
24
+ 没有,故条件路由在本语料上预期无区分力。这一点由实测的桶健康度取证,不预设。
25
+ """
26
+ from __future__ import annotations
27
+
28
+ import json
29
+ import math
30
+ import os
31
+ import shutil
32
+ import sys
33
+ import time
34
+ import urllib.error
35
+ import urllib.request
36
+
37
+ HERE = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
38
+ for _p in (HERE, os.path.join(HERE, "md_cg")):
39
+ if _p not in sys.path:
40
+ sys.path.insert(0, _p)
41
+
42
+ from md_cg import bench6_common as bc # noqa: E402
43
+ from md_cg import eval_common as ec # noqa: E402
44
+
45
+ ROOT_BASE = os.path.join(HERE, "_md_cg_eval_bench6") # .gitignore 的 /_md_cg_eval_*/ 已覆盖
46
+
47
+ # 条件约束路的查询侧情境:所有题共用同一份默认情境(查询串本身无情境标注)。
48
+ # 与建库侧 condition_space 同构 → route_key 两侧落在同一键上。这是 bucket 路能被
49
+ # 开启的唯一合法构造方式;若查询侧能精确给出每题的场景/域,那已是使用 qrels 作弊。
50
+ QUERY_CONTEXT = {
51
+ "observation_position": "会话陈述",
52
+ "observation_tool": "会话记录",
53
+ "existence_constraint": "公开",
54
+ }
55
+
56
+
57
+ # 生效条件:形参 c 若提供映射接口,则取 c["zh_fields"](缺失或假值回落 {})再取其 "condition"(缺失或假值回落 {}),返回三槽 observation_position/observation_tool/existence_constraint,各自以 cond.get(中文键, "") 取值——中文键缺失时回落空串,键存在而值为 None 时结果即为 None(不回落)。
58
+ def cond_of(c):
59
+ """zh_fields.condition(中文三槽)→ mdcos 期望的英文槽名。
60
+
61
+ 只映射 zh_fields 里**真实存在**的三槽,不臆造 time_window(写入侧会自行补)。
62
+ """
63
+ cond = (c.get("zh_fields") or {}).get("condition") or {}
64
+ return {"observation_position": cond.get("观测位置", ""),
65
+ "observation_tool": cond.get("观测工具", ""),
66
+ "existence_constraint": cond.get("存在约束", "")}
67
+
68
+
69
+ # 生效条件:形参 c 若提供映射接口,则 f = c["zh_fields"] 为假值(缺失/None/{})时当作 {},返回 [str(f["identity"] 或 "")] + [str(t) for t in (f["terms"] 或 [])]:identity 缺失或假值时首元素为空串(列表恒有 1 项),terms 缺失或假值时只有首元素。
70
+ def tags_of(c):
71
+ """喂 entity 路的裸词 tags = identity + terms。
72
+
73
+ 刻意不加 `ent:` 前缀:`mdcos._path_entity` 的判据是 `t in query or query in t`,
74
+ 带前缀的标签在自然查询下永不命中(既有实测教训)。也不加 `domain:`——那会
75
+ 劫持 route_key 的 domain 分支,把 bucket 路变成按场景分桶,而查询侧无法复现
76
+ 同一场景键(见模块头「诚实边界」)。
77
+ """
78
+ f = c.get("zh_fields") or {}
79
+ return [str(f.get("identity") or "")] + [str(t) for t in (f.get("terms") or [])]
80
+
81
+
82
+ # 生效条件:类无 __init__,实例化无需任何形参;其 describe_ingest(nids) 对任意 nids(含空)恒返回 [],而 reset()、add(nid, text)、search(query, k=5) 对任意实参一律抛 NotImplementedError。
83
+ class Adapter:
84
+ """统一适配接口。六家一律只回吐 id 列表,指标计算交回 bench6_common。"""
85
+ name = "adapter"
86
+
87
+ # 生效条件:无可选/必需形参,任何调用一律抛 NotImplementedError(基类接口桩)。
88
+ def reset(self):
89
+ raise NotImplementedError
90
+
91
+ # 生效条件:对任意 nid 与 text 一律抛 NotImplementedError(形参不参与任何判断)。
92
+ def add(self, nid, text):
93
+ raise NotImplementedError
94
+
95
+ # 生效条件:对任意 query 与任意 k(默认 5)一律抛 NotImplementedError,不返回结果。
96
+ def search(self, query, k=5):
97
+ raise NotImplementedError
98
+
99
+ # 生效条件:对任意 nids(包括空列表或 None)都直接返回空列表 [],不读取任何存储。
100
+ def describe_ingest(self, nids):
101
+ """回读真实存储内容样本,用于取证「入库语言与入库形态」。"""
102
+ return []
103
+
104
+
105
+ # 生效条件:必须以 rows、variant、paths 三个必需形参构造(context 默认 None、with_meta 默认 False、rebuild 默认 False 可选),构造后 search(query, k=5) 是否向 search_rrf 传 context 由 context 是否为 None 决定,describe_ingest(nids)/bucket_health() 的取证内容取决于 variant 对应 root 库的索引状态。
106
+ class LingshuAdapter(Adapter):
107
+ """灵枢臂:进程内 MdCGOS。
108
+
109
+ with_meta=True 时三口径共用一库(lex 需与公开脚本同库,故 lex 单独建)。
110
+ """
111
+
112
+ name = "lingshu"
113
+
114
+ # 生效条件:root 固定为 os.path.join(ROOT_BASE, variant);rebuild 为真且 os.path.isdir(root) 为真时先 rmtree,索引中已有节点数 ≥ len(rows) 时直接 return(幂等复用、不写库),否则按 rows 逐条 add(with_meta 为真时同时补 tags=tags_of(c)、condition_space=cond_of(c))后 flush。
115
+ def __init__(self, rows, variant, paths, context=None, with_meta=False,
116
+ rebuild=False):
117
+ from md_cg.bench_locomo_zh_public import body_of
118
+ from md_cg.mdcos import MdCGOS
119
+
120
+ self.variant = variant
121
+ self.paths = tuple(paths)
122
+ self.context = context
123
+ self._body_of = body_of
124
+ root = os.path.join(ROOT_BASE, variant)
125
+ self.root = root
126
+ if rebuild and os.path.isdir(root):
127
+ shutil.rmtree(root, ignore_errors=True)
128
+ self.cg = MdCGOS(root, autoflush=500)
129
+ if len(self.cg.index["nodes"]) >= len(rows):
130
+ return # 幂等复用
131
+ t0 = time.time()
132
+ for c in rows:
133
+ kw = {}
134
+ if with_meta:
135
+ kw["tags"] = tags_of(c)
136
+ kw["condition_space"] = cond_of(c)
137
+ self.cg.add(c["id"], body_of(c), layer="knowledge",
138
+ eval_src="bench6:locomo-zh-500",
139
+ verification_basis="data", **kw)
140
+ self.cg.flush()
141
+ print(" [lingshu/%s] 建库 %d 节点 %.1fs"
142
+ % (variant, len(self.cg.index["nodes"]), time.time() - t0))
143
+
144
+ # 生效条件:给定 query 与 k(默认 5)即调用 self.cg.search_rrf(k=k、paths=self.paths、judge=False、record=False),仅当 self.context 不为 None 时附加 context 参数,返回每个结果 r 的 r[0]["id"] 组成的列表。
145
+ def search(self, query, k=5):
146
+ kw = {"context": self.context} if self.context is not None else {}
147
+ res, _meta = self.cg.search_rrf(query, k=k, paths=self.paths,
148
+ judge=False, record=False, **kw)
149
+ return [r[0]["id"] for r in res]
150
+
151
+ # 生效条件:只遍历 nids[:2],节点索引中 .get(nid) 为假值(缺失)的 nid 被跳过,其余按 os.path.join(self.cg.root, e["path"]) 读文件头 300 字符,抛 OSError 时 file_head 保持空串,输出各字段用 e.get(缺键为 None)。
152
+ def describe_ingest(self, nids):
153
+ """回读真实落盘内容(索引元数据 + 文件头),取证入库语言与形态。
154
+
155
+ 不走 `cg.get`:其返回形状随层不同,且读缓存会介入;直接按索引 path 读
156
+ 文件是最贴近"磁盘上真实存了什么"的取证方式。
157
+ """
158
+ out = []
159
+ for nid in nids[:2]:
160
+ e = self.cg.index["nodes"].get(nid)
161
+ if not e:
162
+ continue
163
+ head = ""
164
+ try:
165
+ with open(os.path.join(self.cg.root, e["path"]), encoding="utf-8") as f:
166
+ head = f.read()[:300]
167
+ except OSError:
168
+ pass
169
+ out.append({"id": nid, "layer": e.get("layer"), "tags": e.get("tags"),
170
+ "bucket": e.get("bucket"),
171
+ "condition_space": e.get("condition_space"),
172
+ "file_head": head})
173
+ return out
174
+
175
+ # 生效条件:无参数,遍历 self.cg.index["nodes"] 各节点的 e.get("bucket"),其缺失或为假值(None/空串等)时归入 "<none>" 计数,再把计数字典交 routing.bucket_health 并返回其结果。
176
+ def bucket_health(self):
177
+ """桶健康度自检(routing.bucket_health):取证条件路由是否有区分力。"""
178
+ from md_cg import routing
179
+ counts = {}
180
+ for e in self.cg.index["nodes"].values():
181
+ b = e.get("bucket") or "<none>"
182
+ counts[b] = counts.get(b, 0) + 1
183
+ return routing.bucket_health(counts)
184
+
185
+
186
+ # 生效条件:无必需构造形参,base 为假值(None/空串)时先回落 os.environ["BENCH6_EMBED_BASE"]、再回落 "http://127.0.0.1:1234/v1" 并 rstrip("/"),model 为假值时回落 os.environ["BENCH6_EMBED_MODEL"]、再回落空串 "",timeout 缺省为 30。
187
+ class VectorRagAdapter(Adapter):
188
+ """纯向量 RAG 基线(零 LLM):英文原文直嵌入 + 余弦 Top-k。
189
+
190
+ 作为**下界锚**:无结构化、无图、无实体/条件路。embedding 走本地
191
+ 127.0.0.1:1234(OpenAI 兼容),与既有竞品探针同源,不引入新依赖。
192
+ """
193
+
194
+ name = "vector_rag"
195
+
196
+ # 生效条件:base 依次按 base 形参 → os.environ.get("BENCH6_EMBED_BASE") → "http://127.0.0.1:1234/v1" 取值(每级为空串/None 均继续回落)再去掉尾部 "/",model 依次按 model 形参 → os.environ.get("BENCH6_EMBED_MODEL") → "" 取值(空串也回落),timeout 直接取形参(含 0),ids/vecs 置 []、_dim 置 0。
197
+ def __init__(self, base=None, model=None, timeout=30):
198
+ self.base = (base or os.environ.get("BENCH6_EMBED_BASE")
199
+ or "http://127.0.0.1:1234/v1").rstrip("/")
200
+ self.model = model or os.environ.get("BENCH6_EMBED_MODEL") or ""
201
+ self.timeout = timeout
202
+ self.ids = []
203
+ self.vecs = []
204
+ self._dim = 0
205
+
206
+ # 生效条件:以 self.base + path 为 URL、method="POST"、JSON 编码的 payload 为 body、Content-Type: application/json、超时 self.timeout 发出请求,返回响应体按 UTF-8 解码后 json.loads 的对象。
207
+ def _post(self, path, payload):
208
+ req = urllib.request.Request(
209
+ self.base + path, method="POST",
210
+ data=json.dumps(payload).encode("utf-8"),
211
+ headers={"Content-Type": "application/json"})
212
+ with urllib.request.urlopen(req, timeout=self.timeout) as r:
213
+ return json.loads(r.read().decode("utf-8"))
214
+
215
+ # 生效条件:self.model 为真值时直接返回;否则请求 self.base + "/models",从 data.get("data") 筛出 id 非空的模型名列表,该列表为空时抛 RuntimeError,否则优先取名字含 embed/bge/gte/m3 的第一个,无匹配则取 ids[0],写入 self.model 后返回。
216
+ def resolve_model(self):
217
+ """未显式指定时,从 /models 取第一个 embedding 模型。"""
218
+ if self.model:
219
+ return self.model
220
+ req = urllib.request.Request(self.base + "/models")
221
+ with urllib.request.urlopen(req, timeout=15) as r:
222
+ data = json.loads(r.read().decode("utf-8"))
223
+ ids = [m.get("id") for m in (data.get("data") or []) if m.get("id")]
224
+ if not ids:
225
+ raise RuntimeError("embedding 服务未返回任何模型:%s" % self.base)
226
+ # 优先明显是 embedding 的模型名
227
+ for mid in ids:
228
+ if any(k in mid.lower() for k in ("embed", "bge", "gte", "m3")):
229
+ self.model = mid
230
+ break
231
+ else:
232
+ self.model = ids[0]
233
+ return self.model
234
+
235
+ # 生效条件:对任意 text 以 self.model 调 _post("/embeddings", {"model":…, "input": text}),取 d["data"][0]["embedding"],令 self._dim 等于该向量长度并返回该向量。
236
+ def embed(self, text):
237
+ d = self._post("/embeddings", {"model": self.model, "input": text})
238
+ v = d["data"][0]["embedding"]
239
+ self._dim = len(v)
240
+ return v
241
+
242
+ # 生效条件:按 batch(默认 32)把 texts 切片,每片整批 POST /embeddings 成功时按 x.get("index", 0) 排序后依次收集 r["embedding"],该片抛任何异常时改为对片内每条调 self.embed 回退,self._dim 为 0 且有结果时置为最后一条向量长度,最后返回 out。
243
+ def embed_many(self, texts, batch=32):
244
+ """批量嵌入(服务不支持 batch 时逐条回退)。"""
245
+ out = []
246
+ for i in range(0, len(texts), batch):
247
+ chunk = texts[i:i + batch]
248
+ try:
249
+ d = self._post("/embeddings", {"model": self.model, "input": chunk})
250
+ rows = sorted(d["data"], key=lambda x: x.get("index", 0))
251
+ out.extend([r["embedding"] for r in rows])
252
+ except Exception:
253
+ out.extend([self.embed(t) for t in chunk])
254
+ if self._dim == 0 and out:
255
+ self._dim = len(out[-1])
256
+ return out
257
+
258
+ # 生效条件:无前置;把 self.ids 与 self.vecs 同时清空(二者下标耦合,必须成对重置),self._dim 保留原值不动;
259
+ def reset(self):
260
+ self.ids, self.vecs = [], []
261
+
262
+ # 生效条件:对任意 nid 与 text,把 nid 追加到 self.ids、把 self.embed(text) 的向量追加到 self.vecs,二者按下标一一对应,不查重、不返回。
263
+ def add(self, nid, text):
264
+ self.ids.append(nid)
265
+ self.vecs.append(self.embed(text))
266
+
267
+ # 生效条件:self.vecs 为空时直接返回 [];否则嵌入 query 并对每条候选计算余弦相似度(qn 或 vn 为 0 时用 1.0 兜底),按相似度降序、同分按 id 升序排序后返回前 k 个 nid。
268
+ def search(self, query, k=5):
269
+ if not self.vecs:
270
+ return []
271
+ qv = self.embed(query)
272
+ qn = math.sqrt(sum(x * x for x in qv)) or 1.0
273
+ scored = []
274
+ for i, v in enumerate(self.vecs):
275
+ vn = math.sqrt(sum(x * x for x in v)) or 1.0
276
+ s = sum(a * b for a, b in zip(qv, v)) / (qn * vn)
277
+ scored.append((s, self.ids[i]))
278
+ scored.sort(key=lambda x: (-x[0], x[1]))
279
+ return [nid for _s, nid in scored[:k]]
280
+
281
+ # 生效条件:对任意 nids 都只取前 2 项(nids[:2]),各返回 {"id": nid, "form": "原样英文文本 → embedding", "lang": "en", "dim": self._dim},不读磁盘内容。
282
+ def describe_ingest(self, nids):
283
+ return [{"id": nid, "form": "原样英文文本 → embedding",
284
+ "lang": "en", "dim": self._dim} for nid in nids[:2]]
285
+
286
+
287
+ # ------------------------------------------------------------------ 套件与评分
288
+
289
+ # 生效条件:lang 等于 "zh" 时逐题取 q["question_zh"],lang 为其它任何值(含 "en")时取 q["question_en"],对 questions 每项调 adapter.search(query, k=k),verbose 为真且序数能被 50 整除时打印进度,返回 {qid: 检索结果列表}。
290
+ def run_suite(adapter, questions, lang, k=5, verbose=True):
291
+ """一套查询语言跑一遍 → {qid: [id...]}(顺序即相关性降序)。"""
292
+ key = "question_zh" if lang == "zh" else "question_en"
293
+ hits, t0 = {}, time.time()
294
+ for i, q in enumerate(questions, 1):
295
+ hits[q["qid"]] = adapter.search(q[key], k=k)
296
+ if verbose and i % 50 == 0:
297
+ print(" [%s] %d/%d(%.0fs)" % (lang, i, len(questions),
298
+ time.time() - t0))
299
+ return hits
300
+
301
+
302
+ # 生效条件:对 langs 中每个 lang 依次跑 run_suite(adapter, questions, lang, k=k)、bc.rows_from_hits 与 ec.summarize,结果写入 out["langs"][lang];最后取 questions 前 2 条的 qid 调 adapter.describe_ingest 存入 out["ingest_probe"] 并返回 out。
303
+ def evaluate(arm, adapter, questions, k=5, langs=("zh", "en")):
304
+ """一套库 × 两种查询语言 → 指标 + per-question 明细 + 回读取证。"""
305
+ out = {"arm": arm, "k": k, "langs": {}}
306
+ for lang in langs:
307
+ hits = run_suite(adapter, questions, lang, k=k)
308
+ rows = bc.rows_from_hits(questions, hits, k=k)
309
+ s = ec.summarize(rows, k=k)
310
+ out["langs"][lang] = {"summary": s, "rows": rows, "hits": hits}
311
+ print(" [%s/%s] hit@1=%.1f%% hit@%d=%.1f%% MRR=%.4f"
312
+ % (arm, lang, s["hit@1"] * 100, k, s["hit@%d" % k] * 100, s["mrr"]))
313
+ out["ingest_probe"] = adapter.describe_ingest([q["qid"] for q in questions[:2]])
314
+ return out
315
+
316
+
317
+ # 生效条件:model 依次按 model 形参 → os.environ.get("BENCH6_EMBED_MODEL") → "text-embedding-bge-m3" 取值(形参为空串/None、环境变量缺失或为空串都会继续回落),随后 resolve_model(),再把 pool 中每条的 t["id"]、t["ingest"] 分别装进 vec.ids 与批量嵌入结果 vec.vecs 后返回 vec。
318
+ def build_vector_rag(pool, model=None):
319
+ """向量基线:池内英文原文批量嵌入(零 LLM、无结构化)。"""
320
+ vec = VectorRagAdapter(model=model or os.environ.get("BENCH6_EMBED_MODEL")
321
+ or "text-embedding-bge-m3")
322
+ vec.resolve_model()
323
+ t0 = time.time()
324
+ vec.ids = [t["id"] for t in pool]
325
+ vec.vecs = vec.embed_many([t["ingest"] for t in pool])
326
+ print(" [vector_rag] 模型=%s dim=%d 嵌入 %d 条 %.0fs"
327
+ % (vec.model, vec._dim, len(vec.vecs), time.time() - t0))
328
+ return vec
329
+
330
+
331
+ # 生效条件:argv 为 None 时取 sys.argv[1:],其中出现 "--rebuild" 则各臂以 rebuild=True 建库,非 "-" 开头的项构成 only 白名单,仅当 only 为空或臂名在 only 中时执行对应臂(only 为空时额外执行 2×2 消融块),跑完返回含 manifest/results/elapsed_s 的 payload。
332
+ def main(argv=None):
333
+ argv = sys.argv[1:] if argv is None else argv
334
+ rebuild = "--rebuild" in argv
335
+ only = [a for a in argv if not a.startswith("-")]
336
+ t_all = time.time()
337
+
338
+ data = bc.load()
339
+ questions, pool, man = data["questions"], data["pool"], data["manifest"]
340
+ print("[bench6] 题 %d / 池 %d(口径固化于 %s)"
341
+ % (len(questions), len(pool), man["created_at"]))
342
+
343
+ # 评测口径:与既有公开基准一致,否则与参考量级不可比(见 eval_common 注释)
344
+ ec.unlock_global_cap()
345
+ ec.use_jaccard()
346
+
347
+ corpus_by_id = {c["id"]: c for c in ec.iter_jsonl(bc.CORPUS567)}
348
+ rows = [corpus_by_id[t["id"]] for t in pool]
349
+ results, table = {}, {}
350
+
351
+ # 生效条件:形参 name 出现在外层 main 的 only 白名单中时返回 True;only 为空(假值)时对任何 name 都返回 True;only 非空且不含 name 时返回 False。
352
+ def _want(name):
353
+ return not only or name in only
354
+
355
+ # (1) 灵枢单词法路 = 回归锚。建库刻意**不加** tags/condition_space,与
356
+ # bench_locomo_zh_public.build_pool 逐字同口径;须复现 hit@1≈0.936,
357
+ # 否则说明本次口径已漂移,后续所有四路数字都不可信。
358
+ if _want("lingshu_lex"):
359
+ lex = LingshuAdapter(rows, "lex", paths=("lexical",), with_meta=False,
360
+ rebuild=rebuild)
361
+ ec.install_read_cache(lex.cg)
362
+ results["lingshu_lex"] = evaluate("lingshu_lex", lex, questions)
363
+ table["灵枢·单词法"] = results["lingshu_lex"]["langs"]["zh"]["summary"]
364
+
365
+ # (2) 灵枢四路:真开 bucket(传 context)vs 名义四路(不传),单变量对照。
366
+ if _want("lingshu_rrf4"):
367
+ rrf = LingshuAdapter(rows, "rrf4", paths=ec.PATHS, with_meta=True,
368
+ rebuild=rebuild)
369
+ ec.install_read_cache(rrf.cg)
370
+ health = rrf.bucket_health()
371
+ print(" [lingshu] 桶健康度 %s" % json.dumps(health, ensure_ascii=False))
372
+ rrf.context = QUERY_CONTEXT
373
+ results["lingshu_rrf4"] = evaluate("lingshu_rrf4", rrf, questions)
374
+ rrf.context = None
375
+ results["lingshu_rrf4_noref"] = evaluate("lingshu_rrf4_noref", rrf, questions)
376
+ table["灵枢·四路(真开bucket)"] = results["lingshu_rrf4"]["langs"]["zh"]["summary"]
377
+ table["灵枢·四路(名义)"] = results["lingshu_rrf4_noref"]["langs"]["zh"]["summary"]
378
+ results["bucket_health"] = health
379
+
380
+ # (2b) 2×2 消融:隔离「建库补 meta(tags/condition_space)」与「检索从 1 路变
381
+ # 4 路」两个变量。rrf4(81%) 与 lex(99%) 之间混了这两个变量,不隔离就
382
+ # 无法归因下降来自哪一侧。两个臂都复用已建好的库,只改检索参数,0 成本。
383
+ if not only:
384
+ rrf.paths = ("lexical",)
385
+ results["lingshu_lex_meta"] = evaluate("lingshu_lex_meta", rrf, questions)
386
+ rrf.paths = ec.PATHS # 复原
387
+ lex.paths = ec.PATHS
388
+ lex.context = QUERY_CONTEXT
389
+ results["lingshu_rrf4_nometa"] = evaluate("lingshu_rrf4_nometa", lex, questions)
390
+ lex.paths, lex.context = ("lexical",), None # 复原
391
+ table["灵枢·词法+meta"] = results["lingshu_lex_meta"]["langs"]["zh"]["summary"]
392
+ table["灵枢·四路(无meta)"] = results["lingshu_rrf4_nometa"]["langs"]["zh"]["summary"]
393
+
394
+ # (3) 纯向量 RAG 基线(零 LLM,下界锚)
395
+ if _want("vector_rag"):
396
+ vec = build_vector_rag(pool)
397
+ results["vector_rag"] = evaluate("vector_rag", vec, questions)
398
+ table["纯向量RAG"] = results["vector_rag"]["langs"]["zh"]["summary"]
399
+
400
+ payload = {"manifest": man, "results": results,
401
+ "elapsed_s": round(time.time() - t_all, 1)}
402
+ ec.save_result("bench6_arms_result.json", payload)
403
+ if table:
404
+ ec.print_table("bench6 主进程臂 · 中文查询(池 %d / 题 %d)"
405
+ % (len(pool), len(questions)), table, k=5)
406
+ print("\n[bench6] 主进程臂完成,用时 %.0fs" % (time.time() - t_all))
407
+ return payload
408
+
409
+
410
+ if __name__ == "__main__":
411
411
  main()