# hangzhou_q8_tmf **Repository Path**: Gitee_Program_Lee/hangzhou_q8_tmf ## Basic Information - **Project Name**: hangzhou_q8_tmf - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 109 - **Created**: 2026-09-14 - **Last Updated**: 2026-09-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 投满分 · 今日头条短文本多分类项目 > 面向今日头条推荐场景的短文本自动分类项目(把新闻 / 资讯短文本自动分到对应频道,再“投递”进各自的推荐流)。 --- ## 一、项目背景 字节跳动旗下产品线众多,其中**抖音**与**今日头条**是最大的两张王牌,分别代表"基于短视频的推荐"与"基于短文本的推荐",背后融合了 CV、NLP、推荐系统、大数据等多个领域的技术。以今日头条为例:用户在大量资讯中,必然对某些类别更感兴趣(如男生的历史、军事、足球;女生的财经、八卦、美妆)。如果能主动把用户更感兴趣的类别筛选出来并做推荐阅读,点击量、订阅量、付费量都会明显增长。因此,在今日头条 App 的推荐系统模块中,需要内嵌一个子任务:**将短文本自动多分类,并像"投递"一样把内容送到对应的"频道 / 推荐流"中**。"投满分"项目正是这一功能子集——它只负责完成新闻、资讯等短文本的多分类。 ## 二、功能概述 本项目采用经典的 **离线训练 + 在线推理** 分离架构: - **离线侧**:对原始语料做清洗、预处理,训练文本分类模型并导出产物。 - **在线侧**:以 Flask 提供 HTTP 服务,接收短文本,返回其所属频道类别。 | 环节 | 入口 | 说明 | | --- | --- | --- | | 离线训练流水线 | `run_pipeline.py` | 编排 数据准备 → 训练导出 → 模型评估 | | 在线推理服务 | `wsgi.py` | Flask 应用启动入口(应用工厂) | | 分类接口 | `POST /api/v1/classify` | 短文本 → 类别(当前为占位实现) | ## 三、技术栈 - **语言**:Python 3.12 - **离线建模**:jieba(分词)、scikit-learn(特征 + 分类模型)、joblib(模型持久化)、pandas / numpy(数据处理) - **在线服务**:Flask + flask-cors(应用工厂模式 + 蓝图 + 版本化路由) - **数据处理**:tqdm(进度)、jieba 自定义停用词 ## 四、数据集 数据为今日头条渠道的新闻标题(短文本)语料,位于 `data/raw/` 下,`\t` 分隔,一行一条: ``` 标题文本\t类别编号 ``` | 文件 | 行数 | 用途 | | --- | --- | --- | | `data/raw/tmf_train.txt` | 180,000 | 训练集 | | `data/raw/tmf_valid.txt` | 10,000 | 验证集 | | `data/raw/tmf_test.txt` | 10,000 | 测试集 | - 类别共 10 个,清单见 `data/tmf_class.txt`(finance / realty / stocks / education / science / society / politics / sports / game / entertainment)。 - 类别编号为整数,与 `data/tmf_class.txt` 中类别顺序对应。 - 停用词表:`data/stopwords.txt`。 ## 五、目录结构 ``` hangzhou_q8_tmf/ ├── run_pipeline.py # 离线训练流水线入口(编排 Step1~3) ├── wsgi.py # Web 服务启动入口(gunicorn 可挂载 wsgi:app) ├── requirements.txt # Python 依赖 ├── Dockerfile # 后端镜像构建(仅打包 app/ 与 wsgi.py) ├── docker-compose.yml # 编排 app + nginx 两个服务 ├── training/ # —— 离线模型侧 —— │ ├── __init__.py │ ├── config.py # 训练侧配置(路径、超参,dataclass) │ ├── data_eda.py # 探索性数据分析(EDA) │ ├── data_clean.py # 数据清洗 │ ├── model_train.py # 特征工程 + 模型训练与导出 │ ├── model_eval.py # 模型评估 │ └── utils.py # 通用工具 ├── app/ # —— 在线服务侧(Flask)—— │ ├── __init__.py # 应用工厂 create_app():配置加载/蓝图注册/全局钩子 │ ├── config.py # Web 配置(dev / prod / test 环境映射) │ ├── extensions.py # 自定义 Flask 扩展 │ └── v1/ │ └── prediction.py # 分类接口蓝图(blueprint,url_prefix=/api/v1) ├── front/ # —— 前端(Vue 3 + Vite)—— │ ├── src/ # 前端源码(组件 / API 封装 / 常量) │ ├── dist/ # 构建产物(已 gitignore,由 Nginx 挂载服务) │ └── package.json # 前端依赖与构建脚本 ├── nginx/ │ └── nginx.conf # 站点入口:服务静态页 + 将 /api/ 反代到后端 ├── prompts/ # 提示词模板 ├── data/ │ ├── raw/ # 原始语料(训练/验证/测试) │ ├── pre/ # 预处理后产物 │ ├── stopwords.txt # 停用词 │ └── tmf_class.txt # 类别清单 ├── model/ # 训练产物(模型文件,已 gitignore) ├── logs/ # 日志目录 └── tests/ # 测试目录 ``` ## 六、安装与运行 ```bash # 1. 准备 Python 3.12 环境 conda create -n tmf_venv python=3.12 conda activate tmf_venv # 2. 安装依赖 pip install -r requirements.txt ``` ## 七、使用说明 ### 1. 离线训练流水线 ```bash python run_pipeline.py ``` 流水线规划了三个步骤: 1. **数据清洗与准备**(对应 `training/data_eda.py` + `training/data_pre.py`); 2. **训练并导出分类模型**(对应 `training/model_train.py`,产物写往 `model/text-clf-model.pkl`); 3. **模型评估**(对应 `training/model_eval.py`)。 ### 2. 启动在线服务(开发模式) ```bash python wsgi.py # 默认 127.0.0.1:8000 ``` 调用分类接口(占位实现): ```bash curl http://127.0.0.1:8000/api/v1/classify ``` **生产部署参考**(务必置于 Nginx 等反向代理之后): ```bash gunicorn -w 4 -b 0.0.0.0:8000 -t 120 wsgi:app ``` > 若模型加载耗时较长,可通过 `-t` 提高 gunicorn 超时,或在应用内做延迟加载。 ### 3. 容器化部署(Docker Compose) > **前置步骤:必须先构建前端,再启动容器。** > > `front/dist/` 已被 `.gitignore` 忽略(不随仓库分发),但 `docker-compose.yml` 会把它挂载进 Nginx 容器:`./front/dist:/usr/share/nginx/html:ro`。全新 clone 后若跳过构建,Nginx 的站点根目录是空的,访问首页只会得到 404。 > > 这一步只能在宿主机完成:根目录 `Dockerfile` 仅构建后端(只 `COPY app/` 与 `wsgi.py`),镜像内没有 Node 环境,前端无法在容器中构建。 ```bash # 1. 构建前端静态产物(宿主机需已安装 Node.js) cd front && npm install && npm run build && cd .. # 2. 确保 .env 存在(该文件已在 .gitignore 中,缺失会导致 compose 启动失败) vim .env # 3. 构建后端镜像并启动全部服务 docker compose up -d --build ``` 编排关系: | 服务 | 角色 | 端口 | | --- | --- | --- | | `nginx` | 站点入口:服务 `front/dist` 静态页,并将 `/api/` 反向代理到后端 | `80`(对外暴露) | | `app` | Flask 服务(gunicorn),仅容器内网可达 | `8000`(`expose`,不对外) | - Nginx 依赖后端健康后才启动(`depends_on: condition: service_healthy`),因此后端模型加载慢不会导致 502。 - `./model` 以只读方式挂载到容器 `/app/model`,宿主机上需已备好模型产物,容器不会自行下载。 启动后入口为 ;接口经 Nginx 转发,例如 `http://localhost/api/v1/classify`。 ## 八、开发状态(现状与规划) 当前为**脚手架阶段**,目录与架构已按企业级规范搭建,业务逻辑仍在实现中: | 模块 | 状态 | | --- | --- | | `training/*` 训练管线模块 | 骨架已建,待填充实现 | | `app/v1/prediction.py` 分类接口 | 占位实现,待接入真实模型 | | 环境配置加载 / 鉴权 / 数据库等扩展 | 规划中(应用工厂已预留钩子) | | 测试(`tests/`)、README | 持续补充 | ## 九、配置说明 - **训练侧配置**:`training/config.py` 中的 `Config`(路径、超参)。 - **服务侧配置**:`app/config.py` 中的 `config_map`,按环境区分 `development` / `production` / `test`;`SECRET_KEY`、`DATABASE_URL` 等敏感项通过环境变量注入(生产环境禁止使用代码中的兜底默认值)。 ---