-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path3_rag_v2.py
More file actions
82 lines (63 loc) · 2.77 KB
/
3_rag_v2.py
File metadata and controls
82 lines (63 loc) · 2.77 KB
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
# pip install -U langchain langchain-openai langchain-community faiss-cpu pypdf python-dotenv langsmith
import os
from dotenv import load_dotenv
from langsmith import traceable # <-- key import
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_community.vectorstores import FAISS
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableParallel, RunnablePassthrough, RunnableLambda
from langchain_core.output_parsers import StrOutputParser
os.environ['LANGCHAIN_PROJECT'] = 'RAG ChatBot'
load_dotenv()
PDF_PATH = "islr.pdf" # change to your file
# ---------- traced setup steps ----------
@traceable(name="load_pdf",tags=['pdf','loader'],metadata={'loader':'PyPDFLoader'})
def load_pdf(path: str):
loader = PyPDFLoader(path)
return loader.load() # list[Document]
@traceable(name="split_documents")
def split_documents(docs, chunk_size=1000, chunk_overlap=150):
splitter = RecursiveCharacterTextSplitter(
chunk_size=chunk_size, chunk_overlap=chunk_overlap
)
return splitter.split_documents(docs)
@traceable(name="build_vectorstore", tags=['embedding','vectorstore'],metadata={'embedding-model':'text-embedding-3-small'})
def build_vectorstore(splits):
emb = OpenAIEmbeddings(model="text-embedding-3-small")
# FAISS.from_documents internally calls the embedding model:
vs = FAISS.from_documents(splits, emb)
return vs
# You can also trace a “setup” umbrella span if you want:
@traceable(name="setup_pipeline")
def setup_pipeline(pdf_path: str):
docs = load_pdf(pdf_path)
splits = split_documents(docs)
vs = build_vectorstore(splits)
return vs
# ---------- pipeline ----------
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
prompt = ChatPromptTemplate.from_messages([
("system", "Answer ONLY from the provided context. If not found, say you don't know."),
("human", "Question: {question}\n\nContext:\n{context}")
])
def format_docs(docs):
return "\n\n".join(d.page_content for d in docs)
# Build the index under traced setup
vectorstore = setup_pipeline(PDF_PATH)
retriever = vectorstore.as_retriever(search_type="similarity", search_kwargs={"k": 4})
parallel = RunnableParallel({
"context": retriever | RunnableLambda(format_docs),
"question": RunnablePassthrough(),
})
chain = parallel | prompt | llm | StrOutputParser()
# ---------- run a query (also traced) ----------
print("PDF RAG ready. Ask a question (or Ctrl+C to exit).")
q = input("\nQ: ").strip()
# Give the visible run name + tags/metadata so it’s easy to find:
config = {
"run_name": "pdf_rag_query"
}
ans = chain.invoke(q, config=config)
print("\nA:", ans)