Skip to content

Releases: foreverkol/pj102-engine

v2.5.0 · excerpt 输入截断体系 + 缓存熔断 + 内容承接门 + 日期权威

Choose a tag to compare

@foreverkol foreverkol released this 17 Sep 12:56

pj102-engine v2.5.0

引擎设施补全:LLM 输入截断统一入口 · 缓存熔断 · 内容承接门 · 日期权威分层判据,并补齐引擎自身两处既有缺陷(后处理装置死于无人调用 / ASR 别名探测路径差一级)。

测试 85 → 118 passed(117 passed, 1 skipped,skip 为既有对拍夹具缺失)。

完整变更

引擎设施补全:LLM 输入截断统一入口 · 缓存熔断 · 内容承接门 · 日期权威分层判据,
并补齐引擎自身两处既有缺陷(后处理装置死于无人调用 / ASR 别名探测路径差一级)。
测试 85 → 118 passed。

上游范围经 scripts/engine_sync_probe_20260917.py 勘察裁定:先归一化
(去 BOM / CRLF→LF / 去行尾空白)再比对,并按行的语法角色分型 ——
避免把「实例中性化差异」误当工作量。环境适配与部署侧数据一律不上游。

新增

  • code/excerpt.py —— LLM 输入截断的单一入口。
    原先 12 个 LLM 步骤各自硬编码 content[:N](4000~10000 不等),且都不告知
    模型「末尾已省略」
    ⇒ 长会议(中位 25664 字)中后段被系统性丢弃,模型对残缺
    上下文臆测或弃答 ⇒ 落盘空骨架被判为「无产出」。现统一为
    excerpt_for_llm(content, default),超限时把「原文共 X 字 / 末尾 Y 字未提供 /
    不要臆测」直接拼进 excerpt;环境变量 PJ102_EXCERPT_LIMIT 提供统一下限。
    12 个消费方同步接线(steps/{s2,s4,s5,s6,s7,s8,s9,s10,s11,s13,s14}.py + s3_summary)。
  • code/pipeline.py:B3 缓存熔断 fuse_check(两级)。
    hard = 已实证的确定性退化(如 s3 的 one_sentence 为空/占位)⇒ 中止该样本;
    soft = 「全字段空/占位」⇒ 不落盘但样本继续(保持可重试、不误伤批次)。
    s13/s14 合法产物是 list,空 list 不判退化。
    开关 PJ102_FUSE_DISABLE=1 应急关闭。
    理由:缓存是「可信重放」的契约 —— 写入退化产物即违约(曾致下游 s15 重放抛
    S15MissingS3,而批跑依然报「成功」)。
  • code/polish_pages.py v1.6:分片页丢弃必须过「内容承接」门。
    三条无校验丢弃路径曾致 210 个分片页中 20 份的实质内容未被任何规范页承接即被
    unlink
    。现统一为一条不变式:分片页只有在其实质内容已被目标页承接时才可丢弃;
    未承接 ⇒ 强制并入目标页(而非新建「(2)」副本),保证只增不减。
    含 _norm_line / _body_lines / _subst_lines / _contained 装置。
  • scripts/run_full.py 接线 4 个后处理装置:2.5 link_orphans(孤儿回链补齐,
    必须排在 backlink_builder 之后、index_builder 之前)、7.5 normalize_tree
    (出口署名校正,幂等)、7.6 registry 别名健康度巡检(只读 + 告警)、
    8 baseline_check(19 维标尺对拍,使「每批次后自动断言」成为管线固有行为)。
    ⇒ 原版上述装置死于无人调用(与旧基线 p1_lint_baseline.json 同一病因)。
  • scripts/baseline_check.py(19 维标尺对拍) 与
    scripts/audit_registry_aliases.py(registry 别名健康度巡检) 随引擎首次分发。
  • scripts/s3_fidelity_gate_20260916.py(s3 值级忠实度门):把 s3 抽出的每个
    数字回原始转写稿做值级比对(不采信 wiki 派生文本),分层判据
    L1 exact → L2 去分隔 → L3 口读连写(含降序链 1亿1511万)→ L4 量级换算,
    MISS 即可疑编造。支持多源回退,并打印 skipped 计数防「单源假绿」。
  • scripts/engine_sync_probe_20260917.py(引擎 ↔ 部署仓差异勘察器):
    落实「每处热修都问:引擎侧是否同步」的自动化装置。只读。

修复

  • code/steps/s1_basic.py:日期权威改为分层判据。
    源稿文件名的年月日可能笔误(有孪生副本 sha256 完全相同却日期不同者),
    而文件头也可能被污染(与内部标题自相矛盾)⇒ 单一证据源都不可信。
    改为:⓪ config/date_authority.json 覆盖表 → ① 头部与内部标题年月日交叉一致
    则采信 → ② 不一致/缺失则回退文件名(保持历史行为,零回归)。
    判据只用年月日、不比时分(时分本就不一致,比了反使判据失效)。
  • code/steps/s3_summary.py(四项):
    1. 截断上限 6000 → 20000 字(原值只覆盖源稿中位长的约 23%),并在提示词中
      显式告知「末尾 N 字未提供、不要臆测」;
    2. 提示词新增署名硬规则:方括号内只写人名本身,严禁「发言人 / 发言人本人 /
      说话人 / 本人 / 关键发言人」等转写口条词;
    3. 抓取规则扩展:人数(几百人 / 十几人)、时长(一年左右)、倍数、月份等
      非货币数字同样是关键数字,严禁因缺少货币单位而漏抓;
    4. 出口兜底清洗(幂等,仅 T1/T2)—— 白名单归约(T3)依赖部署侧数据,刻意不启用
      以保持引擎可移植。
  • code/entity_resolver.py(ASR 别名探测路径差一级):
    原 <registry>/../../config/asr_alias.json 在多种布局下解析错位 ⇒ 探测失败 ⇒
    load_asr_alias(None) 静默降级为空表 ⇒ ASR 音近错听映射在整个链路中失效。
    改为自 registry 逐级上溯探测 <ancestor>/config/asr_alias.json(布局无关)。
  • code/pipeline.py(线程泄漏):脉冲线程停止原先只在成功路径执行 ⇒
    抛异常的样本会让 daemon 线程永久泄漏,日志出现「多个样本同时在跑」的假象
    (曾被误判为并发跑批)。改为 try/finally。
  • code/llm_client.py(四项):
    1. 空响应必须计为重试 —— SSE 建连成功、随即 0 字节结束时原实现直接 return "",
      被当作「成功」⇒ 不再重试 ⇒ 步骤产出全字段空 ⇒ 被软熔断拒落盘;
    2. base_resp 透出 —— MiniMax 的业务级错误以 HTTP 200 + SSE 返回、
      choices 为 null,真实原因在 base_resp.status_code;原实现直接 continue
      ⇒ 错误被静默吞掉,与真正的网络抖动无法区分;
    3. 429/5xx 重试条件修正 —— 原 e.code == 429 and e.code >= 500 恒假,
      限流与服务端错误从未触发重试;
    4. JSON 解析失败可见化(写 sys.stderr):原静默兜底把「解析失败」伪装成
      「确无产出」;另补 import sys(原缺失 ⇒ 兜底分支 NameError)。
  • code/judgments_aggregator.py 补 import os:使用了 os.environ 但顶部未 import。
  • 写入侧统一声明 newline="\n"(8 文件 / 10 处):.gitattributes 只管 git 侧,
    写入侧不显式指定则在 Windows 上写出 CRLF 污染工作区。

测试

  • 新增 6 个布局无关测试(33 例):test_llm_empty_retry(4) /
    test_llm_server_refusal(6) / test_newline_contract(8) / test_pulse_thread_leak(2) /
    test_s3_prompt_contract(5) / test_s3_value_gate(8)。
    test_llm_server_refusal 内嵌实测原始报文做回归;
    test_s3_value_gate 含负控(真编造必须仍被抓,防「宽容」演化成「放水」)。
  • 修复既有测试的路径脆弱性:test_entity_alias_guard 与 test_fidelity_gate
    原先只写 ROOT/"code"(src layout 下不存在),依赖收集顺序副作用才能 import ——
    单独跑必 collection error、逆序跑会中断整个套件。现统一为双布局解析
    (模板见 tests/test_d42_no_id_ops.py)。
  • 合计 118 例(85 → 118)。

上游范围经 scripts/engine_sync_probe_20260917.py 勘察裁定:先归一化(去 BOM / CRLF→LF / 去行尾空白)再比对,并按行的语法角色分型 —— 环境适配与部署侧数据一律不上游。

v2.2.4 — 分叉清账版(4 处实例热修一次上游 + 实体页并入回并根治)

Choose a tag to compare

@foreverkol foreverkol released this 15 Sep 16:29

v2.2.4 分叉清账版

实例侧 4 处热修一次上游 + 实体页并入重复小节根治。换 5 个文件即可(code/pipeline.py / code/lint_wiki.py / code/polish_pages.py / scripts/link_orphans.py / scripts/ingest_source.py,后者仅注释),已部署 2.2.0+ 的环境可按文件覆盖升级。

修复

  • pipeline.py mark_processed()(分叉 #1):count 冻结(实测 39 vs 实际 43)+ 重跑非幂等 → 同 content_hash 旧 ok 条目出栈 + count 与 ingest 口径同步 + updated_at
  • polish_pages.py merge_mode(分叉 #4 / D-d):并入规范主页时原样带回 H1+全套骨架 H2,多次并入产生重复同名小节(实例实测 23 页)→ 改为回并既有 H2 结构:剥 H1、同名小节((N) 后缀归一化)并入末尾、无名残留降级 H3 挂 ### {date} 补充出现 标记下

变更

  • lint_wiki.py(分叉 #2):MANUAL 人工审查白名单外置为 system/state/manual_entities.json(与 known_orphans.json 同套路:代码同构、数据分离;缺省空集)
  • scripts/link_orphans.py(分叉 #3):真孤儿回链工具首次进入引擎发行版(幂等、零 LLM、Synthesis/Queries/Summaries 豁免、source_meeting→source_ref 别名回退);路径锚点 PJ102_PROJECT_ROOT
  • scripts/ingest_source.py:非递归护栏注释(严禁 glob 改递归)

验证

引擎版本三处一致 2.2.4;模块级冒烟 5/5(版本/import/mark_processed 幂等+count/MANUAL config/回并逻辑);实例 verify.py 退出码 0、重复同名 H2 23→0、lint 关键维度零回归。

v2.2.3-s15fix 同源重跑不再累积(2)重复摘要页

Choose a tag to compare

@foreverkol foreverkol released this 15 Sep 02:42

v2.2.3-s15fix — 同源重跑不再累积「(2)」重复摘要页

补丁版:只动 s15_summary_page.py 一个文件。已部署 2.2.0 / 2.2.2 的环境无需重装,
按下面"路径 A"覆盖一个文件即可。想图省事就用"路径 B"重装 whl。


这个补丁修什么

code/steps/s15_summary_page.py 生成摘要页时,处理"目标文件名已存在"的逻辑写成了:

n = 2
while target.exists():                      # 只判"文件名是否被占用"
    target = out_dir / f"摘要_{date}_{topic}({n}).md"
    n += 1

它从不读旧页的 source_hash,于是:

  1. 同一份源文件每重跑一次,就必然新产出一张「(2)」「(3)」页 —— 跑得越多,垃圾页越多(污染型缺陷,会持续累积);
  2. 更糟的是重跑产物质量可能低于既有版本。实测 2026-09-08 那一场:
    新版 2585 B / 8 条双链 vs 旧版 3905 B / 15 条双链 —— 即"重跑倒退"。

修好之后的行为

改成 三级命名判定:

情形 判定 行为
目标不存在 direct 直写
存在,且 source_hash 相同(同源重跑) same_source 渲染后按内容完备度择优覆盖:新版不劣于旧版才落地,否则保留既有版本(记为 same_source_kept_old)
存在,且 source_hash 不同(异源真冲突) suffixed 沿用既有约定加 (n) —— 真冲突仍并存,不会被误删

返回体新增 naming_decision 字段,落在 system/cache/steps/<hash>/s15.json,可直接审计每次决策。
新增 _content_grade(text) -> (双链数, 五要素已填数, 字节数) 作为同源择优的排序键。

验证:四分支单测全绿;端到端真回归(B-RERUN0908)产出「(3)」= 0,
s15.json 记录 naming_decision = "same_source_kept_old"(即正确地保留了质量更高的旧版)。


升级方式

路径 A(推荐,最小改动):只换一个文件

用附件 s15_summary_page.py 覆盖你环境里的同名文件:

<你的实例或引擎目录>/pj102_engine/code/steps/s15_summary_page.py

覆盖后确认版本与关键行:

pj102 version                                   # 应显示 2.2.3-s15fix
grep -n "same_source_kept_old" .../s15_summary_page.py   # 应命中 1 行

提醒:build/lib/... 下的副本是构建产物(已被 .gitignore 忽略),不影响运行,无需同步。

路径 B:重装 whl

pip install --force-reinstall pj102_engine-2.2.3-py3-none-any.whl
pj102 version        # 应显示 pj102-engine 2.2.3-s15fix

附件

文件 用途
s15_summary_page.py 路径 A:单独替换的修复文件(273 行)
pj102_engine-2.2.3-py3-none-any.whl 路径 B:完整补丁版安装包

版本号

  • cli.py ENGINE_VERSION → 2.2.3-s15fix(pj102 version 可见)
  • pyproject.toml version → 2.2.3
  • __init__.py __version__ → 2.2.3-s15fix(此前滞留在 2.1.0-dist,本次一并归位)

不在本补丁范围

以下三项属"结果不一致 / 误报"的一致性缺陷,不产生新垃圾页,留到下一次重构批次一并处理:

  • code/pipeline.py mark_processed() —— 状态文件 count 字段不同步
  • code/lint_wiki.py —— 实体分片白名单(发布版会多报 4 组)
  • scripts/link_orphans.py —— 来源字段别名回退(source_meeting → source_ref,对 Scenarios 类页面生效)

v2.2.0-multienv 一引擎三环境

Choose a tag to compare

@foreverkol foreverkol released this 13 Sep 03:07

v2.2.0-multienv — 一引擎三环境

在 v2.1.0 基础上的维护修复与里程碑标记:一个引擎、三个隔离环境(WorkBuddy / codex / hermes)共享同一 venv、各自独立实例的部署形态达成。

修复

  • CLI ask 通道崩溃:scripts/run_query.py 为原项目遗留启动器,引用引擎包中不存在的 kb_retriever.main() 导致 ImportError——已重写为与 MCP kb_query 完全同构的调用路径(L1 实体卡直答 / L2 综合问答、行内编号引用);
  • 新增 --stub 参数:pj102 ask "问题" --stub 不调 LLM,快速验证 L1 检索链路;
  • LLM 初始化失败时优雅降级 stub(不再崩溃)。

多环境部署形态(本里程碑推荐结构)

C:\pj102-venv\          ← 共享引擎 venv(本包安装一处,三环境共用)
C:\pj102-kb\            ← 实例1:WorkBuddy 用
C:\pj102-kb-codex\      ← 实例2:codex 用(MCP 注册:config.toml [mcp_servers.pj102])
C:\pj102-kb-hermes\     ← 实例3:hermes 用(CLI 通道)

引擎升级只升 venv 一处,实例数据互不影响;MCP 注册以 args = ["mcp", "-i", "<实例路径>"] 区分实例。

升级方式

pip install -U pj102-engine==2.2.0

升级后需重启 MCP 客户端进程(常驻进程缓旧代码)。

附件

文件 用途
pj102_engine-2.2.0-py3-none-any.whl 标准 wheel
pj102-green-v2.2.0.zip Windows 绿色包(离线依赖 + 双击安装 + 完整指引)

v2.1.0 首个公开发行版

Choose a tag to compare

@foreverkol foreverkol released this 13 Sep 00:47

pj102-engine v2.1.0 首发

LLM Wiki 编译知识库引擎 —— 把录音转写 / 对话纪要编译成结构化、可检索、可溯源的 wiki 知识库。
引擎与实例彻底分离:本仓库只含能力,不含任何数据;你的知识库由你自己的文件生成,全部数据只存在你自己的电脑上。

能力清单

能力 说明
13 步 LLM 编译管线 转写原文 → 实体抽取 → 关系构建 → 概念沉淀 → 判断定义 → 洞察归纳 → wiki 页生成(Meetings / Judgments / Scenarios / Synthesis / Entities / Summaries 分区)
五类内容分型 多人会议纪要 / 双人通话 / 判断 / 情景 / 综合,按文件名与内容形态自动分型
12 维质量门(lint) 链接完整性 / 孤页 / 日期规范 / 空页 / 重名等十二维度自动巡检
两级检索栈 L1 实体导航(纯规则,毫秒级)/ L2 综合问答(三改写扩召回 → wiki 上下文 → LLM 综合 → 行内编号引用可溯源)
MCP 三工具 kb_query 问答 / kb_lint 质检 / kb_stats 统计,可注册进任何支持 MCP 的 AI 客户端
工程红线内建 幂等可重跑 / 断点续跑 / 预算熔断 / 占位符守卫 / 异常注入自检

依赖极简:Python ≥ 3.10 + PyYAML,无平台专属调用。

安装(三通道任选)

通道 ① git clone(开发者推荐)

git clone https://github.com/foreverkol/pj102-engine.git
cd pj102-engine && pip install -e .
pj102 init 我的知识库

通道 ② 直接 pip 安装(最简)

pip install git+https://github.com/foreverkol/pj102-engine.git
pj102 init 我的知识库

通道 ③ 绿色包(Windows 小白 / 离线)

下载本页附件 pj102-green-v2.1.1.zip,解压后双击 install.bat,详见包内 FRIEND_INSTALL_GUIDE.md。

需要 LLM 编译能力(pj102 run)的用户请在实例 .env 中配置自己的 API key;仅检索/质检(pj102 ask / lint / stats)无需 key。

附件说明

文件 用途
pj102_engine-2.1.0-py3-none-any.whl 标准 wheel,pip install 即用
pj102-green-v2.1.1.zip Windows 绿色包(含离线 PyYAML 依赖 + 双击安装 + 12 节安装指引)

已知限制

  • pj102 run 依赖 MiniMax 系列 API(可在配置中调整 provider);
  • wiki 生成当前以中文语料为主要形态优化,英文语料未做专项测试;
  • L2 综合问答的引用召回质量依赖 wiki 规模,小规模实例建议优先用 L1 实体导航。

许可证

Apache-2.0,详见 LICENSE。