Spaces:
Runtime error
Runtime error
quincyqiang
commited on
Commit
·
a10fbed
1
Parent(s):
4d7c081
feature@添加知识库选择功能
Browse files- README.md +9 -1
- clc/langchain_application.py +11 -2
- clc/source_service.py +6 -2
- create_knowledge.py +23 -11
- main.py +30 -4
- tests/test_langchain.py +0 -1
- tests/test_vector_store.py +11 -0
README.md
CHANGED
@@ -7,13 +7,20 @@
|
|
7 |
![](https://github.com/yanqiangmiffy/Chinese-LangChain/blob/master/images/web_demo.png)
|
8 |
|
9 |
## 🚀 特性
|
|
|
10 |
- 🚀 2023/04/18 webui增加知识库选择功能
|
11 |
- 🚀 2023/04/18 修复推理预测超时5s报错问题
|
12 |
-
- 🎉 2023/04/17
|
13 |
- 🎉 2023/04/17 支持知识增量更新
|
14 |
|
15 |
[//]: # (- 支持检索结果与LLM生成结果对比)
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
## 🔨 TODO
|
18 |
|
19 |
* [x] 支持上下文
|
@@ -26,6 +33,7 @@
|
|
26 |
* [ ] 增加非LangChain策略
|
27 |
|
28 |
## 交流
|
|
|
29 |
欢迎多提建议、Bad cases,目前尚不完善,欢迎进群及时交流,也欢迎大家多提PR
|
30 |
<img src="https://raw.githubusercontent.com/yanqiangmiffy/Chinese-LangChain/master/images/ch.jpg" width="300px">
|
31 |
<img src="https://raw.githubusercontent.com/yanqiangmiffy/Chinese-LangChain/master/images/chatgroup.jpg" width="300px">
|
|
|
7 |
![](https://github.com/yanqiangmiffy/Chinese-LangChain/blob/master/images/web_demo.png)
|
8 |
|
9 |
## 🚀 特性
|
10 |
+
|
11 |
- 🚀 2023/04/18 webui增加知识库选择功能
|
12 |
- 🚀 2023/04/18 修复推理预测超时5s报错问题
|
13 |
+
- 🎉 2023/04/17 支持多种文档上传与内容解析:pdf、docx,ppt等
|
14 |
- 🎉 2023/04/17 支持知识增量更新
|
15 |
|
16 |
[//]: # (- 支持检索结果与LLM生成结果对比)
|
17 |
|
18 |
+
## 🧰 知识库
|
19 |
+
|
20 |
+
| 知识库数据 |FAISS向量|
|
21 |
+
|--------|----|
|
22 |
+
|💹 [大规模金融研报知识图谱](http://openkg.cn/dataset/fr2kg)|链接:https://pan.baidu.com/s/1FcIH5Fi3EfpS346DnDu51Q?pwd=ujjv 提取码:ujjv |
|
23 |
+
|
24 |
## 🔨 TODO
|
25 |
|
26 |
* [x] 支持上下文
|
|
|
33 |
* [ ] 增加非LangChain策略
|
34 |
|
35 |
## 交流
|
36 |
+
|
37 |
欢迎多提建议、Bad cases,目前尚不完善,欢迎进群及时交流,也欢迎大家多提PR
|
38 |
<img src="https://raw.githubusercontent.com/yanqiangmiffy/Chinese-LangChain/master/images/ch.jpg" width="300px">
|
39 |
<img src="https://raw.githubusercontent.com/yanqiangmiffy/Chinese-LangChain/master/images/chatgroup.jpg" width="300px">
|
clc/langchain_application.py
CHANGED
@@ -12,6 +12,7 @@
|
|
12 |
|
13 |
from langchain.chains import RetrievalQA
|
14 |
from langchain.prompts.prompt import PromptTemplate
|
|
|
15 |
from clc.gpt_service import ChatGLMService
|
16 |
from clc.source_service import SourceService
|
17 |
|
@@ -22,7 +23,15 @@ class LangChainApplication(object):
|
|
22 |
self.llm_service = ChatGLMService()
|
23 |
self.llm_service.load_model(model_name_or_path=self.config.llm_model_name)
|
24 |
self.source_service = SourceService(config)
|
25 |
-
self.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
|
27 |
def get_knowledge_based_answer(self, query,
|
28 |
history_len=5,
|
@@ -45,7 +54,7 @@ class LangChainApplication(object):
|
|
45 |
knowledge_chain = RetrievalQA.from_llm(
|
46 |
llm=self.llm_service,
|
47 |
retriever=self.source_service.vector_store.as_retriever(
|
48 |
-
search_kwargs={"k":
|
49 |
prompt=prompt)
|
50 |
knowledge_chain.combine_documents_chain.document_prompt = PromptTemplate(
|
51 |
input_variables=["page_content"], template="{page_content}")
|
|
|
12 |
|
13 |
from langchain.chains import RetrievalQA
|
14 |
from langchain.prompts.prompt import PromptTemplate
|
15 |
+
|
16 |
from clc.gpt_service import ChatGLMService
|
17 |
from clc.source_service import SourceService
|
18 |
|
|
|
23 |
self.llm_service = ChatGLMService()
|
24 |
self.llm_service.load_model(model_name_or_path=self.config.llm_model_name)
|
25 |
self.source_service = SourceService(config)
|
26 |
+
if self.config.kg_vector_stores is None:
|
27 |
+
print("init a source vector store")
|
28 |
+
self.source_service.init_source_vector()
|
29 |
+
else:
|
30 |
+
print("load zh_wikipedia source vector store ")
|
31 |
+
try:
|
32 |
+
self.source_service.load_vector_store(self.config.kg_vector_stores['初始化知识库'])
|
33 |
+
except Exception as e:
|
34 |
+
self.source_service.init_source_vector()
|
35 |
|
36 |
def get_knowledge_based_answer(self, query,
|
37 |
history_len=5,
|
|
|
54 |
knowledge_chain = RetrievalQA.from_llm(
|
55 |
llm=self.llm_service,
|
56 |
retriever=self.source_service.vector_store.as_retriever(
|
57 |
+
search_kwargs={"k": 4}),
|
58 |
prompt=prompt)
|
59 |
knowledge_chain.combine_documents_chain.document_prompt = PromptTemplate(
|
60 |
input_variables=["page_content"], template="{page_content}")
|
clc/source_service.py
CHANGED
@@ -19,6 +19,7 @@ from langchain.vectorstores import FAISS
|
|
19 |
|
20 |
class SourceService(object):
|
21 |
def __init__(self, config):
|
|
|
22 |
self.config = config
|
23 |
self.embeddings = HuggingFaceEmbeddings(model_name=self.config.embedding_model_name)
|
24 |
self.docs_path = self.config.docs_path
|
@@ -45,8 +46,11 @@ class SourceService(object):
|
|
45 |
self.vector_store.add_documents(doc)
|
46 |
self.vector_store.save_local(self.vector_store_path)
|
47 |
|
48 |
-
def load_vector_store(self):
|
49 |
-
|
|
|
|
|
|
|
50 |
return self.vector_store
|
51 |
|
52 |
# if __name__ == '__main__':
|
|
|
19 |
|
20 |
class SourceService(object):
|
21 |
def __init__(self, config):
|
22 |
+
self.vector_store = None
|
23 |
self.config = config
|
24 |
self.embeddings = HuggingFaceEmbeddings(model_name=self.config.embedding_model_name)
|
25 |
self.docs_path = self.config.docs_path
|
|
|
46 |
self.vector_store.add_documents(doc)
|
47 |
self.vector_store.save_local(self.vector_store_path)
|
48 |
|
49 |
+
def load_vector_store(self, path):
|
50 |
+
if path is None:
|
51 |
+
self.vector_store = FAISS.load_local(self.vector_store_path, self.embeddings)
|
52 |
+
else:
|
53 |
+
self.vector_store = FAISS.load_local(path, self.embeddings)
|
54 |
return self.vector_store
|
55 |
|
56 |
# if __name__ == '__main__':
|
create_knowledge.py
CHANGED
@@ -7,24 +7,36 @@
|
|
7 |
@time: 2023/04/18
|
8 |
@contact: [email protected]
|
9 |
@software: PyCharm
|
10 |
-
@description:
|
11 |
"""
|
12 |
-
|
|
|
|
|
13 |
from langchain.embeddings.huggingface import HuggingFaceEmbeddings
|
14 |
from langchain.vectorstores import FAISS
|
15 |
from tqdm import tqdm
|
16 |
-
|
17 |
# 中文Wikipedia数据导入示例:
|
18 |
-
embedding_model_name = '/
|
19 |
-
docs_path = '/
|
20 |
embeddings = HuggingFaceEmbeddings(model_name=embedding_model_name)
|
21 |
|
22 |
-
docs = []
|
23 |
|
24 |
-
with open('docs/zh_wikipedia/zhwiki.sim.utf8', 'r', encoding='utf-8') as f:
|
25 |
-
|
26 |
-
|
27 |
-
|
|
|
|
|
|
|
|
|
|
|
28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
vector_store = FAISS.from_documents(docs, embeddings)
|
30 |
-
vector_store.save_local('cache/
|
|
|
7 |
@time: 2023/04/18
|
8 |
@contact: [email protected]
|
9 |
@software: PyCharm
|
10 |
+
@description: - emoji:https://emojixd.com/pocket/science
|
11 |
"""
|
12 |
+
import os
|
13 |
+
|
14 |
+
from langchain.document_loaders import UnstructuredFileLoader
|
15 |
from langchain.embeddings.huggingface import HuggingFaceEmbeddings
|
16 |
from langchain.vectorstores import FAISS
|
17 |
from tqdm import tqdm
|
|
|
18 |
# 中文Wikipedia数据导入示例:
|
19 |
+
embedding_model_name = '/root/pretrained_models/text2vec-large-chinese'
|
20 |
+
docs_path = '/root/GoMall/Knowledge-ChatGLM/cache/financial_research_reports'
|
21 |
embeddings = HuggingFaceEmbeddings(model_name=embedding_model_name)
|
22 |
|
23 |
+
# docs = []
|
24 |
|
25 |
+
# with open('docs/zh_wikipedia/zhwiki.sim.utf8', 'r', encoding='utf-8') as f:
|
26 |
+
# for idx, line in tqdm(enumerate(f.readlines())):
|
27 |
+
# metadata = {"source": f'doc_id_{idx}'}
|
28 |
+
# docs.append(Document(page_content=line.strip(), metadata=metadata))
|
29 |
+
#
|
30 |
+
# vector_store = FAISS.from_documents(docs, embeddings)
|
31 |
+
# vector_store.save_local('cache/zh_wikipedia/')
|
32 |
+
|
33 |
+
docs = []
|
34 |
|
35 |
+
for doc in tqdm(os.listdir(docs_path)):
|
36 |
+
if doc.endswith('.txt'):
|
37 |
+
# print(doc)
|
38 |
+
loader = UnstructuredFileLoader(f'{docs_path}/{doc}', mode="elements")
|
39 |
+
doc = loader.load()
|
40 |
+
docs.extend(doc)
|
41 |
vector_store = FAISS.from_documents(docs, embeddings)
|
42 |
+
vector_store.save_local('cache/financial_research_reports')
|
main.py
CHANGED
@@ -14,6 +14,12 @@ class LangChainCFG:
|
|
14 |
embedding_model_name = '../../pretrained_models/text2vec-large-chinese' # 检索模型文件 or huggingface远程仓库
|
15 |
vector_store_path = './cache'
|
16 |
docs_path = './docs'
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
|
18 |
|
19 |
config = LangChainCFG()
|
@@ -40,6 +46,15 @@ def upload_file(file):
|
|
40 |
return gr.Dropdown.update(choices=file_list, value=filename)
|
41 |
|
42 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
def clear_session():
|
44 |
return '', None
|
45 |
|
@@ -61,8 +76,8 @@ def predict(input,
|
|
61 |
)
|
62 |
history.append((input, resp['result']))
|
63 |
search_text = ''
|
64 |
-
for idx, source in enumerate(resp['source_documents'][:
|
65 |
-
sep = f'----------【搜索结果{idx}:】---------------\n'
|
66 |
search_text += f'{sep}\n{source.page_content}\n\n'
|
67 |
print(search_text)
|
68 |
return '', history, history, search_text
|
@@ -97,10 +112,15 @@ with block as demo:
|
|
97 |
step=1,
|
98 |
label="向量匹配 top k",
|
99 |
interactive=True)
|
100 |
-
kg_name = gr.Radio(['中文维基百科',
|
|
|
|
|
|
|
101 |
label="知识库",
|
102 |
value='中文维基百科',
|
103 |
interactive=True)
|
|
|
|
|
104 |
file = gr.File(label="将文件上传到数据库",
|
105 |
visible=True,
|
106 |
file_types=['.txt', '.md', '.docx', '.pdf']
|
@@ -119,7 +139,12 @@ with block as demo:
|
|
119 |
send = gr.Button("🚀 发送")
|
120 |
with gr.Column(scale=2):
|
121 |
search = gr.Textbox(label='搜索结果')
|
122 |
-
|
|
|
|
|
|
|
|
|
|
|
123 |
# 发送按钮 提交
|
124 |
send.click(predict,
|
125 |
inputs=[
|
@@ -142,6 +167,7 @@ with block as demo:
|
|
142 |
],
|
143 |
outputs=[message, chatbot, state, search])
|
144 |
gr.Markdown("""提醒:<br>
|
|
|
145 |
有任何使用问题[Github Issue区](https://github.com/yanqiangmiffy/Chinese-LangChain)进行反馈. <br>
|
146 |
""")
|
147 |
demo.queue(concurrency_count=2).launch(
|
|
|
14 |
embedding_model_name = '../../pretrained_models/text2vec-large-chinese' # 检索模型文件 or huggingface远程仓库
|
15 |
vector_store_path = './cache'
|
16 |
docs_path = './docs'
|
17 |
+
kg_vector_stores = {
|
18 |
+
'中文维基百科': '/root/GoMall/Knowledge-ChatGLM/cache/zh_wikipedia',
|
19 |
+
'大规模金融研报知识图谱': '/root/GoMall/Knowledge-ChatGLM/cache/financial_research_reports',
|
20 |
+
'初始化知识库': '/root/GoMall/Knowledge-ChatGLM/cache',
|
21 |
+
} # 可以替换成自己的知识库,如果没有需要设置为None
|
22 |
+
# kg_vector_stores=None
|
23 |
|
24 |
|
25 |
config = LangChainCFG()
|
|
|
46 |
return gr.Dropdown.update(choices=file_list, value=filename)
|
47 |
|
48 |
|
49 |
+
def set_knowledge(kg_name, history):
|
50 |
+
try:
|
51 |
+
application.source_service.load_vector_store(config.kg_vector_stores[kg_name])
|
52 |
+
msg_status = f'{kg_name}知识库已成功加载'
|
53 |
+
except Exception as e:
|
54 |
+
msg_status = f'{kg_name}知识库未成功加载'
|
55 |
+
return history + [[None, msg_status]]
|
56 |
+
|
57 |
+
|
58 |
def clear_session():
|
59 |
return '', None
|
60 |
|
|
|
76 |
)
|
77 |
history.append((input, resp['result']))
|
78 |
search_text = ''
|
79 |
+
for idx, source in enumerate(resp['source_documents'][:4]):
|
80 |
+
sep = f'----------【搜索结果{idx+1}:】---------------\n'
|
81 |
search_text += f'{sep}\n{source.page_content}\n\n'
|
82 |
print(search_text)
|
83 |
return '', history, history, search_text
|
|
|
112 |
step=1,
|
113 |
label="向量匹配 top k",
|
114 |
interactive=True)
|
115 |
+
kg_name = gr.Radio(['中文维基百科',
|
116 |
+
'大规模金融研报知识图谱',
|
117 |
+
'初始化知识库'
|
118 |
+
],
|
119 |
label="知识库",
|
120 |
value='中文维基百科',
|
121 |
interactive=True)
|
122 |
+
set_kg_btn = gr.Button("重新加载知识库")
|
123 |
+
|
124 |
file = gr.File(label="将文件上传到数据库",
|
125 |
visible=True,
|
126 |
file_types=['.txt', '.md', '.docx', '.pdf']
|
|
|
139 |
send = gr.Button("🚀 发送")
|
140 |
with gr.Column(scale=2):
|
141 |
search = gr.Textbox(label='搜索结果')
|
142 |
+
set_kg_btn.click(
|
143 |
+
set_knowledge,
|
144 |
+
show_progress=True,
|
145 |
+
inputs=[kg_name, chatbot],
|
146 |
+
outputs=chatbot
|
147 |
+
)
|
148 |
# 发送按钮 提交
|
149 |
send.click(predict,
|
150 |
inputs=[
|
|
|
167 |
],
|
168 |
outputs=[message, chatbot, state, search])
|
169 |
gr.Markdown("""提醒:<br>
|
170 |
+
[Chinese-LangChain](https://github.com/yanqiangmiffy/Chinese-LangChain) <br>
|
171 |
有任何使用问题[Github Issue区](https://github.com/yanqiangmiffy/Chinese-LangChain)进行反馈. <br>
|
172 |
""")
|
173 |
demo.queue(concurrency_count=2).launch(
|
tests/test_langchain.py
CHANGED
@@ -29,7 +29,6 @@ print(doc)
|
|
29 |
search_result = vector_store.similarity_search_with_score(query='科比·布莱恩特', k=2)
|
30 |
print(search_result)
|
31 |
|
32 |
-
|
33 |
"""
|
34 |
[(Document(page_content='王治郅,1977年7月8日出生于北京,前中国篮球运动员,司职大前锋/中锋,现已退役。 [1]', metadata={'source': 'docs/王治郅.txt', 'filename': 'docs/王治郅.txt', 'category': 'Title'}), 285.40765), (Document(page_content='王治郅是中国篮球界进入NBA的第一人,被评选为中国篮坛50大杰出人物和中国申办奥运特使。他和姚明、蒙克·巴特尔一起,被称为篮球场上的“移动长城”。 [5]', metadata={'source': 'docs/王治郅.txt', 'filename': 'docs/王治郅.txt', 'category': 'NarrativeText'}), 290.19086)]
|
35 |
[Document(page_content='科比·布莱恩特(Kobe Bryant,1978年8月23日—2020年1月26日),全名科比·比恩·布莱恩特·考克斯(Kobe Bean Bryant Cox),出生于美国宾夕法尼亚州费城,美国已故篮球运动员,司职得分后卫/小前锋。 [5] [24] [84]', metadata={'source': 'docs/added/科比.txt', 'filename': 'docs/added/科比.txt', 'category': 'NarrativeText'}), Document(page_content='1996年NBA选秀,科比于第1轮第13顺位被夏洛特黄蜂队选中并被交易至洛杉矶湖人队,整个NBA生涯都效力于洛杉矶湖人队;共获得5次NBA总冠军、1次NBA常规赛MVP、2次NBA总决赛MVP、4次NBA全明星赛MVP、2次NBA赛季得分王;共入选NBA全明星首发阵容18次、NBA最佳阵容15次(其中一阵11次、二阵2次、三阵2次)、NBA最佳防守阵容12次(其中一阵9次、二阵3次)。 [9] [24]', metadata={'source': 'docs/added/科比.txt', 'filename': 'docs/added/科比.txt', 'category': 'Title'}), Document(page_content='2007年,科比首次入选美国国家男子篮球队,后帮助美国队夺得2007年美洲男篮锦标赛金牌、2008年北京奥运会男子篮球金牌以及2012年伦敦奥运会男子篮球金牌。 [91]', metadata={'source': 'docs/added/科比.txt', 'filename': 'docs/added/科比.txt', 'category': 'Title'}), Document(page_content='2015年11月30日,科比发文宣布将在赛季结束后退役。 [100] 2017年12月19日,湖人队为科比举行球衣退役仪式。 [22] 2020年4月5日,科比入选奈·史密斯篮球名人纪念堂。 [7]', metadata={'source': 'docs/added/科比.txt', 'filename': 'docs/added/科比.txt', 'category': 'Title'}), Document(page_content='美国时间2020年1月26日(北京时间2020年1月27日),科比因直升机事故遇难,享年41岁。 [23]', metadata={'source': 'docs/added/科比.txt', 'filename': 'docs/added/科比.txt', 'category': 'Title'})]
|
|
|
29 |
search_result = vector_store.similarity_search_with_score(query='科比·布莱恩特', k=2)
|
30 |
print(search_result)
|
31 |
|
|
|
32 |
"""
|
33 |
[(Document(page_content='王治郅,1977年7月8日出生于北京,前中国篮球运动员,司职大前锋/中锋,现已退役。 [1]', metadata={'source': 'docs/王治郅.txt', 'filename': 'docs/王治郅.txt', 'category': 'Title'}), 285.40765), (Document(page_content='王治郅是中国篮球界进入NBA的第一人,被评选为中国篮坛50大杰出人物和中国申办奥运特使。他和姚明、蒙克·巴特尔一起,被称为篮球场上的“移动长城”。 [5]', metadata={'source': 'docs/王治郅.txt', 'filename': 'docs/王治郅.txt', 'category': 'NarrativeText'}), 290.19086)]
|
34 |
[Document(page_content='科比·布莱恩特(Kobe Bryant,1978年8月23日—2020年1月26日),全名科比·比恩·布莱恩特·考克斯(Kobe Bean Bryant Cox),出生于美国宾夕法尼亚州费城,美国已故篮球运动员,司职得分后卫/小前锋。 [5] [24] [84]', metadata={'source': 'docs/added/科比.txt', 'filename': 'docs/added/科比.txt', 'category': 'NarrativeText'}), Document(page_content='1996年NBA选秀,科比于第1轮第13顺位被夏洛特黄蜂队选中并被交易至洛杉矶湖人队,整个NBA生涯都效力于洛杉矶湖人队;共获得5次NBA总冠军、1次NBA常规赛MVP、2次NBA总决赛MVP、4次NBA全明星赛MVP、2次NBA赛季得分王;共入选NBA全明星首发阵容18次、NBA最佳阵容15次(其中一阵11次、二阵2次、三阵2次)、NBA最佳防守阵容12次(其中一阵9次、二阵3次)。 [9] [24]', metadata={'source': 'docs/added/科比.txt', 'filename': 'docs/added/科比.txt', 'category': 'Title'}), Document(page_content='2007年,科比首次入选美国国家男子篮球队,后帮助美国队夺得2007年美洲男篮锦标赛金牌、2008年北京奥运会男子篮球金牌以及2012年伦敦奥运会男子篮球金牌。 [91]', metadata={'source': 'docs/added/科比.txt', 'filename': 'docs/added/科比.txt', 'category': 'Title'}), Document(page_content='2015年11月30日,科比发文宣布将在赛季结束后退役。 [100] 2017年12月19日,湖人队为科比举行球衣退役仪式。 [22] 2020年4月5日,科比入选奈·史密斯篮球名人纪念堂。 [7]', metadata={'source': 'docs/added/科比.txt', 'filename': 'docs/added/科比.txt', 'category': 'Title'}), Document(page_content='美国时间2020年1月26日(北京时间2020年1月27日),科比因直升机事故遇难,享年41岁。 [23]', metadata={'source': 'docs/added/科比.txt', 'filename': 'docs/added/科比.txt', 'category': 'Title'})]
|
tests/test_vector_store.py
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from langchain.embeddings.huggingface import HuggingFaceEmbeddings
|
2 |
+
from langchain.vectorstores import FAISS
|
3 |
+
|
4 |
+
# 中文Wikipedia数据导入示例:
|
5 |
+
embedding_model_name = '/root/pretrained_models/ernie-gram-zh'
|
6 |
+
embeddings = HuggingFaceEmbeddings(model_name=embedding_model_name)
|
7 |
+
|
8 |
+
vector_store = FAISS.load_local("/root/GoMall/Knowledge-ChatGLM/cache/zh_wikipedia", embeddings)
|
9 |
+
print(vector_store)
|
10 |
+
res = vector_store.similarity_search_with_score('闫强')
|
11 |
+
print(res)
|