internal-ai / app.py
sveshkini's picture
Update app.py
21965d4
Raw
History Blame Contribute Delete
5.82 kB
import os
import faiss
import pickle
from typing import List, Tuple, Dict, Any
# from dotenv import load_dotenv
from langchain.llms import OpenAI
from langchain.chains import VectorDBQAWithSourcesChain
from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from notion import NotionPageReader
from gpt_index.schema import Document
from pprint import pprint
import argparse
import gradio as gr
import slack_sdk
from flask import Flask
from slackeventsapi import SlackEventAdapter
from threading import Thread
# load_dotenv()
OPENAI_API_KEY = os.getenv('OPENAI_API_KEY')
NOTION_API_KEY = os.getenv('NOTION_API_KEY')
SLACK_TOKEN=os.getenv('SLACK_TOKEN')
SIGNING_SECRET=os.getenv('SIGNING_SECRET')
def load_notion_documents() -> List[Document]:
print("Retrieving Notion documents...")
notion_client = NotionPageReader(integration_token=NOTION_API_KEY)
pages = notion_client.search("")
documents = notion_client.load_data(pages=pages)
return documents
def preprocess_documents(documents: Document) -> Tuple[List[List[str]], Dict[str, Any]]:
print("Processing documents...")
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
docs = []
metadatas = []
for document in documents:
content = document.text
metadata = document.extra_info
text_splits = text_splitter.split_text(content)
text_splits = list(filter(lambda x: x != "", text_splits))
docs.extend(text_splits)
metadatas.extend([metadata] * len(text_splits))
return docs, metadatas
def create_embeddings_and_vector_db(documents: List[List[str]], metadatas: Dict[str, Any]) -> None:
print("Creating embeddings of documents and loading into vector db...")
vector_db = FAISS.from_texts(documents, OpenAIEmbeddings(), metadatas=metadatas)
faiss.write_index(vector_db.index, "docs.index")
vector_db.index = None
with open("db.pkl", "wb") as f:
pickle.dump(vector_db, f)
def ingest():
# 1. Retrieve documents and metadata from source (Notion API)
documents = load_notion_documents()
# 1.5 Pre-process documents and document metadata
# Split documents into smaller chunks due to the context limits of the LLMs.
docs, metadatas = preprocess_documents(documents)
# 2. Create embeddings of documents
# 3. Store embeddings in vector database
create_embeddings_and_vector_db(docs, metadatas)
def question(question: str) -> None:
question = "Let's think step by step. " + question
index = faiss.read_index("docs.index")
with open("db.pkl", "rb") as f:
vector_db = pickle.load(f)
vector_db.index = index
chain = VectorDBQAWithSourcesChain.from_llm(
llm=OpenAI(temperature=0),
vectorstore=vector_db
)
result = chain({"question": question})
pprint(f"Question: {question}")
pprint(f"Answer: {result['answer']}")
pprint(f"Sources: {result['sources']}")
return (result['answer'], "References used:\n"+"\n".join(result['sources'].split(',')))
# client = slack_sdk.WebClient(token=SLACK_TOKEN)
# app = Flask(__name__)
# slack_event_adapter = SlackEventAdapter(SIGNING_SECRET, '/slack/events', app)
# slack_event_adapter.start()
# @slack_event_adapter.on('message')
# def message(payload):
# try:
# event = payload.get('event', {})
# text = event.get('text')
# cleantext = text.strip()
# if "iai:" in cleantext:
# print(cleantext)
# client.chat_postMessage(channel='#internal-ai',text='thinking...')
# resp = question(text)
# client.chat_postMessage(channel='#internal-ai',text=resp[0])
# client.chat_postMessage(channel='#internal-ai',text=resp[1])
# except Exception as err:
# print(err)
# pass
if __name__ == "__main__":
# ingest() #run this first
# parser = argparse.ArgumentParser(description='Ask a question.')
# parser.add_argument('question', type=str)
# args = parser.parse_args()
# question(args.question)
appdemo = gr.Interface(title="InternalAI v0.1",description="InternalAI is an internal business intelligence tool that gathers information across all sources of knowledge at a company (Notion, Slack, etc) and lets employees easily ask for answers.", fn=question, inputs=gr.Textbox(placeholder="Ask InternalAI a question here..."), outputs=["text","text"], allow_flagging="auto", examples=["How much am I allowed to expense for dinner in the office, and where do I report those expenses? How about at events?", "Which todos are left in our Social Media Monitoring project?", "Who should I contact about the coffee machine and stocking extra flavors?"], article='<h2>FFMPEG co\'s Knowledge Sources</h1> <div>Notion: <a href="https://mixolydian-earl-c34.notion.site/FFMPEG-Company-Home-c8b76f986e2c4e4ab289fdd72627e50c">Link to FFMPEG co\'s Notion Homepage</a></div><h2>Here\'s a video showing the efficacy of InternalAI when compared to searching across Slack, Notion and Google Docs manually.</h1> <iframe width="560" height="315" src="https://www.youtube.com/watch?v=k4VheAF8krI" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>')
# print("FOR SLACK to WORK YOU MUST RUN LOCALTUNNEL (on port 5000 where flask runs) and then change the request URL in slack settings to https://LOCALTUNNELGIVENURL.loca.lt/slack/events")
# flask_thread = Thread(target=app.run,kwargs={'debug':False})
# flask_thread.start()
# appdemo.launch(share=True)
# flask_thread.join()
# appdemo.launch(share=True)
appdemo.launch()
# app.run(debug=True)