assistant/docs/archive/README-school-2026-10-28.md

14 KiB
Raw Permalink Blame History

智能办事助手(School Assistant)

跨系统智能办事助手 MVP:Electron 聊天 + Python 编排 + Browser Use 自主操作网页。

本项目位于 browser_use/school-assistant/,与同级的 AI 获客助手 assistant/ 分开维护;以下命令均在本项目根目录执行。

产品形态类似 Codex 桌面端:左侧任务列表与历史(点开可回放过程),中间对话、任务卡与确认卡片,右侧是内嵌的浏览器面板——Agent 就在这个面板里操作学校系统,可以展开 / 收起,需要用户决定时停下来问,回答后在同一页面里继续,随时可以「我来接管」。

当前能力(D13,2026-09-17)

  • 一句话发起任务:先识别业务并抽取字段(DeepSeek / 千问一次调用),缺资料时对话追问,再按业务角色登录执行
  • Agent 自主登录、找入口、填表、提交前逐项确认(演示业务:辅导员每月查课日志填报;通用探索兜底)
  • ask_user 暂停机制:不受 browser-use 步骤超时限制,浏览器会话保活,用户回答后续跑同一个 Agent
  • 系统账号:system_accounts 表按学生 + 系统存加密密码,运行时通过 sensitive_data 自动填写,LLM 看不到明文
  • 可观测:每步截图 data/tasks/{id}/steps/、进度 progress.md、精简执行历史存 run_logs
  • 自动沉淀:任务成功后提炼经验草稿(带类别),按内容判重归并;控件技巧 / 入口路径类被多个任务观察到自动生效,系统规则类由团队在运维模式下采纳。用户端无感。YAML 只是出厂基线,GET /learned/export 可导出交付
  • 运维模式:.env OPERATOR_MODE=true 才显示「沉淀草稿」面板,交付学校默认关闭
  • 内嵌浏览器:每个任务一个 WebContentsView 挂在应用右侧面板里(独立登录态分区、域名白名单),browser-use 经 Electron 的 CDP 端口直接操作它;Agent 开始操作或停下来问你时自动展开,可随时收起;运行中可「我来接管」(Agent 模式下键盘输入会被拦住并提示先接管),操作完交还给 Agent 继续。单独跑后端(无 Electron)时退回独立 Chrome 停靠模式
  • 提交后跟踪:已提交的任务定时回查审批状态,通过 / 驳回时在对话里提示,可「立即回查」或「停止回查」
  • 前置阻断:系统提示「先办另一件事」时,同角色能办的问你要不要顺带办完再回来,需要别人处理的告诉你找谁,任务进入「被前置事项拦住」等你处理好再继续
  • 多校隔离:所有学校数据带 school_id,实例用 .env 的 SCHOOL_ID 指定所属学校
  • 评测脚本 scripts/eval_run.py:同一任务连跑 N 次统计成功率 / 步数 / 时长,默认干跑(到确认即取消)。查课日志填报实测到确认 18 步 / 158 秒
  • Electron 是后端的唯一所有者:启动时自动关掉端口上残留的旧后端,退出时关掉自己的

环境要求

  • Node.js 20.19+(Vite 8 / Electron 33 构建链)
  • Python 3.11+
  • Docker Desktop(运行 PostgreSQL 17)
  • DeepSeek 或千问 API Key(默认 DeepSeek)

快速开始

0. 启动 PostgreSQL(Docker)

cd D:\qiekj\browser_use\school-assistant
docker compose up -d

数据落在 127.0.0.1:15433 的 PostgreSQL 库 school_assistant,账号见 docker-compose.yml;后端启动时自动建表并同步 knowledge/*.yaml。2026-09-17 从 MySQL 切换而来,旧数据用 scripts/migrate_mysql_to_pg.py 迁移。.env 的 SCHOOL_ID 决定本实例属于哪所学校,学校之间数据互不可见。

1. 安装 Python 依赖

推荐用 uv(自动建 Python 3.12 的 .venv,按 backend/requirements.lock 精确同步,含打包用的 PyInstaller):

cd D:\qiekj\browser_use\school-assistant
npm install
npm run backend:setup

没有 uv 也行:脚本会用系统 Python 的 pip 把 uv 装进项目的 native/build/ 里,不碰系统环境。手工方式:python -m venv .venv && .\.venv\Scripts\pip install -r backend\requirements.txt。不需要 playwright install,浏览器就是 Electron 自带的 Chromium。

2. 配置 API Key

复制 .env.example 为 .env,填入:

LLM_PROVIDER=deepseek
DEEPSEEK_API_KEY=sk-你的key
LLM_MODEL=deepseek-chat
LLM_BASE_URL=https://api.deepseek.com/v1

也可切换 LLM_PROVIDER=qwen 并使用 qwen-vl-max。 可选再配一把兜底 Key DEEPSEEK_API_KEY_FALLBACK(千问为 DASHSCOPE_API_KEY_FALLBACK):主 Key 返回 402 余额不足时,识别、沉淀和 Agent 执行中的下一次调用都自动切到兜底 Key,任务不中断;之后每 LLM_PRIMARY_RETRY_HOURS(默认 1)小时重试主 Key,充值后自动恢复。侧栏状态会显示「兜底 Key」。

3. 安装并启动 Electron

npm install
npm start

npm start 先构建(esbuild 打主进程 / preload,Vite 打 React 渲染层,产物在 dist/),再启动 Electron;Electron 自己拉起 Python 后端(用 .venv),并在启动前关闭端口上残留的旧后端。发送任务后右侧浏览器面板自动展开,Agent 在里面操作;停下来提问时,点卡片按钮或直接在聊天框回答即可。只做类型检查用 npm run check。

4. 录入系统账号(可选)

密码本按「人 × 系统」存账号并记录该账号的角色;业务要求的角色和账号角色不一致时直接告知办不了。有账号时 Agent 自动登录(多系统时凭据按域名分组,模型看不到明文),没有则按 knowledge/*.yaml 里 login.fallback_mode 处理(测试环境用快捷登录按钮)。密码用 .env 的 ACCOUNT_ENC_KEY 加密存储:

Invoke-RestMethod -Method Post -Uri http://127.0.0.1:8788/api/accounts -ContentType "application/json; charset=utf-8" -Body (@{ student_id = "default"; system_id = "xgxt"; role = "辅导员"; username = "工号"; password = "密码" } | ConvertTo-Json)

5. 跑测试

npm test

288 个用例约 3.4 秒。其中 15 个要连本机 PostgreSQL(用一次性的测试学校隔离,跑完自动清理,不会碰到正式数据),数据库没起时自动跳过;npm run test:fast 直接跳过它们。覆盖意图识别与退路、状态判定、经验沉淀的判重与自动晋升、角色准入、凭据按域名分组、前置阻断问句、执行结果判定、模型 Key 兜底。

6. 评测成功率

npm run eval -- --n 3 --supplement "课程是高等数学,授课教师是张老师"

默认干跑:走到「提交前确认」自动回复取消,不会真提交;加 --submit 才会确认提交。--supplement 是任务追问时自动补充的话。结果写入 data/eval/*.jsonl。

后台审核台(中心服务端)

桌面端办完事会自动沉淀经验草稿。草稿要不要生效,控件技巧和入口路径类被两个任务观察到就自动生效,系统规则类必须人审。人审就在这个后台做。

npm run hub:build   # 构建界面
npm run hub         # 启动,打开 http://127.0.0.1:8801/

在「学校」页给每所学校生成一串上报凭证(只显示一次),写进那台机器的 .env:

HUB_URL=http://中心地址:8801
HUB_TOKEN=生成的凭证

之后那台桌面端会在每次沉淀后自动上报,并定时(默认 15 分钟)拉回审核结果。没配这两项就是单机模式,本地照常沉淀和自动晋升。

审核台上每条草稿显示它被几所学校观察到过、累计观察多少次,可以采纳、驳回、改写后采纳,也可以批量处理。跨校观察是最强的可信信号:同一条知识被多所学校各自撞见,说明它不是某校特例。采纳时选发布范围:只回来源学校,还是推给所有学校。点「预审」会先让模型给建议和理由,建议只是建议,不会自动改状态。

驳回也会推回各校:本地可能已经自动晋升过一条错知识,中心驳回后桌面端会停止注入它。

智能采纳

队列一次几十条时,「智能采纳」页可以把能自动定的先处理掉。只有控件技巧和入口路径可能被自动采纳,系统规则和其他类永远留给人,因为一条错的规则会让 Agent 以后一直绕开正确操作。

自动采纳有两条路:跨校观察够或单校观察够(证据硬);或者证据薄但模型读过内容后明确说可复用(这种只发回来源学校)。模型如果建议改写,就不会自动采纳原文,留给人确认,理由里直接给出改写建议。

先点「先看会动哪些」干跑,列出每条的处置和理由,确认后再执行。自动处理过的条目标记来源为 auto,队列里勾「只看自动处理的」可复查,审错了点「退回待审」就会推回各校。

自动驳回只是暂缓:那条知识再被观察到会退回队列重新排队。只有人工驳回是终局。这样机器误判一次不会永久吃掉一条知识。

实测 43 条队列,配了模型 Key 的情况下自动处理掉 21 条(19 采纳、2 驳回,两条驳回都是带任务编号的一次性链接),剩 22 条全是按策略必须人审的。

打包(Windows)

npm run package:win

依次执行:构建桌面端(esbuild + Vite → dist/)→ 用 .venv 的 PyInstaller 把后端冻结成 onedir(native/release/school-assistant-backend/,约 100 MB,脚本会跑一遍 --selfcheck 并在本机 PostgreSQL 可达时真起一次服务验收)→ electron-builder 产出 release/win-unpacked/SchoolAssistant.exe(整目录约 400 MB)。冻结后端放在 resources/backend,知识 YAML 放在 resources/knowledge。

运行安装包形态时,可写目录是 %APPDATA%\school-assistant\:首次启动会把 .env 模板复制过去,部署方在里面填模型 Key、PostgreSQL 连接、SCHOOL_ID、ACCOUNT_ENC_KEY;任务进度和登录态分别在其下的 data/、profiles/。目前只出免安装目录(dir),NSIS 安装器、图标、签名待做。

项目结构

school-assistant/
├── electron/          # Electron 主进程(TypeScript):窗口与 app:// 协议、WebContentsView 宿主、给后端的控制接口、后端进程管理、preload 桥
├── renderer/          # React + TypeScript + Vite 聊天界面(Sidebar / TopBar / Feed 卡片 / TaskCard / Composer / BrowserPanel / Settings)
├── dist/              # 构建产物(main.cjs、preload.cjs、renderer/、env.example),不入库
├── native/            # 打包中间产物:release/school-assistant-backend(PyInstaller onedir)、build/(smoke 结果、uv 引导),不入库
├── release/           # electron-builder 产出(win-unpacked/SchoolAssistant.exe),不入库
├── backend/           # FastAPI + 编排 + Browser Use(有 CDP_URL 时走内嵌模式,否则独立 Chrome);requirements.txt / requirements.lock
├── knowledge/         # 业务配置 YAML(系统、登录方式、步骤、规则、learned 沉淀)
├── data/              # 任务 progress.md、每步截图、评测结果(运行时生成)
├── docker-compose.yml # PostgreSQL 17(任务 / 知识 / learned / 密码本 / 设置)
├── profiles/          # 浏览器登录态(按 student_id 一份,登录一次长期有效)
├── server/            # 中心服务端(FastAPI):收各校草稿、审核队列、发布;独立库 school_assistant_hub
├── console/           # 后台审核台界面(React/TS/Vite),构建后由中心服务端直接伺候
├── shared/            # 桌面端与中心共用的规则(经验判重与归类)
├── tests/             # pytest 测试集(npm test);@pytest.mark.db 的用例需要 PostgreSQL
├── scripts/           # eval_run.py、打包与环境脚本
└── docs/PROGRESS.md   # 开发里程碑进度

进度文档

  • 开发进度:docs/PROGRESS.md
  • 任务进度:每个任务自动写入 data/tasks/{task_id}/progress.md

桌面端右侧可预览并「打开 progress.md」。

API 调试

后端 API 端口在 .env 的 API_PORT(默认 8788)。文档:http://127.0.0.1:8788/docs

# 单独启动后端
python backend/main.py

演示业务与探索发现

当前演示业务:辅导员工作日志填报(查课)和每周谈心谈话记录,同一入口下两个业务,由意图识别路由。谈心谈话示例:「帮我记一条谈心谈话,今天和计科2301班的李思涵聊了学业压力,内容是……」。说一句「帮我填今天的查课日志,班级计科2301班,听课记录还好」,助手会追问课程名称和授课教师,然后以辅导员身份进入「辅导员工作日志 → 日志填报 → 每月查课要求 → 新建填报」填表,逐项列出后等你确认再点「提交填报」。业务定义和探索沉淀都在 knowledge/xuegong_demo.yaml 的 businesses 与 learned 段。

学生端探索发现(2026-09-16)

测试环境学生端没有「留校申请」模块。门户 8 个一级模块:学生管理、综合测评、评奖评优、违纪处分、资助管理、请销假、节假日离返校、辅导员评议。最接近的是「节假日离返校 → 我的报备」(默认在校,离校才需报备)。学生端可提交的申请表单是「请销假 → 发起请假」,建议作为填表里程碑的目标。这些已沉淀在 knowledge/xuegong_demo.yaml 的 learned 段,运行时注入为「已知信息」。

测试学工系统

默认业务:knowledge/xuegong_demo.yaml
入口:https://school.miaopinai.com:29800/xuegong/

在聊天框输入办事目标即可,例如:

帮我填今天的查课日志,班级计科2301班,听课记录还好

下一步

见 docs/PROGRESS.md