kholdrex commited on
Commit
ba9518e
·
verified ·
1 Parent(s): 7280cef

ROUGE metric computed with rouge-score-rs

Browse files
Files changed (4) hide show
  1. LICENSE +202 -0
  2. README.md +143 -5
  3. index.html +33 -18
  4. rouge.py +172 -0
LICENSE ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
README.md CHANGED
@@ -1,10 +1,148 @@
1
  ---
2
- title: Rouge
3
- emoji: 📚
4
- colorFrom: purple
5
- colorTo: blue
6
  sdk: static
 
7
  pinned: false
 
 
 
 
 
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: ROUGE (rouge-score-rs)
3
+ emoji: 🦀
4
+ colorFrom: blue
5
+ colorTo: red
6
  sdk: static
7
+ app_file: index.html
8
  pinned: false
9
+ license: apache-2.0
10
+ tags:
11
+ - evaluate
12
+ - metric
13
+ description: >-
14
+ ROUGE computed with rouge-score-rs, a Rust implementation of Google's rouge-score.
15
+ Same inputs, options and scores as the `rouge` metric, computed faster.
16
  ---
17
 
18
+ # Metric Card for ROUGE (rouge-score-rs)
19
+
20
+ ## Metric Description
21
+ ROUGE, or Recall-Oriented Understudy for Gisting Evaluation, is a set of metrics and a software package used for evaluating automatic summarization and machine translation software in natural language processing. The metrics compare an automatically produced summary or translation against a reference or a set of references (human-produced) summary or translation.
22
+
23
+ Note that ROUGE is case insensitive, meaning that upper case letters are treated the same way as lower case letters.
24
+
25
+ This metric has the same inputs, options and outputs as the [`rouge`](https://huggingface.co/spaces/evaluate-metric/rouge) metric and, for the inputs listed under [Compatibility](#compatibility), returns identical scores. It computes them with [`rouge-score-rs`](https://pypi.org/project/rouge-score-rs/) ([source](https://github.com/SyntaxSpirits/rougers)), a Rust implementation of the [Google Research reimplementation of ROUGE](https://github.com/google-research/google-research/tree/master/rouge), instead of the pure Python `rouge-score` package.
26
+
27
+ This Space is maintained by SyntaxSpirits and is not affiliated with Google or Hugging Face. It is derived from the Apache-2.0 [`evaluate-metric/rouge`](https://huggingface.co/spaces/evaluate-metric/rouge) Space by the HuggingFace Evaluate Authors; see [LICENSE](LICENSE).
28
+
29
+ Install the dependencies before loading the metric (tested with `rouge-score-rs` 0.1.1):
30
+
31
+ ```bash
32
+ pip install evaluate 'rouge-score-rs[aggregate]>=0.1.1'
33
+ ```
34
+
35
+ ## How to Use
36
+ At minimum, this metric takes as input a list of predictions and a list of references:
37
+ ```python
38
+ >>> import evaluate
39
+ >>> rouge = evaluate.load('SyntaxSpirits/rouge')
40
+ >>> predictions = ["hello there", "general kenobi"]
41
+ >>> references = ["hello there", "general kenobi"]
42
+ >>> results = rouge.compute(predictions=predictions,
43
+ ... references=references)
44
+ >>> print({key: round(value, 4) for key, value in results.items()})
45
+ {'rouge1': 1.0, 'rouge2': 1.0, 'rougeL': 1.0, 'rougeLsum': 1.0}
46
+ ```
47
+
48
+ One can also pass a custom tokenizer, which is especially useful for non-Latin languages: the default tokenizer keeps only the ASCII letters `a`–`z` and digits.
49
+ ```python
50
+ >>> results = rouge.compute(predictions=predictions,
51
+ ... references=references,
52
+ ... tokenizer=lambda x: x.split())
53
+ >>> print({key: round(value, 4) for key, value in results.items()})
54
+ {'rouge1': 1.0, 'rouge2': 1.0, 'rougeL': 1.0, 'rougeLsum': 1.0}
55
+ ```
56
+
57
+ It can also deal with lists of references for each prediction. For every ROUGE type, the reference with the highest F1 is used:
58
+ ```python
59
+ >>> rouge = evaluate.load('SyntaxSpirits/rouge', seed=0)
60
+ >>> predictions = ["hello there", "general kenobi"]
61
+ >>> references = [["hello", "there"], ["general kenobi", "general yoda"]]
62
+ >>> results = rouge.compute(predictions=predictions,
63
+ ... references=references)
64
+ >>> print({key: round(value, 4) for key, value in results.items()})
65
+ {'rouge1': 0.8333, 'rouge2': 0.5, 'rougeL': 0.8333, 'rougeLsum': 0.8333}
66
+ ```
67
+
68
+ ### Inputs
69
+ - **predictions** (`list` of `str`): predictions to score.
70
+ - **references** (`list` of `str` or `list` of `list` of `str`): one reference per prediction, or several references per prediction.
71
+ - **rouge_types** (`list`): ROUGE types to calculate. Defaults to `['rouge1', 'rouge2', 'rougeL', 'rougeLsum']`.
72
+ - `"rouge1"` to `"rouge9"`: n-gram based scoring, e.g. `"rouge2"` for bigrams.
73
+ - `"rougeL"`: longest common subsequence based scoring.
74
+ - `"rougeLsum"`: summary-level longest common subsequence; sentences are separated by `"\n"`. See [here](https://github.com/huggingface/datasets/issues/617) for more information.
75
+ - **use_aggregator** (`boolean`): if `True`, returns aggregated scores. Defaults to `True`.
76
+ - **use_stemmer** (`boolean`): if `True`, the default tokenizer applies the Porter stemmer to tokens longer than three characters. Defaults to `False`.
77
+ - **tokenizer** (callable, optional): a function that splits a string into a list of string tokens. Lowercasing and stemming are done only by the default tokenizer.
78
+
79
+ ### Output Values
80
+ The output is a dictionary with one entry for each ROUGE type in `rouge_types`; each value is an F1 score between 0 and 1.
81
+
82
+ If `use_aggregator=True` (the default), each entry is the median of 1,000 bootstrap means of the per-prediction F1 scores, as in the `rouge` metric. The bootstrap uses NumPy's random state; pass `seed` to `evaluate.load` to make it reproducible and comparable with the `rouge` metric loaded with the same seed.
83
+
84
+ If `use_aggregator=False`, each entry is a list with one F1 score per prediction.
85
+
86
+ ### Examples
87
+ An example without aggregation:
88
+ ```python
89
+ >>> rouge = evaluate.load('SyntaxSpirits/rouge')
90
+ >>> predictions = ["hello goodbye", "ankh morpork"]
91
+ >>> references = ["goodbye", "general kenobi"]
92
+ >>> results = rouge.compute(predictions=predictions,
93
+ ... references=references,
94
+ ... use_aggregator=False)
95
+ >>> print(list(results.keys()))
96
+ ['rouge1', 'rouge2', 'rougeL', 'rougeLsum']
97
+ >>> print([round(score, 4) for score in results["rouge1"]])
98
+ [0.6667, 0.0]
99
+ ```
100
+
101
+ The same example, but with aggregation:
102
+ ```python
103
+ >>> rouge = evaluate.load('SyntaxSpirits/rouge', seed=0)
104
+ >>> results = rouge.compute(predictions=predictions,
105
+ ... references=references,
106
+ ... use_aggregator=True)
107
+ >>> print(round(results["rouge1"], 4))
108
+ 0.3333
109
+ ```
110
+
111
+ The same example, but only calculating `rouge1`:
112
+ ```python
113
+ >>> results = rouge.compute(predictions=predictions,
114
+ ... references=references,
115
+ ... rouge_types=['rouge1'])
116
+ >>> print({key: round(value, 4) for key, value in results.items()})
117
+ {'rouge1': 0.3333}
118
+ ```
119
+
120
+ ## Compatibility
121
+ Scores are bit-for-bit identical to the `rouge` metric for string inputs with the default tokenizer, with or without stemming, and with custom tokenizers that return lists of strings. This is checked against `rouge-score` 0.1.2 by the [rouge-score-rs test suite](https://github.com/SyntaxSpirits/rougers#compatibility) and, for this metric, by comparing both metrics with the same seed on thousands of random examples.
122
+
123
+ Differences from the `rouge` metric:
124
+ - Tokens returned by a custom tokenizer must be hashable, such as strings.
125
+ - An unknown ROUGE type raises `ValueError` when the scorer is created, and malformed inputs (for example `None` instead of a string) can raise a different exception type.
126
+
127
+ ## Speed
128
+ Pair scoring runs in Rust. With the default tokenizer and one reference per prediction, all pairs are scored in one call that uses every CPU core unless `RAYON_NUM_THREADS` limits it (in a process forked after such a call, pairs are scored on one thread). Aggregation still runs the same NumPy bootstrap as the `rouge` metric, so it benefits less.
129
+
130
+ ## Limitations and Bias
131
+ See [Schluter (2017)](https://aclanthology.org/E17-2007/) for an in-depth discussion of many of ROUGE's limits.
132
+
133
+ ## Citation
134
+ ```bibtex
135
+ @inproceedings{lin-2004-rouge,
136
+ title = "{ROUGE}: A Package for Automatic Evaluation of Summaries",
137
+ author = "Lin, Chin-Yew",
138
+ booktitle = "Text Summarization Branches Out",
139
+ month = jul,
140
+ year = "2004",
141
+ address = "Barcelona, Spain",
142
+ publisher = "Association for Computational Linguistics",
143
+ url = "https://www.aclweb.org/anthology/W04-1013",
144
+ pages = "74--81",
145
+ }
146
+ ```
147
+
148
+ ## Further References
index.html CHANGED
@@ -1,19 +1,34 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </html>
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>ROUGE (rouge-score-rs)</title>
7
+ <style>
8
+ body { font-family: system-ui, -apple-system, sans-serif; max-width: 760px; margin: 40px auto; padding: 0 20px; line-height: 1.55; color: #1f2328; }
9
+ pre { background: #f6f8fa; padding: 14px 16px; border-radius: 6px; overflow-x: auto; }
10
+ code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.92em; }
11
+ a { color: #0969da; }
12
+ </style>
13
+ </head>
14
+ <body>
15
+ <h1>ROUGE (rouge-score-rs)</h1>
16
+ <p>An <a href="https://huggingface.co/docs/evaluate">Evaluate</a> metric with the same inputs, options and scores as
17
+ <a href="https://huggingface.co/spaces/evaluate-metric/rouge"><code>rouge</code></a>, computed with
18
+ <a href="https://pypi.org/project/rouge-score-rs/">rouge-score-rs</a>, a Rust implementation of Google's
19
+ <code>rouge-score</code>.</p>
20
+ <pre><code>pip install evaluate 'rouge-score-rs[aggregate]&gt;=0.1.1'</code></pre>
21
+ <pre><code>import evaluate
22
+
23
+ rouge = evaluate.load("SyntaxSpirits/rouge")
24
+ results = rouge.compute(
25
+ predictions=["hello there", "general kenobi"],
26
+ references=["hello there", "general kenobi"],
27
+ )
28
+ print(results) # {'rouge1': 1.0, 'rouge2': 1.0, 'rougeL': 1.0, 'rougeLsum': 1.0}</code></pre>
29
+ <p>Inputs, outputs, compatibility notes and examples are in the
30
+ <a href="https://huggingface.co/spaces/SyntaxSpirits/rouge/blob/main/README.md">metric card</a>.
31
+ Source code: <a href="https://github.com/SyntaxSpirits/rougers">SyntaxSpirits/rougers</a>.
32
+ Not affiliated with Google or Hugging Face.</p>
33
+ </body>
34
  </html>
rouge.py ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2020 The HuggingFace Evaluate Authors.
2
+ # Modified in 2026 by SyntaxSpirits: scores with rouge-score-rs instead of rouge-score.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ """ ROUGE metric computed with rouge-score-rs, a Rust implementation of Google's rouge-score. """
16
+
17
+ import datasets
18
+ import numpy # Here to have a nice missing dependency error message early on
19
+ import rouge_score_rs
20
+ from packaging import version
21
+ from rouge_score_rs import rouge_scorer, scoring
22
+
23
+ import evaluate
24
+
25
+
26
+ if version.parse(rouge_score_rs.__version__) < version.parse("0.1.1"):
27
+ raise ImportError("This metric requires rouge-score-rs>=0.1.1: pip install -U 'rouge-score-rs[aggregate]>=0.1.1'")
28
+
29
+
30
+ _CITATION = """\
31
+ @inproceedings{lin-2004-rouge,
32
+ title = "{ROUGE}: A Package for Automatic Evaluation of Summaries",
33
+ author = "Lin, Chin-Yew",
34
+ booktitle = "Text Summarization Branches Out",
35
+ month = jul,
36
+ year = "2004",
37
+ address = "Barcelona, Spain",
38
+ publisher = "Association for Computational Linguistics",
39
+ url = "https://www.aclweb.org/anthology/W04-1013",
40
+ pages = "74--81",
41
+ }
42
+ """
43
+
44
+ _DESCRIPTION = """\
45
+ ROUGE, or Recall-Oriented Understudy for Gisting Evaluation, is a set of metrics and a software package used for
46
+ evaluating automatic summarization and machine translation software in natural language processing.
47
+ The metrics compare an automatically produced summary or translation against a reference or a set of references (human-produced) summary or translation.
48
+
49
+ With the default tokenizer, ROUGE is case insensitive, meaning that upper case letters are treated the same way as
50
+ lower case letters.
51
+
52
+ This metric uses rouge-score-rs (https://github.com/SyntaxSpirits/rougers), a Rust implementation of
53
+ Google Research's reimplementation of ROUGE (https://github.com/google-research/google-research/tree/master/rouge).
54
+ It gives the same scores as the `rouge` metric for string inputs and tokenizers that return lists of strings,
55
+ and computes them faster.
56
+ """
57
+
58
+ _KWARGS_DESCRIPTION = """
59
+ Calculates ROUGE F1 scores for a list of predictions and references.
60
+ Args:
61
+ predictions: list of predictions to score, as strings.
62
+ references: list with one reference string per prediction, or a list of reference strings per prediction.
63
+ With several references, the one with the highest F1 is used for each ROUGE type.
64
+ rouge_types: A list of rouge types to calculate.
65
+ Valid names:
66
+ `"rouge{n}"` for n from 1 to 9 (e.g. `"rouge1"`, `"rouge2"`): n-gram based scoring,
67
+ `"rougeL"`: Longest common subsequence based scoring.
68
+ `"rougeLsum"`: rougeLsum splits text using `"\n"`.
69
+ See details in https://github.com/huggingface/datasets/issues/617
70
+ use_stemmer: Bool indicating whether the default tokenizer should apply the Porter stemmer.
71
+ use_aggregator: If True, return for each ROUGE type the median of 1,000 bootstrap means of the
72
+ per-prediction scores (pass `seed` to `evaluate.load` for reproducible values); if False, return
73
+ one score per prediction.
74
+ tokenizer: Optional callable splitting a string into a list of string tokens. Lowercasing and
75
+ stemming are only done by the default tokenizer.
76
+ Returns:
77
+ rouge1: rouge_1 (f1),
78
+ rouge2: rouge_2 (f1),
79
+ rougeL: rouge_l (f1),
80
+ rougeLsum: rouge_lsum (f1)
81
+ Examples:
82
+
83
+ >>> rouge = evaluate.load('SyntaxSpirits/rouge')
84
+ >>> predictions = ["hello there", "general kenobi"]
85
+ >>> references = ["hello there", "general kenobi"]
86
+ >>> results = rouge.compute(predictions=predictions, references=references)
87
+ >>> print(results)
88
+ {'rouge1': 1.0, 'rouge2': 1.0, 'rougeL': 1.0, 'rougeLsum': 1.0}
89
+ """
90
+
91
+
92
+ class Tokenizer:
93
+ """Helper class to wrap a callable into a class with a `tokenize` method as used by rouge-score."""
94
+
95
+ def __init__(self, tokenizer_func):
96
+ self.tokenizer_func = tokenizer_func
97
+
98
+ def tokenize(self, text):
99
+ return self.tokenizer_func(text)
100
+
101
+
102
+ @evaluate.utils.file_utils.add_start_docstrings(_DESCRIPTION, _KWARGS_DESCRIPTION)
103
+ class Rouge(evaluate.Metric):
104
+ def _info(self):
105
+ return evaluate.MetricInfo(
106
+ description=_DESCRIPTION,
107
+ citation=_CITATION,
108
+ inputs_description=_KWARGS_DESCRIPTION,
109
+ features=[
110
+ datasets.Features(
111
+ {
112
+ "predictions": datasets.Value("string", id="sequence"),
113
+ "references": datasets.Sequence(datasets.Value("string", id="sequence")),
114
+ }
115
+ ),
116
+ datasets.Features(
117
+ {
118
+ "predictions": datasets.Value("string", id="sequence"),
119
+ "references": datasets.Value("string", id="sequence"),
120
+ }
121
+ ),
122
+ ],
123
+ codebase_urls=[
124
+ "https://huggingface.co/spaces/SyntaxSpirits/rouge",
125
+ "https://github.com/SyntaxSpirits/rougers",
126
+ "https://github.com/google-research/google-research/tree/master/rouge",
127
+ ],
128
+ reference_urls=[
129
+ "https://en.wikipedia.org/wiki/ROUGE_(metric)",
130
+ "https://github.com/google-research/google-research/tree/master/rouge",
131
+ ],
132
+ )
133
+
134
+ def _compute(
135
+ self, predictions, references, rouge_types=None, use_aggregator=True, use_stemmer=False, tokenizer=None
136
+ ):
137
+ if rouge_types is None:
138
+ rouge_types = ["rouge1", "rouge2", "rougeL", "rougeLsum"]
139
+
140
+ multi_ref = isinstance(references[0], list)
141
+
142
+ if tokenizer is not None:
143
+ tokenizer = Tokenizer(tokenizer)
144
+
145
+ scorer = rouge_scorer.RougeScorer(rouge_types=rouge_types, use_stemmer=use_stemmer, tokenizer=tokenizer)
146
+ if use_aggregator:
147
+ aggregator = scoring.BootstrapAggregator()
148
+ else:
149
+ scores = []
150
+
151
+ if multi_ref:
152
+ all_scores = (scorer.score_multi(ref, pred) for ref, pred in zip(references, predictions))
153
+ else:
154
+ all_scores = scorer.score_batch(references, predictions)
155
+
156
+ for score in all_scores:
157
+ if use_aggregator:
158
+ aggregator.add_scores(score)
159
+ else:
160
+ scores.append(score)
161
+
162
+ if use_aggregator:
163
+ result = aggregator.aggregate()
164
+ for key in result:
165
+ result[key] = result[key].mid.fmeasure
166
+
167
+ else:
168
+ result = {}
169
+ for key in scores[0]:
170
+ result[key] = list(score[key].fmeasure for score in scores)
171
+
172
+ return result