Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@
- `app/tools/schema.py` —— CSV 表结构描述
- `app/llm.py` —— 兼容层(旧的 get_llm),实现已移到 `app/core/llm.py`
- `app/eval/` —— 评测:50 题用例、比较器(顺序/答案形态规则见 comparator.py 文件头)、报告
- `ui/streamlit_app.py` —— 单轮网页界面(工作流版)
- `ui/chat_app.py` —— 多轮对话界面(ReAct 版 + 记忆,支持追问)
- `ui/web/` —— 前端(React + TS),由 `python -m app.server --open` 托管

## 运行

Expand Down Expand Up @@ -87,12 +86,6 @@ python run_eval.py
python run_eval.py --oracle
python run_eval.py --repeat 3 # 同一配置连跑 3 次,看均值与波动
python run_eval.py --rescore outputs/eval_xxx.json # 不调模型,按当前比较器/标准答案重新打分

# 3d. 单轮网页界面(工作流版)
streamlit run ui/streamlit_app.py

# 3e. 多轮对话界面(ReAct 版,支持记忆与追问)
streamlit run ui/chat_app.py
```

在代码里调用:
Expand Down
2 changes: 1 addition & 1 deletion app/core/service.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""统一的分析服务函数 analyze()(B16)。

所有入口(run.py / run_react.py / run_eval.py / 两个 Streamlit 页面,以及以后的 FastAPI)
所有入口(run.py / run_react.py / run_eval.py / app/server 的 FastAPI 后端)
都只调这一个函数,不再各自装配 schema、字典检索、图和模型。

约定:
Expand Down
29 changes: 27 additions & 2 deletions docs/DEVLOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Python · LangGraph(StateGraph 工作流版 + create_react_agent ReAct 版)
| B11 | P2 | eval/report.py:31-34, :40 | 正确率分母只算 executed(虚高);无报错修复率记 100% | 1 |
| B12 | P2 | eval/comparator.py _normalize_obj | Series 转 dict 比较忽略顺序(虚高);答案形态不一致(虚低) | 1 |
| B13 | P2 | eval/runner.py | 只测工作流版;双重执行;无耗时/token | 3 |
| B14 | P2 | ui/streamlit_app.py | 未接字典 RAG,与 README 不符 | 1(随 Streamlit 下线) |
| B14 | P2 | ui/streamlit_app.py | 未接字典 RAG,与 README 不符 | 1(随 Streamlit 下线,已删 [67]) |
| B15 | P2 | tools/csv_io.py | latin-1 兜底静默乱码 | 1 |
| B16 | P2 | 4 个入口 | 各自装配流程,无服务层 | 1 |
| B17 | P2 | requirements.txt | 未锁版本;无测试、CI、日志框架 | 0 |
Expand Down Expand Up @@ -1903,6 +1903,16 @@ S 10-21 第二轮:
走查记录:(S 跑完后填)


**走查记录(S,2026-10-23 ~ 10-26,Windows + Firefox 缩放 90%,真 Key)**
- 五条路径全部通过(S 10-26:「其他的没问题」「都是能接受的」)。⑥ 按 10-21 的约定不用复核。⑦ THREAT_MODEL §2.3 S 10-26 确认无异议。
- 10-23 第一批发现:白屏(Windows .js MIME,#74)和观感 8 条,进了 V2c(#75 / #76)。测试 agent 的基线报告(假模型 ①~⑥ 全过)也一并处理了。
- 10-26 真 Key 发现,S 定为**可接受、不处理**:
- token 消耗偏高。多表题出 4 张图,没取到数字;单轮预算 130,000 兜底([66])。
- 「写代码」阶段停不下来。停止只在事件之间检查(service.py:119-121),正在进行的模型调用要等它返回;单次 60 秒,加最多 3 次重试(llm.py:33-34)。这是 F2「不主动断流」的设计。
- 图表标题选不中、复制不了。标题是画在 ECharts canvas 上的。
- 会话页不显示模式(标准 / 边想边做),只能从步骤条有没有「理解问题」看出来。
- 本机环境:ui\web\dist 是用管理员身份解压的,ACL 锁住了,要在管理员 PowerShell 里用 C:\Windows\System32\takeown.exe / icacls.exe 解锁后才能删(PATH 里没有 System32)。

## [56] 2026-10-22 · F4 迭代 V2a 方案:按 S 设计稿改版 · commit e4b6ef1

[55] 回填为 b6769cd。
Expand Down Expand Up @@ -2204,7 +2214,7 @@ S 10-25 定:§2 上游原文折叠保留;§4 根字号 14。

方案见 docs/roadmap/phase5-frontend.md「V2d」:1 usage 拆分(cache_read / reasoning / estimated,零调用 reported=None,报告导出 6 个字段);2 单轮预算默认 130,000(ReAct 闸门实测最高 63,817 的约 2 倍),调用前判定并预留收尾量,ReAct 走强制收尾、工作流不进 reviewer,缺 usage 按字数估算,卡片显示 tokens;3 finish_reason=length 作为明确错误,本节不设 max_tokens。其余各项记进 plan.md「外部审计待办」。

## [66] 2026-10-26 · V2d 实现:token 观测与单轮预算 · commit <待提交>
## [66] 2026-10-26 · V2d 实现:token 观测与单轮预算 · commit 2b283b6(PR #78)

[65] 回填为 1144c27(PR #77;master tests run 40255033298 绿,这个提交只触发了 tests 工作流)。按 phase5-frontend.md「V2d」§1~3 实现,偏离写在该节「实现与偏离」。

Expand All @@ -2214,3 +2224,18 @@ S 10-25 定:§2 上游原文折叠保留;§4 根字号 14。
- 测试设施:ScriptedChatModel tokens_per_call=None 模拟不回 usage;fake_llm 新增 tokens-<N> 场景、MARK_FINALIZE。
- 判定变更:旧断言一条没改(零调用 reported=None 的路径以前没有测试断言)。新增 tests/test_v2d.py 20 条、src/views/v2d.test.tsx 5 条、e2e/f4-budget.spec.ts 1 条(fake 项目按文件名 f[34]* 匹配)。提示词、chart_fixtures 不变。视觉 11、25 两屏:token 文字让 `.acard-time` 遮罩框变宽(每张 1119 像素,只在遮罩框里),基线换成首跑 CI run 40260578380 的 x64 actual;我本地报的「基线不用重取」是错的——本地 aarch64 这 4 屏本来就红,看不出这个差异。


## [67] 2026-10-26 · F5 通过,删 Streamlit · commit <待提交>

[66] 回填为 2b283b6(PR #78;master tests run 40262438449 绿)。F5 走查记录补在 [55] 末尾:五条路径都过了;10-26 的 4 条发现 S 定为可接受,不处理。

按 phase5「F5 · 通过与收尾」的清单逐条删除:
- [x] `ui/streamlit_app.py`、`ui/chat_app.py`
- [x] `requirements.txt` 的 `streamlit==1.65.0`
- [x] `tests/test_ui_smoke.py`(3 个测试项:test_page_renders × 2 页 + test_chat_app_turn_goes_through_analyze)。pytest 基线从 872 降到 869,这是删除带来的,不是回归。
- [x] `packaging/build_sidecar.py` 的 `--exclude-module streamlit`
- [x] README 里的 Streamlit 界面介绍和两条 `streamlit run`
- [x] HANDOVER 第 20 行;DEVLOG B14 标成「已删」
- 另外改了:app/core/service.py 文件头的入口列表、plan.md 阶段 5 的状态(标成完成)。

pyarrow:它只是 streamlit 的传递依赖([18],DEVLOG 第 771 行),所以删掉 streamlit 后,新装的环境里不会再有 pyarrow。pandas 3.0 在没有 pyarrow 时字符串后端改用 python,开发和打包也因此一致了。这样 [18] 留到阶段 6 的「pyarrow 去留」问题就不用再定了,sidecar 体积预计少约 78 MB,以 CI 的 sidecar 工件为准。验证:我用全新 venv 装 requirements-dev.txt,确认没有 streamlit 和 pyarrow,再跑全量 pytest。
6 changes: 3 additions & 3 deletions docs/HANDOVER.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@
- `app/server`:FastAPI 本地后端(sidecar),SQLite(写法兼容 PG),SSE 推事件,Bearer token,托管前端 dist 并带 CSP。启动契约见 `docs/sidecar-contract.md`(壳必须 `--port 0`)。
- `ui/web`:React 19 + TS 前端(Vite、vitest、Playwright),图表用 ECharts(按需引入)。**前端只通过 HTTP/SSE 和后端通信,不用 Tauri IPC**(S 定,2026-10-12)。
- 外壳:Tauri 2 + PyInstaller 打包的 sidecar,在 GitHub Actions 的 Windows runner 上构建(`packaging/`、`.github/workflows/sidecar.yml`)。
- Streamlit 旧界面(`ui/streamlit_app.py`、`ui/chat_app.py`)还在,F5 验收后单独 PR 删除(连带面 6 处,清单在 phase5「F5」)。
- Streamlit 旧界面已在 F5 验收后删除(DEVLOG [67])。

进度:阶段 0–4 完成;**阶段 5(前端)收尾中**,方案是 `docs/roadmap/phase5-frontend.md`。
- F0–F2(#32–#35)、F3 ECharts 六步(#41–#53)、F4 层 1 面板(#57)、F4 迭代 V1(#67)、F4 迭代 V2a(#70,按 S 的设计稿整体重做界面)都已合并。
- 和 F 路径并行的:chart_errors 按执行记账(result.py:117,#55,已完成)、#49 矮画布紧凑几何(#58)、#44 sidecar 契约(#59)、T11 错误文案脱敏(#61)、A1 错题自动复跑(#63)、G1 闸门 oracle 上 CI(#65)、`llm_kind`(含在 #70 里)。
- F5(S 用真 Key 走五条路径)的清单已合并(#68,DEVLOG [55]),**还没走**,在等 S。
- F5:S 用真 Key 走完五条路径并通过(2026-10-26,走查记录在 DEVLOG [55]);Streamlit 已删(DEVLOG [67])。阶段 5 完成,下一步阶段 6。
- 最近一步:四屏视觉回归(`ui/web/e2e/f4-visual.spec.ts`,DEVLOG [59])。

基线数字(39c4741 + [59],Linux 沙箱):pytest 837 passed(含闸门 25 条,需先下数据)、vitest 790、e2e 38、lint / tsc / build / `gen_ui_types --check` 全过。
Expand Down Expand Up @@ -79,7 +79,7 @@ S 的评审风格:逐条评审,会对照代码和截图核实,按 P0(挡
- 设置页「测试连接」:要后端新接口。
- P1-17:图表警告文案("x 列 '…' 不存在"暴露变量名)在后端 `chart_warnings`,前端改写就是匹配后端文案,要改就改后端。
- P1-16:失效页"重新打开应用"浏览器里做不到,放阶段 6。
4. **F5**:S 用真 Key 走五条路径(清单在 phase5「F5」),走完把记录填进 DEVLOG [55]。然后单独 PR 删 Streamlit(pytest 基线 814 → 811 是当时的数,现在要按 837 重算)。
4. **F5**:已通过(2026-10-26),Streamlit 已删,pytest 基线 872 → 869(DEVLOG [67])。
5. **阶段 6** Tauri 打包。代码签名证书要由有实名主体、能付款的一方办(S 没有),选型(大概率 OV 起步)在 phase5「F5」末尾的阶段 6 前置事项里。

## 6. 环境搭建与运行
Expand Down
2 changes: 1 addition & 1 deletion docs/roadmap/phase5-frontend.md
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@ v2 才可达的字段(link、formatter、aria 等)留到层 2 再测。

估时 1.5 天,一个 PR。

### F5:S 验收走查(已定,S 10-21 评审通过;DEVLOG [55])
### F5:S 验收走查(已通过 2026-10-26,走查记录见 DEVLOG [55];Streamlit 已删,DEVLOG [67])

F5 不是回归清单,而是一次真 Key 的手动走查加观感判断,预计一小时内跑完。32 条 e2e 已经覆盖的内容这里不重抄,只列"看什么、什么算过、截图留哪"。启动命令:`python -m app.server --open`。

Expand Down
4 changes: 2 additions & 2 deletions docs/roadmap/plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
| 3.5 外部验证闸门 | 3 天 | 非自造数据上的 25 题(单表 15:UCI Online Retail 改造的中文 GBK 脏表;多表 10:Olist 8 张表);标准答案由独立脚本在原始数据上算出;最小多表支持(dfs);报告逐题标判对层级、评测集指纹 | 按 docs/roadmap/gate-phase35.md 预登记的阈值与失败分布规则出结论 | M01 M02 M04 M05 M10(部分) M15 |
| 4 后端 API | 1–2 周 | 第一步:API Key 进系统钥匙串(keyring);`analyze_stream()` 逐步产出事件,`analyze()` 包一层(M09)。FastAPI:数据集上传(一个数据集可含多个文件,M10)、会话、消息(SSE 流式推送每一步)、设置;SQLite + SQLAlchemy(表结构兼容 PG,预留 user_id);logging + trace id(会话 / 消息 id),runs.jsonl 换成数据库(M08 M14);接口返回 png + 图表数据(M13)。最后:PyInstaller sidecar + 沙箱 worker 在 Actions Windows runner 上的 spike(B35 / M06) | 用 curl 走完"上传 → 提问 → 流式结果 → 历史可查";重启后会话还在;spike 打出的 exe 能在干净 runner 上执行一次沙箱代码 | B18 B35 |
| 5 前端 | 2–3 周 | 第一件事(M13,从阶段 4 顺延,含后端三步):图表库定为 ECharts;定 option 格式与白名单、写 builder `chart(kind, df, x=, y=, series=, title=)`;worker 产出 chart_option(与 result 脱钩,B44);接口加 chart_option;改绘图提示词并重跑闸门。之后:React + Vite + TS:数据集面板、对话流(展示计划、代码、执行步骤)、图表、可展开的代码、👍👎 反馈、Key 设置页,分步与验收见 docs/roadmap/phase5-frontend.md(F0–F5) | 不碰命令行就能完整用一遍 | — |
| 6 桌面打包 | 1–2 周 | Tauri 2 外壳(前提见上:前端只走 HTTP)+ PyInstaller 后端 sidecar;Windows 安装包;自动更新;首次启动引导填 Key;依赖许可证审计;决定 pyarrow 去留(打包体积 78.5 MB,开发与打包环境须一致,见 DEVLOG [18]) | 在一台干净的 Windows 上一键安装,可用;对外分发前代码签名、SmartScreen 不拦(M19);对外分发前满足 THREAT_MODEL.md 的 (b) 条件 | — |
| 6 桌面打包 | 1–2 周 | Tauri 2 外壳(前提见上:前端只走 HTTP)+ PyInstaller 后端 sidecar;Windows 安装包;自动更新;首次启动引导填 Key;依赖许可证审计;pyarrow 已随 Streamlit 一起去掉(DEVLOG [67]) | 在一台干净的 Windows 上一键安装,可用;对外分发前代码签名、SmartScreen 不拦(M19);对外分发前满足 THREAT_MODEL.md 的 (b) 条件 | — |
| 7 准确率 | 2–4 周 | DuckDB 统一 CSV/Excel/SQL;YAML 语义模型(指标、口径、同义词);枚举值召回;结果合理性校验;反馈沉淀为已验证问答对 | 在阶段 3.5 闸门数据上给出具体目标(闸门结论后定,M20);自造集只作回归 | B05 B09 |
| 8 Web 上线(后续) | 另定 | PostgreSQL、登录、任务队列、Docker/E2B 沙箱、Langfuse、服务器部署与 ICP 备案 | 另定 | 多租户 |

Expand All @@ -30,7 +30,7 @@
| 0–3d | 完成 | 2026-10-09 → 10-10 | DEVLOG [1]–[9] |
| 3.5 / 3.6 | 完成,闸门中间区,P0 ⑤⑥ 已修 | 2026-10-12 | DEVLOG [10]–[13] |
| 4 | **完成**,三条验收都达到 | 2026-10-12 → 10-13 | DEVLOG [14]–[18];curl 全流程与重启见 [16],跨重启多轮见 [17],干净 runner 上执行沙箱代码见 [18] |
| 5 | **收尾中**:M13 后端三步、F0–F3、F4 层 1、F4 迭代 V1 / V2a、四屏视觉回归已合并;剩 V2b、测试连接、P1-17(方案见 phase5「阶段 5 收尾」)→ F5 真 Key 走查 → 删 Streamlit | 2026-10-13 → 进行中 | DEVLOG [19]–[60];最近合并 #71(1c0b41a,tests run 39891923237) |
| 5 | **完成**:F0–F4、V1 / V2a~V2d、F5 真 Key 走查通过(2026-10-26),Streamlit 已删 | 2026-10-13 → 10-26 | DEVLOG [19]–[67] |

**重估(M18)**:阶段 0–4 原估 5–7.5 周,实际 5 个日历日。原因是代码主要由 Hark 写、S 审,**不能**照这个速度外推后面的阶段:
- 阶段 0–4 几乎都能在 Linux 沙箱 + CI 里验证;阶段 5–6 的验收是"不碰命令行能用""干净 Windows 一键安装",必须 S 在本机动手看,日历时间取决于 S 的可用时间,不取决于写代码的速度。
Expand Down
1 change: 0 additions & 1 deletion packaging/build_sidecar.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
"--copy-metadata", "keyring",
"--collect-submodules", "keyring.backends",
# 用不到、但会被分析器拖进来的大包
"--exclude-module", "streamlit",
"--exclude-module", "tkinter",
"--exclude-module", "IPython",
"--exclude-module", "pytest",
Expand Down
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ pandas==3.0.6
numpy==2.4.6
matplotlib==3.11.2
python-dotenv==1.2.4
streamlit==1.65.0
rank-bm25==0.2.2
jieba==0.42.1
# 阶段 4:API Key 存系统钥匙串(app/core/keystore.py)。依赖按平台锁定(uv pip compile,3.11/3.12 × Windows/Linux)
Expand Down
46 changes: 0 additions & 46 deletions tests/test_ui_smoke.py

This file was deleted.

85 changes: 0 additions & 85 deletions ui/chat_app.py

This file was deleted.

Loading
Loading