Spaces:
Sleeping
Sleeping
Vela
commited on
Commit
·
6ccb49e
1
Parent(s):
ed7e26f
added pinecone db
Browse files- chroma.log +20 -0
- src/backend/__pycache__/main.cpython-313.pyc +0 -0
- src/backend/data/__pycache__/chroma_db.cpython-313.pyc +0 -0
- src/backend/data/__pycache__/pinecone_db.cpython-313.pyc +0 -0
- src/backend/data/chroma_db.py +6 -0
- src/backend/data/pinecone_db.py +144 -0
- src/backend/main.py +2 -1
- src/backend/models/__pycache__/embedding_model.cpython-313.pyc +0 -0
- src/backend/models/embedding_model.py +18 -0
- src/backend/routes/__pycache__/chat_api.cpython-313.pyc +0 -0
- src/backend/routes/__pycache__/upsert_data.cpython-313.pyc +0 -0
- src/backend/routes/chat_api.py +7 -4
- src/backend/routes/upsert_data.py +15 -0
chroma.log
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[33mWARNING[0m: [10-03-2025 20:07:32] chroma_server_nofile is not supported on Windows. chroma_server_nofile will not be set.
|
2 |
+
[33mWARNING[0m: [10-03-2025 20:07:51] chroma_server_nofile is not supported on Windows. chroma_server_nofile will not be set.
|
3 |
+
[32mINFO[0m: [10-03-2025 20:07:52] Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
|
4 |
+
[36mDEBUG[0m: [10-03-2025 20:07:52] Starting component System
|
5 |
+
[36mDEBUG[0m: [10-03-2025 20:07:52] Starting component OpenTelemetryClient
|
6 |
+
[36mDEBUG[0m: [10-03-2025 20:07:52] Starting component SqliteDB
|
7 |
+
[36mDEBUG[0m: [10-03-2025 20:07:52] Starting component SimpleQuotaEnforcer
|
8 |
+
[36mDEBUG[0m: [10-03-2025 20:07:52] Starting component Posthog
|
9 |
+
[36mDEBUG[0m: [10-03-2025 20:07:52] Starting component SimpleRateLimitEnforcer
|
10 |
+
[36mDEBUG[0m: [10-03-2025 20:07:52] Starting component LocalSegmentManager
|
11 |
+
[36mDEBUG[0m: [10-03-2025 20:07:52] Starting component LocalExecutor
|
12 |
+
[36mDEBUG[0m: [10-03-2025 20:07:52] Starting component SegmentAPI
|
13 |
+
[36mDEBUG[0m: [10-03-2025 20:07:52] Starting component SimpleAsyncRateLimitEnforcer
|
14 |
+
[32mINFO[0m: [10-03-2025 20:07:52] Started server process [[36m17592[0m]
|
15 |
+
[32mINFO[0m: [10-03-2025 20:07:52] Waiting for application startup.
|
16 |
+
[32mINFO[0m: [10-03-2025 20:07:52] Application startup complete.
|
17 |
+
[32mINFO[0m: [10-03-2025 20:07:52] Uvicorn running on [1mhttp://localhost:8000[0m (Press CTRL+C to quit)
|
18 |
+
[32mINFO[0m: [10-03-2025 20:16:05] ::1:57148 - "GET /api/v2/auth/identity HTTP/1.1" 200
|
19 |
+
[32mINFO[0m: [10-03-2025 20:16:05] ::1:57149 - "GET /api/v2/tenants/default_tenant HTTP/1.1" 200
|
20 |
+
[32mINFO[0m: [10-03-2025 20:16:05] ::1:57149 - "GET /api/v2/tenants/default_tenant/databases/default_database HTTP/1.1" 200
|
src/backend/__pycache__/main.cpython-313.pyc
CHANGED
Binary files a/src/backend/__pycache__/main.cpython-313.pyc and b/src/backend/__pycache__/main.cpython-313.pyc differ
|
|
src/backend/data/__pycache__/chroma_db.cpython-313.pyc
CHANGED
Binary files a/src/backend/data/__pycache__/chroma_db.cpython-313.pyc and b/src/backend/data/__pycache__/chroma_db.cpython-313.pyc differ
|
|
src/backend/data/__pycache__/pinecone_db.cpython-313.pyc
ADDED
Binary file (7.41 kB). View file
|
|
src/backend/data/chroma_db.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
import chromadb
|
|
|
2 |
from utils import logger
|
3 |
from chromadb.utils import embedding_functions
|
4 |
default_ef = embedding_functions.DefaultEmbeddingFunction()
|
@@ -12,6 +13,11 @@ DB_PATH = "./src/backend/vector-db"
|
|
12 |
# Initialize ChromaDB Client
|
13 |
client = chromadb.PersistentClient(path=DB_PATH)
|
14 |
|
|
|
|
|
|
|
|
|
|
|
15 |
collection = client.get_or_create_collection(
|
16 |
name=COLLECTION_NAME,
|
17 |
embedding_function=default_ef,
|
|
|
1 |
import chromadb
|
2 |
+
import asyncio
|
3 |
from utils import logger
|
4 |
from chromadb.utils import embedding_functions
|
5 |
default_ef = embedding_functions.DefaultEmbeddingFunction()
|
|
|
13 |
# Initialize ChromaDB Client
|
14 |
client = chromadb.PersistentClient(path=DB_PATH)
|
15 |
|
16 |
+
|
17 |
+
|
18 |
+
# chroma_client = chromadb.HttpClient(host='localhost', port=8000)
|
19 |
+
# client = chromadb.AsyncHttpClient()
|
20 |
+
|
21 |
collection = client.get_or_create_collection(
|
22 |
name=COLLECTION_NAME,
|
23 |
embedding_function=default_ef,
|
src/backend/data/pinecone_db.py
ADDED
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import sys
|
3 |
+
src_directory = os.path.abspath(os.path.join(os.path.dirname(__file__), "../..", "backend"))
|
4 |
+
sys.path.append(src_directory)
|
5 |
+
from pinecone import Pinecone, ServerlessSpec
|
6 |
+
import time
|
7 |
+
from tqdm import tqdm # Progress bar for large datasets
|
8 |
+
from dotenv import load_dotenv
|
9 |
+
from utils import logger
|
10 |
+
import pandas as pd
|
11 |
+
from models import embedding_model
|
12 |
+
from data import dataset
|
13 |
+
|
14 |
+
load_dotenv()
|
15 |
+
PINECONE_API_KEY = os.environ.get("PINECONE_API_KEY")
|
16 |
+
logger = logger.get_logger()
|
17 |
+
NAMESPACE = "health-care-dataset"
|
18 |
+
INDEX_NAME = "health-care-index"
|
19 |
+
|
20 |
+
|
21 |
+
def create_index(pinecone, index_name):
|
22 |
+
pinecone.create_index(
|
23 |
+
name=index_name,
|
24 |
+
dimension=384,
|
25 |
+
metric="cosine",
|
26 |
+
spec=ServerlessSpec(
|
27 |
+
cloud="aws",
|
28 |
+
region="us-east-1"
|
29 |
+
)
|
30 |
+
)
|
31 |
+
|
32 |
+
def wait_till_index_loaded(pinecone, index_name):
|
33 |
+
while True:
|
34 |
+
index = pinecone.describe_index(index_name)
|
35 |
+
if index.status.get("ready", False):
|
36 |
+
index = pinecone.Index(index_name)
|
37 |
+
logger.info(f"Index '{index_name}' is ready and is now accessible.")
|
38 |
+
return index
|
39 |
+
else:
|
40 |
+
logger.debug(f"Index '{index_name}' is not ready yet. Checking again in 1 second.")
|
41 |
+
time.sleep(1)
|
42 |
+
|
43 |
+
def get_index():
|
44 |
+
global index
|
45 |
+
index = None
|
46 |
+
try:
|
47 |
+
pc = Pinecone(api_key=PINECONE_API_KEY)
|
48 |
+
index_name = INDEX_NAME
|
49 |
+
logger.info(f"Checking if the index '{index_name}' exists...")
|
50 |
+
if not pc.has_index(index_name):
|
51 |
+
logger.info(f"Index '{index_name}' does not exist. Creating a new index...")
|
52 |
+
create_index(pc,index_name)
|
53 |
+
logger.info(f"Index '{index_name}' creation initiated. Waiting for it to be ready...")
|
54 |
+
index = wait_till_index_loaded(pc,index_name)
|
55 |
+
else:
|
56 |
+
index = pc.Index(index_name)
|
57 |
+
logger.info(f"Index '{index_name}' already exists. Returning the existing index.")
|
58 |
+
except Exception as e:
|
59 |
+
logger.info(f"Error occurred while getting or creating the Pinecone index: {str(e)}", exc_info=True)
|
60 |
+
return index
|
61 |
+
|
62 |
+
index = get_index()
|
63 |
+
|
64 |
+
def process_and_upsert_data(index, data: pd.DataFrame):
|
65 |
+
|
66 |
+
# Validate if the required columns exist in the row (Series)
|
67 |
+
try:
|
68 |
+
logger.info("Started upserting the data to database")
|
69 |
+
for idx, row in data.iterrows():
|
70 |
+
logger.info(f"Processing row {row['input']}")
|
71 |
+
input_text = row['input']
|
72 |
+
output_text = row['output']
|
73 |
+
instruction_text = row['instruction']
|
74 |
+
if not isinstance(input_text, str) or not input_text.strip():
|
75 |
+
logger.warning(f"Skipping row {idx} due to empty or invalid input text.")
|
76 |
+
continue
|
77 |
+
row_dict = {
|
78 |
+
"question": input_text,
|
79 |
+
"answer" : output_text,
|
80 |
+
"instruction": instruction_text
|
81 |
+
}
|
82 |
+
embeddings = embedding_model.get_text_embedding(row['input'])
|
83 |
+
index.upsert(
|
84 |
+
vectors=[{
|
85 |
+
"id": f"id{idx}",
|
86 |
+
"values": embeddings,
|
87 |
+
"metadata":row_dict
|
88 |
+
}],
|
89 |
+
namespace=NAMESPACE,
|
90 |
+
)
|
91 |
+
logger.info(f"Successfully upserted data for question {input_text} with answer {output_text}")
|
92 |
+
except Exception as e:
|
93 |
+
logger.error(f"Error processing row with index {idx}: {e}")
|
94 |
+
|
95 |
+
def search_vector_store(query, n_result : int = 3) -> list[dict]:
|
96 |
+
"""
|
97 |
+
Searches the vector store for the most relevant matches based on the given query.
|
98 |
+
|
99 |
+
This method retrieves the top `n_result` closest matches from the vector store
|
100 |
+
using an embedding-based similarity search. Each match includes metadata
|
101 |
+
such as the answer, instruction, and question.
|
102 |
+
|
103 |
+
Args:
|
104 |
+
query (str): The search query text.
|
105 |
+
n_result (int, optional): The number of top results to retrieve. Defaults to 3.
|
106 |
+
|
107 |
+
Returns:
|
108 |
+
list[dict]: A list of dictionaries, where each dictionary contains:
|
109 |
+
- "answer" (str): The retrieved answer.
|
110 |
+
- "instruction" (str): The instruction related to the answer.
|
111 |
+
- "question" (str): The question associated with the answer.
|
112 |
+
|
113 |
+
Raises:
|
114 |
+
Exception: If an error occurs while querying the vector store.
|
115 |
+
|
116 |
+
"""
|
117 |
+
try:
|
118 |
+
index = get_index()
|
119 |
+
embedding = embedding_model.get_text_embedding(query)
|
120 |
+
response = index.query(
|
121 |
+
top_k=n_result,
|
122 |
+
vector=embedding,
|
123 |
+
namespace=NAMESPACE,
|
124 |
+
include_metadata=True)
|
125 |
+
metadata = []
|
126 |
+
for response in response['matches']:
|
127 |
+
metadata.append({"answer":response['metadata']['answer'],
|
128 |
+
"instruction":response['metadata']['instruction'],
|
129 |
+
"question":response['metadata']['question']})
|
130 |
+
return metadata
|
131 |
+
except Exception as e:
|
132 |
+
raise Exception(f"Error occurred while searching the vector store: {str(e)}")
|
133 |
+
|
134 |
+
def get_retrieved_context(prompt: str) -> str:
|
135 |
+
response = search_vector_store(prompt)
|
136 |
+
if response and "metadatas" in response and response["metadatas"]:
|
137 |
+
retrieved_contexts = [metadata["answer"] for metadata in response["metadatas"][0]]
|
138 |
+
return "\n".join(retrieved_contexts[:3])
|
139 |
+
return "No relevant information found in the database."
|
140 |
+
|
141 |
+
data_set = dataset.get_data_set()[6139:10000]
|
142 |
+
process_and_upsert_data(index, data_set)
|
143 |
+
# response = search_vector_store("What is the treatment for diabetes?")
|
144 |
+
# print(response)
|
src/backend/main.py
CHANGED
@@ -3,4 +3,5 @@ from routes import chat_api
|
|
3 |
|
4 |
app = FastAPI()
|
5 |
|
6 |
-
app.include_router(chat_api.router, prefix="/chat", tags=["chat"])
|
|
|
|
3 |
|
4 |
app = FastAPI()
|
5 |
|
6 |
+
app.include_router(chat_api.router, prefix="/chat", tags=["chat"])
|
7 |
+
# app.include_router(upsert_data.router, prefix="/data", tags=["data"])
|
src/backend/models/__pycache__/embedding_model.cpython-313.pyc
ADDED
Binary file (1.31 kB). View file
|
|
src/backend/models/embedding_model.py
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from sentence_transformers import SentenceTransformer
|
2 |
+
from utils import logger
|
3 |
+
from fastapi import UploadFile
|
4 |
+
from PIL import Image
|
5 |
+
|
6 |
+
logger = logger.get_logger()
|
7 |
+
|
8 |
+
model = SentenceTransformer("all-MiniLM-L6-v2")
|
9 |
+
|
10 |
+
def get_text_embedding(search_query: str):
|
11 |
+
try:
|
12 |
+
logger.info(f"Getting embedding for the text: {search_query}")
|
13 |
+
text_embedding = model.encode(search_query, convert_to_tensor=True).cpu().numpy().tolist()
|
14 |
+
logger.info("Text embedding successfully retrieved.")
|
15 |
+
return text_embedding
|
16 |
+
except Exception as e:
|
17 |
+
logger.error(f"Error while getting embedding for text: {e}")
|
18 |
+
raise
|
src/backend/routes/__pycache__/chat_api.cpython-313.pyc
CHANGED
Binary files a/src/backend/routes/__pycache__/chat_api.cpython-313.pyc and b/src/backend/routes/__pycache__/chat_api.cpython-313.pyc differ
|
|
src/backend/routes/__pycache__/upsert_data.cpython-313.pyc
ADDED
Binary file (187 Bytes). View file
|
|
src/backend/routes/chat_api.py
CHANGED
@@ -2,7 +2,8 @@ from fastapi import APIRouter, HTTPException
|
|
2 |
from utils import logger
|
3 |
from models.schemas import Chat_Response, ChatRequest
|
4 |
from models import llm_model
|
5 |
-
from data import
|
|
|
6 |
|
7 |
logger = logger.get_logger()
|
8 |
router = APIRouter()
|
@@ -23,9 +24,9 @@ async def get_db_response(chat_request: Chat_Response):
|
|
23 |
try:
|
24 |
logger.info(f"Received user prompt: {chat_request.prompt}")
|
25 |
query = chat_request.prompt[-1]
|
26 |
-
response_text =
|
27 |
logger.info(f"Retrieved context for user prompt: {chat_request.prompt[:50]}...")
|
28 |
-
return
|
29 |
except Exception as e:
|
30 |
logger.exception("Unexpected error occurred while processing the request.")
|
31 |
raise HTTPException(status_code=500, detail="An error occurred while processing your request.")
|
@@ -37,4 +38,6 @@ async def chat_with_assistant(request: ChatRequest):
|
|
37 |
response = llm_model.get_medical_assistant_request(request.conversation_history)
|
38 |
return {"response": response}
|
39 |
except Exception as e:
|
40 |
-
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
2 |
from utils import logger
|
3 |
from models.schemas import Chat_Response, ChatRequest
|
4 |
from models import llm_model
|
5 |
+
from data import pinecone_db
|
6 |
+
# from data import chroma_db
|
7 |
|
8 |
logger = logger.get_logger()
|
9 |
router = APIRouter()
|
|
|
24 |
try:
|
25 |
logger.info(f"Received user prompt: {chat_request.prompt}")
|
26 |
query = chat_request.prompt[-1]
|
27 |
+
response_text = pinecone_db.search_vector_store(query)
|
28 |
logger.info(f"Retrieved context for user prompt: {chat_request.prompt[:50]}...")
|
29 |
+
return response_text
|
30 |
except Exception as e:
|
31 |
logger.exception("Unexpected error occurred while processing the request.")
|
32 |
raise HTTPException(status_code=500, detail="An error occurred while processing your request.")
|
|
|
38 |
response = llm_model.get_medical_assistant_request(request.conversation_history)
|
39 |
return {"response": response}
|
40 |
except Exception as e:
|
41 |
+
raise HTTPException(status_code=500, detail=str(e))
|
42 |
+
|
43 |
+
# Input format for above endpoint
|
src/backend/routes/upsert_data.py
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# from fastapi import APIRouter,HTTPException
|
2 |
+
# from data import dataset
|
3 |
+
# from data import pinecone_db
|
4 |
+
|
5 |
+
# router = APIRouter()
|
6 |
+
# index_name = "question-answering-index"
|
7 |
+
|
8 |
+
# @router.post("/upsert_data")
|
9 |
+
# async def upsert_data():
|
10 |
+
# try:
|
11 |
+
# df = dataset.get_data_set()[0:1000]
|
12 |
+
# pinecone_db.process_and_upsert_data(index_name, df)
|
13 |
+
# return {"status": "success"}
|
14 |
+
# except Exception as e:
|
15 |
+
# raise HTTPException(status_code=500, detail=str(e))
|