Pulastya0 commited on
Commit
eac3167
·
verified ·
1 Parent(s): 3577386

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +60 -33
app.py CHANGED
@@ -35,53 +35,55 @@ kb_collection = None
35
  # -------------------------------
36
  @app.post("/setup")
37
  async def setup_kb(kb_file: UploadFile = File(...)):
 
 
 
 
38
  global kb_collection
 
39
  try:
40
- # Read JSON directly
41
  content_bytes = await kb_file.read()
42
  data = json.loads(content_bytes)
43
 
44
  if not isinstance(data, list):
45
- raise HTTPException(status_code=400, detail="JSON must contain a list of knowledge items.")
46
 
47
- print(f"📘 Loaded {len(data)} items from uploaded file '{kb_file.filename}'")
48
 
49
- # Initialize Sentence Transformer
50
  encoder = SentenceTransformer("all-MiniLM-L6-v2")
 
 
51
 
52
- # Initialize ChromaDB (persistent)
53
- chroma_client = chromadb.PersistentClient(path="/tmp/chroma") # must be writable
54
- kb_collection = chroma_client.get_or_create_collection(
55
- name="knowledge_base",
56
- embedding_function=embedding_functions.SentenceTransformerEmbeddingFunction(
57
- model_name="all-MiniLM-L6-v2"
58
- )
59
- )
60
-
61
- # Clear old data
62
- if kb_collection.count() > 0:
63
- kb_collection.delete(ids=kb_collection.get()['ids'])
64
 
65
- # Prepare data
66
  texts, ids, metadatas = [], [], []
67
  for i, item in enumerate(data):
68
- content = item.get("answer") or item.get("content") or ""
69
- title = item.get("id") or f"Document {i+1}"
70
- texts.append(f"{title}. {content}")
71
- ids.append(str(i))
72
- # Only keep str/int/bool/float for metadata
73
- metadata = {k: str(v) if isinstance(v, list) else v for k, v in item.items()}
74
- metadatas.append(metadata)
75
 
76
  # Generate embeddings
 
77
  embeddings = encoder.encode(texts, show_progress_bar=True).tolist()
78
 
79
- # Add to Chroma
80
- kb_collection.add(ids=ids, embeddings=embeddings, metadatas=metadatas)
81
- print(f"✅ Successfully added {kb_collection.count()} records.")
 
82
 
83
- return {"message": "Knowledge base successfully initialized.", "count": kb_collection.count()}
 
84
 
 
 
85
  except Exception as e:
86
  raise HTTPException(status_code=500, detail=f"Setup failed: {e}")
87
 
@@ -103,13 +105,38 @@ async def route_endpoint(ticket: TicketRequest):
103
 
104
  @app.post("/kb_query")
105
  async def kb_query_endpoint(ticket: TicketRequest):
106
- """Query KB directly"""
 
107
  if not kb_collection:
108
  raise HTTPException(status_code=400, detail="KB not set up. Call /setup first.")
109
- result = kb_collection.query(query_texts=[ticket.text], n_results=1)
110
- if not result or len(result['documents'][0]) == 0:
111
- return {"answer": "No relevant KB found."}
112
- return {"answer": result['documents'][0][0], "confidence": result['distances'][0][0] if result.get('distances') else 0.0}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
 
114
  # -------------------------------
115
  # Full Ticket Orchestration
 
35
  # -------------------------------
36
  @app.post("/setup")
37
  async def setup_kb(kb_file: UploadFile = File(...)):
38
+ """
39
+ Uploads a JSON KB file (flattened), generates embeddings with SentenceTransformer,
40
+ and populates a persistent ChromaDB collection.
41
+ """
42
  global kb_collection
43
+
44
  try:
45
+ # Load JSON from uploaded file
46
  content_bytes = await kb_file.read()
47
  data = json.loads(content_bytes)
48
 
49
  if not isinstance(data, list):
50
+ raise HTTPException(status_code=400, detail="JSON must be a list of items.")
51
 
52
+ print(f"📘 Loaded {len(data)} items from {kb_file.filename}")
53
 
54
+ # Initialize encoder and Chroma
55
  encoder = SentenceTransformer("all-MiniLM-L6-v2")
56
+ chroma_client = chromadb.PersistentClient(path=CHROMA_PATH)
57
+ collection = chroma_client.get_or_create_collection(COLLECTION_NAME)
58
 
59
+ # Clear existing records
60
+ if collection.count() > 0:
61
+ print(f"🧹 Clearing {collection.count()} existing records...")
62
+ collection.delete(ids=collection.get()['ids'])
 
 
 
 
 
 
 
 
63
 
64
+ # Prepare texts, ids, and metadata
65
  texts, ids, metadatas = [], [], []
66
  for i, item in enumerate(data):
67
+ text = item.get("text") or ""
68
+ item_id = item.get("id") or str(i)
69
+ texts.append(text)
70
+ ids.append(str(item_id))
71
+ metadatas.append({"id": str(item_id)})
 
 
72
 
73
  # Generate embeddings
74
+ print("🧠 Generating embeddings...")
75
  embeddings = encoder.encode(texts, show_progress_bar=True).tolist()
76
 
77
+ # Add to ChromaDB
78
+ print("💾 Adding to ChromaDB...")
79
+ collection.add(ids=ids, embeddings=embeddings, metadatas=metadatas)
80
+ kb_collection = collection # assign to global
81
 
82
+ print(f" Successfully added {collection.count()} records to {COLLECTION_NAME}.")
83
+ return {"message": "Knowledge base successfully initialized.", "count": collection.count()}
84
 
85
+ except json.JSONDecodeError:
86
+ raise HTTPException(status_code=400, detail="Invalid JSON file.")
87
  except Exception as e:
88
  raise HTTPException(status_code=500, detail=f"Setup failed: {e}")
89
 
 
105
 
106
  @app.post("/kb_query")
107
  async def kb_query_endpoint(ticket: TicketRequest):
108
+ """Query the flattened KB directly using embeddings and return the best match."""
109
+ global kb_collection
110
  if not kb_collection:
111
  raise HTTPException(status_code=400, detail="KB not set up. Call /setup first.")
112
+
113
+ try:
114
+ # Use the same SentenceTransformer as in /setup
115
+ encoder = SentenceTransformer("all-MiniLM-L6-v2")
116
+ query_vec = encoder.encode([ticket.text])[0]
117
+
118
+ # Query ChromaDB
119
+ result = kb_collection.query(
120
+ query_embeddings=[query_vec],
121
+ n_results=1,
122
+ include=["documents", "distances", "metadatas"]
123
+ )
124
+
125
+ if not result or len(result['documents'][0]) == 0:
126
+ return {"answer": "No relevant KB found.", "confidence": 0.0}
127
+
128
+ # Extract best match
129
+ best_doc = result['documents'][0][0]
130
+ best_distance = result['distances'][0][0] if result.get('distances') else 0.0
131
+ confidence = float(1 - best_distance) # Convert distance → confidence
132
+
133
+ return {
134
+ "answer": best_doc,
135
+ "confidence": round(confidence, 3)
136
+ }
137
+
138
+ except Exception as e:
139
+ raise HTTPException(status_code=500, detail=f"KB query failed: {e}")
140
 
141
  # -------------------------------
142
  # Full Ticket Orchestration