JoshuaKelleyDs commited on
Commit
c63c9d3
1 Parent(s): 75db28a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +65 -56
app.py CHANGED
@@ -10,6 +10,66 @@ from langchain_community.retrievers import BM25Retriever # for the BM25 retrieve
10
  from langchain.retrievers.ensemble import EnsembleRetriever # for the ensemble retriever
11
  from langchain_text_splitters import RecursiveCharacterTextSplitter # for the text splitter
12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  async def create_youtube_transcription(youtube_url: str) -> List[langchain_core.documents.Document]:
14
  """
15
  Create a youtube transcription from a youtube url
@@ -28,7 +88,10 @@ async def create_youtube_transcription(youtube_url: str) -> List[langchain_core.
28
  except Exception as e:
29
  await cl.Message(content=f"failed to load youtube video: {e} Please refresh the page").send() # display the error if we failed to load the youtube video
30
 
31
- async def create_text_splitter(docs: List[langchain_core.documents.Document]):
 
 
 
32
  """
33
  Create a text splitter from a list of documents
34
  More Info: ument_transformers/recursive_text_splitter/
@@ -88,58 +151,4 @@ async def create_ensemble_retriever(vector_db:FAISS, bm25:BM25Retriever) -> Ense
88
  ensemble_retreiver = EnsembleRetriever(retrievers=[vector_db.as_retriever(), bm25], weights=[.3, .7]) # 30% semantic, 70% keyword retrieval
89
  return ensemble_retreiver
90
  except Exception as e:
91
- await cl.Message(content=f"failed to create ensemble retriever: {e}").send() # display the error if we failed to create the ensemble retriever
92
-
93
- @cl.on_chat_start
94
- async def start():
95
- """
96
- More info: https://docs.chainlit.io/api-reference/lifecycle-hooks/on-chat-start
97
- This function is called when the chat starts. Under the hood it handles all the complicated stuff for loading the UI.
98
- We explicitly load the model, embeddings, and retrievers.
99
- Asks the user to provide the YouTube video link and loads the transcription.
100
- With the transcription, it creates a vector store and a BM25 vector store. That is used to create an ensemble retriever combining the two.
101
- """
102
- await cl.Message(content="Hello! I am your AI assistant. I can help you with your questions about the video you provide.").send()
103
- try: # a try catch block prevents the app from crashing if have an error
104
- llm = ChatTogether(model="meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo") # initialize the LLM model
105
- await cl.Message(content=f"model is successfully loaded").send() # we can send messages to be displayed with cl.Message().send()
106
- cl.user_session.set("llm", llm) # we can store variables in a special memory called the user session, so we can use them in our on message function and more
107
- embedding = TogetherEmbeddings(model="togethercomputer/m2-bert-80M-8k-retrieval") # initialize the embedding model
108
- cl.user_session.set("embedding", embedding) # store the embedding model in the user session
109
- await cl.Message(content="embedding model loaded").send()
110
- youtube_link = await cl.AskUserMessage("Please provide the YouTube video link").send() # We can ask the user for input using cl.AskUserMessage().send() which does not affect cl.on_message()
111
- # more on ask user message: https://docs.chainlit.io/api-reference/ask/ask-for-input
112
- await cl.Message(content=f"youtube link: {youtube_link['content']}").send() # display and double check to make sure the link is correct
113
- youtube_docs = await create_youtube_transcription(youtube_link['content']) # create the youtube transcription
114
- transcription = youtube_docs # get the transcription of the first document
115
- await cl.Message(content=f"youtube docs: {transcription}").send() # display the transcription of the first document to show that we have the correct data
116
- split_docs = await create_text_splitter(youtube_docs) # split the documents into chunks
117
- vector_db = await create_faiss_vector_store(split_docs) # create the vector db
118
- bm25 = await create_bm25_retreiver(split_docs) # create the BM25 retreiver
119
- ensemble_retriever = await create_ensemble_retriever(vector_db, bm25) # create the ensemble retriever
120
- cl.user_session.set("ensemble_retriever", ensemble_retriever) # store the ensemble retriever in the user session for our on message function
121
- except Exception as e:
122
- await cl.Message(content=f"error that happened: {e}").send() # display the error if we failed to load the model
123
-
124
- @cl.on_message
125
- async def message(message: cl.Message):
126
- """
127
- More info: https://docs.chainlit.io/api-reference/lifecycle-hooks/on-message
128
- This function is called when the user sends a message. It uses the ensemble retriever to find the most relevant documents and feeds them into the LLM.
129
- We can then display the answer and the relevant documents to the user.
130
- """
131
- prompt_template = ChatPromptTemplate.from_template(template="""
132
- You are a helpful assistant that can answer questions about the following video. Here is the appropriate chunks of context: {context}.
133
- Answer the question: {question} but do not use any information outside of the video. Site the source or information you used to answer the question
134
- """) # we create a prompt template that we will use to format our prompt
135
- llm = cl.user_session.get("llm") # we get the LLM model we initialized in the start function
136
- ensemble_retriever = cl.user_session.get("ensemble_retriever") # we get the ensemble retriever we initialized in the start function
137
- relevant_docs = ensemble_retriever.invoke(message.content) # we use the ensemble retriever to find the most relevant documents
138
- cl.Message(content=f"Displaying Relevant Docs").send() # we display the relevant documents to the user
139
- for doc in relevant_docs: # loop through the relevant documents and display each one!
140
- await cl.Message(content=doc.page_content).send()
141
- await cl.Message(content="Done Displaying Relevant Docs").send()
142
- # question -> retrieve relevant docs -> format the question and context and add it to the prompt template -> pass to LLM
143
- rag_chain = RunnableSequence({"context": ensemble_retriever, "question": RunnablePassthrough()} | prompt_template | llm)
144
- response = rag_chain.invoke(message.content) # we invoke the rag chain with the user's message
145
- await cl.Message(content=f"LLM Response: {response.content}").send() # we display the response to the user
 
10
  from langchain.retrievers.ensemble import EnsembleRetriever # for the ensemble retriever
11
  from langchain_text_splitters import RecursiveCharacterTextSplitter # for the text splitter
12
 
13
+
14
+
15
+ ######## Chainlit ########
16
+ @cl.on_chat_start
17
+ async def start():
18
+ """
19
+ More info: https://docs.chainlit.io/api-reference/lifecycle-hooks/on-chat-start
20
+ This function is called when the chat starts. Under the hood it handles all the complicated stuff for loading the UI.
21
+ We explicitly load the model, embeddings, and retrievers.
22
+ Asks the user to provide the YouTube video link and loads the transcription.
23
+ With the transcription, it creates a vector store and a BM25 vector store. That is used to create an ensemble retriever combining the two.
24
+ """
25
+ await cl.Message(content="Hello! I am your AI assistant. I can help you with your questions about the video you provide.").send()
26
+ try: # a try catch block prevents the app from crashing if have an error
27
+ llm = ChatTogether(model="meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo") # initialize the LLM model
28
+ await cl.Message(content=f"model is successfully loaded").send() # we can send messages to be displayed with cl.Message().send()
29
+ cl.user_session.set("llm", llm) # we can store variables in a special memory called the user session, so we can use them in our on message function and more
30
+ embedding = TogetherEmbeddings(model="togethercomputer/m2-bert-80M-8k-retrieval") # initialize the embedding model
31
+ cl.user_session.set("embedding", embedding) # store the embedding model in the user session
32
+ await cl.Message(content="embedding model loaded").send()
33
+ youtube_link = await cl.AskUserMessage("Please provide the YouTube video link").send() # We can ask the user for input using cl.AskUserMessage().send() which does not affect cl.on_message()
34
+ # more on ask user message: https://docs.chainlit.io/api-reference/ask/ask-for-input
35
+
36
+ await cl.Message(content=f"youtube link: {youtube_link['content']}").send() # display and double check to make sure the link is correct
37
+ youtube_docs = await create_youtube_transcription(youtube_link['content']) # create the youtube transcription
38
+ transcription = youtube_docs # get the transcription of the first document
39
+ await cl.Message(content=f"youtube docs: {transcription}").send() # display the transcription of the first document to show that we have the correct data
40
+ split_docs = await create_text_splitter(youtube_docs) # split the documents into chunks
41
+ vector_db = await create_faiss_vector_store(split_docs) # create the vector db
42
+ bm25 = await create_bm25_retreiver(split_docs) # create the BM25 retreiver
43
+ ensemble_retriever = await create_ensemble_retriever(vector_db, bm25) # create the ensemble retriever
44
+ cl.user_session.set("ensemble_retriever", ensemble_retriever) # store the ensemble retriever in the user session for our on message function
45
+ except Exception as e:
46
+ await cl.Message(content=f"failed to load model: {e}").send() # display the error if we failed to load the model
47
+
48
+ @cl.on_message
49
+ async def message(message: cl.Message):
50
+ """
51
+ More info: https://docs.chainlit.io/api-reference/lifecycle-hooks/on-message
52
+ This function is called when the user sends a message. It uses the ensemble retriever to find the most relevant documents and feeds them into the LLM.
53
+ We can then display the answer and the relevant documents to the user.
54
+ """
55
+ prompt_template = ChatPromptTemplate.from_template(template="""
56
+ You are a helpful assistant that can answer questions about the following video. Here is the appropriate chunks of context: {context}.
57
+ Answer the question: {question} but do not use any information outside of the video. Site the source or information you used to answer the question
58
+ """) # we create a prompt template that we will use to format our prompt
59
+ llm = cl.user_session.get("llm") # we get the LLM model we initialized in the start function
60
+ ensemble_retriever = cl.user_session.get("ensemble_retriever") # we get the ensemble retriever we initialized in the start function
61
+ relevant_docs = ensemble_retriever.invoke(message.content) # we use the ensemble retriever to find the most relevant documents
62
+ cl.Message(content=f"Displaying Relevant Docs").send() # we display the relevant documents to the user
63
+ for doc in relevant_docs: # loop through the relevant documents and display each one!
64
+ await cl.Message(content=doc.page_content).send()
65
+ await cl.Message(content="Done Displaying Relevant Docs").send()
66
+ # question -> retrieve relevant docs -> format the question and context and add it to the prompt template -> pass to LLM
67
+ rag_chain = RunnableSequence({"context": ensemble_retriever, "question": RunnablePassthrough()} | prompt_template | llm)
68
+ response = rag_chain.invoke(message.content) # we invoke the rag chain with the user's message
69
+ await cl.Message(content=f"LLM Response: {response.content}").send() # we display the response to the user
70
+
71
+ ######## Youtube ########
72
+
73
  async def create_youtube_transcription(youtube_url: str) -> List[langchain_core.documents.Document]:
74
  """
75
  Create a youtube transcription from a youtube url
 
88
  except Exception as e:
89
  await cl.Message(content=f"failed to load youtube video: {e} Please refresh the page").send() # display the error if we failed to load the youtube video
90
 
91
+
92
+ ######## RAG ########
93
+
94
+ async def create_text_splitter(docs: List[langchain_core.documents.Document]) -> List[langchain_core.documents.Document]:
95
  """
96
  Create a text splitter from a list of documents
97
  More Info: ument_transformers/recursive_text_splitter/
 
151
  ensemble_retreiver = EnsembleRetriever(retrievers=[vector_db.as_retriever(), bm25], weights=[.3, .7]) # 30% semantic, 70% keyword retrieval
152
  return ensemble_retreiver
153
  except Exception as e:
154
+ await cl.Message(content=f"failed to create ensemble retriever: {e}").send() # display the error if we failed to create the ensemble retriever