import os import pinecone import logging import time import faiss import nest_asyncio import streamlit as st from langchain.llms import OpenAI from langchain.chat_models.openai import ChatOpenAI from langchain.llms import HuggingFacePipeline from langchain import HuggingFaceHub from langchain import PromptTemplate, LLMChain from langchain.chains.router import MultiPromptChain from langchain.llms import OpenAI from langchain.chains import ConversationChain from langchain.chains.llm import LLMChain from langchain.prompts import PromptTemplate from langchain.chains.router.llm_router import LLMRouterChain, RouterOutputParser from langchain.chains.router.multi_prompt_prompt import MULTI_PROMPT_ROUTER_TEMPLATE from langchain.chains.router.embedding_router import EmbeddingRouterChain from langchain.vectorstores import FAISS from langchain.embeddings import HuggingFaceEmbeddings from langchain.embeddings import HuggingFaceEmbeddings, SentenceTransformerEmbeddings from templates import hebrew_template, greek_template, apologetics_template, theology_template, therapy_template, history_template, commentary_template from langchain.callbacks.base import BaseCallbackHandler from langchain.chains import RetrievalQAWithSourcesChain from langchain.retrievers.web_research import WebResearchRetriever from langchain.vectorstores import FAISS from langchain.embeddings.openai import OpenAIEmbeddings from langchain.docstore import InMemoryDocstore from langchain.utilities import GoogleSearchAPIWrapper from langchain.retrievers.multi_query import MultiQueryRetriever from langchain.chains.question_answering import load_qa_chain from langchain.vectorstores import Pinecone st.title("BereaAI Bible Assistant") st.write("BereaAI has expertise in Biblical Hebrew, Greek, Apologetics, Theology, Counselling and Church History. \ Though still in the early stages BereaAI shows promise in delivering nuanced and thorough explanations. \ The first answer takes a while to load but the consequent answers load much faster. \ ") #HUGGINGFACEHUB_API_TOKEN = st.secrets["HUGGINGFACEHUB_API_TOKEN"] GOOGLE_API_KEY = st.secrets["GOOGLE_API_KEY"] GOOGLE_CSE_ID = st.secrets["GOOGLE_CSE_ID"] OPENAI_API_BASE = st.secrets["OPENAI_API_BASE"] OPENAI_API_KEY = st.secrets["OPENAI_API_KEY"] PINECONE_API_KEY = st.secrets["PINECONE_API_KEY"] #repo_id = "meta-llama/Llama-2-7b-chat-hf" #st.header("Parameters") #temperature = st.slider('Temperature', min_value=0.0, max_value=1.0, value=0.3, step=0.1) #max_new_tokens = st.slider('Max New Tokens', min_value=100, max_value=2000, value=1024, step=50) #top_p = st.slider('Top P', min_value=0.0, max_value=1.0, value=0.4, step=0.05) #llm = HuggingFaceHub(repo_id=repo_id, model_kwargs={"temperature": temperature, "max_new_tokens": max_new_tokens, "top_p": top_p}) llm = ChatOpenAI(model_name="gpt-3.5-turbo-16k",openai_api_key=OPENAI_API_KEY, temperature=0.3, streaming=True) # initialize pinecone pinecone.init( api_key=PINECONE_API_KEY, # find at app.pinecone.io environment="us-west1-gcp", # next to api key in console ) index_name = "bereaai" embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/stsb-bert-large") prompt_infos = [ { "name": "hebrew", "description": "Good for answering questions about Hebrew Old Testament Bible", "prompt_template": hebrew_template, }, { "name": "greek", "description": "Good for answering questions about Greek New Testament Bible", "prompt_template": greek_template, }, { "name": "apologetics", "description": "Good for answering questions directed against the Bible or Christianity", "prompt_template": apologetics_template, }, { "name": "theology", "description": "Good for answering questions about biblical theology", "prompt_template": theology_template, }, { "name": "therapy", "description": "Good for answering questions about mental health or personal issues", "prompt_template": therapy_template, }, { "name": "history", "description": "Good for answering questions about mental health or personal issues", "prompt_template": history_template, }, { "name": "commentary", "description": "Good for answering questions about verses, chapters or books of the Bible", "prompt_template": commentary_template, }, ] destination_chains = {} for p_info in prompt_infos: name = p_info["name"] prompt_template = p_info["prompt_template"] prompt = PromptTemplate(template=prompt_template, input_variables=["input"]) chain = LLMChain(llm=llm, prompt=prompt) destination_chains[name] = chain default_chain = ConversationChain(llm=llm, output_key="text") names_and_descriptions = [ ("hebrew", ["for questions about hebrew"]), ("greek", ["for questions about greek"]), ("apologetics", ["for questions directed against the Bible or Christianity"]), ("theology", ["for questions about theology"]), ("therapy", ["for questions about mental health"]), ("history", ["for questions about history"]), ("commentary", ["for questions about verses, passages or books of the Bible"]), ] router_chain = EmbeddingRouterChain.from_names_and_descriptions( names_and_descriptions, FAISS, embeddings, routing_keys=["input"] ) def generate_response(input_text): chain = MultiPromptChain( router_chain=router_chain, destination_chains=destination_chains, default_chain=default_chain, verbose=True,) return chain.run(input_text) def settings(): embedding_size = 1024 index = faiss.IndexFlatL2(embedding_size) vectorstore_public = FAISS(embeddings.embed_query, index, InMemoryDocstore({}), {}) search = GoogleSearchAPIWrapper() # Initialize web_retriever = WebResearchRetriever.from_llm( vectorstore=vectorstore_public, llm=llm, search=search, num_search_results=3 ) return web_retriever, llm # Make retriever and llm web_retriever, llm = settings() nest_asyncio.apply() def web_search(question): logging.basicConfig() logging.getLogger("langchain.retrievers.web_research").setLevel(logging.INFO) qa_chain = RetrievalQAWithSourcesChain.from_chain_type(llm, retriever=web_retriever) # Get result result = qa_chain({"question": question}) return(result) def vector_search(question): docsearch = Pinecone.from_existing_index(index_name, embeddings) logging.basicConfig() logging.getLogger('langchain.retrievers.multi_query').setLevel(logging.INFO) qa_chain = RetrievalQAWithSourcesChain.from_chain_type(llm, retriever=docsearch.as_retriever()) result = qa_chain({"question": question}) if result: sources_list = result['sources'].split('/content/drive/MyDrive/Commentaries/') filenames_with_extension = [os.path.basename(source) for source in sources_list] filename_without_extension = [os.path.splitext(source)[0] for source in filenames_with_extension] filtered_sources = [source for source in filename_without_extension if source] cleaned_sources = "\n- ".join(filtered_sources) else: pass return text, cleaned_sources def combined_answer(text1, text2, text3, source, question): text_answer2 = text2['answer'] books_ref = source web_ref = text2['sources'] return text1, books_ref, web_ref with st.form("my_form"): text = st.text_area("Enter text:", "Type question here") submitted = st.form_submit_button("Submit") if not text: st.info("You forgot to type something") elif submitted: with st.spinner('Researching...'): text1 = generate_response(text) text2 = web_search(text) text3, source = vector_search(text) answer, source2, source3 = combined_answer(text1, text2, text3, source,text) st.info(answer) st.info(f"Web Sources:\n {source3}") st.info(f"Book Sources: \n\n {source2}") st.markdown("## Examples") example1 = "Give me a Hebrew word study of Psalm 23" example2 = "Give me a Greek word study on John 17:1-5" example3 = "What is the evidence Jesus actually rose from the dead?" example4 = "I'm feeling really overwhelmed and overcome by anxiety and I don't know what to do" example5 = "How and when was the canon of the Bible put together?" example6 = "Explain the Trinity" example7 = "Give me a commentary on Matthew 5:3-12" if st.button(example1): user_input = example1 if st.button(example2): user_input = example2 if st.button(example3): user_input = example3 if st.button(example4): user_input = example4 if st.button(example5): user_input = example5 if st.button(example6): user_input = example6 if st.button(example7): user_input = example7