Jina ReaderLM v2 测试记录

jina 出了 ReaderLM v2 版本,这个版本的 ReaderLM 在处理文本数据时更加高效和准确。
之前简单测试了下 v1, 结论是:

  • 幻觉严重, 尤其特别喜欢造 url
  • 很容易触发无限生成 比如 example1 example2…. 一直生成下去

第一眼就是不可用就没继续了。
这次 v2 来了,测试了一下,幻觉问题好了很多,无限生成测试了几个也没遇到,但最为一个 html 转 markdown 的工具还是不够稳定。
这里的稳定性主要是指,与传统的基于语法树解析的工具相比,它在处理速度和结构识别的准确性上还有差距。他的确能生成不错的 markdown,但是很容易被正确结构但是内容文本里有特殊构造的/或者有一些语法错误的 html 页面所影响。

注意:这个博客里的测试只是为了列出 v2 的一些问题,针对问题进行特殊构造的测试,实际网页可能也遇不到文中提到的问题,具体以实际场景为准了。
顺道一提,这个模型是以 CC 协议发布的,所以商用场景需要遵守相关协议。

测试

测试直接使用 hf 页面上的colab环境,改一下 html 就行,用我们自己构造的 html。

结构丢失/错乱

构造了一个嵌套比较多的 html 结构 查看最后结果
测试 html:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>嵌套层级示例</title>
</head>
<body>
<header>
<h1>嵌套层级示例</h1>
</header>

<div id="main-content">
<div class="section">
<h2>第一部分</h2>
<div class="subsection">
<p>这是一个段落,嵌套在第一部分的子部分中。</p>
<div class="nested-div">
<p>这是一个更深层级的段落,嵌套在子部分的 div 中。</p>
<div class="deeply-nested">
<p>这是一个更深层级的段落,嵌套在更深层级的 div 中。</p>
<div class="very-deeply-nested">
<p>这是一个非常深层级的段落,嵌套在非常深层级的 div 中。</p>
</div>
</div>
</div>
</div>
</div>

<div class="section">
<h2>第二部分</h2>
<div class="subsection">
<p>这是第二部分的第一个段落。</p>
<div class="nested-div">
<p>这是嵌套在第二部分的 div 中的段落。</p>
<div class="deeply-nested">
<p>这是更深层级的段落。</p>
<div class="very-deeply-nested">
<p>这是非常深层级的段落。</p>
<div class="extremely-deeply-nested">
<p>这是极其深层级的段落。</p>
</div>
</div>
</div>
</div>
</div>
<div class="subsection">
<p>这是第二部分的第二个子部分。</p>
<div class="nested-div">
<p>这是另一个嵌套的段落。</p>
<div class="deeply-nested">
<p>这是更深层级的段落。</p>
</div>
</div>
</div>
</div>

<div class="section">
<h2>第三部分</h2>
<div class="subsection">
<p>这是第三部分的段落。</p>
<div class="nested-div">
<p>这是嵌套在第三部分的 div 中的段落。</p>
<div class="deeply-nested">
<p>这是更深层级的段落。</p>
<div class="very-deeply-nested">
<p>这是非常深层级的段落。</p>
<div class="extremely-deeply-nested">
<p>这是极其深层级的段落。</p>
<div class="ultra-deeply-nested">
<p>这是超深层级的段落。</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

<footer>
<p>&copy; 2023 示例公司. 保留所有权利.</p>
</footer>
</body>
</html>

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# 嵌套层级示例

## 第一部分

这是一个段落,嵌套在第一部分的子部分中。

### 第一个子部分

这是一个更深层级的段落,嵌套在子部分的 div 中。

#### 第二个子部分

这是一个更深层级的段落,嵌套在更深层级的 div 中。

##### 更深层级的段落

这是一个非常深层级的段落,嵌套在非常深层级的 div 中。

## 第二部分

### 第二部分的第一个段落

这是第二部分的第一个段落。

#### 第二部分的 div 中的段落

这是一个嵌套在第二部分的 div 中的段落。

##### 更深层级的段落

这是一个更深层级的段落。

###### 第三部分的段落

这是第三部分的段落。

#### 第二部分的 div 中的段落

这是嵌套在第三部分的 div 中的段落。

##### 更深层级的段落

这是更深层级的段落。

###### 第二部分的子部分

这是另一个嵌套的段落。

##### 更深层级的段落

这是更深层级的段落。

## 第三部分

### 第三部分的段落

这是第三部分的段落。

#### 第二部分的 div 中的段落

这是嵌套在第三部分的 div 中的段落。

##### 更深层级的段落

这是更深层级的段落。

###### 第二部分的子部分

这是另一个嵌套的段落。

##### 更深层级的段落

这是第二部分的子部分。

##### 第三部分的段落

这是嵌套在第三部分的 div 中的段落。

##### 更深层级的段落

这是更深层级的段落。

###### 第二部分的子部分

这是另一个嵌套的段落。

##### 更深层级的段落

这是第二部分的子部分。

在这个测试中,我构造了一个多层嵌套的 HTML 结构,目的是验证 ReaderLM v2 在处理复杂嵌套时的表现。
结果显示,模型在转换过程中丢失了部分内容,并且层级结构出现了错乱。例如,原本的“第一部分”、“第二部分”和“第三部分”在 Markdown 中被错误地合并或拆分,导致语义不连贯。这表明模型在处理深度嵌套的 HTML 结构时,可能无法准确识别和保留原有的层级关系,从而影响输出结果的可读性和准确性。

被符号干扰 产生幻觉

测试:

1
2
3
4
<div>
测试1+1=
<div>'"这是一句带各种标点,.。的话</div>
</div>

返回:

1
2
3
测试 1+1=

"这是一句带各种标点,.。的话"

这个测试旨在验证模型对特殊符号(如引号、标点符号等)的处理能力。我们构造了一个包含多种符号的 HTML 片段,结果显示模型在转换过程中对符号的处理不一致,甚至产生了“幻觉”(即输出与输入不符)。例如,输入中的单引号和双引号在输出中被错误地调整或省略,导致语义发生变化。这表明模型在处理符号时可能存在一定的局限性,尤其是在符号与上下文结合紧密的情况下,容易产生错误。

注释干扰

测试:

1
<div>测试1+1='<!-- 这句话不应该出现 -->2<!-- 连续注释 -->'</div>

返回:

1
测试 1+1='<!-- 这句话不应该出现 -->2<!-- 连续注释 -->'

在这个测试中,我们构造了一个包含 HTML 注释的片段,目的是验证模型是否能正确处理注释内容。结果显示,模型在注释前后存在单引号的情况下,未能正确忽略注释内容,导致注释被保留在输出中。这表明模型在处理注释时,可能会受到周围符号(如引号)的干扰,从而无法完全过滤掉注释内容。这种问题在实际应用中可能会导致不必要的噪音,影响输出结果的纯净度。

转义问题

测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<h1>转义字符测试</h1>
<p>这是一个包含各种转义字符的段落:</p>
<ul>
<li>小于号:&lt;</li>
<li>大于号:&gt;</li>
<li>和号:&amp;</li>
<li>双引号:&quot;</li>
<li>单引号:&apos;</li>
<li>版权符号:&copy;</li>
<li>注册商标符号:&reg;</li>
<li>商标符号:&trade;</li>
<li>欧元符号:&euro;</li>
<li>英镑符号:&pound;</li>
<li>日元符号:&yen;</li>
<li>分符号:&cent;</li>
<li>章节符号:&sect;</li>
<li>段落符号:&para;</li>
<li>中间点:&middot;</li>
<li>短破折号:&ndash;</li>
<li>长破折号:&mdash;</li>
</ul>
<p>这是一个包含特殊字符的代码块:</p>
<pre><code>
def escape_example():
print("&lt; &gt; &amp; &quot; &apos; &copy; &reg; &trade; &euro; &pound; &yen; &cent; &sect; &para; &middot; &ndash; &mdash;")
</code></pre>
<p>
这是一个包含转义字符的链接:<a href="https://example.com?q=test&amp;lang=en"
>点击这里</a
>
</p>

结果:

转义字符测试
------------

这是一个包含各种转义字符的段落:

- 小于号:< 
- 大于号:> 
- 和号:& 
- 双引号:" 
- 单引号:' 
- 版权符号:copy 
- 注册商标符号:reg 
- 商标符号:trade 
- 欧元符号:euro 
- 英镑符号:pound 
- 日元符号:yen 
- 分符号:cent 
- 章节符号:sect 
- 段落符号:para 
- 中间点:middot 
- 短破折号:– 
- 长破折号:–

这是一个包含特殊字符的代码块:

1
2
def escape_example():
print("< > & \" ' copy reg trade euro pound yen cent sect para middot -- —")
这是一个包含转义字符的链接:[点击这里](https://example.com?q=test&lang=en) ```

emmm 博客显示原文有点问题 这里截个图:

这个测试重点验证模型对 HTML 转义字符的处理能力。我们构造了一个包含多种转义字符(如 &lt;&gt;&amp; 等)的 HTML 片段,结果显示模型在转换过程中未能正确还原所有转义字符,甚至出现了错误转换(如将 &copy; 转换为 copy)。此外,模型还错误地处理了 <pre> 标签内的内容,导致代码块中的转义字符也被错误地转换。这表明模型在处理转义字符时存在明显的不足,尤其是在需要保留原始格式的场景下,可能会严重影响输出结果的质量。

总结

LLM 在处理许多语言相关任务时表现出色,尤其是在自然语言生成、翻译、摘要等领域,效果往往优于传统方法。

然而,当涉及到 HTML 转 Markdown 这种任务时,当前的 Jina ReaderLM v2 仍然存在不少问题。这些问题不仅体现在结构丢失、符号干扰、注释处理等方面,还表现在对 HTML 和 Markdown 这种相对宽松、自由的结构转换上。

相比于 JSON 等严格结构化的数据转换,HTML 和 Markdown 的灵活性使得转换过程更加复杂,容易受到各种特殊符号、嵌套结构、注释等干扰,导致输出结果不稳定。因此,尽管 ReaderLM v2 在幻觉问题和无限生成问题上有所改进,但在实际应用中,尤其是对结构要求较高的场景下,仍需进一步优化和提升。

还测试了一些正常的页面,比如他例子里给的 yc 官网。对这些页面进行转换后,结果都比较正常,但是这速度是有点慢了,yc 官网不管用 colab(免费版)还是 jina 的 api(也是免费版)都需要将近 1 分钟才能返回,可能是免费版在排队吧,不过如果速度就是这么慢的话,可能只适合小量处理,这个等大佬做了量化之后再看看效果吧。

参考资料

jinaai/ReaderLM-v2

ReaderLM v2:用于 HTML 转 Markdown 和 JSON 的前沿小型语言模型