Spaces:
Running
Running
Upload 16 files
Browse files- .gitignore +176 -0
- .gitmodules +3 -0
- LICENSE +201 -0
- README.md +197 -9
- README_en.md +198 -0
- README_ja.md +158 -0
- copy_config_example.py +12 -0
- init_database.py +120 -0
- release.py +50 -0
- requirements.txt +66 -0
- requirements_api.txt +57 -0
- requirements_lite.txt +33 -0
- requirements_webui.txt +8 -0
- shutdown_all.sh +2 -0
- startup.py +900 -0
- 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 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
|
|
|
|
|
|
|
|
|
|
10 |
---
|
11 |
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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)
|