We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Adding Anthology ID 2021.naacl-srw.21
## Revision or erratum: please add the following information**

- [x] I have attached the revised PDF or erratum to this issue

Hi! I (one of the NAACL SRW chairs) mistakenly omitted this paper when compiling the proceedings. Would it be possible to add it as a new entry `2021.naacl-srw.21` ?

The paper is attached to this issue.
The title is: `Towards Multi-Modal Text-Image Retrieval to improve Human Reading`
The authors are: `Florian Schneider, Özge Alacam, Xintong Wang, Chris Biemann`
[37_Final_Paper_PDF.pdf](https://github.com/acl-org/acl-anthology/files/6704101/37_Final_Paper_PDF.pdf)

Thank you so much!

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `bin/likely_name_split.py`
Content:
```
1 #!/usr/bin/env python3
2 # Daniel Gildea, 2020
3 
4 """Usage: likely_name_split.py [--importdir=DIR]
5 
6 Counts first and last names in anthology.
7 Predicts best split into first and last.
8 Checks whether current names match our predictions.
9 
10 Options:
11   --importdir=DIR          Directory to import XML files from. [default: {scriptdir}/../data/]
12   -h, --help               Display this helpful text.
13 """
14 
15 from collections import defaultdict
16 from docopt import docopt
17 import pickle, json
18 import sys
19 import re
20 import os
21 from math import *
22 
23 from anthology import Anthology
24 from anthology.people import PersonName
25 
26 
27 class NameSplitter:
28     def __init__(self, anthology=None, anthology_dir=None):
29         # counts of how often each name appears
30         self.first_count = defaultdict(lambda: 0)  # "Maria" "Victoria"
31         self.first_full_count = defaultdict(lambda: 0)  # "Maria Victoria"
32         self.last_count = defaultdict(lambda: 0)  # "van" "den" "Bosch"
33         self.last_full_count = defaultdict(lambda: 0)  # "van den Bosch"
34         self.first_total = 0
35         self.last_total = 0
36 
37         if os.path.exists("names.cache"):
38             self.load_cache()
39         else:
40             if anthology is None and anthology_dir is not None:
41                 anthology = Anthology(os.path.join(anthology_dir, "data"))
42             self.count_names(anthology)
43             self.dump_cache()
44 
45     def load_cache(self):
46         with open("names.cache", "r") as cache:
47             p = json.load(cache)
48             self.first_count = defaultdict(int, p["first_count"])
49             self.first_full_count = defaultdict(int, p["first_full_count"])
50             self.first_total = p["first_total"]
51             self.last_count = defaultdict(int, p["last_count"])
52             self.last_full_count = defaultdict(int, p["last_full_count"])
53             self.last_total = p["last_total"]
54         print(f"Loaded cache from names.cache", file=sys.stderr)
55 
56     def dump_cache(self):
57         with open("names.cache", "w") as cache:
58             p = {
59                 "first_count": self.first_count,
60                 "first_full_count": self.first_full_count,
61                 "first_total": self.first_total,
62                 "last_count": self.last_count,
63                 "last_full_count": self.last_full_count,
64                 "last_total": self.last_total,
65             }
66             print(json.dumps(p), file=cache)
67         print(f"Dumped counts to names.cache", file=sys.stderr)
68 
69     # counts names in anthology database into global vars
70     # first_count last_count (dicts)
71     # first_full_count last_full_count (dicts)
72     # first_total last_total (floats)
73     def count_names(self, anthology):
74         for person in anthology.people.personids():
75             name = anthology.people.get_canonical_name(person)
76             num_papers = len(anthology.people.get_papers(person)) + 0.0
77             # print(name.last, ", ", name.first, num_papers)
78             for w in name.first.split(" "):
79                 self.first_count[w] += num_papers
80             self.first_full_count[name.first] += num_papers
81             self.first_total += num_papers
82 
83             for w in name.last.split(" "):
84                 self.last_count[w] += num_papers
85             self.last_full_count[name.last] += num_papers
86             self.last_total += num_papers
87 
88     # takes "Maria Victoria Lopez Gonzalez"
89     # returns ("Lopez Gonzalez", "Maria Victoria")
90     # uses counts of words in first and last names in current database
91     def best_split(self, name):
92         if "," in name and not "Jr." in name:
93             # Short-circuit names that are already split
94             # comma in "William Baumgartner, Jr." does not count as a split
95             surname, given_names = name.split(",")
96             return (surname.strip(), given_names.strip())
97 
98         words = name.split(" ")
99         best_score = -inf
100         best = ("", "")
101         # loop over possible split points between first/last
102         for i in range(1, len(words)):  # at least one word in each part
103             first = " ".join(words[0:i])
104             last = " ".join(words[i:])
105             # max of log prob of "Maria Victoria" and
106             # log prob of "Maria" + log prob of "Victoria"
107             first_probs = [
108                 log((self.first_count[x] + 0.01) / self.first_total) for x in words[0:i]
109             ]
110             first_score = max(
111                 log((self.first_full_count[first] + 0.000001) / self.first_total),
112                 sum(first_probs),
113             )
114             last_probs = [
115                 log((self.last_count[x] + 0.01) / self.last_total) for x in words[i:]
116             ]
117             last_score = max(
118                 log((self.last_full_count[last] + 0.000001) / self.last_total),
119                 sum(last_probs),
120             )
121 
122             if first_score + last_score > best_score:
123                 best_score = first_score + last_score
124                 best = (last, first)
125             # end of loop over split points
126         return best
127 
128 
129 if __name__ == "__main__":
130     args = docopt(__doc__)
131     scriptdir = os.path.dirname(os.path.abspath(__file__))
132     if "{scriptdir}" in args["--importdir"]:
133         args["--importdir"] = os.path.abspath(
134             args["--importdir"].format(scriptdir=scriptdir)
135         )
136 
137     anthology = Anthology(importdir=args["--importdir"])
138     splitter = NameSplitter(anthology)
139 
140     # for all names currently in anthology,
141     # see if they match what we predict
142     for person in anthology.people.personids():
143         name = anthology.people.get_canonical_name(person)
144 
145         # find our prediction of split
146         best = splitter.best_split(name.first + " " + name.last)
147 
148         # if current split does not match our prediction
149         if not (best[0] == name.last and best[1] == name.first):
150             # print suggested replacement
151             print(name.last, ",", name.first, "  ==>  ", best[0], ",", best[1])
152
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/bin/likely_name_split.py b/bin/likely_name_split.py
--- a/bin/likely_name_split.py
+++ b/bin/likely_name_split.py
@@ -24,6 +24,13 @@
 from anthology.people import PersonName
 
 
+def log0(x):
+    if x == 0:
+        return -inf
+    else:
+        return log(x)
+
+
 class NameSplitter:
     def __init__(self, anthology=None, anthology_dir=None):
         # counts of how often each name appears
@@ -105,18 +112,21 @@
             # max of log prob of "Maria Victoria" and
             # log prob of "Maria" + log prob of "Victoria"
             first_probs = [
-                log((self.first_count[x] + 0.01) / self.first_total) for x in words[0:i]
+                # more smoothing for first than last name,
+                # so that default is one-word last name when all counts are zero
+                log((self.first_count[x] + 0.1) / self.first_total)
+                for x in words[0:i]
             ]
             first_score = max(
-                log((self.first_full_count[first] + 0.000001) / self.first_total),
+                # no smoothing for multiword name: log(0) => -inf
+                log0((self.first_full_count[first]) / self.first_total),
                 sum(first_probs),
             )
             last_probs = [
                 log((self.last_count[x] + 0.01) / self.last_total) for x in words[i:]
             ]
             last_score = max(
-                log((self.last_full_count[last] + 0.000001) / self.last_total),
-                sum(last_probs),
+                log0((self.last_full_count[last]) / self.last_total), sum(last_probs)
             )
 
             if first_score + last_score > best_score:

{"golden_diff": "diff --git a/bin/likely_name_split.py b/bin/likely_name_split.py\n--- a/bin/likely_name_split.py\n+++ b/bin/likely_name_split.py\n@@ -24,6 +24,13 @@\n from anthology.people import PersonName\n \n \n+def log0(x):\n+    if x == 0:\n+        return -inf\n+    else:\n+        return log(x)\n+\n+\n class NameSplitter:\n     def __init__(self, anthology=None, anthology_dir=None):\n         # counts of how often each name appears\n@@ -105,18 +112,21 @@\n             # max of log prob of \"Maria Victoria\" and\n             # log prob of \"Maria\" + log prob of \"Victoria\"\n             first_probs = [\n-                log((self.first_count[x] + 0.01) / self.first_total) for x in words[0:i]\n+                # more smoothing for first than last name,\n+                # so that default is one-word last name when all counts are zero\n+                log((self.first_count[x] + 0.1) / self.first_total)\n+                for x in words[0:i]\n             ]\n             first_score = max(\n-                log((self.first_full_count[first] + 0.000001) / self.first_total),\n+                # no smoothing for multiword name: log(0) => -inf\n+                log0((self.first_full_count[first]) / self.first_total),\n                 sum(first_probs),\n             )\n             last_probs = [\n                 log((self.last_count[x] + 0.01) / self.last_total) for x in words[i:]\n             ]\n             last_score = max(\n-                log((self.last_full_count[last] + 0.000001) / self.last_total),\n-                sum(last_probs),\n+                log0((self.last_full_count[last]) / self.last_total), sum(last_probs)\n             )\n \n             if first_score + last_score > best_score:\n", "issue": "Adding Anthology ID 2021.naacl-srw.21\n## Revision or erratum: please add the following information**\r\n\r\n- [x] I have attached the revised PDF or erratum to this issue\r\n\r\nHi! I (one of the NAACL SRW chairs) mistakenly omitted this paper when compiling the proceedings. Would it be possible to add it as a new entry `2021.naacl-srw.21` ?\r\n\r\nThe paper is attached to this issue.\r\nThe title is: `Towards Multi-Modal Text-Image Retrieval to improve Human Reading`\r\nThe authors are: `Florian Schneider, \u00d6zge Alacam, Xintong Wang, Chris Biemann`\r\n[37_Final_Paper_PDF.pdf](https://github.com/acl-org/acl-anthology/files/6704101/37_Final_Paper_PDF.pdf)\r\n\r\nThank you so much!\n", "before_files": [{"content": "#!/usr/bin/env python3\n# Daniel Gildea, 2020\n\n\"\"\"Usage: likely_name_split.py [--importdir=DIR]\n\nCounts first and last names in anthology.\nPredicts best split into first and last.\nChecks whether current names match our predictions.\n\nOptions:\n  --importdir=DIR          Directory to import XML files from. [default: {scriptdir}/../data/]\n  -h, --help               Display this helpful text.\n\"\"\"\n\nfrom collections import defaultdict\nfrom docopt import docopt\nimport pickle, json\nimport sys\nimport re\nimport os\nfrom math import *\n\nfrom anthology import Anthology\nfrom anthology.people import PersonName\n\n\nclass NameSplitter:\n    def __init__(self, anthology=None, anthology_dir=None):\n        # counts of how often each name appears\n        self.first_count = defaultdict(lambda: 0)  # \"Maria\" \"Victoria\"\n        self.first_full_count = defaultdict(lambda: 0)  # \"Maria Victoria\"\n        self.last_count = defaultdict(lambda: 0)  # \"van\" \"den\" \"Bosch\"\n        self.last_full_count = defaultdict(lambda: 0)  # \"van den Bosch\"\n        self.first_total = 0\n        self.last_total = 0\n\n        if os.path.exists(\"names.cache\"):\n            self.load_cache()\n        else:\n            if anthology is None and anthology_dir is not None:\n                anthology = Anthology(os.path.join(anthology_dir, \"data\"))\n            self.count_names(anthology)\n            self.dump_cache()\n\n    def load_cache(self):\n        with open(\"names.cache\", \"r\") as cache:\n            p = json.load(cache)\n            self.first_count = defaultdict(int, p[\"first_count\"])\n            self.first_full_count = defaultdict(int, p[\"first_full_count\"])\n            self.first_total = p[\"first_total\"]\n            self.last_count = defaultdict(int, p[\"last_count\"])\n            self.last_full_count = defaultdict(int, p[\"last_full_count\"])\n            self.last_total = p[\"last_total\"]\n        print(f\"Loaded cache from names.cache\", file=sys.stderr)\n\n    def dump_cache(self):\n        with open(\"names.cache\", \"w\") as cache:\n            p = {\n                \"first_count\": self.first_count,\n                \"first_full_count\": self.first_full_count,\n                \"first_total\": self.first_total,\n                \"last_count\": self.last_count,\n                \"last_full_count\": self.last_full_count,\n                \"last_total\": self.last_total,\n            }\n            print(json.dumps(p), file=cache)\n        print(f\"Dumped counts to names.cache\", file=sys.stderr)\n\n    # counts names in anthology database into global vars\n    # first_count last_count (dicts)\n    # first_full_count last_full_count (dicts)\n    # first_total last_total (floats)\n    def count_names(self, anthology):\n        for person in anthology.people.personids():\n            name = anthology.people.get_canonical_name(person)\n            num_papers = len(anthology.people.get_papers(person)) + 0.0\n            # print(name.last, \", \", name.first, num_papers)\n            for w in name.first.split(\" \"):\n                self.first_count[w] += num_papers\n            self.first_full_count[name.first] += num_papers\n            self.first_total += num_papers\n\n            for w in name.last.split(\" \"):\n                self.last_count[w] += num_papers\n            self.last_full_count[name.last] += num_papers\n            self.last_total += num_papers\n\n    # takes \"Maria Victoria Lopez Gonzalez\"\n    # returns (\"Lopez Gonzalez\", \"Maria Victoria\")\n    # uses counts of words in first and last names in current database\n    def best_split(self, name):\n        if \",\" in name and not \"Jr.\" in name:\n            # Short-circuit names that are already split\n            # comma in \"William Baumgartner, Jr.\" does not count as a split\n            surname, given_names = name.split(\",\")\n            return (surname.strip(), given_names.strip())\n\n        words = name.split(\" \")\n        best_score = -inf\n        best = (\"\", \"\")\n        # loop over possible split points between first/last\n        for i in range(1, len(words)):  # at least one word in each part\n            first = \" \".join(words[0:i])\n            last = \" \".join(words[i:])\n            # max of log prob of \"Maria Victoria\" and\n            # log prob of \"Maria\" + log prob of \"Victoria\"\n            first_probs = [\n                log((self.first_count[x] + 0.01) / self.first_total) for x in words[0:i]\n            ]\n            first_score = max(\n                log((self.first_full_count[first] + 0.000001) / self.first_total),\n                sum(first_probs),\n            )\n            last_probs = [\n                log((self.last_count[x] + 0.01) / self.last_total) for x in words[i:]\n            ]\n            last_score = max(\n                log((self.last_full_count[last] + 0.000001) / self.last_total),\n                sum(last_probs),\n            )\n\n            if first_score + last_score > best_score:\n                best_score = first_score + last_score\n                best = (last, first)\n            # end of loop over split points\n        return best\n\n\nif __name__ == \"__main__\":\n    args = docopt(__doc__)\n    scriptdir = os.path.dirname(os.path.abspath(__file__))\n    if \"{scriptdir}\" in args[\"--importdir\"]:\n        args[\"--importdir\"] = os.path.abspath(\n            args[\"--importdir\"].format(scriptdir=scriptdir)\n        )\n\n    anthology = Anthology(importdir=args[\"--importdir\"])\n    splitter = NameSplitter(anthology)\n\n    # for all names currently in anthology,\n    # see if they match what we predict\n    for person in anthology.people.personids():\n        name = anthology.people.get_canonical_name(person)\n\n        # find our prediction of split\n        best = splitter.best_split(name.first + \" \" + name.last)\n\n        # if current split does not match our prediction\n        if not (best[0] == name.last and best[1] == name.first):\n            # print suggested replacement\n            print(name.last, \",\", name.first, \"  ==>  \", best[0], \",\", best[1])\n", "path": "bin/likely_name_split.py"}], "after_files": [{"content": "#!/usr/bin/env python3\n# Daniel Gildea, 2020\n\n\"\"\"Usage: likely_name_split.py [--importdir=DIR]\n\nCounts first and last names in anthology.\nPredicts best split into first and last.\nChecks whether current names match our predictions.\n\nOptions:\n  --importdir=DIR          Directory to import XML files from. [default: {scriptdir}/../data/]\n  -h, --help               Display this helpful text.\n\"\"\"\n\nfrom collections import defaultdict\nfrom docopt import docopt\nimport pickle, json\nimport sys\nimport re\nimport os\nfrom math import *\n\nfrom anthology import Anthology\nfrom anthology.people import PersonName\n\n\ndef log0(x):\n    if x == 0:\n        return -inf\n    else:\n        return log(x)\n\n\nclass NameSplitter:\n    def __init__(self, anthology=None, anthology_dir=None):\n        # counts of how often each name appears\n        self.first_count = defaultdict(lambda: 0)  # \"Maria\" \"Victoria\"\n        self.first_full_count = defaultdict(lambda: 0)  # \"Maria Victoria\"\n        self.last_count = defaultdict(lambda: 0)  # \"van\" \"den\" \"Bosch\"\n        self.last_full_count = defaultdict(lambda: 0)  # \"van den Bosch\"\n        self.first_total = 0\n        self.last_total = 0\n\n        if os.path.exists(\"names.cache\"):\n            self.load_cache()\n        else:\n            if anthology is None and anthology_dir is not None:\n                anthology = Anthology(os.path.join(anthology_dir, \"data\"))\n            self.count_names(anthology)\n            self.dump_cache()\n\n    def load_cache(self):\n        with open(\"names.cache\", \"r\") as cache:\n            p = json.load(cache)\n            self.first_count = defaultdict(int, p[\"first_count\"])\n            self.first_full_count = defaultdict(int, p[\"first_full_count\"])\n            self.first_total = p[\"first_total\"]\n            self.last_count = defaultdict(int, p[\"last_count\"])\n            self.last_full_count = defaultdict(int, p[\"last_full_count\"])\n            self.last_total = p[\"last_total\"]\n        print(f\"Loaded cache from names.cache\", file=sys.stderr)\n\n    def dump_cache(self):\n        with open(\"names.cache\", \"w\") as cache:\n            p = {\n                \"first_count\": self.first_count,\n                \"first_full_count\": self.first_full_count,\n                \"first_total\": self.first_total,\n                \"last_count\": self.last_count,\n                \"last_full_count\": self.last_full_count,\n                \"last_total\": self.last_total,\n            }\n            print(json.dumps(p), file=cache)\n        print(f\"Dumped counts to names.cache\", file=sys.stderr)\n\n    # counts names in anthology database into global vars\n    # first_count last_count (dicts)\n    # first_full_count last_full_count (dicts)\n    # first_total last_total (floats)\n    def count_names(self, anthology):\n        for person in anthology.people.personids():\n            name = anthology.people.get_canonical_name(person)\n            num_papers = len(anthology.people.get_papers(person)) + 0.0\n            # print(name.last, \", \", name.first, num_papers)\n            for w in name.first.split(\" \"):\n                self.first_count[w] += num_papers\n            self.first_full_count[name.first] += num_papers\n            self.first_total += num_papers\n\n            for w in name.last.split(\" \"):\n                self.last_count[w] += num_papers\n            self.last_full_count[name.last] += num_papers\n            self.last_total += num_papers\n\n    # takes \"Maria Victoria Lopez Gonzalez\"\n    # returns (\"Lopez Gonzalez\", \"Maria Victoria\")\n    # uses counts of words in first and last names in current database\n    def best_split(self, name):\n        if \",\" in name and not \"Jr.\" in name:\n            # Short-circuit names that are already split\n            # comma in \"William Baumgartner, Jr.\" does not count as a split\n            surname, given_names = name.split(\",\")\n            return (surname.strip(), given_names.strip())\n\n        words = name.split(\" \")\n        best_score = -inf\n        best = (\"\", \"\")\n        # loop over possible split points between first/last\n        for i in range(1, len(words)):  # at least one word in each part\n            first = \" \".join(words[0:i])\n            last = \" \".join(words[i:])\n            # max of log prob of \"Maria Victoria\" and\n            # log prob of \"Maria\" + log prob of \"Victoria\"\n            first_probs = [\n                # more smoothing for first than last name,\n                # so that default is one-word last name when all counts are zero\n                log((self.first_count[x] + 0.1) / self.first_total)\n                for x in words[0:i]\n            ]\n            first_score = max(\n                # no smoothing for multiword name: log(0) => -inf\n                log0((self.first_full_count[first]) / self.first_total),\n                sum(first_probs),\n            )\n            last_probs = [\n                log((self.last_count[x] + 0.01) / self.last_total) for x in words[i:]\n            ]\n            last_score = max(\n                log0((self.last_full_count[last]) / self.last_total), sum(last_probs)\n            )\n\n            if first_score + last_score > best_score:\n                best_score = first_score + last_score\n                best = (last, first)\n            # end of loop over split points\n        return best\n\n\nif __name__ == \"__main__\":\n    args = docopt(__doc__)\n    scriptdir = os.path.dirname(os.path.abspath(__file__))\n    if \"{scriptdir}\" in args[\"--importdir\"]:\n        args[\"--importdir\"] = os.path.abspath(\n            args[\"--importdir\"].format(scriptdir=scriptdir)\n        )\n\n    anthology = Anthology(importdir=args[\"--importdir\"])\n    splitter = NameSplitter(anthology)\n\n    # for all names currently in anthology,\n    # see if they match what we predict\n    for person in anthology.people.personids():\n        name = anthology.people.get_canonical_name(person)\n\n        # find our prediction of split\n        best = splitter.best_split(name.first + \" \" + name.last)\n\n        # if current split does not match our prediction\n        if not (best[0] == name.last and best[1] == name.first):\n            # print suggested replacement\n            print(name.last, \",\", name.first, \"  ==>  \", best[0], \",\", best[1])\n", "path": "bin/likely_name_split.py"}]}