Files
PromptCR-Lab/openspec/changes/init-promptcr-platform/design.md
T
2026-09-19 12:54:45 +08:00

72 lines
7.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Design: init-promptcr-platform
## Context
仓库当前为空。本设计为"面向代码审查的大语言模型实验支撑平台"(PromptCR-Lab)从零搭建的技术方案。平台服务单研究者毕业设计场景,核心负载是 3 模型 × N 级提示词 × 12 commit × 3 重复的全因子对照实验(N=3 时 324 个单元),要求全流程自动化、结果可复现、Docker 一键部署。
**硬约束**:Python 3.11 + FastAPI + Typer + SQLAlchemy + PostgreSQL + asyncio;前端 React 18 + Tailwind 3 + shadcn/ui + Vite + ECharts;基础设施仅允许 Docker / docker-compose / PostgreSQL / Nginx;密钥走环境变量;禁止重型多语言解析框架、禁止消息队列与 Redis。
## Goals / Non-Goals
**Goals:**
- 五模块(F1 数据集 / F2 模型适配 / F3 提示词 / F4 调度采集 / F5 分析)+ 接入层(F6)+ 前端(F7)的完整落地。
- 三条解耦红线:模型接入 ↔ 提示词策略解耦;实验执行 ↔ 结果评价解耦;数据生产 ↔ 数据消费解耦。
- 可复现性:采样参数随 run 持久化、重复实验独立 `run_id`、原始输出全量留痕、实验绑定模板版本且历史版本只读。
- 本地开发与 Docker 两种运行方式均可用;后端 pytest 覆盖率 ≥90%。
**Non-Goals:**
- 用户系统、多租户、移动端、SSR。
- 模型训练/微调、真实缺陷挖掘、缺陷自动修复。
- 任意语言即插即用(只覆盖数据集实际语言)、RAG 等重型提示词策略。
- 模型输出的模糊"猜测式"补救解析。
## Decisions
### D1 单体后端 + 分层模块,而非微服务
单个 FastAPI 进程内按 `dataset / models / prompts / experiments / analysis` 划分包,模块间只通过标准数据接口(DTO/服务层函数)交互,禁止跨模块读内部实现、接入层与前端禁止直连数据库。
- 备选:微服务/任务队列(Celery + Redis)——被约束显式排除;单机毕业设计场景无需此复杂度。
### D2 asyncio 进程内调度,数据库即队列
实验单元落库为 `experiment_runs`(status: pending/running/done/failed),调度器用 `asyncio.Semaphore` 按适配器并发额度取 pending 单元执行。**断点续跑 = 重启后扫描 pending/failed 可重试单元继续**,无需额外中间件。
- 备选:RQ/Celery——引入 Redis,违反约束。
### D3 三厂商统一 OpenAI 兼容适配器
抽象基类 `ModelAdapter.chat(prompt, params) -> {text, token_usage, latency_ms}`;DeepSeek/Kimi/通义均基于 openai SDK,仅 `base_url / api_key / model` 配置不同;工厂按模型标识创建。并发信号量与指数退避重试器封装在基类,对上层透明。
### D4 可插拔缺陷规则:目录扫描 + 注册表
规则按语言组织为独立文件(如 `backend/dataset/rules/python/null_pointer.py`),每条规则实现统一接口(`detect_and_mutate(source) -> Mutation | None`,返回植入位置/类型/参考修复),框架启动时扫描目录自动注册。**所有语言的规则一律基于语法解析做 AST 级变换,不使用正则/纯文本级替换**:Python 用标准库 `ast`;Java 用 `javalang`(纯 Python 轻量 Java 解析器);JavaScript 用 `esprima`(Python 移植版)。引入 `javalang`/`esprima` 属新增第三方依赖,按约束在代码注释与文档中说明理由(保证植入位置精确可知、缺陷语义真实)。若数据集后续纳入 TypeScript,再单独评估对应解析方案。仍禁止 tree-sitter / ANTLR 等重型多语言解析框架。新增规则文件即扩展,满足 A1b。
### D5 提示词模板版本化存储于数据库
`prompt_templates`(strategy_id, level)+ `prompt_template_versions`(version, body, variables_schema, created_at)。渲染走 `render(strategy_id, version, context)`;Web 编辑保存 = 插入新版本行,旧版本只读;`experiment_runs` 记录 `template_version_id` 保证 C1。
### D6 五维指标半自动计算
检出率/误报率/覆盖率:模型输出按约定结构(L2/L3 要求类型+行号)解析后与 Ground Truth 自动比对,解析失败标记失败并留原文(不猜测)。建议可操作性:前端录入李克特 1–5 分人工盲评结果,后端按"模型 × 级别"聚合均值+频数分布。稳定性:同一配置三次重复输出的指出项集合,两两(3 对)Jaccard 相似度取平均值。统计用 pandas + scipy(ANOVA、配对 t 检验);论文图用 matplotlib(中文字体、统一样式),前端图用同口径 JSON + ECharts。
### D7 前后端严格分离,Nginx 托管前端
前端 Vite SPA 构建产物由 Nginx 托管并反代 `/api` 到后端;API 只返回 JSON。本地开发:后端 `uvicorn` 一条命令、前端 `vite dev` 一条命令;Docker:`docker compose up` 拉起 db + backend + frontend(nginx),PG 数据挂 volume。
### D8 核心数据模型
- `samples`(commit 样本:repo、commit_sha、language、diff、上下文)
- `defects`(预埋缺陷:sample 外键、类型、位置行号、参考修复)→ 与样本共同构成 Ground Truth
- `prompt_templates` / `prompt_template_versions`
- `experiments`(批次配置快照:模型集合、级别集合、样本集合、重复次数、采样参数)
- `experiment_runs`(`run_id` 主键;外键关联实验、模型、模板版本、样本;重复序号、状态、重试次数、采样参数快照)
- `results`(与 `experiment_runs` 一对一:原始输出、token、耗时、解析出的指出项、五维指标得分、李克特人工分)
## Risks / Trade-offs
- [模型输出不按约定结构返回,自动比对失败率高] → L2/L3 模板中强约束输出格式;解析失败标记失败留原文(B3),并在分析中区分"解析失败"与"未检出"。
- [非 Python 语言的文本级缺陷变换可能产生不自然代码] → 规则内置语义校验(植入后位置精确可知、样本可编译性抽查);数据集仅 12 样本,允许人工抽检修正规则。
- [进程内调度在强杀后丢失 in-flight 状态] → run 状态先落库再执行;重启时将 running 但无结果的单元重置为 pending(B2)。
- [真实 API 调用有费用与限流] → CLI 提供 1×1×1×1 冒烟配置;重试器指数退避 + 单单元失败不中断批次(B1)。
- [单进程 asyncio 吞吐有限] → 可接受:实验总量数百单元,瓶颈在模型 API 而非本机。
## Migration Plan
全新项目,无迁移。首先初始化 Git 仓库(`.gitignore` 排除 `.env`、密钥、构建产物),按 M1–M7 里程碑推进(骨架 → F1 → F2/F3 → F4 → F5 → F7 → 测试/Docker/文档),每里程碑自验对应验收项,**验收通过后创建一个 Git commit 作为里程碑存档点**,再进入下一阶段。
## Open Questions
- 具体选用哪三个开源仓库(须覆盖 Python/Java/JS 且 commit 质量适合)——M2 启动时确定。
- ~~输出稳定性的具体一致性度量~~ **已确定**:同一配置三次重复实验的输出指出项集合,计算两两(共 3 对)Jaccard 相似度后取平均值,作为该配置的输出稳定性得分。