We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
BUG: chatglm max_length doesn't work
### Describe the bug
The gen config has `max_tokens`, but chatglm requires `max_length`.

### To Reproduce
To help us to reproduce this bug, please provide information below:

1. Your Python version.
2. The version of xinference you use.
3. Versions of crucial packages.
4. Full stack of the error.
5. Minimized code to reproduce the error.

### Expected behavior
A clear and concise description of what you expected to happen.

### Additional context
Add any other context about the problem here.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `xinference/model/llm/ggml/chatglm.py`
Content:
```
1 # Copyright 2022-2023 XProbe Inc.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 import logging
16 import os
17 import time
18 import uuid
19 from pathlib import Path
20 from typing import TYPE_CHECKING, Iterator, List, Optional, TypedDict, Union
21 
22 from ....types import ChatCompletion, ChatCompletionChunk, ChatCompletionMessage
23 from .. import LLMFamilyV1, LLMSpecV1
24 from ..core import LLM
25 
26 if TYPE_CHECKING:
27     from chatglm_cpp import Pipeline
28 
29 
30 logger = logging.getLogger(__name__)
31 
32 
33 class ChatglmCppModelConfig(TypedDict, total=False):
34     pass
35 
36 
37 class ChatglmCppGenerateConfig(TypedDict, total=False):
38     max_tokens: int
39     top_p: float
40     temperature: float
41     stream: bool
42 
43 
44 class ChatglmCppChatModel(LLM):
45     def __init__(
46         self,
47         model_uid: str,
48         model_family: "LLMFamilyV1",
49         model_spec: "LLMSpecV1",
50         quantization: str,
51         model_path: str,
52         model_config: Optional[ChatglmCppModelConfig] = None,
53     ):
54         super().__init__(model_uid, model_family, model_spec, quantization, model_path)
55         self._llm: Optional["Pipeline"] = None
56 
57         # just a placeholder for now as the chatglm_cpp repo doesn't support model config.
58         self._model_config = model_config
59 
60     @classmethod
61     def _sanitize_generate_config(
62         cls,
63         chatglmcpp_generate_config: Optional[ChatglmCppGenerateConfig],
64     ) -> ChatglmCppGenerateConfig:
65         if chatglmcpp_generate_config is None:
66             chatglmcpp_generate_config = ChatglmCppGenerateConfig()
67         chatglmcpp_generate_config.setdefault("stream", False)
68         return chatglmcpp_generate_config
69 
70     def load(self):
71         try:
72             import chatglm_cpp
73         except ImportError:
74             error_message = "Failed to import module 'chatglm_cpp'"
75             installation_guide = [
76                 "Please make sure 'chatglm_cpp' is installed. ",
77                 "You can install it by running the following command in the terminal:\n",
78                 "pip install git+https://github.com/li-plus/chatglm.cpp.git@main\n\n",
79                 "Or visit the original git repo if the above command fails:\n",
80                 "https://github.com/li-plus/chatglm.cpp",
81             ]
82 
83             raise ImportError(f"{error_message}\n\n{''.join(installation_guide)}")
84 
85         model_file_path = os.path.join(
86             self.model_path,
87             self.model_spec.model_file_name_template.format(
88                 quantization=self.quantization
89             ),
90         )
91 
92         # handle legacy cache.
93         legacy_model_file_path = os.path.join(self.model_path, "model.bin")
94         if os.path.exists(legacy_model_file_path):
95             model_file_path = legacy_model_file_path
96 
97         self._llm = chatglm_cpp.Pipeline(Path(model_file_path))
98 
99     @classmethod
100     def match(cls, llm_family: "LLMFamilyV1", llm_spec: "LLMSpecV1") -> bool:
101         if llm_spec.model_format != "ggmlv3":
102             return False
103         if "chatglm" not in llm_family.model_name:
104             return False
105         if "chat" not in llm_family.model_ability:
106             return False
107         return True
108 
109     @staticmethod
110     def _convert_raw_text_chunks_to_chat(
111         tokens: Iterator[str], model_name: str
112     ) -> Iterator[ChatCompletionChunk]:
113         yield {
114             "id": "chat" + f"cmpl-{str(uuid.uuid4())}",
115             "model": model_name,
116             "object": "chat.completion.chunk",
117             "created": int(time.time()),
118             "choices": [
119                 {
120                     "index": 0,
121                     "delta": {
122                         "role": "assistant",
123                     },
124                     "finish_reason": None,
125                 }
126             ],
127         }
128         for token in enumerate(tokens):
129             yield {
130                 "id": "chat" + f"cmpl-{str(uuid.uuid4())}",
131                 "model": model_name,
132                 "object": "chat.completion.chunk",
133                 "created": int(time.time()),
134                 "choices": [
135                     {
136                         "index": 0,
137                         "delta": {
138                             "content": token[1],
139                         },
140                         "finish_reason": None,
141                     }
142                 ],
143             }
144 
145     @staticmethod
146     def _convert_raw_text_completion_to_chat(
147         text: str, model_name: str
148     ) -> ChatCompletion:
149         return {
150             "id": "chat" + f"cmpl-{str(uuid.uuid4())}",
151             "model": model_name,
152             "object": "chat.completion",
153             "created": int(time.time()),
154             "choices": [
155                 {
156                     "index": 0,
157                     "message": {
158                         "role": "assistant",
159                         "content": text,
160                     },
161                     "finish_reason": None,
162                 }
163             ],
164             "usage": {
165                 "prompt_tokens": -1,
166                 "completion_tokens": -1,
167                 "total_tokens": -1,
168             },
169         }
170 
171     def chat(
172         self,
173         prompt: str,
174         chat_history: Optional[List[ChatCompletionMessage]] = None,
175         generate_config: Optional[ChatglmCppGenerateConfig] = None,
176     ) -> Union[ChatCompletion, Iterator[ChatCompletionChunk]]:
177         if chat_history is not None:
178             chat_history_list = [message["content"] for message in chat_history]
179         else:
180             chat_history_list = []
181 
182         chat_history_list.append(prompt)
183         logger.debug("Full conversation history:\n%s", str(chat_history_list))
184 
185         generate_config = self._sanitize_generate_config(generate_config)
186 
187         assert self._llm is not None
188 
189         if generate_config.get("stream", False):
190             it = self._llm.stream_chat(
191                 chat_history_list,
192             )
193             assert not isinstance(it, str)
194             return self._convert_raw_text_chunks_to_chat(it, self.model_uid)
195         else:
196             c = self._llm.chat(
197                 chat_history_list,
198             )
199             assert not isinstance(c, Iterator)
200             return self._convert_raw_text_completion_to_chat(c, self.model_uid)
201
```
--- 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/xinference/model/llm/ggml/chatglm.py b/xinference/model/llm/ggml/chatglm.py
--- a/xinference/model/llm/ggml/chatglm.py
+++ b/xinference/model/llm/ggml/chatglm.py
@@ -183,18 +183,23 @@
         logger.debug("Full conversation history:\n%s", str(chat_history_list))
 
         generate_config = self._sanitize_generate_config(generate_config)
+        params = dict(generate_config)
+        if "max_tokens" in params:
+            params["max_length"] = params.pop("max_tokens")
 
         assert self._llm is not None
 
-        if generate_config.get("stream", False):
+        if params.pop("stream", False):
             it = self._llm.stream_chat(
                 chat_history_list,
+                **params,
             )
             assert not isinstance(it, str)
             return self._convert_raw_text_chunks_to_chat(it, self.model_uid)
         else:
             c = self._llm.chat(
                 chat_history_list,
+                **params,
             )
             assert not isinstance(c, Iterator)
             return self._convert_raw_text_completion_to_chat(c, self.model_uid)

{"golden_diff": "diff --git a/xinference/model/llm/ggml/chatglm.py b/xinference/model/llm/ggml/chatglm.py\n--- a/xinference/model/llm/ggml/chatglm.py\n+++ b/xinference/model/llm/ggml/chatglm.py\n@@ -183,18 +183,23 @@\n         logger.debug(\"Full conversation history:\\n%s\", str(chat_history_list))\n \n         generate_config = self._sanitize_generate_config(generate_config)\n+        params = dict(generate_config)\n+        if \"max_tokens\" in params:\n+            params[\"max_length\"] = params.pop(\"max_tokens\")\n \n         assert self._llm is not None\n \n-        if generate_config.get(\"stream\", False):\n+        if params.pop(\"stream\", False):\n             it = self._llm.stream_chat(\n                 chat_history_list,\n+                **params,\n             )\n             assert not isinstance(it, str)\n             return self._convert_raw_text_chunks_to_chat(it, self.model_uid)\n         else:\n             c = self._llm.chat(\n                 chat_history_list,\n+                **params,\n             )\n             assert not isinstance(c, Iterator)\n             return self._convert_raw_text_completion_to_chat(c, self.model_uid)\n", "issue": "BUG: chatglm max_length doesn't work\n### Describe the bug\r\nThe gen config has `max_tokens`, but chatglm requires `max_length`.\r\n\r\n### To Reproduce\r\nTo help us to reproduce this bug, please provide information below:\r\n\r\n1. Your Python version.\r\n2. The version of xinference you use.\r\n3. Versions of crucial packages.\r\n4. Full stack of the error.\r\n5. Minimized code to reproduce the error.\r\n\r\n### Expected behavior\r\nA clear and concise description of what you expected to happen.\r\n\r\n### Additional context\r\nAdd any other context about the problem here.\r\n\n", "before_files": [{"content": "# Copyright 2022-2023 XProbe Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport logging\nimport os\nimport time\nimport uuid\nfrom pathlib import Path\nfrom typing import TYPE_CHECKING, Iterator, List, Optional, TypedDict, Union\n\nfrom ....types import ChatCompletion, ChatCompletionChunk, ChatCompletionMessage\nfrom .. import LLMFamilyV1, LLMSpecV1\nfrom ..core import LLM\n\nif TYPE_CHECKING:\n    from chatglm_cpp import Pipeline\n\n\nlogger = logging.getLogger(__name__)\n\n\nclass ChatglmCppModelConfig(TypedDict, total=False):\n    pass\n\n\nclass ChatglmCppGenerateConfig(TypedDict, total=False):\n    max_tokens: int\n    top_p: float\n    temperature: float\n    stream: bool\n\n\nclass ChatglmCppChatModel(LLM):\n    def __init__(\n        self,\n        model_uid: str,\n        model_family: \"LLMFamilyV1\",\n        model_spec: \"LLMSpecV1\",\n        quantization: str,\n        model_path: str,\n        model_config: Optional[ChatglmCppModelConfig] = None,\n    ):\n        super().__init__(model_uid, model_family, model_spec, quantization, model_path)\n        self._llm: Optional[\"Pipeline\"] = None\n\n        # just a placeholder for now as the chatglm_cpp repo doesn't support model config.\n        self._model_config = model_config\n\n    @classmethod\n    def _sanitize_generate_config(\n        cls,\n        chatglmcpp_generate_config: Optional[ChatglmCppGenerateConfig],\n    ) -> ChatglmCppGenerateConfig:\n        if chatglmcpp_generate_config is None:\n            chatglmcpp_generate_config = ChatglmCppGenerateConfig()\n        chatglmcpp_generate_config.setdefault(\"stream\", False)\n        return chatglmcpp_generate_config\n\n    def load(self):\n        try:\n            import chatglm_cpp\n        except ImportError:\n            error_message = \"Failed to import module 'chatglm_cpp'\"\n            installation_guide = [\n                \"Please make sure 'chatglm_cpp' is installed. \",\n                \"You can install it by running the following command in the terminal:\\n\",\n                \"pip install git+https://github.com/li-plus/chatglm.cpp.git@main\\n\\n\",\n                \"Or visit the original git repo if the above command fails:\\n\",\n                \"https://github.com/li-plus/chatglm.cpp\",\n            ]\n\n            raise ImportError(f\"{error_message}\\n\\n{''.join(installation_guide)}\")\n\n        model_file_path = os.path.join(\n            self.model_path,\n            self.model_spec.model_file_name_template.format(\n                quantization=self.quantization\n            ),\n        )\n\n        # handle legacy cache.\n        legacy_model_file_path = os.path.join(self.model_path, \"model.bin\")\n        if os.path.exists(legacy_model_file_path):\n            model_file_path = legacy_model_file_path\n\n        self._llm = chatglm_cpp.Pipeline(Path(model_file_path))\n\n    @classmethod\n    def match(cls, llm_family: \"LLMFamilyV1\", llm_spec: \"LLMSpecV1\") -> bool:\n        if llm_spec.model_format != \"ggmlv3\":\n            return False\n        if \"chatglm\" not in llm_family.model_name:\n            return False\n        if \"chat\" not in llm_family.model_ability:\n            return False\n        return True\n\n    @staticmethod\n    def _convert_raw_text_chunks_to_chat(\n        tokens: Iterator[str], model_name: str\n    ) -> Iterator[ChatCompletionChunk]:\n        yield {\n            \"id\": \"chat\" + f\"cmpl-{str(uuid.uuid4())}\",\n            \"model\": model_name,\n            \"object\": \"chat.completion.chunk\",\n            \"created\": int(time.time()),\n            \"choices\": [\n                {\n                    \"index\": 0,\n                    \"delta\": {\n                        \"role\": \"assistant\",\n                    },\n                    \"finish_reason\": None,\n                }\n            ],\n        }\n        for token in enumerate(tokens):\n            yield {\n                \"id\": \"chat\" + f\"cmpl-{str(uuid.uuid4())}\",\n                \"model\": model_name,\n                \"object\": \"chat.completion.chunk\",\n                \"created\": int(time.time()),\n                \"choices\": [\n                    {\n                        \"index\": 0,\n                        \"delta\": {\n                            \"content\": token[1],\n                        },\n                        \"finish_reason\": None,\n                    }\n                ],\n            }\n\n    @staticmethod\n    def _convert_raw_text_completion_to_chat(\n        text: str, model_name: str\n    ) -> ChatCompletion:\n        return {\n            \"id\": \"chat\" + f\"cmpl-{str(uuid.uuid4())}\",\n            \"model\": model_name,\n            \"object\": \"chat.completion\",\n            \"created\": int(time.time()),\n            \"choices\": [\n                {\n                    \"index\": 0,\n                    \"message\": {\n                        \"role\": \"assistant\",\n                        \"content\": text,\n                    },\n                    \"finish_reason\": None,\n                }\n            ],\n            \"usage\": {\n                \"prompt_tokens\": -1,\n                \"completion_tokens\": -1,\n                \"total_tokens\": -1,\n            },\n        }\n\n    def chat(\n        self,\n        prompt: str,\n        chat_history: Optional[List[ChatCompletionMessage]] = None,\n        generate_config: Optional[ChatglmCppGenerateConfig] = None,\n    ) -> Union[ChatCompletion, Iterator[ChatCompletionChunk]]:\n        if chat_history is not None:\n            chat_history_list = [message[\"content\"] for message in chat_history]\n        else:\n            chat_history_list = []\n\n        chat_history_list.append(prompt)\n        logger.debug(\"Full conversation history:\\n%s\", str(chat_history_list))\n\n        generate_config = self._sanitize_generate_config(generate_config)\n\n        assert self._llm is not None\n\n        if generate_config.get(\"stream\", False):\n            it = self._llm.stream_chat(\n                chat_history_list,\n            )\n            assert not isinstance(it, str)\n            return self._convert_raw_text_chunks_to_chat(it, self.model_uid)\n        else:\n            c = self._llm.chat(\n                chat_history_list,\n            )\n            assert not isinstance(c, Iterator)\n            return self._convert_raw_text_completion_to_chat(c, self.model_uid)\n", "path": "xinference/model/llm/ggml/chatglm.py"}], "after_files": [{"content": "# Copyright 2022-2023 XProbe Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport logging\nimport os\nimport time\nimport uuid\nfrom pathlib import Path\nfrom typing import TYPE_CHECKING, Iterator, List, Optional, TypedDict, Union\n\nfrom ....types import ChatCompletion, ChatCompletionChunk, ChatCompletionMessage\nfrom .. import LLMFamilyV1, LLMSpecV1\nfrom ..core import LLM\n\nif TYPE_CHECKING:\n    from chatglm_cpp import Pipeline\n\n\nlogger = logging.getLogger(__name__)\n\n\nclass ChatglmCppModelConfig(TypedDict, total=False):\n    pass\n\n\nclass ChatglmCppGenerateConfig(TypedDict, total=False):\n    max_tokens: int\n    top_p: float\n    temperature: float\n    stream: bool\n\n\nclass ChatglmCppChatModel(LLM):\n    def __init__(\n        self,\n        model_uid: str,\n        model_family: \"LLMFamilyV1\",\n        model_spec: \"LLMSpecV1\",\n        quantization: str,\n        model_path: str,\n        model_config: Optional[ChatglmCppModelConfig] = None,\n    ):\n        super().__init__(model_uid, model_family, model_spec, quantization, model_path)\n        self._llm: Optional[\"Pipeline\"] = None\n\n        # just a placeholder for now as the chatglm_cpp repo doesn't support model config.\n        self._model_config = model_config\n\n    @classmethod\n    def _sanitize_generate_config(\n        cls,\n        chatglmcpp_generate_config: Optional[ChatglmCppGenerateConfig],\n    ) -> ChatglmCppGenerateConfig:\n        if chatglmcpp_generate_config is None:\n            chatglmcpp_generate_config = ChatglmCppGenerateConfig()\n        chatglmcpp_generate_config.setdefault(\"stream\", False)\n        return chatglmcpp_generate_config\n\n    def load(self):\n        try:\n            import chatglm_cpp\n        except ImportError:\n            error_message = \"Failed to import module 'chatglm_cpp'\"\n            installation_guide = [\n                \"Please make sure 'chatglm_cpp' is installed. \",\n                \"You can install it by running the following command in the terminal:\\n\",\n                \"pip install git+https://github.com/li-plus/chatglm.cpp.git@main\\n\\n\",\n                \"Or visit the original git repo if the above command fails:\\n\",\n                \"https://github.com/li-plus/chatglm.cpp\",\n            ]\n\n            raise ImportError(f\"{error_message}\\n\\n{''.join(installation_guide)}\")\n\n        model_file_path = os.path.join(\n            self.model_path,\n            self.model_spec.model_file_name_template.format(\n                quantization=self.quantization\n            ),\n        )\n\n        # handle legacy cache.\n        legacy_model_file_path = os.path.join(self.model_path, \"model.bin\")\n        if os.path.exists(legacy_model_file_path):\n            model_file_path = legacy_model_file_path\n\n        self._llm = chatglm_cpp.Pipeline(Path(model_file_path))\n\n    @classmethod\n    def match(cls, llm_family: \"LLMFamilyV1\", llm_spec: \"LLMSpecV1\") -> bool:\n        if llm_spec.model_format != \"ggmlv3\":\n            return False\n        if \"chatglm\" not in llm_family.model_name:\n            return False\n        if \"chat\" not in llm_family.model_ability:\n            return False\n        return True\n\n    @staticmethod\n    def _convert_raw_text_chunks_to_chat(\n        tokens: Iterator[str], model_name: str\n    ) -> Iterator[ChatCompletionChunk]:\n        yield {\n            \"id\": \"chat\" + f\"cmpl-{str(uuid.uuid4())}\",\n            \"model\": model_name,\n            \"object\": \"chat.completion.chunk\",\n            \"created\": int(time.time()),\n            \"choices\": [\n                {\n                    \"index\": 0,\n                    \"delta\": {\n                        \"role\": \"assistant\",\n                    },\n                    \"finish_reason\": None,\n                }\n            ],\n        }\n        for token in enumerate(tokens):\n            yield {\n                \"id\": \"chat\" + f\"cmpl-{str(uuid.uuid4())}\",\n                \"model\": model_name,\n                \"object\": \"chat.completion.chunk\",\n                \"created\": int(time.time()),\n                \"choices\": [\n                    {\n                        \"index\": 0,\n                        \"delta\": {\n                            \"content\": token[1],\n                        },\n                        \"finish_reason\": None,\n                    }\n                ],\n            }\n\n    @staticmethod\n    def _convert_raw_text_completion_to_chat(\n        text: str, model_name: str\n    ) -> ChatCompletion:\n        return {\n            \"id\": \"chat\" + f\"cmpl-{str(uuid.uuid4())}\",\n            \"model\": model_name,\n            \"object\": \"chat.completion\",\n            \"created\": int(time.time()),\n            \"choices\": [\n                {\n                    \"index\": 0,\n                    \"message\": {\n                        \"role\": \"assistant\",\n                        \"content\": text,\n                    },\n                    \"finish_reason\": None,\n                }\n            ],\n            \"usage\": {\n                \"prompt_tokens\": -1,\n                \"completion_tokens\": -1,\n                \"total_tokens\": -1,\n            },\n        }\n\n    def chat(\n        self,\n        prompt: str,\n        chat_history: Optional[List[ChatCompletionMessage]] = None,\n        generate_config: Optional[ChatglmCppGenerateConfig] = None,\n    ) -> Union[ChatCompletion, Iterator[ChatCompletionChunk]]:\n        if chat_history is not None:\n            chat_history_list = [message[\"content\"] for message in chat_history]\n        else:\n            chat_history_list = []\n\n        chat_history_list.append(prompt)\n        logger.debug(\"Full conversation history:\\n%s\", str(chat_history_list))\n\n        generate_config = self._sanitize_generate_config(generate_config)\n        params = dict(generate_config)\n        if \"max_tokens\" in params:\n            params[\"max_length\"] = params.pop(\"max_tokens\")\n\n        assert self._llm is not None\n\n        if params.pop(\"stream\", False):\n            it = self._llm.stream_chat(\n                chat_history_list,\n                **params,\n            )\n            assert not isinstance(it, str)\n            return self._convert_raw_text_chunks_to_chat(it, self.model_uid)\n        else:\n            c = self._llm.chat(\n                chat_history_list,\n                **params,\n            )\n            assert not isinstance(c, Iterator)\n            return self._convert_raw_text_completion_to_chat(c, self.model_uid)\n", "path": "xinference/model/llm/ggml/chatglm.py"}]}