乐于分享
好东西不私藏

长文档压缩实战:三种策略帮你节省50-75% tokens,附完整代码

长文档压缩实战:三种策略帮你节省50-75% tokens,附完整代码

在信息呈指数级增长的时代,在保持原意的前提下自动压缩内容的能力,对于高效获取信息至关重要,以下三种“面向任务”压缩策略:

一、LLM summarization with constraints(带约束的抽取式压缩)目标:将检索到的每个相关章节压缩为聚焦要点(仅包含与 query 相关的定价信息)。

实现思路:先用 LLM 提取结构化要点;再用 gensim 的 TextRank 在这些要点内进行抽取式压缩,确保语义聚焦与客观可复现。

Python 示例:

from openai import OpenAIimport gensim.summarization as gsclient = OpenAI()defconstraint_llm_summary(text: str, query: str) -> str:    prompt = ("请仅提取与定价相关的要点,忽略认证、示例及其他无关内容。"f"Query: {query}\n\n内容:\n{text}"    )    resp = client.chat.completions.create(        model="gpt-4o-mini",        messages=[{"role""user""content": prompt}],        temperature=0.0,    )return resp.choices[0].message.content.strip()defcompress_with_textrank(summary_text: str, ratio: float = 0.4) -> str:# ratio 控制压缩比例,例如保留约40%的句子/要点return gs.summarizer(summary_text, ratio=ratio)# 假设检索到的三个相关章节(各约10页文本)sections = ["section1.txt""section2.txt""section3.txt"]query = "只提取 Plan A 与 Plan B 的 rate limits 和 quotas,包含具体数值"compressed_summaries = []for sec in sections:    raw = open(sec).read()    step1 = constraint_llm_summary(raw, query)  # 先由 LLM 提取聚焦要点    step2 = compress_with_textrank(step1, ratio=0.4)  # 再做抽取式压缩    compressed_summaries.append(step2)# 最终将三个压缩后的摘要与 query 一并送入下游生成

说明:

  • • TextRank 的抽取式特性可保留原文中包含确切数值的句子,适合与 LLM 约束提取配合。
  • • 使用 gs.summarizer 时注意其底层是句子级抽取,建议 ratio 不要过低,避免丢失关键数字。
  • • 与 README 对应:Graph-based 与 Feature-based 的抽取方法在 README 的 Extractive 章节(graph-based methodsfeature-based methods)有更详细背景。

二、Sentence-level scoring(句子级评分过滤)目标:基于 query 计算每句相关性,保留前 20% 的句子(Context-Preserving Compression)。

实现思路:使用 BERT 变体计算句子与 query 的相似度,按分数截断。

Python 示例:

from sentence_transformers import SentenceTransformerimport numpy as npmodel = SentenceTransformer("all-MiniLM-L6-v2")defsentence_level_filter(text: str, query: str, keep_ratio: float = 0.2) -> str:    lines = [l.strip() for l in text.split("\n"if l.strip()]ifnot lines:return""    query_emb = model.encode([query])    line_embs = model.encode(lines)    scores = (line_embs * query_emb).sum(axis=1)  # 点积近似余弦    k = max(1int(len(lines) * keep_ratio))    top_idxs = np.argpartition(scores, -k)[-k:]  # 快速取Top-K    top_idxs = sorted(top_idxs)return"\n".join([lines[i] for i in top_idxs])filtered = sentence_level_filter(long_doc, query, keep_ratio=0.2)

说明:

  • • 此处“句子级评分”对应 README 中 Feature-based 方法的核心思路:用特征/表示为句子打分并选择。更多细节见 feature-based methods

三、Hierarchical summarization(层次化摘要)目标:对超长文档先按章节摘要,再做元摘要(meta-summary),形成三层:全文 → 章节摘要 → 最终摘要。

实现思路:按章节切分后使用基于 LSA 的主题抽取方法(如使用 gensim 的 LSI)得到章节主题摘要;再用 LLM 将各章节摘要聚合为最终摘要。

Python 示例:

from gensim import corpora, modelsfrom gensim.summarization import summarize as gs_summarizeimport redefsplit_into_chapters(text: str, chapter_pattern: str = r"^#+\s+.+$") -> list:    lines = text.split("\n")    chapters, cur = [], []for l in lines:if re.match(chapter_pattern, l):if cur:                chapters.append("\n".join(cur))                cur = []            cur.append(l)else:            cur.append(l)if cur:        chapters.append("\n".join(cur))return chaptersdefchapter_lsa_summary(chapter: str, num_topics: int = 2) -> str:# 转换为句子列表,去除空行    sentences = [s.strip() for s in chapter.split("\n"if s.strip()]    tokenized = [[w.lower() for w in s.split()] for s in sentences]    dictionary = corpora.Dictionary(tokenized)    corpus = [dictionary.doc2bow(t) for t in tokenized]    lsi = models.LsiModel(corpus, id2word=dictionary, num_topics=num_topics)# 以每句对主导主题的贡献加权选择句子    corpus_lsi = lsi[corpus]    topic_weights = np.array([sum(w for _, w in vec) for vec in corpus_lsi])    top_k = max(1int(len(sentences) * 0.3))  # 保留约30%主题高相关句子    top_idxs = np.argsort(topic_weights)[-top_k:][::-1]return"\n".join([sentences[i] for i insorted(top_idxs)])defhierarchical_summary(text: str, query: str):    chapters = split_into_chapters(text)    chapter_summaries = [chapter_lsa_summary(ch) for ch in chapters]    meta = "\n\n".join(chapter_summaries)    final = constraint_llm_summary(meta, query)return finalfinal_summary = hierarchical_summary(very_long_doc, query)

权衡与落地建议:

  • Summarization 会增加额外 LLM 调用(每个检索文档一次)。对于超过约 2000 tokens 的文档,压缩在成本与效果上通常更划算;建议根据实际 token 限制与延迟要求动态选择策略。
  • 在需要严格保留数字与结构化信息的场景(如定价配额、错误码与重置规则),结合 TextRank 等抽取式方法更为稳妥;在需要语义融合与连贯表述的场景,可加重生成式或混合方法的权重。
本站文章均为手工撰写未经允许谢绝转载:夜雨聆风 » 长文档压缩实战:三种策略帮你节省50-75% tokens,附完整代码

评论 抢沙发

3 + 6 =
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
×
订阅图标按钮