""", unsafe_allow_html=True)
html(f"""
""", width=None, height=42, scrolling=False)
st.title("Scientific Question Answering with Citations")
st.write("""
Ask a scientific question and get an answer drawn from [scite.ai](https://scite.ai) corpus of over 1.1bn citation statements.
Answers are linked to source documents containing citations where users can explore further evidence from scientific literature for the answer.
For example try: Do tanning beds cause cancer?
""")
st.markdown("""
""", unsafe_allow_html=True)
# with st.expander("Settings (strictness, context limit, top hits)"):
# concat_passages = st.radio(
# "Concatenate passages as one long context?",
# ('yes', 'no'))
# present_impossible = st.radio(
# "Present impossible answers? (if the model thinks its impossible to answer should it still try?)",
# ('yes', 'no'))
# support_all = st.radio(
# "Use abstracts and titles as a ranking signal (if the words are matched in the abstract then the document is more relevant)?",
# ('no', 'yes'))
# support_abstracts = st.radio(
# "Use abstracts as a source document?",
# ('yes', 'no', 'abstract only'))
# strict_lenient_mix = st.radio(
# "Type of strict+lenient combination: Fallback or Mix? If fallback, strict is run first then if the results are less than context_lim we also search lenient. Mix will search them both and let reranking sort em out",
# ('mix', 'fallback'))
# confidence_threshold = st.slider('Confidence threshold for answering questions? This number represents how confident the model should be in the answers it gives. The number is out of 100%', 0, 100, 1)
# use_reranking = st.radio(
# "Use Reranking? Reranking will rerank the top hits using semantic similarity of document and query.",
# ('yes', 'no'))
# top_hits_limit = st.slider('Top hits? How many documents to use for reranking. Larger is slower but higher quality', 10, 300, 100)
# context_lim = st.slider('Context limit? How many documents to use for answering from. Larger is slower but higher quality', 10, 300, 25)
# def paraphrase(text, max_length=128):
# input_ids = queryexp_tokenizer.encode(text, return_tensors="pt", add_special_tokens=True)
# generated_ids = queryexp_model.generate(input_ids=input_ids, num_return_sequences=suggested_queries or 5, num_beams=suggested_queries or 5, max_length=max_length)
# queries = set([queryexp_tokenizer.decode(g, skip_special_tokens=True, clean_up_tokenization_spaces=True) for g in generated_ids])
# preds = '\n * '.join(queries)
# return preds
def group_results_by_context(results):
result_groups = {}
for result in results:
if result['context'] not in result_groups:
result_groups[result['context']] = result
result_groups[result['context']]['texts'] = []
result_groups[result['context']]['texts'].append(
result['answer']
)
if result['score'] > result_groups[result['context']]['score']:
result_groups[result['context']]['score'] = result['score']
return list(result_groups.values())
def matched_context(start_i, end_i, contexts_string, seperator='---'):
# find seperators to identify start and end
doc_starts = [0]
for match in re.finditer(seperator, contexts_string):
doc_starts.append(match.end())
for i in range(len(doc_starts)):
if i == len(doc_starts) - 1:
if start_i >= doc_starts[i]:
return contexts_string[doc_starts[i]:len(contexts_string)].replace(seperator, '')
if start_i >= doc_starts[i] and end_i <= doc_starts[i+1]:
return contexts_string[doc_starts[i]:doc_starts[i+1]].replace(seperator, '')
return None
# def run_query_full(query, progress_bar):
# # if use_query_exp == 'yes':
# # query_exp = paraphrase(f"question2question: {query}")
# # st.markdown(f"""
# # If you are not getting good results try one of:
# # * {query_exp}
# # """)
# # could also try fallback if there are no good answers by score...
# limit = top_hits_limit or 100
# context_limit = context_lim or 10
# contexts_strict, orig_docs_strict = search(query, limit=limit, strict=True, all_mode=support_all == 'yes', abstracts= support_abstracts == 'yes', abstract_only=support_abstracts == 'abstract only')
# if strict_lenient_mix == 'fallback' and len(contexts_strict) < context_limit:
# contexts_lenient, orig_docs_lenient = search(query, limit=limit, strict=False, all_mode=support_all == 'yes', abstracts= support_abstracts == 'yes', abstract_only= support_abstracts == 'abstract only')
# contexts = list(
# set(contexts_strict + contexts_lenient)
# )
# orig_docs = orig_docs_strict + orig_docs_lenient
# elif strict_lenient_mix == 'mix':
# contexts_lenient, orig_docs_lenient = search(query, limit=limit, strict=False)
# contexts = list(
# set(contexts_strict + contexts_lenient)
# )
# orig_docs = orig_docs_strict + orig_docs_lenient
# else:
# contexts = list(
# set(contexts_strict)
# )
# orig_docs = orig_docs_strict
# progress_bar.progress(25)
# if len(contexts) == 0 or not ''.join(contexts).strip():
# return st.markdown("""
#
#
#
# Sorry... no results for that question! Try another...
#
#
#
# """, unsafe_allow_html=True)
# if use_reranking == 'yes':
# sentence_pairs = [[query, context] for context in contexts]
# scores = reranker.predict(sentence_pairs, batch_size=len(sentence_pairs), show_progress_bar=False)
# hits = {contexts[idx]: scores[idx] for idx in range(len(scores))}
# sorted_contexts = [k for k,v in sorted(hits.items(), key=lambda x: x[0], reverse=True)]
# contexts = sorted_contexts[:context_limit]
# else:
# contexts = contexts[:context_limit]
# progress_bar.progress(50)
# if concat_passages == 'yes':
# context = '\n---'.join(contexts)
# model_results = qa_model(question=query, context=context, top_k=10, doc_stride=512 // 2, max_answer_len=128, max_seq_len=512, handle_impossible_answer=present_impossible=='yes')
# else:
# context = ['\n---\n'+ctx for ctx in contexts]
# model_results = qa_model(question=[query]*len(contexts), context=context, handle_impossible_answer=present_impossible=='yes')
# results = []
# progress_bar.progress(75)
# for i, result in enumerate(model_results):
# if concat_passages == 'yes':
# matched = matched_context(result['start'], result['end'], context)
# else:
# matched = matched_context(result['start'], result['end'], context[i])
# support = find_source(result['answer'], orig_docs, matched)
# if not support:
# continue
# results.append({
# "answer": support['text'],
# "title": support['source_title'],
# "link": support['source_link'],
# "context": support['citation_statement'],
# "score": result['score'],
# "doi": support["supporting"]
# })
# grouped_results = group_results_by_context(results)
# sorted_result = sorted(grouped_results, key=lambda x: x['score'], reverse=True)
# if confidence_threshold == 0:
# threshold = 0
# else:
# threshold = (confidence_threshold or 10) / 100
# sorted_result = list(filter(
# lambda x: x['score'] > threshold,
# sorted_result
# ))
# progress_bar.progress(100)
# for r in sorted_result:
# ctx = remove_html(r["context"])
# for answer in r['texts']:
# ctx = ctx.replace(answer.strip(), f"{answer.strip()}")
# # .replace( '
Sorry... no results for that question! Try another...
""", unsafe_allow_html=True)
for r in resp['results']:
ctx = remove_html(r["context"])
for answer in r['texts']:
ctx = ctx.replace(answer.strip(), f"{answer.strip()}")
# .replace( '