Releases: foreverkol/pj102-engine
Release list
v2.5.0 · excerpt 输入截断体系 + 缓存熔断 + 内容承接门 + 日期权威
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.pyv1.6:分片页丢弃必须过「内容承接」门。
三条无校验丢弃路径曾致 210 个分片页中 20 份的实质内容未被任何规范页承接即被
unlink。现统一为一条不变式:分片页只有在其实质内容已被目标页承接时才可丢弃;
未承接 ⇒ 强制并入目标页(而非新建「(2)」副本),保证只增不减。
含_norm_line/_body_lines/_subst_lines/_contained装置。scripts/run_full.py接线 4 个后处理装置:2.5link_orphans(孤儿回链补齐,
必须排在 backlink_builder 之后、index_builder 之前)、7.5normalize_tree
(出口署名校正,幂等)、7.6 registry 别名健康度巡检(只读 + 告警)、
8baseline_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(四项):- 截断上限 6000 → 20000 字(原值只覆盖源稿中位长的约 23%),并在提示词中
显式告知「末尾 N 字未提供、不要臆测」; - 提示词新增署名硬规则:方括号内只写人名本身,严禁「发言人 / 发言人本人 /
说话人 / 本人 / 关键发言人」等转写口条词; - 抓取规则扩展:人数(几百人 / 十几人)、时长(一年左右)、倍数、月份等
非货币数字同样是关键数字,严禁因缺少货币单位而漏抓; - 出口兜底清洗(幂等,仅 T1/T2)—— 白名单归约(T3)依赖部署侧数据,刻意不启用
以保持引擎可移植。
- 截断上限 6000 → 20000 字(原值只覆盖源稿中位长的约 23%),并在提示词中
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(四项):- 空响应必须计为重试 —— SSE 建连成功、随即 0 字节结束时原实现直接
return "",
被当作「成功」⇒ 不再重试 ⇒ 步骤产出全字段空 ⇒ 被软熔断拒落盘; base_resp透出 —— MiniMax 的业务级错误以 HTTP 200 + SSE 返回、
choices为null,真实原因在base_resp.status_code;原实现直接continue
⇒ 错误被静默吞掉,与真正的网络抖动无法区分;- 429/5xx 重试条件修正 —— 原
e.code == 429 and e.code >= 500恒假,
限流与服务端错误从未触发重试; - JSON 解析失败可见化(写
sys.stderr):原静默兜底把「解析失败」伪装成
「确无产出」;另补import sys(原缺失 ⇒ 兜底分支NameError)。
- 空响应必须计为重试 —— SSE 建连成功、随即 0 字节结束时原实现直接
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 处实例热修一次上游 + 实体页并入回并根治)
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_atpolish_pages.pymerge_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_ROOTscripts/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)重复摘要页
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,于是:
- 同一份源文件每重跑一次,就必然新产出一张「(2)」「(3)」页 —— 跑得越多,垃圾页越多(污染型缺陷,会持续累积);
- 更糟的是重跑产物质量可能低于既有版本。实测 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.pymark_processed()—— 状态文件count字段不同步code/lint_wiki.py—— 实体分片白名单(发布版会多报 4 组)scripts/link_orphans.py—— 来源字段别名回退(source_meeting → source_ref,对 Scenarios 类页面生效)
v2.2.0-multienv 一引擎三环境
v2.2.0-multienv — 一引擎三环境
在 v2.1.0 基础上的维护修复与里程碑标记:一个引擎、三个隔离环境(WorkBuddy / codex / hermes)共享同一 venv、各自独立实例的部署形态达成。
修复
- CLI
ask通道崩溃:scripts/run_query.py为原项目遗留启动器,引用引擎包中不存在的kb_retriever.main()导致ImportError——已重写为与 MCPkb_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 首个公开发行版
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。