💻 源码
# 金融文本大模型打标项目实战(讲师方案)

## 一、课程重新定位

本项目实战**不拆成两个独立项目**,也**不一开始就做复杂的前后端工程**。

课程主线改成两步走:

```text
第一步:用命令行跑通大模型,用提示词给测试数据打标。
第二步:做一个统一网页,学生点选任务、点选示例数据、对比提示词与结果。
```

让学生真正理解的核心链路:

- 提示词放在哪里、怎么改。
- 数据放在哪里、怎么换。
- 配置放在哪里、怎么调。
- 代码如何把数据交给大模型。
- 大模型如何根据提示词返回结果。
- 改提示词后,结果为什么变化。

## 二、三种打标任务

课堂统一用「打标」这个词,因为真实业务里常是给文本生成标签或结构化标注。

| 打标方式 | 输入 | 输出 | 学生要理解的重点 |
| --- | --- | --- | --- |
| 金融文本分类 | 一段金融文本 | 类别标签 `category` | 约束模型只能从固定标签里选 |
| 金融信息抽取 | 一段金融文本 | 实体 JSON | 约束模型按字段返回结构化结果 |
| 金融文本匹配 | 两段金融文本 | `is_match`、`score` | 约束匹配判断标准 |

## 三、推荐课堂节奏

| 阶段 | 时长 | 目标 | 学生产出 |
| --- | --- | --- | --- |
| 任务介绍 | 15 分钟 | 知道两种打标方式分别是什么 | 听讲师讲清楚链路 |
| 第一步:命令行打标 | 60 分钟 | 跑通代码、修改提示词、修改测试数据 | 命令行运行后得到清晰结果 |
| 提示词实验 | 35 分钟 | 观察提示词变化后的影响 | 一份提示词修改记录 |
| 第二步:统一网页 | 75 分钟 | 用网页模拟真实业务交互 | 一个可点选、可对比的网页 |
| 总结 | 15 分钟 | 总结真实开发链路 | 掌握大模型接口开发的基本链路 |

## 四、项目最终形态(标准 Python 项目结构)

最终课堂使用的是**一个统一项目**,遵循常见 Python 项目布局:

```text
financial-labeling-project/
  bootstrap.py          ← 自动切换工作目录(PyCharm 友好)
  config.yaml           ← 统一配置(模型、路径、输出格式)
  label.py              ← 命令行入口(第一步只跑这个)
  run_web.py            ← 网页入口(第二步)
  .run/                 ← PyCharm 运行配置(Run Web / Label Classify 等)
  requirements.txt
  README.md
  backend/              ← 核心业务代码包
    __init__.py
    config.py           ← 读取 config.yaml
    llm_client.py       ← 调用大模型
    label_service.py    ← 打标逻辑
    cli_output.py       ← 命令行清晰输出
    main.py             ← FastAPI 入口(第二步)
  prompts/              ← 学生主要改这里
  data/                 ← 学生主要改这里
  outputs/              ← 命令行 JSON 结果
  frontend/             ← 网页(第二步)
    index.html
    app.js
    style.css
```

学生需要重点知道的:

| 想做什么 | 去哪里改 |
| --- | --- |
| 改模型、温度、输出格式 | `config.yaml` |
| 改分类提示词 | `prompts/classify.txt` |
| 改抽取提示词 | `prompts/extract.txt` |
| 改匹配提示词 | `prompts/match.txt` |
| 改分类测试数据 | `data/classify_samples.json`(含 `expected_category`) |
| 改抽取测试数据 | `data/extract_samples.json`(含 `expected_result`) |
| 改匹配测试数据 | `data/match_samples.json`(含 `expected_is_match`) |
| 看命令行结果 | `outputs/` 文件夹 |
| 看网页交互效果 | PyCharm 选 **Run Web**,或 `python run_web.py` |

## 五、技术统一要求

所有代码统一调用 DashScope:

- API Key 从环境变量 `DASHSCOPE_API_KEY` 读取,**不写进 config.yaml**。
- 模型名、temperature、base_url 等写在 `config.yaml` 的 `llm` 段。
- 使用 OpenAI 兼容接口。
- 默认模型使用 `qwen-plus`。
- DashScope 地址使用 `https://dashscope.aliyuncs.com/compatible-mode/v1`。

## 六、命令行输出规范(重要)

**禁止**在终端直接 `print` 一大段嵌套 JSON 当作默认输出。

默认输出模式为 `summary`,每条样本单独分段,学生一眼能看懂:

```text
============================================================
金融文本打标结果 | 任务: classify | 共 3 条
============================================================

[1/3] c_easy_1 | 难度: 简单
输入: 某上市公司发布公告称,预计上半年净利润同比增长 40%。
标准: category = 公司公告
模型: category = 财报解读
对比: 错误
状态: 成功

[2/3] c_medium_1 | 难度: 中等
...

------------------------------------------------------------
汇总
------------------------------------------------------------
c_easy_1     简单   错误   标准=公司公告 | 模型=财报解读
c_medium_1   中等   正确   标准=市场行情 | 模型=市场行情
c_hard_1     困难   正确   标准=风险提示 | 模型=风险提示

完整 JSON 已保存到: outputs/classify_results.json
```

可通过 `config.yaml` 或命令行参数切换输出模式:

| 模式 | 说明 |
| --- | --- |
| `summary` | 默认,分段展示 + 末尾汇总表 |
| `json` | 调试用,输出完整 JSON |
| `quiet` | 只打印保存路径和成功/失败数量 |

## 七、课堂重点

本课堂的重点**不是页面多漂亮**,也**不是后端架构多复杂**。

重点是让学生理解这条链路:

```text
配置 + 数据 + 提示词 + 大模型接口 = 自动打标结果
```

学生只要能做到下面四件事,本课堂就是成功的:

1. 知道如何修改 `config.yaml` 中的模型参数。
2. 知道如何修改提示词。
3. 知道如何修改待打标数据。
4. 知道如何通过命令行或网页查看清晰、可对比的结果。

## 八、两步设计的教学原则

### 第一步:尽可能简单

- 只跑 `python label.py --task xxx`,不涉及网页。
- 学生只需理解 4 个位置:`config.yaml`、`prompts/`、`data/`、`outputs/`。
- 终端默认输出 `summary`,不要求学生读 raw JSON。

### 第二步:尽可能好用

- 默认使用**示例数据 + 点击选择**,减少手动输入。
- 提供**简单 / 中等 / 困难**三档难度;困难样本由 `backend/difficulty_validator.py` 程序校验,确保足够复杂。
- 页面左右分栏:**左边提示词、右边模型结果**,对比一目了然。
- 保留「自己输入」选项,供进阶学生自由测试。

### 提示词输出原则

当前阶段三类任务的模型输出**都不包含理由字段**:

- 分类:只返回 `category`
- 抽取:只返回 7 个中文字段(主体机构、时间周期、金额数值、财务指标、业务事件、风险因素、行业板块)
- 匹配:只返回 `is_match` 和 `score`

需要可解释性时,再在提示词中扩展 `reason` 字段。