svjack commited on
Commit
a2257c1
1 Parent(s): 2933ccc

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +500 -0
app.py ADDED
@@ -0,0 +1,500 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from gradio_client import Client
2
+ client = Client("https://svjack-entity-property-extractor-zh.hf.space")
3
+
4
+ import pandas as pd
5
+ import numpy as np
6
+ import os
7
+ import re
8
+
9
+ from langchain.vectorstores import FAISS
10
+ from langchain.embeddings.huggingface import HuggingFaceEmbeddings
11
+ from langchain import chains
12
+ from rapidfuzz import fuzz
13
+
14
+ import pandas as pd
15
+
16
+ from haystack.components.generators.chat import HuggingFaceTGIChatGenerator
17
+ from haystack.dataclasses import ChatMessage
18
+ import pandas as pd
19
+ import numpy as np
20
+
21
+ from huggingface_hub import snapshot_download
22
+
23
+ if not os.path.exists("genshin_book_chunks_with_qa_sp"):
24
+ path = snapshot_download(
25
+ repo_id="svjack/genshin_book_chunks_with_qa_sp",
26
+ repo_type="dataset",
27
+ local_dir="genshin_book_chunks_with_qa_sp",
28
+ local_dir_use_symlinks = False
29
+ )
30
+
31
+ if not os.path.exists("bge_small_book_chunks_prebuld"):
32
+ path = snapshot_download(
33
+ repo_id="svjack/bge_small_book_chunks_prebuld",
34
+ repo_type="dataset",
35
+ local_dir="bge_small_book_chunks_prebuld",
36
+ local_dir_use_symlinks = False
37
+ )
38
+
39
+ model_id = "mistralai/Mistral-7B-Instruct-v0.2"
40
+ HF_TOKEN = os.environ.get("HF_READ_TOKEN")
41
+ tgi_chat_generator = HuggingFaceTGIChatGenerator(model=model_id, token=HF_TOKEN,
42
+ #stop_words = [".", "。"]
43
+ )
44
+ tgi_chat_generator.warm_up()
45
+
46
+ def chat_messages(message, history,
47
+ max_length = 128, show_process = False):
48
+ flatten_history = []
49
+ for a, b in history:
50
+ flatten_history.append(
51
+ #chatglm_cpp.ChatMessage(role="user", content=a)
52
+ ChatMessage.from_user(a)
53
+ )
54
+ flatten_history.append(
55
+ #chatglm_cpp.ChatMessage(role="assistant", content=b)
56
+ ChatMessage.from_assistant(b)
57
+ )
58
+ response = tgi_chat_generator.run(
59
+ flatten_history + [
60
+ ChatMessage.from_user(message)
61
+ ]
62
+ , generation_kwargs={"max_new_tokens": max_length})
63
+ #print(response["replies"][0].content)
64
+ yield response["replies"][0].content
65
+
66
+ '''
67
+ query = "警察是如何破获邪恶计划的?" ## 警 执律 盗
68
+ k = 10
69
+ uniform_recall_docs_to_pairwise_cos(
70
+ query,
71
+ docsearch_bge_loaded.similarity_search_with_score(query, k = k, ),
72
+ bge_book_embeddings
73
+ )
74
+ '''
75
+ def uniform_recall_docs_to_pairwise_cos(query ,doc_list, embeddings):
76
+ assert type(doc_list) == type([])
77
+ from langchain.evaluation import load_evaluator
78
+ from langchain.evaluation import EmbeddingDistance
79
+ hf_evaluator = load_evaluator("pairwise_embedding_distance", embeddings=embeddings,
80
+ distance_metric = EmbeddingDistance.COSINE)
81
+ return sorted(pd.Series(doc_list).map(lambda x: x[0].page_content).map(lambda x:
82
+ (x ,hf_evaluator.evaluate_string_pairs(prediction=query, prediction_b=x)["score"])
83
+ ).values.tolist(), key = lambda t2: t2[1])
84
+
85
+ '''
86
+ sort_by_kw("深渊使徒", book_df)["content_chunks_formatted"].head(5).values.tolist() ### 深渊
87
+ '''
88
+ def sort_by_kw(kw, book_df):
89
+ req = book_df.copy()
90
+ req["sim_score"] = req.apply(
91
+ lambda x:
92
+ max(map(lambda y: fuzz.ratio(y, kw) ,eval(x["person"]) + eval(x["locate"]) + eval(x["locate"]))) if \
93
+ eval(x["person"]) + eval(x["locate"]) + eval(x["locate"]) else 0
94
+ , axis = 1
95
+ )
96
+ req = req.sort_values(by = "sim_score", ascending = False)
97
+ return req
98
+
99
+ def recall_chuncks(query, docsearch, embedding, book_df,
100
+ sparse_threshold = 30,
101
+ dense_top_k = 10,
102
+ rerank_by = "emb",
103
+ ):
104
+ sparse_output = sort_by_kw(query, book_df)[["content_chunks_formatted", "sim_score"]]
105
+ sparse_output_list = sparse_output[
106
+ sparse_output["sim_score"] >= sparse_threshold
107
+ ]["content_chunks_formatted"].values.tolist()
108
+ dense_output = uniform_recall_docs_to_pairwise_cos(
109
+ query,
110
+ docsearch.similarity_search_with_score(query, k = dense_top_k,),
111
+ embedding
112
+ )
113
+ for chunck, score in dense_output:
114
+ if chunck not in sparse_output_list:
115
+ sparse_output_list.append(chunck)
116
+ if rerank_by == "emb":
117
+ from langchain.evaluation import load_evaluator
118
+ from langchain.evaluation import EmbeddingDistance
119
+ hf_evaluator = load_evaluator("pairwise_embedding_distance", embeddings=embedding,
120
+ distance_metric = EmbeddingDistance.COSINE)
121
+ return pd.Series(sorted(pd.Series(sparse_output_list).map(lambda x:
122
+ (x ,hf_evaluator.evaluate_string_pairs(prediction=query, prediction_b=x)["score"])
123
+ ).values.tolist(), key = lambda t2: t2[1])).map(lambda x: x[0]).values.tolist()
124
+ else:
125
+ sparse_output_list = sorted(sparse_output_list, key = lambda x: fuzz.ratio(x, query), reverse = True)
126
+ return sparse_output_list
127
+
128
+ def reduce_list_by_order(text_list, as_text = False):
129
+ if not text_list:
130
+ return
131
+ df = pd.DataFrame(
132
+ list(map(lambda x: (x.split("\n")[0], x.split("\n")[1], "\n".join(x.split("\n")[2:])), text_list))
133
+ ).groupby([0, 1])[2].apply(list).map(lambda x: sorted(x, key = len, reverse=True)).map(
134
+ "\n\n".join
135
+ ).reset_index()
136
+ d = dict(df.apply(lambda x: ((x.iloc[0], x.iloc[1]), x.iloc[2]), axis = 1).values.tolist())
137
+ #return df
138
+ order_list = []
139
+ for x in text_list:
140
+ a, b = x.split("\n")[0], x.split("\n")[1]
141
+ if not order_list:
142
+ order_list = [[a, [b]]]
143
+ elif a in list(map(lambda t2: t2[0], order_list)):
144
+ order_list[list(map(lambda t2: t2[0], order_list)).index(a)][1].append(b)
145
+ elif a not in list(map(lambda t2: t2[0], order_list)):
146
+ order_list.append([a, [b]])
147
+ df = pd.DataFrame(pd.DataFrame(order_list).explode(1).dropna().apply(
148
+ lambda x: (x.iloc[0], x.iloc[1], d[(x.iloc[0], x.iloc[1])]), axis = 1
149
+ ).values.tolist()).drop_duplicates()
150
+ if as_text:
151
+ return "\n\n".join(
152
+ df.apply(lambda x: "{}\n{}\n{}".format(x.iloc[0], x.iloc[1], x.iloc[2]), axis = 1).values.tolist()
153
+ )
154
+ return df
155
+
156
+ def build_gpt_prompt(query, docsearch, embedding, book_df, max_context_length = 4090):
157
+ l = recall_chuncks(query, docsearch, embedding, book_df)
158
+ context = reduce_list_by_order(l, as_text = True)
159
+ context_l = []
160
+ for ele in context.split("\n"):
161
+ if sum(map(len, context_l)) >= max_context_length:
162
+ break
163
+ context_l.append(ele)
164
+ context = "\n".join(context_l).strip()
165
+ template = """使用以下上下文来回答最后的问题。如果你不知道答案,就说你不知道,不要试图编造答案。尽量使答案简明扼要。总是在回答的最后说“谢谢你的提问!”。
166
+
167
+ {context}
168
+
169
+ 问题: {question}
170
+ 有用的回答:"""
171
+ return template.format(
172
+ **{
173
+ "context": context,
174
+ "question": query
175
+ }
176
+ )
177
+
178
+ def collect_prompt_to_hist_list(prompt, add_assistant = False):
179
+ l = pd.Series(prompt.split("\n\n")).map(lambda x: x.strip()).values.tolist()
180
+ ll = []
181
+ for ele in l:
182
+ if not ll:
183
+ ll.append(ele)
184
+ else:
185
+ if ele.startswith("文章标题:") or ele.startswith("问题:"):
186
+ ll.append(ele)
187
+ else:
188
+ ll[-1] += ("\n\n" + ele)
189
+ if add_assistant:
190
+ ll_ = []
191
+ for i in range(len(ll)):
192
+ if i == 0:
193
+ ll_.append((ll[i], "好的。"))
194
+ elif i < len(ll) - 1:
195
+ ll_.append((ll[i], "我读懂了。"))
196
+ else:
197
+ ll_.append((ll[i], ""))
198
+ return ll_
199
+ else:
200
+ return ll
201
+
202
+ def row_to_content_ask(r):
203
+ question = r["question"]
204
+ content_list = r["content_list"]
205
+ assert type(content_list) == type([])
206
+ content_prompt_list = pd.Series(content_list).map(
207
+ lambda x: '''
208
+ {}\n从上面的相关的叙述中抽取包含"{}"中词汇的相关语段。
209
+ '''.format(x, question).strip()
210
+ ).values.tolist()
211
+ return content_prompt_list
212
+
213
+ def entity_extractor_by_hf(query,
214
+ show_process = False, max_length = 512,
215
+ return_out_text = False,
216
+ ):
217
+ import re
218
+ hist = [
219
+ ['请从下面的句子中提取实体和属性。不需要进行进一步解释。', '好的。'],
220
+ ['问题:宁波在哪个省份?', '实体:宁波 属性:省份'],
221
+ ['问题:中国的货币是什么?', '实体:中国 属性:货币'],
222
+ ['问题:百慕大三角在什么地方?', '实体:百慕大三角 属性:地方'],
223
+ ['问题:谁是最可爱的人?', "实体:人 属性:可爱"],
224
+ ['问题:黄河的拐点在哪里?', "实体:黄河 属性:拐点"],
225
+ #['问题:魔神归终在哪里?', '实体:归终 属性:哪里'],
226
+ #["玉米的引进时间是什么时候?", ""]
227
+ ]
228
+
229
+ out_text = chat_messages("问题:{}".format(query),
230
+ hist,
231
+ )
232
+ req = ""
233
+ for ele in out_text:
234
+ req = ele
235
+ out_text = req
236
+
237
+ if return_out_text:
238
+ return out_text
239
+ e_list = re.findall(r"实体(.*?)属性", out_text.replace("\n", " "))
240
+ if e_list:
241
+ return re.findall(u"[\u4e00-\u9fa5]+" ,e_list[0])
242
+ return None
243
+
244
+ def unzip_string(x, size = 2):
245
+ if len(x) <= size:
246
+ return [x]
247
+ req = []
248
+ for i in range(len(x) - size + 1):
249
+ req.append(x[i: i + size])
250
+ return req
251
+
252
+ def entity_extractor_by_adapter(x):
253
+ import json
254
+ result = client.predict(
255
+ x, # str in 'question' Textbox component
256
+ api_name="/predict"
257
+ )
258
+ with open(result, "r") as f:
259
+ req = json.load(f)
260
+ req_list = req.get("E-TAG", [])
261
+ req_ = []
262
+ for ele in req_list:
263
+ for x in unzip_string(ele, 2):
264
+ if x not in req_:
265
+ req_.append(x)
266
+ return req_
267
+
268
+ ##### maybe 0.5
269
+ def query_content_ask_func(question, content_list,
270
+ setfit_model, show_process = False, max_length = 1024):
271
+ ask_list = row_to_content_ask(
272
+ {
273
+ "question": question,
274
+ "content_list": content_list
275
+ }
276
+ )
277
+ #return ask_list
278
+ req = []
279
+ for prompt in ask_list:
280
+
281
+ out_text = chat_messages(prompt + "如果没有提到相关内容,请回答不知道。使用中文进行回答,不要包含任何英文。",
282
+ [], show_process = show_process, max_length = max_length
283
+ )
284
+ req_ = ""
285
+ for ele in out_text:
286
+ req_ = ele
287
+ out_text = req_
288
+
289
+ req.append(out_text)
290
+ d = {
291
+ "question": question,
292
+ "content_list": content_list
293
+ }
294
+ assert len(req) == len(ask_list)
295
+ d["question_content_relate_list"] = req
296
+ d["relate_prob_list"] = setfit_model.predict_proba(
297
+ req
298
+ ).numpy()[:, 1].tolist()
299
+ return d
300
+
301
+ def build_relate_ask_list(query, docsearch_bge_loaded, bge_book_embeddings, book_df,
302
+ setfit_model, as_content_score_df = True,
303
+ show_process = False, add_relate_entities = False,
304
+ max_length = 1024):
305
+ prompt = build_gpt_prompt(query, docsearch_bge_loaded, bge_book_embeddings, book_df)
306
+ prompt_list = collect_prompt_to_hist_list(prompt)
307
+ question = prompt_list[-1].split("\n")[0]
308
+ content_list = prompt_list[1:-1]
309
+
310
+ d = query_content_ask_func(question, content_list,
311
+ setfit_model, show_process = show_process)
312
+
313
+ #entity_list = entity_extractor_by_hf(query,
314
+ # show_process = show_process, max_length = max_length)
315
+ entity_list = entity_extractor_by_adapter(query)
316
+ if type(entity_list) != type([]):
317
+ entity_list = []
318
+
319
+ d["in_content_entity_list"] = list(map(lambda x:
320
+ list(filter(lambda e: e in x, entity_list))
321
+ , d["content_list"]))
322
+
323
+ if add_relate_entities:
324
+ relate_content_entity_list = [[]] * len(content_list)
325
+
326
+ for entity in entity_list:
327
+ entity_content_score_d = query_content_ask_func(entity, d["content_list"],
328
+ setfit_model, show_process = show_process)
329
+ lookup_df = pd.DataFrame(
330
+ list(zip(*[entity_content_score_d["content_list"],
331
+ entity_content_score_d["relate_prob_list"]]))
332
+ )
333
+ for ii, (i, r) in enumerate(lookup_df.iterrows()):
334
+ if r.iloc[1] >= 0.5 and entity not in relate_content_entity_list[ii]:
335
+ #relate_content_entity_list[ii].append(entity)
336
+ relate_content_entity_list[ii] = relate_content_entity_list[ii] + [entity]
337
+
338
+ d["relate_content_entity_list"] = relate_content_entity_list
339
+
340
+ if as_content_score_df:
341
+ if add_relate_entities:
342
+ df = pd.concat(
343
+ [
344
+ pd.Series(d["content_list"]).map(lambda x: x.strip()),
345
+ pd.Series(d["in_content_entity_list"]),
346
+ pd.Series(d["relate_content_entity_list"]),
347
+ pd.Series(d["question_content_relate_list"]).map(lambda x: x.strip()),
348
+ pd.Series(d["relate_prob_list"])
349
+ ], axis = 1
350
+ )
351
+ df.columns = ["content", "entities", "relate_entities", "relate_eval_str", "score"]
352
+ else:
353
+ df = pd.concat(
354
+ [
355
+ pd.Series(d["content_list"]).map(lambda x: x.strip()),
356
+ pd.Series(d["in_content_entity_list"]),
357
+ #pd.Series(d["relate_content_entity_list"]),
358
+ pd.Series(d["question_content_relate_list"]).map(lambda x: x.strip()),
359
+ pd.Series(d["relate_prob_list"])
360
+ ], axis = 1
361
+ )
362
+ df.columns = ["content", "entities", "relate_eval_str", "score"]
363
+ req = []
364
+ entities_num_list = df["entities"].map(len).drop_duplicates().dropna().sort_values(ascending = False).\
365
+ values.tolist()
366
+ for e_num in entities_num_list:
367
+ req.append(
368
+ df[
369
+ df["entities"].map(lambda x: len(x) == e_num)
370
+ ].sort_values(by = "score", ascending = False)
371
+ )
372
+ return pd.concat(req, axis = 0)
373
+ #df = df.sort_values(by = "score", ascending = False)
374
+ #return df
375
+ return d
376
+
377
+ def run_all(query, docsearch_bge_loaded, bge_book_embeddings, book_df,
378
+ setfit_model, only_return_prompt = False,
379
+ use_gf4_on_qa = False):
380
+ df = build_relate_ask_list(query, docsearch_bge_loaded, bge_book_embeddings, book_df,
381
+ setfit_model, show_process=False)
382
+ info_list = df[
383
+ df.apply(
384
+ lambda x: x["score"] >= 0.5 and bool(x["entities"]), axis = 1
385
+ )
386
+ ].values.tolist()
387
+ if not info_list:
388
+ return df, info_list, "没有相关内容,谢谢你的提问。"
389
+ prompt = '''
390
+ 问题: {}
391
+ 根据下面的内容回答上面的问题,如果无法根据内容确定答案,请回答不知道。
392
+ {}
393
+ '''.format(query, "\n\n".join(pd.Series(info_list).map(lambda x: x[0]).values.tolist()))
394
+ if only_return_prompt:
395
+ return df, info_list, prompt
396
+
397
+ q_head = "\n".join(prompt.split("\n")[:2])
398
+ c_tail = "\n".join(prompt.split("\n")[2:])[:4000]
399
+ if use_gf4_on_qa:
400
+ out_text = chat_messages_gf4(
401
+ c_tail + "\n" + q_head.replace("下面的内容回答上面的问题", "上面的内容回答问题") + "用中文回答问题。",
402
+ [], show_process = False, max_length = 512
403
+ )
404
+ else:
405
+ out_text = chat_messages(
406
+ c_tail + "\n" + q_head.replace("下面的内容回答上面的问题", "上面的内容回答问题") + "用中文回答问题。",
407
+ [], show_process = False, max_length = 512
408
+ )
409
+ req_ = ""
410
+ for ele in out_text:
411
+ req_ = ele
412
+ out_text = req_
413
+
414
+ return df, info_list, out_text
415
+
416
+ import gradio as gr
417
+
418
+ #book_df = pd.read_csv("genshin_book_chunks_with_qa_sp.csv")
419
+ book_df = pd.read_csv("genshin_book_chunks_with_qa_sp/genshin_book_chunks_with_qa_sp.csv")
420
+ book_df["content_chunks"].dropna().drop_duplicates().shape
421
+
422
+ book_df["content_chunks_formatted"] = book_df.apply(
423
+ lambda x: "文章标题:{}\n子标题:{}\n内容:{}".format(x["title"], x["sub_title"], x["content_chunks"]),
424
+ axis = 1
425
+ )
426
+
427
+ texts = book_df["content_chunks_formatted"].dropna().drop_duplicates().values.tolist()
428
+
429
+ #embedding_path = "bge-small-book-qa/"
430
+ embedding_path = "svjack/bge-small-book-qa"
431
+ bge_book_embeddings = HuggingFaceEmbeddings(model_name=embedding_path)
432
+ docsearch_bge_loaded = FAISS.load_local("bge_small_book_chunks_prebuld/", bge_book_embeddings)
433
+
434
+ from setfit import SetFitModel
435
+ #setfit_model = SetFitModel.from_pretrained("setfit_info_cls")
436
+ setfit_model = SetFitModel.from_pretrained("svjack/setfit_info_cls")
437
+
438
+ with gr.Blocks() as demo:
439
+ title = gr.HTML(
440
+ """<h1 align="center"> <font size="+3"> Genshin Impact Book QA Haystack Demo 🍔 </font> </h1>""",
441
+ elem_id="title",
442
+ )
443
+
444
+ with gr.Column():
445
+ with gr.Row():
446
+ query = gr.Text(label = "输入问题:", lines = 1, interactive = True, scale = 5.0)
447
+ run_button = gr.Button("得到答案")
448
+ output = gr.Text(label = "回答:", lines = 5, interactive = True)
449
+ recall_items = gr.JSON(label = "召回相关内容", interactive = False)
450
+
451
+ with gr.Row():
452
+ gr.Examples(
453
+ [
454
+ '丘丘人有哪些生活习惯?',
455
+ '岩王帝君和归终是什么关系?',
456
+ '盐之魔神的下场是什么样的?',
457
+ #'归终是谁?',
458
+ '岩王帝君是一个什么样的人?',
459
+ #'铳枪手的故事内容是什么样的?',
460
+ '白夜国的子民遭遇了什么?',
461
+ '大蛇居住在哪里?',
462
+ '珊瑚宫有哪些传说?',
463
+ '灵光颂的内容是什么样的?',
464
+ '连心珠讲了一件什么事情?',
465
+ '梓心是谁?',
466
+ #'枫丹有哪些故事?',
467
+ '璃月有哪些故事?',
468
+ '轻策庄有哪些故事?',
469
+ '瑶光滩有哪些故事?',
470
+ '稻妻有哪些故事?',
471
+ '海祇岛有哪些故事?',
472
+ '须弥有哪些故事?',
473
+ '蒙德有哪些故事?',
474
+ '璃月有哪些奇珍异宝?',
475
+ '狸猫和天狗是什么关系?',
476
+ ],
477
+ inputs = query,
478
+ label = "被书目内容包含的问题"
479
+ )
480
+ with gr.Row():
481
+ gr.Examples(
482
+ [
483
+ '爱丽丝女士是可莉的妈妈吗?',
484
+ '摘星崖是什么样的?',
485
+ '丘丘人使用的是什么文字?',
486
+ '深渊使徒哪里来的?',
487
+ '发条机关可以用来做什么?',
488
+ '那先朱那做了什么?',
489
+ ],
490
+ inputs = query,
491
+ label = "没有被书目明确提到的问题"
492
+ )
493
+
494
+ run_button.click(lambda x:
495
+ run_all(x, docsearch_bge_loaded, bge_book_embeddings, book_df,
496
+ setfit_model = setfit_model)[1:],
497
+ query, [recall_items, output]
498
+ )
499
+
500
+ demo.queue(max_size=4, concurrency_count=1).launch(debug=True, show_api=False, share = True)