mirror of
https://github.com/arc53/DocsGPT.git
synced 2025-11-29 16:43:16 +00:00
302 lines
12 KiB
Python
302 lines
12 KiB
Python
"""Conversation sharing routes."""
|
|
|
|
import uuid
|
|
|
|
from bson.binary import Binary, UuidRepresentation
|
|
from bson.dbref import DBRef
|
|
from bson.objectid import ObjectId
|
|
from flask import current_app, jsonify, make_response, request
|
|
from flask_restx import fields, inputs, Namespace, Resource
|
|
|
|
from application.api import api
|
|
from application.api.user.base import (
|
|
agents_collection,
|
|
attachments_collection,
|
|
conversations_collection,
|
|
db,
|
|
shared_conversations_collections,
|
|
)
|
|
from application.utils import check_required_fields
|
|
|
|
sharing_ns = Namespace(
|
|
"sharing", description="Conversation sharing operations", path="/api"
|
|
)
|
|
|
|
|
|
@sharing_ns.route("/share")
|
|
class ShareConversation(Resource):
|
|
share_conversation_model = api.model(
|
|
"ShareConversationModel",
|
|
{
|
|
"conversation_id": fields.String(
|
|
required=True, description="Conversation ID"
|
|
),
|
|
"user": fields.String(description="User ID (optional)"),
|
|
"prompt_id": fields.String(description="Prompt ID (optional)"),
|
|
"chunks": fields.Integer(description="Chunks count (optional)"),
|
|
},
|
|
)
|
|
|
|
@api.expect(share_conversation_model)
|
|
@api.doc(description="Share a conversation")
|
|
def post(self):
|
|
decoded_token = request.decoded_token
|
|
if not decoded_token:
|
|
return make_response(jsonify({"success": False}), 401)
|
|
user = decoded_token.get("sub")
|
|
data = request.get_json()
|
|
required_fields = ["conversation_id"]
|
|
missing_fields = check_required_fields(data, required_fields)
|
|
if missing_fields:
|
|
return missing_fields
|
|
is_promptable = request.args.get("isPromptable", type=inputs.boolean)
|
|
if is_promptable is None:
|
|
return make_response(
|
|
jsonify({"success": False, "message": "isPromptable is required"}), 400
|
|
)
|
|
conversation_id = data["conversation_id"]
|
|
|
|
try:
|
|
conversation = conversations_collection.find_one(
|
|
{"_id": ObjectId(conversation_id)}
|
|
)
|
|
if conversation is None:
|
|
return make_response(
|
|
jsonify(
|
|
{
|
|
"status": "error",
|
|
"message": "Conversation does not exist",
|
|
}
|
|
),
|
|
404,
|
|
)
|
|
current_n_queries = len(conversation["queries"])
|
|
explicit_binary = Binary.from_uuid(
|
|
uuid.uuid4(), UuidRepresentation.STANDARD
|
|
)
|
|
|
|
if is_promptable:
|
|
prompt_id = data.get("prompt_id", "default")
|
|
chunks = data.get("chunks", "2")
|
|
|
|
name = conversation["name"] + "(shared)"
|
|
new_api_key_data = {
|
|
"prompt_id": prompt_id,
|
|
"chunks": chunks,
|
|
"user": user,
|
|
}
|
|
|
|
if "source" in data and ObjectId.is_valid(data["source"]):
|
|
new_api_key_data["source"] = DBRef(
|
|
"sources", ObjectId(data["source"])
|
|
)
|
|
if "retriever" in data:
|
|
new_api_key_data["retriever"] = data["retriever"]
|
|
pre_existing_api_document = agents_collection.find_one(new_api_key_data)
|
|
if pre_existing_api_document:
|
|
api_uuid = pre_existing_api_document["key"]
|
|
pre_existing = shared_conversations_collections.find_one(
|
|
{
|
|
"conversation_id": DBRef(
|
|
"conversations", ObjectId(conversation_id)
|
|
),
|
|
"isPromptable": is_promptable,
|
|
"first_n_queries": current_n_queries,
|
|
"user": user,
|
|
"api_key": api_uuid,
|
|
}
|
|
)
|
|
if pre_existing is not None:
|
|
return make_response(
|
|
jsonify(
|
|
{
|
|
"success": True,
|
|
"identifier": str(pre_existing["uuid"].as_uuid()),
|
|
}
|
|
),
|
|
200,
|
|
)
|
|
else:
|
|
shared_conversations_collections.insert_one(
|
|
{
|
|
"uuid": explicit_binary,
|
|
"conversation_id": {
|
|
"$ref": "conversations",
|
|
"$id": ObjectId(conversation_id),
|
|
},
|
|
"isPromptable": is_promptable,
|
|
"first_n_queries": current_n_queries,
|
|
"user": user,
|
|
"api_key": api_uuid,
|
|
}
|
|
)
|
|
return make_response(
|
|
jsonify(
|
|
{
|
|
"success": True,
|
|
"identifier": str(explicit_binary.as_uuid()),
|
|
}
|
|
),
|
|
201,
|
|
)
|
|
else:
|
|
api_uuid = str(uuid.uuid4())
|
|
new_api_key_data["key"] = api_uuid
|
|
new_api_key_data["name"] = name
|
|
|
|
if "source" in data and ObjectId.is_valid(data["source"]):
|
|
new_api_key_data["source"] = DBRef(
|
|
"sources", ObjectId(data["source"])
|
|
)
|
|
if "retriever" in data:
|
|
new_api_key_data["retriever"] = data["retriever"]
|
|
agents_collection.insert_one(new_api_key_data)
|
|
shared_conversations_collections.insert_one(
|
|
{
|
|
"uuid": explicit_binary,
|
|
"conversation_id": {
|
|
"$ref": "conversations",
|
|
"$id": ObjectId(conversation_id),
|
|
},
|
|
"isPromptable": is_promptable,
|
|
"first_n_queries": current_n_queries,
|
|
"user": user,
|
|
"api_key": api_uuid,
|
|
}
|
|
)
|
|
return make_response(
|
|
jsonify(
|
|
{
|
|
"success": True,
|
|
"identifier": str(explicit_binary.as_uuid()),
|
|
}
|
|
),
|
|
201,
|
|
)
|
|
pre_existing = shared_conversations_collections.find_one(
|
|
{
|
|
"conversation_id": DBRef(
|
|
"conversations", ObjectId(conversation_id)
|
|
),
|
|
"isPromptable": is_promptable,
|
|
"first_n_queries": current_n_queries,
|
|
"user": user,
|
|
}
|
|
)
|
|
if pre_existing is not None:
|
|
return make_response(
|
|
jsonify(
|
|
{
|
|
"success": True,
|
|
"identifier": str(pre_existing["uuid"].as_uuid()),
|
|
}
|
|
),
|
|
200,
|
|
)
|
|
else:
|
|
shared_conversations_collections.insert_one(
|
|
{
|
|
"uuid": explicit_binary,
|
|
"conversation_id": {
|
|
"$ref": "conversations",
|
|
"$id": ObjectId(conversation_id),
|
|
},
|
|
"isPromptable": is_promptable,
|
|
"first_n_queries": current_n_queries,
|
|
"user": user,
|
|
}
|
|
)
|
|
return make_response(
|
|
jsonify(
|
|
{"success": True, "identifier": str(explicit_binary.as_uuid())}
|
|
),
|
|
201,
|
|
)
|
|
except Exception as err:
|
|
current_app.logger.error(
|
|
f"Error sharing conversation: {err}", exc_info=True
|
|
)
|
|
return make_response(jsonify({"success": False}), 400)
|
|
|
|
|
|
@sharing_ns.route("/shared_conversation/<string:identifier>")
|
|
class GetPubliclySharedConversations(Resource):
|
|
@api.doc(description="Get publicly shared conversations by identifier")
|
|
def get(self, identifier: str):
|
|
try:
|
|
query_uuid = Binary.from_uuid(
|
|
uuid.UUID(identifier), UuidRepresentation.STANDARD
|
|
)
|
|
shared = shared_conversations_collections.find_one({"uuid": query_uuid})
|
|
conversation_queries = []
|
|
|
|
if (
|
|
shared
|
|
and "conversation_id" in shared
|
|
and isinstance(shared["conversation_id"], DBRef)
|
|
):
|
|
conversation_ref = shared["conversation_id"]
|
|
conversation = db.dereference(conversation_ref)
|
|
if conversation is None:
|
|
return make_response(
|
|
jsonify(
|
|
{
|
|
"success": False,
|
|
"error": "might have broken url or the conversation does not exist",
|
|
}
|
|
),
|
|
404,
|
|
)
|
|
conversation_queries = conversation["queries"][
|
|
: (shared["first_n_queries"])
|
|
]
|
|
|
|
for query in conversation_queries:
|
|
if "attachments" in query and query["attachments"]:
|
|
attachment_details = []
|
|
for attachment_id in query["attachments"]:
|
|
try:
|
|
attachment = attachments_collection.find_one(
|
|
{"_id": ObjectId(attachment_id)}
|
|
)
|
|
if attachment:
|
|
attachment_details.append(
|
|
{
|
|
"id": str(attachment["_id"]),
|
|
"fileName": attachment.get(
|
|
"filename", "Unknown file"
|
|
),
|
|
}
|
|
)
|
|
except Exception as e:
|
|
current_app.logger.error(
|
|
f"Error retrieving attachment {attachment_id}: {e}",
|
|
exc_info=True,
|
|
)
|
|
query["attachments"] = attachment_details
|
|
else:
|
|
return make_response(
|
|
jsonify(
|
|
{
|
|
"success": False,
|
|
"error": "might have broken url or the conversation does not exist",
|
|
}
|
|
),
|
|
404,
|
|
)
|
|
date = conversation["_id"].generation_time.isoformat()
|
|
res = {
|
|
"success": True,
|
|
"queries": conversation_queries,
|
|
"title": conversation["name"],
|
|
"timestamp": date,
|
|
}
|
|
if shared["isPromptable"] and "api_key" in shared:
|
|
res["api_key"] = shared["api_key"]
|
|
return make_response(jsonify(res), 200)
|
|
except Exception as err:
|
|
current_app.logger.error(
|
|
f"Error getting shared conversation: {err}", exc_info=True
|
|
)
|
|
return make_response(jsonify({"success": False}), 400)
|