GLM-4-9B-Chat-1M提示工程指南:长文本摘要与关键信息提取技巧

最近在折腾一些长文档处理的项目,比如法律合同审查、学术论文分析,发现很多模型一遇到几十万字的文本就“歇菜”了,要么漏掉关键信息,要么生成的内容前后矛盾。直到试了GLM-4-9B-Chat-1M,这个支持100万tokens上下文的模型,才算是找到了一个靠谱的解决方案。

不过,光有模型还不够,怎么跟它“沟通”才是关键。同样的模型,不同的提问方式,得到的结果可能天差地别。这篇文章就是我这段时间摸索出来的一些实用技巧,专门针对GLM-4-9B-Chat-1M的长文本处理能力,重点讲怎么让它帮你做摘要和提取关键信息。我会用大白话解释,配上实际的代码例子,让你看完就能上手用起来。

1. 先搞清楚GLM-4-9B-Chat-1M到底能干什么

在开始设计提示词之前,咱们得先了解这个模型的“脾气”。GLM-4-9B-Chat-1M最大的特点就是能处理超长文本——100万tokens,大概相当于200万个汉字。这是什么概念呢?差不多是两本《红楼梦》的长度,或者125篇学术论文。

但光能“吃下”长文本还不够,关键是要能“消化”。根据官方的测试,这个模型在“大海捞针”实验里表现很不错,能在超长文本里准确找到分散的关键信息。这意味着它不只是把文本存起来,而是真的能理解里面的内容。

不过,模型毕竟是模型,它不会主动告诉你“我觉得这段很重要”。你得通过合适的提示词,引导它关注你想要的信息。下面这张表简单对比了一下不同场景下,模型能帮你做什么:

你能给它的任务 它能给你的结果 适合的场景
“总结一下这篇文档” 生成一段概括性的摘要 快速了解长文档大意
“提取所有的人名、地名、时间” 列出具体的实体信息 信息整理、数据抽取
“找出关于‘违约责任’的条款” 定位相关段落并解释 合同审查、法规查找
“对比前后两个版本的变化” 列出新增、删除、修改的内容 文档版本对比

知道了它能做什么,接下来咱们就看看具体怎么跟它“说话”。

2. 分层摘要:让模型像人一样阅读长文档

直接让模型“总结这篇100万字的文档”,效果往往不理想。要么摘要太笼统,要么漏掉重要细节。我试下来,最好的方法是分层处理——先让模型看整体结构,再深入具体章节,最后合成完整的摘要。

2.1 第一步:先看目录,了解框架

就像我们读一本书先看目录一样,你可以先让模型提取文档的结构。下面是一个简单的例子:

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

# 加载模型和分词器
model_name = "THUDM/glm-4-9b-chat-1m"
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    torch_dtype=torch.bfloat16,
    low_cpu_mem_usage=True,
    trust_remote_code=True
).eval()

# 假设你的长文档已经加载为text变量
# 这里用简化的例子说明
long_document = """
第一章 项目背景
本章介绍了项目的起源、发展历程和当前状况...
第二章 技术方案
本章详细说明了采用的技术架构、核心算法和实现路径...
第三章 实施计划
本章列出了项目的时间安排、资源分配和风险控制...
第四章 预期成果
本章描述了项目完成后能达到的效果和产生的价值...
"""

# 构建提示词
prompt = f"""请分析以下文档的结构,提取出所有章节标题,并简要说明每个章节的主要内容。

文档内容:
{long_document}

请按照以下格式回复:
1. 章节标题:简要说明
2. 章节标题:简要说明
..."""

# 编码并生成
inputs = tokenizer.apply_chat_template(
    [{"role": "user", "content": prompt}],
    add_generation_prompt=True,
    tokenize=True,
    return_tensors="pt"
)

with torch.no_grad():
    outputs = model.generate(
        inputs,
        max_new_tokens=500,
        temperature=0.7,
        do_sample=True
    )
    
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
print("模型回复:")
print(response)

这样做的目的是让模型先对文档有个整体把握,知道有哪些部分,每个部分大概讲什么。这比直接总结全文要准确得多。

2.2 第二步:分章节摘要,抓住重点

有了整体结构后,就可以让模型对每个重要章节进行详细摘要。这里有个小技巧:不要一次性处理所有章节,而是逐个处理,避免信息过载。

# 假设我们已经从第一步得到了章节列表
chapters = [
    "第一章 项目背景",
    "第二章 技术方案", 
    "第三章 实施计划",
    "第四章 预期成果"
]

# 对每个章节进行摘要
summaries = []
for i, chapter_title in enumerate(chapters):
    # 这里需要根据实际情况提取对应章节的内容
    # 假设我们有一个函数能根据标题提取内容
    chapter_content = extract_chapter_content(long_document, chapter_title)
    
    prompt = f"""请对以下章节内容进行摘要,要求:
1. 提取核心观点(不超过3个)
2. 总结关键数据或事实
3. 用简洁的语言概括主要内容

章节标题:{chapter_title}
章节内容:
{chapter_content}

请按照以下格式回复:
核心观点:
1. ...
2. ...
3. ...

关键数据/事实:
- ...
- ...

内容概括:..."""
    
    # 调用模型生成摘要(代码类似上面,省略重复部分)
    chapter_summary = call_model(prompt)
    summaries.append((chapter_title, chapter_summary))
    
    print(f"已完成章节 {i+1}/{len(chapters)} 的摘要")

2.3 第三步:合成最终摘要

有了各个章节的摘要后,最后一步是让模型把这些摘要整合成一个连贯的全文摘要。

# 把所有章节摘要拼接起来
all_summaries = "\n\n".join([f"{title}:\n{summary}" for title, summary in summaries])

prompt = f"""基于以下各章节的摘要,请生成一份完整的文档摘要。

各章节摘要:
{all_summaries}

要求:
1. 保持逻辑连贯,不要简单拼接
2. 突出文档的核心价值和关键结论
3. 控制长度在300字左右
4. 用第三人称客观叙述

完整摘要:"""

final_summary = call_model(prompt)
print("最终生成的文档摘要:")
print(final_summary)

这种分层的方法有几个好处:一是减轻了模型单次处理的压力,二是让摘要更有层次感,三是如果某个章节的摘要不满意,可以单独调整,不用重做全文。

3. 关键信息提取:从大海里捞出那根针

长文档里往往藏着很多重要信息,比如合同里的金额、日期、责任条款,论文里的实验数据、结论观点。手动找这些信息就像大海捞针,但用对提示词,模型能帮你高效完成。

3.1 实体提取:让人物、地点、时间无所遁形

最基本的提取任务就是找出文档里的各种实体。GLM-4-9B-Chat-1M在这方面表现不错,但需要你明确告诉它要找什么。

# 实体提取的提示词示例
prompt = f"""请从以下文本中提取所有实体信息,并按类别整理。

文本内容:
{long_document}

请提取以下类型的实体:
1. 人名(包括个人、组织)
2. 地名(国家、城市、机构等)
3. 时间(日期、年份、时间段)
4. 数字信息(金额、数量、百分比等)
5. 专业术语(技术名词、法律条款等)

请按照以下格式回复:
【人名】
- 实体1
- 实体2
...

【地名】
- 实体1
- 实体2
...

【时间】
- 实体1
- 实体2
...

【数字信息】
- 实体1(上下文说明)
- 实体2(上下文说明)
...

【专业术语】
- 术语1(简要解释)
- 术语2(简要解释)
..."""

entities = call_model(prompt)
print("提取的实体信息:")
print(entities)

这里的关键是分类要清晰,格式要明确。模型看到这样的提示词,就知道该怎么组织答案。

3.2 特定信息定位:精准找到你要的内容

有时候你不需要所有实体,只关心某个特定信息。比如在合同里找“违约金条款”,在论文里找“实验结论”。

# 特定信息定位的提示词
target_info = "违约责任"  # 你想找的信息

prompt = f"""请从以下文档中查找所有关于“{target_info}”的内容。

文档内容:
{long_document}

要求:
1. 找到包含“{target_info}”或相关表述的所有段落
2. 对每个段落,说明它位于文档的哪个部分(如章节标题)
3. 解释该段落中“{target_info}”的具体含义或规定
4. 如果有多处相关内容,请说明它们之间的关系

请按照以下格式回复:
位置1:[章节/页码]
内容:[引用原文]
解释:[你的理解]

位置2:[章节/页码]
内容:[引用原文]
解释:[你的理解]

..."""

located_info = call_model(prompt)
print(f"关于'{target_info}'的定位结果:")
print(located_info)

这种定位特别适合法律文档、技术规范等需要精确引用的场景。模型不仅能找到位置,还能帮你初步理解内容。

3.3 关系提取:连接散落的信息点

在长文档里,相关信息往往分散在不同地方。比如一个项目的预算可能在开头提到总数,在中间分项列出,在结尾又有调整。提取这些信息并建立联系,能让你对文档有更深的理解。

# 关系提取的提示词
prompt = f"""请分析以下文档中关于“项目预算”的所有信息,并建立它们之间的关系。

文档内容:
{long_document}

请完成以下任务:
1. 找出所有提到预算、成本、费用的地方
2. 提取具体的数字和时间信息
3. 分析预算的构成(如人力成本、设备成本等)
4. 如果文档中有预算调整,说明调整的原因和幅度
5. 用表格形式汇总所有预算相关信息

表格格式建议:
| 预算项目 | 金额 | 时间 | 相关说明 |
|----------|------|------|----------|
| ... | ... | ... | ... |

最后,请总结文档中预算安排的主要特点。"""

budget_analysis = call_model(prompt)
print("预算关系分析:")
print(budget_analysis)

这种提取方式对财务报告、项目计划等文档特别有用,能帮你快速理清复杂的数据关系。

4. 多轮对话优化:让模型记住上下文

处理长文档时,经常需要多轮对话。比如先让模型总结,再针对某个细节提问,然后要求它对比不同部分的内容。GLM-4-9B-Chat-1M支持多轮对话,但要用好这个功能,有些技巧需要注意。

4.1 保持对话连贯性

多轮对话的关键是让模型记住之前的交流内容。虽然模型有长上下文能力,但你需要明确告诉它现在的问题和之前内容的关系。

# 第一轮:获取文档摘要
first_prompt = f"""请对以下文档进行摘要:
{document_content}

摘要要求:突出核心观点,控制长度在200字以内。"""

first_response = call_model(first_prompt)

# 第二轮:基于摘要提问
second_prompt = f"""基于你刚才生成的摘要,我有一个具体问题。

你刚才的摘要:
{first_response}

我的问题:文档中提到的技术方案,主要解决了哪些传统方法的不足?

请结合摘要和原文(如有需要)回答这个问题。"""

second_response = call_model(second_prompt)

# 第三轮:进一步追问
third_prompt = f"""我们之前的对话:
1. 我让你总结了文档
2. 你给出了摘要:{first_response[:100]}...
3. 我问了技术方案的优势
4. 你回答:{second_response[:100]}...

现在我想知道:这个技术方案的实施难点是什么?预计需要多少资源?

请基于文档内容和之前的对话回答。"""

third_response = call_model(third_prompt)

注意在后续提示词中引用之前的对话内容,这能帮助模型保持上下文连贯性。但也不要引用太多,否则会占用不必要的tokens。

4.2 处理复杂查询

有时候你需要模型进行复杂的分析,比如对比文档的不同部分,或者从多个角度评估某个方案。

# 复杂分析提示词
prompt = f"""请对以下文档进行综合分析。

文档内容:
{long_document}

请完成以下任务:
1. 从技术可行性、经济成本、实施风险三个角度评估文档中的方案
2. 对比方案实施前后的预期变化
3. 找出方案可能依赖的外部条件或资源
4. 如果文档中有多个备选方案,请比较它们的优劣

请按照以下结构回复:
一、多角度评估
1. 技术可行性:...
2. 经济成本:...
3. 实施风险:...

二、前后对比
- 实施前:...
- 实施后:...

三、依赖条件
- 内部依赖:...
- 外部依赖:...

四、方案比较(如有多个方案)
- 方案A优势:... 劣势:...
- 方案B优势:... 劣势:...

五、综合建议
基于以上分析,我认为..."""

complex_analysis = call_model(prompt)
print("复杂分析结果:")
print(complex_analysis)

这种提示词给了模型明确的分析框架,让它知道要从哪些方面思考,怎么组织答案。

4.3 纠正和引导

如果模型的回答偏离了你的预期,不要直接说“你错了”,而是引导它重新思考。

# 假设模型的第一次回答不够准确
initial_response = call_model("总结这篇文档的技术部分")

# 发现模型漏掉了重要内容,进行引导
correction_prompt = f"""你刚才对技术部分的总结是:
{initial_response}

我注意到你漏掉了关于“分布式架构”和“容错机制”的内容。文档中这些部分其实很重要。

请重新阅读文档的技术部分,特别关注:
1. 系统是如何分层的
2. 各个模块之间怎么通信  
3. 出错时怎么恢复
4. 怎么保证数据一致性

然后重新生成技术总结,确保包含以上要点。"""

corrected_response = call_model(correction_prompt)

这种引导方式比简单否定更有效,既指出了问题,又给出了具体的改进方向。

5. 实际应用中的小技巧和注意事项

用了这么长时间GLM-4-9B-Chat-1M,我总结了一些实用的小技巧,能帮你避开一些坑,提升使用效果。

5.1 控制输出长度和格式

模型有时候会“啰嗦”,或者格式不符合你的要求。通过提示词可以很好地控制这些。

# 明确要求输出格式和长度
prompt = f"""请提取以下文档的关键信息。

文档:
{document_content}

要求:
1. 输出必须是JSON格式
2. 包含以下字段:title, author, main_points, key_data, conclusions
3. main_points是数组,不超过5项
4. key_data是键值对
5. 总字数不超过500字
6. 使用中文回复

JSON格式示例:
{{
  "title": "文档标题",
  "author": "作者或来源",
  "main_points": ["要点1", "要点2", "要点3"],
  "key_data": {{"数据1": "值1", "数据2": "值2"}},
  "conclusions": "主要结论"
}}

现在开始提取:"""

formatted_output = call_model(prompt)

明确要求输出格式,模型会更配合。JSON格式特别适合后续的程序处理。

5.2 处理超长文档的分块策略

虽然GLM-4-9B-Chat-1M能处理100万tokens,但有时候文档实在太长,或者你想节省计算资源,可以考虑分块处理。

def process_long_document_by_chunks(document, chunk_size=50000):
    """将长文档分块处理"""
    chunks = []
    for i in range(0, len(document), chunk_size):
        chunk = document[i:i+chunk_size]
        
        # 尽量在段落边界分块
        if i + chunk_size < len(document):
            # 找到最近的段落结束位置
            last_period = chunk.rfind('。')
            if last_period > chunk_size * 0.9:  # 如果在后10%找到句号
                chunk = chunk[:last_period+1]
                # 调整下一次的起始位置
                i = i - (chunk_size - (last_period + 1))
        
        chunks.append(chunk)
    
    # 对每个块进行处理
    chunk_results = []
    for j, chunk in enumerate(chunks):
        print(f"处理第 {j+1}/{len(chunks)} 块...")
        
        prompt = f"""这是文档的第{j+1}部分(共{len(chunks)}部分)。

内容:
{chunk}

请提取这部分的关键信息,包括:
1. 主要话题或主题
2. 重要事实或数据
3. 出现的核心人物、组织、地点
4. 与其他部分的可能联系

请简洁回答,为后续整合做准备。"""
        
        result = call_model(prompt)
        chunk_results.append(result)
    
    # 整合所有块的结果
    integration_prompt = f"""以下是文档各部分的提取结果:

{chr(10).join([f'部分{i+1}: {result}' for i, result in enumerate(chunk_results)])}

请将这些部分整合成完整的文档摘要,注意:
1. 保持逻辑连贯
2. 去除重复信息
3. 突出文档的整体脉络
4. 控制总长度在800字以内

完整摘要:"""
    
    final_summary = call_model(integration_prompt)
    return final_summary

分块处理的关键是要处理好块与块之间的衔接,避免信息断裂。

5.3 温度参数和采样策略

GLM-4-9B-Chat-1M的生成参数会影响输出质量。根据我的经验:

  • 摘要任务:温度(temperature)设低一点(0.3-0.5),让输出更确定、更聚焦
  • 创意提取:温度可以高一点(0.7-0.9),让模型更有“想象力”
  • 精确信息提取:用贪心搜索(top_k=1)或低温度,减少随机性
# 不同任务的参数设置示例
summary_params = {
    "temperature": 0.3,
    "top_p": 0.9,
    "do_sample": True,
    "max_new_tokens": 500
}

creative_params = {
    "temperature": 0.8,
    "top_p": 0.95,
    "do_sample": True,
    "max_new_tokens": 1000
}

precise_params = {
    "temperature": 0.1,
    "top_k": 1,  # 贪心搜索
    "do_sample": False,
    "max_new_tokens": 300
}

5.4 处理模型的不确定回答

有时候模型会对某些问题表示不确定,或者说“文档中没有明确提到”。这时候不要轻易放弃,可以换个方式提问。

# 如果模型说“文档中没有明确提到”
initial_question = "文档中的项目预算是多少?"
initial_response = call_model(initial_question)

if "没有明确提到" in initial_response or "不确定" in initial_response:
    # 换个方式提问
    follow_up = f"""文档中可能没有直接说“预算”这个词,但请查找以下相关信息:
    1. 成本、费用、资金相关的表述
    2. 数字金额加上“万元”、“亿元”等单位
    3. 财务计划、资金安排等内容
    4. 资源投入、人力投入的量化描述
    
    请重新查找,看看有没有间接提到的预算信息。"""
    
    refined_response = call_model(follow_up)

很多信息在文档中不是直接表述的,需要模型进行推理和关联。引导模型从不同角度查找,往往能有新发现。

6. 效果怎么样?实际用用看

说了这么多技巧,到底效果如何呢?我用自己的几个项目做了测试,这里分享一些实际感受。

首先是最常见的摘要任务。我拿了一篇大概5万字的行业分析报告做测试,分别用了三种方法:一是直接让模型总结全文,二是用我前面说的分层摘要法,三是传统的人工摘要。结果分层摘要法生成的内容最接近人工摘要的质量,关键点都覆盖到了,而且逻辑更清晰。直接总结的方法虽然快,但漏掉了一些重要数据。

关键信息提取方面,我测试了一份30页的技术合同。让模型提取所有金额、日期、责任条款,准确率大概在85%左右。有些特别隐晦的表述(比如用“相关费用”代替具体金额),模型会漏掉,但明确写出来的信息基本都能找到。

多轮对话的效果让我挺惊喜的。我模拟了一个合同审查的场景:先让模型总结合同要点,然后问它“违约责任条款是否合理”,接着问“如果发生争议,应该怎么解决”。模型能记住之前的对话内容,回答很有连贯性,不像有些模型聊着聊着就忘了前面说过什么。

当然也有不足的地方。处理速度是个问题,特别是文档特别长的时候,生成摘要要等比较久。另外,虽然模型能处理长文本,但如果文档结构特别混乱(比如没有明确章节划分),效果会打折扣。

总的来说,GLM-4-9B-Chat-1M在长文本处理上确实有优势,但要用好它,提示词的设计很关键。我上面分享的这些技巧,都是实际项目中摸索出来的,希望能帮你少走些弯路。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐