💻 源码
# 第二步:统一网页打标

## 一、第二步要达到什么

第二步在第一步命令行跑通的基础上,做一个**统一点选式网页**。

页面让学生可以:

1. **点击**选择打标方式(分类 / 抽取 / 匹配)
2. **点击**选择数据来源(示例数据 / 自己输入)
3. **点击**选择难度(简单 / 中等 / 困难)
4. **点击**选择一条示例,自动填入待打标内容
5. **点击**「开始打标」,调用后端
6. **左右对比**查看提示词与模型返回结果

第一步的命令行能力不变;第二步只是把同一套逻辑做成更好用的交互界面。

```text
前端点选数据
后端读取提示词
后端调用大模型
模型返回结果
前端左右对比展示
```

## 二、页面设计原则

| 原则 | 说明 |
| --- | --- |
| 默认点选,少打字 | 默认「使用示例数据」,学生点难度、点卡片即可 |
| 对比要明显 | 左栏提示词(蓝灰底)、右栏模型结果(绿灰底),标题和边框颜色区分 |
| 一步完成打标 | 选好示例后,点一次「开始打标」即可 |
| 保留自由输入 | 进阶学生可切换到「自己输入」模式 |

## 三、统一页面布局

页面只有一个主界面,从上到下分 4 个区域:

### 区域 1:任务选择(卡片式,点击切换)

- 金融文本分类
- 金融信息抽取
- 金融文本匹配

### 区域 2:数据来源(切换按钮)

| 模式 | 交互 |
| --- | --- |
| 使用示例数据(默认) | 显示难度按钮 + 示例卡片列表,点击卡片即选中 |
| 自己输入 | 显示文本框,供自由输入 |

### 区域 3:待打标内容预览

选中示例或输入文本后,在显眼位置展示当前待打标内容,避免学生搞不清正在测哪条数据。

### 区域 4:左右对比区

| 左栏 | 右栏 |
| --- | --- |
| 当前提示词(只读展示) | 模型返回结果(格式化 JSON) |
| 蓝色系标题和边框 | 绿色系标题和边框 |

底部居中放一个大按钮:**开始打标**。

## 四、示例数据交互(重点)

### 难度选择

每个任务在 `data/` 中已准备 3 条数据:

- `easy`:简单,适合验证流程
- `medium`:中等,适合测试提示词
- `hard`:困难,适合观察边界情况

页面上用三个按钮切换难度,只显示当前难度下的示例卡片。

### 示例卡片

每张卡片显示:

- 样本 ID
- 文本摘要(匹配任务显示 A / B 两段摘要)
- 难度标签

点击卡片即选中,卡片高亮,并自动更新「待打标内容预览」。

**不需要学生手动输入任何内容。**

### 生成测试数据(新增)

在「使用示例数据」模式下,难度按钮旁增加:

```text
生成当前难度测试数据
```

点击后调用 `POST /generate-sample`,由大模型生成 1 条带标准答案的新样本,并自动加入当前列表顶部。

难度设计必须能真正区分:

| 难度 | 生成要求 |
| --- | --- |
| 简单 | 意图明显,标准答案一眼可验证 |
| 中等 | 多个信息点,需要读完整句 |
| 困难 | 多重歧义/指代/条件嵌套;**程序校验**拒绝过短、过简单的样本 |

困难样本具体标准(生成器会自动校验,不合格则重试):

| 任务 | 困难样本必须满足 |
| --- | --- |
| 分类 | ≥60 字;含转折(但/然而/同时);至少 2 类表面信号词 |
| 抽取 | ≥80 字;≥5 个字段非空;主体用指代;含条件推测(若/可能) |
| 匹配 | 每段 ≥45 字;高度相关但难判断(如回购 vs 减持) |

生成的样本带 `AI生成` 标记,可立即用于打标和对比。

生成过程状态(按钮旁状态芯片):

| 状态 | 含义 |
| --- | --- |
| 待生成 | 初始状态,可点击生成 |
| 生成中... | 正在调用大模型,按钮禁用 |
| 已生成 | 成功,新样本已加入列表顶部 |
| 生成失败 | 失败,提示区会显示具体原因 |

### 生成测试数据常见问题

| 现象 | 原因 | 解决办法 |
| --- | --- | --- |
| 点击后完全没反应 | 前端 JS 报错(如 `app.js` 语法错误) | 浏览器 F12 看 Console;Ctrl+F5 强制刷新 |
| 一直显示「生成中...」 | 大模型 API 慢或未返回 | 等待 90s;检查 `DASHSCOPE_API_KEY` 和网络 |
| 状态变为「生成失败」 | API Key 未设置、JSON 校验失败等 | 看提示区错误详情;检查 `config.yaml` 中 `generator` 段 |
| 后端报 `No module named 'backend'` | 用 PyCharm 打开 `financial-labeling-project`;或运行 `run_web.py` / `label.py` |

`config.yaml` 中可调整生成超时与重试:

```yaml
generator:
  model: qwen-plus
  temperature: 0.85
  timeout_seconds: 90
  max_retries: 3
  hard_temperature: 0.95      # 困难样本更高随机性
  hard_max_retries: 5         # 困难样本更多重试
  hard_timeout_seconds: 120
```

## 五、自己输入模式(可选)

切换到「自己输入」后:

- 分类 / 抽取:显示一个文本框
- 匹配:显示文本 A、文本 B 两个文本框

此模式供学生测试自定义句子,课堂默认不强制使用。

## 六、配置与后端共用

网页后端与命令行**共用同一套配置和业务代码**:

```text
config.yaml          → backend/config.py 读取
backend/label_service.py  → 打标逻辑
backend/llm_client.py     → 模型调用(参数来自 config.yaml)
```

改模型名、temperature 时,只改 `config.yaml`,命令行和网页同时生效。

### 启动网页

**PyCharm 推荐**:右上角选 **Run Web**,或右键 `run_web.py` → Run。

命令行 / README 一键运行:

```bash
python run_web.py
```

`bootstrap.py` 会自动切换工作目录,通常不需要再 `cd financial-labeling-project`。

网页返回结果也应**精简展示**:右栏默认只显示 `result` 核心字段,不把 `raw_output` 重复堆给学生看;解析失败时才显示错误和原始返回。

## 七、后端接口设计

### 主要接口

```text
POST /label
```

请求体示例(分类):

```json
{
  "task": "classify",
  "text": "某上市公司发布公告称,预计上半年净利润同比增长 40%。"
}
```

### 辅助接口

```text
GET /prompt/{task}
```

作用:切换任务时,左栏展示对应提示词。

```text
GET /samples/{task}?difficulty=easy
```

作用:获取示例数据列表;`difficulty` 可选 `easy`、`medium`、`hard`,不传则返回全部。

## 八、讲师演示顺序

1. 打开网页,默认选「金融文本分类」
2. 保持「使用示例数据」,点「简单」难度
3. 点第一条示例卡片,展示待打标内容
4. 点「开始打标」,看左右对比结果
5. 不改数据,切换到「困难」难度,再打一标,对比结果差异
6. 打开 `prompts/classify.txt`,删掉「只能从给定类别中选择」
7. 回到网页,对同一条数据重新打标,观察右栏变化
8. 切换到「金融信息抽取」,演示 7 个中文字段(主体机构、财务指标等)如何被约束
9. 切换到「金融文本匹配」,强调判断标准写法的影响

这样学生能直观看到:**同一数据 + 不同提示词 = 不同结果**。

## 九、给 AI 编程工具的生成计划(可直接复制)

```text
请帮我开发一个「金融文本统一网页打标」项目,要求标准 Python 结构、配置可控、页面美观、默认点选操作。

一、项目目标
做一个统一网页,学生可以点选三种金融文本打标方式:
1. 金融文本分类
2. 金融文本信息抽取
3. 金融文本匹配

二、项目结构
financial-labeling-project/
  config.yaml
  label.py
  backend/(config.py、llm_client.py、label_service.py、cli_output.py、main.py)
  prompts/、data/、outputs/、frontend/

三、技术要求
1. config.yaml 统一管理 model、temperature、base_url、paths、cli 输出模式
2. API Key 从环境变量 DASHSCOPE_API_KEY 读取
3. 命令行与网页共用 label_service.py
4. 命令行默认 summary 输出,网页右栏只展示 result 核心字段

四、前端页面要求
1. 卡片切换任务;默认示例数据 + 难度按钮 + 可点击卡片
2. 左右分栏:蓝=提示词,绿=结果
3. 支持自己输入模式

五、后端接口
POST /label、GET /prompt/{task}、GET /samples/{task}

请生成完整可运行代码。
```

## 十、验收标准

- 学生不输入任何文字,只靠点击就能完成一次打标
- 左栏提示词、右栏结果一眼能区分
- 切换难度后,待打标内容跟着变化
- 修改 `prompts/` 后刷新网页,再打同一示例,结果有明显变化