├── Dockerfile ├── Dockerfile.Base ├── LICENSE ├── README.md ├── __pycache__ └── config.cpython-39.pyc ├── app.py ├── chatllm.py ├── chinese_text_splitter.py ├── config.py ├── docs ├── deploy.md ├── faq.md └── update_history.md ├── img ├── bg.jpg ├── demo.jpg ├── demo_hf.jpg ├── demo_ms.jpg ├── demo_new.jpg └── wechat_group.jpg ├── jina_serving.py ├── model_cache └── OfflineDeploy.md ├── modelscope ├── README.md ├── app.py ├── chatglm_llm.py ├── modelscope_hub.py └── requirements.txt ├── nltk_data ├── taggers │ └── averaged_perceptron_tagger │ │ └── averaged_perceptron_tagger.pickle └── tokenizers │ └── punkt │ ├── .DS_Store │ ├── PY3 │ ├── README │ ├── czech.pickle │ ├── danish.pickle │ ├── dutch.pickle │ ├── english.pickle │ ├── estonian.pickle │ ├── finnish.pickle │ ├── french.pickle │ ├── german.pickle │ ├── greek.pickle │ ├── italian.pickle │ ├── malayalam.pickle │ ├── norwegian.pickle │ ├── polish.pickle │ ├── portuguese.pickle │ ├── russian.pickle │ ├── slovene.pickle │ ├── spanish.pickle │ ├── swedish.pickle │ └── turkish.pickle │ ├── README │ ├── czech.pickle │ ├── danish.pickle │ ├── dutch.pickle │ ├── english.pickle │ ├── estonian.pickle │ ├── finnish.pickle │ ├── french.pickle │ ├── german.pickle │ ├── greek.pickle │ ├── italian.pickle │ ├── malayalam.pickle │ ├── norwegian.pickle │ ├── polish.pickle │ ├── portuguese.pickle │ ├── russian.pickle │ ├── slovene.pickle │ ├── spanish.pickle │ ├── swedish.pickle │ └── turkish.pickle ├── paddlepaddle ├── README.md ├── app.py ├── chatllm.py ├── cli.py ├── paddle_embedding.py └── requirements.txt ├── poetry.lock ├── poetry.toml ├── pyproject.toml └── requirements.txt /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM registry.cn-beijing.aliyuncs.com/public-development-resources/langchain-chatglm-webui:Base 2 | RUN mkdir -p /pretrainmodel/belle /pretrainmodel/vicuna /pretrainmodel/chatglm 3 | RUN git clone https://github.com/thomas-yanxin/LangChain-ChatGLM-Webui.git /code 4 | WORKDIR /code 5 | RUN pip install -r requirements.txt 6 | CMD ["python3", "app.py"] -------------------------------------------------------------------------------- /Dockerfile.Base: -------------------------------------------------------------------------------- 1 | FROM nvidia/cuda:11.7.1-devel-ubuntu22.04 2 | RUN apt-get update && \ 3 | apt-get install --no-install-recommends -y git python3 python3-dev python3-pip build-essential libmagic-dev poppler-utils tesseract-ocr libreoffice vim libgl1-mesa-glx aria2 unzip && \ 4 | rm -rf /var/lib/apt/lists/* 5 | WORKDIR /build 6 | RUN pip install --upgrade pip 7 | RUN pip install --user torch torchvision tensorboard cython PyPDF2 pdfrw -i https://pypi.tuna.tsinghua.edu.cn/simple 8 | COPY requirements.txt requirements.txt 9 | RUN pip install -r requirements.txt && rm -f requirements.txt -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 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. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |

3 | github 4 | HuggingFace 5 | modelscope 6 | openxlab 7 | OpenI 8 | AIStudio 9 | bilibili 10 | 11 |

12 |
13 | 14 | ![stars](https://img.shields.io/github/stars/thomas-yanxin/LangChain-ChatGLM-Webui) [![contributors](https://img.shields.io/github/contributors/thomas-yanxin/LangChain-ChatGLM-Webui)](https://github.com/thomas-yanxin/LangChain-ChatGLM-Webui/graphs/contributors) [![issues](http://isitmaintained.com/badge/open/thomas-yanxin/LangChain-ChatGLM-Webui.svg)](https://github.com/thomas-yanxin/LangChain-ChatGLM-Webui/issues) [![pull requests](https://img.shields.io/github/issues-pr/thomas-yanxin/LangChain-ChatGLM-Webui?color=orange)](https://github.com/thomas-yanxin/LangChain-ChatGLM-Webui/pulls) 15 | 16 |

17 |
18 | 19 |

20 | 视频链接 | 在线体验 | 部署文档| 更新日志 | 常见问题 21 | 22 |

23 | 24 | ## 🔥 项目体验 25 | 26 | 本项目提供基于[HuggingFace社区](https://huggingface.co/spaces/thomas-yanxin/LangChain-ChatLLM)、[OpenXLab](https://openxlab.org.cn/apps/detail/thomas-yanxin/LangChain-ChatLLM)、[ModelScope魔搭社区](https://modelscope.cn/studios/AI-ModelScope/LangChain-ChatLLM/summary)、[飞桨AIStudio社区](https://aistudio.baidu.com/aistudio/projectdetail/6195067)的在线体验, 欢迎尝试和反馈! 27 | 28 | ## 👏 项目介绍 29 | 30 | 受[langchain-ChatGLM](https://github.com/imClumsyPanda/langchain-ChatGLM)启发, 利用LangChain和ChatGLM-6B系列模型制作的Webui, 提供基于本地知识的大模型应用. 31 | 32 | 目前支持上传 txt、docx、md、pdf等文本格式文件, 提供包括ChatGLM-6B系列、Belle系列等模型文件以及[GanymedeNil/text2vec-large-chinese](https://huggingface.co/GanymedeNil/text2vec-large-chinese)、[nghuyong/ernie-3.0-base-zh](https://huggingface.co/nghuyong/ernie-3.0-base-zh)、[nghuyong/ernie-3.0-nano-zh](https://huggingface.co/nghuyong/ernie-3.0-nano-zh)等Embedding模型. 33 | 34 |
HuggingFace效果 35 | 36 | ![](./img/demo_hf.jpg) 37 | 38 |
39 |
ModelScope效果 40 | 41 | ![](./img/demo_ms.jpg) 42 | 43 |
44 | 45 | ## 🚀 使用方式 46 | 47 | 提供ModelScope版本和HuggingFace版本. 48 | **需要Python>=3.8.1** 49 | 50 | 详细部署教程可参考: [部署文档](./docs/deploy.md) | [视频教程](https://www.bilibili.com/video/BV1No4y1b7eu/) 51 | 52 | ### 支持模型 53 | 54 | 若存在网络问题可在[此找到本项目涉及的所有模型](https://openi.pcl.ac.cn/Learning-Develop-Union/LangChain-ChatGLM-Webui/datasets): 55 | | large language model | Embedding model | 56 | | :----: | :----: | 57 | | ChatGLM-6B | text2vec-large-chinese | 58 | | ChatGLM-6B-int8 | ernie-3.0-base-zh | 59 | | ChatGLM-6B-int4 | ernie-3.0-nano-zh | 60 | | ChatGLM-6B-int4-qe | ernie-3.0-xbase-zh | 61 | | Vicuna-7b-1.1 | simbert-base-chinese | 62 | | Vicuna-13b-1.1 | paraphrase-multilingual-MiniLM-L12-v2 | 63 | | BELLE-LLaMA-7B-2M | | 64 | | BELLE-LLaMA-13B-2M | | 65 | | internlm-chat-7b-8k | | 66 | | internlm-chat-7b-v1_1 | | 67 | | internlm-chat-7b | | 68 | 69 | ## 💪 更新日志 70 | 71 | 详情请见: [更新日志](./docs/update_history.md) 72 | 73 | 项目处于初期阶段, 有很多可以做的地方和优化的空间, 欢迎感兴趣的社区大佬们一起加入! 74 | 75 | ## ❤️ 引用 76 | 77 | 1. [ChatGLM-6B](https://github.com/THUDM/ChatGLM-6B): ChatGLM-6B: 开源双语对话语言模型 78 | 2. [LangChain](https://github.com/hwchase17/langchain): Building applications with LLMs through composability 79 | 3. [langchain-ChatGLM](https://github.com/imClumsyPanda/langchain-ChatGLM): 基于本地知识的 ChatGLM 应用实现 80 |
ChatGLM论文引用 81 | 82 | ``` 83 | @inproceedings{ 84 | zeng2023glm-130b, 85 | title={{GLM}-130B: An Open Bilingual Pre-trained Model}, 86 | author={Aohan Zeng and Xiao Liu and Zhengxiao Du and Zihan Wang and Hanyu Lai and Ming Ding and Zhuoyi Yang and Yifan Xu and Wendi Zheng and Xiao Xia and Weng Lam Tam and Zixuan Ma and Yufei Xue and Jidong Zhai and Wenguang Chen and Zhiyuan Liu and Peng Zhang and Yuxiao Dong and Jie Tang}, 87 | booktitle={The Eleventh International Conference on Learning Representations (ICLR)}, 88 | year={2023}, 89 | url={https://openreview.net/forum?id=-Aw0rrrPUF} 90 | } 91 | ``` 92 | 93 | ``` 94 | @inproceedings{du2022glm, 95 | title={GLM: General Language Model Pretraining with Autoregressive Blank Infilling}, 96 | author={Du, Zhengxiao and Qian, Yujie and Liu, Xiao and Ding, Ming and Qiu, Jiezhong and Yang, Zhilin and Tang, Jie}, 97 | booktitle={Proceedings of the 60th Annual Meeting of the Association for Computational Linguistics (Volume 1: Long Papers)}, 98 | pages={320--335}, 99 | year={2022} 100 | } 101 | ``` 102 | 103 |
104 |
BELLE论文引用 105 | 106 | ``` 107 | @misc{BELLE, 108 | author = {Yunjie Ji, Yong Deng, Yan Gong, Yiping Peng, Qiang Niu, Baochang Ma and Xiangang Li}, 109 | title = {BELLE: Be Everyone's Large Language model Engine }, 110 | year = {2023}, 111 | publisher = {GitHub}, 112 | journal = {GitHub repository}, 113 | howpublished = {\url{https://github.com/LianjiaTech/BELLE}}, 114 | } 115 | @article{belle2023exploring, 116 | title={Exploring the Impact of Instruction Data Scaling on Large Language Models: An Empirical Study on Real-World Use Cases}, 117 | author={Yunjie Ji, Yong Deng, Yan Gong, Yiping Peng, Qiang Niu, Lei Zhang, Baochang Ma, Xiangang Li}, 118 | journal={arXiv preprint arXiv:2303.14742}, 119 | year={2023} 120 | } 121 | ``` 122 | 123 |
124 | 125 | ## 🙇‍ ‍感谢 126 | 127 | 1. [langchain-ChatGLM](https://github.com/imClumsyPanda/langchain-ChatGLM)提供的基础框架 128 | 2. [魔搭ModelScope](https://modelscope.cn/home)提供展示空间 129 | 3. [OpenI启智社区](https://openi.pcl.ac.cn/)提供调试算力 130 | 4. [langchain-serve](https://github.com/jina-ai/langchain-serve)提供十分简易的Serving方式 131 | 5. 除此以外, 感谢来自社区的同学们对本项目的关注和支持! 132 | 133 | 134 | 135 | 136 | ## 🌟 Star History 137 | 138 | [![Star History Chart](https://api.star-history.com/svg?repos=thomas-yanxin/LangChain-ChatGLM-Webui&type=Date)](https://star-history.com/#thomas-yanxin/LangChain-ChatGLM-Webui&Date) 139 | 140 | ## 😊 加群沟通 141 | 142 |
143 | -------------------------------------------------------------------------------- /__pycache__/config.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/__pycache__/config.cpython-39.pyc -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | import os 2 | from typing import List 3 | 4 | import gradio as gr 5 | import nltk 6 | import sentence_transformers 7 | from duckduckgo_search import ddg 8 | from duckduckgo_search.utils import SESSION 9 | from langchain.chains import RetrievalQA 10 | from langchain_community.document_loaders import UnstructuredFileLoader 11 | from langchain.embeddings.huggingface import HuggingFaceEmbeddings 12 | from langchain.prompts import PromptTemplate 13 | from langchain.prompts.prompt import PromptTemplate 14 | from langchain_community.vectorstores import FAISS 15 | 16 | from chatllm import ChatLLM 17 | from chinese_text_splitter import ChineseTextSplitter 18 | from config import * 19 | import torch 20 | 21 | nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data") 22 | ] + nltk.data.path 23 | 24 | embedding_model_dict = embedding_model_dict 25 | llm_model_dict = llm_model_dict 26 | EMBEDDING_DEVICE = EMBEDDING_DEVICE 27 | LLM_DEVICE = LLM_DEVICE 28 | num_gpus = num_gpus 29 | init_llm = init_llm 30 | init_embedding_model = init_embedding_model 31 | 32 | llm_model_list = [] 33 | llm_model_dict = llm_model_dict 34 | 35 | for i in llm_model_dict: 36 | for j in llm_model_dict[i]: 37 | llm_model_list.append(j) 38 | 39 | 40 | def search_web(query): 41 | 42 | SESSION.proxies = { 43 | "http": f"socks5h://localhost:7890", 44 | "https": f"socks5h://localhost:7890" 45 | } 46 | results = ddg(query) 47 | web_content = '' 48 | if results: 49 | for result in results: 50 | web_content += result['body'] 51 | return web_content 52 | 53 | 54 | class KnowledgeBasedChatLLM: 55 | 56 | llm: object = None 57 | embeddings: object = None 58 | 59 | def init_model_config( 60 | self, 61 | large_language_model: str = init_llm, 62 | embedding_model: str = init_embedding_model, 63 | ): 64 | 65 | self.embeddings = HuggingFaceEmbeddings( 66 | model_name=embedding_model_dict[embedding_model], ) 67 | self.embeddings.client = sentence_transformers.SentenceTransformer( 68 | self.embeddings.model_name, 69 | device=EMBEDDING_DEVICE, 70 | cache_folder=os.path.join(MODEL_CACHE_PATH, self.embeddings.model_name), 71 | trust_remote_code=True 72 | ) 73 | self.llm = None 74 | torch.cuda.empty_cache() 75 | self.llm = ChatLLM() 76 | if 'chatglm2' in large_language_model.lower(): 77 | self.llm.model_type = 'chatglm2' 78 | self.llm.model_name_or_path = llm_model_dict['chatglm2'][ 79 | large_language_model] 80 | elif 'chatglm' in large_language_model.lower(): 81 | self.llm.model_type = 'chatglm' 82 | self.llm.model_name_or_path = llm_model_dict['chatglm'][ 83 | large_language_model] 84 | elif 'belle' in large_language_model.lower(): 85 | self.llm.model_type = 'belle' 86 | self.llm.model_name_or_path = llm_model_dict['belle'][ 87 | large_language_model] 88 | elif 'vicuna' in large_language_model.lower(): 89 | self.llm.model_type = 'vicuna' 90 | self.llm.model_name_or_path = llm_model_dict['vicuna'][ 91 | large_language_model] 92 | elif 'internlm' in large_language_model.lower(): 93 | self.llm.model_type = 'internlm' 94 | self.llm.model_name_or_path = llm_model_dict['internlm'][ 95 | large_language_model] 96 | elif 'yuan2' in large_language_model.lower(): 97 | self.llm.model_type = 'yuan2' 98 | self.llm.model_name_or_path = llm_model_dict['yuan2'][large_language_model] 99 | 100 | self.llm.load_llm(llm_device=LLM_DEVICE, num_gpus=num_gpus) 101 | 102 | def init_knowledge_vector_store(self, filepath): 103 | 104 | docs = self.load_file(filepath) 105 | 106 | vector_store = FAISS.from_documents(docs, self.embeddings) 107 | vector_store.save_local('faiss_index') 108 | return vector_store 109 | 110 | def get_knowledge_based_answer(self, 111 | query, 112 | web_content, 113 | top_k: int = 6, 114 | history_len: int = 3, 115 | temperature: float = 0.01, 116 | top_p: float = 0.1, 117 | history=[]): 118 | self.llm.temperature = temperature 119 | self.llm.top_p = top_p 120 | self.history_len = history_len 121 | self.top_k = top_k 122 | if web_content: 123 | prompt_template = f"""基于以下已知信息,简洁和专业的来回答用户的问题。 124 | 如果无法从中得到答案,请说 "根据已知信息无法回答该问题" 或 "没有提供足够的相关信息",不允许在答案中添加编造成分,答案请使用中文。 125 | 已知网络检索内容:{web_content}""" + """ 126 | 已知内容: 127 | {context} 128 | 问题: 129 | {question}""" 130 | else: 131 | prompt_template = """基于以下已知信息,请简洁并专业地回答用户的问题。 132 | 如果无法从中得到答案,请说 "根据已知信息无法回答该问题" 或 "没有提供足够的相关信息"。不允许在答案中添加编造成分。另外,答案请使用中文。 133 | 134 | 已知内容: 135 | {context} 136 | 137 | 问题: 138 | {question}""" 139 | prompt = PromptTemplate(template=prompt_template, 140 | input_variables=["context", "question"]) 141 | self.llm.history = history[ 142 | -self.history_len:] if self.history_len > 0 else [] 143 | vector_store = FAISS.load_local('faiss_index', self.embeddings) 144 | 145 | knowledge_chain = RetrievalQA.from_llm( 146 | llm=self.llm, 147 | retriever=vector_store.as_retriever( 148 | search_kwargs={"k": self.top_k}), 149 | prompt=prompt) 150 | knowledge_chain.combine_documents_chain.document_prompt = PromptTemplate( 151 | input_variables=["page_content"], template="{page_content}") 152 | 153 | knowledge_chain.return_source_documents = True 154 | 155 | result = knowledge_chain({"query": query}) 156 | return result 157 | 158 | def load_file(self, filepath): 159 | if filepath.lower().endswith(".md"): 160 | loader = UnstructuredFileLoader(filepath, mode="elements") 161 | docs = loader.load() 162 | elif filepath.lower().endswith(".pdf"): 163 | loader = UnstructuredFileLoader(filepath) 164 | textsplitter = ChineseTextSplitter(pdf=True) 165 | docs = loader.load_and_split(textsplitter) 166 | elif filepath.lower().endswith(".txt"): 167 | loader = UnstructuredFileLoader(filepath,encoding='utf8') 168 | textsplitter = ChineseTextSplitter(pdf=False) 169 | docs = loader.load_and_split(textsplitter) 170 | else: 171 | loader = UnstructuredFileLoader(filepath, mode="elements") 172 | textsplitter = ChineseTextSplitter(pdf=False) 173 | docs = loader.load_and_split(text_splitter=textsplitter) 174 | return docs 175 | 176 | 177 | def update_status(history, status): 178 | history = history + [[None, status]] 179 | print(status) 180 | return history 181 | 182 | 183 | knowladge_based_chat_llm = KnowledgeBasedChatLLM() 184 | 185 | 186 | def init_model(): 187 | try: 188 | print("开始加载模型配置") 189 | knowladge_based_chat_llm.init_model_config() 190 | print("模型配置加载成功") 191 | knowladge_based_chat_llm.llm._call("你好") 192 | return """初始模型已成功加载,可以开始对话""" 193 | except Exception as e: 194 | print(f"加载模型出错: {e}") # 打印详细的异常信息 195 | return """模型未成功加载,请重新选择模型后点击"重新加载模型"按钮""" 196 | 197 | 198 | def clear_session(): 199 | return '', None 200 | 201 | 202 | def reinit_model(large_language_model, embedding_model, history): 203 | try: 204 | knowladge_based_chat_llm.init_model_config( 205 | large_language_model=large_language_model, 206 | embedding_model=embedding_model) 207 | model_status = """模型已成功重新加载,可以开始对话""" 208 | except Exception as e: 209 | 210 | model_status = """模型未成功重新加载,请点击重新加载模型""" 211 | return history + [[None, model_status]] 212 | 213 | 214 | def init_vector_store(file_obj): 215 | 216 | vector_store = knowladge_based_chat_llm.init_knowledge_vector_store( 217 | file_obj.name) 218 | 219 | return vector_store 220 | 221 | 222 | def predict(input, 223 | use_web, 224 | top_k, 225 | history_len, 226 | temperature, 227 | top_p, 228 | history=None): 229 | if history == None: 230 | history = [] 231 | 232 | if use_web == 'True': 233 | web_content = search_web(query=input) 234 | else: 235 | web_content = '' 236 | 237 | resp = knowladge_based_chat_llm.get_knowledge_based_answer( 238 | query=input, 239 | web_content=web_content, 240 | top_k=top_k, 241 | history_len=history_len, 242 | temperature=temperature, 243 | top_p=top_p, 244 | history=history) 245 | history.append((input, resp['result'])) 246 | return '', history, history 247 | 248 | 249 | model_status = init_model() 250 | 251 | if __name__ == "__main__": 252 | block = gr.Blocks() 253 | with block as demo: 254 | 255 | gr.Markdown("""

LangChain-ChatLLM-Webui

256 |
257 | 本项目基于LangChain和大型语言模型系列模型, 提供基于本地知识的自动问答应用.
258 | 目前项目提供基于ChatGLM-6B 的LLM和包括GanymedeNil/text2vec-large-chinese、nghuyong/ernie-3.0-base-zh、nghuyong/ernie-3.0-nano-zh在内的多个Embedding模型, 支持上传 txt、docx、md、pdf等文本格式文件.
259 | 后续将提供更加多样化的LLM、Embedding和参数选项供用户尝试, 欢迎关注Github地址. 260 |
261 | """) 262 | model_status = gr.State(model_status) 263 | with gr.Row(): 264 | with gr.Column(scale=1): 265 | model_choose = gr.Accordion("模型选择") 266 | with model_choose: 267 | large_language_model = gr.Dropdown( 268 | llm_model_list, 269 | label="large language model", 270 | value=init_llm) 271 | 272 | embedding_model = gr.Dropdown(list( 273 | embedding_model_dict.keys()), 274 | label="Embedding model", 275 | value=init_embedding_model) 276 | load_model_button = gr.Button("重新加载模型") 277 | model_argument = gr.Accordion("模型参数配置") 278 | with model_argument: 279 | 280 | top_k = gr.Slider(1, 281 | 10, 282 | value=6, 283 | step=1, 284 | label="vector search top k", 285 | interactive=True) 286 | 287 | history_len = gr.Slider(0, 288 | 5, 289 | value=3, 290 | step=1, 291 | label="history len", 292 | interactive=True) 293 | 294 | temperature = gr.Slider(0, 295 | 1, 296 | value=0.01, 297 | step=0.01, 298 | label="temperature", 299 | interactive=True) 300 | top_p = gr.Slider(0, 301 | 1, 302 | value=0.9, 303 | step=0.1, 304 | label="top_p", 305 | interactive=True) 306 | 307 | file = gr.File(label='请上传知识库文件', 308 | file_types=['.txt', '.md', '.docx', '.pdf']) 309 | 310 | init_vs = gr.Button("知识库文件向量化") 311 | 312 | use_web = gr.Radio(["True", "False"], 313 | label="Web Search", 314 | value="False") 315 | 316 | with gr.Column(scale=4): 317 | chatbot = gr.Chatbot([[None, model_status.value]], 318 | label='ChatLLM').style(height=750) 319 | message = gr.Textbox(label='请输入问题') 320 | state = gr.State() 321 | 322 | with gr.Row(): 323 | clear_history = gr.Button("🧹 清除历史对话") 324 | send = gr.Button("🚀 发送") 325 | 326 | load_model_button.click( 327 | reinit_model, 328 | show_progress=True, 329 | inputs=[large_language_model, embedding_model, chatbot], 330 | outputs=chatbot, 331 | ) 332 | init_vs.click( 333 | init_vector_store, 334 | show_progress=True, 335 | inputs=[file], 336 | outputs=[], 337 | ) 338 | 339 | send.click(predict, 340 | inputs=[ 341 | message, use_web, top_k, history_len, temperature, 342 | top_p, state 343 | ], 344 | outputs=[message, chatbot, state]) 345 | clear_history.click(fn=clear_session, 346 | inputs=[], 347 | outputs=[chatbot, state], 348 | queue=False) 349 | 350 | message.submit(predict, 351 | inputs=[ 352 | message, use_web, top_k, history_len, 353 | temperature, top_p, state 354 | ], 355 | outputs=[message, chatbot, state]) 356 | gr.Markdown("""提醒:
357 | 1. 使用时请先上传自己的知识文件,并且文件中不含某些特殊字符,否则将返回error.
358 | 2. 有任何使用问题,请通过[Github Issue区](https://github.com/thomas-yanxin/LangChain-ChatGLM-Webui/issues)进行反馈.
359 | """) 360 | # threads to consume the request 361 | demo.queue(concurrency_count=3) \ 362 | .launch(server_name='0.0.0.0', # ip for listening, 0.0.0.0 for every inbound traffic, 127.0.0.1 for local inbound 363 | server_port=7860, # the port for listening 364 | show_api=False, # if display the api document 365 | share=False, # if register a public url 366 | inbrowser=False) # if browser would be open automatically 367 | -------------------------------------------------------------------------------- /chatllm.py: -------------------------------------------------------------------------------- 1 | import os 2 | from typing import Dict, List, Optional, Tuple, Union 3 | 4 | import torch 5 | from fastchat.conversation import (compute_skip_echo_len, 6 | get_default_conv_template) 7 | from fastchat.serve.inference import load_model as load_fastchat_model 8 | from langchain.llms.base import LLM 9 | from langchain.llms.utils import enforce_stop_tokens 10 | from transformers import AutoModel, AutoModelForCausalLM, AutoTokenizer 11 | 12 | from config import * 13 | 14 | os.environ["TOKENIZERS_PARALLELISM"] = "false" 15 | 16 | DEVICE = LLM_DEVICE 17 | DEVICE_ID = "0" 18 | CUDA_DEVICE = f"{DEVICE}:{DEVICE_ID}" if DEVICE_ID else DEVICE 19 | 20 | init_llm = init_llm 21 | init_embedding_model = init_embedding_model 22 | 23 | def torch_gc(): 24 | if torch.cuda.is_available(): 25 | with torch.cuda.device(CUDA_DEVICE): 26 | torch.cuda.empty_cache() 27 | torch.cuda.ipc_collect() 28 | 29 | 30 | def auto_configure_device_map(num_gpus: int) -> Dict[str, int]: 31 | num_trans_layers = 28 32 | per_gpu_layers = 30 / num_gpus 33 | 34 | device_map = { 35 | 'transformer.word_embeddings': 0, 36 | 'transformer.final_layernorm': 0, 37 | 'lm_head': 0 38 | } 39 | 40 | used = 2 41 | gpu_target = 0 42 | for i in range(num_trans_layers): 43 | if used >= per_gpu_layers: 44 | gpu_target += 1 45 | used = 0 46 | assert gpu_target < num_gpus 47 | device_map[f'transformer.layers.{i}'] = gpu_target 48 | used += 1 49 | 50 | return device_map 51 | 52 | 53 | class ChatLLM(LLM): 54 | max_token: int = 10000 55 | temperature: float = 0.1 56 | top_p = 0.9 57 | history = [] 58 | model_type: str = "chatglm" 59 | model_name_or_path: str = init_llm, 60 | tokenizer: object = None 61 | model: object = None 62 | 63 | def __init__(self): 64 | super().__init__() 65 | 66 | @property 67 | def _llm_type(self) -> str: 68 | return "ChatLLM" 69 | 70 | def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str: 71 | 72 | if self.model_type == 'vicuna': 73 | conv = get_default_conv_template(self.model_name_or_path).copy() 74 | conv.append_message(conv.roles[0], prompt) 75 | conv.append_message(conv.roles[1], None) 76 | prompt = conv.get_prompt() 77 | inputs = self.tokenizer([prompt]) 78 | output_ids = self.model.generate( 79 | torch.as_tensor(inputs.input_ids).cuda(), 80 | do_sample=True, 81 | temperature=self.temperature, 82 | max_new_tokens=self.max_token, 83 | ) 84 | outputs = self.tokenizer.batch_decode(output_ids, skip_special_tokens=True)[0] 85 | skip_echo_len = compute_skip_echo_len(self.model_name_or_path, conv, prompt) 86 | response = outputs[skip_echo_len:] 87 | torch_gc() 88 | if stop is not None: 89 | response = enforce_stop_tokens(response, stop) 90 | self.history = [[None, response]] 91 | 92 | elif self.model_type == 'belle': 93 | prompt = "Human: "+ prompt +" \n\nAssistant: " 94 | input_ids = self.tokenizer(prompt, return_tensors="pt").input_ids.to(DEVICE) 95 | generate_ids = self.model.generate(input_ids, max_new_tokens=self.max_token, do_sample = True, top_k = 30, top_p = self.top_p, temperature = self.temperature, repetition_penalty=1., eos_token_id=2, bos_token_id=1, pad_token_id=0) 96 | output = self.tokenizer.batch_decode(generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0] 97 | response = output[len(prompt)+1:] 98 | torch_gc() 99 | if stop is not None: 100 | response = enforce_stop_tokens(response, stop) 101 | self.history = [[None, response]] 102 | 103 | elif self.model_type == 'chatglm2': 104 | response, _ = self.model.chat( 105 | self.tokenizer, 106 | prompt, 107 | history=self.history, 108 | max_length=self.max_token, 109 | temperature=self.temperature, 110 | top_p = self.top_p, 111 | ) 112 | torch_gc() 113 | if stop is not None: 114 | response = enforce_stop_tokens(response, stop) 115 | self.history = self.history + [[None, response]] 116 | 117 | elif self.model_type == 'chatglm': 118 | response, _ = self.model.chat( 119 | self.tokenizer, 120 | prompt, 121 | history=self.history, 122 | max_length=self.max_token, 123 | temperature=self.temperature, 124 | ) 125 | torch_gc() 126 | if stop is not None: 127 | response = enforce_stop_tokens(response, stop) 128 | self.history = self.history + [[None, response]] 129 | elif self.model_type == 'internlm': 130 | response, _ = self.model.chat(self.tokenizer, prompt, history=self.history, max_length=self.max_token, temperature=self.temperature) 131 | 132 | elif self.model_type == 'yuan2': 133 | inputs = self.tokenizer(prompt, return_tensors="pt").to(DEVICE) 134 | outputs = self.model.generate(inputs.input_ids, max_length=self.max_token, do_sample=True, 135 | temperature=self.temperature) 136 | output = self.tokenizer.decode(outputs[0], skip_special_tokens=True) 137 | response = output[len(prompt)+1:] 138 | torch_gc() 139 | if stop is not None: 140 | response = enforce_stop_tokens(response, stop) 141 | self.history = self.history + [[None, response]] 142 | 143 | return response 144 | 145 | 146 | def load_llm(self, 147 | llm_device=DEVICE, 148 | num_gpus='auto', 149 | device_map: Optional[Dict[str, int]] = None, 150 | **kwargs): 151 | if 'chatglm2' in self.model_name_or_path.lower(): 152 | self.tokenizer = AutoTokenizer.from_pretrained(self.model_name_or_path, 153 | trust_remote_code=True, cache_dir=os.path.join(MODEL_CACHE_PATH, self.model_name_or_path)) 154 | if torch.cuda.is_available() and llm_device.lower().startswith("cuda"): 155 | 156 | num_gpus = torch.cuda.device_count() 157 | if num_gpus < 2 and device_map is None: 158 | self.model = (AutoModel.from_pretrained( 159 | self.model_name_or_path, trust_remote_code=True, cache_dir=os.path.join(MODEL_CACHE_PATH, self.model_name_or_path), 160 | **kwargs).half().cuda()) 161 | else: 162 | from accelerate import dispatch_model 163 | 164 | model = AutoModel.from_pretrained(self.model_name_or_path, 165 | trust_remote_code=True, cache_dir=os.path.join(MODEL_CACHE_PATH, self.model_name_or_path), 166 | **kwargs).half() 167 | 168 | if device_map is None: 169 | device_map = auto_configure_device_map(num_gpus) 170 | 171 | self.model = dispatch_model(model, device_map=device_map) 172 | else: 173 | self.model = (AutoModel.from_pretrained( 174 | self.model_name_or_path, 175 | trust_remote_code=True, cache_dir=os.path.join(MODEL_CACHE_PATH, self.model_name_or_path)).float().to(llm_device)) 176 | self.model = self.model.eval() 177 | 178 | elif 'chatglm' in self.model_name_or_path.lower(): 179 | self.tokenizer = AutoTokenizer.from_pretrained(self.model_name_or_path, 180 | trust_remote_code=True, cache_dir=os.path.join(MODEL_CACHE_PATH, self.model_name_or_path)) 181 | if torch.cuda.is_available() and llm_device.lower().startswith("cuda"): 182 | 183 | num_gpus = torch.cuda.device_count() 184 | if num_gpus < 2 and device_map is None: 185 | self.model = (AutoModel.from_pretrained( 186 | self.model_name_or_path, trust_remote_code=True, cache_dir=os.path.join(MODEL_CACHE_PATH, self.model_name_or_path), 187 | **kwargs).half().cuda()) 188 | else: 189 | from accelerate import dispatch_model 190 | 191 | model = AutoModel.from_pretrained(self.model_name_or_path, 192 | trust_remote_code=True, cache_dir=os.path.join(MODEL_CACHE_PATH, self.model_name_or_path), 193 | **kwargs).half() 194 | 195 | if device_map is None: 196 | device_map = auto_configure_device_map(num_gpus) 197 | 198 | self.model = dispatch_model(model, device_map=device_map) 199 | else: 200 | self.model = (AutoModel.from_pretrained( 201 | self.model_name_or_path, 202 | trust_remote_code=True, cache_dir=os.path.join(MODEL_CACHE_PATH, self.model_name_or_path)).float().to(llm_device)) 203 | self.model = self.model.eval() 204 | 205 | elif 'internlm' in self.model_name_or_path.lower(): 206 | 207 | self.tokenizer = AutoTokenizer.from_pretrained(self.model_name_or_path, trust_remote_code=True) 208 | self.model = AutoModelForCausalLM.from_pretrained(self.model_name_or_path, trust_remote_code=True).cuda() 209 | self.model = self.model.eval() 210 | 211 | elif 'yuan2' in self.model_name_or_path.lower(): 212 | self.tokenizer = AutoTokenizer.from_pretrained(self.model_name_or_path, trust_remote_code=True) 213 | self.model = AutoModelForCausalLM.from_pretrained(self.model_name_or_path, device_map='auto', 214 | torch_dtype=torch.bfloat16, trust_remote_code=True) 215 | self.model = self.model.eval() 216 | 217 | else: 218 | self.model, self.tokenizer = load_fastchat_model( 219 | model_path = self.model_name_or_path, 220 | device = llm_device, 221 | num_gpus = num_gpus 222 | ) 223 | 224 | -------------------------------------------------------------------------------- /chinese_text_splitter.py: -------------------------------------------------------------------------------- 1 | import re 2 | from typing import List 3 | 4 | from langchain.text_splitter import CharacterTextSplitter 5 | 6 | 7 | class ChineseTextSplitter(CharacterTextSplitter): 8 | def __init__(self, pdf: bool = False, **kwargs): 9 | super().__init__(**kwargs) 10 | self.pdf = pdf 11 | 12 | def split_text(self, text: str) -> List[str]: 13 | if self.pdf: 14 | text = re.sub(r"\n{3,}", "\n", text) 15 | text = re.sub('\s', ' ', text) 16 | text = text.replace("\n\n", "") 17 | sent_sep_pattern = re.compile( 18 | '([﹒﹔﹖﹗.。!?]["’”」』]{0,2}|(?=["‘“「『]{1,2}|$))') 19 | sent_list = [] 20 | for ele in sent_sep_pattern.split(text): 21 | if sent_sep_pattern.match(ele) and sent_list: 22 | sent_list[-1] += ele 23 | elif ele: 24 | sent_list.append(ele) 25 | return sent_list 26 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import torch 4 | 5 | # device config 6 | EMBEDDING_DEVICE = "cuda" if torch.cuda.is_available( 7 | ) else "mps" if torch.backends.mps.is_available() else "cpu" 8 | LLM_DEVICE = "cuda" if torch.cuda.is_available( 9 | ) else "mps" if torch.backends.mps.is_available() else "cpu" 10 | num_gpus = torch.cuda.device_count() 11 | 12 | # model cache config 13 | MODEL_CACHE_PATH = os.path.join(os.path.dirname(__file__), 'model_cache') 14 | 15 | 16 | # vector storage config 17 | VECTOR_STORE_PATH='./vector_store' 18 | COLLECTION_NAME='my_collection' 19 | 20 | 21 | # init model config 22 | init_llm = "ChatGLM2-6B" 23 | init_embedding_model = "text2vec-base" 24 | 25 | # model config 26 | embedding_model_dict = { 27 | "ernie-tiny": "nghuyong/ernie-3.0-nano-zh", 28 | "ernie-base": "nghuyong/ernie-3.0-base-zh", 29 | "ernie-medium": "nghuyong/ernie-3.0-medium-zh", 30 | "ernie-xbase": "nghuyong/ernie-3.0-xbase-zh", 31 | "text2vec-base": "GanymedeNil/text2vec-base-chinese", 32 | 'simbert-base-chinese': 'WangZeJun/simbert-base-chinese', 33 | 'paraphrase-multilingual-MiniLM-L12-v2': "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2", 34 | "jina-embeddings-v2-base-zh": "jinaai/jina-embeddings-v2-base-zh", 35 | "bge-m3":"BAAI/bge-m3 " 36 | } 37 | 38 | 39 | llm_model_dict = { 40 | "chatglm2": { 41 | "ChatGLM2-6B": "THUDM/chatglm2-6b", 42 | "ChatGLM2-6B-int4": "THUDM/chatglm2-6b-int4", 43 | }, 44 | "chatglm": { 45 | "ChatGLM-6B": "THUDM/chatglm-6b", 46 | "ChatGLM-6B-int4": "THUDM/chatglm-6b-int4", 47 | "ChatGLM-6B-int8": "THUDM/chatglm-6b-int8", 48 | "ChatGLM-6b-int4-qe": "THUDM/chatglm-6b-int4-qe" 49 | }, 50 | "belle": { 51 | "BELLE-LLaMA-Local": "/pretrainmodel/belle", 52 | }, 53 | "vicuna": { 54 | "Vicuna-Local": "/pretrainmodel/vicuna", 55 | }, 56 | "internlm": { 57 | "internlm-chat-7b-8k": "internlm/internlm-chat-7b-8k", 58 | "internlm-chat-7b": "internlm/internlm-chat-7b", 59 | "internlm-chat-7b-v1_1": "internlm/internlm-chat-7b-v1_1", 60 | } 61 | "yuan2":{ 62 | "Yuan2-2B-hf":"IEITYuan/Yuan2-2B-hf" 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /docs/deploy.md: -------------------------------------------------------------------------------- 1 | # 部署文档 2 | 3 | ## 直接安装 4 | 5 | ### 环境准备 6 | 7 | **项目需要Python>=3.8.1, 默认已安装torch** 8 | 9 | 1. git clone本项目, 您可以在自己的terminal中执行: `git clone https://github.com/thomas-yanxin/LangChain-ChatGLM-Webui.git`. 若国内用户访问Github存在网络问题, 也可以执行: `https://openi.pcl.ac.cn/Learning-Develop-Union/LangChain-ChatGLM-Webui.git` 10 | 2. 进入本项目目录:`cd LangChain-ChatGLM-Webui` 11 | 3. 安装依赖包:`pip install -r requirements.txt`, 国内用户可设置清华源加速下载. 12 | 13 | 另: 若您想要安装测试ModelScope版本, 需要额外安装ModelScope包: `pip install modelscope==1.4.3 -f https://modelscope.oss-cn-beijing.aliyuncs.com/releases/repo.html ` 14 | 15 | [OpenI启智社区](https://openi.pcl.ac.cn/Learning-Develop-Union/LangChain-ChatGLM-Webui)部署推荐的Docker镜像: `dockerhub.pcl.ac.cn:5000/user-images/openi:LangChain-ChatLLM-2.0` 16 | 17 | ### 启动程序 18 | 19 | * Huggingface版本 20 | 21 | 在terminal中执行命令: `python3 app.py` 22 | 23 | * ModelScope版本 24 | 25 | 1. 进入modelscope文件目录:`cd modelscope` 26 | 2. 执行命令:`python3 app.py` 27 | 28 | ## Docker 基础环境运行 29 | 30 | 1. 运行镜像:`docker run -it --rm --runtime=nvidia --gpus all --network host registry.cn-beijing.aliyuncs.com/public-development-resources/langchain-chatglm-webui:Base bash` 31 | 2. git clone项目: `git clone https://github.com/thomas-yanxin/LangChain-ChatGLM-Webui.git` 32 | 3. 进入本项目目录:`cd LangChain-ChatGLM-Webui` 33 | 4. 安装依赖包:`pip3 install -r requirements.txt` 34 | 5. 执行app.py:`python3 app.py` 35 | 36 | ## Docker 小白运行 37 | 38 | 1. 运行镜像:`docker run -d --name langchain-ChatGLM-webui --runtime=nvidia --gpus all --network host registry.cn-beijing.aliyuncs.com/public-development-resources/langchain-chatglm-webui:latest` 39 | 2. 访问服务:`http://ip:7860` 40 | 3. 运行环境,镜像大小约14G。 41 | 4. nvidia-runtime 请参考: [container-toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html) 42 | 5. 本地模型放置目录: 43 | BELLE-LLaMA-Local:/pretrainmodel/belle 44 | Vicuna-Local:/pretrainmodel/vicuna 45 | ChatGLM-Local:/pretrainmodel/chatglm 46 | 47 | 6. 挂载cache目录,容器重启或更新无需重新下载相关模型。 48 | `-v langchain-ChatGLM-webui-cache:/root/.cache/` 49 | 50 | ## Jina Serving API 51 | 52 | 1. 启动服务:`lc-serve deploy local jina_serving` 53 | 54 | 2. 执行curl初始化模型命令 55 | 56 | ```bash 57 | curl -X 'POST' \ 58 |   'http://localhost:8080/reinit_model' \ 59 |   -H 'accept: application/json' \ 60 |   -H 'Content-Type: application/json' \ 61 |   -d '{ 62 |     "large_language_model": "ChatGLM-6B-int8", 63 |     "embedding_model": "text2vec-base" 64 |   }' 65 | ``` 66 | 67 | 3. 执行curl构建向量库命令 68 | 69 | ```bash 70 | curl -X 'POST' \ 71 |   'http://localhost:8080/vector_store' \ 72 |   -H 'accept: application/json' \ 73 |   -H 'Content-Type: application/json' \ 74 |   -d '{ 75 |     "file_path": "./README.md" 76 |   }' 77 | ``` 78 | 79 | 4. 执行curl发送指令 80 | 81 | ```bash 82 | curl -X 'POST' \ 83 |   'http://localhost:8080/predict' \ 84 |   -H 'accept: application/json' \ 85 |   -H 'Content-Type: application/json' \ 86 |   -d '{ 87 |     "input": "ChatGLM-6B的具体局限性?" 88 |     "use_web": true, 89 |     "top_k": 3,   90 |     "history_len": 1, 91 |     "temperature": 0.01, 92 |     "top_p": 0.1, 93 |     "history": [] 94 |   }' 95 | ``` 96 | 97 | 5. Docker API 服务快速启动 98 | 99 | ```bash 100 | docker run -d --name LangChain-ChatGLM-Webui --runtime=nvidia --gpus all --network host registry.cn-beijing.aliyuncs.com/public-development-resources/langchain-chatglm-webui:api 101 | ``` 102 | -------------------------------------------------------------------------------- /docs/faq.md: -------------------------------------------------------------------------------- 1 | # 常见问题 2 | 3 | ### 模型下载问题 4 | 5 | 对于国内用户来说, 直接从HuggingFace下载模型可能会遇到网络阻碍, 您可以先通过以下链接提前将模型下载并解压到本地: 6 | | large language model | Embedding model | 7 | | :----: | :----: | 8 | | [ChatGLM-6B](https://s3.openi.org.cn/opendata/attachment/b/3/b33c55bb-8e7c-4e9d-90e5-c310dcc776d9?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=1fa9e58b6899afd26dd3%2F20230424%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230424T014727Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%3D%22chatglm-6b.zip%22&X-Amz-Signature=7324f73e66ee6ec9b955023d4f56076e3817b7daf14e874865c45f409094adf3) | [text2vec-large-chinese](https://s3.openi.org.cn/opendata/attachment/a/2/a2f0edca-1b7b-4dfc-b7c8-15730d33cc3e?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=1fa9e58b6899afd26dd3%2F20230424%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230424T050110Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%3D%22text2vec-large-chinese.zip%22&X-Amz-Signature=a2e1bdb16f7b55fa05e134649ea1967c0be32d7afbcd300ea82202cc3a7aae6c) | 9 | | [ChatGLM-6B-int8](https://s3.openi.org.cn/opendata/attachment/3/a/3aad10d1-ac8e-48f8-ac5f-cea8b54cf41b?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=1fa9e58b6899afd26dd3%2F20230424%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230424T014606Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%3D%22chatglm-6b-int8.zip%22&X-Amz-Signature=50f15ed60e4feaffb0984feafd5b2627fa8b5b4105c04a2516b122fb251eedc8) | [ernie-3.0-base-zh](https://s3.openi.org.cn/opendata/attachment/7/3/733fe6e4-2c29-46d8-93e8-6be16194a204?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=1fa9e58b6899afd26dd3%2F20230424%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230424T050111Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%3D%22ernie-3.0-base-zh.zip%22&X-Amz-Signature=92290028b0a64def599f27804e9314972fd115724ed4ad312a48797d20c5feb1) | 10 | | [ChatGLM-6B-int4](https://s3.openi.org.cn/opendata/attachment/b/2/b2c7f23f-6864-40da-9c81-2c0607cb1d02?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=1fa9e58b6899afd26dd3%2F20230424%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230424T050113Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%3D%22chatglm-6b-int4.zip%22&X-Amz-Signature=e8204284dcb2138e6fdce87d1b704a39f0dbe362512c28cef5a51cdea78a2858) | [ernie-3.0-nano-zh](https://s3.openi.org.cn/opendata/attachment/2/2/22833889-1683-422e-a44c-929bc379904c?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=1fa9e58b6899afd26dd3%2F20230422%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230422T152948Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%3D%22ernie-3.0-nano-zh.zip%22&X-Amz-Signature=c8b213d627efb8518c8e54a857c7c323e5e0451a08a3a473d37e2372aabd182f) | 11 | | [ChatGLM-6B-int4-qe](https://s3.openi.org.cn/opendata/attachment/b/f/bf5131da-62e0-4b57-b52a-4135c273b4fc?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=1fa9e58b6899afd26dd3%2F20230424%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230424T050105Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%3D%22chatglm-6b-int4-qe.zip%22&X-Amz-Signature=3205ca3c5690a086eef95bd032a7314b258a7550ad88bb36c4b738cc5059fbee) | [ernie-3.0-xbase-zh](https://s3.openi.org.cn/opendata/attachment/c/5/c5f746c3-4c60-4fb7-8424-8f7e40f3cce8?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=1fa9e58b6899afd26dd3%2F20230424%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230424T050103Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%3D%22ernie-3.0-xbase-zh.zip%22&X-Amz-Signature=edffb1ee1e7729fc45305750e1faaff54546683e1e1a983fce4cbff16d28e219) | 12 | | [Vicuna-7b-1.1](https://s3.openi.org.cn/opendata/attachment/2/5/25854cfb-3d57-44ff-a842-2a98e1a2dafe?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=1fa9e58b6899afd26dd3%2F20230423%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230423T014232Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%3D%22vicuna-7b-1.1.zip%22&X-Amz-Signature=353d6295d5260d5c53ee512680b211b67fe91fab8376aaef4c17e477f09a666a) | [simbert-base-chinese](https://s3.openi.org.cn/opendata/attachment/1/9/19a54b2f-e527-47e1-aa16-62887498b7f7?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=1fa9e58b6899afd26dd3%2F20230423%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230423T033222Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%3D%22simbert-base-chinese.zip%22&X-Amz-Signature=6ba81f63582fcb5a45fdc33415aabd40cd8ce0e803d79388390006f5feec5def) | 13 | | [BELLE-LLaMA-7B-2M](https://s3.openi.org.cn/opendata/attachment/2/6/26f570ea-03c8-4e48-8058-e90b4854edfb?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=1fa9e58b6899afd26dd3%2F20230424%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230424T045945Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%3D%22BELLE-LLaMA-7B-2M.zip%22&X-Amz-Signature=a3a06bbce4389e21e384d5831f3a484bfae29a4af5a71fb043c26e6282ac00ee) | | 14 | | [BELLE-LLaMA-13B-2M](https://s3.openi.org.cn/opendata/attachment/a/c/acb0655f-4d3c-49c4-8320-f4b8584cf5bb?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=1fa9e58b6899afd26dd3%2F20230424%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230424T014910Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%3D%22BELLE-LLaMA-13B-2M.zip%22&X-Amz-Signature=7409fd2eba9768e720380759601cd462deabb3ebb24f493b21e1762b5f3410da) | | 15 | 16 | 然后在 `config.py` 文件中对以下字段进行修改: 17 | 18 | ```python 19 | 20 | embedding_model_dict = { 21 | "ernie-tiny": "nghuyong/ernie-3.0-nano-zh", 22 | "ernie-base": "your_model_path", 23 | "ernie-medium": "your_model_path", 24 | "ernie-xbase": "your_model_path", 25 | "text2vec-base": "your_model_path", 26 | 'simbert-base-chinese': 'your_model_path', 27 | 'paraphrase-multilingual-MiniLM-L12-v2': "your_model_path" 28 | } 29 | 30 | ``` 31 | 32 | 具体路径仿见[issue 36](https://github.com/thomas-yanxin/LangChain-ChatGLM-Webui/issues/36)、[issue 37](https://github.com/thomas-yanxin/LangChain-ChatGLM-Webui/issues/37) 33 | 34 | ### 爆显存问题 35 | 36 | * ChatGLM-6B 模型硬件需求 37 | | **量化等级** | **最低 GPU 显存**(推理) | **最低 GPU 显存**(高效参数微调) | 38 | | -------------- | ------------------------- | --------------------------------- | 39 | | FP16(无量化) | 13 GB | 14 GB | 40 | | INT8 | 8 GB | 9 GB | 41 | | INT4 | 6 GB | 7 GB | 42 | 43 | 若您的设备显存有限 44 | 45 | 1. 可以选择 `ChatGLM-6B-int8` 或者 `ChatGLM-6B-int4` 以及选择较小的Embedding Model进行组合使用. 46 | 2. 参数选择时,可以选择叫小的history进行尝试. 47 | 48 | ### 常见的细节问题 49 | 50 | 1. 需要等文件完全上传之后再进行对话. 51 | 2. 若detectron2安装有问题, 可以执行:`pip install git+https://openi.pcl.ac.cn/Learning-Develop-Union/detectron2.git`. 52 | 3. 目前项目仅在linux环境下进行测试,win/mac下或许存在一些未知问题. 53 | -------------------------------------------------------------------------------- /docs/update_history.md: -------------------------------------------------------------------------------- 1 | # 更新日志 2 | 3 | ## May 20 2023 4 | 5 | 1. vsctor store 本地存储 6 | 7 | ## May 19 2023 8 | 9 | 1. 提供PaddlePaddle版本和AIStudio环境 10 | 11 | ## Apr 28 2023 12 | 13 | 1. 增加推荐Embedding Model 14 | 2. 修复modelscope引用chatglm_llm错误问题 15 | 3. 修复相关注释问题 16 | 4. 更新微信群二维码 17 | 5. 完善FAQ和部署文档 18 | 6. 增加Vicuna-13B-1.1模型 19 | 7. 更改向量存储为Qdrant(尝试) 20 | 21 | ## Apr 27 2023 22 | 23 | 1. 优化Jina Serving API,支持批量文件 24 | 25 | ## Apr 26 2023 26 | 27 | 1. 增加Jina Serving API调用 28 | 2. 完善Readme描述 29 | 3. 修复切换模型时可能的潜在问题 30 | 4. 修复Jina Serving的Crul命令 31 | 5. 增加model cache目录@[AliscaCL](https://github.com/AliscaCL) 32 | 6. 更新Docker镜像地址@[online2311](https://github.com/online2311) 33 | 7. gradio发布时增加多项参数@[godlockin](https://github.com/godlockin) 34 | 8. 修复安装依赖冲突@[online2311](https://github.com/online2311) 35 | 36 | ## Apr 25 2023 37 | 38 | 1. 上传项目镜像至阿里云:`registry.cn-beijing.aliyuncs.com/public-development-resources/langchain-chatglm-webui:latest` 39 | 2. 优化Docker部署说明 40 | 3. 提供单独的config.py配置文件 41 | 4. Dockerfile增加aria2c unzip 42 | 5. 优化Dockerfile 43 | 6. config.py 增加本地Models参数 44 | 7. 构建基础镜像: `registry.cn-beijing.aliyuncs.com/public-development-resources/langchain-chatglm-webui:Base` 45 | 46 | 上述由[@online2311](https://github.com/online2311)贡献 47 | 48 | ## Apr 24 2023 49 | 50 | 1. 提供群聊沟通 51 | 2. 更新Dockerfile及requirements.txt 52 | 53 | ## Apr 22 2023 54 | 55 | 1. 优化模型加载机制 56 | 2. 修复对不同系列模型推理的bug 57 | 3. 修改参数不参与重新加载模型 58 | 4. 增加对Belle系列模型的支持 59 | 5. 优化UI设计 60 | 6. 完善Readme描述 61 | 62 | ## Apr 21 2023 63 | 64 | 1. 提供对`Vicuna`模型的支持 65 | 2. ModelScope版本支持Web Search 66 | 3. 在[HuggingFace](https://huggingface.co/spaces/thomas-yanxin/LangChain-ChatLLM)和[ModelScope](https://www.modelscope.cn/studios/AI-ModelScope/LangChain-ChatLLM/summary)的APP上支持了由Jina.ai提供的`ViT-B-32::laion2b-s34b-b79k` Embedding Inference 67 | 68 | ## Apr 20 2023 69 | 70 | 1. 优化对`.pdf`的支持 71 | 2. 优化UI设计 72 | 3. 修改对于Docker镜像的描述 73 | 4. 提供HuggingFace的在线体验 74 | 5. 完善Readme描述 75 | 76 | ## Apr 19 2023 77 | 78 | 1. 提供视频部署教程 79 | 2. 提供Docker部署及文字教程 80 | 3. 支持多卡推理ChatGLM-6B 81 | 4. 增加外部访问支持 82 | 5. 增加ChatGLM-6b-local以及本地模型读取路径 83 | 6. 修复text2vec无法加载的错误 84 | 85 | 上述2-6由社区[@online2311](https://github.com/online2311)贡献 86 | 87 | ## Apr 18 2023 88 | 89 | 1. 更新ModelScope版本 90 | 2. 完善Readme描述 91 | 92 | ## Apr 17 2023 93 | 94 | 1. 提供部署文档 95 | 2. 支持`.pdf`格式 96 | 3. 更新Docker镜像地址 97 | 4. 完善Readme描述 98 | 99 | ## Apr 16 2023 100 | 101 | 1. 提供模型下载链接 102 | 2. 完善Prompt设计 103 | 3. 修复上下文的bug 104 | 4. 支持更多的LLM和Embedding Model 105 | 5. 同步更新ModelScope版本 106 | 6. 完善Readme描述 107 | 108 | ## Apr 15 2023 109 | 110 | 1. 完善Readme描述 111 | 112 | ## Apr 14 2023 113 | 114 | 1. 提供离线的`nltk_data`依赖文件, 用户无需再次下载 115 | 2. 支持上下文 116 | 3. 增加支持的Embedding Model 117 | 4. 增加参数`history_len`、`temperature`、`top_p` 118 | 5. 同步更新ModelScope版本 119 | 6. 完善Readme描述 120 | 121 | ## Apr 13 2023 122 | 123 | 1. 提供ModelScope版本,支持在线体验 124 | 2. 使用langchain中的`RetrievalQA`替代之前选用的`ChatVectorDBChain` 125 | 3. 提供选择参数`VECTOR_SEARCH_TOP_K` 126 | 4. 删除提供的错误Docker地址 127 | 128 | ## Apr 12 2023 129 | 130 | 1. 增加对Embedding Model推理设备的定义 131 | 132 | ## Apr 11 2023 133 | 134 | 1. 提供部署镜像 135 | 2. 完善Readme描述 136 | 137 | ## Apr 10 2023 138 | 139 | 1. 提供多种LLM和Embedding Model可选择 140 | 2. 增加显存清理机制 141 | 3. 完善Readme描述 142 | 143 | ## Apr 10 2023 144 | 145 | 1. 初始化仓库, 提交Readme和Licence 146 | 2. 提交基础关键代码: app.py和chatglm_llm.py 147 | 3. 支持ChatGLM-6B的LLM和GanymedeNil/text2vec-large-chinese的Embedding Model 148 | -------------------------------------------------------------------------------- /img/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/img/bg.jpg -------------------------------------------------------------------------------- /img/demo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/img/demo.jpg -------------------------------------------------------------------------------- /img/demo_hf.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/img/demo_hf.jpg -------------------------------------------------------------------------------- /img/demo_ms.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/img/demo_ms.jpg -------------------------------------------------------------------------------- /img/demo_new.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/img/demo_new.jpg -------------------------------------------------------------------------------- /img/wechat_group.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/img/wechat_group.jpg -------------------------------------------------------------------------------- /jina_serving.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import os 3 | from typing import List 4 | 5 | import nltk 6 | import qdrant_client 7 | import sentence_transformers 8 | import torch 9 | from duckduckgo_search import ddg 10 | from duckduckgo_search.utils import SESSION 11 | from langchain.chains import RetrievalQA 12 | from langchain.document_loaders import UnstructuredFileLoader 13 | from langchain.embeddings.huggingface import HuggingFaceEmbeddings 14 | from langchain.prompts import PromptTemplate 15 | from langchain.prompts.prompt import PromptTemplate 16 | from langchain.vectorstores import Qdrant 17 | from lcserve import serving 18 | 19 | from chatllm import ChatLLM 20 | from chinese_text_splitter import ChineseTextSplitter 21 | from config import * 22 | 23 | nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data") 24 | ] + nltk.data.path 25 | 26 | embedding_model_dict = embedding_model_dict 27 | llm_model_dict = llm_model_dict 28 | EMBEDDING_DEVICE = EMBEDDING_DEVICE 29 | LLM_DEVICE = LLM_DEVICE 30 | VECTOR_STORE_PATH = VECTOR_STORE_PATH 31 | COLLECTION_NAME = COLLECTION_NAME 32 | num_gpus = num_gpus 33 | init_llm = init_llm 34 | init_embedding_model = init_embedding_model 35 | 36 | 37 | 38 | def search_web(query): 39 | 40 | SESSION.proxies = { 41 | "http": f"socks5h://localhost:7890", 42 | "https": f"socks5h://localhost:7890" 43 | } 44 | results = ddg(query) 45 | web_content = '' 46 | if results: 47 | for result in results: 48 | web_content += result['body'] 49 | return web_content 50 | 51 | 52 | class KnowledgeBasedChatLLM: 53 | 54 | llm: object = None 55 | embeddings: object = None 56 | 57 | def init_model_config( 58 | self, 59 | large_language_model: str = init_llm, 60 | embedding_model: str = init_embedding_model, 61 | ): 62 | self.llm = ChatLLM() 63 | if 'chatglm' in large_language_model.lower(): 64 | self.llm.model_type = 'chatglm' 65 | self.llm.model_name_or_path = llm_model_dict['chatglm'][ 66 | large_language_model] 67 | elif 'belle' in large_language_model.lower(): 68 | self.llm.model_type = 'belle' 69 | self.llm.model_name_or_path = llm_model_dict['belle'][ 70 | large_language_model] 71 | elif 'vicuna' in large_language_model.lower(): 72 | self.llm.model_type = 'vicuna' 73 | self.llm.model_name_or_path = llm_model_dict['vicuna'][ 74 | large_language_model] 75 | self.embeddings = HuggingFaceEmbeddings( 76 | model_name=embedding_model_dict[embedding_model], ) 77 | self.embeddings.client = sentence_transformers.SentenceTransformer( 78 | self.embeddings.model_name, device=EMBEDDING_DEVICE) 79 | self.llm.load_llm(llm_device=LLM_DEVICE, num_gpus=num_gpus) 80 | 81 | def init_knowledge_vector_store(self, 82 | filepath: str or List[str],): 83 | loaded_files = [] 84 | if isinstance(filepath, str): 85 | if not os.path.exists(filepath): 86 | return "路径不存在" 87 | elif os.path.isfile(filepath): 88 | file = os.path.split(filepath)[-1] 89 | try: 90 | docs = self.load_file(filepath) 91 | print(f"{file} 已成功加载") 92 | loaded_files.append(filepath) 93 | except Exception as e: 94 | print(e) 95 | print(f"{file} 未能成功加载") 96 | return f"{file} 未能成功加载" 97 | elif os.path.isdir(filepath): 98 | docs = [] 99 | for file in os.listdir(filepath): 100 | fullfilepath = os.path.join(filepath, file) 101 | try: 102 | docs += self.load_file(fullfilepath) 103 | print(f"{file} 已成功加载") 104 | loaded_files.append(fullfilepath) 105 | except Exception as e: 106 | print(e) 107 | print(f"{file} 未能成功加载") 108 | else: 109 | docs = [] 110 | for file in filepath: 111 | try: 112 | docs += self.load_file(file) 113 | print(f"{file} 已成功加载") 114 | loaded_files.append(file) 115 | except Exception as e: 116 | print(e) 117 | print(f"{file} 未能成功加载") 118 | if len(docs) > 0: 119 | if VECTOR_STORE_PATH and os.path.isdir(VECTOR_STORE_PATH): 120 | vector_store = Qdrant.from_documents( 121 | docs, 122 | self.embeddings, 123 | path=VECTOR_STORE_PATH, 124 | collection_name=COLLECTION_NAME, 125 | ) 126 | vector_store.add_documents(docs) 127 | else: 128 | vector_store = Qdrant.from_documents( 129 | docs, 130 | self.embeddings, 131 | path=VECTOR_STORE_PATH, 132 | collection_name=COLLECTION_NAME, 133 | ) 134 | return "文件均未成功加载,请检查依赖包或文件路径。", loaded_files 135 | else: 136 | print("文件均未成功加载,请检查依赖包或文件路径。") 137 | return "文件均未成功加载,请检查依赖包或文件路径。", loaded_files 138 | 139 | def get_knowledge_based_answer(self, 140 | query, 141 | web_content, 142 | top_k: int = 6, 143 | history_len: int = 3, 144 | temperature: float = 0.01, 145 | top_p: float = 0.1, 146 | history=[]): 147 | self.llm.temperature = temperature 148 | self.llm.top_p = top_p 149 | self.history_len = history_len 150 | self.top_k = top_k 151 | if web_content: 152 | prompt_template = f"""基于以下已知信息,简洁和专业的来回答用户的问题。 153 | 如果无法从中得到答案,请说 "根据已知信息无法回答该问题" 或 "没有提供足够的相关信息",不允许在答案中添加编造成分,答案请使用中文。 154 | 已知网络检索内容:{web_content}""" + """ 155 | 已知内容: 156 | {context} 157 | 问题: 158 | {question}""" 159 | else: 160 | prompt_template = """基于以下已知信息,请简洁并专业地回答用户的问题。 161 | 如果无法从中得到答案,请说 "根据已知信息无法回答该问题" 或 "没有提供足够的相关信息"。不允许在答案中添加编造成分。另外,答案请使用中文。 162 | 163 | 已知内容: 164 | {context} 165 | 166 | 问题: 167 | {question}""" 168 | prompt = PromptTemplate(template=prompt_template, 169 | input_variables=["context", "question"]) 170 | self.llm.history = history[ 171 | -self.history_len:] if self.history_len > 0 else [] 172 | client = qdrant_client.QdrantClient(path=VECTOR_STORE_PATH, 173 | prefer_grpc=True) 174 | qdrant = Qdrant(client=client, 175 | collection_name=COLLECTION_NAME, 176 | embedding_function=self.embeddings.embed_query) 177 | knowledge_chain = RetrievalQA.from_llm( 178 | llm=self.llm, 179 | retriever=qdrant.as_retriever(search_kwargs={"k": self.top_k}), 180 | prompt=prompt) 181 | knowledge_chain.combine_documents_chain.document_prompt = PromptTemplate( 182 | input_variables=["page_content"], template="{page_content}") 183 | 184 | knowledge_chain.return_source_documents = True 185 | 186 | result = knowledge_chain({"query": query}) 187 | return result 188 | 189 | def load_file(self, filepath): 190 | if filepath.lower().endswith(".md"): 191 | loader = UnstructuredFileLoader(filepath, mode="elements") 192 | docs = loader.load() 193 | elif filepath.lower().endswith(".pdf"): 194 | loader = UnstructuredFileLoader(filepath) 195 | textsplitter = ChineseTextSplitter(pdf=True) 196 | docs = loader.load_and_split(textsplitter) 197 | else: 198 | loader = UnstructuredFileLoader(filepath, mode="elements") 199 | textsplitter = ChineseTextSplitter(pdf=False) 200 | docs = loader.load_and_split(text_splitter=textsplitter) 201 | return docs 202 | 203 | 204 | knowladge_based_chat_llm = KnowledgeBasedChatLLM() 205 | 206 | 207 | def init_model(): 208 | try: 209 | knowladge_based_chat_llm.init_model_config() 210 | knowladge_based_chat_llm.llm._call("你好") 211 | return """初始模型已成功加载""" 212 | except Exception as e: 213 | 214 | return """模型未成功加载,请检查后重新尝试""" 215 | 216 | 217 | @serving 218 | def reinit_model(large_language_model: str, embedding_model: str): 219 | try: 220 | knowladge_based_chat_llm.init_model_config( 221 | large_language_model=large_language_model, 222 | embedding_model=embedding_model) 223 | model_status = """模型已成功重新加载""" 224 | except Exception as e: 225 | model_status = """模型未成功加载,请检查后重新尝试""" 226 | return model_status 227 | 228 | 229 | @serving 230 | def vector_store(file_path: str or List[str]): 231 | 232 | vector_store_state, loaded_files = knowladge_based_chat_llm.init_knowledge_vector_store( 233 | file_path) 234 | return vector_store_state 235 | 236 | 237 | @serving 238 | def predict(input: str, 239 | use_web: bool, top_k: int, history_len: int, temperature: float, 240 | top_p: float, history: list): 241 | if history == None: 242 | history = [] 243 | 244 | if use_web == 'True': 245 | web_content = search_web(query=input) 246 | else: 247 | web_content = '' 248 | 249 | resp = knowladge_based_chat_llm.get_knowledge_based_answer( 250 | query=input, 251 | web_content=web_content, 252 | top_k=top_k, 253 | history_len=history_len, 254 | temperature=temperature, 255 | top_p=top_p, 256 | history=history) 257 | history.append((input, resp['result'])) 258 | print(resp['result']) 259 | return resp['result'] 260 | 261 | if __name__ == "__main__": 262 | reinit_model(large_language_model='ChatGLM-6B-int8', 263 | embedding_model='text2vec-base') 264 | 265 | vector_store(file_path='./README.md') 266 | 267 | predict('chatglm-6b的局限性在哪里?', 268 | use_web=False, 269 | top_k=6, 270 | history_len=3, 271 | temperature=0.01, 272 | top_p=0.1, 273 | history=[]) 274 | -------------------------------------------------------------------------------- /model_cache/OfflineDeploy.md: -------------------------------------------------------------------------------- 1 | This path is the model cache path. 2 | It could be setting via config.MODEL_CACHE_PATH variable in config.py scripts. 3 | 4 | You could run the app.py file as usural, and then all model download by hugging face migt be downloaded in this folder. 5 | When you try to transfer this project to offline environment, you could directly package all the file with 6 | 7 | ```bash 8 | tar -zcvf LangChain-ChatGLM-Webui.tar.gz /path/to/LangChain-ChatGLM-Webui 9 | ``` 10 | 11 | Then transfer the tar file to the offline line environment and extend with 12 | 13 | ```bash 14 | mkdir -p /path/to/LangChain-ChatGLM-Webui 15 | tar -zcvf LangChain-ChatGLM-Webui.tar.gz -C /path/to/LangChain-ChatGLM-Webui 16 | cd /path/to/LangChain-ChatGLM-Webui 17 | ``` 18 | 19 | Then run script as usural in offline environment. -------------------------------------------------------------------------------- /modelscope/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/modelscope/README.md -------------------------------------------------------------------------------- /modelscope/app.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import gradio as gr 4 | import nltk 5 | import torch 6 | from chatglm_llm import ChatGLM 7 | from duckduckgo_search import ddg 8 | from duckduckgo_search.utils import SESSION 9 | from langchain.chains import RetrievalQA 10 | from langchain.document_loaders import UnstructuredFileLoader 11 | from langchain.prompts import PromptTemplate 12 | from langchain.vectorstores import FAISS 13 | from modelscope_hub import ModelScopeEmbeddings 14 | 15 | nltk.data.path.append('../nltk_data') 16 | 17 | DEVICE = "cuda" if torch.cuda.is_available( 18 | ) else "mps" if torch.backends.mps.is_available() else "cpu" 19 | 20 | embedding_model_dict = { 21 | "corom-tiny": "damo/nlp_corom_sentence-embedding_chinese-tiny", 22 | "corom-tiny-ecom": "damo/nlp_corom_sentence-embedding_chinese-tiny-ecom", 23 | "corom-base-ecom": "damo/nlp_corom_sentence-embedding_chinese-base-ecom", 24 | "corom-base": "damo/nlp_corom_sentence-embedding_chinese-base", 25 | } 26 | 27 | llm_dict = { 28 | 'ChatGLM-6B': { 29 | 'model_name': 'ZhipuAI/ChatGLM-6B', 30 | 'model_revision': 'v1.0.15', 31 | }, 32 | 'ChatGLM-6B-int8': { 33 | 'model_name': 'thomas/ChatGLM-6B-Int8', 34 | 'model_revision': 'v1.0.3', 35 | }, 36 | 'ChatGLM-6B-int4': { 37 | 'model_name': 'ZhipuAI/ChatGLM-6B-Int4', 38 | 'model_revision': 'v1.0.3', 39 | } 40 | } 41 | 42 | 43 | def search_web(query): 44 | 45 | SESSION.proxies = { 46 | "http": f"socks5h://localhost:7890", 47 | "https": f"socks5h://localhost:7890" 48 | } 49 | results = ddg(query) 50 | web_content = '' 51 | if results: 52 | for result in results: 53 | web_content += result['body'] 54 | return web_content 55 | 56 | 57 | def init_knowledge_vector_store(embedding_model, filepath): 58 | 59 | embeddings = ModelScopeEmbeddings( 60 | model_name=embedding_model_dict[embedding_model], ) 61 | 62 | loader = UnstructuredFileLoader(filepath, mode="elements") 63 | docs = loader.load() 64 | 65 | vector_store = FAISS.from_documents(docs, embeddings) 66 | return vector_store 67 | 68 | 69 | def get_knowledge_based_answer( 70 | query, 71 | large_language_model, 72 | vector_store, 73 | VECTOR_SEARCH_TOP_K, 74 | web_content, 75 | chat_history=[], 76 | history_len=3, 77 | temperature=0.01, 78 | top_p=0.9, 79 | ): 80 | if web_content: 81 | prompt_template = f"""基于以下已知信息,简洁和专业的来回答用户的问题。 82 | 如果无法从中得到答案,请说 "根据已知信息无法回答该问题" 或 "没有提供足够的相关信息",不允许在答案中添加编造成分,答案请使用中文。 83 | 已知网络检索内容:{web_content}""" + """ 84 | 已知内容: 85 | {context} 86 | 问题: 87 | {question}""" 88 | else: 89 | prompt_template = """基于以下已知信息,请简洁并专业地回答用户的问题。 90 | 如果无法从中得到答案,请说 "根据已知信息无法回答该问题" 或 "没有提供足够的相关信息"。不允许在答案中添加编造成分。另外,答案请使用中文。 91 | 92 | 已知内容: 93 | {context} 94 | 95 | 问题: 96 | {question}""" 97 | prompt = PromptTemplate(template=prompt_template, 98 | input_variables=["context", "question"]) 99 | 100 | chatLLM = ChatGLM() 101 | chatLLM.model_name = llm_dict[large_language_model]['model_name'] 102 | chatLLM.model_revision = llm_dict[large_language_model]['model_revision'] 103 | 104 | chatLLM.history = chat_history[-history_len:] if history_len > 0 else [] 105 | chatLLM.temperature = temperature 106 | chatLLM.top_p = top_p 107 | 108 | knowledge_chain = RetrievalQA.from_llm( 109 | llm=chatLLM, 110 | retriever=vector_store.as_retriever( 111 | search_kwargs={"k": VECTOR_SEARCH_TOP_K}), 112 | prompt=prompt) 113 | knowledge_chain.combine_documents_chain.document_prompt = PromptTemplate( 114 | input_variables=["page_content"], template="{page_content}") 115 | 116 | knowledge_chain.return_source_documents = True 117 | result = knowledge_chain({"query": query}) 118 | 119 | return result['result'] 120 | 121 | 122 | def clear_session(): 123 | return '', None 124 | 125 | 126 | def predict(input, 127 | large_language_model, 128 | embedding_model, 129 | file_obj, 130 | VECTOR_SEARCH_TOP_K, 131 | history_len, 132 | temperature, 133 | top_p, 134 | use_web, 135 | history=None): 136 | if history == None: 137 | history = [] 138 | print(file_obj.name) 139 | if use_web == 'True': 140 | web_content = search_web(query=input) 141 | else: 142 | web_content = '' 143 | vector_store = init_knowledge_vector_store(embedding_model, file_obj.name) 144 | 145 | resp = get_knowledge_based_answer( 146 | query=input, 147 | large_language_model=large_language_model, 148 | vector_store=vector_store, 149 | VECTOR_SEARCH_TOP_K=VECTOR_SEARCH_TOP_K, 150 | web_content=web_content, 151 | chat_history=history, 152 | history_len=history_len, 153 | temperature=temperature, 154 | top_p=top_p, 155 | ) 156 | print(resp) 157 | history.append((input, resp)) 158 | return '', history, history 159 | 160 | 161 | if __name__ == "__main__": 162 | block = gr.Blocks() 163 | with block as demo: 164 | gr.Markdown("""

LangChain-ChatLLM-Webui

165 |
166 | 本项目基于LangChain和大型语言模型系列模型, 提供基于本地知识的自动问答应用.
167 | 目前项目提供基于ChatGLM-6B 的LLM和包括nlp_corom_sentence-embedding系列的多个Embedding模型, 支持上传 txt、docx、md 等文本格式文件.
168 | 后续将提供更加多样化的LLM、Embedding和参数选项供用户尝试, 欢迎关注Github地址. 169 |
170 | """) 171 | with gr.Row(): 172 | with gr.Column(scale=1): 173 | model_choose = gr.Accordion("模型选择") 174 | with model_choose: 175 | large_language_model = gr.Dropdown( 176 | ["ChatGLM-6B", "ChatGLM-6B-int4", 'ChatGLM-6B-int8'], 177 | label="large language model", 178 | value="ChatGLM-6B-int8") 179 | 180 | embedding_model = gr.Dropdown(list( 181 | embedding_model_dict.keys()), 182 | label="Embedding model", 183 | value="corom-tiny") 184 | 185 | file = gr.File(label='请上传知识库文件', 186 | file_types=['.txt', '.md', '.docx']) 187 | use_web = gr.Radio(["True", "False"], 188 | label="Web Search", 189 | value="False") 190 | model_argument = gr.Accordion("模型参数配置") 191 | 192 | with model_argument: 193 | 194 | VECTOR_SEARCH_TOP_K = gr.Slider( 195 | 1, 196 | 10, 197 | value=6, 198 | step=1, 199 | label="vector search top k", 200 | interactive=True) 201 | 202 | HISTORY_LEN = gr.Slider(0, 203 | 3, 204 | value=0, 205 | step=1, 206 | label="history len", 207 | interactive=True) 208 | 209 | temperature = gr.Slider(0, 210 | 1, 211 | value=0.01, 212 | step=0.01, 213 | label="temperature", 214 | interactive=True) 215 | top_p = gr.Slider(0, 216 | 1, 217 | value=0.9, 218 | step=0.1, 219 | label="top_p", 220 | interactive=True) 221 | 222 | with gr.Column(scale=4): 223 | chatbot = gr.Chatbot(label='ChatLLM').style(height=400) 224 | message = gr.Textbox(label='请输入问题') 225 | state = gr.State() 226 | 227 | with gr.Row(): 228 | clear_history = gr.Button("🧹 清除历史对话") 229 | send = gr.Button("🚀 发送") 230 | 231 | send.click(predict, 232 | inputs=[ 233 | message, large_language_model, 234 | embedding_model, file, VECTOR_SEARCH_TOP_K, 235 | HISTORY_LEN, temperature, top_p, use_web, 236 | state 237 | ], 238 | outputs=[message, chatbot, state]) 239 | clear_history.click(fn=clear_session, 240 | inputs=[], 241 | outputs=[chatbot, state], 242 | queue=False) 243 | 244 | message.submit(predict, 245 | inputs=[ 246 | message, large_language_model, 247 | embedding_model, file, 248 | VECTOR_SEARCH_TOP_K, HISTORY_LEN, 249 | temperature, top_p, use_web, state 250 | ], 251 | outputs=[message, chatbot, state]) 252 | gr.Markdown("""提醒:
253 | 1. 更改LLM模型前请先刷新页面,否则将返回error(后续将完善此部分).
254 | 2. 使用时请先上传自己的知识文件,并且文件中不含某些特殊字符,否则将返回error.
255 | 3. 请勿上传或输入敏感内容,否则输出内容将被平台拦截返回error.
256 | 4. 有任何使用问题,请通过[问题交流区](https://modelscope.cn/studios/thomas/ChatYuan-test/comment)或[Github Issue区](https://github.com/thomas-yanxin/LangChain-ChatGLM-Webui/issues)进行反馈.
257 | """) 258 | demo.queue().launch(share=False) -------------------------------------------------------------------------------- /modelscope/chatglm_llm.py: -------------------------------------------------------------------------------- 1 | import os 2 | from typing import List, Optional 3 | 4 | import torch 5 | from langchain.llms.base import LLM 6 | from langchain.llms.utils import enforce_stop_tokens 7 | 8 | from modelscope.pipelines import pipeline 9 | from modelscope.utils.constant import Tasks 10 | 11 | os.environ["TOKENIZERS_PARALLELISM"] = "false" 12 | 13 | DEVICE = "cuda" 14 | DEVICE_ID = "0" 15 | CUDA_DEVICE = f"{DEVICE}:{DEVICE_ID}" if DEVICE_ID else DEVICE 16 | 17 | 18 | def torch_gc(): 19 | if torch.cuda.is_available(): 20 | with torch.cuda.device(CUDA_DEVICE): 21 | torch.cuda.empty_cache() 22 | torch.cuda.ipc_collect() 23 | 24 | 25 | class ChatGLM(LLM): 26 | history = [] 27 | max_length = 10000 28 | temperature: float = 0.01 29 | top_p = 0.9 30 | model_name = 'ZhipuAI/ChatGLM-6B' 31 | model_revision = 'v1.0.13' 32 | 33 | def __init__(self): 34 | super().__init__() 35 | 36 | @property 37 | def _llm_type(self) -> str: 38 | return "ChatGLM" 39 | 40 | def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str: 41 | 42 | inputs = { 43 | 'text': prompt, 44 | 'history': self.history, 45 | 'max_length': self.max_length, 46 | 'temperature': self.temperature, 47 | 'top_p': self.top_p 48 | } 49 | pipe = self.pipe() 50 | result = pipe(inputs) 51 | response = result['response'] 52 | updated_history = result['history'] 53 | torch_gc() 54 | if stop is not None: 55 | response = enforce_stop_tokens(response, stop) 56 | self.history = updated_history 57 | return response 58 | 59 | def pipe(self): 60 | pipe = pipeline(task=Tasks.chat, 61 | model=self.model_name, 62 | model_revision=self.model_revision) 63 | return pipe 64 | -------------------------------------------------------------------------------- /modelscope/modelscope_hub.py: -------------------------------------------------------------------------------- 1 | """Wrapper around ModelScopeHub embedding models.""" 2 | from typing import Any, List 3 | 4 | from langchain.embeddings.base import Embeddings 5 | from pydantic import BaseModel, Extra 6 | 7 | 8 | class ModelScopeEmbeddings(BaseModel, Embeddings): 9 | """Wrapper around modelscope_hub embedding models. 10 | 11 | To use, you should have the ``modelscope`` python package installed. 12 | 13 | Example: 14 | .. code-block:: python 15 | 16 | from langchain.embeddings import ModelScopeEmbeddingsEmbeddings 17 | model_id = "damo/nlp_corom_sentence-embedding_english-base" 18 | embed = ModelScopeEmbeddingsEmbeddings(model_id=model_id) 19 | """ 20 | 21 | embed: Any 22 | model_id: str ="damo/nlp_corom_sentence-embedding_english-base" 23 | """Model name to use.""" 24 | 25 | def __init__(self, **kwargs: Any): 26 | """Initialize the modelscope""" 27 | super().__init__(**kwargs) 28 | try: 29 | from modelscope.models import Model 30 | from modelscope.pipelines import pipeline 31 | from modelscope.utils.constant import Tasks 32 | self.embed = pipeline(Tasks.sentence_embedding, 33 | model=self.model_id) 34 | 35 | except ImportError as e: 36 | raise ValueError( 37 | "Could not import some python packages." "Please install it with `pip install modelscope`." 38 | ) from e 39 | 40 | class Config: 41 | """Configuration for this pydantic object.""" 42 | 43 | extra = Extra.forbid 44 | 45 | def embed_documents(self, texts: List[str]) -> List[List[float]]: 46 | """Compute doc embeddings using a modelscope embedding model. 47 | 48 | Args: 49 | texts: The list of texts to embed. 50 | 51 | Returns: 52 | List of embeddings, one for each text. 53 | """ 54 | texts = list(map(lambda x: x.replace("\n", " "), texts)) 55 | inputs = {"source_sentence": texts} 56 | embeddings = self.embed(input=inputs)['text_embedding'] 57 | return embeddings 58 | 59 | def embed_query(self, text: str) -> List[float]: 60 | """Compute query embeddings using a modelscope embedding model. 61 | 62 | Args: 63 | text: The text to embed. 64 | 65 | Returns: 66 | Embeddings for the text. 67 | """ 68 | text = text.replace("\n", " ") 69 | inputs = {"source_sentence": [text]} 70 | embedding = self.embed(input=inputs)['text_embedding'][0] 71 | return embedding -------------------------------------------------------------------------------- /modelscope/requirements.txt: -------------------------------------------------------------------------------- 1 | modelscope -------------------------------------------------------------------------------- /nltk_data/taggers/averaged_perceptron_tagger/averaged_perceptron_tagger.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/taggers/averaged_perceptron_tagger/averaged_perceptron_tagger.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/.DS_Store -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/PY3/README: -------------------------------------------------------------------------------- 1 | Pretrained Punkt Models -- Jan Strunk (New version trained after issues 313 and 514 had been corrected) 2 | 3 | Most models were prepared using the test corpora from Kiss and Strunk (2006). Additional models have 4 | been contributed by various people using NLTK for sentence boundary detection. 5 | 6 | For information about how to use these models, please confer the tokenization HOWTO: 7 | http://nltk.googlecode.com/svn/trunk/doc/howto/tokenize.html 8 | and chapter 3.8 of the NLTK book: 9 | http://nltk.googlecode.com/svn/trunk/doc/book/ch03.html#sec-segmentation 10 | 11 | There are pretrained tokenizers for the following languages: 12 | 13 | File Language Source Contents Size of training corpus(in tokens) Model contributed by 14 | ======================================================================================================================================================================= 15 | czech.pickle Czech Multilingual Corpus 1 (ECI) Lidove Noviny ~345,000 Jan Strunk / Tibor Kiss 16 | Literarni Noviny 17 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 18 | danish.pickle Danish Avisdata CD-Rom Ver. 1.1. 1995 Berlingske Tidende ~550,000 Jan Strunk / Tibor Kiss 19 | (Berlingske Avisdata, Copenhagen) Weekend Avisen 20 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 21 | dutch.pickle Dutch Multilingual Corpus 1 (ECI) De Limburger ~340,000 Jan Strunk / Tibor Kiss 22 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 23 | english.pickle English Penn Treebank (LDC) Wall Street Journal ~469,000 Jan Strunk / Tibor Kiss 24 | (American) 25 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 26 | estonian.pickle Estonian University of Tartu, Estonia Eesti Ekspress ~359,000 Jan Strunk / Tibor Kiss 27 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 28 | finnish.pickle Finnish Finnish Parole Corpus, Finnish Books and major national ~364,000 Jan Strunk / Tibor Kiss 29 | Text Bank (Suomen Kielen newspapers 30 | Tekstipankki) 31 | Finnish Center for IT Science 32 | (CSC) 33 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 34 | french.pickle French Multilingual Corpus 1 (ECI) Le Monde ~370,000 Jan Strunk / Tibor Kiss 35 | (European) 36 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 37 | german.pickle German Neue Zürcher Zeitung AG Neue Zürcher Zeitung ~847,000 Jan Strunk / Tibor Kiss 38 | (Switzerland) CD-ROM 39 | (Uses "ss" 40 | instead of "ß") 41 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 42 | greek.pickle Greek Efstathios Stamatatos To Vima (TO BHMA) ~227,000 Jan Strunk / Tibor Kiss 43 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 44 | italian.pickle Italian Multilingual Corpus 1 (ECI) La Stampa, Il Mattino ~312,000 Jan Strunk / Tibor Kiss 45 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 46 | norwegian.pickle Norwegian Centre for Humanities Bergens Tidende ~479,000 Jan Strunk / Tibor Kiss 47 | (Bokmål and Information Technologies, 48 | Nynorsk) Bergen 49 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 50 | polish.pickle Polish Polish National Corpus Literature, newspapers, etc. ~1,000,000 Krzysztof Langner 51 | (http://www.nkjp.pl/) 52 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 53 | portuguese.pickle Portuguese CETENFolha Corpus Folha de São Paulo ~321,000 Jan Strunk / Tibor Kiss 54 | (Brazilian) (Linguateca) 55 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 56 | slovene.pickle Slovene TRACTOR Delo ~354,000 Jan Strunk / Tibor Kiss 57 | Slovene Academy for Arts 58 | and Sciences 59 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 60 | spanish.pickle Spanish Multilingual Corpus 1 (ECI) Sur ~353,000 Jan Strunk / Tibor Kiss 61 | (European) 62 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 63 | swedish.pickle Swedish Multilingual Corpus 1 (ECI) Dagens Nyheter ~339,000 Jan Strunk / Tibor Kiss 64 | (and some other texts) 65 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 66 | turkish.pickle Turkish METU Turkish Corpus Milliyet ~333,000 Jan Strunk / Tibor Kiss 67 | (Türkçe Derlem Projesi) 68 | University of Ankara 69 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 70 | 71 | The corpora contained about 400,000 tokens on average and mostly consisted of newspaper text converted to 72 | Unicode using the codecs module. 73 | 74 | Kiss, Tibor and Strunk, Jan (2006): Unsupervised Multilingual Sentence Boundary Detection. 75 | Computational Linguistics 32: 485-525. 76 | 77 | ---- Training Code ---- 78 | 79 | # import punkt 80 | import nltk.tokenize.punkt 81 | 82 | # Make a new Tokenizer 83 | tokenizer = nltk.tokenize.punkt.PunktSentenceTokenizer() 84 | 85 | # Read in training corpus (one example: Slovene) 86 | import codecs 87 | text = codecs.open("slovene.plain","Ur","iso-8859-2").read() 88 | 89 | # Train tokenizer 90 | tokenizer.train(text) 91 | 92 | # Dump pickled tokenizer 93 | import pickle 94 | out = open("slovene.pickle","wb") 95 | pickle.dump(tokenizer, out) 96 | out.close() 97 | 98 | --------- 99 | -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/PY3/czech.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/PY3/czech.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/PY3/danish.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/PY3/danish.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/PY3/dutch.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/PY3/dutch.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/PY3/english.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/PY3/english.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/PY3/estonian.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/PY3/estonian.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/PY3/finnish.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/PY3/finnish.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/PY3/french.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/PY3/french.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/PY3/german.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/PY3/german.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/PY3/greek.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/PY3/greek.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/PY3/italian.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/PY3/italian.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/PY3/malayalam.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/PY3/malayalam.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/PY3/norwegian.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/PY3/norwegian.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/PY3/polish.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/PY3/polish.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/PY3/portuguese.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/PY3/portuguese.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/PY3/russian.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/PY3/russian.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/PY3/slovene.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/PY3/slovene.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/PY3/spanish.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/PY3/spanish.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/PY3/swedish.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/PY3/swedish.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/PY3/turkish.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/PY3/turkish.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/README: -------------------------------------------------------------------------------- 1 | Pretrained Punkt Models -- Jan Strunk (New version trained after issues 313 and 514 had been corrected) 2 | 3 | Most models were prepared using the test corpora from Kiss and Strunk (2006). Additional models have 4 | been contributed by various people using NLTK for sentence boundary detection. 5 | 6 | For information about how to use these models, please confer the tokenization HOWTO: 7 | http://nltk.googlecode.com/svn/trunk/doc/howto/tokenize.html 8 | and chapter 3.8 of the NLTK book: 9 | http://nltk.googlecode.com/svn/trunk/doc/book/ch03.html#sec-segmentation 10 | 11 | There are pretrained tokenizers for the following languages: 12 | 13 | File Language Source Contents Size of training corpus(in tokens) Model contributed by 14 | ======================================================================================================================================================================= 15 | czech.pickle Czech Multilingual Corpus 1 (ECI) Lidove Noviny ~345,000 Jan Strunk / Tibor Kiss 16 | Literarni Noviny 17 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 18 | danish.pickle Danish Avisdata CD-Rom Ver. 1.1. 1995 Berlingske Tidende ~550,000 Jan Strunk / Tibor Kiss 19 | (Berlingske Avisdata, Copenhagen) Weekend Avisen 20 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 21 | dutch.pickle Dutch Multilingual Corpus 1 (ECI) De Limburger ~340,000 Jan Strunk / Tibor Kiss 22 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 23 | english.pickle English Penn Treebank (LDC) Wall Street Journal ~469,000 Jan Strunk / Tibor Kiss 24 | (American) 25 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 26 | estonian.pickle Estonian University of Tartu, Estonia Eesti Ekspress ~359,000 Jan Strunk / Tibor Kiss 27 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 28 | finnish.pickle Finnish Finnish Parole Corpus, Finnish Books and major national ~364,000 Jan Strunk / Tibor Kiss 29 | Text Bank (Suomen Kielen newspapers 30 | Tekstipankki) 31 | Finnish Center for IT Science 32 | (CSC) 33 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 34 | french.pickle French Multilingual Corpus 1 (ECI) Le Monde ~370,000 Jan Strunk / Tibor Kiss 35 | (European) 36 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 37 | german.pickle German Neue Zürcher Zeitung AG Neue Zürcher Zeitung ~847,000 Jan Strunk / Tibor Kiss 38 | (Switzerland) CD-ROM 39 | (Uses "ss" 40 | instead of "ß") 41 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 42 | greek.pickle Greek Efstathios Stamatatos To Vima (TO BHMA) ~227,000 Jan Strunk / Tibor Kiss 43 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 44 | italian.pickle Italian Multilingual Corpus 1 (ECI) La Stampa, Il Mattino ~312,000 Jan Strunk / Tibor Kiss 45 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 46 | norwegian.pickle Norwegian Centre for Humanities Bergens Tidende ~479,000 Jan Strunk / Tibor Kiss 47 | (Bokmål and Information Technologies, 48 | Nynorsk) Bergen 49 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 50 | polish.pickle Polish Polish National Corpus Literature, newspapers, etc. ~1,000,000 Krzysztof Langner 51 | (http://www.nkjp.pl/) 52 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 53 | portuguese.pickle Portuguese CETENFolha Corpus Folha de São Paulo ~321,000 Jan Strunk / Tibor Kiss 54 | (Brazilian) (Linguateca) 55 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 56 | slovene.pickle Slovene TRACTOR Delo ~354,000 Jan Strunk / Tibor Kiss 57 | Slovene Academy for Arts 58 | and Sciences 59 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 60 | spanish.pickle Spanish Multilingual Corpus 1 (ECI) Sur ~353,000 Jan Strunk / Tibor Kiss 61 | (European) 62 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 63 | swedish.pickle Swedish Multilingual Corpus 1 (ECI) Dagens Nyheter ~339,000 Jan Strunk / Tibor Kiss 64 | (and some other texts) 65 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 66 | turkish.pickle Turkish METU Turkish Corpus Milliyet ~333,000 Jan Strunk / Tibor Kiss 67 | (Türkçe Derlem Projesi) 68 | University of Ankara 69 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- 70 | 71 | The corpora contained about 400,000 tokens on average and mostly consisted of newspaper text converted to 72 | Unicode using the codecs module. 73 | 74 | Kiss, Tibor and Strunk, Jan (2006): Unsupervised Multilingual Sentence Boundary Detection. 75 | Computational Linguistics 32: 485-525. 76 | 77 | ---- Training Code ---- 78 | 79 | # import punkt 80 | import nltk.tokenize.punkt 81 | 82 | # Make a new Tokenizer 83 | tokenizer = nltk.tokenize.punkt.PunktSentenceTokenizer() 84 | 85 | # Read in training corpus (one example: Slovene) 86 | import codecs 87 | text = codecs.open("slovene.plain","Ur","iso-8859-2").read() 88 | 89 | # Train tokenizer 90 | tokenizer.train(text) 91 | 92 | # Dump pickled tokenizer 93 | import pickle 94 | out = open("slovene.pickle","wb") 95 | pickle.dump(tokenizer, out) 96 | out.close() 97 | 98 | --------- 99 | -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/czech.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/czech.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/danish.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/danish.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/dutch.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/dutch.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/estonian.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/estonian.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/finnish.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/finnish.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/french.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/french.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/german.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/german.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/italian.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/italian.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/malayalam.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/malayalam.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/norwegian.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/norwegian.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/polish.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/polish.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/portuguese.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/portuguese.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/russian.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/russian.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/slovene.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/slovene.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/spanish.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/spanish.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/swedish.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/swedish.pickle -------------------------------------------------------------------------------- /nltk_data/tokenizers/punkt/turkish.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/X-D-Lab/LangChain-ChatGLM-Webui/7996cd5f621dfc7a51a6de871b38bae87f41bb71/nltk_data/tokenizers/punkt/turkish.pickle -------------------------------------------------------------------------------- /paddlepaddle/README.md: -------------------------------------------------------------------------------- 1 | # LangChain-ChatGLM-Paddle 2 | 3 | LangChain-ChatGLM的Paddle版本依赖 `PaddlePaddle` 和 `PaddleNLP` 的develop版本 4 | 5 | 在AIStudio上可以一键运行:[链接](https://aistudio.baidu.com/aistudio/projectdetail/6195067) 6 | -------------------------------------------------------------------------------- /paddlepaddle/app.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import gradio as gr 4 | import nltk 5 | from langchain.chains import RetrievalQA 6 | from langchain.document_loaders import UnstructuredFileLoader 7 | from langchain.prompts import PromptTemplate 8 | from langchain.prompts.prompt import PromptTemplate 9 | from langchain.vectorstores import FAISS 10 | from paddle_embedding import PaddleNLPEmbeddings 11 | 12 | from chatllm import ChatLLM 13 | 14 | nltk.data.path.append('../nltk_data') 15 | llm_model_dict = { 16 | 'ChatGLM-6B': 'THUDM/chatglm-6b' 17 | } 18 | 19 | embedding_model_dict = { 20 | "rocketqa-zh-base-query": "rocketqa-zh-base-query-encoder", 21 | "rocketqa-zh-dureader": "rocketqa-zh-dureader-query-encoder", 22 | "rocketqa-zh-dureader-query": "rocketqa-zh-dureader-query-encoder", 23 | "rocketqa-zh-medium-query": "rocketqa-zh-medium-query-encoder", 24 | "rocketqa-zh-medium-para": "rocketqa-zh-medium-para-encoder" 25 | 26 | } 27 | 28 | 29 | def init_knowledge_vector_store(embedding_model, filepath): 30 | 31 | embeddings = PaddleNLPEmbeddings( 32 | model = embedding_model_dict[embedding_model]) 33 | 34 | 35 | loader = UnstructuredFileLoader(filepath, mode="elements") 36 | docs = loader.load() 37 | 38 | vector_store = FAISS.from_documents(docs, embeddings) 39 | 40 | return vector_store 41 | 42 | 43 | def get_knowledge_based_answer(query, 44 | large_language_model, 45 | vector_store, 46 | VECTOR_SEARCH_TOP_K, 47 | chat_history=[]): 48 | 49 | 50 | prompt_template = """基于以下已知信息,请简洁并专业地回答用户的问题。 51 | 如果无法从中得到答案,请说 "根据已知信息无法回答该问题" 或 "没有提供足够的相关信息"。不允许在答案中添加编造成分。另外,答案请使用中文。 52 | 53 | 已知内容: 54 | {context} 55 | 56 | 问题: 57 | {question}""" 58 | prompt = PromptTemplate(template=prompt_template, 59 | input_variables=["context", "question"]) 60 | chatLLM = ChatLLM() 61 | 62 | knowledge_chain = RetrievalQA.from_llm( 63 | llm=chatLLM, 64 | retriever=vector_store.as_retriever( 65 | search_kwargs={"k": VECTOR_SEARCH_TOP_K}), 66 | prompt=prompt) 67 | knowledge_chain.combine_documents_chain.document_prompt = PromptTemplate( 68 | input_variables=["page_content"], template="{page_content}") 69 | 70 | knowledge_chain.return_source_documents = True 71 | 72 | result = knowledge_chain({"query": query}) 73 | print('result') 74 | print(result) 75 | return result 76 | 77 | 78 | def clear_session(): 79 | return '', None 80 | 81 | 82 | def predict(input: str, 83 | large_language_model: str, 84 | embedding_model: str, 85 | file_obj, 86 | VECTOR_SEARCH_TOP_K: int, 87 | history=None): 88 | if history == None: 89 | history = [] 90 | print(file_obj.name) 91 | vector_store = init_knowledge_vector_store(embedding_model, file_obj.name) 92 | 93 | resp = get_knowledge_based_answer( 94 | query=input, 95 | large_language_model=large_language_model, 96 | vector_store=vector_store, 97 | VECTOR_SEARCH_TOP_K=VECTOR_SEARCH_TOP_K, 98 | chat_history=history, 99 | ) 100 | print(resp['result']) 101 | history.append((input, resp['result'])) 102 | return '', history, history 103 | 104 | 105 | if __name__ == "__main__": 106 | block = gr.Blocks() 107 | with block as demo: 108 | gr.Markdown("""

LangChain-ChatLLM-Webui

109 |
110 | 本项目基于LangChain和大型语言模型系列模型, 提供基于本地知识的自动问答应用.
111 | 目前项目提供基于ChatGLM-6B 的LLM和包括rocketqa-zh系列的多个Embedding模型, 支持上传 txt、docx、md等文本格式文件.
112 | 后续将提供更加多样化的LLM、Embedding和参数选项供用户尝试, 欢迎关注Github地址.
113 |
114 | """) 115 | with gr.Row(): 116 | with gr.Column(scale=1): 117 | model_choose = gr.Accordion("模型选择") 118 | with model_choose: 119 | large_language_model = gr.Dropdown( 120 | list(llm_model_dict.keys()), 121 | label="large language model", 122 | value="ChatGLM-6B") 123 | embedding_model = gr.Dropdown(list( 124 | embedding_model_dict.keys()), 125 | label="Embedding model", 126 | value="rocketqa-zh-dureader-query") 127 | 128 | VECTOR_SEARCH_TOP_K = gr.Slider( 129 | 1, 130 | 10, 131 | value=6, 132 | step=1, 133 | label="vector search top k", 134 | interactive=True) 135 | file = gr.File(label='请上传知识库文件, 目前支持txt、docx、md格式', 136 | file_types=['.txt', '.md', '.docx']) 137 | 138 | with gr.Column(scale=4): 139 | chatbot = gr.Chatbot(label='ChatLLM') 140 | message = gr.Textbox(label='请输入问题') 141 | state = gr.State() 142 | 143 | with gr.Row(): 144 | clear_history = gr.Button("🧹 清除历史对话") 145 | send = gr.Button("🚀 发送") 146 | 147 | send.click(predict, 148 | inputs=[ 149 | message, large_language_model, 150 | embedding_model, file, VECTOR_SEARCH_TOP_K, 151 | state 152 | ], 153 | outputs=[message, chatbot, state]) 154 | clear_history.click(fn=clear_session, 155 | inputs=[], 156 | outputs=[chatbot, state], 157 | queue=False) 158 | 159 | message.submit(predict, 160 | inputs=[ 161 | message, large_language_model, 162 | embedding_model, file, 163 | VECTOR_SEARCH_TOP_K, state 164 | ], 165 | outputs=[message, chatbot, state]) 166 | gr.Markdown("""提醒:
167 | 1. 使用时请先上传自己的知识文件,并且文件中不含某些特殊字符,否则将返回error.
168 | 2. 有任何使用问题,请通过[问题交流区](https://huggingface.co/spaces/thomas-yanxin/LangChain-ChatLLM/discussions)或[Github Issue区](https://github.com/thomas-yanxin/LangChain-ChatGLM-Webui/issues)进行反馈.
169 | """) 170 | demo.queue().launch(server_name='0.0.0.0', share=True) 171 | -------------------------------------------------------------------------------- /paddlepaddle/chatllm.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | from typing import Dict, List, Optional, Tuple, Union 4 | 5 | from langchain.llms.base import LLM 6 | from langchain.llms.utils import enforce_stop_tokens 7 | from paddlenlp import Taskflow 8 | 9 | chatbot = Taskflow("text2text_generation", batch_size=2) 10 | 11 | 12 | class ChatLLM(LLM): 13 | max_token: int = 10000 14 | temperature: float = 0.1 15 | top_p = 0.9 16 | history = [] 17 | tokenizer: object = None 18 | model: object = None 19 | 20 | def __init__(self): 21 | super().__init__() 22 | 23 | @property 24 | def _llm_type(self) -> str: 25 | return "ChatLLM" 26 | 27 | def _call(self, 28 | prompt: str, 29 | stop: Optional[List[str]] = None) -> str: 30 | prompt_list = [] 31 | prompt_list.append(prompt) 32 | results = chatbot(prompt_list) 33 | response = results['result'][0] 34 | if stop is not None: 35 | response = enforce_stop_tokens(response, stop) 36 | return response -------------------------------------------------------------------------------- /paddlepaddle/cli.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import gradio as gr 4 | import nltk 5 | from langchain.chains import RetrievalQA 6 | from langchain.document_loaders import UnstructuredFileLoader 7 | from langchain.prompts import PromptTemplate 8 | from langchain.prompts.prompt import PromptTemplate 9 | from langchain.vectorstores import FAISS 10 | from paddle_embedding import PaddleNLPEmbeddings 11 | 12 | from chatllm import ChatLLM 13 | 14 | nltk.data.path.append('../nltk_data') 15 | llm_model_dict = {'ChatGLM-6B': 'THUDM/chatglm-6b'} 16 | 17 | embedding_model_dict = { 18 | "rocketqa-zh-base-query": "rocketqa-zh-base-query-encoder", 19 | "rocketqa-zh-dureader": "rocketqa-zh-dureader-query-encoder", 20 | "rocketqa-zh-dureader-query": "rocketqa-zh-dureader-query-encoder", 21 | "rocketqa-zh-medium-query": "rocketqa-zh-medium-query-encoder", 22 | "rocketqa-zh-medium-para": "rocketqa-zh-medium-para-encoder" 23 | } 24 | 25 | 26 | def init_knowledge_vector_store(embedding_model, filepath): 27 | 28 | embeddings = PaddleNLPEmbeddings( 29 | model=embedding_model_dict[embedding_model]) 30 | 31 | loader = UnstructuredFileLoader(filepath, mode="elements") 32 | docs = loader.load() 33 | 34 | vector_store = FAISS.from_documents(docs, embeddings) 35 | 36 | return vector_store 37 | 38 | 39 | def get_knowledge_based_answer(query, 40 | large_language_model, 41 | vector_store, 42 | VECTOR_SEARCH_TOP_K, 43 | chat_history=[]): 44 | 45 | prompt_template = """基于以下已知信息,请简洁并专业地回答用户的问题。 46 | 如果无法从中得到答案,请说 "根据已知信息无法回答该问题" 或 "没有提供足够的相关信息"。不允许在答案中添加编造成分。另外,答案请使用中文。 47 | 48 | 已知内容: 49 | {context} 50 | 51 | 问题: 52 | {question}""" 53 | prompt = PromptTemplate(template=prompt_template, 54 | input_variables=["context", "question"]) 55 | chatLLM = ChatLLM() 56 | 57 | knowledge_chain = RetrievalQA.from_llm( 58 | llm=chatLLM, 59 | retriever=vector_store.as_retriever( 60 | search_kwargs={"k": VECTOR_SEARCH_TOP_K}), 61 | prompt=prompt) 62 | knowledge_chain.combine_documents_chain.document_prompt = PromptTemplate( 63 | input_variables=["page_content"], template="{page_content}") 64 | 65 | knowledge_chain.return_source_documents = True 66 | 67 | result = knowledge_chain({"query": query}) 68 | 69 | return result['result'] 70 | 71 | 72 | def clear_session(): 73 | return '', None 74 | 75 | 76 | def predict(input: str, 77 | large_language_model: str, 78 | embedding_model: str, 79 | file_obj, 80 | VECTOR_SEARCH_TOP_K: int, 81 | history=None): 82 | if history == None: 83 | history = [] 84 | 85 | vector_store = init_knowledge_vector_store(embedding_model, file_obj.name) 86 | 87 | resp = get_knowledge_based_answer( 88 | query=input, 89 | large_language_model=large_language_model, 90 | vector_store=vector_store, 91 | VECTOR_SEARCH_TOP_K=VECTOR_SEARCH_TOP_K, 92 | chat_history=history, 93 | ) 94 | 95 | history.append((input, resp['result'])) 96 | return '', history, history 97 | 98 | 99 | if __name__ == "__main__": 100 | 101 | vector_store = init_knowledge_vector_store( 102 | 'rocketqa-zh-dureader', '/home/aistudio/docs/README-ChatGLM.md') 103 | 104 | # for i, (old_query, response) in enumerate(history): 105 | # prompt += "[Round {}]\n问:{}\n答:{}\n".format(i, old_query, response) 106 | # prompt += "[Round {}]\n问:{}\n答:".format(len(history), query) 107 | 108 | while True: 109 | query = input('提问: ') 110 | resp = get_knowledge_based_answer(query=query, 111 | large_language_model='ChatGLM-6B', 112 | vector_store=vector_store, 113 | VECTOR_SEARCH_TOP_K=10, 114 | chat_history=[]) 115 | 116 | print("回答: " + resp) 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /paddlepaddle/paddle_embedding.py: -------------------------------------------------------------------------------- 1 | """Wrapper around PaddleNLP embedding models.""" 2 | from typing import Any, List 3 | 4 | from langchain.embeddings.base import Embeddings 5 | from pydantic import BaseModel, Extra 6 | 7 | 8 | class PaddleNLPEmbeddings(BaseModel, Embeddings): 9 | """Wrapper around paddlenlp embedding models. 10 | 11 | To use, you should have the ``modelscope`` python package installed. 12 | 13 | Example: 14 | .. code-block:: python 15 | 16 | from langchain.embeddings import PaddleNLPEmbeddings 17 | model = "rocketqa-zh-base-query-encoder" 18 | embed = PaddleNLPEmbeddings(model=model) 19 | """ 20 | 21 | text_encoder: Any 22 | model: str ='rocketqa-zh-base-query-encoder' 23 | 24 | """Model name to use.""" 25 | 26 | def __init__(self, **kwargs: Any): 27 | """Initialize the modelscope""" 28 | super().__init__(**kwargs) 29 | try: 30 | import paddle.nn.functional as F 31 | from paddlenlp import Taskflow 32 | 33 | self.text_encoder = Taskflow("feature_extraction", model=self.model) 34 | 35 | 36 | except ImportError as e: 37 | raise ValueError( 38 | "Could not import some python packages." "Please install it with `pip install modelscope`." 39 | ) from e 40 | 41 | class Config: 42 | """Configuration for this pydantic object.""" 43 | 44 | extra = Extra.forbid 45 | 46 | def embed_documents(self, texts: List[str]) -> List[List[float]]: 47 | """Compute doc embeddings using a modelscope embedding model. 48 | 49 | Args: 50 | texts: The list of texts to embed. 51 | 52 | Returns: 53 | List of embeddings, one for each text. 54 | """ 55 | texts = list(map(lambda x: x.replace("\n", " "), texts)) 56 | text_embeds = self.text_encoder(texts) 57 | embeddings = text_embeds["features"].numpy() 58 | 59 | return embeddings.tolist() 60 | 61 | def embed_query(self, text: str) -> List[float]: 62 | """Compute query embeddings using a modelscope embedding model. 63 | 64 | Args: 65 | text: The text to embed. 66 | 67 | Returns: 68 | Embeddings for the text. 69 | """ 70 | text = text.replace("\n", " ") 71 | text_embeds = self.text_encoder(text) 72 | embedding = text_embeds["features"].numpy()[0] 73 | 74 | return embedding.tolist() -------------------------------------------------------------------------------- /paddlepaddle/requirements.txt: -------------------------------------------------------------------------------- 1 | langchain==0.0.147 2 | unstructured[local-inference] 3 | layoutparser[layoutmodels,tesseract] 4 | nltk 5 | beautifulsoup4 6 | icetk 7 | cpm_kernels 8 | faiss-cpu 9 | protobuf==3.19.0 10 | -------------------------------------------------------------------------------- /poetry.toml: -------------------------------------------------------------------------------- 1 | [virtualenvs] 2 | in-project = true 3 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "langchain-chatglm-webui" 3 | version = "0.1.0" 4 | description = "基于LangChain和ChatGLM-6B等系列LLM的针对本地知识库的自动问答" 5 | authors = ["thomas-yanxin "] 6 | license = "Apache-2.0" 7 | readme = "README.md" 8 | repository = "https://github.com/thomas-yanxin/LangChain-ChatGLM-Webui" 9 | 10 | [tool.poetry.dependencies] 11 | python = ">=3.9,<4.0" 12 | langchain = "0.0.147" 13 | fschat = "0.2.3" 14 | accelerate = "*" 15 | qdrant-client = "*" 16 | duckduckgo_search = "*" 17 | transformers = ">=4.28.0" 18 | tokenizers = "*" 19 | nltk = "*" 20 | sentence-transformers = "*" 21 | beautifulsoup4 = "*" 22 | icetk = "*" 23 | cpm_kernels = "*" 24 | faiss-cpu = "*" 25 | # TODO: uncomment next line when detectron2 support PEP517 and poetry. 26 | # detectron2 = { git = "https://github.com/facebookresearch/detectron2.git", tag = "v0.6" } 27 | wandb = "0.13.0" 28 | jina = ">=3.15.2" 29 | langchain-serve = ">=0.0.24" 30 | protobuf = "3.19.0" 31 | 32 | [tool.poetry.extras] 33 | unstructured = ["local-inference"] 34 | layoutparser = ["layoutmodels", "tesseract"] 35 | 36 | 37 | [build-system] 38 | requires = ["poetry-core"] 39 | build-backend = "poetry.core.masonry.api" 40 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | langchain==0.1.0 2 | fschat==0.2.3 3 | accelerate 4 | qdrant-client # API版本需要 5 | duckduckgo_search==2.9.5 6 | transformers>=4.32.0 7 | tokenizers 8 | unstructured[local-inference] 9 | layoutparser[layoutmodels,tesseract] 10 | nltk 11 | sentence-transformers==2.3.1 12 | beautifulsoup4 13 | icetk 14 | cpm_kernels 15 | faiss-cpu 16 | detectron2@git+https://github.com/facebookresearch/detectron2.git@v0.6#egg=detectron2 # PDF需要 17 | wandb==0.16.2 18 | jina # API版本需要 19 | langchain-serve # API版本需要 20 | protobuf==4.25.2 21 | langchain-community 22 | einops 23 | --------------------------------------------------------------------------------