Spaces:
Runtime error
Runtime error
| import os | |
| import gradio as gr | |
| import nltk | |
| import sentence_transformers | |
| import torch | |
| from duckduckgo_search import ddg | |
| from duckduckgo_search.utils import SESSION | |
| from langchain.chains import RetrievalQA | |
| from langchain.document_loaders import UnstructuredFileLoader | |
| from langchain.embeddings import JinaEmbeddings | |
| from langchain.embeddings.huggingface import HuggingFaceEmbeddings | |
| from langchain.prompts import PromptTemplate | |
| from langchain.prompts.prompt import PromptTemplate | |
| from langchain.vectorstores import FAISS | |
| from chatllm import ChatLLM | |
| from chinese_text_splitter import ChineseTextSplitter | |
| nltk.data.path.append('./nltk_data') | |
| embedding_model_dict = { | |
| "ernie-tiny": "nghuyong/ernie-3.0-nano-zh", | |
| "ernie-base": "nghuyong/ernie-3.0-base-zh", | |
| "text2vec-base": "GanymedeNil/text2vec-base-chinese", | |
| #"ViT-B-32": 'ViT-B-32::laion2b-s34b-b79k' | |
| } | |
| llm_model_dict = { | |
| "ChatGLM-6B-int8": "THUDM/chatglm-6b-int8", | |
| "ChatGLM-6B-int4": "THUDM/chatglm-6b-int4", | |
| "ChatGLM-6b-int4-qe": "THUDM/chatglm-6b-int4-qe", | |
| #"Minimax": "Minimax" | |
| } | |
| DEVICE = "cuda" if torch.cuda.is_available( | |
| ) else "mps" if torch.backends.mps.is_available() else "cpu" | |
| def search_web(query): | |
| SESSION.proxies = { | |
| "http": f"socks5h://localhost:7890", | |
| "https": f"socks5h://localhost:7890" | |
| } | |
| results = ddg(query) | |
| web_content = '' | |
| if results: | |
| for result in results: | |
| web_content += result['body'] | |
| return web_content | |
| def load_file(filepath): | |
| if filepath.lower().endswith(".pdf"): | |
| loader = UnstructuredFileLoader(filepath) | |
| textsplitter = ChineseTextSplitter(pdf=True) | |
| docs = loader.load_and_split(textsplitter) | |
| else: | |
| loader = UnstructuredFileLoader(filepath, mode="elements") | |
| textsplitter = ChineseTextSplitter(pdf=False) | |
| docs = loader.load_and_split(text_splitter=textsplitter) | |
| return docs | |
| def init_knowledge_vector_store(embedding_model, filepath): | |
| if embedding_model == "ViT-B-32": | |
| jina_auth_token = os.getenv('jina_auth_token') | |
| embeddings = JinaEmbeddings( | |
| jina_auth_token=jina_auth_token, | |
| model_name=embedding_model_dict[embedding_model]) | |
| else: | |
| embeddings = HuggingFaceEmbeddings( | |
| model_name=embedding_model_dict[embedding_model], ) | |
| embeddings.client = sentence_transformers.SentenceTransformer( | |
| embeddings.model_name, device=DEVICE) | |
| docs = load_file(filepath) | |
| vector_store = FAISS.from_documents(docs, embeddings) | |
| return vector_store | |
| def get_knowledge_based_answer(query, | |
| large_language_model, | |
| vector_store, | |
| VECTOR_SEARCH_TOP_K, | |
| web_content, | |
| history_len, | |
| temperature, | |
| top_p, | |
| chat_history=[]): | |
| if web_content: | |
| prompt_template = f"""基于以下已知信息,简洁和专业的来回答用户的问题。 | |
| 如果无法从中得到答案,请说 "根据已知信息无法回答该问题" 或 "没有提供足够的相关信息",不允许在答案中添加编造成分,答案请使用中文。 | |
| 已知网络检索内容:{web_content}""" + """ | |
| 已知内容: | |
| {context} | |
| 问题: | |
| {question}""" | |
| else: | |
| prompt_template = """基于以下已知信息,请简洁并专业地回答用户的问题。 | |
| 如果无法从中得到答案,请说 "根据已知信息无法回答该问题" 或 "没有提供足够的相关信息"。不允许在答案中添加编造成分。另外,答案请使用中文。 | |
| 已知内容: | |
| {context} | |
| 问题: | |
| {question}""" | |
| prompt = PromptTemplate(template=prompt_template, | |
| input_variables=["context", "question"]) | |
| chatLLM = ChatLLM() | |
| chatLLM.history = chat_history[-history_len:] if history_len > 0 else [] | |
| if large_language_model == "Minimax": | |
| chatLLM.model = 'Minimax' | |
| else: | |
| chatLLM.load_model( | |
| model_name_or_path=llm_model_dict[large_language_model]) | |
| chatLLM.temperature = temperature | |
| chatLLM.top_p = top_p | |
| knowledge_chain = RetrievalQA.from_llm( | |
| llm=chatLLM, | |
| retriever=vector_store.as_retriever( | |
| search_kwargs={"k": VECTOR_SEARCH_TOP_K}), | |
| prompt=prompt) | |
| knowledge_chain.combine_documents_chain.document_prompt = PromptTemplate( | |
| input_variables=["page_content"], template="{page_content}") | |
| knowledge_chain.return_source_documents = True | |
| result = knowledge_chain({"query": query}) | |
| return result | |
| def clear_session(): | |
| return '', None | |
| def predict(input, | |
| large_language_model, | |
| embedding_model, | |
| file_obj, | |
| VECTOR_SEARCH_TOP_K, | |
| history_len, | |
| temperature, | |
| top_p, | |
| use_web, | |
| history=None): | |
| if history == None: | |
| history = [] | |
| print(file_obj.name) | |
| vector_store = init_knowledge_vector_store(embedding_model, file_obj.name) | |
| if use_web == 'True': | |
| web_content = search_web(query=input) | |
| else: | |
| web_content = '' | |
| resp = get_knowledge_based_answer( | |
| query=input, | |
| large_language_model=large_language_model, | |
| vector_store=vector_store, | |
| VECTOR_SEARCH_TOP_K=VECTOR_SEARCH_TOP_K, | |
| web_content=web_content, | |
| chat_history=history, | |
| history_len=history_len, | |
| temperature=temperature, | |
| top_p=top_p, | |
| ) | |
| print(resp) | |
| history.append((input, resp['result'])) | |
| return '', history, history | |
| if __name__ == "__main__": | |
| block = gr.Blocks() | |
| with block as demo: | |
| gr.Markdown("""<h1><center>LangChain-ChatLLM-Webui</center></h1> | |
| <center><font size=3> | |
| 本项目基于LangChain和大型语言模型系列模型, 提供基于本地知识的自动问答应用. <br> | |
| 目前项目提供基于<a href='https://github.com/THUDM/ChatGLM-6B' target="_blank">ChatGLM-6B </a>系列、Minimax的LLM和包括text2vec-base-chinese、ernie-3.0-zh系列以及由<a href='https://cloud.jina.ai/user/inference' target="_blank">Jina</a>提供的ViT-B-32::laion2b-s34b-b79k等多个Embedding模型, 支持上传 txt、docx、md等文本格式文件. <br> | |
| 后续将提供更加多样化的LLM、Embedding和参数选项供用户尝试, 欢迎关注<a href='https://github.com/thomas-yanxin/LangChain-ChatGLM-Webui' target="_blank">Github地址</a>. <br> | |
| 本项目已内置开发者自己的key,用户无需输入自己的相关key. <br> | |
| 当然,更推荐您点击右上角的<strong>Duplicate this Space</strong>,将项目Fork到自己的Space中,保护个人隐私,且避免排队! | |
| </center></font> | |
| """) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| model_choose = gr.Accordion("模型选择") | |
| with model_choose: | |
| large_language_model = gr.Dropdown( | |
| list(llm_model_dict.keys()), | |
| label="large language model", | |
| value="ChatGLM-6B-int4") | |
| embedding_model = gr.Dropdown(list( | |
| embedding_model_dict.keys()), | |
| label="Embedding model", | |
| value="text2vec-base") | |
| file = gr.File(label='请上传知识库文件, 目前支持txt、docx、md格式', | |
| file_types=['.txt', '.md', '.docx']) | |
| use_web = gr.Radio(["True", "False"], | |
| label="Web Search", | |
| value="False") | |
| model_argument = gr.Accordion("模型参数配置") | |
| with model_argument: | |
| VECTOR_SEARCH_TOP_K = gr.Slider( | |
| 1, | |
| 10, | |
| value=6, | |
| step=1, | |
| label="vector search top k", | |
| interactive=True) | |
| HISTORY_LEN = gr.Slider(0, | |
| 3, | |
| value=0, | |
| step=1, | |
| label="history len", | |
| interactive=True) | |
| temperature = gr.Slider(0, | |
| 1, | |
| value=0.01, | |
| step=0.01, | |
| label="temperature", | |
| interactive=True) | |
| top_p = gr.Slider(0, | |
| 1, | |
| value=0.9, | |
| step=0.1, | |
| label="top_p", | |
| interactive=True) | |
| with gr.Column(scale=4): | |
| chatbot = gr.Chatbot(label='ChatLLM').style(height=600) | |
| message = gr.Textbox(label='请输入问题') | |
| state = gr.State() | |
| with gr.Row(): | |
| clear_history = gr.Button("🧹 清除历史对话") | |
| send = gr.Button("🚀 发送") | |
| send.click(predict, | |
| inputs=[ | |
| message, large_language_model, | |
| embedding_model, file, VECTOR_SEARCH_TOP_K, | |
| HISTORY_LEN, temperature, top_p, use_web, | |
| state | |
| ], | |
| outputs=[message, chatbot, state]) | |
| clear_history.click(fn=clear_session, | |
| inputs=[], | |
| outputs=[chatbot, state], | |
| queue=False) | |
| message.submit(predict, | |
| inputs=[ | |
| message, large_language_model, | |
| embedding_model, file, | |
| VECTOR_SEARCH_TOP_K, HISTORY_LEN, | |
| temperature, top_p, use_web, state | |
| ], | |
| outputs=[message, chatbot, state]) | |
| gr.Markdown("""提醒:<br> | |
| 1. 使用时请先上传自己的知识文件,并且文件中不含某些特殊字符,否则将返回error. <br> | |
| 2. 有任何使用问题,请通过[问题交流区](https://huggingface.co/spaces/thomas-yanxin/LangChain-ChatLLM/discussions)或[Github Issue区](https://github.com/thomas-yanxin/LangChain-ChatGLM-Webui/issues)进行反馈. <br> | |
| """) | |
| demo.queue().launch(server_name='0.0.0.0', share=False) | |