| from fastapi import FastAPI, Request, Query |
| from fastapi.templating import Jinja2Templates |
| from fastapi import File, UploadFile |
| from fastapi.responses import FileResponse |
| from fastapi.responses import Response |
|
|
| from pydantic import BaseModel |
| from sentence_transformers import SentenceTransformer |
| import faiss |
| import numpy as np |
| import json |
| import io |
|
|
| app = FastAPI() |
| model = SentenceTransformer('paraphrase-MiniLM-L6-v2') |
| embedding_dimension = 384 |
| index = faiss.IndexFlatL2(embedding_dimension) |
| documents = [] |
|
|
| templates = Jinja2Templates(directory=".") |
|
|
| class EmbedRequest(BaseModel): |
| texts: list[str] |
|
|
| class SearchRequest(BaseModel): |
| text: str |
| n: int = 5 |
| |
| @app.get("/") |
| def read_root(request: Request): |
| return templates.TemplateResponse("index.html", {"request": request}) |
|
|
|
|
| @app.post("/embed") |
| def embed_strings(request: EmbedRequest): |
| new_documents = request.texts |
| new_embeddings = model.encode(new_documents) |
| index.add(np.array(new_embeddings)) |
| new_size = index.ntotal |
| documents.extend(new_documents) |
| return { |
| "message": f"{len(new_documents)} new strings embedded and added to FAISS database. New size of the database: {new_size}" |
| } |
|
|
|
|
| @app.post("/search") |
| def search_string(request: SearchRequest): |
| embedding = model.encode([request.text]) |
| distances, indices = index.search(np.array(embedding), request.n) |
|
|
| |
| found_documents = [documents[i] for i in indices[0]] |
|
|
| return { |
| "distances": distances[0].tolist(), |
| "indices": indices[0].tolist(), |
| "documents": found_documents |
| } |
|
|
| |
| |
| |
| @app.get("/admin/database/length") |
| def get_database_length(): |
| return {"length": index.ntotal} |
|
|
| @app.post("/admin/database/reset") |
| def reset_database(): |
| global index |
| global documents |
| index = faiss.IndexFlatL2(embedding_dimension) |
| documents = [] |
| return {"message": "Database reset"} |
|
|
| @app.get("/admin/documents/download") |
| def download_documents(): |
| |
| documents_json = json.dumps({"texts": documents}) |
|
|
| |
| response = Response(content=documents_json, media_type="application/json") |
|
|
| |
| response.headers["Content-Disposition"] = "attachment; filename=documents.json" |
|
|
| return response |
|
|
| |
| @app.post("/admin/documents/upload") |
| def upload_documents(request: EmbedRequest): |
| documents.extend(request.texts) |
| return { |
| "message": f"{len(documents)} new documents uploaded" |
| } |
|
|
| @app.get("/admin/database/download") |
| def download_database(): |
| |
| data = { |
| "index": faiss.write_index_binary(index), |
| "documents": documents |
| } |
| with open("database.json", "w") as f: |
| json.dump(data, f) |
|
|
| |
| response = FileResponse("database.json") |
|
|
| |
| response.headers["Content-Disposition"] = "attachment; filename=database.json" |
|
|
| return response |
|
|
| @app.post("/admin/database/upload") |
| def upload_database(file: UploadFile = File(...)): |
| |
| contents = json.load(file.file) |
|
|
| |
| index = faiss.read_index_binary(contents["index"]) |
|
|
| |
| documents.clear() |
| documents.extend(contents["documents"]) |
|
|
| return {"message": "Database uploaded", "documents": documents} |
|
|