We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Use information on how a bug is filed as a feature
This could be especially useful for the Spam model.

https://bugzilla.mozilla.org/show_bug.cgi?id=1565403

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `bugbug/models/spambug.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 # This Source Code Form is subject to the terms of the Mozilla Public
3 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
4 # You can obtain one at http://mozilla.org/MPL/2.0/.
5 
6 import xgboost
7 from imblearn.over_sampling import BorderlineSMOTE
8 from sklearn.compose import ColumnTransformer
9 from sklearn.feature_extraction import DictVectorizer
10 from sklearn.pipeline import Pipeline
11 
12 from bugbug import bug_features, bugzilla, feature_cleanup, utils
13 from bugbug.model import BugModel
14 
15 
16 class SpamBugModel(BugModel):
17     def __init__(self, lemmatization=False):
18         BugModel.__init__(self, lemmatization)
19 
20         self.sampler = BorderlineSMOTE(random_state=0)
21         self.calculate_importance = False
22 
23         feature_extractors = [
24             bug_features.has_str(),
25             bug_features.has_regression_range(),
26             bug_features.severity(),
27             bug_features.has_crash_signature(),
28             bug_features.has_url(),
29             bug_features.whiteboard(),
30             bug_features.product(),
31             # TODO: We would like to use the component at the time of filing too,
32             # but we can't because the rollback script doesn't support changes to
33             # components yet.
34             # bug_features.component(),
35             bug_features.num_words_title(),
36             bug_features.num_words_comments(),
37             bug_features.keywords(),
38             bug_features.priority(),
39             bug_features.version(),
40             bug_features.target_milestone(),
41             bug_features.has_attachment(),
42             bug_features.platform(),
43             bug_features.op_sys(),
44         ]
45 
46         cleanup_functions = [
47             feature_cleanup.fileref(),
48             feature_cleanup.url(),
49             feature_cleanup.synonyms(),
50         ]
51 
52         self.extraction_pipeline = Pipeline(
53             [
54                 (
55                     "bug_extractor",
56                     bug_features.BugExtractor(
57                         feature_extractors, cleanup_functions, rollback=True
58                     ),
59                 ),
60                 (
61                     "union",
62                     ColumnTransformer(
63                         [
64                             ("data", DictVectorizer(), "data"),
65                             ("title", self.text_vectorizer(min_df=0.0001), "title"),
66                             (
67                                 "comments",
68                                 self.text_vectorizer(min_df=0.0001),
69                                 "comments",
70                             ),
71                         ]
72                     ),
73                 ),
74             ]
75         )
76 
77         self.clf = xgboost.XGBClassifier(n_jobs=utils.get_physical_cpu_count())
78         self.clf.set_params(predictor="cpu_predictor")
79 
80     def get_labels(self):
81         classes = {}
82 
83         for bug_data in bugzilla.get_bugs(include_invalid=True):
84             bug_id = bug_data["id"]
85 
86             # Skip bugs filed by Mozillians, since we are sure they are not spam.
87             if "@mozilla" in bug_data["creator"]:
88                 continue
89 
90             # A bug that was moved out of 'Invalid Bugs' is definitely a legitimate bug.
91             for history in bug_data["history"]:
92                 for change in history["changes"]:
93                     if (
94                         change["field_name"] == "product"
95                         and change["removed"] == "Invalid Bugs"
96                     ):
97                         classes[bug_id] = 0
98 
99             # A fixed bug is definitely a legitimate bug.
100             if bug_data["resolution"] == "FIXED":
101                 classes[bug_id] = 0
102 
103             # A bug in the 'Invalid Bugs' product is definitely a spam bug.
104             elif bug_data["product"] == "Invalid Bugs":
105                 classes[bug_id] = 1
106 
107         print(
108             "{} bugs are classified as non-spam".format(
109                 sum(1 for label in classes.values() if label == 0)
110             )
111         )
112         print(
113             "{} bugs are classified as spam".format(
114                 sum(1 for label in classes.values() if label == 1)
115             )
116         )
117 
118         return classes, [0, 1]
119 
120     def items_gen(self, classes):
121         # Overwriting this method to add include_invalid=True to get_bugs to
122         # include spam bugs.
123         return (
124             (bug, classes[bug["id"]])
125             for bug in bugzilla.get_bugs(include_invalid=True)
126             if bug["id"] in classes
127         )
128 
129     def get_feature_names(self):
130         return self.extraction_pipeline.named_steps["union"].get_feature_names_out()
131 
132     def overwrite_classes(self, bugs, classes, probabilities):
133         for i, bug in enumerate(bugs):
134             if "@mozilla" in bug["creator"]:
135                 if probabilities:
136                     classes[i] = [1.0, 0.0]
137                 else:
138                     classes[i] = 0
139 
140         return classes
141
```
--- 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/bugbug/models/spambug.py b/bugbug/models/spambug.py
--- a/bugbug/models/spambug.py
+++ b/bugbug/models/spambug.py
@@ -41,6 +41,7 @@
             bug_features.has_attachment(),
             bug_features.platform(),
             bug_features.op_sys(),
+            bug_features.filed_via(),
         ]
 
         cleanup_functions = [

{"golden_diff": "diff --git a/bugbug/models/spambug.py b/bugbug/models/spambug.py\n--- a/bugbug/models/spambug.py\n+++ b/bugbug/models/spambug.py\n@@ -41,6 +41,7 @@\n             bug_features.has_attachment(),\n             bug_features.platform(),\n             bug_features.op_sys(),\n+            bug_features.filed_via(),\n         ]\n \n         cleanup_functions = [\n", "issue": "Use information on how a bug is filed as a feature\nThis could be especially useful for the Spam model.\r\n\r\nhttps://bugzilla.mozilla.org/show_bug.cgi?id=1565403\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this file,\n# You can obtain one at http://mozilla.org/MPL/2.0/.\n\nimport xgboost\nfrom imblearn.over_sampling import BorderlineSMOTE\nfrom sklearn.compose import ColumnTransformer\nfrom sklearn.feature_extraction import DictVectorizer\nfrom sklearn.pipeline import Pipeline\n\nfrom bugbug import bug_features, bugzilla, feature_cleanup, utils\nfrom bugbug.model import BugModel\n\n\nclass SpamBugModel(BugModel):\n    def __init__(self, lemmatization=False):\n        BugModel.__init__(self, lemmatization)\n\n        self.sampler = BorderlineSMOTE(random_state=0)\n        self.calculate_importance = False\n\n        feature_extractors = [\n            bug_features.has_str(),\n            bug_features.has_regression_range(),\n            bug_features.severity(),\n            bug_features.has_crash_signature(),\n            bug_features.has_url(),\n            bug_features.whiteboard(),\n            bug_features.product(),\n            # TODO: We would like to use the component at the time of filing too,\n            # but we can't because the rollback script doesn't support changes to\n            # components yet.\n            # bug_features.component(),\n            bug_features.num_words_title(),\n            bug_features.num_words_comments(),\n            bug_features.keywords(),\n            bug_features.priority(),\n            bug_features.version(),\n            bug_features.target_milestone(),\n            bug_features.has_attachment(),\n            bug_features.platform(),\n            bug_features.op_sys(),\n        ]\n\n        cleanup_functions = [\n            feature_cleanup.fileref(),\n            feature_cleanup.url(),\n            feature_cleanup.synonyms(),\n        ]\n\n        self.extraction_pipeline = Pipeline(\n            [\n                (\n                    \"bug_extractor\",\n                    bug_features.BugExtractor(\n                        feature_extractors, cleanup_functions, rollback=True\n                    ),\n                ),\n                (\n                    \"union\",\n                    ColumnTransformer(\n                        [\n                            (\"data\", DictVectorizer(), \"data\"),\n                            (\"title\", self.text_vectorizer(min_df=0.0001), \"title\"),\n                            (\n                                \"comments\",\n                                self.text_vectorizer(min_df=0.0001),\n                                \"comments\",\n                            ),\n                        ]\n                    ),\n                ),\n            ]\n        )\n\n        self.clf = xgboost.XGBClassifier(n_jobs=utils.get_physical_cpu_count())\n        self.clf.set_params(predictor=\"cpu_predictor\")\n\n    def get_labels(self):\n        classes = {}\n\n        for bug_data in bugzilla.get_bugs(include_invalid=True):\n            bug_id = bug_data[\"id\"]\n\n            # Skip bugs filed by Mozillians, since we are sure they are not spam.\n            if \"@mozilla\" in bug_data[\"creator\"]:\n                continue\n\n            # A bug that was moved out of 'Invalid Bugs' is definitely a legitimate bug.\n            for history in bug_data[\"history\"]:\n                for change in history[\"changes\"]:\n                    if (\n                        change[\"field_name\"] == \"product\"\n                        and change[\"removed\"] == \"Invalid Bugs\"\n                    ):\n                        classes[bug_id] = 0\n\n            # A fixed bug is definitely a legitimate bug.\n            if bug_data[\"resolution\"] == \"FIXED\":\n                classes[bug_id] = 0\n\n            # A bug in the 'Invalid Bugs' product is definitely a spam bug.\n            elif bug_data[\"product\"] == \"Invalid Bugs\":\n                classes[bug_id] = 1\n\n        print(\n            \"{} bugs are classified as non-spam\".format(\n                sum(1 for label in classes.values() if label == 0)\n            )\n        )\n        print(\n            \"{} bugs are classified as spam\".format(\n                sum(1 for label in classes.values() if label == 1)\n            )\n        )\n\n        return classes, [0, 1]\n\n    def items_gen(self, classes):\n        # Overwriting this method to add include_invalid=True to get_bugs to\n        # include spam bugs.\n        return (\n            (bug, classes[bug[\"id\"]])\n            for bug in bugzilla.get_bugs(include_invalid=True)\n            if bug[\"id\"] in classes\n        )\n\n    def get_feature_names(self):\n        return self.extraction_pipeline.named_steps[\"union\"].get_feature_names_out()\n\n    def overwrite_classes(self, bugs, classes, probabilities):\n        for i, bug in enumerate(bugs):\n            if \"@mozilla\" in bug[\"creator\"]:\n                if probabilities:\n                    classes[i] = [1.0, 0.0]\n                else:\n                    classes[i] = 0\n\n        return classes\n", "path": "bugbug/models/spambug.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this file,\n# You can obtain one at http://mozilla.org/MPL/2.0/.\n\nimport xgboost\nfrom imblearn.over_sampling import BorderlineSMOTE\nfrom sklearn.compose import ColumnTransformer\nfrom sklearn.feature_extraction import DictVectorizer\nfrom sklearn.pipeline import Pipeline\n\nfrom bugbug import bug_features, bugzilla, feature_cleanup, utils\nfrom bugbug.model import BugModel\n\n\nclass SpamBugModel(BugModel):\n    def __init__(self, lemmatization=False):\n        BugModel.__init__(self, lemmatization)\n\n        self.sampler = BorderlineSMOTE(random_state=0)\n        self.calculate_importance = False\n\n        feature_extractors = [\n            bug_features.has_str(),\n            bug_features.has_regression_range(),\n            bug_features.severity(),\n            bug_features.has_crash_signature(),\n            bug_features.has_url(),\n            bug_features.whiteboard(),\n            bug_features.product(),\n            # TODO: We would like to use the component at the time of filing too,\n            # but we can't because the rollback script doesn't support changes to\n            # components yet.\n            # bug_features.component(),\n            bug_features.num_words_title(),\n            bug_features.num_words_comments(),\n            bug_features.keywords(),\n            bug_features.priority(),\n            bug_features.version(),\n            bug_features.target_milestone(),\n            bug_features.has_attachment(),\n            bug_features.platform(),\n            bug_features.op_sys(),\n            bug_features.filed_via(),\n        ]\n\n        cleanup_functions = [\n            feature_cleanup.fileref(),\n            feature_cleanup.url(),\n            feature_cleanup.synonyms(),\n        ]\n\n        self.extraction_pipeline = Pipeline(\n            [\n                (\n                    \"bug_extractor\",\n                    bug_features.BugExtractor(\n                        feature_extractors, cleanup_functions, rollback=True\n                    ),\n                ),\n                (\n                    \"union\",\n                    ColumnTransformer(\n                        [\n                            (\"data\", DictVectorizer(), \"data\"),\n                            (\"title\", self.text_vectorizer(min_df=0.0001), \"title\"),\n                            (\n                                \"comments\",\n                                self.text_vectorizer(min_df=0.0001),\n                                \"comments\",\n                            ),\n                        ]\n                    ),\n                ),\n            ]\n        )\n\n        self.clf = xgboost.XGBClassifier(n_jobs=utils.get_physical_cpu_count())\n        self.clf.set_params(predictor=\"cpu_predictor\")\n\n    def get_labels(self):\n        classes = {}\n\n        for bug_data in bugzilla.get_bugs(include_invalid=True):\n            bug_id = bug_data[\"id\"]\n\n            # Skip bugs filed by Mozillians, since we are sure they are not spam.\n            if \"@mozilla\" in bug_data[\"creator\"]:\n                continue\n\n            # A bug that was moved out of 'Invalid Bugs' is definitely a legitimate bug.\n            for history in bug_data[\"history\"]:\n                for change in history[\"changes\"]:\n                    if (\n                        change[\"field_name\"] == \"product\"\n                        and change[\"removed\"] == \"Invalid Bugs\"\n                    ):\n                        classes[bug_id] = 0\n\n            # A fixed bug is definitely a legitimate bug.\n            if bug_data[\"resolution\"] == \"FIXED\":\n                classes[bug_id] = 0\n\n            # A bug in the 'Invalid Bugs' product is definitely a spam bug.\n            elif bug_data[\"product\"] == \"Invalid Bugs\":\n                classes[bug_id] = 1\n\n        print(\n            \"{} bugs are classified as non-spam\".format(\n                sum(1 for label in classes.values() if label == 0)\n            )\n        )\n        print(\n            \"{} bugs are classified as spam\".format(\n                sum(1 for label in classes.values() if label == 1)\n            )\n        )\n\n        return classes, [0, 1]\n\n    def items_gen(self, classes):\n        # Overwriting this method to add include_invalid=True to get_bugs to\n        # include spam bugs.\n        return (\n            (bug, classes[bug[\"id\"]])\n            for bug in bugzilla.get_bugs(include_invalid=True)\n            if bug[\"id\"] in classes\n        )\n\n    def get_feature_names(self):\n        return self.extraction_pipeline.named_steps[\"union\"].get_feature_names_out()\n\n    def overwrite_classes(self, bugs, classes, probabilities):\n        for i, bug in enumerate(bugs):\n            if \"@mozilla\" in bug[\"creator\"]:\n                if probabilities:\n                    classes[i] = [1.0, 0.0]\n                else:\n                    classes[i] = 0\n\n        return classes\n", "path": "bugbug/models/spambug.py"}]}