atulkrs commited on
Commit
37f130f
·
verified ·
1 Parent(s): 223d01b

Add full RAG pipeline: agent, rag_engine, generator, knowledge_base, full Gradio UI

Browse files
Files changed (3) hide show
  1. agent.py +6 -9
  2. generator.py +4 -1
  3. rag_engine.py +3 -2
agent.py CHANGED
@@ -22,7 +22,6 @@ from rag_engine import MLOpsRAGEngine
22
  logger = logging.getLogger(__name__)
23
 
24
  MAX_ITERATIONS = 2
25
- RELEVANCE_SCORE_THRESHOLD = 0.30
26
 
27
 
28
  @dataclass
@@ -96,21 +95,19 @@ class MLOpsRAGAgent:
96
  logger.error(f"Retrieval failed: {e}")
97
  return [], []
98
 
99
- # Filter by similarity score threshold first (fast path)
100
- score_filtered = [
101
- n for n in nodes
102
- if self.rag.get_node_score(n) >= RELEVANCE_SCORE_THRESHOLD
103
- ]
104
 
105
- # Self-reflection relevance check on remaining nodes
106
  relevant = []
107
- for node in score_filtered:
108
  text = self.rag.get_node_text(node)
109
  try:
110
  if self.gen.check_relevance(query, text):
111
  relevant.append(node)
112
  except Exception:
113
- # On error, include by score only
114
  relevant.append(node)
115
 
116
  logger.info(f"Nodes after relevance filtering: {len(relevant)}/{len(nodes)}")
 
22
  logger = logging.getLogger(__name__)
23
 
24
  MAX_ITERATIONS = 2
 
25
 
26
 
27
  @dataclass
 
95
  logger.error(f"Retrieval failed: {e}")
96
  return [], []
97
 
98
+ # ChromaDB returns cosine *distance* (lower = more similar).
99
+ # A score threshold on distance would silently discard the best chunks,
100
+ # so we pass all retrieved nodes to the Flan-T5 relevance check instead.
101
+ scores = [self.rag.get_node_score(n) for n in nodes]
102
+ logger.info(f"Raw node distances: {[round(s, 3) for s in scores]}")
103
 
 
104
  relevant = []
105
+ for node in nodes:
106
  text = self.rag.get_node_text(node)
107
  try:
108
  if self.gen.check_relevance(query, text):
109
  relevant.append(node)
110
  except Exception:
 
111
  relevant.append(node)
112
 
113
  logger.info(f"Nodes after relevance filtering: {len(relevant)}/{len(nodes)}")
generator.py CHANGED
@@ -95,7 +95,10 @@ class FlanT5Generator:
95
  f"Answer:"
96
  )
97
  result = self._generate(prompt, max_new_tokens=5).lower()
98
- return "yes" in result
 
 
 
99
 
100
  def reflect_on_answer(self, query: str, answer: str) -> tuple[bool, str]:
101
  """Self-reflect on whether the generated answer adequately addresses the query."""
 
95
  f"Answer:"
96
  )
97
  result = self._generate(prompt, max_new_tokens=5).lower()
98
+ # Lenient: include the chunk unless the model explicitly says "no".
99
+ # "yes" in result is too strict — Flan-T5 sometimes outputs synonyms or
100
+ # fuller sentences; requiring an explicit "no" avoids false negatives.
101
+ return "no" not in result
102
 
103
  def reflect_on_answer(self, query: str, answer: str) -> tuple[bool, str]:
104
  """Self-reflect on whether the generated answer adequately addresses the query."""
rag_engine.py CHANGED
@@ -16,8 +16,9 @@ from llama_index.vector_stores.chroma import ChromaVectorStore
16
  logger = logging.getLogger(__name__)
17
 
18
  EMBED_MODEL_NAME = "sentence-transformers/all-MiniLM-L6-v2"
19
- KNOWLEDGE_BASE_PATH = "./knowledge_base"
20
- CHROMA_DB_PATH = "./chroma_db"
 
21
  COLLECTION_NAME = "mlops_knowledge_base"
22
  CHUNK_SIZE = 512
23
  CHUNK_OVERLAP = 64
 
16
  logger = logging.getLogger(__name__)
17
 
18
  EMBED_MODEL_NAME = "sentence-transformers/all-MiniLM-L6-v2"
19
+ _HERE = Path(__file__).parent
20
+ KNOWLEDGE_BASE_PATH = str(_HERE / "knowledge_base")
21
+ CHROMA_DB_PATH = str(_HERE / "chroma_db")
22
  COLLECTION_NAME = "mlops_knowledge_base"
23
  CHUNK_SIZE = 512
24
  CHUNK_OVERLAP = 64