Zulelee commited on
Commit
8d50bff
1 Parent(s): 0bcb256

Upload 16 files

Browse files
Files changed (16) hide show
  1. .gitignore +176 -0
  2. .gitmodules +3 -0
  3. LICENSE +201 -0
  4. README.md +197 -9
  5. README_en.md +198 -0
  6. README_ja.md +158 -0
  7. copy_config_example.py +12 -0
  8. init_database.py +120 -0
  9. release.py +50 -0
  10. requirements.txt +66 -0
  11. requirements_api.txt +57 -0
  12. requirements_lite.txt +33 -0
  13. requirements_webui.txt +8 -0
  14. shutdown_all.sh +2 -0
  15. startup.py +900 -0
  16. webui.py +64 -0
.gitignore ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.log
2
+ *.log.*
3
+ *.bak
4
+ logs
5
+ /knowledge_base/*
6
+ !/knowledge_base/samples
7
+ /knowledge_base/samples/vector_store
8
+
9
+ /configs/*.py
10
+ .vscode/
11
+
12
+ # below are standard python ignore files
13
+ # Byte-compiled / optimized / DLL files
14
+ __pycache__/
15
+ *.py[cod]
16
+ *$py.class
17
+
18
+ # C extensions
19
+ *.so
20
+
21
+ # Distribution / packaging
22
+ .Python
23
+ build/
24
+ develop-eggs/
25
+ dist/
26
+ downloads/
27
+ eggs/
28
+ .eggs/
29
+ lib/
30
+ lib64/
31
+ parts/
32
+ sdist/
33
+ var/
34
+ wheels/
35
+ share/python-wheels/
36
+ *.egg-info/
37
+ .installed.cfg
38
+ *.egg
39
+ MANIFEST
40
+
41
+ # PyInstaller
42
+ # Usually these files are written by a python script from a template
43
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
44
+ *.manifest
45
+ *.spec
46
+
47
+ # Installer logs
48
+ pip-log.txt
49
+ pip-delete-this-directory.txt
50
+
51
+ # Unit test / coverage reports
52
+ htmlcov/
53
+ .tox/
54
+ .nox/
55
+ .coverage
56
+ .coverage.*
57
+ .cache
58
+ nosetests.xml
59
+ coverage.xml
60
+ *.cover
61
+ *.py,cover
62
+ .hypothesis/
63
+ .pytest_cache/
64
+ cover/
65
+
66
+ # Translations
67
+ *.mo
68
+ *.pot
69
+
70
+ # Django stuff:
71
+ *.log
72
+ local_settings.py
73
+ db.sqlite3
74
+ db.sqlite3-journal
75
+
76
+ # Flask stuff:
77
+ instance/
78
+ .webassets-cache
79
+
80
+ # Scrapy stuff:
81
+ .scrapy
82
+
83
+ # Sphinx documentation
84
+ docs/_build/
85
+
86
+ # PyBuilder
87
+ .pybuilder/
88
+ target/
89
+
90
+ # Jupyter Notebook
91
+ .ipynb_checkpoints
92
+
93
+ # IPython
94
+ profile_default/
95
+ ipython_config.py
96
+
97
+ # pyenv
98
+ # For a library or package, you might want to ignore these files since the code is
99
+ # intended to run in multiple environments; otherwise, check them in:
100
+ .python-version
101
+
102
+ # pipenv
103
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
104
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
105
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
106
+ # install all needed dependencies.
107
+ Pipfile.lock
108
+
109
+ # poetry
110
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
111
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
112
+ # commonly ignored for libraries.
113
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
114
+ poetry.lock
115
+
116
+ # pdm
117
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
118
+ #pdm.lock
119
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
120
+ # in version control.
121
+ # https://pdm.fming.dev/#use-with-ide
122
+ .pdm.toml
123
+
124
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
125
+ __pypackages__/
126
+
127
+ # Celery stuff
128
+ celerybeat-schedule
129
+ celerybeat.pid
130
+
131
+ # SageMath parsed files
132
+ *.sage.py
133
+
134
+ # Environments
135
+ .env
136
+ .venv
137
+ env/
138
+ venv/
139
+ ENV/
140
+ env.bak/
141
+ venv.bak/
142
+
143
+ # Spyder project settings
144
+ .spyderproject
145
+ .spyproject
146
+
147
+ # Rope project settings
148
+ .ropeproject
149
+
150
+ # mkdocs documentation
151
+ /site
152
+
153
+ # mypy
154
+ .mypy_cache/
155
+ .dmypy.json
156
+ dmypy.json
157
+
158
+ # Pyre type checker
159
+ .pyre/
160
+
161
+ # pytype static type analyzer
162
+ .pytype/
163
+
164
+ # Cython debug symbols
165
+ cython_debug/
166
+
167
+ # PyCharm
168
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
169
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
170
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
171
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
172
+ .idea/
173
+ .pytest_cache
174
+ .DS_Store
175
+
176
+
.gitmodules ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ [submodule "knowledge_base/samples/content/wiki"]
2
+ path = knowledge_base/samples/content/wiki
3
+ url = https://github.com/chatchat-space/Langchain-Chatchat.wiki.git
LICENSE ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
README.md CHANGED
@@ -1,12 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
- title: Langchain Chatchat
3
- emoji: 👁
4
- colorFrom: gray
5
- colorTo: red
6
- sdk: streamlit
7
- sdk_version: 1.30.0
8
- app_file: app.py
9
- pinned: false
 
 
 
 
 
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ![](img/logo-long-chatchat-trans-v2.png)
2
+
3
+ 🌍 [READ THIS IN ENGLISH](README_en.md)
4
+ 🌍 [日本語で読む](README_ja.md)
5
+
6
+ 📃 **LangChain-Chatchat** (原 Langchain-ChatGLM)
7
+
8
+ 基于 ChatGLM 等大语言模型与 Langchain 等应用框架实现,开源、可离线部署的检索增强生成(RAG)大模型知识库项目。
9
+
10
+ ⚠️`0.2.10`将会是`0.2.x`系列的最后一个版本,`0.2.x`系列版本将会停止更新和技术支持,全力研发具有更强应用性的 `Langchain-Chatchat 0.3.x`。
11
+
12
+ ---
13
+
14
+ ## 目录
15
+
16
+ * [介绍](README.md#介绍)
17
+ * [解决的痛点](README.md#解决的痛点)
18
+ * [快速上手](README.md#快速上手)
19
+ * [1. 环境配置](README.md#1-环境配置)
20
+ * [2. 模型下载](README.md#2-模型下载)
21
+ * [3. 初始化知识库和配置文件](README.md#3-初始化知识库和配置文件)
22
+ * [4. 一键启动](README.md#4-一键启动)
23
+ * [5. 启动界面示例](README.md#5-启动界面示例)
24
+ * [联系我们](README.md#联系我们)
25
+
26
+ ## 介绍
27
+
28
+ 🤖️ 一种利用 [langchain](https://github.com/langchain-ai/langchain)
29
+ 思想实现的基于本地知识库的问答应用,目标期望建立一套对中文场景与开源模型支持友好、可离线运行的知识库问答解决方案。
30
+
31
+ 💡 受 [GanymedeNil](https://github.com/GanymedeNil) 的项目 [document.ai](https://github.com/GanymedeNil/document.ai)
32
+ 和 [AlexZhangji](https://github.com/AlexZhangji)
33
+ 创建的 [ChatGLM-6B Pull Request](https://github.com/THUDM/ChatGLM-6B/pull/216)
34
+ 启发,建立了全流程可使用开源模型实现的本地知识库问答应用。本项目的最新版本中通过使用 [FastChat](https://github.com/lm-sys/FastChat)
35
+ 接入 Vicuna, Alpaca, LLaMA, Koala, RWKV 等模型,依托于 [langchain](https://github.com/langchain-ai/langchain)
36
+ 框架支持通过基于 [FastAPI](https://github.com/tiangolo/fastapi) 提供的 API
37
+ 调用服务,或使用基于 [Streamlit](https://github.com/streamlit/streamlit) 的 WebUI 进行操作。
38
+
39
+ ✅ 依托于本项目支持的开源 LLM 与 Embedding 模型,本项目可实现全部使用**开源**模型**离线私有部署**。与此同时,本项目也支持
40
+ OpenAI GPT API 的调用,并将在后续持续扩充对各类模型及模型 API 的接入。
41
+
42
+ ⛓️ 本项目实现原理如下图所示,过程包括加载文件 -> 读取文本 -> 文本分割 -> 文本向量化 -> 问句向量化 ->
43
+ 在文本向量中匹配出与问句向量最相似的 `top k`个 -> 匹配出的文本作为上下文和问题一起添加到 `prompt`中 -> 提交给 `LLM`生成回答。
44
+
45
+ 📺 [原理介绍视频](https://www.bilibili.com/video/BV13M4y1e7cN/?share_source=copy_web&vd_source=e6c5aafe684f30fbe41925d61ca6d514)
46
+
47
+ ![实现原理图](img/langchain+chatglm.png)
48
+
49
+ 从文档处理角度来看,实现流程如下:
50
+
51
+ ![实现原理图2](img/langchain+chatglm2.png)
52
+
53
+ 🚩 本项目未涉及微调、训练过程,但可利用微调或训练对本项目效果进行优化。
54
+
55
+ 🌐 [AutoDL 镜像](https://www.codewithgpu.com/i/chatchat-space/Langchain-Chatchat/Langchain-Chatchat) 中 `v0.2.10`
56
+ 版本所使用代码已更新至本项目 `v0.2.10` 版本。
57
+
58
+ 🐳 [Docker 镜像](registry.cn-beijing.aliyuncs.com/chatchat/chatchat:0.2.6) 已经更新到 ```0.2.7``` 版本。
59
+
60
+ 🌲 一行命令运行 Docker :
61
+
62
+ ```shell
63
+ docker run -d --gpus all -p 80:8501 registry.cn-beijing.aliyuncs.com/chatchat/chatchat:0.2.7
64
+ ```
65
+
66
+ 🧩 本项目有一个非常完整的[Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/) , README只是一个简单的介绍,_
67
+ _仅仅是入门教程,能够基础运行__。
68
+ 如果你想要更深入的了解本项目,或者想对本项目做出贡献。请移步 [Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/)
69
+ 界面
70
+
71
+ ## 解决的痛点
72
+
73
+ 该项目是一个可以实现 __完全本地化__推理的知识库增强方案, 重点解决数据安全保护,私域化部署的企业痛点。
74
+ 本开源方案采用```Apache License```,可以免费商用,无需付费。
75
+
76
+ 我们支持市面上主流的本地大语言模型和Embedding模型,支持开源的本地向量数据库。
77
+ 支持列表详见[Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/)
78
+
79
+ ## 快速上手
80
+
81
+ ### 1. 环境配置
82
+
83
+ + 首先,确保你的机器安装了 Python 3.8 - 3.11 (我们强烈推荐使用 Python3.11)。
84
+
85
+ ```
86
+ $ python --version
87
+ Python 3.11.7
88
+ ```
89
+
90
+ 接着,创建一个虚拟环境,并在虚拟环境内安装项目的依赖
91
+
92
+ ```shell
93
+
94
+ # 拉取仓库
95
+ $ git clone https://github.com/chatchat-space/Langchain-Chatchat.git
96
+
97
+ # 进入目录
98
+ $ cd Langchain-Chatchat
99
+
100
+ # 安装全部依赖
101
+ $ pip install -r requirements.txt
102
+ $ pip install -r requirements_api.txt
103
+ $ pip install -r requirements_webui.txt
104
+
105
+ # 默认依赖包括基本运行环境(FAISS向量库)。如果要使用 milvus/pg_vector 等向量库,请将 requirements.txt 中相应依赖取消注释再安装。
106
+ ```
107
+
108
+ 请注意,LangChain-Chatchat `0.2.x` 系列是针对 Langchain `0.0.x` 系列版本的,如果你使用的是 Langchain `0.1.x`
109
+ 系列版本,需要降级您的`Langchain`版本。
110
+
111
+ ### 2, 模型下载
112
+
113
+ 如需在本地或离线环境下运行本项目,需要首先将项目所需的模型下载至本地,通常开源 LLM 与 Embedding
114
+ 模型可以从 [HuggingFace](https://huggingface.co/models) 下载。
115
+
116
+ 以本项目中默认使用的 LLM 模型 [THUDM/ChatGLM3-6B](https://huggingface.co/THUDM/chatglm3-6b) 与 Embedding
117
+ 模型 [BAAI/bge-large-zh](https://huggingface.co/BAAI/bge-large-zh) 为例:
118
+
119
+ 下载模型需要先[安装 Git LFS](https://docs.github.com/zh/repositories/working-with-files/managing-large-files/installing-git-large-file-storage)
120
+ ,然后运行
121
+
122
+ ```Shell
123
+ $ git lfs install
124
+ $ git clone https://huggingface.co/THUDM/chatglm3-6b
125
+ $ git clone https://huggingface.co/BAAI/bge-large-zh
126
+ ```
127
+
128
+ ### 3. 初始化知识库和配置文件
129
+
130
+ 按照下列方式初始化自己的知识库和简单的复制配置文件
131
+
132
+ ```shell
133
+ $ python copy_config_example.py
134
+ $ python init_database.py --recreate-vs
135
+ ```
136
+
137
+ ### 4. 一键启动
138
+
139
+ 按照以下命令启动项目
140
+
141
+ ```shell
142
+ $ python startup.py -a
143
+ ```
144
+
145
+ ### 5. 启动界面示例
146
+
147
+ 如果正常启动,你将能看到以下界面
148
+
149
+ 1. FastAPI Docs 界面
150
+
151
+ ![](img/fastapi_docs_026.png)
152
+
153
+ 2. Web UI 启动界面示例:
154
+
155
+ - Web UI 对话界面:
156
+
157
+ ![img](img/LLM_success.png)
158
+
159
+ - Web UI 知识库管理页面:
160
+
161
+ ![](img/init_knowledge_base.jpg)
162
+
163
+ ### 注意
164
+
165
+ 以上方式只是为了快速上手,如果需要更多的功能和自定义启动方式
166
+ ,请参考[Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/)
167
+
168
+
169
  ---
170
+
171
+ ## 项目里程碑
172
+
173
+ + `2023年4月`: `Langchain-ChatGLM 0.1.0` 发布,支持基于 ChatGLM-6B 模型的本地知识库问答。
174
+ + `2023年8月`: `Langchain-ChatGLM` 改名为 `Langchain-Chatchat`,`0.2.0` 发布,使用 `fastchat` 作为模型加载方案,支持更多的模型和数据库。
175
+ + `2023年10月`: `Langchain-Chatchat 0.2.5` 发布,推出 Agent 内容,开源项目在`Founder Park & Zhipu AI & Zilliz`
176
+ 举办的黑客马拉松获得三等奖。
177
+ + `2023年12月`: `Langchain-Chatchat` 开源项目获得超过 **20K** stars.
178
+ + `2024年1月`: `LangChain 0.1.x` 推出,`Langchain-Chatchat 0.2.x` 发布稳定版本`0.2.10`
179
+ 后将停止更新和技术支持,全力研发具有更强应用性的 `Langchain-Chatchat 0.3.x`。
180
+
181
+ + 🔥 让我们一起期待未来 Chatchat 的故事 ···
182
+
183
  ---
184
 
185
+ ## 联系我们
186
+
187
+ ### Telegram
188
+
189
+ [![Telegram](https://img.shields.io/badge/Telegram-2CA5E0?style=for-the-badge&logo=telegram&logoColor=white "langchain-chatglm")](https://t.me/+RjliQ3jnJ1YyN2E9)
190
+
191
+ ### 项目交流群
192
+ <img src="img/qr_code_88.jpg" alt="二维码" width="300" />
193
+
194
+ 🎉 Langchain-Chatchat 项目微信交流群,如果你也对本项目感兴趣,欢迎加入群聊参与讨论交流。
195
+
196
+ ### 公众号
197
+
198
+ <img src="img/official_wechat_mp_account.png" alt="二维码" width="300" />
199
+
200
+ 🎉 Langchain-Chatchat 项目官方公众号,欢迎扫码关注。
README_en.md ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ![](img/logo-long-chatchat-trans-v2.png)
2
+
3
+ 🌍 [中文文档](README.md)
4
+ 🌍 [日本語で読む](README_ja.md)
5
+
6
+ 📃 **LangChain-Chatchat** (formerly Langchain-ChatGLM):
7
+
8
+ A LLM application aims to implement knowledge and search engine based QA based on Langchain and open-source or remote
9
+ LLM API.
10
+
11
+ ⚠️`0.2.10` will be the last version of the `0.2.x` series. The `0.2.x` series will stop updating and technical support,
12
+ and strive to develop `Langchain-Chachat 0.3.x with stronger applicability. `.
13
+
14
+
15
+ ---
16
+
17
+ ## Table of Contents
18
+
19
+ - [Introduction](README.md#Introduction)
20
+ - [Pain Points Addressed](README.md#Pain-Points-Addressed)
21
+ - [Quick Start](README.md#Quick-Start)
22
+ - [1. Environment Setup](README.md#1-Environment-Setup)
23
+ - [2. Model Download](README.md#2-Model-Download)
24
+ - [3. Initialize Knowledge Base and Configuration Files](README.md#3-Initialize-Knowledge-Base-and-Configuration-Files)
25
+ - [4. One-Click Startup](README.md#4-One-Click-Startup)
26
+ - [5. Startup Interface Examples](README.md#5-Startup-Interface-Examples)
27
+ - [Contact Us](README.md#Contact-Us)
28
+
29
+ ## Introduction
30
+
31
+ 🤖️ A Q&A application based on local knowledge base implemented using the idea
32
+ of [langchain](https://github.com/langchain-ai/langchain). The goal is to build a KBQA(Knowledge based Q&A) solution
33
+ that
34
+ is friendly to Chinese scenarios and open source models and can run both offline and online.
35
+
36
+ 💡 Inspired by [document.ai](https://github.com/GanymedeNil/document.ai)
37
+ and [ChatGLM-6B Pull Request](https://github.com/THUDM/ChatGLM-6B/pull/216) , we build a local knowledge base question
38
+ answering application that can be implemented using an open source model or remote LLM api throughout the process. In
39
+ the latest version of this project, [FastChat](https://github.com/lm-sys/FastChat) is used to access Vicuna, Alpaca,
40
+ LLaMA, Koala, RWKV and many other models. Relying on [langchain](https://github.com/langchain-ai/langchain) , this
41
+ project supports calling services through the API provided based on [FastAPI](https://github.com/tiangolo/fastapi), or
42
+ using the WebUI based on [Streamlit](https://github.com/streamlit/streamlit).
43
+
44
+ ✅ Relying on the open source LLM and Embedding models, this project can realize full-process **offline private
45
+ deployment**. At the same time, this project also supports the call of OpenAI GPT API- and Zhipu API, and will continue
46
+ to expand the access to various models and remote APIs in the future.
47
+
48
+ ⛓️ The implementation principle of this project is shown in the graph below. The main process includes: loading files ->
49
+ reading text -> text segmentation -> text vectorization -> question vectorization -> matching the `top-k` most similar
50
+ to the question vector in the text vector -> The matched text is added to `prompt `as context and question -> submitte
51
+ to `LLM` to generate an answer.
52
+
53
+ 📺[video introduction](https://www.bilibili.com/video/BV13M4y1e7cN/?share_source=copy_web&vd_source=e6c5aafe684f30fbe41925d61ca6d514)
54
+
55
+ ![实现原理图](img/langchain+chatglm.png)
56
+
57
+ The main process analysis from the aspect of document process:
58
+
59
+ ![实现原理图2](img/langchain+chatglm2.png)
60
+
61
+ 🚩 The training or fine-tuning are not involved in the project, but still, one always can improve performance by do
62
+ these.
63
+
64
+ 🌐 [AutoDL image](https://www.codewithgpu.com/i/chatchat-space/Langchain-Chatchat/Langchain-Chatchat) is supported, and in v13 the codes are update to v0.2.9.
65
+
66
+ 🐳 [Docker image](registry.cn-beijing.aliyuncs.com/chatchat/chatchat:0.2.7) is supported to 0.2.7
67
+
68
+ ## Pain Points Addressed
69
+
70
+ This project is a solution for enhancing knowledge bases with fully localized inference, specifically addressing the
71
+ pain points of data security and private deployments for businesses.
72
+ This open-source solution is under the Apache License and can be used for commercial purposes for free, with no fees
73
+ required.
74
+ We support mainstream local large prophecy models and Embedding models available in the market, as well as open-source
75
+ local vector databases. For a detailed list of supported models and databases, please refer to
76
+ our [Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/)
77
+
78
+ ## Quick Start
79
+
80
+ ### Environment Setup
81
+
82
+ First, make sure your machine has Python 3.10 installed.
83
+
84
+ ```
85
+ $ python --version
86
+ Python 3.10.12
87
+ ```
88
+
89
+ Then, create a virtual environment and install the project's dependencies within the virtual environment.
90
+
91
+ ```shell
92
+
93
+ # 拉取仓库
94
+ $ git clone https://github.com/chatchat-space/Langchain-Chatchat.git
95
+
96
+ # 进入目录
97
+ $ cd Langchain-Chatchat
98
+
99
+ # 安装全部依赖
100
+ $ pip install -r requirements.txt
101
+ $ pip install -r requirements_api.txt
102
+ $ pip install -r requirements_webui.txt
103
+
104
+ # 默认依赖包括基本运行环境(FAISS向量库)。如果要使用 milvus/pg_vector 等向量库,请将 requirements.txt 中相应依赖取消注释再安装。
105
+ ```
106
+
107
+ Please note that the LangChain-Chachat `0.2.x` series is for the Langchain `0.0.x` series version. If you are using the
108
+ Langchain `0.1.x` series version, you need to downgrade.
109
+
110
+ ### Model Download
111
+
112
+ If you need to run this project locally or in an offline environment, you must first download the required models for
113
+ the project. Typically, open-source LLM and Embedding models can be downloaded from HuggingFace.
114
+
115
+ Taking the default LLM model used in this project, [THUDM/chatglm2-6b](https://huggingface.co/THUDM/chatglm2-6b), and
116
+ the Embedding model [moka-ai/m3e-base](https://huggingface.co/moka-ai/m3e-base) as examples:
117
+
118
+ To download the models, you need to first
119
+ install [Git LFS](https://docs.github.com/zh/repositories/working-with-files/managing-large-files/installing-git-large-file-storage)
120
+ and then run:
121
+
122
+ ```Shell
123
+ $ git lfs install
124
+ $ git clone https://huggingface.co/THUDM/chatglm2-6b
125
+ $ git clone https://huggingface.co/moka-ai/m3e-base
126
+ ```
127
+
128
+ ### Initializing the Knowledge Base and Config File
129
+
130
+ Follow the steps below to initialize your own knowledge base and config file:
131
+
132
+ ```shell
133
+ $ python copy_config_example.py
134
+ $ python init_database.py --recreate-vs
135
+ ```
136
+
137
+ ### One-Click Launch
138
+
139
+ To start the project, run the following command:
140
+
141
+ ```shell
142
+ $ python startup.py -a
143
+ ```
144
+
145
+ ### Example of Launch Interface
146
+
147
+ 1. FastAPI docs interface
148
+
149
+ ![](img/fastapi_docs_026.png)
150
+
151
+ 2. webui page
152
+
153
+ - Web UI dialog page:
154
+
155
+ ![img](img/LLM_success.png)
156
+
157
+ - Web UI knowledge base management page:
158
+
159
+ ![](img/init_knowledge_base.jpg)
160
+
161
+ ### Note
162
+
163
+ The above instructions are provided for a quick start. If you need more features or want to customize the launch method,
164
+ please refer to the [Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/).
165
+
166
+ ---
167
+
168
+ ## Project Milestones
169
+
170
+ + `April 2023`: `Langchain-ChatGLM 0.1.0` released, supporting local knowledge base question and answer based on the
171
+ ChatGLM-6B model.
172
+ + `August 2023`: `Langchain-ChatGLM` was renamed to `Langchain-Chatchat`, `0.2.0` was released, using `fastchat` as the
173
+ model loading solution, supporting more models and databases.
174
+ + `October 2023`: `Langchain-Chachat 0.2.5` was released, Agent content was launched, and the open source project won
175
+ the third prize in the hackathon held by `Founder Park & Zhipu AI & Zilliz`.
176
+ + `December 2023`: `Langchain-Chachat` open source project received more than **20K** stars.
177
+ + `January 2024`: `LangChain 0.1.x` is launched, `Langchain-Chachat 0.2.x` is released. After the stable
178
+ version `0.2.10` is released, updates and technical support will be stopped, and all efforts will be made to
179
+ develop `Langchain with stronger applicability -Chat 0.3.x`.
180
+
181
+
182
+ + 🔥 Let’s look forward to the future Chatchat stories together···
183
+
184
+ ---
185
+
186
+ ## Contact Us
187
+
188
+ ### Telegram
189
+
190
+ [![Telegram](https://img.shields.io/badge/Telegram-2CA5E0?style=for-the-badge&logo=telegram&logoColor=white "langchain-chatglm")](https://t.me/+RjliQ3jnJ1YyN2E9)
191
+
192
+ ### WeChat Group
193
+
194
+ <img src="img/qr_code_87.jpg" alt="二维码" width="300" height="300" />
195
+
196
+ ### WeChat Official Account
197
+
198
+ <img src="img/official_wechat_mp_account.png" alt="图片" width="900" height="300" />
README_ja.md ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ![](img/logo-long-chatchat-trans-v2.png)
2
+
3
+ 🌍 [中文文档](README.md)
4
+ 🌍 [READ THIS IN ENGLISH](README_en.md)
5
+
6
+ 📃 **LangChain-Chatchat** (旧名 Langchain-ChatGLM):
7
+
8
+ LLM アプリケーションは、Langchain とオープンソースまたはリモートの LLM API に基づいて、知識と検索エンジンベースの QA を実装することを目的としています。
9
+
10
+ ---
11
+
12
+ ## 目次
13
+
14
+ - [イントロ](README_ja.md#イントロ)
15
+ - [ペインポイントへの対応](README_ja.md#ペインポイントへの対応)
16
+ - [クイックスタート](README_ja.md#クイックスタート)
17
+ - [1. 環境セットアップ](README_ja.md#環境セットアップ)
18
+ - [2. モデルをダウンロード](README_ja.md#モデルをダウンロード)
19
+ - [3. ナレッジベースと設定ファイルの初期化](README_ja.md#ナレッジベースと設定ファイルの初期化)
20
+ - [4. ワンクリック起動](README_ja.md#ワンクリック起動)
21
+ - [5. 起動インターフェースの例](README_ja.md#起動インターフェースの例)
22
+ - [お問い合わせ](README_ja.md#お問い合わせ)
23
+
24
+ ## イントロ
25
+
26
+ 🤖️ [langchain](https://github.com/hwchase17/langchain) のアイデアを用いて実装された、ローカルナレッジベースに基づく Q&A アプリケーション。
27
+ 目標は、中国のシナリオとオープンソースモデルに親和性があり、オフラインとオンラインの両方で実行可能な KBQA(ナレッジベースの Q&A)ソリューションを構築することです。
28
+
29
+ 💡 [document.ai](https://github.com/GanymedeNil/document.ai) と [ChatGLM-6B Pull Request](https://github.com/THUDM/ChatGLM-6B/pull/216) に触発され、
30
+ プロセス全体を通してオープンソースモデルまたはリモート LLM api を使用して実装することができるローカルナレッジベースの質問応答アプリケーションを構築します。
31
+ このプロジェクトの最新バージョンでは、[FastChat](https://github.com/lm-sys/FastChat) を使用して、Vicuna、Alpaca、LLaMA、Koala、RWKV、その他多くのモデルにアクセスしています。
32
+ このプロジェクトは [langchain](https://github.com/langchain-ai/langchain) に依存し、[FastAPI](https://github.com/tiangolo/fastapi) に基づいて提供されるAPIを通してサービスを呼び出したり、
33
+ [Streamlit](https://github.com/streamlit/streamlit) に基づいて WebUI を使ったりすることをサポートしています。
34
+
35
+ ✅ オープンソースの LLM と Embedding モデルに依存して、このプロジェクトはフルプロセスの **オフラインプライベートデプロイメント** を実現することができます。
36
+ 同時に、本プロジェクトは OpenAI GPT API や Zhipu API の呼び出しにも対応しており、今後も様々な機種やリモート API へのアクセスを拡大していきます。
37
+
38
+ ⛓️ このプロジェクトの実施原則を下のグラフに示します。主なプロセスは以下の通りです:
39
+ ファイルの読み込み -> テキストの読み込み -> テキストのセグメンテーション -> テキストのベクトル化 -> 質問のベクトル化 -> 質問ベクトルと最も似ている `top-k` をテキストベクトルでマッチング -> マッチしたテキストをコンテキストと質問として `prompt` に追加 -> 回答を生成するために `LLM` に送信。
40
+
41
+ 📺[video introduction](https://www.bilibili.com/video/BV13M4y1e7cN/?share_source=copy_web&vd_source=e6c5aafe684f30fbe41925d61ca6d514)
42
+
43
+ ![实现原理图](img/langchain+chatglm.png)
44
+
45
+ 文書プロセスの側面からの主なプロセス分析:
46
+
47
+ ![实现原理图2](img/langchain+chatglm2.png)
48
+
49
+ 🚩 トレーニングやファインチューニングはプロジェクトには含まれないが、これらを行うことで必ずパフォーマンスを向上させることができます。
50
+
51
+ 🌐 [AutoDL イメージ](registry.cn-beijing.aliyuncs.com/chatchat/chatchat:0.2.5)がサポートされ、v13 では v0.2.9 にアップデートされました。
52
+
53
+ 🐳 [Docker イメージ](registry.cn-beijing.aliyuncs.com/chatchat/chatchat:0.2.7)
54
+
55
+ ## ペインポイントへの対応
56
+
57
+ このプロジェクトは、完全にローカライズされた推論によってナレッジベースを強化するソリューションであり、特にデータセキュリティと企業向けのプライベートな展開の問題に取り組んでいます。
58
+ このオープンソースソリューションは Apache ライセンスに基づき、無償で商用利用できます。
59
+ 私たちは、市場で入手可能な主流のローカル大予言モデルや Embedding モデル、オープンソースのローカルベクターデータベースをサポートしています。
60
+ 対応機種とデータベースの詳細については、[Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/) をご参照くださ���。
61
+
62
+ ## クイックスタート
63
+
64
+ ### 環境セットアップ
65
+
66
+ まず、マシンにPython 3.10がインストールされていることを確認してください。
67
+
68
+ ```
69
+ $ python --version
70
+ Python 3.10.12
71
+ ```
72
+
73
+ 次に、仮想環境を作成し、プロジェクトの依存関係を仮想環境内にインストールする。
74
+
75
+ ```shell
76
+
77
+ # リポジトリをクローン
78
+ $ git clone https://github.com/chatchat-space/Langchain-Chatchat.git
79
+
80
+ # ディレクトリに移動
81
+ $ cd Langchain-Chatchat
82
+
83
+ # すべての依存関係をインストール
84
+ $ pip install -r requirements.txt
85
+ $ pip install -r requirements_api.txt
86
+ $ pip install -r requirements_webui.txt
87
+
88
+ # デフォルトの依存関係には、基本的な実行環境(FAISS ベクターライブラリ)が含まれます。milvus/pg_vector などのベクターライブラリを使用する場合は、requirements.txt 内の対応する依存関係のコメントを解除してからインストールしてください。
89
+ ```
90
+ LangChain-Chachat `0.2.x` シリーズは Langchain `0.0.x` シリーズ用です。Langchain `0.1.x` シリーズをお使いの場合は、ダウングレードする必要があります。
91
+
92
+ ### モデルをダウンロード
93
+
94
+ このプロジェクトをローカルまたはオフライン環境で実行する必要がある場合は、まずプロジェクトに必要なモデルをダウンロードする必要があります。
95
+ 通常、オープンソースの LLM と Embedding モデルは Hugging Face からダウンロードできる。
96
+
97
+ このプロジェクトで使用されているデフォルトの LLM モデルである [THUDM/chatglm2-6b](https://huggingface.co/THUDM/chatglm2-6b)と、Embedding モデル [moka-ai/m3e-base](https://huggingface.co/moka-ai/m3e-base) を例にとると、次のようになります:
98
+
99
+ モデルをダウンロードするには、まず [Git LFS](https://docs.github.com/zh/repositories/working-with-files/managing-large-files/installing-git-large-file-storage) をインストールし、次のように実行する必要があります:
100
+
101
+ ```Shell
102
+ $ git lfs install
103
+ $ git clone https://huggingface.co/THUDM/chatglm2-6b
104
+ $ git clone https://huggingface.co/moka-ai/m3e-base
105
+ ```
106
+
107
+ ### ナレッジベースと設定ファイルの初期化
108
+
109
+ 以下の手順に従って、ナレッジベースと設定ファイルを初期化してください:
110
+
111
+ ```shell
112
+ $ python copy_config_example.py
113
+ $ python init_database.py --recreate-vs
114
+ ```
115
+
116
+ ### ワンクリック起動
117
+
118
+ プロジェクトを開始するには、次のコマンドを実行します:
119
+
120
+ ```shell
121
+ $ python startup.py -a
122
+ ```
123
+
124
+ ### 起動インターフェースの例
125
+
126
+ 1. FastAPI docs インターフェース
127
+
128
+ ![](img/fastapi_docs_026.png)
129
+
130
+ 2. webui ページ
131
+
132
+ - Web UI ダイアログページ:
133
+
134
+ ![img](img/LLM_success.png)
135
+
136
+ - Web UI ナレッジベースマネジメントページ:
137
+
138
+ ![](img/init_knowledge_base.jpg)
139
+
140
+ ### 注
141
+
142
+ 上記の手順はクイックスタートのために提供されています。より多くの機能が必要な場合や、起動方法をカスタマイズしたい場合は、[Wiki](https://github.com/chatchat-space/Langchain-Chatchat/wiki/) を参照してください。
143
+
144
+ ---
145
+
146
+ ## お問い合わせ
147
+
148
+ ### Telegram
149
+
150
+ [![Telegram](https://img.shields.io/badge/Telegram-2CA5E0?style=for-the-badge&logo=telegram&logoColor=white "langchain-chatglm")](https://t.me/+RjliQ3jnJ1YyN2E9)
151
+
152
+ ### WeChat グループ
153
+
154
+ <img src="img/qr_code_67.jpg" alt="二维码" width="300" height="300" />
155
+
156
+ ### WeChat 公式アカウント
157
+
158
+ <img src="img/official_wechat_mp_account.png" alt="图片" width="900" height="300" />
copy_config_example.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 用于批量将configs下的.example文件复制并命名为.py文件
2
+ import os
3
+ import shutil
4
+
5
+ if __name__ == "__main__":
6
+ files = os.listdir("configs")
7
+
8
+ src_files = [os.path.join("configs", file) for file in files if ".example" in file]
9
+
10
+ for src_file in src_files:
11
+ tar_file = src_file.replace(".example", "")
12
+ shutil.copy(src_file, tar_file)
init_database.py ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ sys.path.append(".")
3
+ from server.knowledge_base.migrate import (create_tables, reset_tables, import_from_db,
4
+ folder2db, prune_db_docs, prune_folder_files)
5
+ from configs.model_config import NLTK_DATA_PATH, EMBEDDING_MODEL
6
+ import nltk
7
+ nltk.data.path = [NLTK_DATA_PATH] + nltk.data.path
8
+ from datetime import datetime
9
+
10
+
11
+ if __name__ == "__main__":
12
+ import argparse
13
+
14
+ parser = argparse.ArgumentParser(description="please specify only one operate method once time.")
15
+
16
+ parser.add_argument(
17
+ "-r",
18
+ "--recreate-vs",
19
+ action="store_true",
20
+ help=('''
21
+ recreate vector store.
22
+ use this option if you have copied document files to the content folder, but vector store has not been populated or DEFAUL_VS_TYPE/EMBEDDING_MODEL changed.
23
+ '''
24
+ )
25
+ )
26
+ parser.add_argument(
27
+ "--create-tables",
28
+ action="store_true",
29
+ help=("create empty tables if not existed")
30
+ )
31
+ parser.add_argument(
32
+ "--clear-tables",
33
+ action="store_true",
34
+ help=("create empty tables, or drop the database tables before recreate vector stores")
35
+ )
36
+ parser.add_argument(
37
+ "--import-db",
38
+ help="import tables from specified sqlite database"
39
+ )
40
+ parser.add_argument(
41
+ "-u",
42
+ "--update-in-db",
43
+ action="store_true",
44
+ help=('''
45
+ update vector store for files exist in database.
46
+ use this option if you want to recreate vectors for files exist in db and skip files exist in local folder only.
47
+ '''
48
+ )
49
+ )
50
+ parser.add_argument(
51
+ "-i",
52
+ "--increment",
53
+ action="store_true",
54
+ help=('''
55
+ update vector store for files exist in local folder and not exist in database.
56
+ use this option if you want to create vectors incrementally.
57
+ '''
58
+ )
59
+ )
60
+ parser.add_argument(
61
+ "--prune-db",
62
+ action="store_true",
63
+ help=('''
64
+ delete docs in database that not existed in local folder.
65
+ it is used to delete database docs after user deleted some doc files in file browser
66
+ '''
67
+ )
68
+ )
69
+ parser.add_argument(
70
+ "--prune-folder",
71
+ action="store_true",
72
+ help=('''
73
+ delete doc files in local folder that not existed in database.
74
+ is is used to free local disk space by delete unused doc files.
75
+ '''
76
+ )
77
+ )
78
+ parser.add_argument(
79
+ "-n",
80
+ "--kb-name",
81
+ type=str,
82
+ nargs="+",
83
+ default=[],
84
+ help=("specify knowledge base names to operate on. default is all folders exist in KB_ROOT_PATH.")
85
+ )
86
+ parser.add_argument(
87
+ "-e",
88
+ "--embed-model",
89
+ type=str,
90
+ default=EMBEDDING_MODEL,
91
+ help=("specify embeddings model.")
92
+ )
93
+
94
+ args = parser.parse_args()
95
+ start_time = datetime.now()
96
+
97
+ if args.create_tables:
98
+ create_tables() # confirm tables exist
99
+
100
+ if args.clear_tables:
101
+ reset_tables()
102
+ print("database tables reset")
103
+
104
+ if args.recreate_vs:
105
+ create_tables()
106
+ print("recreating all vector stores")
107
+ folder2db(kb_names=args.kb_name, mode="recreate_vs", embed_model=args.embed_model)
108
+ elif args.import_db:
109
+ import_from_db(args.import_db)
110
+ elif args.update_in_db:
111
+ folder2db(kb_names=args.kb_name, mode="update_in_db", embed_model=args.embed_model)
112
+ elif args.increment:
113
+ folder2db(kb_names=args.kb_name, mode="increment", embed_model=args.embed_model)
114
+ elif args.prune_db:
115
+ prune_db_docs(args.kb_name)
116
+ elif args.prune_folder:
117
+ prune_folder_files(args.kb_name)
118
+
119
+ end_time = datetime.now()
120
+ print(f"总计用时: {end_time-start_time}")
release.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import subprocess
3
+ import re
4
+
5
+ def get_latest_tag():
6
+ output = subprocess.check_output(['git', 'tag'])
7
+ tags = output.decode('utf-8').split('\n')[:-1]
8
+ latest_tag = sorted(tags, key=lambda t: tuple(map(int, re.match(r'v(\d+)\.(\d+)\.(\d+)', t).groups())))[-1]
9
+ return latest_tag
10
+
11
+ def update_version_number(latest_tag, increment):
12
+ major, minor, patch = map(int, re.match(r'v(\d+)\.(\d+)\.(\d+)', latest_tag).groups())
13
+ if increment == 'X':
14
+ major += 1
15
+ minor, patch = 0, 0
16
+ elif increment == 'Y':
17
+ minor += 1
18
+ patch = 0
19
+ elif increment == 'Z':
20
+ patch += 1
21
+ new_version = f"v{major}.{minor}.{patch}"
22
+ return new_version
23
+
24
+ def main():
25
+ print("当前最近的Git标签:")
26
+ latest_tag = get_latest_tag()
27
+ print(latest_tag)
28
+
29
+ print("请选择要递增的版本号部分(X, Y, Z):")
30
+ increment = input().upper()
31
+
32
+ while increment not in ['X', 'Y', 'Z']:
33
+ print("输入错误,请输入X, Y或Z:")
34
+ increment = input().upper()
35
+
36
+ new_version = update_version_number(latest_tag, increment)
37
+ print(f"新的版本号为:{new_version}")
38
+
39
+ print("确认更新版本号并推送到远程仓库?(y/n)")
40
+ confirmation = input().lower()
41
+
42
+ if confirmation == 'y':
43
+ subprocess.run(['git', 'tag', new_version])
44
+ subprocess.run(['git', 'push', 'origin', new_version])
45
+ print("新版本号已创建并推送到远程仓库。")
46
+ else:
47
+ print("操作已取消。")
48
+
49
+ if __name__ == '__main__':
50
+ main()
requirements.txt ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ torch==2.1.2
2
+ torchvision==0.16.2
3
+ torchaudio==2.1.2
4
+ xformers==0.0.23.post1
5
+ transformers==4.36.2
6
+ sentence_transformers==2.2.2
7
+ langchain==0.0.354
8
+ langchain-experimental==0.0.47
9
+ pydantic==1.10.13
10
+ fschat==0.2.35
11
+ openai==1.9.0
12
+ fastapi==0.109.0
13
+ sse_starlette==1.8.2
14
+ nltk==3.8.1
15
+ uvicorn==0.24.0.post1
16
+ starlette==0.35.0
17
+ unstructured[all-docs] # ==0.11.8
18
+ python-magic-bin; sys_platform == 'win32'
19
+ SQLAlchemy==2.0.25
20
+ faiss-cpu==1.7.4
21
+ accelerate==0.24.1
22
+ spacy==3.7.2
23
+ PyMuPDF==1.23.16
24
+ rapidocr_onnxruntime==1.3.8
25
+ requests==2.31.0
26
+ pathlib==1.0.1
27
+ pytest==7.4.3
28
+ numexpr==2.8.6
29
+ strsimpy==0.2.1
30
+ markdownify==0.11.6
31
+ tiktoken==0.5.2
32
+ tqdm==4.66.1
33
+ websockets==12.0
34
+ numpy==1.24.4
35
+ pandas==2.0.3
36
+ einops==0.7.0
37
+ transformers_stream_generator==0.0.4
38
+ vllm==0.2.7; sys_platform == "linux"
39
+ llama-index==0.9.35
40
+
41
+ #jq==1.6.0
42
+ # beautifulsoup4==4.12.2
43
+ # pysrt==1.1.2
44
+ # dashscope==1.13.6 # qwen
45
+ # volcengine==1.0.119 # fangzhou
46
+ # uncomment libs if you want to use corresponding vector store
47
+ # pymilvus==2.3.4
48
+ # psycopg2==2.9.9
49
+ # pgvector==0.2.4
50
+ #flash-attn==2.4.2 # For Orion-14B-Chat and Qwen-14B-Chat
51
+ #autoawq==0.1.8 # For Int4
52
+ #rapidocr_paddle[gpu]==1.3.11 # gpu accelleration for ocr of pdf and image files
53
+
54
+ arxiv==2.1.0
55
+ youtube-search==2.1.2
56
+ duckduckgo-search==3.9.9
57
+ metaphor-python==0.1.23
58
+ streamlit==1.30.0
59
+ streamlit-option-menu==0.3.12
60
+ streamlit-antd-components==0.3.1
61
+ streamlit-chatbox==1.1.11
62
+ streamlit-modal==0.1.0
63
+ streamlit-aggrid==0.3.4.post3
64
+ httpx==0.26.0
65
+ watchdog==3.0.0
66
+ jwt==1.3.1
requirements_api.txt ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ torch~=2.1.2
2
+ torchvision~=0.16.2
3
+ torchaudio~=2.1.2
4
+ xformers>=0.0.23.post1
5
+ transformers==4.36.2
6
+ sentence_transformers==2.2.2
7
+ langchain==0.0.354
8
+ langchain-experimental==0.0.47
9
+ pydantic==1.10.13
10
+ fschat==0.2.35
11
+ openai~=1.9.0
12
+ fastapi~=0.109.0
13
+ sse_starlette==1.8.2
14
+ nltk>=3.8.1
15
+ uvicorn>=0.24.0.post1
16
+ starlette~=0.35.0
17
+ unstructured[all-docs]==0.11.0
18
+ python-magic-bin; sys_platform == 'win32'
19
+ SQLAlchemy==2.0.19
20
+ faiss-cpu~=1.7.4
21
+ accelerate~=0.24.1
22
+ spacy~=3.7.2
23
+ PyMuPDF~=1.23.8
24
+ rapidocr_onnxruntime==1.3.8
25
+ requests~=2.31.0
26
+ pathlib~=1.0.1
27
+ pytest~=7.4.3
28
+ numexpr~=2.8.6
29
+ strsimpy~=0.2.1
30
+ markdownify~=0.11.6
31
+ tiktoken~=0.5.2
32
+ tqdm>=4.66.1
33
+ websockets>=12.0
34
+ numpy~=1.24.4
35
+ pandas~=2.0.3
36
+ einops>=0.7.0
37
+ transformers_stream_generator==0.0.4
38
+ vllm==0.2.7; sys_platform == "linux"
39
+ httpx==0.26.0
40
+ llama-index==0.9.35
41
+
42
+ # jq==1.6.0
43
+ # beautifulsoup4~=4.12.2
44
+ # pysrt~=1.1.2
45
+ # dashscope==1.13.6
46
+ # arxiv~=2.1.0
47
+ # youtube-search~=2.1.2
48
+ # duckduckgo-search~=3.9.9
49
+ # metaphor-python~=0.1.23
50
+
51
+ # volcengine>=1.0.119
52
+ # pymilvus>=2.3.4
53
+ # psycopg2==2.9.9
54
+ # pgvector>=0.2.4
55
+ #flash-attn==2.4.2 # For Orion-14B-Chat and Qwen-14B-Chat
56
+ #autoawq==0.1.8 # For Int4
57
+ #rapidocr_paddle[gpu]==1.3.11 # gpu accelleration for ocr of pdf and image files
requirements_lite.txt ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ langchain==0.0.354
2
+ langchain-experimental==0.0.47
3
+ pydantic==1.10.13
4
+ fschat~=0.2.35
5
+ openai~=1.9.0
6
+ fastapi~=0.109.0
7
+ sse_starlette~=1.8.2
8
+ nltk~=3.8.1
9
+ uvicorn~=0.24.0.post1
10
+ starlette~=0.35.0
11
+ unstructured[all-docs]~=0.12.0
12
+ python-magic-bin; sys_platform == 'win32'
13
+ SQLAlchemy~=2.0.25
14
+ faiss-cpu~=1.7.4
15
+ accelerate~=0.24.1
16
+ spacy~=3.7.2
17
+ PyMuPDF~=1.23.16
18
+ rapidocr_onnxruntime~=1.3.8
19
+ requests~=2.31.0
20
+ pathlib~=1.0.1
21
+ pytest~=7.4.3
22
+ llama-index==0.9.35
23
+
24
+ dashscope==1.13.6
25
+ arxiv~=2.1.0
26
+ youtube-search~=2.1.2
27
+ duckduckgo-search~=3.9.9
28
+ metaphor-python~=0.1.23
29
+ watchdog~=3.0.0
30
+ # volcengine>=1.0.119
31
+ # pymilvus>=2.3.4
32
+ # psycopg2==2.9.9
33
+ # pgvector>=0.2.4
requirements_webui.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ streamlit~=1.30.0
2
+ streamlit-option-menu~=0.3.12
3
+ streamlit-antd-components~=0.3.1
4
+ streamlit-chatbox~=1.1.11
5
+ streamlit-modal~=0.1.0
6
+ streamlit-aggrid~=0.3.4.post3
7
+ httpx~=0.26.0
8
+ watchdog~=3.0.0
shutdown_all.sh ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ # mac设备上的grep命令可能不支持grep -P选项,请使用Homebrew安装;或使用ggrep命令
2
+ ps -eo pid,user,cmd|grep -P 'server/api.py|webui.py|fastchat.serve|multiprocessing'|grep -v grep|awk '{print $1}'|xargs kill -9
startup.py ADDED
@@ -0,0 +1,900 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import multiprocessing as mp
3
+ import os
4
+ import subprocess
5
+ import sys
6
+ from multiprocessing import Process
7
+ from datetime import datetime
8
+ from pprint import pprint
9
+ from langchain_core._api import deprecated
10
+
11
+ try:
12
+ import numexpr
13
+
14
+ n_cores = numexpr.utils.detect_number_of_cores()
15
+ os.environ["NUMEXPR_MAX_THREADS"] = str(n_cores)
16
+ except:
17
+ pass
18
+
19
+ sys.path.append(os.path.dirname(os.path.dirname(__file__)))
20
+ from configs import (
21
+ LOG_PATH,
22
+ log_verbose,
23
+ logger,
24
+ LLM_MODELS,
25
+ EMBEDDING_MODEL,
26
+ TEXT_SPLITTER_NAME,
27
+ FSCHAT_CONTROLLER,
28
+ FSCHAT_OPENAI_API,
29
+ FSCHAT_MODEL_WORKERS,
30
+ API_SERVER,
31
+ WEBUI_SERVER,
32
+ HTTPX_DEFAULT_TIMEOUT,
33
+ )
34
+ from server.utils import (fschat_controller_address, fschat_model_worker_address,
35
+ fschat_openai_api_address, get_httpx_client, get_model_worker_config,
36
+ MakeFastAPIOffline, FastAPI, llm_device, embedding_device)
37
+ from server.knowledge_base.migrate import create_tables
38
+ import argparse
39
+ from typing import List, Dict
40
+ from configs import VERSION
41
+
42
+
43
+ @deprecated(
44
+ since="0.3.0",
45
+ message="模型启动功能将于 Langchain-Chatchat 0.3.x重写,支持更多模式和加速启动,0.2.x中相关功能将废弃",
46
+ removal="0.3.0")
47
+ def create_controller_app(
48
+ dispatch_method: str,
49
+ log_level: str = "INFO",
50
+ ) -> FastAPI:
51
+ import fastchat.constants
52
+ fastchat.constants.LOGDIR = LOG_PATH
53
+ from fastchat.serve.controller import app, Controller, logger
54
+ logger.setLevel(log_level)
55
+
56
+ controller = Controller(dispatch_method)
57
+ sys.modules["fastchat.serve.controller"].controller = controller
58
+
59
+ MakeFastAPIOffline(app)
60
+ app.title = "FastChat Controller"
61
+ app._controller = controller
62
+ return app
63
+
64
+
65
+ def create_model_worker_app(log_level: str = "INFO", **kwargs) -> FastAPI:
66
+ """
67
+ kwargs包含的字段如下:
68
+ host:
69
+ port:
70
+ model_names:[`model_name`]
71
+ controller_address:
72
+ worker_address:
73
+
74
+ 对于Langchain支持的模型:
75
+ langchain_model:True
76
+ 不会使用fschat
77
+ 对于online_api:
78
+ online_api:True
79
+ worker_class: `provider`
80
+ 对于离线模型:
81
+ model_path: `model_name_or_path`,huggingface的repo-id或本地路径
82
+ device:`LLM_DEVICE`
83
+ """
84
+ import fastchat.constants
85
+ fastchat.constants.LOGDIR = LOG_PATH
86
+ import argparse
87
+
88
+ parser = argparse.ArgumentParser()
89
+ args = parser.parse_args([])
90
+
91
+ for k, v in kwargs.items():
92
+ setattr(args, k, v)
93
+ if worker_class := kwargs.get("langchain_model"): # Langchian支持的模型不用做操作
94
+ from fastchat.serve.base_model_worker import app
95
+ worker = ""
96
+ # 在线模型API
97
+ elif worker_class := kwargs.get("worker_class"):
98
+ from fastchat.serve.base_model_worker import app
99
+
100
+ worker = worker_class(model_names=args.model_names,
101
+ controller_addr=args.controller_address,
102
+ worker_addr=args.worker_address)
103
+ # sys.modules["fastchat.serve.base_model_worker"].worker = worker
104
+ sys.modules["fastchat.serve.base_model_worker"].logger.setLevel(log_level)
105
+ # 本地模型
106
+ else:
107
+ from configs.model_config import VLLM_MODEL_DICT
108
+ if kwargs["model_names"][0] in VLLM_MODEL_DICT and args.infer_turbo == "vllm":
109
+ import fastchat.serve.vllm_worker
110
+ from fastchat.serve.vllm_worker import VLLMWorker, app, worker_id
111
+ from vllm import AsyncLLMEngine
112
+ from vllm.engine.arg_utils import AsyncEngineArgs
113
+
114
+ args.tokenizer = args.model_path
115
+ args.tokenizer_mode = 'auto'
116
+ args.trust_remote_code = True
117
+ args.download_dir = None
118
+ args.load_format = 'auto'
119
+ args.dtype = 'auto'
120
+ args.seed = 0
121
+ args.worker_use_ray = False
122
+ args.pipeline_parallel_size = 1
123
+ args.tensor_parallel_size = 1
124
+ args.block_size = 16
125
+ args.swap_space = 4 # GiB
126
+ args.gpu_memory_utilization = 0.90
127
+ args.max_num_batched_tokens = None # 一个批次中的最大令牌(tokens)数量,这个取决于你的显卡和大模型设置,设置太大显存会不够
128
+ args.max_num_seqs = 256
129
+ args.disable_log_stats = False
130
+ args.conv_template = None
131
+ args.limit_worker_concurrency = 5
132
+ args.no_register = False
133
+ args.num_gpus = 1 # vllm worker的切分是tensor并行,这里填写显卡的数量
134
+ args.engine_use_ray = False
135
+ args.disable_log_requests = False
136
+
137
+ # 0.2.1 vllm后要加的参数, 但是这里不需要
138
+ args.max_model_len = None
139
+ args.revision = None
140
+ args.quantization = None
141
+ args.max_log_len = None
142
+ args.tokenizer_revision = None
143
+
144
+ # 0.2.2 vllm需要新加的参���
145
+ args.max_paddings = 256
146
+
147
+ if args.model_path:
148
+ args.model = args.model_path
149
+ if args.num_gpus > 1:
150
+ args.tensor_parallel_size = args.num_gpus
151
+
152
+ for k, v in kwargs.items():
153
+ setattr(args, k, v)
154
+
155
+ engine_args = AsyncEngineArgs.from_cli_args(args)
156
+ engine = AsyncLLMEngine.from_engine_args(engine_args)
157
+
158
+ worker = VLLMWorker(
159
+ controller_addr=args.controller_address,
160
+ worker_addr=args.worker_address,
161
+ worker_id=worker_id,
162
+ model_path=args.model_path,
163
+ model_names=args.model_names,
164
+ limit_worker_concurrency=args.limit_worker_concurrency,
165
+ no_register=args.no_register,
166
+ llm_engine=engine,
167
+ conv_template=args.conv_template,
168
+ )
169
+ sys.modules["fastchat.serve.vllm_worker"].engine = engine
170
+ sys.modules["fastchat.serve.vllm_worker"].worker = worker
171
+ sys.modules["fastchat.serve.vllm_worker"].logger.setLevel(log_level)
172
+
173
+ else:
174
+ from fastchat.serve.model_worker import app, GptqConfig, AWQConfig, ModelWorker, worker_id
175
+
176
+ args.gpus = "0" # GPU的编号,如果有多个GPU,可以设置为"0,1,2,3"
177
+ args.max_gpu_memory = "22GiB"
178
+ args.num_gpus = 1 # model worker的切分是model并行,这里填写显卡的数量
179
+
180
+ args.load_8bit = False
181
+ args.cpu_offloading = None
182
+ args.gptq_ckpt = None
183
+ args.gptq_wbits = 16
184
+ args.gptq_groupsize = -1
185
+ args.gptq_act_order = False
186
+ args.awq_ckpt = None
187
+ args.awq_wbits = 16
188
+ args.awq_groupsize = -1
189
+ args.model_names = [""]
190
+ args.conv_template = None
191
+ args.limit_worker_concurrency = 5
192
+ args.stream_interval = 2
193
+ args.no_register = False
194
+ args.embed_in_truncate = False
195
+ for k, v in kwargs.items():
196
+ setattr(args, k, v)
197
+ if args.gpus:
198
+ if args.num_gpus is None:
199
+ args.num_gpus = len(args.gpus.split(','))
200
+ if len(args.gpus.split(",")) < args.num_gpus:
201
+ raise ValueError(
202
+ f"Larger --num-gpus ({args.num_gpus}) than --gpus {args.gpus}!"
203
+ )
204
+ os.environ["CUDA_VISIBLE_DEVICES"] = args.gpus
205
+ gptq_config = GptqConfig(
206
+ ckpt=args.gptq_ckpt or args.model_path,
207
+ wbits=args.gptq_wbits,
208
+ groupsize=args.gptq_groupsize,
209
+ act_order=args.gptq_act_order,
210
+ )
211
+ awq_config = AWQConfig(
212
+ ckpt=args.awq_ckpt or args.model_path,
213
+ wbits=args.awq_wbits,
214
+ groupsize=args.awq_groupsize,
215
+ )
216
+
217
+ worker = ModelWorker(
218
+ controller_addr=args.controller_address,
219
+ worker_addr=args.worker_address,
220
+ worker_id=worker_id,
221
+ model_path=args.model_path,
222
+ model_names=args.model_names,
223
+ limit_worker_concurrency=args.limit_worker_concurrency,
224
+ no_register=args.no_register,
225
+ device=args.device,
226
+ num_gpus=args.num_gpus,
227
+ max_gpu_memory=args.max_gpu_memory,
228
+ load_8bit=args.load_8bit,
229
+ cpu_offloading=args.cpu_offloading,
230
+ gptq_config=gptq_config,
231
+ awq_config=awq_config,
232
+ stream_interval=args.stream_interval,
233
+ conv_template=args.conv_template,
234
+ embed_in_truncate=args.embed_in_truncate,
235
+ )
236
+ sys.modules["fastchat.serve.model_worker"].args = args
237
+ sys.modules["fastchat.serve.model_worker"].gptq_config = gptq_config
238
+ # sys.modules["fastchat.serve.model_worker"].worker = worker
239
+ sys.modules["fastchat.serve.model_worker"].logger.setLevel(log_level)
240
+
241
+ MakeFastAPIOffline(app)
242
+ app.title = f"FastChat LLM Server ({args.model_names[0]})"
243
+ app._worker = worker
244
+ return app
245
+
246
+
247
+ def create_openai_api_app(
248
+ controller_address: str,
249
+ api_keys: List = [],
250
+ log_level: str = "INFO",
251
+ ) -> FastAPI:
252
+ import fastchat.constants
253
+ fastchat.constants.LOGDIR = LOG_PATH
254
+ from fastchat.serve.openai_api_server import app, CORSMiddleware, app_settings
255
+ from fastchat.utils import build_logger
256
+ logger = build_logger("openai_api", "openai_api.log")
257
+ logger.setLevel(log_level)
258
+
259
+ app.add_middleware(
260
+ CORSMiddleware,
261
+ allow_credentials=True,
262
+ allow_origins=["*"],
263
+ allow_methods=["*"],
264
+ allow_headers=["*"],
265
+ )
266
+
267
+ sys.modules["fastchat.serve.openai_api_server"].logger = logger
268
+ app_settings.controller_address = controller_address
269
+ app_settings.api_keys = api_keys
270
+
271
+ MakeFastAPIOffline(app)
272
+ app.title = "FastChat OpeanAI API Server"
273
+ return app
274
+
275
+
276
+ def _set_app_event(app: FastAPI, started_event: mp.Event = None):
277
+ @app.on_event("startup")
278
+ async def on_startup():
279
+ if started_event is not None:
280
+ started_event.set()
281
+
282
+
283
+ def run_controller(log_level: str = "INFO", started_event: mp.Event = None):
284
+ import uvicorn
285
+ import httpx
286
+ from fastapi import Body
287
+ import time
288
+ import sys
289
+ from server.utils import set_httpx_config
290
+ set_httpx_config()
291
+
292
+ app = create_controller_app(
293
+ dispatch_method=FSCHAT_CONTROLLER.get("dispatch_method"),
294
+ log_level=log_level,
295
+ )
296
+ _set_app_event(app, started_event)
297
+
298
+ # add interface to release and load model worker
299
+ @app.post("/release_worker")
300
+ def release_worker(
301
+ model_name: str = Body(..., description="要释放模型的名称", samples=["chatglm-6b"]),
302
+ # worker_address: str = Body(None, description="要释放模型的地址,与名称二选一", samples=[FSCHAT_CONTROLLER_address()]),
303
+ new_model_name: str = Body(None, description="释放后加载该模型"),
304
+ keep_origin: bool = Body(False, description="不释放原模型,加载新模型")
305
+ ) -> Dict:
306
+ available_models = app._controller.list_models()
307
+ if new_model_name in available_models:
308
+ msg = f"要切换的LLM模型 {new_model_name} 已经存在"
309
+ logger.info(msg)
310
+ return {"code": 500, "msg": msg}
311
+
312
+ if new_model_name:
313
+ logger.info(f"开始切换LLM模型:从 {model_name} 到 {new_model_name}")
314
+ else:
315
+ logger.info(f"即将停止LLM模型: {model_name}")
316
+
317
+ if model_name not in available_models:
318
+ msg = f"the model {model_name} is not available"
319
+ logger.error(msg)
320
+ return {"code": 500, "msg": msg}
321
+
322
+ worker_address = app._controller.get_worker_address(model_name)
323
+ if not worker_address:
324
+ msg = f"can not find model_worker address for {model_name}"
325
+ logger.error(msg)
326
+ return {"code": 500, "msg": msg}
327
+
328
+ with get_httpx_client() as client:
329
+ r = client.post(worker_address + "/release",
330
+ json={"new_model_name": new_model_name, "keep_origin": keep_origin})
331
+ if r.status_code != 200:
332
+ msg = f"failed to release model: {model_name}"
333
+ logger.error(msg)
334
+ return {"code": 500, "msg": msg}
335
+
336
+ if new_model_name:
337
+ timer = HTTPX_DEFAULT_TIMEOUT # wait for new model_worker register
338
+ while timer > 0:
339
+ models = app._controller.list_models()
340
+ if new_model_name in models:
341
+ break
342
+ time.sleep(1)
343
+ timer -= 1
344
+ if timer > 0:
345
+ msg = f"sucess change model from {model_name} to {new_model_name}"
346
+ logger.info(msg)
347
+ return {"code": 200, "msg": msg}
348
+ else:
349
+ msg = f"failed change model from {model_name} to {new_model_name}"
350
+ logger.error(msg)
351
+ return {"code": 500, "msg": msg}
352
+ else:
353
+ msg = f"sucess to release model: {model_name}"
354
+ logger.info(msg)
355
+ return {"code": 200, "msg": msg}
356
+
357
+ host = FSCHAT_CONTROLLER["host"]
358
+ port = FSCHAT_CONTROLLER["port"]
359
+
360
+ if log_level == "ERROR":
361
+ sys.stdout = sys.__stdout__
362
+ sys.stderr = sys.__stderr__
363
+
364
+ uvicorn.run(app, host=host, port=port, log_level=log_level.lower())
365
+
366
+
367
+ def run_model_worker(
368
+ model_name: str = LLM_MODELS[0],
369
+ controller_address: str = "",
370
+ log_level: str = "INFO",
371
+ q: mp.Queue = None,
372
+ started_event: mp.Event = None,
373
+ ):
374
+ import uvicorn
375
+ from fastapi import Body
376
+ import sys
377
+ from server.utils import set_httpx_config
378
+ set_httpx_config()
379
+
380
+ kwargs = get_model_worker_config(model_name)
381
+ host = kwargs.pop("host")
382
+ port = kwargs.pop("port")
383
+ kwargs["model_names"] = [model_name]
384
+ kwargs["controller_address"] = controller_address or fschat_controller_address()
385
+ kwargs["worker_address"] = fschat_model_worker_address(model_name)
386
+ model_path = kwargs.get("model_path", "")
387
+ kwargs["model_path"] = model_path
388
+
389
+ app = create_model_worker_app(log_level=log_level, **kwargs)
390
+ _set_app_event(app, started_event)
391
+ if log_level == "ERROR":
392
+ sys.stdout = sys.__stdout__
393
+ sys.stderr = sys.__stderr__
394
+
395
+ # add interface to release and load model
396
+ @app.post("/release")
397
+ def release_model(
398
+ new_model_name: str = Body(None, description="释放后加载该模型"),
399
+ keep_origin: bool = Body(False, description="不释放原模型,加载新模型")
400
+ ) -> Dict:
401
+ if keep_origin:
402
+ if new_model_name:
403
+ q.put([model_name, "start", new_model_name])
404
+ else:
405
+ if new_model_name:
406
+ q.put([model_name, "replace", new_model_name])
407
+ else:
408
+ q.put([model_name, "stop", None])
409
+ return {"code": 200, "msg": "done"}
410
+
411
+ uvicorn.run(app, host=host, port=port, log_level=log_level.lower())
412
+
413
+
414
+ def run_openai_api(log_level: str = "INFO", started_event: mp.Event = None):
415
+ import uvicorn
416
+ import sys
417
+ from server.utils import set_httpx_config
418
+ set_httpx_config()
419
+
420
+ controller_addr = fschat_controller_address()
421
+ app = create_openai_api_app(controller_addr, log_level=log_level)
422
+ _set_app_event(app, started_event)
423
+
424
+ host = FSCHAT_OPENAI_API["host"]
425
+ port = FSCHAT_OPENAI_API["port"]
426
+ if log_level == "ERROR":
427
+ sys.stdout = sys.__stdout__
428
+ sys.stderr = sys.__stderr__
429
+ uvicorn.run(app, host=host, port=port)
430
+
431
+
432
+ def run_api_server(started_event: mp.Event = None, run_mode: str = None):
433
+ from server.api import create_app
434
+ import uvicorn
435
+ from server.utils import set_httpx_config
436
+ set_httpx_config()
437
+
438
+ app = create_app(run_mode=run_mode)
439
+ _set_app_event(app, started_event)
440
+
441
+ host = API_SERVER["host"]
442
+ port = API_SERVER["port"]
443
+
444
+ uvicorn.run(app, host=host, port=port)
445
+
446
+
447
+ def run_webui(started_event: mp.Event = None, run_mode: str = None):
448
+ from server.utils import set_httpx_config
449
+ set_httpx_config()
450
+
451
+ host = WEBUI_SERVER["host"]
452
+ port = WEBUI_SERVER["port"]
453
+
454
+ cmd = ["streamlit", "run", "webui.py",
455
+ "--server.address", host,
456
+ "--server.port", str(port),
457
+ "--theme.base", "light",
458
+ "--theme.primaryColor", "#165dff",
459
+ "--theme.secondaryBackgroundColor", "#f5f5f5",
460
+ "--theme.textColor", "#000000",
461
+ ]
462
+ if run_mode == "lite":
463
+ cmd += [
464
+ "--",
465
+ "lite",
466
+ ]
467
+ p = subprocess.Popen(cmd)
468
+ started_event.set()
469
+ p.wait()
470
+
471
+
472
+ def parse_args() -> argparse.ArgumentParser:
473
+ parser = argparse.ArgumentParser()
474
+ parser.add_argument(
475
+ "-a",
476
+ "--all-webui",
477
+ action="store_true",
478
+ help="run fastchat's controller/openai_api/model_worker servers, run api.py and webui.py",
479
+ dest="all_webui",
480
+ )
481
+ parser.add_argument(
482
+ "--all-api",
483
+ action="store_true",
484
+ help="run fastchat's controller/openai_api/model_worker servers, run api.py",
485
+ dest="all_api",
486
+ )
487
+ parser.add_argument(
488
+ "--llm-api",
489
+ action="store_true",
490
+ help="run fastchat's controller/openai_api/model_worker servers",
491
+ dest="llm_api",
492
+ )
493
+ parser.add_argument(
494
+ "-o",
495
+ "--openai-api",
496
+ action="store_true",
497
+ help="run fastchat's controller/openai_api servers",
498
+ dest="openai_api",
499
+ )
500
+ parser.add_argument(
501
+ "-m",
502
+ "--model-worker",
503
+ action="store_true",
504
+ help="run fastchat's model_worker server with specified model name. "
505
+ "specify --model-name if not using default LLM_MODELS",
506
+ dest="model_worker",
507
+ )
508
+ parser.add_argument(
509
+ "-n",
510
+ "--model-name",
511
+ type=str,
512
+ nargs="+",
513
+ default=LLM_MODELS,
514
+ help="specify model name for model worker. "
515
+ "add addition names with space seperated to start multiple model workers.",
516
+ dest="model_name",
517
+ )
518
+ parser.add_argument(
519
+ "-c",
520
+ "--controller",
521
+ type=str,
522
+ help="specify controller address the worker is registered to. default is FSCHAT_CONTROLLER",
523
+ dest="controller_address",
524
+ )
525
+ parser.add_argument(
526
+ "--api",
527
+ action="store_true",
528
+ help="run api.py server",
529
+ dest="api",
530
+ )
531
+ parser.add_argument(
532
+ "-p",
533
+ "--api-worker",
534
+ action="store_true",
535
+ help="run online model api such as zhipuai",
536
+ dest="api_worker",
537
+ )
538
+ parser.add_argument(
539
+ "-w",
540
+ "--webui",
541
+ action="store_true",
542
+ help="run webui.py server",
543
+ dest="webui",
544
+ )
545
+ parser.add_argument(
546
+ "-q",
547
+ "--quiet",
548
+ action="store_true",
549
+ help="减少fastchat服务log信息",
550
+ dest="quiet",
551
+ )
552
+ parser.add_argument(
553
+ "-i",
554
+ "--lite",
555
+ action="store_true",
556
+ help="以Lite模式运行:仅支持在线API的LLM对话、搜索引擎对话",
557
+ dest="lite",
558
+ )
559
+ args = parser.parse_args()
560
+ return args, parser
561
+
562
+
563
+ def dump_server_info(after_start=False, args=None):
564
+ import platform
565
+ import langchain
566
+ import fastchat
567
+ from server.utils import api_address, webui_address
568
+
569
+ print("\n")
570
+ print("=" * 30 + "Langchain-Chatchat Configuration" + "=" * 30)
571
+ print(f"操作系统:{platform.platform()}.")
572
+ print(f"python版本:{sys.version}")
573
+ print(f"项目版本:{VERSION}")
574
+ print(f"langchain版本:{langchain.__version__}. fastchat版本:{fastchat.__version__}")
575
+ print("\n")
576
+
577
+ models = LLM_MODELS
578
+ if args and args.model_name:
579
+ models = args.model_name
580
+
581
+ print(f"当前使用的分词器:{TEXT_SPLITTER_NAME}")
582
+ print(f"当前启动的LLM模型:{models} @ {llm_device()}")
583
+
584
+ for model in models:
585
+ pprint(get_model_worker_config(model))
586
+ print(f"当前Embbedings模型: {EMBEDDING_MODEL} @ {embedding_device()}")
587
+
588
+ if after_start:
589
+ print("\n")
590
+ print(f"服务端运行信息:")
591
+ if args.openai_api:
592
+ print(f" OpenAI API Server: {fschat_openai_api_address()}")
593
+ if args.api:
594
+ print(f" Chatchat API Server: {api_address()}")
595
+ if args.webui:
596
+ print(f" Chatchat WEBUI Server: {webui_address()}")
597
+ print("=" * 30 + "Langchain-Chatchat Configuration" + "=" * 30)
598
+ print("\n")
599
+
600
+
601
+ async def start_main_server():
602
+ import time
603
+ import signal
604
+
605
+ def handler(signalname):
606
+ """
607
+ Python 3.9 has `signal.strsignal(signalnum)` so this closure would not be needed.
608
+ Also, 3.8 includes `signal.valid_signals()` that can be used to create a mapping for the same purpose.
609
+ """
610
+
611
+ def f(signal_received, frame):
612
+ raise KeyboardInterrupt(f"{signalname} received")
613
+
614
+ return f
615
+
616
+ # This will be inherited by the child process if it is forked (not spawned)
617
+ signal.signal(signal.SIGINT, handler("SIGINT"))
618
+ signal.signal(signal.SIGTERM, handler("SIGTERM"))
619
+
620
+ mp.set_start_method("spawn")
621
+ manager = mp.Manager()
622
+ run_mode = None
623
+
624
+ queue = manager.Queue()
625
+ args, parser = parse_args()
626
+
627
+ if args.all_webui:
628
+ args.openai_api = True
629
+ args.model_worker = True
630
+ args.api = True
631
+ args.api_worker = True
632
+ args.webui = True
633
+
634
+ elif args.all_api:
635
+ args.openai_api = True
636
+ args.model_worker = True
637
+ args.api = True
638
+ args.api_worker = True
639
+ args.webui = False
640
+
641
+ elif args.llm_api:
642
+ args.openai_api = True
643
+ args.model_worker = True
644
+ args.api_worker = True
645
+ args.api = False
646
+ args.webui = False
647
+
648
+ if args.lite:
649
+ args.model_worker = False
650
+ run_mode = "lite"
651
+
652
+ dump_server_info(args=args)
653
+
654
+ if len(sys.argv) > 1:
655
+ logger.info(f"正在启动服务:")
656
+ logger.info(f"如需查看 llm_api 日志,请前往 {LOG_PATH}")
657
+
658
+ processes = {"online_api": {}, "model_worker": {}}
659
+
660
+ def process_count():
661
+ return len(processes) + len(processes["online_api"]) + len(processes["model_worker"]) - 2
662
+
663
+ if args.quiet or not log_verbose:
664
+ log_level = "ERROR"
665
+ else:
666
+ log_level = "INFO"
667
+
668
+ controller_started = manager.Event()
669
+ if args.openai_api:
670
+ process = Process(
671
+ target=run_controller,
672
+ name=f"controller",
673
+ kwargs=dict(log_level=log_level, started_event=controller_started),
674
+ daemon=True,
675
+ )
676
+ processes["controller"] = process
677
+
678
+ process = Process(
679
+ target=run_openai_api,
680
+ name=f"openai_api",
681
+ daemon=True,
682
+ )
683
+ processes["openai_api"] = process
684
+
685
+ model_worker_started = []
686
+ if args.model_worker:
687
+ for model_name in args.model_name:
688
+ config = get_model_worker_config(model_name)
689
+ if not config.get("online_api"):
690
+ e = manager.Event()
691
+ model_worker_started.append(e)
692
+ process = Process(
693
+ target=run_model_worker,
694
+ name=f"model_worker - {model_name}",
695
+ kwargs=dict(model_name=model_name,
696
+ controller_address=args.controller_address,
697
+ log_level=log_level,
698
+ q=queue,
699
+ started_event=e),
700
+ daemon=True,
701
+ )
702
+ processes["model_worker"][model_name] = process
703
+
704
+ if args.api_worker:
705
+ for model_name in args.model_name:
706
+ config = get_model_worker_config(model_name)
707
+ if (config.get("online_api")
708
+ and config.get("worker_class")
709
+ and model_name in FSCHAT_MODEL_WORKERS):
710
+ e = manager.Event()
711
+ model_worker_started.append(e)
712
+ process = Process(
713
+ target=run_model_worker,
714
+ name=f"api_worker - {model_name}",
715
+ kwargs=dict(model_name=model_name,
716
+ controller_address=args.controller_address,
717
+ log_level=log_level,
718
+ q=queue,
719
+ started_event=e),
720
+ daemon=True,
721
+ )
722
+ processes["online_api"][model_name] = process
723
+
724
+ api_started = manager.Event()
725
+ if args.api:
726
+ process = Process(
727
+ target=run_api_server,
728
+ name=f"API Server",
729
+ kwargs=dict(started_event=api_started, run_mode=run_mode),
730
+ daemon=True,
731
+ )
732
+ processes["api"] = process
733
+
734
+ webui_started = manager.Event()
735
+ if args.webui:
736
+ process = Process(
737
+ target=run_webui,
738
+ name=f"WEBUI Server",
739
+ kwargs=dict(started_event=webui_started, run_mode=run_mode),
740
+ daemon=True,
741
+ )
742
+ processes["webui"] = process
743
+
744
+ if process_count() == 0:
745
+ parser.print_help()
746
+ else:
747
+ try:
748
+ # 保证任务收到SIGINT后,能够正常退出
749
+ if p := processes.get("controller"):
750
+ p.start()
751
+ p.name = f"{p.name} ({p.pid})"
752
+ controller_started.wait() # 等待controller启动完成
753
+
754
+ if p := processes.get("openai_api"):
755
+ p.start()
756
+ p.name = f"{p.name} ({p.pid})"
757
+
758
+ for n, p in processes.get("model_worker", {}).items():
759
+ p.start()
760
+ p.name = f"{p.name} ({p.pid})"
761
+
762
+ for n, p in processes.get("online_api", []).items():
763
+ p.start()
764
+ p.name = f"{p.name} ({p.pid})"
765
+
766
+ # 等待所有model_worker启动完成
767
+ for e in model_worker_started:
768
+ e.wait()
769
+
770
+ if p := processes.get("api"):
771
+ p.start()
772
+ p.name = f"{p.name} ({p.pid})"
773
+ api_started.wait() # 等待api.py启动完成
774
+
775
+ if p := processes.get("webui"):
776
+ p.start()
777
+ p.name = f"{p.name} ({p.pid})"
778
+ webui_started.wait() # 等待webui.py启动完成
779
+
780
+ dump_server_info(after_start=True, args=args)
781
+
782
+ while True:
783
+ cmd = queue.get() # 收到切换模型的消息
784
+ e = manager.Event()
785
+ if isinstance(cmd, list):
786
+ model_name, cmd, new_model_name = cmd
787
+ if cmd == "start": # 运行新模型
788
+ logger.info(f"准备启动新模型进程:{new_model_name}")
789
+ process = Process(
790
+ target=run_model_worker,
791
+ name=f"model_worker - {new_model_name}",
792
+ kwargs=dict(model_name=new_model_name,
793
+ controller_address=args.controller_address,
794
+ log_level=log_level,
795
+ q=queue,
796
+ started_event=e),
797
+ daemon=True,
798
+ )
799
+ process.start()
800
+ process.name = f"{process.name} ({process.pid})"
801
+ processes["model_worker"][new_model_name] = process
802
+ e.wait()
803
+ logger.info(f"成功启动新模型进程:{new_model_name}")
804
+ elif cmd == "stop":
805
+ if process := processes["model_worker"].get(model_name):
806
+ time.sleep(1)
807
+ process.terminate()
808
+ process.join()
809
+ logger.info(f"停止模型进程:{model_name}")
810
+ else:
811
+ logger.error(f"未找到模型进程:{model_name}")
812
+ elif cmd == "replace":
813
+ if process := processes["model_worker"].pop(model_name, None):
814
+ logger.info(f"停止模型进程:{model_name}")
815
+ start_time = datetime.now()
816
+ time.sleep(1)
817
+ process.terminate()
818
+ process.join()
819
+ process = Process(
820
+ target=run_model_worker,
821
+ name=f"model_worker - {new_model_name}",
822
+ kwargs=dict(model_name=new_model_name,
823
+ controller_address=args.controller_address,
824
+ log_level=log_level,
825
+ q=queue,
826
+ started_event=e),
827
+ daemon=True,
828
+ )
829
+ process.start()
830
+ process.name = f"{process.name} ({process.pid})"
831
+ processes["model_worker"][new_model_name] = process
832
+ e.wait()
833
+ timing = datetime.now() - start_time
834
+ logger.info(f"成功启动新模型进程:{new_model_name}。用时:{timing}。")
835
+ else:
836
+ logger.error(f"未找到模型进程:{model_name}")
837
+
838
+ # for process in processes.get("model_worker", {}).values():
839
+ # process.join()
840
+ # for process in processes.get("online_api", {}).values():
841
+ # process.join()
842
+
843
+ # for name, process in processes.items():
844
+ # if name not in ["model_worker", "online_api"]:
845
+ # if isinstance(p, dict):
846
+ # for work_process in p.values():
847
+ # work_process.join()
848
+ # else:
849
+ # process.join()
850
+ except Exception as e:
851
+ logger.error(e)
852
+ logger.warning("Caught KeyboardInterrupt! Setting stop event...")
853
+ finally:
854
+ # Send SIGINT if process doesn't exit quickly enough, and kill it as last resort
855
+ # .is_alive() also implicitly joins the process (good practice in linux)
856
+ # while alive_procs := [p for p in processes.values() if p.is_alive()]:
857
+
858
+ for p in processes.values():
859
+ logger.warning("Sending SIGKILL to %s", p)
860
+ # Queues and other inter-process communication primitives can break when
861
+ # process is killed, but we don't care here
862
+
863
+ if isinstance(p, dict):
864
+ for process in p.values():
865
+ process.kill()
866
+ else:
867
+ p.kill()
868
+
869
+ for p in processes.values():
870
+ logger.info("Process status: %s", p)
871
+
872
+
873
+ if __name__ == "__main__":
874
+ create_tables()
875
+ if sys.version_info < (3, 10):
876
+ loop = asyncio.get_event_loop()
877
+ else:
878
+ try:
879
+ loop = asyncio.get_running_loop()
880
+ except RuntimeError:
881
+ loop = asyncio.new_event_loop()
882
+
883
+ asyncio.set_event_loop(loop)
884
+
885
+ loop.run_until_complete(start_main_server())
886
+
887
+ # 服务启动后接口调用示例:
888
+ # import openai
889
+ # openai.api_key = "EMPTY" # Not support yet
890
+ # openai.api_base = "http://localhost:8888/v1"
891
+
892
+ # model = "chatglm3-6b"
893
+
894
+ # # create a chat completion
895
+ # completion = openai.ChatCompletion.create(
896
+ # model=model,
897
+ # messages=[{"role": "user", "content": "Hello! What is your name?"}]
898
+ # )
899
+ # # print the completion
900
+ # print(completion.choices[0].message.content)
webui.py ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from webui_pages.utils import *
3
+ from streamlit_option_menu import option_menu
4
+ from webui_pages.dialogue.dialogue import dialogue_page, chat_box
5
+ from webui_pages.knowledge_base.knowledge_base import knowledge_base_page
6
+ import os
7
+ import sys
8
+ from configs import VERSION
9
+ from server.utils import api_address
10
+
11
+
12
+ api = ApiRequest(base_url=api_address())
13
+
14
+ if __name__ == "__main__":
15
+ is_lite = "lite" in sys.argv
16
+
17
+ st.set_page_config(
18
+ "Langchain-Chatchat WebUI",
19
+ os.path.join("img", "chatchat_icon_blue_square_v2.png"),
20
+ initial_sidebar_state="expanded",
21
+ menu_items={
22
+ 'Get Help': 'https://github.com/chatchat-space/Langchain-Chatchat',
23
+ 'Report a bug': "https://github.com/chatchat-space/Langchain-Chatchat/issues",
24
+ 'About': f"""欢迎使用 Langchain-Chatchat WebUI {VERSION}!"""
25
+ }
26
+ )
27
+
28
+ pages = {
29
+ "对话": {
30
+ "icon": "chat",
31
+ "func": dialogue_page,
32
+ },
33
+ "知识库管理": {
34
+ "icon": "hdd-stack",
35
+ "func": knowledge_base_page,
36
+ },
37
+ }
38
+
39
+ with st.sidebar:
40
+ st.image(
41
+ os.path.join(
42
+ "img",
43
+ "logo-long-chatchat-trans-v2.png"
44
+ ),
45
+ use_column_width=True
46
+ )
47
+ st.caption(
48
+ f"""<p align="right">当前版本:{VERSION}</p>""",
49
+ unsafe_allow_html=True,
50
+ )
51
+ options = list(pages)
52
+ icons = [x["icon"] for x in pages.values()]
53
+
54
+ default_index = 0
55
+ selected_page = option_menu(
56
+ "",
57
+ options=options,
58
+ icons=icons,
59
+ # menu_icon="chat-quote",
60
+ default_index=default_index,
61
+ )
62
+
63
+ if selected_page in pages:
64
+ pages[selected_page]["func"](api=api, is_lite=is_lite)