#实战项目二:自动摘要生成器
📂 所属阶段:第六阶段 — 工业级 NLP 项目实战
🔗 相关章节:BERT 家族详解 · Prompt Engineering 基础
#1. 摘要的两大流派
#1.1 抽取式 vs 生成式
抽取式摘要:
- 从原文中直接挑选关键句子组成摘要
- 不生成新词,保留原文表达
- 方法:TextRank、TF-IDF、BERT 句子排序
生成式摘要:
- 像人一样理解后重新组织语言
- 可以改写、压缩、生成新词
- 方法:T5、BART、ChatGPT
2026 年主流:
- 短文本 → 抽取式(快,成本低)
- 长文本 → 生成式(质量高、GPT-4 效果最佳)#2. 抽取式摘要(TextRank)
# extractive_summary.py
from sklearn.feature_extraction.text import TfidfVectorizer
import numpy as np
import jieba
def cosine_sim(a, b):
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b) + 1e-8)
def textrank_summary(text, top_k=3):
"""TextRank 摘要抽取"""
sentences = [s.strip() for s in text.split("。") if len(s.strip()) > 10]
# TF-IDF 向量化
vectorizer = TfidfVectorizer(tokenizer=lambda x: jieba.lcut(x))
tfidf_matrix = vectorizer.fit_transform(sentences).toarray()
# 构建相似度矩阵
n = len(sentences)
similarity = np.zeros((n, n))
for i in range(n):
for j in range(n):
if i != j:
similarity[i][j] = cosine_sim(tfidf_matrix[i], tfidf_matrix[j])
# TextRank 迭代
scores = np.ones(n) / n
d = 0.85
for _ in range(50):
new_scores = (1 - d) / n + d * similarity.T @ scores
if np.allclose(scores, new_scores, atol=1e-5):
break
scores = new_scores
# 取 top_k
top_indices = sorted(scores.argsort()[-top_k:][::-1])
return "。".join([sentences[i] for i in top_indices])
# 示例
text = "自然语言处理是人工智能的重要分支。它研究计算机与人类语言的交互。自然语言处理包括语音识别、文本分类、机器翻译等任务。近年来,大语言模型取得了突破性进展。BERT和GPT是代表性模型。ChatGPT在对话系统中表现出色。"
print(textrank_summary(text))
# 模型输出关键句子组成的摘要#3. BERT 抽取式摘要
# bert_extractive.py
from transformers import pipeline
# 直接使用 Hugging Face 的预训练中文摘要模型
summarizer = pipeline(
"summarization",
model="facebook/bart-large-cnn", # 英文
# 中文模型:michaelrwang/distilbart-cnn-12-6
)
def bert_summary(text, max_length=130, min_length=30):
"""BERT 抽取式摘要"""
result = summarizer(text, max_length=max_length, min_length=min_length, do_sample=False)
return result[0]["summary_text"]
# 示例
print(bert_summary("自然语言处理是..."))#4. ChatGPT 生成式摘要
# openai_summary.py
from openai import OpenAI
client = OpenAI(api_key="your-api-key")
def gpt_summary(text, style="简洁"):
"""用 GPT-4o 生成摘要"""
prompt = f"""请为以下文章生成一个{style}摘要:
{text}
要求:
1. 字数控制在100字以内
2. 保留核心信息和关键数据
3. 语言简洁流畅
4. 直接输出摘要,不要解释"""
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
max_tokens=200,
)
return response.choices[0].message.content#5. 评估指标:ROUGE
# rouge_score.py
def evaluate_summary(reference, hypothesis):
"""手动计算 ROUGE-1 / ROUGE-2(简化版)"""
from collections import Counter
def rouge_n(ref, hyp, n):
ref_ngrams = set([tuple(ref[i:i+n]) for i in range(len(ref)-n+1)])
hyp_ngrams = set([tuple(hyp[i:i+n]) for i in range(len(hyp)-n+1)])
overlap = len(ref_ngrams & hyp_ngrams)
if len(hyp_ngrams) == 0:
return 0
return overlap / len(hyp_ngrams)
ref_tokens = list(reference)
hyp_tokens = list(hypothesis)
return {
"rouge-1": rouge_n(ref_tokens, hyp_tokens, 1),
"rouge-2": rouge_n(ref_tokens, hyp_tokens, 2),
}
# 使用 rouge 库
from rouge import Rouge
rouge = Rouge()
scores = rouge.get_scores(hypothesis, reference, avg=True)
print(scores)
# {'rouge-1': {'f': 0.86, 'p': 0.90, 'r': 0.82}#6. FastAPI 摘要服务
# app.py
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI(title="摘要生成 API")
class SummarizeRequest(BaseModel):
text: str
method: str = "chatgpt" # chatgpt / textrank / bert
@app.post("/summarize")
def summarize(req: SummarizeRequest):
if req.method == "chatgpt":
result = gpt_summary(req.text)
elif req.method == "textrank":
result = textrank_summary(req.text)
else:
result = bert_summary(req.text)
return {"summary": result, "method": req.method}
# 部署:uvicorn app:app --host 0.0.0.0 --port 8000#7. 小结
摘要系统选择指南:
文本长度 < 500 字:
→ 抽取式(TextRank / BERT)→ 快,成本低
文本长度 500-5000 字:
→ BERT 抽取式 or T5 生成式
文本长度 > 5000 字:
→ 分段处理 + GPT-4 摘要
2026 年推荐:
- 快速原型:TextRank
- 高质量:GPT-4o / Claude
- 开源可部署:T5 / BART💡 实践建议:实际生产中"抽取+生成"结合效果最好——先用抽取选出关键句,再用生成模型润色压缩,能显著提升摘要质量。
🔗 扩展阅读

