From 87455d79e4192e5d56fc972852d620ba41887d59 Mon Sep 17 00:00:00 2001 From: liuhua <10215101452@stu.ecnu.edu.cn> Date: Tue, 3 Dec 2024 19:03:16 +0800 Subject: [PATCH] Add api for list agents and agent seesions (#3835) ### What problem does this PR solve? Add api for list agents and agent seesions ### Type of change - [x] New Feature (non-breaking change which adds functionality) Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn> --- api/apps/canvas_app.py | 2 +- api/apps/sdk/agent.py | 39 ++++++++++++++++++ api/apps/sdk/chat.py | 7 +++- api/apps/sdk/session.py | 66 ++++++++++++++++++++++++++++--- api/db/services/api_service.py | 16 ++++++++ api/db/services/canvas_service.py | 19 +++++++++ 6 files changed, 141 insertions(+), 8 deletions(-) create mode 100644 api/apps/sdk/agent.py diff --git a/api/apps/canvas_app.py b/api/apps/canvas_app.py index 0a397bb0f..b21ca87dc 100644 --- a/api/apps/canvas_app.py +++ b/api/apps/canvas_app.py @@ -65,7 +65,7 @@ def save(): req["dsl"] = json.loads(req["dsl"]) if "id" not in req: if UserCanvasService.query(user_id=current_user.id, title=req["title"].strip()): - return server_error_response(ValueError("Duplicated title.")) + return get_data_error_result(f"{req['title'].strip()} already exists.") req["id"] = get_uuid() if not UserCanvasService.save(**req): return get_data_error_result(message="Fail to save canvas.") diff --git a/api/apps/sdk/agent.py b/api/apps/sdk/agent.py new file mode 100644 index 000000000..0ea4bfa00 --- /dev/null +++ b/api/apps/sdk/agent.py @@ -0,0 +1,39 @@ +# +# Copyright 2024 The InfiniFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +from api.db.services.canvas_service import CanvasTemplateService, UserCanvasService +from api.utils.api_utils import get_error_data_result, token_required +from api.utils.api_utils import get_result +from flask import request + +@manager.route('/agents', methods=['GET']) +@token_required +def list_agents(tenant_id): + id = request.args.get("id") + title = request.args.get("title") + if id or title: + canvas = UserCanvasService.query(id=id, title=title, user_id=tenant_id) + if not canvas: + return get_error_data_result("The agent doesn't exist.") + page_number = int(request.args.get("page", 1)) + items_per_page = int(request.args.get("page_size", 30)) + orderby = request.args.get("orderby", "update_time") + if request.args.get("desc") == "False" or request.args.get("desc") == "false": + desc = False + else: + desc = True + canvas = UserCanvasService.get_list(tenant_id,page_number,items_per_page,orderby,desc,id,title) + return get_result(data=canvas) diff --git a/api/apps/sdk/chat.py b/api/apps/sdk/chat.py index 0f7509aac..aea6a74bf 100644 --- a/api/apps/sdk/chat.py +++ b/api/apps/sdk/chat.py @@ -104,9 +104,12 @@ def create(tenant_id): "parameters": [ {"key": "knowledge", "optional": False} ], - "empty_response": "Sorry! No relevant content was found in the knowledge base!" + "empty_response": "Sorry! No relevant content was found in the knowledge base!", + "quote":True, + "tts":False, + "refine_multiturn":True } - key_list_2 = ["system", "prologue", "parameters", "empty_response"] + key_list_2 = ["system", "prologue", "parameters", "empty_response","quote","tts","refine_multiturn"] if "prompt_config" not in req: req['prompt_config'] = {} for key in key_list_2: diff --git a/api/apps/sdk/session.py b/api/apps/sdk/session.py index 117016bab..9c3dee32e 100644 --- a/api/apps/sdk/session.py +++ b/api/apps/sdk/session.py @@ -63,7 +63,6 @@ def create(tenant_id,chat_id): @manager.route('/agents//sessions', methods=['POST']) @token_required def create_agent_session(tenant_id, agent_id): - req = request.json e, cvs = UserCanvasService.get_by_id(agent_id) if not e: return get_error_data_result("Agent not found.") @@ -77,7 +76,7 @@ def create_agent_session(tenant_id, agent_id): conv = { "id": get_uuid(), "dialog_id": cvs.id, - "user_id": req.get("usr_id","") if isinstance(req, dict) else "", + "user_id": tenant_id, "message": [{"role": "assistant", "content": canvas.get_prologue()}], "source": "agent", "dsl":json.loads(cvs.dsl) @@ -112,13 +111,16 @@ def update(tenant_id,chat_id,session_id): @manager.route('/chats//completions', methods=['POST']) @token_required def completion(tenant_id, chat_id): + dia= DialogService.query(id=chat_id, tenant_id=tenant_id, status=StatusEnum.VALID.value) + if not dia: + return get_error_data_result(message="You do not own the chat") req = request.json if not req.get("session_id"): conv = { "id": get_uuid(), "dialog_id": chat_id, "name": req.get("name", "New session"), - "message": [{"role": "assistant", "content": "Hi! I am your assistant,can I help you?"}] + "message": [{"role": "assistant", "content": dia[0].prompt_config.get("prologue")}] } if not conv.get("name"): return get_error_data_result(message="`name` can not be empty.") @@ -133,8 +135,6 @@ def completion(tenant_id, chat_id): if not conv: return get_error_data_result(message="Session does not exist") conv = conv[0] - if not DialogService.query(id=chat_id, tenant_id=tenant_id, status=StatusEnum.VALID.value): - return get_error_data_result(message="You do not own the chat") msg = [] question = { "content": req.get("question"), @@ -374,6 +374,8 @@ def agent_completion(tenant_id, agent_id): rename_field(result) return get_result(data=result) + + @manager.route('/chats//sessions', methods=['GET']) @token_required def list_session(chat_id,tenant_id): @@ -427,6 +429,60 @@ def list_session(chat_id,tenant_id): del conv["reference"] return get_result(data=convs) +@manager.route('/agents//sessions', methods=['GET']) +@token_required +def list_agent_session(agent_id,tenant_id): + if not UserCanvasService.query(user_id=tenant_id, id=agent_id): + return get_error_data_result(message=f"You don't own the agent {agent_id}.") + id = request.args.get("id") + if not API4ConversationService.query(id=id,user_id=tenant_id): + return get_error_data_result(f"You don't own the session {id}") + page_number = int(request.args.get("page", 1)) + items_per_page = int(request.args.get("page_size", 30)) + orderby = request.args.get("orderby", "update_time") + if request.args.get("desc") == "False" or request.args.get("desc") == "false": + desc = False + else: + desc = True + convs = API4ConversationService.get_list(agent_id,tenant_id,page_number,items_per_page,orderby,desc,id) + if not convs: + return get_result(data=[]) + for conv in convs: + conv['messages'] = conv.pop("message") + infos = conv["messages"] + for info in infos: + if "prompt" in info: + info.pop("prompt") + conv["agent_id"] = conv.pop("dialog_id") + if conv["reference"]: + messages = conv["messages"] + message_num = 0 + chunk_num = 0 + while message_num < len(messages): + if message_num != 0 and messages[message_num]["role"] != "user": + chunk_list = [] + if "chunks" in conv["reference"][chunk_num]: + chunks = conv["reference"][chunk_num]["chunks"] + for chunk in chunks: + new_chunk = { + "id": chunk["chunk_id"], + "content": chunk["content"], + "document_id": chunk["doc_id"], + "document_name": chunk["docnm_kwd"], + "dataset_id": chunk["kb_id"], + "image_id": chunk.get("image_id", ""), + "similarity": chunk["similarity"], + "vector_similarity": chunk["vector_similarity"], + "term_similarity": chunk["term_similarity"], + "positions": chunk["positions"], + } + chunk_list.append(new_chunk) + chunk_num += 1 + messages[message_num]["reference"] = chunk_list + message_num += 1 + del conv["reference"] + return get_result(data=convs) + @manager.route('/chats//sessions', methods=["DELETE"]) @token_required diff --git a/api/db/services/api_service.py b/api/db/services/api_service.py index 24226d442..864e66432 100644 --- a/api/db/services/api_service.py +++ b/api/db/services/api_service.py @@ -39,6 +39,22 @@ class APITokenService(CommonService): class API4ConversationService(CommonService): model = API4Conversation + @classmethod + @DB.connection_context() + def get_list(cls,dialog_id, tenant_id, + page_number, items_per_page, orderby, desc, id): + sessions = cls.model.select().where(cls.model.dialog_id ==dialog_id) + if id: + sessions = sessions.where(cls.model.id == id) + if desc: + sessions = sessions.order_by(cls.model.getter_by(orderby).desc()) + else: + sessions = sessions.order_by(cls.model.getter_by(orderby).asc()) + sessions = sessions.where(cls.model.user_id == tenant_id) + sessions = sessions.paginate(page_number, items_per_page) + + return list(sessions.dicts()) + @classmethod @DB.connection_context() def append_message(cls, id, conversation): diff --git a/api/db/services/canvas_service.py b/api/db/services/canvas_service.py index 112dcf0bf..23eb18693 100644 --- a/api/db/services/canvas_service.py +++ b/api/db/services/canvas_service.py @@ -25,3 +25,22 @@ class CanvasTemplateService(CommonService): class UserCanvasService(CommonService): model = UserCanvas + + @classmethod + @DB.connection_context() + def get_list(cls, tenant_id, + page_number, items_per_page, orderby, desc, id, title): + agents = cls.model.select() + if id: + agents = agents.where(cls.model.id == id) + if title: + agents = agents.where(cls.model.title == title) + agents = agents.where(cls.model.user_id == tenant_id) + if desc: + agents = agents.order_by(cls.model.getter_by(orderby).desc()) + else: + agents = agents.order_by(cls.model.getter_by(orderby).asc()) + + agents = agents.paginate(page_number, items_per_page) + + return list(agents.dicts())