把一段聊天记录粘进来,它给你结构化判断 + 3 条候选回复 + 排序:
真实意图 确认你是否在乎
危险等级 █████░░░░░ 4.0/9 阴阳怪气/试探
对方需要 被重视
最佳动作 先查聊天记录
提示 先别给实质内容(别硬答) · 紧张未解除 · 话里有话
边界先说明白: 它只读你贴进来的对话,不接管任何聊天软件、不读你的账号、不联你的微信; 不自动发送,也不替你回。发送与否、发什么,你自己定。
三段式,判断和生成严格分工:
你粘贴的对话(最近 10 条 + 关系描述)
│
▼
① judge 7 道结构化判断题,一次请求全发
literal_question noul 对方最新消息是字面意思还是话里有话
true_intent choice 真实意图(6 类)
danger_level score 离吵架/伤感情多近(10 档,每档写具体情景)
should_reply_now noul 下一条消息该不该含实质内容
best_action choice 下一步动作类型(7 类)
she_needs choice 对方现在要什么(5 类)
tension_resolved noul 紧张是否已解除
│ (判断结果既展示给人看,也当约束喂给下一步)
▼
② draft 生成模型起草恰好 3 条候选,禁止自己做判断
│
▼
③ rank 再让 judge 给这 3 条排序,选最该发的一条
│
▼
终端展示 → /copy 复制到剪贴板(你自己粘到聊天窗口里)
关键点:judge 只答选择题/打分/是非,永远不写正文;writer 只按 judge 的结论填字, 系统提示里明确写了"你不做判断"。这是上游项目验证过的分工——判断和生成混在一个模型里, 模型会一边写一边改判断,输出不稳定。
判断层的题目措辞、state 结构、标注集,全部来自开源项目
332_lab-jev-chat(MIT,见 NOTICE.md)。
| 上游(Android/Windows App) | 本项目 | |
|---|---|---|
| 采集 | 无障碍读屏(伪装服务绕过微信节点混淆)、桌面版 UI Automation、OCR | 没有,你自己粘贴或者从剪贴板读 |
| 判断题目 | 7 题 + 1 排序题,英文 criteria | 原样保留(jev/questions.py) |
| judge 后端 | TypeSafe Jev(OpenRouter alpha decisions) | 默认换成通用模型(DeepSeek),--judge jev 可切回原版 |
| 校准 | 有脚本,但结果被 gitignore,仓库里查不到数字 | 补上了,见第 6 节,带真实数字 |
| 测试 | 无 | 56 个离线单测(假后端,不花钱) |
| 分发 | 编译好的 APK 进仓库 | 单仓库纯 Python,无依赖 |
上游真正的资产是"怎么问"——那 7 道题的英文措辞踩过坑(详见 jev/questions.py 顶部注释):
should_reply_now 和 best_action 会互相打架、对方明明已经收尾却判成"还要行动",
这些都是靠改措辞压下去的。换上任何模型都要带着这堆 criteria 走,别自己重写。
- Python 3.9+(本机系统
python3是 3.6,bin/jev会自动挑python3.12/3.11或~/.local/bin/python3.11) - 零第三方依赖,纯标准库(urllib / json / argparse / unittest)
- 一个 DeepSeek API key:
export DEEPSEEK_API_KEY=sk-...没设的话会去读本机已有的~/chat_tool/config.json(api.api_key字段) - 只有
--judge jev才需要OPENROUTER_API_KEY(Jev 走 OpenRouter 的 alpha 接口)
cd ~/jev-cli
./install.sh # 软链到 ~/.local/bin/jev,并自检 + 跑测试不想装也行,直接 ./bin/jev ...;想当包用就 pip install -e .。
密钥都不进配置文件和 git,只从环境变量读。
jev # 交互模式(stdin 是终端时)
cat chat.txt | jev # 从管道读
jev analyze chat.txt -r 情侣 # 读文件;关系描述直接影响判断结果
jev --clip -r 同事 # 从剪贴板读对话
jev -j jev -r 情侣 # 判断层换成 TypeSafe Jev 原版
jev --judge-only # 只要判断,不生成候选(最省)
jev --no-rank # 生成 3 条,但不让 judge 排序
jev --json # 只输出 JSON,方便接别的脚本
jev logs -n 10 # 看历史分析
jev show latest # 回看某次分析的完整结果
jev config show # 看当前配置和 key 状态
jev config set relationship 同事 # 改配置(会写 ~/.config/jev-cli/config.json)
jev calibrate --limit 5 # 先跑 5 条标注看校准对不对真实输出(jev analyze demos/meme.txt -r 情侣,judge=deepseek,全程约 2.7 秒):
▍结构化判断 关系:情侣 耗时 0.8s
真实意图 确认你是否在乎
危险等级 █████░░░░░ 4.0/9 阴阳怪气/试探
对方需要 被重视
最佳动作 先查聊天记录
提示 先别给实质内容(别硬答) · 紧张未解除 · 话里有话
理由 对方用“你最好是”在测试我是否真的记得,内容未给出,需先回想而非编造。
▍候选回复 耗时 1.1s + 排序 0.8s
✔ 1. 我这就去翻一下咱们的聊天记录,确认好了马上跟你说,不想瞎蒙你。
2. 你这一句“你最好是”让我有点慌,先别急,我认真回想一下,不糊弄你。
3. 不用等了,你直接告诉我是什么事吧,我想马上确认,不想让你觉得我不在乎。
→ 建议发第 1 条 最佳动作是先查聊天记录,候选1明确说去核实而非假装记得,最符合要求。
tokens_in=2782 tokens_out=200 (判断 0.8s + 生成 1.1s + 排序 0.8s)
| 命令 | 作用 |
|---|---|
/go |
分析当前缓冲(直接回车也行) |
/rel <关系> |
改关系描述,会影响判断结果 |
/list /del /clear |
看缓冲 / 删最后一条 / 清空 |
/paste |
把剪贴板里的对话追加进来 |
/copy [N] |
把第 N 条候选复制到剪贴板(默认复制排序第一那条) |
/json |
打印上一次分析的 JSON |
/q |
退出 |
输入一行一条消息:对方: xxx / 我: xxx;不带前缀按对方算。
对方: 你今天是不是又忘了我跟你说过什么?
我: 记得,你先别提示我,让我自己说。
你今天是不是又忘了我跟你说过什么? # 不带前缀 = 对方
行首 8 个字符内有 : 或 : 才当说话人前缀,正文里的冒号不会被误切。
判断准不准不能靠感觉。jev calibrate 会拿标注集跑一遍 judge,
算出每题命中率和 danger_level 的平均绝对误差,并写报告到 report/。
门禁沿用上游验收口径:danger_level MAE < 1.0 档、true_intent 和 she_needs 命中率 ≥ 60%。
实测结果(2026-09-27,judge=deepseek,30 条上游标注集 fixtures/labeled_set.json,命令 jev calibrate):
question hit mae avg_conf n
----------------------------------------------------
literal_question 63.3% - - 30
true_intent 80.0% - - 30
danger_level 63.3% 0.400 - 30
should_reply_now 63.3% - - 30
best_action 80.0% - - 30
she_needs 76.7% - - 30
tension_resolved 93.3% - - 30
----------------------------------------------------
n=30 ok=30 errors=0 avg_latency=0.895s tokens_in=63374 tokens_out=2810
gates: danger_mae<1.0=True true_intent>=60%=True she_needs>=60%=True
三条门禁全过。整轮 30 次请求 32.9 秒、HTTP 全 200。
avg_conf 是空的,因为置信度只有 Jev 会返回;通用模型 judge 不回这个字段(--judge jev 时才有值)。
错得最多的地方(校准报告 report/calibration.md 里有逐条差异):
danger_level错 11/30,但方向是双向的(偏低 6 条、偏高 5 条),MAE 0.400 说明只是差一档; 典型是"小事被当成没事":标注 2 分判成 1 分。literal_question/should_reply_now各错 11/30: 模型偏保守,常把"对方要具体东西"判成"先别给实质内容"; 反例是把已经收尾的对话(标注close_topic/say_less)判成casual_chat/make_plan。tension_resolved最稳(93.3%),true_intent和best_action都在 80%,够用。
这些偏差跟上游任务书里记的老问题同源,所以换成自己的真实对话做校准才有意义:
cp fixtures/labeled_set.json fixtures/my_set.json
# 按同样格式往里加你自己的对话片段,expect 里只写你有把握的那几题
jev config set fixtures ~/jev-cli/fixtures/my_set.json
jev calibrate想知道它到底发了什么、模型回了什么,开一个抓包目录就行(Authorization 头会自动脱敏):
JEV_TRACE_DIR=/tmp/trace jev analyze chat.txt -r 情侣
ls /tmp/trace
# 01-judge.json 02-draft.json 03-rank.json每个文件里是 {"step":1,"label":"judge","url":"...","request":{"headers":{...},"body":{...}},"response":{...}},
其中 request.body.messages 就是完整 prompt,response.usage 是这次消耗的 token。
每次分析都会在 logs/ 落一份 JSON(对话、判断、候选、排序、耗时、token),
用 jev logs 列表、jev show latest 回看。攒够带期望值的样本就能直接拿去做校准集。
jev-cli/
├── bin/jev 启动器(自动挑 3.9+ 的 python)
├── install.sh 软链到 ~/.local/bin/jev
├── pyproject.toml 可选打包(console script: jev)
├── jev/
│ ├── cli.py 命令行入口:子命令 + 交互模式
│ ├── questions.py ★ 题目集(上游资产,改之前先读顶部注释)
│ ├── backends.py judge / writer / ranker 三种后端 + 切换
│ ├── pipeline.py 三段式编排(可注入假后端,便于测试)
│ ├── llm.py HTTP(重试、错误人话化、密钥脱敏)
│ ├── model.py Message / Judgment / AnalysisResult / Usage
│ ├── input_parser.py 贴进来的文本 -> Message 列表
│ ├── calibrate.py 校准:命中率 / MAE / 门禁 / 报告
│ ├── render.py 终端渲染(颜色、危险等级条)
│ ├── store.py logs/ 读写
│ ├── clipboard.py 剪贴板(xclip/xsel/wl-copy/clip.exe)
│ ├── config.py 配置与密钥解析
│ └── labels.py 中文展示标签
├── demos/ 几段示例对话
├── fixtures/ 标注集(30 条,来自上游,MIT)
├── tests/ 56 个离线单测
└── report/ calibrate 生成的报告(不入库)
python3.11 -m unittest discover -s tests -t . # 56 passed全部用假后端,不打网络、不花钱。覆盖:题目集口径、输入解析、三段式编排、 usage 累加、校准命中率与门禁逻辑、报告生成、渲染、配置与子命令。
- 没有采集层。上游用无障碍/OCR 自动读屏,这里是你手动粘贴——这是功能取舍,不是遗漏。 真要自动化,路子是桌面版微信的 UI Automation 或轮询剪贴板,是另一个工程。
- 群聊不准。判断口径针对一对一,"对方"和关系描述在群里失效。
--judge jev这条路径没验证过。本机没有 OPENROUTER_API_KEY,代码写了但一次没跑过; 另外上游 Windows 版打的是api.typesafe.ai/v1/systemone,与这里的 OpenRouter alpha 接口不一致。- 中文判断用英文题目。这是上游的结论(模型主训练语言是英文,中文题目效果更差), 聊天内容保留中文原文。
- 没有"查聊天记录"能力。
best_action=check_history只是提示你该去翻记录, 工具本身没有历史库,也不会假装记得。 - 单模型 judge 不返回置信度(只有 Jev 有),所以校准表里
avg_conf是空的。
没有 DeepSeek key — export DEEPSEEK_API_KEY=sk-...,或者 jev config show 看它有没有读到
~/chat_tool/config.json。
需要 Python 3.9+ — 系统的 python3 太旧。用 ./bin/jev(会自动挑),或
python3.11 -m jev。
输出没有颜色 — 管道/重定向时自动关色;想强制关就 --no-color 或 NO_COLOR=1。
/copy 说没找到剪贴板工具 — 装 xclip/xsel,或者手动选中复制输出里的候选。
判断结果和你的直觉不一致 — 先改 -r 关系描述(它直接影响判断),
再考虑按第 6 节用自己的对话做一个小标注集量化一下;不要凭单个案例改 questions.py 的措辞。
- 本项目 MIT(
LICENSE)。 - 题目集、state 结构、标注集来自 332_lab-jev-chat(MIT),
见
NOTICE.md与THIRD_PARTY_LICENSE_upstream_MIT.txt。 - 判断模型的原始方案来自 TypeSafe Jev。
- 仅供个人学习与研究;只处理你自己设备上、你自己有权查看的对话。