dsmcewan/Convergence

GitHub: dsmcewan/Convergence

一个确定性的通信取证分析引擎,通过六层独立检测的交叉佐证机制,从书面通信语料中提取可审计、可追溯的结构化发现。

Stars: 0 | Forks: 0

# convergence — 通信取证引擎 (demo) [![tests](https://static.pigsec.cn/wp-content/uploads/repos/cas/6b/6b52945adbf8d9e421fe243515ae54cfbd3da263f16b1eabda37cdc0b797b8eb.svg)](https://github.com/dsmcewan/Convergence/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![Python](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12-blue.svg)](pyproject.toml) [![coverage](https://img.shields.io/badge/coverage-%E2%89%A580%25-brightgreen.svg)](.github/workflows/ci.yml) 这是一个用于分析书面通信语料库的六层引擎。它**不**知道也不关心接收到的消息属于谁。它是基于消息记录的结构*构建的*——而不是为任何特定的对话*量身定制的*——因此**同一个引擎**可以在不相关的语料库上运行,而无需更改代码。(此处附带了捆绑语料库中的十四个数据文件——承包商、共同抚养、频道、语法以及五个动态变体;运行之间唯一的区别在于 `data/` 中的数据。) **适用对象:** 任何需要通过**可审计、确定性**的方法而非黑盒分类器来展示*为什么*某个结论成立的人——例如基于书面记录进行调查的调查人员、分析师和诉讼当事人。每一个裁决都可以追溯到具体的消息以及相互印证的独立层级;语言模型可以*解释*某个发现,但永远无法改变它。 ## 六个层级 1. **模式检测** (`layers/pattern_detector.py`) — 使用其所执行的沟通策略为消息打上标签,首先是*借用权威 / 推卸责任*(“平台政策说……”、“我的律师说……”)。 2. **记录与展示重构 / "青蛙 DNA"** (`layers/gap_detector.py`) — 给定完整记录及其精选的*展示子集*,重构被删除的内容,并将**对话内部的**遗漏(从连续对话中间被裁剪掉的消息)与普通的边界修剪区分开来并打上标记。 3. **第三方引用** (`layers/third_party.py`) — 根据外部记录集测试声明并揭示矛盾,反向指向证明事实的消息。 4. **领域聚合** (`layers/domain_convergence.py`) — 检测独立主题领域在单个锚点上聚合的位置。 5. **短语碎片化** (`layers/phrase_fragmentation.py`) — 记录语域异常(发送者偏离了自身的基准)以及重复出现的 n-grams。 6. **跨频道关联** (`layers/cross_channel.py`) — 在一个频道中测试发送者的*声明*,并与该**同一发送者在第二个频道中的原话**进行比对,按发送者和谓词对齐(例如正式频道中的“我总是通知你”对比非正式频道中的“忘了告诉你……”)。在提出声明的消息上标记分歧,并引用相矛盾的跨频道消息。 ## 聚合规则 每个层级都被简化为一个通用的 `Signal`;`engine.py` 对信号进行分组,仅当独立的层级达成一致时才提升为发现。各层级的权重如下: - **实质性 (Substantive)** — L1(策略)、L2(遗漏)、L3(矛盾)、L6(跨频道分歧):实际的行动。 - **佐证层 (Corroborator)** — L4(领域重叠):增强其重叠的集群,但从不自行形成或合并发现。 - **焦点兼上下文 (Focal-but-contextual)** — L5(语域转换):像焦点层一样桥接集群,但不具有实质性;如果没有实质性层级,则无法形成发现。 只有当一个组包含 ≥1 个实质性层级**并且**总共有 ≥2 个不同的层级时,该组才会被**提升**。仅包含上下文的组以及孤立的信号将保持在**低**级别。该引擎的构建初衷是*否定自身的发现*,除非它们能经受住佐证——它不能给自己的作业打分。 ## 组合:模式与运动 引擎回答的是针对单个事件的问题(“这个发现是否得到了佐证?”)。`composition.py` 位于其上,读取结构化的结果——**无需更改引擎**——来回答两个高阶问题: - **模式** (`find_patterns`) — 跨发现的重复结构: - *命名链*(模板,与语料库无关的 DARVO 类比):例如 `sanitize-record`(清理记录) = 矛盾 + 对话内部遗漏;`two-faced`(两面派) = 跨频道分歧;`defer-and-deny`(推迟与否认) = 借用权威 + 矛盾。 - *重复策略*:一项**实质性**行动重复次数超过阈值(一种习惯,而不是单一事件)。上下文信号(领域重叠、语域转换)被排除在外——它们是环境背景,而不是行动。 - **运动** (`find_campaigns`) — 一种**持续的行为模式**:同一个*行动者*(发送者)随着时间的推移,针对同一个*目标*(主题领域)推动 ≥2 次被提升的发现。归属和时间跨度来源于消息;而裁决仍由引擎做出。一次被提升的发现是一个事件;两次针对同一目标的发现构成一次运动。 这就是 `碎片 → 策略 → 发现 → 模式 → 运动` 的层级结构:演示语料库在承包商记录中展示了一条 `sanitize-record`(清理记录)链(单一事件),而在共同抚养记录中则展示了一场真实的运动——同一个发送者在医疗相关的对话中反复引用医疗/法律权威,以否认事先约定好的日程调换。 有三份文档描述了这个层级结构,每份文档都通过一个测试与代码保持同步: - [`FRAGMENTS.md`](FRAGMENTS.md) — 最底层:每个层级所匹配的受控片段词汇表及其精确的边界(*触发条件*)。 - [`INTENT.md`](INTENT.md) — 贯穿每一个层级:每个片段及其组合的沟通**功能**,被设定为结构所提出的假设,而绝非引擎的裁决(*目的*)。 - [`HIERARCHY.md`](HIERARCHY.md) — 核心主轴:四个等级 `策略 → 发现 → 模式 → 运动`,以及促使行动升级的**每一处箭头规则**(*如何累积*)——包括第一个**命名的运动形态**,即反应性强制语法 `1 Action → [(2⇄3)⇄(4⇄5)]^n → 6 fait accompli`(`convergence/coercion_grammar.py`;尝试运行 `demo.py --corpus grammar`)。 (保障测试:`tests/test_fragments_doc.py`、`tests/test_intent_doc.py`、`tests/test_hierarchy_doc.py`。) [`ENGINEERING.md`](ENGINEERING.md) 记录了确定性优先于代理的决策,并将代码库映射到 Anthropic 的工程原则(评估优先、狭窄且有依据的模型接口、可组合的工具)。`demo.py --eval` 会打印带有评分的鉴别器报告(precision / recall / F1 / specificity,并包含困难负样本的特别标注)。 [`DYNAMICS.md`](DYNAMICS.md) 记录了五个为期 3 年的合成共同抚养语料库(`data/dyn_*.json`),涵盖了经过验证的光谱:**合作型 → 平行型 → 冲突型 → 高冲突型 → 强制控制型**,每一项均以相关文献为基础 (Maccoby & Mnookin; Ahrons; Kelly & Johnson; Stark)。`demo.py --corpus dynamics` 展示了引擎如何**依靠结构而非词汇**来**区分强制控制与高冲突**——强制语法包络仅在单方面的情况下才会完成闭环。 ## 解说 `engine.py` 输出结构化的发现;在任何模型介入之前,裁决就已经确定了。 - **`narration.py`** — `TemplateNarrator`:确定性的、无需 API Key 的通俗语言解释。这是默认选项,也是测试基准和兜底方案。 - **Convergence 之声 — `BlancNarrator`** (`--voice blanc`):以 Benoit Blanc 的语域来呈现*相同的*结构化发现、模式和运动——他是一位严谨的侦探,讲究摆出证据、尊重佐证,并拒绝凭借直觉定罪。在主题上极其精准:Blanc 只解构方法和足迹,绝不妄下结论。这是**纯粹的展现形式**——确定性的、无需 API Key 的,并且它不会改变任何裁决(有一个测试断言 Blanc 报告的已提升序列与普通解说员完全一致)。 - **`conversation.py`** — `Conversation`:一个问答层,**仅从结构化的发现中**(绝不触碰原始语料库或检测代码)进行回答,通过注入的 `complete(prompt) -> str` 实现。模型可以解释裁决,但不能改变裁决。可选的角色设定(`BLANC_PERSONA`)依附于这一事实基础之上——改变的是声音,而不是约束条件。 - **`adapters/anthropic_llm.py`** — 可选的 Claude 后端(需要 `anthropic` + `ANTHROPIC_API_KEY`)。 - **`adapters/openai_llm.py`** — 可选的 OpenAI 后端(需要 `openai` + `OPENAI_API_KEY`)。 - **`adapters/grok_llm.py`** — 可选的 Grok/xAI 后端(使用兼容 OpenAI 的 xAI API;需要 `openai` + `XAI_API_KEY` 或 `GROK_API_KEY`)。 - **`adapters/antigravity_cli_llm.py`** — 可选且**无需 API Key** 的后端,驱动已安装的 Antigravity CLI(`agy`,通过应用程序的 OAuth 实现的快速 Gemini 后端)。`agy` 仅在真实终端中打印其答案,因此此适配器会在 ConPTY 内部运行它(需要 `pywinpty`)并去除终端控制字节。`--model agy`。 适配器是唯一涉及第三方 SDK 的地方;核心代码从不导入它们。密钥可以存在于环境中,也可以放在本地的 `.env` 文件中。可选的后端依赖项列在 [`requirements.txt`](requirements.txt) 中(引擎核心不需要其中的任何一项)。 ## 安装 要求 **Python 3.10+** 和 `git`。引擎核心是**仅依赖标准库的**——安装过程不会拉取任何运行时依赖项;可选的 `llm` 扩展仅用于对话后端。 ``` git clone https://github.com/dsmcewan/convergence cd convergence python -m venv .venv # Windows (PowerShell): .venv\Scripts\Activate.ps1 # Windows (Git Bash): source .venv/Scripts/activate # macOS / Linux: source .venv/bin/activate pip install -e ".[dev]" # core + pytest; add ,llm for the optional chat backends ``` 这会安装三个控制台命令——`convergence`、`convergence-web` 和 `convergence-build`——因此不依赖于你克隆的具体路径。(如果你不想安装,从仓库根目录运行以下每个命令也都有效:`python demo.py …` / `python -m web.server`)。 ## 运行 ``` pytest tests/ -q # 191 deterministic tests convergence-build # write web/site/data/*.json (auto-runs on first serve) convergence-web # local frontend: http://127.0.0.1:8765/ convergence --corpus contractor # default convergence --corpus coparenting # same engine, other corpus convergence --corpus channels # two-channel corpus (Layer 6) convergence --about # the Voice of Convergence explains itself convergence --trick # ... explains the magic trick (the method) convergence --corpus contractor --voice blanc # the Voice of Convergence convergence --corpus grammar # coercion-grammar structural analysis convergence --corpus dynamics # 5-type discrimination table convergence --corpus db --db /path/to/your.db # run on your own SQLite export convergence --eval # scored discriminator report convergence --investigate # propose + verify new detectors convergence --chat --voice blanc # conversational Blanc with Claude convergence --chat --model openai # use OpenAI convergence --chat --model grok # use Grok/xAI convergence --chat --voice blanc --model agy # keyless, via the Antigravity CLI ``` 可选的聊天后端会从环境变量或本地 `.env` 文件中读取密钥(`ANTHROPIC_API_KEY`、`OPENAI_API_KEY`、`XAI_API_KEY`/`GROK_API_KEY`);当缺少相应的密钥/CLI 时,每个后端都会降级为确定性的解说器。 ### Docker ``` docker build -t convergence . docker run --rm -p 8765:8765 convergence # local only (no API key needed) docker run --rm -p 8765:8765 -e CONVERGENCE_API_KEY= convergence # required for any exposed deployment ``` 镜像绑定 `0.0.0.0`(通过 `CONVERGENCE_HOST`),以便可以从宿主机访问该端口;在其他所有地方,应用程序依然默认使用 `127.0.0.1`。`/api/chat` 会代理到付费的 LLM 后端,因此请务必在受信任的边界内部发布此端口。 ## 评估 有两种互补的衡量标准,因为它们回答的是不同的问题: - **合成鉴别器(带标签的真实值)。** `convergence --eval` 对五个带标签的动态语料库上的强制语法鉴别器进行评分:`precision = recall = F1 = 1.00`(**基于合成的、带标签的数据**,而非通用人群的指标),其中高冲突语料库被用作*困难负样本*(充满敌意,有多次阶段命中,但正确地未被判定为强制性)。在合成数据上的满分证明了鉴别器能够分离其设计时所围绕的类别——但也仅此而已。 - **真实数据的文档准确率(无标签真实值)。** 在真实语料库上通常没有真实值,只有流水线的分类标签——而且用这些标签来评估引擎会陷入循环逻辑。`evaluation.documentary_precision` 转而提出了一个*仅关于准确率*的问题:在引擎**提升**的消息中,有多少是独立锚定到文档或展示材料上的(通过 `corpus.load_documentary_ids`,指向你自己的证据表)?**不声称任何召回率**——文档集是不完整的,因此未经验证的发现只是一个待审查的指针,而不是一个假阳性。这尊重了文档优先原则:文档就是证据;标签只负责分类。引入你自己的佐证源即可在你的数据上运行它。 ## 部署 分为两种模式,具体取决于你是否需要实时的聊天 endpoint: - **纯静态(无服务器、无聊天)。** `convergence-build` 会写入 `web/site/data/*.json`;随后整个 `web/site/` 文件夹就是一个可以托管在任何地方的静态站点 (GitHub Pages, S3, Netlify)。讲座幻灯片、语料库和记分卡都可以基于静态 JSON 运行——只有 `/api/chat` 不可用。这是最安全的部署方式:没有后端、没有密钥、没有网络出口。 - **全栈(带聊天)。** 运行服务器(`convergence-web`) Docker 镜像。`/api/chat` 会代理到付费的 LLM 后端,因此对于任何公开的部署:请设置 `CONVERGENCE_HOST=0.0.0.0`,设置 `CONVERGENCE_API_KEY`(客户端会发送 `X-API-Key`),并在其前端部署一个具有速率限制功能且负责 TLS 终结的反向代理。 有关完整的威胁模型,请参阅 `SECURITY.md`。 ## 布局 ``` convergence/ engine (corpus-agnostic; stdlib only in core) corpus.py Message model + JSON / SQLite loaders records.py third-party Record model + loader text.py shared deterministic text helpers engine.py signal normalization + convergence verdict composition.py patterns (L7) + campaigns (L8), above the engine narration.py deterministic TemplateNarrator (+ composition narration) conversation.py grounded Q&A seam (model injected) layers/ one module per analytical layer (L1–L6) adapters/ optional LLM adapters (Claude, OpenAI, Grok, Gemini, agy) data/ 14 data files: contractor (sample_*), coparenting, channels (formal+casual), grammar, dynamics (dyn_*) tools/ generate_dynamics.py — seeded dynamics-corpus generator tests/ 191 deterministic tests web/ static frontend + local stdlib server serialize.py engine result -> browser JSON build.py writes web/site/data/*.json for static hosting server.py local frontend + /api/chat site/ vanilla HTML/CSS/JS demo demo.py narrated walkthrough (--corpus, --chat, --model) requirements.txt optional backend deps (core is stdlib only) ```
标签:Petitpotam, Python, 审计, 提示词模板, 数据分析引擎, 文本分析, 无后门, 请求拦截, 逆向工具, 通信取证