| import os |
| from flask import Blueprint, request, jsonify |
| import requests |
| from pymongo import MongoClient |
| from bson.objectid import ObjectId |
| from werkzeug.utils import secure_filename |
|
|
| from application.api.user.tasks import ingest |
|
|
| from application.core.settings import settings |
| from application.vectorstore.vector_creator import VectorCreator |
|
|
| mongo = MongoClient(settings.MONGO_URI) |
| db = mongo["docsgpt"] |
| conversations_collection = db["conversations"] |
| vectors_collection = db["vectors"] |
| prompts_collection = db["prompts"] |
| feedback_collection = db["feedback"] |
| user = Blueprint('user', __name__) |
|
|
| current_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) |
|
|
| @user.route("/api/delete_conversation", methods=["POST"]) |
| def delete_conversation(): |
| |
| conversation_id = request.args.get("id") |
| |
| conversations_collection.delete_one( |
| { |
| "_id": ObjectId(conversation_id), |
| } |
| ) |
|
|
| return {"status": "ok"} |
|
|
| @user.route("/api/get_conversations", methods=["get"]) |
| def get_conversations(): |
| |
| conversations = conversations_collection.find().sort("date", -1) |
| list_conversations = [] |
| for conversation in conversations: |
| list_conversations.append({"id": str(conversation["_id"]), "name": conversation["name"]}) |
|
|
| |
|
|
| return jsonify(list_conversations) |
|
|
|
|
| @user.route("/api/get_single_conversation", methods=["get"]) |
| def get_single_conversation(): |
| |
| conversation_id = request.args.get("id") |
| conversation = conversations_collection.find_one({"_id": ObjectId(conversation_id)}) |
| return jsonify(conversation['queries']) |
|
|
| @user.route("/api/update_conversation_name", methods=["POST"]) |
| def update_conversation_name(): |
| |
| data = request.get_json() |
| id = data["id"] |
| name = data["name"] |
| conversations_collection.update_one({"_id": ObjectId(id)},{"$set":{"name":name}}) |
| return {"status": "ok"} |
|
|
|
|
| @user.route("/api/feedback", methods=["POST"]) |
| def api_feedback(): |
| data = request.get_json() |
| question = data["question"] |
| answer = data["answer"] |
| feedback = data["feedback"] |
|
|
|
|
| feedback_collection.insert_one( |
| { |
| "question": question, |
| "answer": answer, |
| "feedback": feedback, |
| } |
| ) |
| return {"status": "ok"} |
|
|
| @user.route("/api/delete_by_ids", methods=["get"]) |
| def delete_by_ids(): |
| """Delete by ID. These are the IDs in the vectorstore""" |
|
|
| ids = request.args.get("path") |
| if not ids: |
| return {"status": "error"} |
|
|
| if settings.VECTOR_STORE == "faiss": |
| result = vectors_collection.delete_index(ids=ids) |
| if result: |
| return {"status": "ok"} |
| return {"status": "error"} |
|
|
| @user.route("/api/delete_old", methods=["get"]) |
| def delete_old(): |
| """Delete old indexes.""" |
| import shutil |
|
|
| path = request.args.get("path") |
| dirs = path.split("/") |
| dirs_clean = [] |
| for i in range(0, len(dirs)): |
| dirs_clean.append(secure_filename(dirs[i])) |
| |
|
|
| if dirs_clean[0] not in ["indexes", "vectors"]: |
| return {"status": "error"} |
| path_clean = "/".join(dirs_clean) |
| vectors_collection.delete_one({"name": dirs_clean[-1], 'user': dirs_clean[-2]}) |
| if settings.VECTOR_STORE == "faiss": |
| try: |
| shutil.rmtree(os.path.join(current_dir, path_clean)) |
| except FileNotFoundError: |
| pass |
| else: |
| vetorstore = VectorCreator.create_vectorstore( |
| settings.VECTOR_STORE, path=os.path.join(current_dir, path_clean) |
| ) |
| vetorstore.delete_index() |
| |
| return {"status": "ok"} |
|
|
| @user.route("/api/upload", methods=["POST"]) |
| def upload_file(): |
| """Upload a file to get vectorized and indexed.""" |
| if "user" not in request.form: |
| return {"status": "no user"} |
| user = secure_filename(request.form["user"]) |
| if "name" not in request.form: |
| return {"status": "no name"} |
| job_name = secure_filename(request.form["name"]) |
| |
| if "file" not in request.files: |
| print("No file part") |
| return {"status": "no file"} |
| file = request.files["file"] |
| if file.filename == "": |
| return {"status": "no file name"} |
|
|
| if file: |
| filename = secure_filename(file.filename) |
| |
| save_dir = os.path.join(current_dir, settings.UPLOAD_FOLDER, user, job_name) |
| |
| if not os.path.exists(save_dir): |
| os.makedirs(save_dir) |
|
|
| file.save(os.path.join(save_dir, filename)) |
| task = ingest.delay(settings.UPLOAD_FOLDER, [".rst", ".md", ".pdf", ".txt", ".docx", |
| ".csv", ".epub", ".html", ".mdx"], |
| job_name, filename, user) |
| |
| task_id = task.id |
| return {"status": "ok", "task_id": task_id} |
| else: |
| return {"status": "error"} |
|
|
| @user.route("/api/task_status", methods=["GET"]) |
| def task_status(): |
| """Get celery job status.""" |
| task_id = request.args.get("task_id") |
| from application.celery import celery |
| task = celery.AsyncResult(task_id) |
| task_meta = task.info |
| return {"status": task.status, "result": task_meta} |
|
|
|
|
| @user.route("/api/combine", methods=["GET"]) |
| def combined_json(): |
| user = "local" |
| """Provide json file with combined available indexes.""" |
| |
|
|
| data = [ |
| { |
| "name": "default", |
| "language": "default", |
| "version": "", |
| "description": "default", |
| "fullName": "default", |
| "date": "default", |
| "docLink": "default", |
| "model": settings.EMBEDDINGS_NAME, |
| "location": "remote", |
| } |
| ] |
| |
| |
| for index in vectors_collection.find({"user": user}): |
| data.append( |
| { |
| "name": index["name"], |
| "language": index["language"], |
| "version": "", |
| "description": index["name"], |
| "fullName": index["name"], |
| "date": index["date"], |
| "docLink": index["location"], |
| "model": settings.EMBEDDINGS_NAME, |
| "location": "local", |
| } |
| ) |
| if settings.VECTOR_STORE == "faiss": |
| data_remote = requests.get("https://d3dg1063dc54p9.cloudfront.net/combined.json").json() |
| for index in data_remote: |
| index["location"] = "remote" |
| data.append(index) |
|
|
| return jsonify(data) |
|
|
|
|
| @user.route("/api/docs_check", methods=["POST"]) |
| def check_docs(): |
| |
| data = request.get_json() |
| |
| if data["docs"].split("/")[0] == "local": |
| return {"status": "exists"} |
| vectorstore = "vectors/" + data["docs"] |
| base_path = "https://raw.githubusercontent.com/arc53/DocsHUB/main/" |
| if os.path.exists(vectorstore) or data["docs"] == "default": |
| return {"status": "exists"} |
| else: |
| r = requests.get(base_path + vectorstore + "index.faiss") |
|
|
| if r.status_code != 200: |
| return {"status": "null"} |
| else: |
| if not os.path.exists(vectorstore): |
| os.makedirs(vectorstore) |
| with open(vectorstore + "index.faiss", "wb") as f: |
| f.write(r.content) |
|
|
| |
| r = requests.get(base_path + vectorstore + "index.pkl") |
| with open(vectorstore + "index.pkl", "wb") as f: |
| f.write(r.content) |
|
|
| return {"status": "loaded"} |
|
|
| @user.route("/api/create_prompt", methods=["POST"]) |
| def create_prompt(): |
| data = request.get_json() |
| content = data["content"] |
| name = data["name"] |
| if name == "": |
| return {"status": "error"} |
| user = "local" |
| resp = prompts_collection.insert_one( |
| { |
| "name": name, |
| "content": content, |
| "user": user, |
| } |
| ) |
| new_id = str(resp.inserted_id) |
| return {"id": new_id} |
|
|
| @user.route("/api/get_prompts", methods=["GET"]) |
| def get_prompts(): |
| user = "local" |
| prompts = prompts_collection.find({"user": user}) |
| list_prompts = [] |
| list_prompts.append({"id": "default", "name": "default", "type": "public"}) |
| list_prompts.append({"id": "creative", "name": "creative", "type": "public"}) |
| list_prompts.append({"id": "strict", "name": "strict", "type": "public"}) |
| for prompt in prompts: |
| list_prompts.append({"id": str(prompt["_id"]), "name": prompt["name"], "type": "private"}) |
|
|
| return jsonify(list_prompts) |
|
|
| @user.route("/api/get_single_prompt", methods=["GET"]) |
| def get_single_prompt(): |
| prompt_id = request.args.get("id") |
| if prompt_id == 'default': |
| with open(os.path.join(current_dir, "prompts", "chat_combine_default.txt"), "r") as f: |
| chat_combine_template = f.read() |
| return jsonify({"content": chat_combine_template}) |
| elif prompt_id == 'creative': |
| with open(os.path.join(current_dir, "prompts", "chat_combine_creative.txt"), "r") as f: |
| chat_reduce_creative = f.read() |
| return jsonify({"content": chat_reduce_creative}) |
| elif prompt_id == 'strict': |
| with open(os.path.join(current_dir, "prompts", "chat_combine_strict.txt"), "r") as f: |
| chat_reduce_strict = f.read() |
| return jsonify({"content": chat_reduce_strict}) |
|
|
|
|
| prompt = prompts_collection.find_one({"_id": ObjectId(prompt_id)}) |
| return jsonify({"content": prompt["content"]}) |
|
|
| @user.route("/api/delete_prompt", methods=["POST"]) |
| def delete_prompt(): |
| data = request.get_json() |
| id = data["id"] |
| prompts_collection.delete_one( |
| { |
| "_id": ObjectId(id), |
| } |
| ) |
| return {"status": "ok"} |
|
|
| @user.route("/api/update_prompt", methods=["POST"]) |
| def update_prompt_name(): |
| data = request.get_json() |
| id = data["id"] |
| name = data["name"] |
| content = data["content"] |
| |
| if name == "": |
| return {"status": "error"} |
| prompts_collection.update_one({"_id": ObjectId(id)},{"$set":{"name":name, "content": content}}) |
| return {"status": "ok"} |
|
|
|
|
|
|
|
|
|
|
|
|