From f51bc1caaba5cdca37dd22235c7a5931ee5272ee Mon Sep 17 00:00:00 2001 From: Darssal <110779014+Darssal@users.noreply.github.com> Date: Sun, 18 Oct 2026 23:37:50 +0800 Subject: [PATCH] docs: present research projects through implementations and design notes --- README.md | 64 +++++++++++++++------- docs/ENGINEERING_NOTES.md | 62 +++++++++++++++++++++ projects/job-text-classification/README.md | 10 +++- projects/memlab/README.md | 8 ++- 4 files changed, 119 insertions(+), 25 deletions(-) create mode 100644 docs/ENGINEERING_NOTES.md diff --git a/README.md b/README.md index 791d306..5f5cc76 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,58 @@ # Research Code Collection -用于维护研究项目的代码、配置和最小运行说明。公开版本仅包含经过筛选的源码与新编写的合成示例。 +**Agent 多层记忆与中文文本分类实验工程。** 两个独立 Python 子项目,覆盖上下文组装、异步会话、实验有效性检查、分类基线与服务批处理。 -| 项目 | 代码入口 | 当前可验证的范围 | +[![Code and publication checks](https://github.com/Darssal/Research-Code-Collection/actions/workflows/checks.yml/badge.svg)](https://github.com/Darssal/Research-Code-Collection/actions/workflows/checks.yml) + +[MemLab](#memlab--agent-多层记忆) · [文本分类](#招聘文本三分类) · [工程笔记](docs/ENGINEERING_NOTES.md) · [验证与来源](#验证与来源) + +## MemLab / Agent 多层记忆 + +面向并行会话,分离近期上下文、热缓存、持久化元数据与向量检索,提供统一记忆接口和实验控制组件。 + +| 技术问题 | 实现机制 | 入口 | | --- | --- | --- | -| 成像测井裂缝解释 | [FracLogGPT-Lite](https://github.com/Darssal/FracLogGPT-Lite) | 既有独立仓库:实验阶段编排、推理恢复、视觉对比解码与文本标签评测 | -| 招聘文本分类 | [job-text-classification](projects/job-text-classification/) | TF-IDF + 随机森林基线、可选 BERT 分类、外部聊天服务的批处理适配 | -| 多层记忆实验 | [memlab](projects/memlab/) | 上下文组装、缓存与持久化接口、并发会话实验入口、离线逻辑测试 | +| 记忆如何放置与取回 | L0–L3 分层、重要度准入、大对象指针、异步批量写入 | [记忆管理器](projects/memlab/memlab/memory_manager/manager.py) | +| 检索内容如何进入上下文 | 相关性筛选、版本与文本去重、注入预算、直接证据绕过 | [上下文策略](projects/memlab/memlab/memory_manager/l0.py) | +| 并发会话如何保留归属 | ContextVar 隔离日志上下文,记录缓存与降级路径 | [会话日志](projects/memlab/memlab/session_logging.py) | +| 哪些运行可进入汇总 | 有效性条件、失效阶段回滚和重跑计划 | [实验控制](projects/memlab/memlab/pipeline/control_plane.py) | -各子项目独立安装,具体依赖、运行命令和验证边界见各自 README。分类服务适配器不包含检索索引或知识库建设;memlab 的完整实验需要另行配置外部服务。 +`Python 3.12` · `asyncio` · `Redis` · `PostgreSQL` · `Qdrant` -## 从这里开始 +[项目与安装](projects/memlab/) · [架构](projects/memlab/docs/ARCHITECTURE.md) · [53 项离线测试的覆盖范围](projects/memlab/docs/TESTING.md) -1. 阅读对应项目的 README,先运行合成示例或离线测试。 -2. 按项目说明配置自己的数据路径和服务环境变量。 -3. 将运行输出保留在本地;提交前运行公开边界检查。 +## 招聘文本三分类 + +识别环保、人工智能与其它招聘文本(其它在接口中使用标签 `否`),提供本地基线、可选 BERT 和外部聊天服务适配器。 + +- **数据与评测**:CSV / JSONL 接口、固定种子分层划分、重复文本检查;先划分再拟合 TF-IDF,按实际类别顺序对齐概率与指标。 +- **服务批处理**:超时、有界重试、非临时错误快速结束、并发保序;默认预测产物只保留 ID、标签与错误状态。 +- **可运行示例**:24 条新编写的合成文本,CPU 执行本地随机森林流程,16 项回归测试覆盖核心行为。 ```bash -python tools/check_publication.py --help -python -m unittest discover -s tests -v +cd projects/job-text-classification +python -m pip install -e . +python -m job_text_classification demo ``` -## 维护约定 +`Python` · `scikit-learn` · `TF-IDF` · `Random Forest` · `ThreadPoolExecutor` + +[数据接口与运行](projects/job-text-classification/) · [分类实现](projects/job-text-classification/src/job_text_classification/baseline.py) · [服务适配](projects/job-text-classification/src/job_text_classification/http_adapter.py) · [回归测试](projects/job-text-classification/tests/test_regressions.py) + +## 相关项目 / FracLogGPT-Lite + +[FracLogGPT-Lite](https://github.com/Darssal/FracLogGPT-Lite) 在独立仓库维护成像测井裂缝解释的多模态实验流程:LoRA-SFT、DPO / SimPO、可恢复推理与视觉对比解码。 + +[项目介绍](https://github.com/Darssal/FracLogGPT-Lite) · [无 GPU 验证](https://github.com/Darssal/FracLogGPT-Lite/blob/main/docs/QUICKSTART.md) · [双分支解码](https://github.com/Darssal/FracLogGPT-Lite/blob/main/src/fraclog/vcd.py) + +## 设计与验证 + +[工程笔记](docs/ENGINEERING_NOTES.md)连接问题、机制、小例子和测试,涵盖推理恢复、上下文与会话隔离、分类评测与失败处理。 + +每个子项目独立安装。分类 demo 与 MemLab 单元测试可离线运行;MemLab stub / E2E 需要另行配置基础设施。持续集成检查分类、记忆组件及公开文件边界,详见 [Actions](https://github.com/Darssal/Research-Code-Collection/actions/workflows/checks.yml)。 + +## 验证与来源 -- 真实语料、测井图像、论文正文与审稿材料、模型权重、检查点、预测结果、日志和本地环境文件不进入仓库。 -- 示例数据须为新编写的合成内容。公开示例不能从真实数据中抽样或简单替换姓名得到。 -- 凭据从环境变量读取,接口地址由使用者配置;不提交真实密钥和私有服务地址。 -- 本仓库重新建立 Git 历史,不导入原实验目录的提交历史。 -- 没有附带模型训练成绩或论文性能表。合成示例与单元测试只能验证相应代码行为。 +2026-10-18 验证记录:分类 16 项、MemLab 53 项离线测试通过。合成示例用于检查流程;BERT 训练、真实 HTTP 服务、数据库与 DeerFlow 集成、论文性能实验尚未在公开版整理中运行。 -详细规则见 [公开范围](docs/PUBLICATION_SCOPE.md)、[贡献与维护](CONTRIBUTING.md) 和 [第三方来源](THIRD_PARTY.md)。检查器是提交前的辅助检查,新增文件仍需人工检查其来源、内容与公开范围。 +源码、配置、测试与合成示例可以公开;真实语料、论文材料、权重、运行输出和凭据保留在本地。第三方框架与模型的来源见 [THIRD_PARTY.md](THIRD_PARTY.md),提交规则见 [CONTRIBUTING.md](CONTRIBUTING.md) 与[公开范围](docs/PUBLICATION_SCOPE.md)。 diff --git a/docs/ENGINEERING_NOTES.md b/docs/ENGINEERING_NOTES.md new file mode 100644 index 0000000..14bcf22 --- /dev/null +++ b/docs/ENGINEERING_NOTES.md @@ -0,0 +1,62 @@ +# 工程实现与设计取舍 + +这份说明沿着源码中的三条路径展开:多模态实验的阶段衔接与解码、Agent 记忆的上下文组装与运行控制、文本分类的数据划分与服务批处理。例子用于解释代码行为;模型效果和真实服务性能需要独立实验。 + +## 1. FracLogGPT-Lite:让阶段衔接与预测恢复有明确语义 + +**问题。** 多阶段训练会产生多个 checkpoint;长时间推理可能中断,也可能重复写入。视觉对比解码则要求两条图像分支在同一文本前缀上比较下一 token 的分数。 + +**机制。** + +- **阶段交接:** [`run_pipeline.py`](https://github.com/Darssal/FracLogGPT-Lite/blob/main/scripts/run_pipeline.py) 从配置读取阶段顺序,发现已有阶段产物,并将 `${checkpoint:sft}` 等占位符解析为下游输入。[`checkpoints.py`](https://github.com/Darssal/FracLogGPT-Lite/blob/main/src/fraclog/checkpoints.py) 通过 adapter、trainer state 或权重文件识别 checkpoint;在子目录候选中按修改时间选择最新项。命令预演允许保留尚未生成的占位符。 +- **稳定样本键:** [`predictions.py`](https://github.com/Darssal/FracLogGPT-Lite/blob/main/src/fraclog/predictions.py) 优先使用 `id`,其次使用 `image` 或 `images[0]`。恢复时只处理未完成的键;结果去重时,同键保留最后一条。输出文件旁的 `.lock` 目录以排他创建方式阻止同时写入。 +- **同步对比解码:** [`vcd.py`](https://github.com/Darssal/FracLogGPT-Lite/blob/main/src/fraclog/vcd.py) 将原图和扰动图的下一 token logits 按 `original + α × (original − perturbed)` 融合,只采样一次,再将同一 token 追加到两个分支。批处理路径把两个分支放在同一 batch 中维护缓存;HF `generate` 路径限制为确定性解码,以保持分支一致。 + +**小例子。** 已有结果含 `id:sample-a`,输入为 `sample-a`、`sample-b` 时,恢复模式只推理 `sample-b`。若两个分支对同一前缀分别给出不同的下一 token,融合后选出的 token 必须同时进入两边;让分支各自采样会使后续 logits 对应不同文本历史,失去直接对比的条件。 + +**设计取舍。** 以图像路径派生键依赖路径稳定;移动文件或同图多问时应提供显式且唯一的 `id`。目录锁处理并发互斥,没有实现进程崩溃后的自动租约回收。checkpoint 的“最新”指修改时间,不等于最佳验证分数或最大训练步数。缓存路径的单元测试验证张量与状态行为,实际模型、设备和 Transformers 版本的兼容性仍需集成验证。 + +**测试入口:** [阶段恢复](https://github.com/Darssal/FracLogGPT-Lite/blob/main/tests/test_run_pipeline.py) · [预测过滤、去重与互斥锁](https://github.com/Darssal/FracLogGPT-Lite/blob/main/tests/test_predictions.py) · [分支配对、字段对齐与缓存](https://github.com/Darssal/FracLogGPT-Lite/blob/main/tests/test_vcd.py) · [无 GPU 使用指南](https://github.com/Darssal/FracLogGPT-Lite/blob/main/docs/QUICKSTART.md) + +## 2. MemLab:控制上下文注入,并记录运行是否有效 + +**问题。** 更多记忆不一定应该全部放进提示:候选可能重复、相关性不足,或与现有工具证据重叠。多个异步会话共享记忆管理器时,日志归属也不能依赖反复覆盖的全局回调。实验成功执行后,还需要判断其配置和记录是否满足比较条件。 + +**机制。** + +- **上下文组装:** [`l0.py`](../projects/memlab/memlab/memory_manager/l0.py) 先保留近期消息,再按检索分数排序候选;过滤低相关项,按键与版本去重,并用规范化文本前 512 个字符的哈希去除重复内容。选中记忆受注入预算约束,最终组装还会从前部裁剪消息。 [`manager.py`](../projects/memlab/memlab/memory_manager/manager.py) 在已有直接工具证据时可绕过检索,并返回检索跳过原因、缓存命中和降级轨迹。 +- **分层放置:** 同一管理器按重要度与对象大小选择 L0 近期上下文、L1 Redis、L2 Postgres / Qdrant 或 L3 对象存储。大对象可保存为正文加指针;异步写入队列提供批处理与背压策略。服务失败会进入降级记录,后台写入失败会向调用方暴露。 +- **并发归属:** [`session_logging.py`](../projects/memlab/memlab/session_logging.py) 安装共享操作 logger,从 `ContextVar` 读取当前 agent。会话 worker 设置上下文并在 `finally` 中恢复;A、B 会话交错执行时,各自的操作仍读取各自上下文。初始化和独立后台批次没有唯一会话归属时,字段可以为空。 +- **运行有效性:** [`control_plane.py`](../projects/memlab/memlab/pipeline/control_plane.py) 区分 accepted、invalid 和 diagnostic 等状态。新格式运行只有在已接受、汇总链有效、非诊断且未被替代时才进入正式报告;旧格式保留环境、复现和真实模型标志的兼容检查。失效运行记录异常、确定最早回滚阶段并生成重跑计划。[`summary_builder.py`](../projects/memlab/memlab/metrics/summary_builder.py) 据此排除不合格运行。 + +**小例子。** 近期消息已经包含所需工具证据时,策略可以直接组装上下文,并记录 `direct_tool_evidence_present`;无需为了“使用记忆”再次检索。另一条运行即使生成了答案,若 manifest 被标记为 diagnostic,也不会成为正式对比表中的有效样本。 + +**设计取舍。** token 数按 `ceil(len(text) / 4)` 估算,属于启发式预算;它不是模型 tokenizer 的精确计数,单条过长的最终用户消息也不会被该裁剪循环删除。文本去重只比较规范化后的前缀,并非语义去重。默认 `hash_embedding` 用于确定性实验,不等同于经过训练的语义嵌入模型。`ContextVar` 解决异步调用上下文的日志归属,没有使跨服务写入成为事务,也不会为所有后台工作自动补上会话身份。有效性门禁约束报告输入,不能替代实验设计与人工判断。 + +**测试入口:** [检索绕过策略](../projects/memlab/tests/test_memory_manager_policy.py) · [L3 指针化与降级轨迹](../projects/memlab/tests/test_system_rebaseline.py) · [交错会话日志归属](../projects/memlab/tests/test_stub_event_attribution.py) · [失效运行与回滚](../projects/memlab/tests/test_control_plane.py) · [汇总排除与作用域](../projects/memlab/tests/test_branch_audit.py) · [指标分母](../projects/memlab/tests/test_metrics_denominator.py) + +## 3. 招聘文本分类:隔离训练信息,明确批处理失败 + +**问题。** 在划分数据前拟合 TF-IDF 会把验证文本带入词表;分类器的内部类别顺序也可能与输出约定不同。批量调用外部服务时,超时、非法响应和认证失败需要终止语义,并发完成顺序不能改变记录与预测的对应关系。 + +```mermaid +flowchart LR + A[带标签文本] --> B[检查重复并分层划分] + B --> C[训练集拟合 TF-IDF 与随机森林] + B --> D[保留验证集] + C --> E[预测验证文本] + D --> E + E --> F[按固定标签顺序计算指标] +``` + +**机制。** + +- **先 split,后 fit:** [`data.py`](../projects/job-text-classification/src/job_text_classification/data.py) 检查标签,拒绝去空白、大小写规范化后相同的文本,再用固定种子按类别划分。 [`cli.py`](../projects/job-text-classification/src/job_text_classification/cli.py) 只把训练子集交给 `fit`;验证文本仅经过已拟合流水线的 `predict`。字符二至四元组 TF-IDF 与随机森林封装在 scikit-learn `Pipeline` 中。 +- **按 `classes_` 对齐概率:** [`baseline.py`](../projects/job-text-classification/src/job_text_classification/baseline.py) 将 `predict_proba` 的每列先映射到分类器的真实类别,再按固定公共标签顺序输出。未参与训练的类别填入 `0.0`;指标计算还检查输入记录与预测的 ID 顺序一致。 +- **有界 HTTP 调用:** [`http_adapter.py`](../projects/job-text-classification/src/job_text_classification/http_adapter.py) 为请求配置 timeout 和最大 attempts,失败后有限退避;除 429 外的 4xx 直接结束。响应大小和标签范围受检查。`ThreadPoolExecutor.map` 保留输入顺序,每条失败记录也会返回状态;CLI 写出结果后在有失败时返回退出码 2。输出保留记录 ID、标签、状态和概率,不写入输入原文、服务回复正文或凭据。 + +**小例子。** 分类器内部顺序为 `[人工智能, 环保]`,返回概率 `[0.2, 0.8]` 时,公开结果仍按 `[环保, 人工智能, 否]` 输出 `{环保: 0.8, 人工智能: 0.2, 否: 0.0}`。并发处理中第一条较慢、第二条先完成,最终结果仍以第一条、第二条排列;认证失败不会用完全部重试次数。 + +**设计取舍。** 拒绝规范化重复文本是明确的划分约束,没有解决语义近重复、同公司岗位泄漏或时间漂移;正式研究还需要独立测试方案。固定标签映射使接口稳定,不代表三类预测已经校准。保序意味着慢请求会影响后续结果交付;当前实现收集全部结果,不提供流式完成通知。timeout 约束请求等待,不是整个任务的严格总时限。该 HTTP 适配器遵循 `message / mode / textResponse` 协议,不包含知识库、索引或检索链路。 + +**测试入口:** [`test_regressions.py`](../projects/job-text-classification/tests/test_regressions.py) 覆盖训练词表隔离、固定种子与重复文本、概率列映射、记录对齐、模型保存加载、超时与非法响应、401 快速失败、并发保序及输出不含原文。运行方法见[项目 README](../projects/job-text-classification/README.md)。 diff --git a/projects/job-text-classification/README.md b/projects/job-text-classification/README.md index 36f314e..0fdceb4 100644 --- a/projects/job-text-classification/README.md +++ b/projects/job-text-classification/README.md @@ -1,8 +1,10 @@ -# 招聘文本三分类:无原始数据的代码整理版 +# 招聘文本三分类 / 本地基线与服务批处理 -将招聘文本分为“环保 / 人工智能 / 否”三类,提供中文字符 TF-IDF + 随机森林、可选 BERT 基线,以及外部聊天服务的 HTTP 适配器。默认示例仅在 CPU 上处理 24 条新编写的虚构文本,无需原始语料、模型权重、GPU 或 API。 +识别环保、人工智能与其它招聘文本(接口标签分别为 `环保`、`人工智能`、`否`),提供中文字符 TF-IDF + 随机森林、可选 BERT 基线,以及外部聊天服务的 HTTP 适配器。默认示例仅在 CPU 上处理 24 条新编写的虚构文本,无需原始语料、模型权重、GPU 或 API。 -本工程基于本地研究脚本 `bert_classifier.py`、`bert_classifier_bert.py` 和 `3.py` 的功能进行重新组织与修复。原先名为 `bert_classifier.py` 的脚本实际使用 TF-IDF 和随机森林,现已按真实方法命名。此版本用于展示代码组织、分类流程与失败处理,不提供论文结果,也不表示论文的完整复现或作者贡献认定。 +核心实现包括训练词表隔离、固定标签概率对齐、预测输出最小化,以及带超时、有界重试和并发保序的外部服务批处理。 + +[快速运行](#快速运行) · [数据与基线](#数据接口与本地基线) · [HTTP 适配](#可选-http-服务适配) · [设计取舍](../../docs/ENGINEERING_NOTES.md) ## 快速运行 @@ -61,6 +63,8 @@ python -m job_text_classification http --input data/authorized_jobs.jsonl --outp ## 公开范围与验证 +本工程基于原研究脚本的分类与批处理功能重新组织。原先名为 `bert_classifier.py` 的脚本实际使用 TF-IDF 和随机森林,公开版按真实方法命名;BERT 保留为可选路径。这里的验证针对代码流程,不提供论文效果或个人贡献归属的证明。 + - 保留:数据接口、训练与推理代码、HTTP 适配、全新合成例子和回归测试。 - 排除:原始岗位语料、Excel、论文及审稿材料、真实输出、服务地址、密钥、模型与既有实验指标。 - 回归测试覆盖:训练词表隔离、概率列对齐、固定指标标签顺序、重复文本划分限制、模型保存加载、HTTP 超时/非法响应/认证失败、并发保序和输出不带原文。 diff --git a/projects/memlab/README.md b/projects/memlab/README.md index 53a10d1..42bb266 100644 --- a/projects/memlab/README.md +++ b/projects/memlab/README.md @@ -1,8 +1,8 @@ -# MemLab:多层 Agent 记忆实验组件 +# MemLab / Agent 多层记忆与实验控制 -这个子工程保留多层记忆管理、上下文组装、运行记录和实验有效性检查的实现。代码可用于阅读架构、运行离线单元测试,以及自行配置 Redis / Postgres / Qdrant / DeerFlow 后开展实验。 +面向并行 Agent 会话,将近期上下文、热缓存、持久化元数据与向量检索组织为统一记忆接口。提供上下文预算与去重、分层放置、异步会话记录和实验有效性检查。 -公开版本不包含论文数据、真实对话、实验输出或模型凭据。这里没有可据以比较算法优劣的性能结果,也不声称已复现论文结果。 +[架构](docs/ARCHITECTURE.md) · [核心记忆策略](memlab/memory_manager/manager.py) · [实验控制](memlab/pipeline/control_plane.py) · [设计取舍](../../docs/ENGINEERING_NOTES.md) · [离线测试](docs/TESTING.md) ## 可以从代码中查看的能力 @@ -29,6 +29,8 @@ python -m pytest -q ## 上游与公开范围 +公开版本提供源码、配置和离线测试;真实对话、论文数据、实验输出与模型凭据保留在本地。性能比较需另行配置服务与数据并完成实验,具体状态见[测试边界](docs/TESTING.md)。 + DeerFlow 来自 [ByteDance / deer-flow](https://github.com/bytedance/deer-flow),本项目的适配参考固定版本 `7de94394d4295182701ffb47e938e7c39b963091`。公开版没有复制该上游源码,外部 checkout 和依赖需要自行准备。适配代码不代表对该上游项目的全部实现负责。 基准适配器只保留 LongMemEval 的准备脚本和 profile 判断逻辑;下载仅在显式运行该脚本时发生。使用数据集时应先核对来源及使用条件。原工作区的历史实验矩阵、论文汇报脚本和实验结论不属于本子工程。