vickyvigneshmass commited on
Commit
01fcf24
·
verified ·
1 Parent(s): d7c9b29

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +109 -41
app.py CHANGED
@@ -1,60 +1,128 @@
1
  from fastapi import FastAPI, UploadFile, File, Form
2
- from transformers import CLIPProcessor, CLIPModel
3
- from PIL import Image
4
- import torch
5
- import io
6
  import uuid
7
  import chromadb
8
  from chromadb.config import Settings
 
9
 
10
  # Initialize FastAPI
11
  app = FastAPI()
12
 
13
- # Load CLIP model and processor
14
- model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
15
- processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")
16
 
17
  # Initialize ChromaDB
18
  chroma_client = chromadb.Client(Settings(chroma_db_impl="duckdb+parquet", persist_directory="./chroma_storage"))
19
- collection = chroma_client.get_or_create_collection(name="images")
20
-
21
- # Function to extract image embeddings
22
- def get_image_embedding(image: Image.Image):
23
- inputs = processor(images=image, return_tensors="pt")
24
- with torch.no_grad():
25
- embeddings = model.get_image_features(**inputs)
26
- embeddings = embeddings / embeddings.norm(p=2, dim=-1, keepdim=True)
27
- return embeddings[0].tolist()
28
-
29
- # Function to extract text embeddings
30
- def get_text_embedding(text: str):
31
- inputs = processor(text=[text], return_tensors="pt", padding=True)
32
- with torch.no_grad():
33
- embeddings = model.get_text_features(**inputs)
34
- embeddings = embeddings / embeddings.norm(p=2, dim=-1, keepdim=True)
35
- return embeddings[0].tolist()
36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  @app.get("/")
38
  def root():
39
- return {"message": "CLIP + ChromaDB image-text similarity search"}
40
 
41
- @app.post("/add-image/")
42
- async def add_image(file: UploadFile = File(...), label: str = Form(...)):
 
 
 
 
43
  contents = await file.read()
44
- image = Image.open(io.BytesIO(contents)).convert("RGB")
45
- embedding = get_image_embedding(image)
46
- uid = str(uuid.uuid4())
47
- collection.add(documents=[label], embeddings=[embedding], ids=[uid], metadatas=[{"label": label}])
48
- return {"message": f"Image '{label}' added with ID {uid}"}
49
 
 
50
  @app.post("/search/")
51
  async def search_text(query: str = Form(...), top_k: int = 3):
52
- embedding = get_text_embedding(query)
53
- results = collection.query(query_embeddings=[embedding], n_results=top_k)
54
- return {
55
- "query": query,
56
- "results": [
57
- {"label": doc, "score": score}
58
- for doc, score in zip(results["documents"][0], results["distances"][0])
59
- ]
60
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  from fastapi import FastAPI, UploadFile, File, Form
2
+ from sentence_transformers import SentenceTransformer
3
+ import pdfplumber
 
 
4
  import uuid
5
  import chromadb
6
  from chromadb.config import Settings
7
+ import httpx
8
 
9
  # Initialize FastAPI
10
  app = FastAPI()
11
 
12
+ # Load SentenceTransformer model for document embeddings
13
+ model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
 
14
 
15
  # Initialize ChromaDB
16
  chroma_client = chromadb.Client(Settings(chroma_db_impl="duckdb+parquet", persist_directory="./chroma_storage"))
17
+ collection = chroma_client.get_or_create_collection(name="documents")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
+ # RedMindGPT API details
20
+ REDMIND_API_URL = "http://redmindgpt.redmindtechnologies.com/v1"
21
+ REDMIND_API_KEY = "dataset-feqz5KrqHkFRdWbh2DInt58L"
22
+
23
+ # Function to process PDF and store each page
24
+ def process_pdf_and_store(file_bytes: bytes, filename: str):
25
+ with pdfplumber.open(file_bytes) as pdf:
26
+ for page_number, page in enumerate(pdf.pages, start=1):
27
+ text = page.extract_text()
28
+ if text:
29
+ embedding = model.encode(text, normalize_embeddings=True).tolist()
30
+ uid = str(uuid.uuid4())
31
+ collection.add(
32
+ documents=[text],
33
+ embeddings=[embedding],
34
+ ids=[uid],
35
+ metadatas=[{
36
+ "filename": filename,
37
+ "page": page_number
38
+ }]
39
+ )
40
+
41
+ # Home route
42
  @app.get("/")
43
  def root():
44
+ return {"message": "Semantic Document Retrieval API with RedMindGPT is running!"}
45
 
46
+ # Upload PDF and store embeddings
47
+ @app.post("/upload-pdf/")
48
+ async def upload_pdf(file: UploadFile = File(...)):
49
+ if not file.filename.endswith(".pdf"):
50
+ return {"error": "Only PDF files are supported."}
51
+
52
  contents = await file.read()
53
+ try:
54
+ process_pdf_and_store(file_bytes=contents, filename=file.filename)
55
+ return {"message": f"Successfully processed and stored '{file.filename}'"}
56
+ except Exception as e:
57
+ return {"error": f"Failed to process PDF: {str(e)}"}
58
 
59
+ # Search top K results
60
  @app.post("/search/")
61
  async def search_text(query: str = Form(...), top_k: int = 3):
62
+ try:
63
+ embedding = model.encode(query, normalize_embeddings=True).tolist()
64
+ results = collection.query(query_embeddings=[embedding], n_results=top_k)
65
+
66
+ return {
67
+ "query": query,
68
+ "results": [
69
+ {
70
+ "filename": metadata["filename"],
71
+ "page": metadata["page"],
72
+ "snippet": doc[:200] + "..." if len(doc) > 200 else doc,
73
+ "score": score
74
+ }
75
+ for doc, metadata, score in zip(
76
+ results["documents"][0],
77
+ results["metadatas"][0],
78
+ results["distances"][0]
79
+ )
80
+ ]
81
+ }
82
+ except Exception as e:
83
+ return {"error": f"Search failed: {str(e)}"}
84
+
85
+ # Search + send top result to RedMind API
86
+ @app.post("/search-and-query/")
87
+ async def search_and_query_redmind(question: str = Form(...)):
88
+ try:
89
+ # Get document embedding
90
+ embedding = model.encode(question, normalize_embeddings=True).tolist()
91
+ results = collection.query(query_embeddings=[embedding], n_results=1)
92
+
93
+ if not results["documents"][0]:
94
+ return {"error": "No relevant document found."}
95
+
96
+ top_doc = results["documents"][0][0]
97
+
98
+ # Send top doc + question to RedMind
99
+ headers = {
100
+ "Authorization": f"Bearer {REDMIND_API_KEY}",
101
+ "Content-Type": "application/json"
102
+ }
103
+
104
+ payload = {
105
+ "input": f"Context: {top_doc}\n\nQuestion: {question}"
106
+ }
107
+
108
+ async with httpx.AsyncClient() as client:
109
+ response = await client.post(REDMIND_API_URL, headers=headers, json=payload)
110
+ response.raise_for_status()
111
+ answer = response.json()
112
+
113
+ return {
114
+ "question": question,
115
+ "top_document_snippet": top_doc[:200] + "...",
116
+ "redmind_response": answer
117
+ }
118
+
119
+ except Exception as e:
120
+ return {"error": f"RedMind integration failed: {str(e)}"}
121
+
122
+ # List all stored documents (for dev use)
123
+ @app.get("/list-docs/")
124
+ def list_documents():
125
+ try:
126
+ return collection.peek()
127
+ except Exception as e:
128
+ return {"error": f"Failed to list documents: {str(e)}"}