We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[tensor] fix some unittests

[tensor] fix some unittests

[tensor] fix some unittests


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `applications/Chat/inference/utils.py`
Content:
```
1 import re
2 from threading import Lock
3 from typing import Any, Callable, Generator, List, Optional
4 import json
5 
6 import torch
7 import torch.distributed as dist
8 import torch.nn as nn
9 from pydantic import BaseModel, Field
10 
11 try:
12     from transformers.generation_logits_process import (
13         LogitsProcessorList,
14         TemperatureLogitsWarper,
15         TopKLogitsWarper,
16         TopPLogitsWarper,
17     )
18 except ImportError:
19     from transformers.generation import LogitsProcessorList, TemperatureLogitsWarper, TopKLogitsWarper, TopPLogitsWarper
20 
21 
22 def prepare_logits_processor(top_k: Optional[int] = None,
23                              top_p: Optional[float] = None,
24                              temperature: Optional[float] = None) -> LogitsProcessorList:
25     processor_list = LogitsProcessorList()
26     if temperature is not None and temperature != 1.0:
27         processor_list.append(TemperatureLogitsWarper(temperature))
28     if top_k is not None and top_k != 0:
29         processor_list.append(TopKLogitsWarper(top_k))
30     if top_p is not None and top_p < 1.0:
31         processor_list.append(TopPLogitsWarper(top_p))
32     return processor_list
33 
34 
35 def _is_sequence_finished(unfinished_sequences: torch.Tensor) -> bool:
36     if dist.is_initialized() and dist.get_world_size() > 1:
37         # consider DP
38         unfinished_sequences = unfinished_sequences.clone()
39         dist.all_reduce(unfinished_sequences)
40     return unfinished_sequences.max() == 0
41 
42 
43 def sample_streamingly(model: nn.Module,
44                        input_ids: torch.Tensor,
45                        max_generate_tokens: int,
46                        early_stopping: bool = False,
47                        eos_token_id: Optional[int] = None,
48                        pad_token_id: Optional[int] = None,
49                        top_k: Optional[int] = None,
50                        top_p: Optional[float] = None,
51                        temperature: Optional[float] = None,
52                        prepare_inputs_fn: Optional[Callable[[torch.Tensor, Any], dict]] = None,
53                        update_model_kwargs_fn: Optional[Callable[[dict, Any], dict]] = None,
54                        **model_kwargs) -> Generator:
55 
56     logits_processor = prepare_logits_processor(top_k, top_p, temperature)
57     unfinished_sequences = input_ids.new(input_ids.shape[0]).fill_(1)
58 
59     for _ in range(max_generate_tokens):
60         model_inputs = prepare_inputs_fn(input_ids, **model_kwargs) if prepare_inputs_fn is not None else {
61             'input_ids': input_ids
62         }
63         outputs = model(**model_inputs)
64 
65         next_token_logits = outputs['logits'][:, -1, :]
66         # pre-process distribution
67         next_token_logits = logits_processor(input_ids, next_token_logits)
68         # sample
69         probs = torch.softmax(next_token_logits, dim=-1, dtype=torch.float)
70         next_tokens = torch.multinomial(probs, num_samples=1).squeeze(1)
71 
72         # finished sentences should have their next token be a padding token
73         if eos_token_id is not None:
74             if pad_token_id is None:
75                 raise ValueError("If `eos_token_id` is defined, make sure that `pad_token_id` is defined.")
76             next_tokens = next_tokens * unfinished_sequences + pad_token_id * (1 - unfinished_sequences)
77 
78         yield next_tokens
79 
80         # update generated ids, model inputs for next step
81         input_ids = torch.cat([input_ids, next_tokens[:, None]], dim=-1)
82         if update_model_kwargs_fn is not None:
83             model_kwargs = update_model_kwargs_fn(outputs, **model_kwargs)
84 
85         # if eos_token was found in one sentence, set sentence to finished
86         if eos_token_id is not None:
87             unfinished_sequences = unfinished_sequences.mul((next_tokens != eos_token_id).long())
88 
89         # stop when each sentence is finished if early_stopping=True
90         if early_stopping and _is_sequence_finished(unfinished_sequences):
91             break
92 
93 
94 def update_model_kwargs_fn(outputs: dict, **model_kwargs) -> dict:
95     if "past_key_values" in outputs:
96         model_kwargs["past"] = outputs["past_key_values"]
97     else:
98         model_kwargs["past"] = None
99 
100     # update token_type_ids with last value
101     if "token_type_ids" in model_kwargs:
102         token_type_ids = model_kwargs["token_type_ids"]
103         model_kwargs["token_type_ids"] = torch.cat([token_type_ids, token_type_ids[:, -1].unsqueeze(-1)], dim=-1)
104 
105     # update attention mask
106     if "attention_mask" in model_kwargs:
107         attention_mask = model_kwargs["attention_mask"]
108         model_kwargs["attention_mask"] = torch.cat(
109             [attention_mask, attention_mask.new_ones((attention_mask.shape[0], 1))], dim=-1)
110 
111     return model_kwargs
112 
113 
114 class Dialogue(BaseModel):
115     instruction: str = Field(min_length=1, example='Count up from 1 to 500.')
116     response: str = Field(example='')
117 
118 
119 def _format_dialogue(instruction: str, response: str = ''):
120     return f'\n\n### Instruction:\n{instruction}\n\n### Response:\n{response}'
121 
122 
123 STOP_PAT = re.compile(r'(###|instruction:).*', flags=(re.I | re.S))
124 
125 
126 class ChatPromptProcessor:
127     SAFE_RESPONSE = 'The input/response contains inappropriate content, please rephrase your prompt.'
128 
129     def __init__(self, tokenizer, context: str, max_len: int = 2048, censored_words: List[str]=[]):
130         self.tokenizer = tokenizer
131         self.context = context
132         self.max_len = max_len
133         if len(censored_words) > 0:
134             self.censored_pat = re.compile(f'({"|".join(map(re.escape, censored_words))})', flags=re.I)
135         else:
136             self.censored_pat = None
137         # These will be initialized after the first call of preprocess_prompt()
138         self.context_len: Optional[int] = None
139         self.dialogue_placeholder_len: Optional[int] = None
140 
141     def preprocess_prompt(self, history: List[Dialogue], max_new_tokens: int) -> str:
142         if self.context_len is None:
143             self.context_len = len(self.tokenizer(self.context)['input_ids'])
144         if self.dialogue_placeholder_len is None:
145             self.dialogue_placeholder_len = len(
146                 self.tokenizer(_format_dialogue(''), add_special_tokens=False)['input_ids'])
147         prompt = self.context
148         # the last dialogue must be in the prompt
149         last_dialogue = history.pop()
150         # the response of the last dialogue is empty
151         assert last_dialogue.response == ''
152         if len(self.tokenizer(_format_dialogue(last_dialogue.instruction), add_special_tokens=False)
153                ['input_ids']) + max_new_tokens + self.context_len >= self.max_len:
154             # to avoid truncate placeholder, apply truncate to the original instruction
155             instruction_truncated = self.tokenizer(last_dialogue.instruction,
156                                                    add_special_tokens=False,
157                                                    truncation=True,
158                                                    max_length=(self.max_len - max_new_tokens - self.context_len -
159                                                                self.dialogue_placeholder_len))['input_ids']
160             instruction_truncated = self.tokenizer.decode(instruction_truncated).lstrip()
161             prompt += _format_dialogue(instruction_truncated)
162             return prompt
163 
164         res_len = self.max_len - max_new_tokens - len(self.tokenizer(prompt)['input_ids'])
165 
166         rows = []
167         for dialogue in history[::-1]:
168             text = _format_dialogue(dialogue.instruction, dialogue.response)
169             cur_len = len(self.tokenizer(text, add_special_tokens=False)['input_ids'])
170             if res_len - cur_len < 0:
171                 break
172             res_len -= cur_len
173             rows.insert(0, text)
174         prompt += ''.join(rows) + _format_dialogue(last_dialogue.instruction)
175         return prompt
176 
177     def postprocess_output(self, output: str) -> str:
178         output = STOP_PAT.sub('', output)
179         return output.strip()
180 
181     def has_censored_words(self, text: str) -> bool:
182         if self.censored_pat is None:
183             return False
184         return self.censored_pat.search(text) is not None
185 
186 class LockedIterator:
187 
188     def __init__(self, it, lock: Lock) -> None:
189         self.lock = lock
190         self.it = iter(it)
191 
192     def __iter__(self):
193         return self
194 
195     def __next__(self):
196         with self.lock:
197             return next(self.it)
198 
199 def load_json(path: str):
200     with open(path) as f:
201         return json.load(f)
```
--- 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/applications/Chat/inference/utils.py b/applications/Chat/inference/utils.py
--- a/applications/Chat/inference/utils.py
+++ b/applications/Chat/inference/utils.py
@@ -2,6 +2,7 @@
 from threading import Lock
 from typing import Any, Callable, Generator, List, Optional
 import json
+import jieba
 
 import torch
 import torch.distributed as dist
@@ -130,10 +131,7 @@
         self.tokenizer = tokenizer
         self.context = context
         self.max_len = max_len
-        if len(censored_words) > 0:
-            self.censored_pat = re.compile(f'({"|".join(map(re.escape, censored_words))})', flags=re.I)
-        else:
-            self.censored_pat = None
+        self.censored_words = set([word.lower() for word in censored_words])
         # These will be initialized after the first call of preprocess_prompt()
         self.context_len: Optional[int] = None
         self.dialogue_placeholder_len: Optional[int] = None
@@ -179,9 +177,10 @@
         return output.strip()
 
     def has_censored_words(self, text: str) -> bool:
-        if self.censored_pat is None:
+        if len(self.censored_words) == 0:
             return False
-        return self.censored_pat.search(text) is not None
+        intersection = set(jieba.cut(text.lower())) & self.censored_words
+        return len(intersection) > 0
 
 class LockedIterator:

{"golden_diff": "diff --git a/applications/Chat/inference/utils.py b/applications/Chat/inference/utils.py\n--- a/applications/Chat/inference/utils.py\n+++ b/applications/Chat/inference/utils.py\n@@ -2,6 +2,7 @@\n from threading import Lock\n from typing import Any, Callable, Generator, List, Optional\n import json\n+import jieba\n \n import torch\n import torch.distributed as dist\n@@ -130,10 +131,7 @@\n         self.tokenizer = tokenizer\n         self.context = context\n         self.max_len = max_len\n-        if len(censored_words) > 0:\n-            self.censored_pat = re.compile(f'({\"|\".join(map(re.escape, censored_words))})', flags=re.I)\n-        else:\n-            self.censored_pat = None\n+        self.censored_words = set([word.lower() for word in censored_words])\n         # These will be initialized after the first call of preprocess_prompt()\n         self.context_len: Optional[int] = None\n         self.dialogue_placeholder_len: Optional[int] = None\n@@ -179,9 +177,10 @@\n         return output.strip()\n \n     def has_censored_words(self, text: str) -> bool:\n-        if self.censored_pat is None:\n+        if len(self.censored_words) == 0:\n             return False\n-        return self.censored_pat.search(text) is not None\n+        intersection = set(jieba.cut(text.lower())) & self.censored_words\n+        return len(intersection) > 0\n \n class LockedIterator:\n", "issue": "[tensor] fix some unittests\n\n[tensor] fix some unittests\n\n[tensor] fix some unittests\n\n", "before_files": [{"content": "import re\nfrom threading import Lock\nfrom typing import Any, Callable, Generator, List, Optional\nimport json\n\nimport torch\nimport torch.distributed as dist\nimport torch.nn as nn\nfrom pydantic import BaseModel, Field\n\ntry:\n    from transformers.generation_logits_process import (\n        LogitsProcessorList,\n        TemperatureLogitsWarper,\n        TopKLogitsWarper,\n        TopPLogitsWarper,\n    )\nexcept ImportError:\n    from transformers.generation import LogitsProcessorList, TemperatureLogitsWarper, TopKLogitsWarper, TopPLogitsWarper\n\n\ndef prepare_logits_processor(top_k: Optional[int] = None,\n                             top_p: Optional[float] = None,\n                             temperature: Optional[float] = None) -> LogitsProcessorList:\n    processor_list = LogitsProcessorList()\n    if temperature is not None and temperature != 1.0:\n        processor_list.append(TemperatureLogitsWarper(temperature))\n    if top_k is not None and top_k != 0:\n        processor_list.append(TopKLogitsWarper(top_k))\n    if top_p is not None and top_p < 1.0:\n        processor_list.append(TopPLogitsWarper(top_p))\n    return processor_list\n\n\ndef _is_sequence_finished(unfinished_sequences: torch.Tensor) -> bool:\n    if dist.is_initialized() and dist.get_world_size() > 1:\n        # consider DP\n        unfinished_sequences = unfinished_sequences.clone()\n        dist.all_reduce(unfinished_sequences)\n    return unfinished_sequences.max() == 0\n\n\ndef sample_streamingly(model: nn.Module,\n                       input_ids: torch.Tensor,\n                       max_generate_tokens: int,\n                       early_stopping: bool = False,\n                       eos_token_id: Optional[int] = None,\n                       pad_token_id: Optional[int] = None,\n                       top_k: Optional[int] = None,\n                       top_p: Optional[float] = None,\n                       temperature: Optional[float] = None,\n                       prepare_inputs_fn: Optional[Callable[[torch.Tensor, Any], dict]] = None,\n                       update_model_kwargs_fn: Optional[Callable[[dict, Any], dict]] = None,\n                       **model_kwargs) -> Generator:\n\n    logits_processor = prepare_logits_processor(top_k, top_p, temperature)\n    unfinished_sequences = input_ids.new(input_ids.shape[0]).fill_(1)\n\n    for _ in range(max_generate_tokens):\n        model_inputs = prepare_inputs_fn(input_ids, **model_kwargs) if prepare_inputs_fn is not None else {\n            'input_ids': input_ids\n        }\n        outputs = model(**model_inputs)\n\n        next_token_logits = outputs['logits'][:, -1, :]\n        # pre-process distribution\n        next_token_logits = logits_processor(input_ids, next_token_logits)\n        # sample\n        probs = torch.softmax(next_token_logits, dim=-1, dtype=torch.float)\n        next_tokens = torch.multinomial(probs, num_samples=1).squeeze(1)\n\n        # finished sentences should have their next token be a padding token\n        if eos_token_id is not None:\n            if pad_token_id is None:\n                raise ValueError(\"If `eos_token_id` is defined, make sure that `pad_token_id` is defined.\")\n            next_tokens = next_tokens * unfinished_sequences + pad_token_id * (1 - unfinished_sequences)\n\n        yield next_tokens\n\n        # update generated ids, model inputs for next step\n        input_ids = torch.cat([input_ids, next_tokens[:, None]], dim=-1)\n        if update_model_kwargs_fn is not None:\n            model_kwargs = update_model_kwargs_fn(outputs, **model_kwargs)\n\n        # if eos_token was found in one sentence, set sentence to finished\n        if eos_token_id is not None:\n            unfinished_sequences = unfinished_sequences.mul((next_tokens != eos_token_id).long())\n\n        # stop when each sentence is finished if early_stopping=True\n        if early_stopping and _is_sequence_finished(unfinished_sequences):\n            break\n\n\ndef update_model_kwargs_fn(outputs: dict, **model_kwargs) -> dict:\n    if \"past_key_values\" in outputs:\n        model_kwargs[\"past\"] = outputs[\"past_key_values\"]\n    else:\n        model_kwargs[\"past\"] = None\n\n    # update token_type_ids with last value\n    if \"token_type_ids\" in model_kwargs:\n        token_type_ids = model_kwargs[\"token_type_ids\"]\n        model_kwargs[\"token_type_ids\"] = torch.cat([token_type_ids, token_type_ids[:, -1].unsqueeze(-1)], dim=-1)\n\n    # update attention mask\n    if \"attention_mask\" in model_kwargs:\n        attention_mask = model_kwargs[\"attention_mask\"]\n        model_kwargs[\"attention_mask\"] = torch.cat(\n            [attention_mask, attention_mask.new_ones((attention_mask.shape[0], 1))], dim=-1)\n\n    return model_kwargs\n\n\nclass Dialogue(BaseModel):\n    instruction: str = Field(min_length=1, example='Count up from 1 to 500.')\n    response: str = Field(example='')\n\n\ndef _format_dialogue(instruction: str, response: str = ''):\n    return f'\\n\\n### Instruction:\\n{instruction}\\n\\n### Response:\\n{response}'\n\n\nSTOP_PAT = re.compile(r'(###|instruction:).*', flags=(re.I | re.S))\n\n\nclass ChatPromptProcessor:\n    SAFE_RESPONSE = 'The input/response contains inappropriate content, please rephrase your prompt.'\n\n    def __init__(self, tokenizer, context: str, max_len: int = 2048, censored_words: List[str]=[]):\n        self.tokenizer = tokenizer\n        self.context = context\n        self.max_len = max_len\n        if len(censored_words) > 0:\n            self.censored_pat = re.compile(f'({\"|\".join(map(re.escape, censored_words))})', flags=re.I)\n        else:\n            self.censored_pat = None\n        # These will be initialized after the first call of preprocess_prompt()\n        self.context_len: Optional[int] = None\n        self.dialogue_placeholder_len: Optional[int] = None\n\n    def preprocess_prompt(self, history: List[Dialogue], max_new_tokens: int) -> str:\n        if self.context_len is None:\n            self.context_len = len(self.tokenizer(self.context)['input_ids'])\n        if self.dialogue_placeholder_len is None:\n            self.dialogue_placeholder_len = len(\n                self.tokenizer(_format_dialogue(''), add_special_tokens=False)['input_ids'])\n        prompt = self.context\n        # the last dialogue must be in the prompt\n        last_dialogue = history.pop()\n        # the response of the last dialogue is empty\n        assert last_dialogue.response == ''\n        if len(self.tokenizer(_format_dialogue(last_dialogue.instruction), add_special_tokens=False)\n               ['input_ids']) + max_new_tokens + self.context_len >= self.max_len:\n            # to avoid truncate placeholder, apply truncate to the original instruction\n            instruction_truncated = self.tokenizer(last_dialogue.instruction,\n                                                   add_special_tokens=False,\n                                                   truncation=True,\n                                                   max_length=(self.max_len - max_new_tokens - self.context_len -\n                                                               self.dialogue_placeholder_len))['input_ids']\n            instruction_truncated = self.tokenizer.decode(instruction_truncated).lstrip()\n            prompt += _format_dialogue(instruction_truncated)\n            return prompt\n\n        res_len = self.max_len - max_new_tokens - len(self.tokenizer(prompt)['input_ids'])\n\n        rows = []\n        for dialogue in history[::-1]:\n            text = _format_dialogue(dialogue.instruction, dialogue.response)\n            cur_len = len(self.tokenizer(text, add_special_tokens=False)['input_ids'])\n            if res_len - cur_len < 0:\n                break\n            res_len -= cur_len\n            rows.insert(0, text)\n        prompt += ''.join(rows) + _format_dialogue(last_dialogue.instruction)\n        return prompt\n\n    def postprocess_output(self, output: str) -> str:\n        output = STOP_PAT.sub('', output)\n        return output.strip()\n\n    def has_censored_words(self, text: str) -> bool:\n        if self.censored_pat is None:\n            return False\n        return self.censored_pat.search(text) is not None\n\nclass LockedIterator:\n\n    def __init__(self, it, lock: Lock) -> None:\n        self.lock = lock\n        self.it = iter(it)\n\n    def __iter__(self):\n        return self\n\n    def __next__(self):\n        with self.lock:\n            return next(self.it)\n\ndef load_json(path: str):\n    with open(path) as f:\n        return json.load(f)", "path": "applications/Chat/inference/utils.py"}], "after_files": [{"content": "import re\nfrom threading import Lock\nfrom typing import Any, Callable, Generator, List, Optional\nimport json\nimport jieba\n\nimport torch\nimport torch.distributed as dist\nimport torch.nn as nn\nfrom pydantic import BaseModel, Field\n\ntry:\n    from transformers.generation_logits_process import (\n        LogitsProcessorList,\n        TemperatureLogitsWarper,\n        TopKLogitsWarper,\n        TopPLogitsWarper,\n    )\nexcept ImportError:\n    from transformers.generation import LogitsProcessorList, TemperatureLogitsWarper, TopKLogitsWarper, TopPLogitsWarper\n\n\ndef prepare_logits_processor(top_k: Optional[int] = None,\n                             top_p: Optional[float] = None,\n                             temperature: Optional[float] = None) -> LogitsProcessorList:\n    processor_list = LogitsProcessorList()\n    if temperature is not None and temperature != 1.0:\n        processor_list.append(TemperatureLogitsWarper(temperature))\n    if top_k is not None and top_k != 0:\n        processor_list.append(TopKLogitsWarper(top_k))\n    if top_p is not None and top_p < 1.0:\n        processor_list.append(TopPLogitsWarper(top_p))\n    return processor_list\n\n\ndef _is_sequence_finished(unfinished_sequences: torch.Tensor) -> bool:\n    if dist.is_initialized() and dist.get_world_size() > 1:\n        # consider DP\n        unfinished_sequences = unfinished_sequences.clone()\n        dist.all_reduce(unfinished_sequences)\n    return unfinished_sequences.max() == 0\n\n\ndef sample_streamingly(model: nn.Module,\n                       input_ids: torch.Tensor,\n                       max_generate_tokens: int,\n                       early_stopping: bool = False,\n                       eos_token_id: Optional[int] = None,\n                       pad_token_id: Optional[int] = None,\n                       top_k: Optional[int] = None,\n                       top_p: Optional[float] = None,\n                       temperature: Optional[float] = None,\n                       prepare_inputs_fn: Optional[Callable[[torch.Tensor, Any], dict]] = None,\n                       update_model_kwargs_fn: Optional[Callable[[dict, Any], dict]] = None,\n                       **model_kwargs) -> Generator:\n\n    logits_processor = prepare_logits_processor(top_k, top_p, temperature)\n    unfinished_sequences = input_ids.new(input_ids.shape[0]).fill_(1)\n\n    for _ in range(max_generate_tokens):\n        model_inputs = prepare_inputs_fn(input_ids, **model_kwargs) if prepare_inputs_fn is not None else {\n            'input_ids': input_ids\n        }\n        outputs = model(**model_inputs)\n\n        next_token_logits = outputs['logits'][:, -1, :]\n        # pre-process distribution\n        next_token_logits = logits_processor(input_ids, next_token_logits)\n        # sample\n        probs = torch.softmax(next_token_logits, dim=-1, dtype=torch.float)\n        next_tokens = torch.multinomial(probs, num_samples=1).squeeze(1)\n\n        # finished sentences should have their next token be a padding token\n        if eos_token_id is not None:\n            if pad_token_id is None:\n                raise ValueError(\"If `eos_token_id` is defined, make sure that `pad_token_id` is defined.\")\n            next_tokens = next_tokens * unfinished_sequences + pad_token_id * (1 - unfinished_sequences)\n\n        yield next_tokens\n\n        # update generated ids, model inputs for next step\n        input_ids = torch.cat([input_ids, next_tokens[:, None]], dim=-1)\n        if update_model_kwargs_fn is not None:\n            model_kwargs = update_model_kwargs_fn(outputs, **model_kwargs)\n\n        # if eos_token was found in one sentence, set sentence to finished\n        if eos_token_id is not None:\n            unfinished_sequences = unfinished_sequences.mul((next_tokens != eos_token_id).long())\n\n        # stop when each sentence is finished if early_stopping=True\n        if early_stopping and _is_sequence_finished(unfinished_sequences):\n            break\n\n\ndef update_model_kwargs_fn(outputs: dict, **model_kwargs) -> dict:\n    if \"past_key_values\" in outputs:\n        model_kwargs[\"past\"] = outputs[\"past_key_values\"]\n    else:\n        model_kwargs[\"past\"] = None\n\n    # update token_type_ids with last value\n    if \"token_type_ids\" in model_kwargs:\n        token_type_ids = model_kwargs[\"token_type_ids\"]\n        model_kwargs[\"token_type_ids\"] = torch.cat([token_type_ids, token_type_ids[:, -1].unsqueeze(-1)], dim=-1)\n\n    # update attention mask\n    if \"attention_mask\" in model_kwargs:\n        attention_mask = model_kwargs[\"attention_mask\"]\n        model_kwargs[\"attention_mask\"] = torch.cat(\n            [attention_mask, attention_mask.new_ones((attention_mask.shape[0], 1))], dim=-1)\n\n    return model_kwargs\n\n\nclass Dialogue(BaseModel):\n    instruction: str = Field(min_length=1, example='Count up from 1 to 500.')\n    response: str = Field(example='')\n\n\ndef _format_dialogue(instruction: str, response: str = ''):\n    return f'\\n\\n### Instruction:\\n{instruction}\\n\\n### Response:\\n{response}'\n\n\nSTOP_PAT = re.compile(r'(###|instruction:).*', flags=(re.I | re.S))\n\n\nclass ChatPromptProcessor:\n    SAFE_RESPONSE = 'The input/response contains inappropriate content, please rephrase your prompt.'\n\n    def __init__(self, tokenizer, context: str, max_len: int = 2048, censored_words: List[str]=[]):\n        self.tokenizer = tokenizer\n        self.context = context\n        self.max_len = max_len\n        self.censored_words = set([word.lower() for word in censored_words])\n        # These will be initialized after the first call of preprocess_prompt()\n        self.context_len: Optional[int] = None\n        self.dialogue_placeholder_len: Optional[int] = None\n\n    def preprocess_prompt(self, history: List[Dialogue], max_new_tokens: int) -> str:\n        if self.context_len is None:\n            self.context_len = len(self.tokenizer(self.context)['input_ids'])\n        if self.dialogue_placeholder_len is None:\n            self.dialogue_placeholder_len = len(\n                self.tokenizer(_format_dialogue(''), add_special_tokens=False)['input_ids'])\n        prompt = self.context\n        # the last dialogue must be in the prompt\n        last_dialogue = history.pop()\n        # the response of the last dialogue is empty\n        assert last_dialogue.response == ''\n        if len(self.tokenizer(_format_dialogue(last_dialogue.instruction), add_special_tokens=False)\n               ['input_ids']) + max_new_tokens + self.context_len >= self.max_len:\n            # to avoid truncate placeholder, apply truncate to the original instruction\n            instruction_truncated = self.tokenizer(last_dialogue.instruction,\n                                                   add_special_tokens=False,\n                                                   truncation=True,\n                                                   max_length=(self.max_len - max_new_tokens - self.context_len -\n                                                               self.dialogue_placeholder_len))['input_ids']\n            instruction_truncated = self.tokenizer.decode(instruction_truncated).lstrip()\n            prompt += _format_dialogue(instruction_truncated)\n            return prompt\n\n        res_len = self.max_len - max_new_tokens - len(self.tokenizer(prompt)['input_ids'])\n\n        rows = []\n        for dialogue in history[::-1]:\n            text = _format_dialogue(dialogue.instruction, dialogue.response)\n            cur_len = len(self.tokenizer(text, add_special_tokens=False)['input_ids'])\n            if res_len - cur_len < 0:\n                break\n            res_len -= cur_len\n            rows.insert(0, text)\n        prompt += ''.join(rows) + _format_dialogue(last_dialogue.instruction)\n        return prompt\n\n    def postprocess_output(self, output: str) -> str:\n        output = STOP_PAT.sub('', output)\n        return output.strip()\n\n    def has_censored_words(self, text: str) -> bool:\n        if len(self.censored_words) == 0:\n            return False\n        intersection = set(jieba.cut(text.lower())) & self.censored_words\n        return len(intersection) > 0\n\nclass LockedIterator:\n\n    def __init__(self, it, lock: Lock) -> None:\n        self.lock = lock\n        self.it = iter(it)\n\n    def __iter__(self):\n        return self\n\n    def __next__(self):\n        with self.lock:\n            return next(self.it)\n\ndef load_json(path: str):\n    with open(path) as f:\n        return json.load(f)", "path": "applications/Chat/inference/utils.py"}]}