实战项目二:自动摘要生成器

目录


项目概述

自动摘要生成是 NLP 最常落地的场景之一——从一篇长文档中提炼出关键信息,生成简洁、准确的内容。这个项目会同时照顾“经典算法的速度”和“大模型的质量”,让你能直接构建可上线的摘要服务。

快速了解我们的目标

用一段 Python 字典把项目的三个维度一次性说清楚:

objectives = {
    "技术": ["TextRank/BERT抽取", "T5/BART/GPT生成", "ROUGE评估", "FastAPI服务"],
    "性能": ["ROUGE-1 > 0.4", "单条响应 < 2秒", "摘要占原文10%~20%"],
    "业务": ["多风格(简洁/技术)", "多长度(100~5000字)", "批量处理"]
}

从抽取到生成,再到评估和上线,下面的内容会帮你一步步走完。


摘要技术分类

抽取式 vs 生成式:2026 年场景选择指南

不用在这个问题上反复纠结,一张表格就能帮你快速决策:

对比维度抽取式(TextRank/BERT)生成式(T5/GPT)
词汇来源100% 来自原文,零幻觉可改写压缩,偶尔出现不准确内容
处理速度很快(<0.5秒/条)较慢(0.5~2秒/条,GPT 更长)
适用场景短新闻、实时需求、规则型文档长文本、技术润色、质量优先场景

简单总结:要快就用抽取式,要精致就用生成式

极简技术发展脉络

不用记一堆论文,记住这三个关键节点就够:

  1. 经典阶段(2004年前):基于词频和 PageRank 变体,速度快但理解不了语义。
  2. 预训练阶段(2017‑2021):Transformer 出现,BERT、T5、BART 让摘要质量大幅提升。
  3. 大模型阶段(2022至今):GPT 系列登场,可以直接理解复杂文本并生成流畅的摘要。

核心实现:抽取式→生成式→评估

1. 抽取式:10 分钟跑通 TextRank(无需大模型)

TextRank 是上手最快、成本最低的方案,特别适合对实时性要求高、规则明确的场景。

import numpy as np
import jieba
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.feature_extraction.text import TfidfVectorizer

class TextRank:
    def __init__(self, top_k=3):
        self.top_k = top_k
        self.damping = 0.85
        self.max_iter = 100
        self.tol = 1e-5

    def _split_sent(self, text):
        sents = []
        for s in text.replace('!', '。').replace('?', '。').split('。'):
            s = s.strip()
            if len(s) > 10:
                sents.append(s)
        return sents

    def _build_sim_mat(self, sents):
        # 用 jieba 分词构造 TF‑IDF 并计算句子相似度
        tfidf = TfidfVectorizer(tokenizer=jieba.lcut, token_pattern=None)
        tfidf_mat = tfidf.fit_transform(sents)
        sim_mat = cosine_similarity(tfidf_mat)
        np.fill_diagonal(sim_mat, 0)
        # 归一化
        row_sum = sim_mat.sum(axis=1, keepdims=True)
        row_sum[row_sum == 0] = 1
        return sim_mat / row_sum

    def summarize(self, text):
        sents = self._split_sent(text)
        if len(sents) <= self.top_k:
            return '。'.join(sents) + '。'

        sim_mat = self._build_sim_mat(sents)
        scores = np.ones(len(sents)) / len(sents)

        # PageRank 迭代
        for _ in range(self.max_iter):
            new_scores = (1 - self.damping)/len(sents) + self.damping * sim_mat.T.dot(scores)
            if abs(new_scores - scores).sum() < self.tol:
                break
            scores = new_scores

        # 按原文顺序选出 top‑k 句
        top_idx = np.argsort(scores)[-self.top_k:][::-1]
        top_idx.sort()
        return '。'.join([sents[i] for i in top_idx]) + '。'


# 测试一下
text = (
    "自然语言处理是AI的重要分支,研究人机语言交互。"
    "包含语音识别、文本分类、机器翻译等任务。"
    "近年来大模型取得突破,BERT和GPT是代表,ChatGPT在对话中表现出色。"
)
print(TextRank().summarize(text))

2. 评估指标:ROUGE 的简化使用

用现成的 py-rouge 库,三行代码就能完成核心评估:

# 安装:pip install py-rouge
from rouge import Rouge

def eval_summary(candidate, reference):
    """简化版 ROUGE 评估,直接返回 F1 值"""
    rouge = Rouge()
    scores = rouge.get_scores(candidate, reference)[0]
    return {
        "ROUGE-1-F1": round(scores['rouge-1']['f'], 4),
        "ROUGE-2-F1": round(scores['rouge-2']['f'], 4),
        "ROUGE-L-F1": round(scores['rouge-l']['f'], 4)
    }

# 测试
print(eval_summary(
    "NLP是AI重要分支,大模型近年突破",
    "自然语言处理是人工智能重要分支,近年大模型取得突破性进展"
))

3. 生成式:5 分钟跑通 T5(开源可控)

T5 是经典的“文本到文本”统一框架,可以灵活调整摘要风格,成本也远低于 GPT。

# 安装:pip install transformers torch
from transformers import T5Tokenizer, T5ForConditionalGeneration
import torch

class T5Summary:
    def __init__(self):
        self.model_name = "t5-small"  # 入门用 t5‑small,效果要求高可换 t5‑base 或中文 mT5
        self.tokenizer = T5Tokenizer.from_pretrained(self.model_name)
        self.model = T5ForConditionalGeneration.from_pretrained(self.model_name)
        self.device = "cuda" if torch.cuda.is_available() else "cpu"
        self.model.to(self.device)

    def summarize(self, text, max_len=100, min_len=30):
        # T5 需要加上前缀:summarize:
        input_text = "summarize: " + text
        inputs = self.tokenizer(
            input_text, return_tensors="pt", truncation=True, max_length=512
        ).to(self.device)

        with torch.no_grad():
            outputs = self.model.generate(
                **inputs,
                max_length=max_len,
                min_length=min_len,
                num_beams=4,               # 束搜索,比随机采样更稳定
                no_repeat_ngram_size=2     # 防止重复短语
            )
        return self.tokenizer.decode(outputs[0], skip_special_tokens=True)


# 测试
print(T5Summary().summarize(text))

模型融合与部署

混合策略:兼顾速度与质量

实际生产中最推荐的做法是:先用 TextRank 抽出 top‑5 关键句,再用 T5/mT5 润色,这样速度和效果都能兼顾。

class HybridSummary:
    def __init__(self):
        self.extract = TextRank(top_k=5)
        self.generate = T5Summary()

    def summarize(self, text, short_threshold=500):
        if len(text) < short_threshold:
            # 短文本直接抽取
            return self.extract.summarize(text)
        else:
            # 长文本抽取后再生成式润色
            extracted = self.extract.summarize(text)
            return self.generate.summarize(extracted)

FastAPI 一键部署

把上面的混合模型包装成 API,配合 Docker 就可以快速上线:

# app.py
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI(title="自动摘要 API", version="1.0")
hybrid = HybridSummary()

class SummaryReq(BaseModel):
    text: str
    short_threshold: int = 500

@app.post("/summary")
async def get_summary(req: SummaryReq):
    return {"summary": hybrid.summarize(req.text, req.short_threshold)}

# 启动命令:uvicorn app:app --host 0.0.0.0 --port 8000 --reload

最佳实践与总结

2026 年落地最佳实践

  1. 场景分层:短文本实时处理 → TextRank;长文本高要求 → 混合模型 → GPT 微调。
  2. 双轨评估:ROUGE 指标量化 + 小批量人工抽查,二者缺一不可。
  3. 术语保护:重要领域词汇可以通过提示词或规则强制保留,防止被错误改写。
  4. 缓存优化:热门新闻等高频请求用 LRU 缓存,降低重复计算成本。

总结

自动摘要的核心逻辑一直没变:选出关键内容 → 组织成连贯句子 → 润色让表达流畅。2026 年的工具链已经足够成熟,新手可以先从 TextRank 开始,进阶到 T5/mT5,最终根据业务需要接入微调后的大模型,就能打造出实用的企业级摘要服务。


相关教程

建议先掌握 TextRank 和 py‑rouge,快速跑通整个流程,再逐步加入预训练模型。

📂 所属阶段:第六阶段 — 工业级 NLP 项目实战
🔗 相关章节:BERT 家族详解 · Prompt Engineering 基础