Gaykar commited on
Commit
baea076
·
1 Parent(s): 45dce4f

vector chage

Browse files
Notebooks/CodeForge.ipynb CHANGED
@@ -589,7 +589,7 @@
589
  },
590
  {
591
  "cell_type": "code",
592
- "execution_count": 11,
593
  "id": "7561b3a1",
594
  "metadata": {},
595
  "outputs": [],
@@ -1368,7 +1368,7 @@
1368
  },
1369
  {
1370
  "cell_type": "code",
1371
- "execution_count": 202,
1372
  "id": "b5cfe4c3",
1373
  "metadata": {},
1374
  "outputs": [],
@@ -1399,10 +1399,14 @@
1399
  "# Agentic ReAct Loop (Planning Agent <-> Tools)\n",
1400
  "builder.add_conditional_edges(\n",
1401
  " \"roadmap_planning_agent\",\n",
1402
- " tools_condition, # Automatically routes to 'tools' if tool_calls present, else to END\n",
 
 
 
 
1403
  ")\n",
1404
  "\n",
1405
- "# After tools run, loop back to the agent for next steps\n",
1406
  "builder.add_edge(\"tools\", \"roadmap_planning_agent\")\n",
1407
  "\n",
1408
  "builder.add_edge(\"roadmap_planning_agent\", \"finalize_state\")\n",
 
589
  },
590
  {
591
  "cell_type": "code",
592
+ "execution_count": null,
593
  "id": "7561b3a1",
594
  "metadata": {},
595
  "outputs": [],
 
1368
  },
1369
  {
1370
  "cell_type": "code",
1371
+ "execution_count": null,
1372
  "id": "b5cfe4c3",
1373
  "metadata": {},
1374
  "outputs": [],
 
1399
  "# Agentic ReAct Loop (Planning Agent <-> Tools)\n",
1400
  "builder.add_conditional_edges(\n",
1401
  " \"roadmap_planning_agent\",\n",
1402
+ " tools_condition,\n",
1403
+ " {\n",
1404
+ " \"tools\": \"tools\", # If tool_calls exist, go to tools\n",
1405
+ " \"__end__\": \"finalize_state\" # If finished, go to finalize_state\n",
1406
+ " }\n",
1407
  ")\n",
1408
  "\n",
1409
+ "# 2. Loop back to agent after tools\n",
1410
  "builder.add_edge(\"tools\", \"roadmap_planning_agent\")\n",
1411
  "\n",
1412
  "builder.add_edge(\"roadmap_planning_agent\", \"finalize_state\")\n",
app/utils/vectordatabase.py CHANGED
@@ -1,34 +1,85 @@
 
 
 
 
 
 
1
  from pinecone import Pinecone, ServerlessSpec
2
  from pinecone_text.sparse import BM25Encoder
3
- import os
4
- from dotenv import load_dotenv
5
  from langchain_community.retrievers import PineconeHybridSearchRetriever
6
- import torch
7
- from langchain_community.embeddings import HuggingFaceEmbeddings
8
- from langchain_community.schema import Document
9
 
 
10
 
11
 
12
- device=torch.device("cuda" if torch.cuda.is_available() else "cpu")
13
- embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2", model_kwargs={"device": device})
 
14
 
 
 
 
15
 
16
- load_dotenv()
17
 
 
 
 
18
 
 
 
19
 
20
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
- PINECONE_API_KEY = os.getenv("PINECONE_API_KEY")
23
- pc = Pinecone(api_key=PINECONE_API_KEY)
24
 
25
- index_name = "catalog-embeddings"
26
 
 
27
 
28
- # Create index if not exists
29
- if index_name not in pc.list_indexes().names():
 
 
 
 
 
 
 
 
 
 
 
30
  pc.create_index(
31
- name=index_name,
32
  dimension=384,
33
  metric="dotproduct",
34
  spec=ServerlessSpec(
@@ -36,17 +87,39 @@ if index_name not in pc.list_indexes().names():
36
  region="us-east-1"
37
  )
38
  )
39
- print("Index created.")
40
 
41
- index = pc.Index(index_name)
42
  print("Index ready:", index.describe_index_stats())
43
 
 
 
 
 
 
 
44
  bm25_encoder = BM25Encoder()
45
 
46
- bm25_encoder.fit([doc.page_content for doc in documents])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
  retriever = PineconeHybridSearchRetriever(
49
  embeddings=embeddings,
50
  sparse_encoder=bm25_encoder,
51
  index=index
52
  )
 
 
 
1
+ import json
2
+ import pickle
3
+ import torch
4
+ from pathlib import Path
5
+ from typing import List
6
+
7
  from pinecone import Pinecone, ServerlessSpec
8
  from pinecone_text.sparse import BM25Encoder
9
+ from langchain_huggingface import HuggingFaceEmbeddings
 
10
  from langchain_community.retrievers import PineconeHybridSearchRetriever
11
+ from langchain_core.documents import Document
 
 
12
 
13
+ from app.core.config import settings
14
 
15
 
16
+ # -----------------------------
17
+ # Paths
18
+ # -----------------------------
19
 
20
+ BASE_DIR = Path(__file__).resolve().parent
21
+ DATA_PATH = BASE_DIR / "formatted_catalog.json"
22
+ BM25_PKL_PATH = BASE_DIR / "bm25.pkl"
23
 
 
24
 
25
+ # -----------------------------
26
+ # Device
27
+ # -----------------------------
28
 
29
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
30
+ print(f"Using device: {device}")
31
 
32
 
33
+ # -----------------------------
34
+ # Embeddings
35
+ # -----------------------------
36
+
37
+ embeddings = HuggingFaceEmbeddings(
38
+ model_name="sentence-transformers/all-MiniLM-L6-v2",
39
+ model_kwargs={"device": str(device)}
40
+ )
41
+
42
+
43
+ # -----------------------------
44
+ # Load Documents from JSON
45
+ # -----------------------------
46
+
47
+ def load_documents(data_path: Path) -> List[Document]:
48
+ if not data_path.exists():
49
+ raise FileNotFoundError(f"Catalog file not found: {data_path}")
50
+
51
+ with open(data_path, "r", encoding="utf-8") as f:
52
+ data = json.load(f)
53
+
54
+ documents = [
55
+ Document(
56
+ page_content=doc["page_content"],
57
+ metadata=doc["metadata"]
58
+ )
59
+ for doc in data
60
+ ]
61
 
62
+ print(f"Loaded {len(documents)} course documents")
63
+ return documents
64
 
 
65
 
66
+ documents: List[Document] = load_documents(DATA_PATH)
67
 
68
+ if not documents:
69
+ raise ValueError("No documents loaded from formatted_catalog.json")
70
+
71
+
72
+ # -----------------------------
73
+ # Pinecone Index
74
+ # -----------------------------
75
+
76
+ pc = Pinecone(api_key=settings.PINECONE_API_KEY)
77
+
78
+ INDEX_NAME = "catalog-embeddings"
79
+
80
+ if INDEX_NAME not in pc.list_indexes().names():
81
  pc.create_index(
82
+ name=INDEX_NAME,
83
  dimension=384,
84
  metric="dotproduct",
85
  spec=ServerlessSpec(
 
87
  region="us-east-1"
88
  )
89
  )
90
+ print(f"Index created: {INDEX_NAME}")
91
 
92
+ index = pc.Index(INDEX_NAME)
93
  print("Index ready:", index.describe_index_stats())
94
 
95
+
96
+ # -----------------------------
97
+ # BM25 Sparse Encoder
98
+ # Loads from pickle if exists, fits and saves if not
99
+ # -----------------------------
100
+
101
  bm25_encoder = BM25Encoder()
102
 
103
+ if BM25_PKL_PATH.exists():
104
+ print("Loading existing BM25 model from pickle...")
105
+ with open(BM25_PKL_PATH, "rb") as f:
106
+ bm25_encoder = pickle.load(f)
107
+ else:
108
+ print("Fitting BM25 on course catalog...")
109
+ bm25_encoder.fit([doc.page_content for doc in documents])
110
+ with open(BM25_PKL_PATH, "wb") as f:
111
+ pickle.dump(bm25_encoder, f)
112
+ print(f"BM25 fitted and saved to {BM25_PKL_PATH}")
113
+
114
+
115
+ # -----------------------------
116
+ # Hybrid Retriever
117
+ # -----------------------------
118
 
119
  retriever = PineconeHybridSearchRetriever(
120
  embeddings=embeddings,
121
  sparse_encoder=bm25_encoder,
122
  index=index
123
  )
124
+
125
+ print("Retriever ready.")