Spaces:
Sleeping
Sleeping
File size: 3,664 Bytes
b20c196 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
import os
import chainlit as cl
import tiktoken
import openai
from dotenv import load_dotenv
from operator import itemgetter
from langchain_openai import ChatOpenAI
from langchain import text_splitter
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import PyMuPDFLoader
from langchain_community.embeddings import OpenAIEmbeddings
from langchain_community.vectorstores import Qdrant
from langchain.prompts import ChatPromptTemplate
from langchain.chat_models import ChatOpenAI
from operator import itemgetter
from langchain.schema.runnable import RunnablePassthrough
# GLOBAL SCOPE - ENTIRE APPLICATION HAS ACCESS TO VALUES SET IN THIS SCOPE #
# ---- ENV VARIABLES ---- #
load_dotenv()
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
# Initialize OpenAI client after loading the environment variables
openai.api_key = OPENAI_API_KEY
# -- RETRIEVAL -- #
"""
1. Load Documents from Text File
2. Split Documents into Chunks
3. Push files into our vectorstore
"""
### 1. CREATE TEXT LOADER AND LOAD DOCUMENTS
source_file = PyMuPDFLoader("./data/airbnb-10k.pdf")
loaded_file = source_file.load()
def tiktoken_len(text):
tokens = tiktoken.encoding_for_model("gpt-4o").encode(text)
return len(tokens)
text_splitter = RecursiveCharacterTextSplitter(
chunk_size = 100,
chunk_overlap = 30,
length_function = tiktoken_len,
)
chunks = text_splitter.split_documents(loaded_file)
#-----Embedding and Vector Store Setup-----#
# Load OpenAI Embeddings Model
embeddings = OpenAIEmbeddings(model="text-embedding-3-large")
# Creating Qdrant Vector Store
qdrant_vector_store = Qdrant.from_documents(
chunks,
embeddings,
location=":memory:",
collection_name="airbnbdocs",
)
# Create a Retriever
retriever = qdrant_vector_store.as_retriever()
#-----Prompt Template and Language Model Setup-----#
# Define the prompt template
template = """Answer the query from the user based only on the context provided. \n
If you cannot answer the question with the context, please respond with 'I don't believe I have the answer to that question, could you try asking it again in a different way?'.
Please also provide examples form the context material that illustrate how you came to your answer.
Context:
{context}
Question:
{question}
"""
prompt = ChatPromptTemplate.from_template(template)
chat_llm = ChatOpenAI(model_name="gpt-4o", temperature=0)
retrieval_augmented_qa_chain = (
{"context": itemgetter("question") | retriever, "question": itemgetter("question")}
| RunnablePassthrough.assign(context=itemgetter("context"))
| {"response": prompt | chat_llm, "context": itemgetter("context")}
)
#-----Chainlit Integration-----#
@cl.on_chat_start
async def start_chat():
settings = {
"model": "gpt-4o",
"temperature": 0,
"max_tokens": 500,
"top_p": 1,
"frequency_penalty": 0,
"presence_penalty": 0,
}
cl.user_session.set("settings", settings)
# Processes incoming messages from the user and sends a response through a series of steps:
# (1) Retrieves the user's settings
# (2) Invokes the RAG chain with the user's message
# (3) Extracts the content from the response and sends it back to the user
@cl.on_message
async def handle_message(message: cl.Message):
settings = cl.user_session.get("settings")
response = retrieval_augmented_qa_chain.invoke({"question": message.content})
# Extracting and sending just the content
content = response["response"].content
pretty_content = content.strip() # Remove any leading/trailing whitespace
await cl.Message(content=pretty_content).send()
|