1. 项目概览与相互关系
| 项目 | 定位 | 形态 |
|---|---|---|
| lawsight-rsi | 独立"自我进化 RSI Agent"原型:Agent 执行专利/法律任务 → 自评估 → 自生成改进策略 → 沙盒验证 → 治理审批 → A/B 上线 | FastAPI + SQL(rsi.db) + Vue3,直连 GLM 与智慧芽专利检索 |
| lawsight-workdsh | 法律 AI 工作台(复刻 workdsh):左对话 + 右文件成果,具备资料库/专家/技能/项目/定时任务/MCP 外部服务 | FastAPI + SQL(lawsight.db) + Vue3;把 RSI 作为 app/rsi/ 子系统深度内嵌,工作台每次对话即进化数据源 |
两者关系:app/rsi/ 各文件 docstring 自述了移植差异——asyncio 化、沙盒移入子进程、A/B 修复为 challenger 不覆盖 champion、L1/L2 挂起策略不再预写配置、记忆多租户隔离、热配置默认值与主系统硬编码完全一致(进化未介入时零行为变化)。RSI 复用主系统全局 LLM 设置,无第二份 API Key(rsi/client.py:36-40)。
flowchart LR
subgraph RSI原型["lawsight-rsi(独立原型)"]
A1["core/rsi_loop.py<br/>四阶段循环"] --- A2["optimizers/ 7个优化器"]
A2 --- A3["governance 沙盒+审批"]
A1 --- A4["智慧芽专利 / GLM"]
end
subgraph 主系统["lawsight-workdsh(主系统)"]
B1["对话/分析任务引擎<br/>llm.py + workflow.py + harness.py"]
B2["app/rsi/ 子系统<br/>(源码级融入,异步化+加固)"]
B1 -- "task.end 钩子" --> B2
B2 -- "热配置反哺提示词/工具/工作流" --> B1
end
RSI原型 == "深度移植" ==> B2
2. 总体架构(lawsight-workdsh)
flowchart TB
subgraph FE["前端 Vue3(frontend/src,11 个视图)"]
V0["WorkbenchView 工作台<br/>左会话/中对话/右产物"]
V1["Library / Experts / Skills / Projects / Schedules"]
V2["McpView MCP服务"]
V3["RSI 三页:Dashboard / Evolution / Governance"]
V4["Settings(模型/语言/标题)"]
end
subgraph API["FastAPI 路由层(main.py 挂载 12 个 router)"]
R1["/api/sessions(chat=SSE)"]
R2["/api/tasks(run/stop=SSE,workflow 透视)"]
R3["/api/library /experts /skills /projects /schedules /artifacts /settings /harness"]
R4["/api/rsi/*(36 端点)"]
R5["/api/mcp/*(服务器 CRUD + 工具调用)"]
end
subgraph ENG["引擎层"]
E1["workflow.py 分析任务引擎<br/>轮次循环·检查点·停止/恢复·Token记账"]
E2["llm.py 提示词组装 + 工具执行<br/>5 内置工具 + SSE 解析"]
E3["harness.py Agent Harness<br/>工具注册表·权限·6钩子·压缩·记忆·重试"]
E4["scheduler.py 定时任务<br/>metrics.py Redis Stream"]
end
subgraph CAP["能力层"]
C1["artifacts.py 产物校验+导出<br/>(html/pptx/docx/xlsx)"]
C2["converters.py 8格式→Markdown"]
C3["skills.py SKILL.md 管理 + ZIP 导入"]
C5["mcp/ Streamable HTTP + STDIO 客户端<br/>工具以 mcp__server__tool 注入 harness"]
end
subgraph RSI["RSI 自我进化子系统(app/rsi/,15 模块)"]
S0["collector 轨迹采集(harness 钩子)"]
S1["evaluator 四维评估"]
S2["optimizers 6优化器+元优化器"]
S3["governance 沙盒/黑名单/审计<br/>executor 应用/回滚/A/B<br/>monitor 巡检熔断"]
S4["loop 循环编排 + events SSE 总线<br/>memory 四层记忆 + knowledge + feedback"]
end
subgraph DATA["数据层"]
D1[("store.py SQLite lawsight.db<br/>18 领域表 + 13 RSI 表 + mcp_servers")]
D2["data/ 技能库(82+) · 记忆文件 · 资料原件 · exports"]
D3["settings.json(6键白名单)"]
end
EXT["外部:GLM(OpenAI兼容) · Redis Stream · MCP 服务器(wk-mcp)"]
FE --> API --> ENG
ENG --> CAP
ENG --> RSI
E3 -- "工具注册表统一调度" --> C5
ENG --> DATA
RSI --> DATA
E1 -- "每轮 LLM 调用" --> EXT
C5 --> EXT
S0 -- "task.end" --> E3
启动装配(main.py:25-34 lifespan):seed_all() → scheduler.start() → rsi_loop.start()(种子配置+采集钩子+监控巡检)→ mcp_manager.start()(自动连接+30s 重连);关闭逆序。静态托管 frontend/dist,非 /api 404 回退 SPA(main.py:65-81)。
3. 核心设计一:对话即任务(统一执行路径)
"一轮对话 = 一个分析任务"(routers/sessions.py:171-193):chat 端点为每条用户消息 workflow.create_task 后 run_task 流式执行,普通聊天免费获得检查点/停止/恢复/Token 记账/RSI 轨迹采集;llm.stream_chat 仅剩定时任务路径使用。
sequenceDiagram
participant U as 用户(WorkbenchView)
participant S as POST /api/sessions/{id}/chat
participant W as workflow.run_task
participant H as harness
participant L as GLM(流式)
U->>S: 发送消息(/技能 专家 资料引用)
S->>W: create_task(每轮对话=1任务)
W-->>U: SSE: task(taskId)
loop 轮次(上限 max_rounds=12, RSI 可调)
W->>W: 停止检查 stop_requested
W->>H: compact_messages(预算压缩)
W->>L: 流式补全(with_retry×3)
L-->>U: SSE: reasoning / delta
W->>W: usage 记账 + Redis XADD wf:llm_tokens
W->>W: 落检查点(round/messages/pendingTools)
loop 每个工具调用
W->>H: execute_tool(权限→钩子→超时)
H-->>U: SSE: tool(running/done) / artifact
W->>W: 再落检查点
end
end
W-->>U: SSE: done(usage) + 落库助手消息
W->>H: emit("task.end") → RSI collector 采集
检查点/停止/恢复语义(workflow.py:209-587):
- checkpoint =
{round, messages[全量], assistantText, reasoning, thinkingMs, pendingToolCalls}(_checkpoint:277-281),每轮后与每个工具后写入。 POST /tasks/{id}/stop仅置stop_requested=1,引擎在安全点(轮开始/工具前后)以stopped收尾并保留 checkpoint;completed 清空。POST /tasks/{id}/run从 checkpoint 恢复:先执行 resume-tools 阶段补跑遗留pendingToolCalls,再续轮次;恢复偏移量保证只落库新增正文(:551-552)。- 客户端断开 →
stopped停在最近检查点(:546-547);前端气泡出现「已停止于检查点 rN,可恢复」芯片,点击续跑。
4. 核心设计二:Agent Harness(手、眼、记忆、安全边界)
harness.py(405 行)把引擎与能力边界解耦:
| 机制 | 设计 |
|---|---|
| 工具注册表 | Tool 数据类自描述 schema/权限(read·write·network)/超时/handler;内置 7 工具(4×save_*、http_request、read/write_memory);MCP 工具以 mcp__{server}__{tool} 动态注册进同一注册表(mcp/manager.py:238-273) |
| 六生命周期钩子 | task.start/end、round.start/end、tool.pre/post;RSI collector 挂在 task.end |
| 权限模式 | allow-all / readonly(禁 write+network);http_request 另受 RSI tool_policy.http_enabled + 主机黑名单(子域后缀匹配) |
| 跨会话记忆 | data/memory/{user}.md(20000 字上限),模型可用 read/write_memory 主动沉淀;RSI 将其增量同步为 long 层记忆 |
| 上下文预算压缩 | 默认 400k 字符(RSI 可调);超限时只压历史 role=tool 消息,保护最近 3 条完整工具结果,逐条截断留 2000 字 |
| 重试 | 指数退避 1s/2s/4s;CancelledError 直通(停止语义优先) |
系统提示词组装(llm.py:67-160):RSI 进化基础提示(SHA1(task_key)%2 确定性 A/B 分流)→ 专家人设(含技能依赖并入)→ 技能正文(8000 字上限)→ 资料库固定修订(≤12 条×24000 字)→ 项目指令 → 语言指令置末(近因效应)。所有限额都是 RSI context_policy 热配置旋钮。
5. 核心设计三:RSI 自进化闭环
5.1 数据采集闭环(Perform 层,持续发生)
flowchart LR
A["会话对话/定时任务"] --> B["analysis_tasks<br/>(trace+精确usage)"]
B -- "harness.emit(task.end)<br/>workflow.py:580" --> C["rsi/collector._on_task_end"]
C --> D["rsi_trajectories 轨迹<br/>(steps/A-B变体/tokens)"]
C --> E["L2隐式+L3结果反馈"]
C --> F["knowledge 知识萃取"]
C --> G["memory.sync_user_memory<br/>文件→long层"]
C --> H["异步 L4 评审(LLM 1-5分<br/>+插件融合调整)"]
C --> I["loop.on_task_finished()<br/>计数≥8 且 autonomy≥2"]
I --> J["run_cycle(auto_after_tasks)"]
U["用户 👍/👎"] --> K["feedback.submit_l1(L1)"]
K --> F
H --> D
stopped 任务不计反馈(可恢复,collector.py:208-210);L4 评审用任务画像(状态/延迟/tokens/轮次/工具成功率/产物)打分,高分轨迹自动沉淀长期记忆。
5.2 进化循环四阶段(rsi/loop.py:31-144,单实例互斥)
flowchart TB
START(["run_cycle(trigger)"]) --> P0{"monitor.is_paused()?<br/>熔断检查"}
P0 -- 是 --> FAIL(["status=failed 熔断拒跑"])
P0 -- 否 --> E1["② Evaluate<br/>evaluator.evaluate()<br/>规则阈值+LLM机会识别<br/>→ rsi_evaluations"]
E1 --> M0["③ Modify<br/>budget=40000-token已用"]
M0 --> M1["generate_strategies<br/>元优化器按可信度选top4<br/>6优化器生成 Strategy"]
M1 --> M2{"governance.check_strategy<br/>14条危险正则+受保护目标"}
M2 -- 拦截 --> BLK["blocked"]
M2 --> M3{"executor.validate_strategy<br/>沙盒验证→sandbox_score"}
M3 -- "score=0" --> BLK2["淘汰"]
M3 --> M4["meta select_best<br/>rank=gain×sandbox×trust<br/>×cost_penalty+roi/1000"]
M4 --> M5{"ROI≥0.5 或零成本?"}
M5 -- 否 --> SKIP["仅存档"]
M5 -- 是 --> M6{"autonomy≥3<br/>或人工批准?"}
M6 -- 是 --> M7["apply_strategy<br/>快照旧值→写热配置/A-B挑战者/插件"]
M6 -- 否 --> M8["pending_approval<br/>不写任何配置(修复点)"]
M7 --> R1["④ Redeploy<br/>settle_ab_test 裁决<br/>monitor.check_once 巡检"]
R1 --> DONE(["cycle completed<br/>report落库+SSE"])
5.3 七类优化器(rsi/optimizers.py)
| 优化器 | kind | 优化对象 | 生成方式 | 沙盒分 |
|---|---|---|---|---|
| PromptOptimizer | prompt_variant | base_system_prompt | LLM 遗传变异 + 历史有效策略元提示 | 0.8 |
| ContextOptimizer | context_param | context_policy 旋钮 | 规则收紧 + LLM 参数学习 | 0.9 |
| ToolOptimizer | tool_param | tool_policy | 近 100 轨迹工具统计(成功率/耗时)驱动 | 0.9 |
| MemoryOptimizer | memory_param | 记忆策略 | 遗忘阈值/迁移门槛调整 | 0.9 |
| WorkflowOptimizer | workflow_param | workflow_policy | 错误率收紧轮次 + ε-greedy(30%) 探索 | 0.9 |
| CodeOptimizer | code_plugin | 评审融合插件 | LLM 写 optimize(results) 纯函数+自测用例,生成期即过子进程沙盒 |
1.0/0.0 |
| 元优化器 | — | 调度+选优 | Laplace 平滑胜率×收益 排序 | — |
5.4 策略生命周期与治理纵深
stateDiagram-v2
[*] --> generated: 优化器生成
generated --> blocked: 危险模式/受保护目标
generated --> validated: 沙盒通过(sandbox_score>0)
validated --> skipped: 未入选/ROI不足
validated --> pending_approval: autonomy L1/L2
validated --> applied: autonomy L3/L4 自动应用
pending_approval --> applied: 人工批准(actor=human)
pending_approval --> rejected: 人工驳回
applied --> kept: A/B challenger 胜出转正
applied --> rolled_back: A/B 落败 / 监控熔断自动回滚 / 人工回滚
kept --> [*]
rolled_back --> [*]
七层安全纵深(每条策略必经):
① 14 条危险正则黑名单 → ② 受保护模块前缀(governance/loop/executor/store…)→ ③ CONFIG_SCHEMA 键与字段范围白名单(如 max_rounds 4-20、提示 30-4000 字)→ ④ 子进程 AST 沙盒(节点白名单+受限 builtins+回归用例+8s 硬超时杀进程)→ ⑤ 自主级别门控(L1 观察/L2 建议/L3 自动应用/L4 全自主,may_auto_apply≥3)→ ⑥ pending_approval 人工审批(未批准不写任何运行时配置)→ ⑦ 监控熔断(30 分钟窗错误率>0.3 → critical 告警 + L3/L4 自动回滚最近 applied + 暂停进化,人工 resume)。全链路 rsi_audit_logs 留痕。
5.5 A/B 测试与热配置反哺
- 分流:
SHA1(task_key) 前8位 % 2确定性分臂(rsi/config.py:177-190),champion 保持原文,challenger 为进化提示。 - 裁决:总样本≥6 且两臂各≥4 条 L4 评审,challenger 均分高出 0.05 才转正;否则回滚(
optimizers.judge_ab_test+executor.settle_ab_test)。 - 反哺点(进化结果 → 下一次对话立即生效):
llm.py:72-75基础提示/A-B;llm.py:61-65上下文限额;llm.py:314-321HTTP 超时;workflow.py:27-53轮次/历史/记忆检索注入;harness.py:191-201工具开关+统一超时(应用策略后executor._refresh_tool_timeouts即时刷新)。
6. 支撑子系统速览
| 子系统 | 关键设计 |
|---|---|
| 资料库 library | 树形目录 + 不可变修订(original + content.md + conversion.json/sha256);导入 8 格式自动转 Markdown;全文检索标题 2 分/正文 1 分;固定修订注入会话保证可复现;草稿发布双乐观锁(draft revision + base revision 双 409) |
| 专家 experts | 草稿/发布修订分离(definition JSON 六字段校验),发布后注入会话人设,技能依赖自动并入 |
| 技能 skills | SKILL.md frontmatter 解析、启停、目录/WorkBuddy ZIP 导入;种子 5 内置 + 法律技能仓库 82 个 |
| 项目 projects | 指令注入任务、看板工作项(5 状态)、资料挂接、会话任务链接 |
| 定时 schedules | interval_minutes / daily_time 两种,asyncio 30s 扫描 + 手动队列优先,运行留痕到独立会话 |
| 产物 artifacts | state 模型防御性钳制(条数/字数/行列上限)→ 前端四种预览器 → python-pptx/docx/openpyxl 真实导出,校验-预览-导出同源 |
| 指标 metrics | 每轮 LLM 调用 XADD wf:llm_tokens(9 字段),MAXLEN 裁剪,Redis 不可用静默降级;usage 精确值优先、CJK 感知估算兜底 |
| MCP mcp/ | 零 SDK 自研双传输客户端(Streamable HTTP 会话头捕获 + STDIO 行协议);Token ${VAR} 引 .env 不落库、界面掩码;工具注入 harness 后自动获得权限/钩子/超时/轨迹采集 |
数据模型(SQL,31+ 表,节选)
erDiagram
sessions ||--o{ messages : "消息"
sessions }o--|| experts : "专家人设"
sessions }o--o| projects : "所属项目"
sessions ||--o{ library_refs : "固定修订引用"
sessions ||--o{ artifacts : "文件成果"
analysis_tasks }o--|| sessions : "一轮对话=一任务"
analysis_tasks ||--o{ rsi_trajectories : "task.end采集"
library_assets ||--o{ library_revisions : "不可变修订"
library_assets ||--o{ library_drafts : "乐观锁草稿"
experts ||--o{ expert_revisions : "发布修订"
projects ||--o{ project_work_items : "看板"
schedules ||--o{ schedule_runs : "运行记录"
rsi_trajectories ||--o{ rsi_feedback : "L1-L4反馈"
rsi_cycles ||--o{ rsi_strategies : "策略"
rsi_cycles ||--o| rsi_evaluations : "评估"
mcp_servers ||--o{ harness_tools : "mcp__前缀注册"