import os import pickle from typing import Optional, Tuple import gradio as gr from threading import Lock from langchain.llms import OpenAI from langchain.chat_models import ChatOpenAI from langchain.chains import ChatVectorDBChain, ConversationalRetrievalChain from template import QA_PROMPT, CONDENSE_QUESTION_PROMPT from pdf2vectorstore import convert_to_vectorstore def get_chain(api_key, vectorstore, model_name): if model_name == "gpt-4": llm = ChatOpenAI(model_name = model_name, temperature=0, openai_api_key=api_key) retriever = vectorstore.as_retriever() retriever.search_kwargs['distance_metric'] = 'cos' retriever.search_kwargs['fetch_k'] = 100 retriever.search_kwargs['maximal_marginal_relevance'] = True retriever.search_kwargs['k'] = 10 qa_chain = ConversationalRetrievalChain.from_llm( llm, retriever, qa_prompt=QA_PROMPT, condense_question_prompt=CONDENSE_QUESTION_PROMPT, ) return qa_chain else: llm = OpenAI(model_name = model_name, temperature=0, openai_api_key=api_key) qa_chain = ChatVectorDBChain.from_llm( llm, vectorstore, qa_prompt=QA_PROMPT, condense_question_prompt=CONDENSE_QUESTION_PROMPT, ) return qa_chain def set_openai_api_key(api_key: str, vectorstore, model_name: str): if api_key: chain = get_chain(api_key, vectorstore, model_name) return chain class ChatWrapper: def __init__(self): self.lock = Lock() self.previous_url = "" self.vectorstore_state = None self.chain = None def __call__( self, api_key: str, arxiv_url: str, inp: str, history: Optional[Tuple[str, str]], model_name: str, ): if not arxiv_url or not api_key: history = history or [] history.append((inp, "Please provide both arXiv URL and API key to begin")) return history, history if arxiv_url != self.previous_url: history = [] vectorstore = convert_to_vectorstore(arxiv_url, api_key) self.previous_url = arxiv_url self.chain = set_openai_api_key(api_key, vectorstore, model_name) self.vectorstore_state = vectorstore if self.chain is None: self.chain = set_openai_api_key(api_key, self.vectorstore_state, model_name) self.lock.acquire() try: history = history or [] if self.chain is None: history.append((inp, "Please paste your OpenAI key to use")) return history, history import openai openai.api_key = api_key output = self.chain ({"question": inp, "chat_history": history})["answer"] history.append((inp, output)) except Exception as e: raise e finally: api_key = "" self.lock.release() return history, history chat = ChatWrapper() block = gr.Blocks(css=".gradio-container {background-color: #f8f8f8; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif}") with block: gr.HTML(""" """) gr.HTML("
Developed by Github and Huggingface: Volkopat
Powered by OpenAI, arXiv and LangChain 🦜️🔗
ArxivGPT is a chatbot that answers questions about research papers. It uses a pretrained GPT-3.5 model to generate answers.
Currently, it can answer questions about the paper you just linked.
It's still in development, so please report any bugs you find.
It can take up to a minute to start a conversation for every new paper as this is just a demo hosted on a lightweight service.
For best results, test it on better hardware. Took 20 seconds to start on M1 Chip
The answers can be quite limited as there is a 4096 token limit for GPT-3.5, hence wait for GPT-4 access for better quality.
If you don't get a response for GPT-4, it is likely that you don't have API access, try 3.5
Possible upgrades coming up: faster parsing, status messages, other research paper hubs.