Spaces:
Sleeping
Sleeping
File size: 3,334 Bytes
05cb41b | 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 | import os
import json
from langchain_core.documents import Document
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_huggingface import HuggingFaceEmbeddings
class PolicyRAG:
def __init__(self):
self.vector_store = None
# Use a small, lightning-fast model for local embeddings
self.embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
# Paths to your admin data
self.base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
self.policy_file = os.path.join(self.base_dir, "data", "policy_terms.json")
self.rules_file = os.path.join(self.base_dir, "data", "adjudication_rules.md")
def initialize(self):
"""
Loads the policy and rules files, chunks them, and builds the FAISS index in memory.
This runs ONLY ONCE when the FastAPI server starts.
"""
print("🧠 Initializing LangChain RAG Vector Database...")
documents = []
# 1. Load and parse JSON Policy Terms
if os.path.exists(self.policy_file):
with open(self.policy_file, "r") as f:
policy_data = json.load(f)
# Convert the JSON dictionary into a flat readable string for the LLM
policy_text = json.dumps(policy_data, indent=2)
documents.append(Document(page_content=f"POLICY TERMS AND LIMITS:\n{policy_text}", metadata={"source": "policy_terms"}))
else:
print("⚠️ Warning: policy_terms.json not found.")
# 2. Load Markdown Adjudication Rules
if os.path.exists(self.rules_file):
with open(self.rules_file, "r") as f:
rules_text = f.read()
documents.append(Document(page_content=f"ADJUDICATION RULES:\n{rules_text}", metadata={"source": "adjudication_rules"}))
else:
print("⚠️ Warning: adjudication_rules.md not found.")
# 3. Chunk the documents so we only pull relevant sections
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=100,
separators=["\n## ", "\n### ", "\n", " ", ""]
)
chunks = text_splitter.split_documents(documents)
# 4. Build the FAISS Vector Database
if chunks:
self.vector_store = FAISS.from_documents(chunks, self.embeddings)
print(f"✅ RAG initialized successfully with {len(chunks)} knowledge chunks.")
else:
print("❌ RAG initialization failed: No documents loaded.")
def get_relevant_context(self, query: str, k: int = 3) -> str:
"""
Searches the FAISS database for the most relevant policy chunks based on the query.
Execution time: ~0.02 seconds.
"""
if not self.vector_store:
return "No policy context available."
# Retrieve top k matching documents
docs = self.vector_store.similarity_search(query, k=k)
# Combine the content into a single string for the Gemini prompt
context = "\n\n---\n\n".join([doc.page_content for doc in docs])
return context
# Create a singleton instance to be imported by the API router
rag_engine = PolicyRAG() |