DeepSeek-OCR 和 Glyph 的视觉文本压缩:一个更直观的解释

清华+智谱的这篇论文和DeepSeek-OCR是同一赛道的两种打法,让我用最简单的方式讲清楚。


🎯 核心思想(一句话版)

把书变成照片给AI看,比一个字一个字读给它听更高效。


💡 背景动机:为什么要压缩?

传统LLM的困境

《简爱》小说 = 24万个token

传统LLM:
├─ 需要24万token的上下文窗口
├─ 内存消耗:O(n²) 爆炸式增长
├─ 训练成本:天文数字
└─ 推理速度:极慢

结果:根本跑不动!

Glyph的解决方案

《简爱》小说 → 渲染成图片 → 8万个视觉token

压缩比:24万 ÷ 8万 = 3×

为什么可行?
因为一张图片可以包含几百个字符,
而VLM只需要几百个视觉token就能编码这张图!

🔧 实现方法:三步走

第1步:持续预训练(教VLM读"照片书")

# 伪代码展示核心逻辑

def continual_pretraining():
    # 准备训练数据
    long_texts = load_books_and_documents()
    
    # 渲染成多种风格
    rendering_styles = [
        "document_style",  # 像Word文档
        "web_style",       # 像网页
        "code_style",      # 像代码编辑器
        "dark_mode"        # 深色主题
    ]
    
    for text in long_texts:
        for style in rendering_styles:
            # 渲染文本为图像
            images = render_text_to_images(text, style)
            
            # 训练任务
            tasks = [
                ocr_task(images),           # 让模型读图上的字
                interleaved_lm(images),     # 图文混合理解
                generation_task(images)     # 看图生成文字
            ]
            
            train_model(tasks)

# 输出:Glyph-Base(会读"照片书"的基础模型)

类比:这就像教小孩认字,既要教他读印刷体,也要教他读手写体,还要教草书、楷书……


第2步:LLM驱动的遗传搜索(找最佳"拍照"参数)

这是论文最有趣的部分!

问题:如何渲染最优?
渲染参数(部分):
├─ DPI(分辨率):72 vs 120 vs 300?
├─ 字体大小:9pt vs 12pt?
├─ 页面尺寸:A4 vs Letter?
├─ 行高:紧凑 vs 宽松?
├─ 颜色:黑底白字 vs 白底黑字?
└─ ... 共20+个参数

组合空间:几乎无限大!
解决方案:让GPT-4帮忙搜索
def llm_driven_genetic_search():
    # 初始化:随机生成配置
    population = random_sample_configs(n=10)
    
    for generation in range(5):  # 论文中跑了5轮
        # 1. 评估每个配置
        results = []
        for config in population:
            images = render_with_config(validation_set, config)
            accuracy = evaluate(model, images)
            compression = calculate_compression(images)
            
            results.append({
                "config": config,
                "accuracy": accuracy,
                "compression": compression,
                "score": balance(accuracy, compression)
            })
        
        # 2. 让GPT-4分析结果,建议改进
        prompt = f"""
        这是当前配置的评估结果:
        {results}
        
        请分析哪些参数影响了性能,
        建议如何变异/交叉配置以获得更好的trade-off。
        """
        suggestions = call_gpt4(prompt)
        
        # 3. 根据GPT-4建议生成新配置
        population = mutate_and_crossover(population, suggestions)
    
    return best_config_from_history

# 输出:最优渲染配置

类比:这就像拍证件照,摄影师会调整光线、角度、背景……让GPT-4当"摄影指导",告诉你怎么调最好看。

论文的实际最优配置(Table 8和Figure 6):

最优配置:
  dpi: 72                    # 较低分辨率(平衡清晰度和压缩)
  font_size: 9pt             # 较小字体(塞更多字)
  font_family: Verdana       # 易读字体
  page_size: 595×842         # A4尺寸
  line_height: 10pt          # 字体大小+1
  alignment: LEFT            # 左对齐
  bg_color: #FFFFFF          # 白底
  font_color: #000000        # 黑字
  margins: 10pt              # 边距
  
压缩比: 3-准确率: 与Qwen3-8B相当

第3步:后训练(精雕细琢)

def post_training(glyph_base, optimal_config):
    # 用最优配置渲染所有训练数据
    training_data = render_all_with_config(sft_data, optimal_config)
    
    # 阶段1:监督微调
    for epoch in sft_epochs:
        for instruction, rendered_images, response in training_data:
            # 加入思维链格式
            response_with_thinking = f"""
            <think>
            我看到图片上有{count_words(rendered_images)}个字...
            关键信息在第3页...
            </think>
            
            {response}
            """
            
            train(instruction, rendered_images, response_with_thinking)
    
    # 阶段2:强化学习(GRPO)
    for iteration in rl_iterations:
        # 采样多个回答
        responses = sample_multiple(model, instruction, rendered_images, n=16)
        
        # 用LLM judge打分
        rewards = [
            llm_judge_score(r, ground_truth) +  # 准确性奖励
            format_reward(r) +                   # 格式奖励
            ocr_alignment_reward(r, images)     # OCR对齐奖励
            for r in responses
        ]
        
        # 用GRPO更新策略
        update_policy(responses, rewards)
    
    return glyph  # 最终模型

# 输出:Glyph(生产级模型)

类比

  • SFT = 老师手把手教,一步步示范
  • RL = 自己做习题,根据对错调整策略

📊 效果对比:直观数据

性能对比

模型上下文长度Token数LongBenchMRCR
Qwen3-8B128K128K47.4623.02
Glyph384K128K50.5625.81

解读

  • Glyph用128K token处理了384K token的文本(3×压缩)
  • 性能不降反升!

速度对比(Figure 4数据)

128K token输入:

预填充(Prefill):
├─ 传统LLM: 1.0x(基准)
└─ Glyph:    4.8x 快 ⚡

解码(Decoding):
├─ 传统LLM: 1.0x
└─ Glyph:    4.4x 快 ⚡

训练(SFT):
├─ 传统LLM: 1.0x
└─ Glyph:    2.0x 快 ⚡

🆚 Glyph vs DeepSeek-OCR:核心差异

维度DeepSeek-OCRGlyph
目标批量生成训练数据实时长文本理解
压缩比10-20×3-4×
准确率容忍度可接受3-5%错误需要接近100%
应用场景内部数据引擎面向用户产品
延迟敏感度不敏感(离线)敏感(在线)
搜索方法无(手动设计)LLM驱动遗传搜索

形象比喻

DeepSeek-OCR = 工厂扫描仪
├─ 目标:快速批量扫描
├─ 可接受:偶尔识别错误(后续数据清洗)
└─ 优势:吞吐量巨大(日产33M页)

Glyph = 精密阅读器
├─ 目标:实时理解长文档
├─ 要求:高准确率(用户直接交互)
└─ 优势:速度快、效果好

🔬 关键技术洞察

1. 为什么视觉压缩可行?

信息密度对比
# 文本表示
text = "Hello World"
text_tokens = tokenizer(text)
# 输出: [15339, 4435]  # 2个token

# 视觉表示
image = render_to_image(text, dpi=72, font_size=9)
vision_tokens = vision_encoder(image)
# 输出: [v1, v2, ..., v64]  # 64个视觉token,但包含整行文字!

# 压缩效果
if len("Hello World " * 100) == 1200_chars:
    text_tokens_needed = 200
    vision_tokens_needed = 64  # 一张图搞定
    compression_ratio = 200 / 64 = 3.1×

关键:一个视觉token可以编码多个文字token的信息!


2. LLM驱动搜索的妙处

传统遗传算法 vs LLM驱动搜索
传统GA:
├─ 随机变异 → 盲目试探
├─ 需要大量迭代(几千次)
└─ 效率低

LLM驱动搜索:
├─ GPT-4分析 → 有理有据的建议
├─ 只需5轮×200步 = 1000次评估
└─ 论文实测:找到接近最优解

GPT-4的典型建议(推测):
"当前DPI=120时,准确率95%但压缩比只有2×。
建议:降低DPI到72-96,可能牺牲2-3%准确率,
但压缩比能提升到3-4×,整体性价比更高。"

3. 多阶段训练的必要性

为什么不能一步到位?

如果直接用最优配置训练:
❌ 模型只见过一种渲染风格
❌ 泛化能力差(换个字体就懵)
❌ 无法应对多样化文档

Glyph的策略:
✅ 预训练:多样化风格 → 鲁棒性
✅ 搜索:找最优配置 → 效率
✅ 后训练:专门优化 → 性能

类比:
预训练 = 通识教育(什么书都读)
搜索    = 找专业方向(物理还是化学?)
后训练  = 专业深造(成为专家)

🎨 可视化示例

渲染效果对比

原始文本(1000 tokens):
┌────────────────────────────────────┐
│ In a hole in the ground there      │
│ lived a hobbit. Not a nasty, dirty,│
│ wet hole, filled with the ends of  │
│ worms and an oozy smell, nor yet a │
│ dry, bare, sandy hole with nothing │
│ in it to sit down on or to eat: it │
│ was a hobbit-hole, and that means  │
│ comfort...                          │
│ [... 继续992个tokens ...]          │
└────────────────────────────────────┘

渲染后(DPI=72, font-size=9pt):
┌──────────────────────┐
│  [密集的文字图片]     │ ← 这一张图 = 256 vision tokens
│  包含约800 text tokens │
└──────────────────────┘
┌──────────────────────┐
│  [密集的文字图片]     │ ← 再一张 = 256 vision tokens
│  包含剩余200 tokens   │
└──────────────────────┘

总计:512 vision tokens 表示 1000 text tokens
压缩比:1000 / 512 ≈ 2×

💎 核心优势总结

1. 突破上下文限制

传统方法:
128K window → 只能处理 128K tokens

Glyph方法:
128K window → 可以处理 384K-512K tokens(3-4×)

极限压缩(8×):
128K window → 理论可处理 1M tokens!

2. 速度与成本优化

计算复杂度对比:

传统LLM(处理240K tokens):
├─ Attention: O(240K²) = 57.6B operations
├─ Memory: 240K × hidden_dim × num_layers
└─ 成本:巨大

Glyph(视觉表示80K tokens):
├─ Attention: O(80K²) = 6.4B operations  ← 9× 更快
├─ Memory: 80K × hidden_dim × num_layers ← 3× 更小
└─ 成本:显著降低

3. 可测试时扩展

# 神奇的特性:推理时可以调节压缩比!

# 低延迟模式(DPI=72)
fast_mode = render(text, dpi=72)
# 压缩比: 4×, 准确率: 72%

# 平衡模式(DPI=96)
balanced_mode = render(text, dpi=96)
# 压缩比: 2.2×, 准确率: 91%

# 高精度模式(DPI=120)
accurate_mode = render(text, dpi=120)
# 压缩比: 1.2×, 准确率: 95%

# 用户可以根据需求动态选择!

🚨 局限性(论文诚实承认)

1. 对渲染参数敏感

问题:
字体大小从9pt改到10pt → 准确率下降5%
DPI从72改到60 → 准确率骤降10%

原因:
模型在特定配置下训练,泛化能力有限

解决方向(论文未做):
训练"自适应渲染器",根据任务动态调整

2. UUID等罕见序列识别困难

传统LLM:
"a3f2-8b91-4c5d-9e17" ✅ 完美识别

Glyph:
"a3f2-8b91-4c5d-9e17" ❌ 可能识别为 "a3f2-8b9l-4cSd-9e17"
                            (1变成l, 5变成S)

原因:
视觉相似字符难以区分

3. 任务泛化能力弱

DeepSeek-OCR现象(论文也承认):
├─ OCR任务: 97% 准确率 ✅
├─ 文档理解: 优秀 ✅
└─ 推理任务: 相对弱 ⚠️

Glyph也存在类似问题:
├─ 长文本QA: 优秀
├─ 多跳推理: 可以
└─ 数学/代码: 未充分测试

🔮 未来方向(论文展望)

1. 自适应渲染

# 当前:固定配置
config = fixed_optimal_config

# 未来:任务感知渲染
def adaptive_render(text, task_type):
    if task_type == "速度敏感":
        return render(text, dpi=60, compression=5×)
    elif task_type == "准确率优先":
        return render(text, dpi=120, compression=1.5×)
    elif task_type == "代码":
        return render(text, font="Monospace", style="code")
    else:
        return render(text, **auto_optimize(task_type))

2. 从128K扩展到10M

论文实验:
128K window + 8× compression = 处理1M tokens ✅

理论极限:
128K window + 80× compression = 处理10M tokens?

挑战:
├─ 信息损失(80×太极端)
├─ OCR精度(字会糊成一团)
└─ 推理能力(太长的链条)

可能的解决方案:
分层渲染(类似图像金字塔)

3. 混合架构

def hybrid_context_manager(context):
    recent_context = context[-10K:]     # 最近内容
    old_context = context[:-10K]        # 历史内容
    
    # 最近内容:保持文本形式(高精度)
    recent_tokens = tokenizer(recent_context)
    
    # 历史内容:渲染压缩(高效率)
    old_images = render_and_compress(old_context, ratio=4×)
    
    # 混合输入
    return combine(old_images, recent_tokens)

# 优势:
# ✅ 保留关键信息的精度
# ✅ 压缩不太重要的历史
# ✅ 平衡性能和效率

📝 最终总结:一个形象比喻

传统LLM = 一个字一个字读书的人
├─ 优点:一字不漏
├─ 缺点:慢,容易忘记前文
└─ 能力:最多读个几万字就累了

Glyph = 会速读和图像记忆的人
├─ 方法:把书"拍照"存进大脑
├─ 优点:快,记得住,能处理长书
├─ 缺点:偶尔会把"0"看成"O"
└─ 能力:能读几十万字的小说

核心思想:
用"空间"(图像)代替"时间"(逐字序列),
实现更高效的信息编码。

最精炼的一句话总结

Glyph把"逐字读书"变成了"看书照片",用VLM的视觉理解能力实现3-4×文本压缩,让128K窗口的模型能处理384-512K tokens的长文本,同时保持准确率并大幅提升速度。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值