Skip to main content

14 posts tagged with "llm"

View All Tags

Paper reading-Eagle Exploring The Design Space for Multi- modal LLMs with Mixture of Encoders

· 8 min read
ayanami

nvidia的论文, 主要还是实践训练MLLM上的一堆经验


任务

探究通过使用不同的视觉编码器和分辨率来提高MLLM系统性能的不同设计带来的效果


motivation

  1. 解读高分辨率的精细视觉信息是MLLM重要的课题,常用的CLIP-ViT 预训练时候的分辨率只有如224*224或者336*336,对OCR等细粒度信息不够好
  2. 近期研究发现enhanced visual perception显著减少幻觉和提高性能,许多近期MLLM用了混合视觉编码器
    • 有扩大视觉编码器的预训练量和参数的
    • 有将高分辨率编码器和CLIP融合的
    • 也有更复杂的融合和路由,根据任务选用不同编码器,"视觉MoE"的
  3. 但缺乏对此类方法设计的通用考量, 以及综合性的大benchmark

方法

  1. 不同的视觉编码器进行基准测试,寻找更高分辨率自适应的方案
  2. 不同的视觉编码器混合策略做同类比较(论文将近期的混合策略归为了CC,SA,LH等几类)
  3. 寻找多个视觉编码器的最优组合
  4. 改进pre-alignment和数据混合

增加输入分辨率的做法

  • Tiling 将输入分割为子图,CLIP-ViT单独编码
  • 直接放大输入分辨率,并对位置编码进行进行插值

Eagle做的实验:

预训练,LLaVA-1.5 + CLIP 基础模型,和LLaVA相同的 595k 图文对,冻结整个模型,只训练projection layer

SFT: 1809k 多模态对话数据

评估:11个任务,包含VQA任务, OCR/文档/图表理解,视觉中心任务,基于知识的任务


结果 - Strong CLIP

  1. 如果插值,需要unfrozen视觉编码器,否则损害性能。这个结论和以前实验不同。

  2. 输入分辨率和预训练分辨率差越大,插值越掉点

  3. 672分辨率下,插值和子图方法性能差不多,但是考虑效率的话还是插值更好

  4. 进行分辨率adaption,300M的CLIP-ViT性能接近6B的InternVL

按照下表,nvidia着重提了448*448+解锁视觉编码器的方案,300M就达到非常接近SOTA的性能了。


image-20250601233933871


Vision Encoder

选取了以下的encoder

  • 视觉语言对比学习的视觉Encoder,比如CLIP的ViT和OpenCLIP的ConxNeXt;

  • 以目标检测为中心的任务预训练的视觉Encoder,EVA-02

  • OCR上训练的Pix2Struct

  • 分割上预训练的SAM

  • 自监督训练的DINO-V2

对不同预训练的视觉encoder输出的特征图进行resize和插值,使得视觉token数量相同.


结果:

image-20250601234936395


分析:

  • 在freeze的情况下他们通常能在和自己预训练任务相近的MLLM benchmark上实现最佳性能。例如来自CLIP的ConvNeXt进行了图文对齐,因此在TextVQA、SQA任务上时所有编码器里表现的最好的。而Text Recognition任务上训练所得的Pix2Struct视觉编码器,在OCR任务上是表现的最好的。
  • 当跟随CLIP-ViT高分辨率拓展策略,unfreeze视觉编码器时,基本都能有性能提升,也有反超对应domain上训练的视觉编码器的可能性,例如CLIP-ConvNeXt微调后在OCR上性能超过了Pix2Struct。

融合策略:

Refer to caption


  • 序列维度拼接:SA sequence append
  • 通道维度拼接:CC concat channel
  • LLAVA-HR式:LH 将高分辨率特征使用adapter注入低分辨率特征中,维持序列长度、通道维度不变
  • Mini-Gemini式:MG 将高分辨率特征使用local windows cross attention注入到低分辨率的queries中。
  • Deformable Attention式:DA 将MG的local windows变成了Deformable Attention

结果:

image-20250601235208565

  • 融合策略越复杂,性能的提升似乎越差,简单的SA/CC稳定涨点

  • 由于SA需要处理边长的序列长度,所以后面用CC


Pre-Alignment

Refer to caption

考虑对其他的视觉专家进行预先的文本模态对齐,再学会去融合不同视觉专家的特征。因此在目前的两阶段MLLM训练框架之前,添加了一个vision-language pre-alignment training阶段,首先使用next-token prediction监督每个视觉专家的特征+各自单独的projector(与LLaVA原始预训练策略不同)训练,让其与一个冻结的较小语言模型对齐。


  • 进行一个额外的预先对齐,可以比较好提升MLLM性能。
  • 预对齐后,再合并所有的视觉专家,训练projector和encoder
  • 虽然在 SFT 期间解冻视觉专家有助于通过更新视觉专家以适应语言模型来提高性能,但预对齐策略更有效地减轻了每位视觉专家的固有偏差,并稳定了训练过程,从而提高了整体性能 (unfreeze + pre-align效果加性

Fusion choice

w h:600


采用上述的3阶段训练和最好最简单的Channel concat策略,就可以进一步研究哪种视觉编码器组合最好。组合的策略是依次增加模型视觉编码器的数量,每次的选择基于上一个数量下最好的组合进行进一步添加。四到五个编码器(X4, X5)目前看来就已经比较合适了。

最佳组合是 CLIPConvNeXtSAMPix2StructEVA-02


最终和benchmark的比较

Refer to caption


高分辨率的文档任务的展示: 红色baseline失败,蓝色eagle成功

h:600


结论

  1. MLLM训练期间解锁视觉编码器matters
  2. 设计先进的融合策略并不能较简单的通道级联显露优势
  3. 更多的视觉专家MoE能带来持续增益,是增强MLLM能力的有效途径
  4. 视觉专家如果开始时候设计的任务和文本无关(没有对齐),用冻结的LLM进行预对齐(+解锁)后再整体训练能显著提升性能

RAG的一些思考与细节

· 13 min read
ayanami

Langchain needle in haystack 实验

长上下文之后,越后面的部分的事实性细节越容易找,尤其是多事实的情况下

引发的一个思考是 rerank 时是否需要将最关注的块放在 prompt 的最后面,也就是倒序?

  • 后补: 但其实又有attention sink相关的研究,可能还是需要具体任务具体测试分析

image-20250417222048515

Maybe recency bias in LLMs:只记得最近的了

No retrieval guarantees

image-20250417222613216

query analysis:将 question 联系到正确的文档

routing (to right DB)

full doc -> summary -> embedding: doc 中噪声非常大, summary 是必要的,语义层次的保留 level 通过 prompt 保证

self-reflection 听起来很美好,但实际常常用不到,太慢了,并且搜不出来更多是前期处理没做好,再换着花样也很难搜出来

HyDE 对于高度 Domain Knowledge 和抽象性理解的任务基本没用:

一些自己的解释

  1. 能否生成正确的假设文档, 难
  2. 即使通过先行的小批量搜索教导 LLM 根据这些 example 生成假设文档,也很难让 LLM 从这些文档中抽取某个泛化的问题,经常会 过度 specific 而导致后续漏掉文档
  3. 目前实验下来垂域脏文档类型最好的解决方案还是 reranker,embedder 如果不微调分布太接近了,例如全部的 chunk 都在 0.5~0.6 之间,意义寥寥

和数据分析的结合:

分析波动->(数据分析)找出波动的阶段-> 对每个波动的阶段做查询

GraphRag 这种 KG-based 的方法经常强调“对整个数据集信息的整合”

但这个要分领域,例如,个人知识库之中,这是好的

但垂域的知识文档常常是相似的格式,固定的路由,同时信息的整合关键不在“多实体”的关系上,而是在于“单个实体随时间的变化”上。

又或者说实体关系 R(e1,e2)R(e_1, e_2) 本身应该建模成一个包含时间的 R(e1,e2,t)R(e_1, e_2, t)

如果仅仅是靠新加入的文档来动态更新 KG 的话,滞后性会很强

在这种半结构化的模板式文档中,LLM 实际上在干一个 Fuzzy DB manager, 提取信息,充当一个搜索引擎

利用 KG 进行某种意义上的多跳推理本质上也只是对文档的多次检索,推理跳数越多,关系越复杂,离线生成 KG 就越难,不是所有领域都像是法律一样有一个明确的 A 判例引用 BCD 法条的连接关系的,这样复杂的 KG 在要想随时间变化也更不可能

从某种意义上来说,KG 是在横向生成,而类似金融这种领域的 RAG 做的是纵向的 Timeline, 这部分对于关键实体是有数据的,并且可能数据都不需要自己做(例如各种行情的图),而离线准备好这些 timeline 之后,如何在 timeline 上进行一个跳跃和查询分析才是关键的。

如果从 DB 的角度上分析的话,金融领域这种关注点快速变化的 RAG 系统(with cache)也就相当于 lazy generated timeseries DB 了,例如问了一个 A 的价格变化,就像是生成了一个 time, delta_price, event(detail) 的 timeseries DB 表,把生成 reason 这样的 LLM 工作 lazy 化了而已

chunk 的前总结和后总结(离线在线)

离线总结最大的问题在于总结哪些方面,实际上是文档预处理的一个部分

最简单的方法就是整个提示模板每个 chunk 问一次 LLM,有 langchain 的 map reduce 等稍微 high level 一点的工具可以支持这个事情

对长文档总结更有效一些的做法是利用好 embedding,先对 chunk embedding 做聚类,再每个聚类里面抽几个 chunk, 从而保证多样性和 chunk 数量的平衡

后总结,或者说 query-based 总结大体上是用 LLM 做比较多,但对于时延和开销的增加太高了,一个比较新的方法是 paragraph sentence-level mask bert(自己造的词),在段落中根据 q, d 的交叉编码得到句子级别的二进制掩码,从而删除无关部分。有一篇 ICLR2025 基于 bge 训了个,https://huggingface.co/blog/nadiinchi/provence

provence效果非常好,又快又几乎对齐例如GPT4.1这种顶级模型的效果

另一个思路就是绕过这个问题,切小块,依赖 rerank 和重新合并乃至知识图谱检索之类的策略保证相关性,也就是在查询完之后是合并还是切分的思路差距

半结构化数据

https://docs.superlinked.com/getting-started/installation 聚焦半结构化的异构数据,例如朴素 embedding 方案对数字的理解不足,无法建模 1-99 的相似度分数与 higher/lower 这种文本的关系

https://github.com/microsoft/multifield-adaptive-retrieval 做多字段的权重学习(自适应选择查询应该着重的权重)

embedding 相关的调优

colbert架构是一个better embedding的方向,其核心在于将文档的token level embedding保存下来,对于每一个query token,计算maxsim算子得到单token的score,再求和

img

对比朴素embedding方案,它在token level进行计算可以很好的带来类似关键词匹配的效果,有效避免长文档下,embedding过于平均化余弦相似太不敏感的问题

对比rerank方案,它的优点又在嵌入矩阵可以离线计算,不需要完全在线的交叉编码器

引入方案: https://python.langchain.com/docs/integrations/providers/ragatouille/

Prompt

基本没有什么特别通用的工作,但值得一提的是将prompt作为一个优化变量,使用LLM在Trajatory上进行采样和跑各种论文的“prompt优化算法”的解耦框架dsPy https://dspy.ai/ 用户以类似类型/对象系统的简短注释提供给dspy作为“初始意图”,而后续复杂的提示由dspy生成,核心思想是让用户专注于编程

class CheckCitationFaithfulness(dspy.Signature):
"""Verify that the text is based on the provided context."""

context: str = dspy.InputField(desc="facts here are assumed to be true")
text: str = dspy.InputField()
faithfulness: bool = dspy.OutputField()
evidence: dict[str, list[str]] = dspy.OutputField(desc="Supporting evidence for claims")

context = "The 21-year-old made seven appearances for the Hammers and netted his only goal for them in a Europa League qualification round match against Andorran side FC Lustrains last season. Lee had two loan spells in League One last term, with Blackpool and then Colchester United. He scored twice for the U's but was unable to save them from relegation. The length of Lee's contract with the promoted Tykes has not been revealed. Find all the latest football transfers on our dedicated page."

text = "Lee scored 3 goals for Colchester United."

faithfulness = dspy.ChainOfThought(CheckCitationFaithfulness)
faithfulness(context=context, text=text)

DSPy 中的不同优化器将通过为每个模块合成良好的小样本示例 (如 dspy.BootstrapRS 1 ) 来调整程序的质量;为每个提示提出并智能地探索更好的自然语言指令 (如 dspy.MIPROv2 2 ) ,以及为您的模块构建数据集并使用它们来微调系统中的 LM 权重 (如 dspy.BootstrapFinetune 3 )

LLM评估

测试不可靠:有多少答案是被记忆出来的?

有多篇相关的paper在讨论这个问题,然后采用了一些方法来衡量这个事情,例如,在数学问题题集中,替换无关的描述、修改数字等等,看看模型性能变差多少

类似数学问题集这种在网络上数据中很难过滤干净,还需要考虑多语言影响

另一些评估指标如ARC-AGI通过抽象图像智力问题集来评估模型的推理能力,相对来说泄题风险小一些(并且有隐藏test set)

  • 丢给LLM的时候不是图像,而是矩阵,用数字表示不同颜色

image-20250505134411046

Chatbot Arena: 让全世界的人都来进行判断哪个模型好

但还是有办法hack: 更fit人的倾向(粗体字、分点、emoji.....)

Elo Score 考虑除了人的直接倾向之外其他因素的影响,在BF模型计算时加上一项β0\beta_0, 11+exp(βiβj+β0)=Eij\frac{1}{1 + exp(\beta_i - \beta_j + \beta_0)} = E_{ij}, EijE_{ij} 是模型i和j的胜率,βi\beta_i 是模型i的真实评分,β0\beta_0 是一个全局偏差项,表示人类评估者的偏好。通过最大化似然函数来估计参数βi\beta_iβ0\beta_0,从而得到模型的真实评分。

β0=γ1长度差+γ2emoji个数差+γ3...\beta_0 = \gamma_1 * 长度差 + \gamma_2 * emoji个数差 + \gamma_3 * ...

image-20250505135351256

可以看到,考不考虑这个β0\beta_0,模型的排名差别很大

Goodhart's Law

一旦一项指标被用作目标,它就不再是一个好的指标

http://becomingahacker.org/integrating-agentic-rag-with-mcp-servers-technical-implementation-guide-1aba8fd4e442

However, traditional RAG has limitations: it usually queries a single data source and only performs one retrieval pass, so if the initial results are poor or the query is phrased oddly, the answer will suffer 但是,传统的 RAG 存在局限性:它通常查询单个数据源,并且只执行一次检索传递,因此如果初始结果不佳或查询措辞奇怪,答案将受到影响

There’s no built-in mechanism for the system to reason about how to retrieve better information or to use additional tools if needed. 系统没有内置机制来推理如何检索更好的信息或在需要时使用其他工具。

关于结构化输出的另一篇特别好的文章: https://www.boundaryml.com/blog/schema-aligned-parsing

推理加速:是对的,例如huggingface-text-embedding项目,将各种转trt/onnx 可以让吞吐提升5x

H100 bge-reranker-v2-m3 1024 * 512char sentence, 13s -> 2.3s

关键词抽取

基于主题LDA,词典等

小模型方法:先用spaCy、hanLP等得到语法树,再从语法树中拿到名词性关键词等

无监督,经典如YAKE!综合考虑词频,词位,共现等。可以考虑https://github.com/JackHCC/Chinese-Keyphrase-Extraction

一篇非常有insight的blog:上下文相关!=上下文充足,定量充足性和它的应用

https://research.google/blog/deeper-insights-into-retrieval-augmented-generation-the-role-of-sufficient-context/

Paper reading - Interleaved Scene Graph for Interleaved Text-and-Image Generation Assessment

· 5 min read
ayanami

开发了一个交错文本和图像生成综合评估框架ISG

使用scene graph捕获文本和图像的关系,提供四个级别的评估:整体的、结构性的、块级别和特定于图像的,并引入了一个新benchmark,ISG-BENCH

作者实验认为现有模型在端到端生成文本图像交错内容时,效果不好,于是做了一个Agent来完成这个任务


motivation

image-20250530152606364

如图,现有MLLM不能直接生成交错文本和图像内容,需要将生成图像部分交给SD等外部模型再组合,带来了更大的开销与不一致性


为了专注这一任务,作者的Benchmark优先考虑视觉为中心的任务,例如风格迁移等图像输出的特定要求。

  • 作者的数据集和人工标注比较有较高Pearson相似度,以此说明准确性
  • 作者表示先前没什么benchmark主要以视觉为中心,以此说明新颖度
  • 但有一说一,作者的表还是有点不公平的,例如它自己的sample很少(一千多),同时评估级别是自己提出的这个四级别评估

作者的表

image-20250530160048840


方法

image-20250530153213139 h:500

注意点: 中间看起来很复杂, 实际上是很多组prompt完成的


评估框架将query拆成scene-graph-like structure,其中图文作为节点,而它们的关系作为边

在整体,结构,块和图四级别的评估中,每个级别都会生成一些用于评估的QA对。作者的意图是,让整体和结构评估连贯性和整体质量,块和图像评估指令完成的细节


结构性:用一个LLM预估图文交替内容的结构,然后与实际生成的内容进行比较

image-20250530163448151


整体:MLLM-as-a-Judge和CoT,用1-10打分配合Yes/No判断

块: 将prompt P用LLM表示成三元组 (subj, obj, rel),再用LLM生成问题,并用VQA评估

image-20250530163519317


图像:从prompt 给的图像中用LLM抽出三元组关系和实体,判断query类别,根据类别不同使用不同的prompt产生判断的VQA,例如如果是"How to",则需要包含特定实体,如果是“Painting”,则需要图像的准确生成

image-20250530163331400 h:600


实验结果

所有统一模型在按照说明生成交错文本和图像内容方面都存在重大缺陷。许多模型只生成 1 到 3 张图像,而有些模型根本无法生成任何图像。

整体评估结果与三个细粒度级别的评估结果之间的不一致表明,即使同时提供用户指示和正确的黄金答案,MLLM-as-a-Judge 在全面评估回答方面也存在显着局限性。具体来说,Judge MLLM 努力根据细粒度的标准评估响应,例如输出结构(包括图像数量)和提示中规定的详细文本-图像关系。此外,我们对结果的分析揭示了 MLLM-as-a-Judge 中固有的偏见,即“图像质量偏见”,即具有更高质量图像内容的回答始终获得更高的分数,尽管这些回答可能违反用户的指导要求和评判指南。这种偏见表明,即使获得了黄金答案,MLLM-as-a-Judge 仍然无法正确地对符合指定要求的交错回答进行准确评估。


image-20250530160948640


效果展示: 跑一次它这个Benchmark要60美刀

image-20250530163815015 h:600


结论

  1. MLLM-as-a-judge存在图像质量bias
  2. 现有端到端MLLM生成图文内容效果不佳, 可能需要在工程性上的agent做补救

来本地部署大模型!

· 4 min read
ayanami

前言

这件事情的起因是这样的, 在开卷上机考想要部署一个本机大模型参考一下, 同时有同学和我讲qwen2.5-coder-7B非常的nice, 于是就有了下面这篇文章, 用ollama + docker部署的local LLM...

本地环境: Ubuntu24.04

以下是步骤

下载nvidia docker runtime

参考 https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html#installing-with-apt

apt

curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
&& curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit

设置 /etc/docker/daemon.json

{
"default-runtime": "nvidia",
"registry-mirrors": [
"https://1nj0zren.mirror.aliyuncs.com",
"https://docker.mirrors.ustc.edu.cn",
"http://f1361db2.m.daocloud.io",
"https://registry.docker-cn.com"
],
"runtimes": {
"nvidia": {
"args": [],
"path": "nvidia-container-runtime"
}
},
}

如果你需要代理, 参考配置加上

   "proxies": {
"http-proxy": "http://127.0.0.1:7890",
"https-proxy": "http://127.0.0.1:7890",
"no-proxy": ""
}

然后重启docker服务

sudo systemctl daemon-reload    
sudo systemctl restart docker

出现找不到"nvidia" runtime错误的, 检查有没有下载过docker desktop

下载过docker desktop的:

docker context ls
docker context use default

切换回default, 然后重启docker服务

下载ollama镜像

mkdir -p /data/containers/ollama/data
vi /data/containers/ollama/docker-compose.yml

docker-compose.yml

name: 'ollama'
services:
ollama:
restart: always
image: ollama/ollama
container_name: ollama
runtime: nvidia
environment:
- TZ=Asia/Shanghai
- NVIDIA_VISIBLE_DEVICES=all
networks:
- ai-tier
ports:
- "11434:11434"
volumes:
- ./data:/root/.ollama
networks:
ai-tier:
name: ai-tier
driver: bridge
ipam:
config:
- subnet: 172.22.1.0/24

启动

cd /data/containers/ollama
docker compose up -d

之后会拉ollama (2G)

验证成功

docker compose ps
# 得到结果应该如下
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
ollama ollama/ollama "/bin/ollama serve" ollama About a minute ago Up About a minute 0.0.0.0:11434->11434/tcp, :::11434->11434/tcp

下载模型

qwen2.5:7b建议换成其他的代码专用模型, 根据自己的电脑显卡配置决定参数量

空间占用 7b:5G, 3b: 2G, 1B:1G

docker exec -it ollama ollama pull qwen2.5:7b

成功结果这样

pulling manifest
pulling 00e1317cbf74... 100% ▕████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ 4.7 GB
pulling 4fa551d4f938... 100% ▕████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ 12 KB
pulling 8ab4849b038c... 100% ▕████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ 254 B
pulling 577073ffcc6c... 100% ▕████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ 110 B
pulling ad1518640c43... 100% ▕████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ 483 B
verifying sha256 digest
writing manifest
removing any unused layers
success

验证

❯ docker exec -it ollama ollama list
NAME ID SIZE MODIFIED
qwen2.5:7b 845dbda0ea48 4.7 GB 2 hours ago

What's next:
Try Docker Debug for seamless, persistent debugging tools in any container or image → docker debug ollama
Learn more at https://docs.docker.com/go/debug-cli/

开始服务

docker compose up -d

会在localhost:11434起一个服务, 浏览器输入后正常会有Ollama is running

前端套壳

ChatBox

直接去官网下载

https://chatboxai.app/zh/install

设置里面指定一下模型

image-20241121211509468

aider版本

参考https://aider.chat/docs/config/dotenv.html设置一下OLLAMA_BASE_API的环境变量

之后aider --model ollama/qwen2.5:7b 即可

下载自己看官网(pip install aider-chat)

ok, 大功告成!

[可选] IDE插件

一个例子是Continue插件https://www.continue.dev/

参考官网, 据说vsc支持还行, jet bug不少