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

目录


项目概述

自动摘要生成是NLP落地高频场景,旨在从长文本中提取关键信息生成简洁准确的内容。本项目兼顾「经典算法的速度」与「大模型的质量」,构建可直接接入生产的服务。

快速了解我们的目标

我们用直观的字典梳理项目三大维度的核心目标:

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

摘要技术分类

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

直接给你一张「2026 年决策表」,不用纠结选哪个:

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

极简技术发展脉络

不用记论文,记住这3个关键节点就行:

  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):
        # 中文TF-IDF(jieba分词)
        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 库,3行搞定核心评估:

# 安装: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基础