BGarida commited on
Commit
05f5dd5
·
1 Parent(s): 4b788e3

Deploying Pythonic RAG4

Browse files
Files changed (3) hide show
  1. app 5.py +141 -0
  2. app.py +81 -100
  3. app3.py +0 -122
app 5.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from typing import List
3
+
4
+ from langchain.embeddings.openai import OpenAIEmbeddings
5
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
6
+ from langchain.vectorstores import Chroma
7
+ from langchain.chains import (
8
+ ConversationalRetrievalChain,
9
+ )
10
+ from langchain.document_loaders import PyPDFLoader
11
+ from langchain.chat_models import ChatOpenAI
12
+ from langchain.prompts.chat import (
13
+ ChatPromptTemplate,
14
+ SystemMessagePromptTemplate,
15
+ HumanMessagePromptTemplate,
16
+ )
17
+ from langchain.docstore.document import Document
18
+ from langchain.memory import ChatMessageHistory, ConversationBufferMemory
19
+ from chainlit.types import AskFileResponse
20
+
21
+ import chainlit as cl
22
+
23
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=100)
24
+
25
+ system_template = """Use the following pieces of context to answer the users question.
26
+ If you don't know the answer, just say that you don't know, don't try to make up an answer.
27
+ ALWAYS return a "SOURCES" part in your answer.
28
+ The "SOURCES" part should be a reference to the source of the document from which you got your answer.
29
+ And if the user greets with greetings like Hi, hello, How are you, etc reply accordingly as well.
30
+ Example of your response should be:
31
+ The answer is foo
32
+ SOURCES: xyz
33
+ Begin!
34
+ ----------------
35
+ {summaries}"""
36
+ messages = [
37
+ SystemMessagePromptTemplate.from_template(system_template),
38
+ HumanMessagePromptTemplate.from_template("{question}"),
39
+ ]
40
+ prompt = ChatPromptTemplate.from_messages(messages)
41
+ chain_type_kwargs = {"prompt": prompt}
42
+
43
+
44
+ def process_file(file: AskFileResponse):
45
+ import tempfile
46
+
47
+ with tempfile.NamedTemporaryFile(mode="w", delete=False) as tempfile:
48
+ with open(tempfile.name, "wb") as f:
49
+ f.write(file.content)
50
+
51
+ pypdf_loader = PyPDFLoader(tempfile.name)
52
+ texts = pypdf_loader.load_and_split()
53
+ texts = [text.page_content for text in texts]
54
+ return texts
55
+
56
+
57
+ @cl.on_chat_start
58
+ async def on_chat_start():
59
+ files = None
60
+
61
+ # Wait for the user to upload a file
62
+ while files == None:
63
+ files = await cl.AskFileMessage(
64
+ content="Please upload a PDF file to begin!",
65
+ accept=["application/pdf"],
66
+ max_size_mb=20,
67
+ timeout=180,
68
+ ).send()
69
+
70
+ file = files[0]
71
+
72
+ msg = cl.Message(
73
+ content=f"Processing `{file.name}`...", disable_human_feedback=True
74
+ )
75
+ await msg.send()
76
+
77
+ # load the file
78
+ texts = process_file(file)
79
+
80
+ print(texts[0])
81
+
82
+ # Create a metadata for each chunk
83
+ metadatas = [{"source": f"{i}-pl"} for i in range(len(texts))]
84
+
85
+ # Create a Chroma vector store
86
+ embeddings = OpenAIEmbeddings()
87
+ docsearch = await cl.make_async(Chroma.from_texts)(
88
+ texts, embeddings, metadatas=metadatas
89
+ )
90
+
91
+ message_history = ChatMessageHistory()
92
+
93
+ memory = ConversationBufferMemory(
94
+ memory_key="chat_history",
95
+ output_key="answer",
96
+ chat_memory=message_history,
97
+ return_messages=True,
98
+ )
99
+
100
+ # Create a chain that uses the Chroma vector store
101
+ chain = ConversationalRetrievalChain.from_llm(
102
+ ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0, streaming=True),
103
+ chain_type="stuff",
104
+ retriever=docsearch.as_retriever(),
105
+ memory=memory,
106
+ return_source_documents=True,
107
+ )
108
+
109
+ # Let the user know that the system is ready
110
+ msg.content = f"Processing `{file.name}` done. You can now ask questions!"
111
+ await msg.update()
112
+
113
+ cl.user_session.set("chain", chain)
114
+
115
+
116
+ @cl.on_message
117
+ async def main(message):
118
+ chain = cl.user_session.get("chain") # type: ConversationalRetrievalChain
119
+ cb = cl.AsyncLangchainCallbackHandler()
120
+
121
+ res = await chain.acall(message.content, callbacks=[cb])
122
+ answer = res["answer"]
123
+ source_documents = res["source_documents"] # type: List[Document]
124
+
125
+ text_elements = [] # type: List[cl.Text]
126
+
127
+ if source_documents:
128
+ for source_idx, source_doc in enumerate(source_documents):
129
+ source_name = f"source_{source_idx}"
130
+ # Create the text element referenced in the message
131
+ text_elements.append(
132
+ cl.Text(content=source_doc.page_content, name=source_name)
133
+ )
134
+ source_names = [text_el.name for text_el in text_elements]
135
+
136
+ if source_names:
137
+ answer += f"\nSources: {', '.join(source_names)}"
138
+ else:
139
+ answer += "\nNo sources found"
140
+
141
+ await cl.Message(content=answer, elements=text_elements).send()
app.py CHANGED
@@ -1,56 +1,67 @@
1
  import os
2
  from typing import List
3
-
4
- from langchain.embeddings.openai import OpenAIEmbeddings
5
- from langchain.text_splitter import RecursiveCharacterTextSplitter
6
- from langchain.vectorstores import Chroma
7
- from langchain.chains import (
8
- ConversationalRetrievalChain,
9
- )
10
- from langchain.document_loaders import PyPDFLoader
11
- from langchain.chat_models import ChatOpenAI
12
- from langchain.prompts.chat import (
13
- ChatPromptTemplate,
14
- SystemMessagePromptTemplate,
15
- HumanMessagePromptTemplate,
16
- )
17
- from langchain.docstore.document import Document
18
- from langchain.memory import ChatMessageHistory, ConversationBufferMemory
19
  from chainlit.types import AskFileResponse
20
-
 
 
 
 
 
 
 
 
21
  import chainlit as cl
22
 
23
- text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=100)
24
-
25
- system_template = """Use the following pieces of context to answer the users question.
26
- If you don't know the answer, just say that you don't know, don't try to make up an answer.
27
- ALWAYS return a "SOURCES" part in your answer.
28
- The "SOURCES" part should be a reference to the source of the document from which you got your answer.
29
- And if the user greets with greetings like Hi, hello, How are you, etc reply accordingly as well.
30
- Example of your response should be:
31
- The answer is foo
32
- SOURCES: xyz
33
- Begin!
34
- ----------------
35
- {summaries}"""
36
- messages = [
37
- SystemMessagePromptTemplate.from_template(system_template),
38
- HumanMessagePromptTemplate.from_template("{question}"),
39
- ]
40
- prompt = ChatPromptTemplate.from_messages(messages)
41
- chain_type_kwargs = {"prompt": prompt}
42
-
43
-
44
- def process_file(file: AskFileResponse):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  import tempfile
46
 
47
- with tempfile.NamedTemporaryFile(mode="w", delete=False) as tempfile:
48
- with open(tempfile.name, "wb") as f:
49
- f.write(file.content)
 
 
50
 
51
- pypdf_loader = PyPDFLoader(tempfile.name)
52
- texts = pypdf_loader.load_and_split()
53
- texts = [text.page_content for text in texts]
54
  return texts
55
 
56
 
@@ -61,9 +72,9 @@ async def on_chat_start():
61
  # Wait for the user to upload a file
62
  while files == None:
63
  files = await cl.AskFileMessage(
64
- content="Please upload a PDF file to begin!",
65
- accept=["application/pdf"],
66
- max_size_mb=20,
67
  timeout=180,
68
  ).send()
69
 
@@ -75,67 +86,37 @@ async def on_chat_start():
75
  await msg.send()
76
 
77
  # load the file
78
- texts = process_file(file)
79
 
80
- print(texts[0])
81
-
82
- # Create a metadata for each chunk
83
- metadatas = [{"source": f"{i}-pl"} for i in range(len(texts))]
84
-
85
- # Create a Chroma vector store
86
- embeddings = OpenAIEmbeddings()
87
- docsearch = await cl.make_async(Chroma.from_texts)(
88
- texts, embeddings, metadatas=metadatas
89
- )
90
 
91
- message_history = ChatMessageHistory()
 
 
 
 
92
 
93
- memory = ConversationBufferMemory(
94
- memory_key="chat_history",
95
- output_key="answer",
96
- chat_memory=message_history,
97
- return_messages=True,
98
  )
99
-
100
- # Create a chain that uses the Chroma vector store
101
- chain = ConversationalRetrievalChain.from_llm(
102
- ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0, streaming=True),
103
- chain_type="stuff",
104
- retriever=docsearch.as_retriever(),
105
- memory=memory,
106
- return_source_documents=True,
107
- )
108
-
109
  # Let the user know that the system is ready
110
  msg.content = f"Processing `{file.name}` done. You can now ask questions!"
111
  await msg.update()
112
 
113
- cl.user_session.set("chain", chain)
114
 
115
 
116
  @cl.on_message
117
  async def main(message):
118
- chain = cl.user_session.get("chain") # type: ConversationalRetrievalChain
119
- cb = cl.AsyncLangchainCallbackHandler()
120
-
121
- res = await chain.acall(message.content, callbacks=[cb])
122
- answer = res["answer"]
123
- source_documents = res["source_documents"] # type: List[Document]
124
-
125
- text_elements = [] # type: List[cl.Text]
126
-
127
- if source_documents:
128
- for source_idx, source_doc in enumerate(source_documents):
129
- source_name = f"source_{source_idx}"
130
- # Create the text element referenced in the message
131
- text_elements.append(
132
- cl.Text(content=source_doc.page_content, name=source_name)
133
- )
134
- source_names = [text_el.name for text_el in text_elements]
135
-
136
- if source_names:
137
- answer += f"\nSources: {', '.join(source_names)}"
138
- else:
139
- answer += "\nNo sources found"
140
-
141
- await cl.Message(content=answer, elements=text_elements).send()
 
1
  import os
2
  from typing import List
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  from chainlit.types import AskFileResponse
4
+ from aimakerspace.text_utils import CharacterTextSplitter, TextFileLoader
5
+ from aimakerspace.openai_utils.prompts import (
6
+ UserRolePrompt,
7
+ SystemRolePrompt,
8
+ AssistantRolePrompt,
9
+ )
10
+ from aimakerspace.openai_utils.embedding import EmbeddingModel
11
+ from aimakerspace.vectordatabase import VectorDatabase
12
+ from aimakerspace.openai_utils.chatmodel import ChatOpenAI
13
  import chainlit as cl
14
 
15
+ system_template = """\
16
+ Use the following context to answer a users question. If you cannot find the answer in the context, say you don't know the answer."""
17
+ system_role_prompt = SystemRolePrompt(system_template)
18
+
19
+ user_prompt_template = """\
20
+ Context:
21
+ {context}
22
+
23
+ Question:
24
+ {question}
25
+ """
26
+ user_role_prompt = UserRolePrompt(user_prompt_template)
27
+
28
+ class RetrievalAugmentedQAPipeline:
29
+ def __init__(self, llm: ChatOpenAI(), vector_db_retriever: VectorDatabase) -> None:
30
+ self.llm = llm
31
+ self.vector_db_retriever = vector_db_retriever
32
+
33
+ async def arun_pipeline(self, user_query: str):
34
+ context_list = self.vector_db_retriever.search_by_text(user_query, k=4)
35
+
36
+ context_prompt = ""
37
+ for context in context_list:
38
+ context_prompt += context[0] + "\n"
39
+
40
+ formatted_system_prompt = system_role_prompt.create_message()
41
+
42
+ formatted_user_prompt = user_role_prompt.create_message(question=user_query, context=context_prompt)
43
+
44
+ async def generate_response():
45
+ async for chunk in self.llm.astream([formatted_system_prompt, formatted_user_prompt]):
46
+ yield chunk
47
+
48
+ return {"response": generate_response(), "context": context_list}
49
+
50
+ text_splitter = CharacterTextSplitter()
51
+
52
+
53
+ def process_text_file(file: AskFileResponse):
54
  import tempfile
55
 
56
+ with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".txt") as temp_file:
57
+ temp_file_path = temp_file.name
58
+
59
+ with open(temp_file_path, "wb") as f:
60
+ f.write(file.content)
61
 
62
+ text_loader = TextFileLoader(temp_file_path)
63
+ documents = text_loader.load_documents()
64
+ texts = text_splitter.split_texts(documents)
65
  return texts
66
 
67
 
 
72
  # Wait for the user to upload a file
73
  while files == None:
74
  files = await cl.AskFileMessage(
75
+ content="Please upload a Text File file to begin!",
76
+ accept=["text/plain"],
77
+ max_size_mb=2,
78
  timeout=180,
79
  ).send()
80
 
 
86
  await msg.send()
87
 
88
  # load the file
89
+ texts = process_text_file(file)
90
 
91
+ print(f"Processing {len(texts)} text chunks")
 
 
 
 
 
 
 
 
 
92
 
93
+ # Create a dict vector store
94
+ vector_db = VectorDatabase()
95
+ vector_db = await vector_db.abuild_from_list(texts)
96
+
97
+ chat_openai = ChatOpenAI()
98
 
99
+ # Create a chain
100
+ retrieval_augmented_qa_pipeline = RetrievalAugmentedQAPipeline(
101
+ vector_db_retriever=vector_db,
102
+ llm=chat_openai
 
103
  )
104
+
 
 
 
 
 
 
 
 
 
105
  # Let the user know that the system is ready
106
  msg.content = f"Processing `{file.name}` done. You can now ask questions!"
107
  await msg.update()
108
 
109
+ cl.user_session.set("chain", retrieval_augmented_qa_pipeline)
110
 
111
 
112
  @cl.on_message
113
  async def main(message):
114
+ chain = cl.user_session.get("chain")
115
+
116
+ msg = cl.Message(content="")
117
+ result = await chain.arun_pipeline(message.content)
118
+
119
+ async for stream_resp in result["response"]:
120
+ await msg.stream_token(stream_resp)
121
+
122
+ await msg.send()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app3.py DELETED
@@ -1,122 +0,0 @@
1
- import os
2
- from typing import List
3
- from chainlit.types import AskFileResponse
4
- from aimakerspace.text_utils import CharacterTextSplitter, TextFileLoader
5
- from aimakerspace.openai_utils.prompts import (
6
- UserRolePrompt,
7
- SystemRolePrompt,
8
- AssistantRolePrompt,
9
- )
10
- from aimakerspace.openai_utils.embedding import EmbeddingModel
11
- from aimakerspace.vectordatabase import VectorDatabase
12
- from aimakerspace.openai_utils.chatmodel import ChatOpenAI
13
- import chainlit as cl
14
-
15
- system_template = """\
16
- Use the following context to answer a users question. If you cannot find the answer in the context, say you don't know the answer."""
17
- system_role_prompt = SystemRolePrompt(system_template)
18
-
19
- user_prompt_template = """\
20
- Context:
21
- {context}
22
-
23
- Question:
24
- {question}
25
- """
26
- user_role_prompt = UserRolePrompt(user_prompt_template)
27
-
28
- class RetrievalAugmentedQAPipeline:
29
- def __init__(self, llm: ChatOpenAI(), vector_db_retriever: VectorDatabase) -> None:
30
- self.llm = llm
31
- self.vector_db_retriever = vector_db_retriever
32
-
33
- async def arun_pipeline(self, user_query: str):
34
- context_list = self.vector_db_retriever.search_by_text(user_query, k=4)
35
-
36
- context_prompt = ""
37
- for context in context_list:
38
- context_prompt += context[0] + "\n"
39
-
40
- formatted_system_prompt = system_role_prompt.create_message()
41
-
42
- formatted_user_prompt = user_role_prompt.create_message(question=user_query, context=context_prompt)
43
-
44
- async def generate_response():
45
- async for chunk in self.llm.astream([formatted_system_prompt, formatted_user_prompt]):
46
- yield chunk
47
-
48
- return {"response": generate_response(), "context": context_list}
49
-
50
- text_splitter = CharacterTextSplitter()
51
-
52
-
53
- def process_text_file(file: AskFileResponse):
54
- import tempfile
55
-
56
- with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".txt") as temp_file:
57
- temp_file_path = temp_file.name
58
-
59
- with open(temp_file_path, "wb") as f:
60
- f.write(file.content)
61
-
62
- text_loader = TextFileLoader(temp_file_path)
63
- documents = text_loader.load_documents()
64
- texts = text_splitter.split_texts(documents)
65
- return texts
66
-
67
-
68
- @cl.on_chat_start
69
- async def on_chat_start():
70
- files = None
71
-
72
- # Wait for the user to upload a file
73
- while files == None:
74
- files = await cl.AskFileMessage(
75
- content="Please upload a Text File file to begin!",
76
- accept=["text/plain"],
77
- max_size_mb=2,
78
- timeout=180,
79
- ).send()
80
-
81
- file = files[0]
82
-
83
- msg = cl.Message(
84
- content=f"Processing `{file.name}`...", disable_human_feedback=True
85
- )
86
- await msg.send()
87
-
88
- # load the file
89
- texts = process_text_file(file)
90
-
91
- print(f"Processing {len(texts)} text chunks")
92
-
93
- # Create a dict vector store
94
- vector_db = VectorDatabase()
95
- vector_db = await vector_db.abuild_from_list(texts)
96
-
97
- chat_openai = ChatOpenAI()
98
-
99
- # Create a chain
100
- retrieval_augmented_qa_pipeline = RetrievalAugmentedQAPipeline(
101
- vector_db_retriever=vector_db,
102
- llm=chat_openai
103
- )
104
-
105
- # Let the user know that the system is ready
106
- msg.content = f"Processing `{file.name}` done. You can now ask questions!"
107
- await msg.update()
108
-
109
- cl.user_session.set("chain", retrieval_augmented_qa_pipeline)
110
-
111
-
112
- @cl.on_message
113
- async def main(message):
114
- chain = cl.user_session.get("chain")
115
-
116
- msg = cl.Message(content="")
117
- result = await chain.arun_pipeline(message.content)
118
-
119
- async for stream_resp in result["response"]:
120
- await msg.stream_token(stream_resp)
121
-
122
- await msg.send()