Abdul2000 commited on
Commit
f183df0
Β·
verified Β·
1 Parent(s): 006a40d

Update src/rag_pipeline.py

Browse files
Files changed (1) hide show
  1. src/rag_pipeline.py +17 -95
src/rag_pipeline.py CHANGED
@@ -1,50 +1,17 @@
1
  """
2
- rag_pipeline.py
3
- ---------------
4
- Ties together the retriever and the LLM to answer user questions.
5
-
6
- RAG in plain English
7
- 1. The user asks a question.
8
- 2. We convert the question to an embedding (same model used for documents).
9
- 3. FAISS finds the top-k document chunks whose embeddings are most similar.
10
- 4. We inject those chunks into a prompt as "context".
11
- 5. The LLM reads the context and generates an answer.
12
-
13
- This approach grounds the LLM's answer in YOUR documents rather than its
14
- general training data β€” which reduces hallucinations and keeps answers
15
- relevant.
16
-
17
- LLM options (set LLM_PROVIDER below):
18
- "openai" – uses OpenAI's API (requires OPENAI_API_KEY env variable)
19
- "ollama" – uses a locally running Ollama model (free, no API key needed)
20
  """
21
 
22
  import os
23
- from langchain_classic.chains import RetrievalQA
24
  from langchain_core.prompts import PromptTemplate
25
  from langchain_community.vectorstores import FAISS
26
 
27
- # ── configuration ─────────────────────────────────────────────────────────────
28
-
29
- # Choose your LLM backend: "groq", "openai", or "ollama"
30
- LLM_PROVIDER = os.getenv("LLM_PROVIDER", "openai").strip().lower()
31
-
32
- # Groq settings (only used when LLM_PROVIDER = "groq")
33
- GROQ_MODEL = os.getenv("GROQ_MODEL", "llama-3.1-8b-instant")
34
-
35
- # OpenAI settings (only used when LLM_PROVIDER = "openai")
36
- OPENAI_MODEL = os.getenv("OPENAI_MODEL", "gpt-3.5-turbo")
37
-
38
- # Ollama settings (only used when LLM_PROVIDER = "ollama")
39
- # Make sure Ollama is running: https://ollama.com/download
40
- OLLAMA_MODEL = os.getenv("OLLAMA_MODEL", "llama3")
41
  OLLAMA_BASE_URL = os.getenv("OLLAMA_BASE_URL", "http://localhost:11434")
42
 
43
-
44
- # ── prompt template ───────────────────────────────────────────────────────────
45
-
46
- # This prompt tells the LLM exactly what role to play and how to use
47
- # the retrieved context. Editing this string is a great way to experiment!
48
  RAG_PROMPT_TEMPLATE = """You are a helpful assistant that answers questions about
49
  Data Science interview preparation based only on the provided context.
50
 
@@ -64,20 +31,14 @@ PROMPT = PromptTemplate(
64
  )
65
 
66
 
67
- # ── LLM factory ───────────────────────────────────────────────────────────────
68
-
69
  def _get_llm():
70
- """
71
- Load and return the chosen LLM.
72
-
73
- Reads LLM_PROVIDER and instantiates the right LangChain wrapper.
74
- """
75
  if LLM_PROVIDER == "groq":
76
  api_key = os.getenv("GROQ_API_KEY")
77
  if not api_key:
78
  raise EnvironmentError(
79
- "GROQ_API_KEY environment variable is not set.\n"
80
- "Create a key at https://console.groq.com/keys and add it to .env."
 
81
  )
82
  from langchain_groq import ChatGroq
83
  print(f" Using Groq model: {GROQ_MODEL}")
@@ -86,82 +47,43 @@ def _get_llm():
86
  elif LLM_PROVIDER == "openai":
87
  api_key = os.getenv("OPENAI_API_KEY")
88
  if not api_key:
89
- raise EnvironmentError(
90
- "OPENAI_API_KEY environment variable is not set.\n"
91
- "Set it with: export OPENAI_API_KEY='sk-...'\n"
92
- "Or switch to Ollama by setting LLM_PROVIDER=ollama"
93
- )
94
  from langchain_openai import ChatOpenAI
95
  print(f" Using OpenAI model: {OPENAI_MODEL}")
96
  return ChatOpenAI(model_name=OPENAI_MODEL, temperature=0)
97
 
98
  elif LLM_PROVIDER == "ollama":
99
  from langchain_ollama import ChatOllama
100
- print(f" Using Ollama model: {OLLAMA_MODEL} at {OLLAMA_BASE_URL}")
101
  return ChatOllama(model=OLLAMA_MODEL, base_url=OLLAMA_BASE_URL, temperature=0)
102
 
103
  else:
104
- raise ValueError(
105
- f"Unknown LLM_PROVIDER: '{LLM_PROVIDER}'. Choose 'groq', 'openai', or 'ollama'."
106
- )
107
 
108
 
109
- # ── pipeline builder ──────────────────────────────────────────────────────────
110
-
111
- def build_rag_chain(vector_store: FAISS, k: int = 4) -> RetrievalQA:
112
- """
113
- Build a RetrievalQA chain that answers questions from the vector store.
114
-
115
- Parameters
116
- ----------
117
- vector_store : FAISS – the indexed documents
118
- k : int – number of chunks to retrieve per query
119
-
120
- Returns
121
- -------
122
- RetrievalQA – a ready-to-use QA chain
123
- """
124
  llm = _get_llm()
125
-
126
  retriever = vector_store.as_retriever(
127
  search_type="similarity",
128
  search_kwargs={"k": k},
129
  )
130
-
131
- # RetrievalQA wires the retriever β†’ prompt β†’ LLM for us
132
  chain = RetrievalQA.from_chain_type(
133
  llm=llm,
134
- chain_type="stuff", # "stuff" = paste all chunks into one prompt
135
  retriever=retriever,
136
- return_source_documents=True, # so we can show users where the answer came from
137
  chain_type_kwargs={"prompt": PROMPT},
138
  )
139
- print(" OK: RAG chain ready.")
140
  return chain
141
 
142
 
143
- # ── query helper ──────────────────────────────────────────────────────────────
144
-
145
- def ask_question(chain: RetrievalQA, question: str) -> dict:
146
- """
147
- Run a question through the RAG chain.
148
-
149
- Parameters
150
- ----------
151
- chain : RetrievalQA – built with build_rag_chain()
152
- question : str – the user's question
153
-
154
- Returns
155
- -------
156
- dict with keys:
157
- "answer" : str – the LLM's answer
158
- "sources" : list[Document] – the retrieved chunks used as context
159
- """
160
  if not question.strip():
161
  return {"answer": "Please enter a question.", "sources": []}
162
 
163
  result = chain.invoke({"query": question})
164
-
165
  return {
166
  "answer": result.get("result", "No answer returned."),
167
  "sources": result.get("source_documents", []),
 
1
  """
2
+ rag_pipeline.py - Connects retriever and LLM to answer questions.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  """
4
 
5
  import os
 
6
  from langchain_core.prompts import PromptTemplate
7
  from langchain_community.vectorstores import FAISS
8
 
9
+ LLM_PROVIDER = os.getenv("LLM_PROVIDER", "groq")
10
+ GROQ_MODEL = os.getenv("GROQ_MODEL", "llama3-8b-8192")
11
+ OPENAI_MODEL = os.getenv("OPENAI_MODEL", "gpt-3.5-turbo")
12
+ OLLAMA_MODEL = os.getenv("OLLAMA_MODEL", "llama3")
 
 
 
 
 
 
 
 
 
 
13
  OLLAMA_BASE_URL = os.getenv("OLLAMA_BASE_URL", "http://localhost:11434")
14
 
 
 
 
 
 
15
  RAG_PROMPT_TEMPLATE = """You are a helpful assistant that answers questions about
16
  Data Science interview preparation based only on the provided context.
17
 
 
31
  )
32
 
33
 
 
 
34
  def _get_llm():
 
 
 
 
 
35
  if LLM_PROVIDER == "groq":
36
  api_key = os.getenv("GROQ_API_KEY")
37
  if not api_key:
38
  raise EnvironmentError(
39
+ "GROQ_API_KEY is not set.\n"
40
+ "Get your free key at: https://console.groq.com/keys\n"
41
+ "Then add to .env: GROQ_API_KEY=gsk_..."
42
  )
43
  from langchain_groq import ChatGroq
44
  print(f" Using Groq model: {GROQ_MODEL}")
 
47
  elif LLM_PROVIDER == "openai":
48
  api_key = os.getenv("OPENAI_API_KEY")
49
  if not api_key:
50
+ raise EnvironmentError("OPENAI_API_KEY is not set.")
 
 
 
 
51
  from langchain_openai import ChatOpenAI
52
  print(f" Using OpenAI model: {OPENAI_MODEL}")
53
  return ChatOpenAI(model_name=OPENAI_MODEL, temperature=0)
54
 
55
  elif LLM_PROVIDER == "ollama":
56
  from langchain_ollama import ChatOllama
57
+ print(f" Using Ollama model: {OLLAMA_MODEL}")
58
  return ChatOllama(model=OLLAMA_MODEL, base_url=OLLAMA_BASE_URL, temperature=0)
59
 
60
  else:
61
+ raise ValueError(f"Unknown LLM_PROVIDER: '{LLM_PROVIDER}'. Use 'groq', 'openai', or 'ollama'.")
 
 
62
 
63
 
64
+ def build_rag_chain(vector_store, k: int = 4):
65
+ from langchain.chains import RetrievalQA
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  llm = _get_llm()
 
67
  retriever = vector_store.as_retriever(
68
  search_type="similarity",
69
  search_kwargs={"k": k},
70
  )
 
 
71
  chain = RetrievalQA.from_chain_type(
72
  llm=llm,
73
+ chain_type="stuff",
74
  retriever=retriever,
75
+ return_source_documents=True,
76
  chain_type_kwargs={"prompt": PROMPT},
77
  )
78
+ print(" RAG chain ready.")
79
  return chain
80
 
81
 
82
+ def ask_question(chain, question: str) -> dict:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  if not question.strip():
84
  return {"answer": "Please enter a question.", "sources": []}
85
 
86
  result = chain.invoke({"query": question})
 
87
  return {
88
  "answer": result.get("result", "No answer returned."),
89
  "sources": result.get("source_documents", []),