### What problem does this PR solve? Update the component of the agent API with parameters. ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) - [x] New Feature (non-breaking change which adds functionality) - [x] Refactoring --------- Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn> Co-authored-by: Kevin Hu <kevinhu.sh@gmail.com> Co-authored-by: writinwaters <93570324+writinwaters@users.noreply.github.com>tags/v0.15.1
| @@ -267,9 +267,10 @@ def delete(tenant_id): | |||
| def list_chat(tenant_id): | |||
| id = request.args.get("id") | |||
| name = request.args.get("name") | |||
| chat = DialogService.query(id=id,name=name,status=StatusEnum.VALID.value,tenant_id=tenant_id) | |||
| if not chat: | |||
| return get_error_data_result(message="The chat doesn't exist") | |||
| if id or name: | |||
| chat = DialogService.query(id=id, name=name, status=StatusEnum.VALID.value, tenant_id=tenant_id) | |||
| if not chat: | |||
| return get_error_data_result(message="The chat 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", "create_time") | |||
| @@ -77,15 +77,28 @@ def create_agent_session(tenant_id, agent_id): | |||
| cvs.dsl = json.dumps(cvs.dsl, ensure_ascii=False) | |||
| canvas = Canvas(cvs.dsl, tenant_id) | |||
| if canvas.get_preset_param(): | |||
| return get_error_data_result("The agent cannot create a session directly") | |||
| canvas.reset() | |||
| query = canvas.get_preset_param() | |||
| if query: | |||
| for ele in query: | |||
| if not ele["optional"]: | |||
| if not req.get(ele["key"]): | |||
| return get_error_data_result(f"`{ele['key']}` is required") | |||
| ele["value"] = req[ele["key"]] | |||
| if ele["optional"]: | |||
| if req.get(ele["key"]): | |||
| ele["value"] = req[ele['key']] | |||
| else: | |||
| if "value" in ele: | |||
| ele.pop("value") | |||
| cvs.dsl = json.loads(str(canvas)) | |||
| conv = { | |||
| "id": get_uuid(), | |||
| "dialog_id": cvs.id, | |||
| "user_id": req.get("usr_id","") if isinstance(req, dict) else "", | |||
| "message": [{"role": "assistant", "content": canvas.get_prologue()}], | |||
| "source": "agent", | |||
| "dsl": json.loads(cvs.dsl) | |||
| "dsl": cvs.dsl | |||
| } | |||
| API4ConversationService.save(**conv) | |||
| conv["agent_id"] = conv.pop("dialog_id") | |||
| @@ -149,6 +162,12 @@ def agent_completions(tenant_id, agent_id): | |||
| if not cvs: | |||
| return get_error_data_result(f"You don't own the agent {agent_id}") | |||
| if req.get("session_id"): | |||
| dsl = cvs[0].dsl | |||
| if not isinstance(dsl,str): | |||
| dsl = json.dumps(dsl) | |||
| canvas=Canvas(dsl,tenant_id) | |||
| if canvas.get_preset_param(): | |||
| req["question"]="" | |||
| conv = API4ConversationService.query(id=req["session_id"], dialog_id=agent_id) | |||
| if not conv: | |||
| return get_error_data_result(f"You don't own the session {req['session_id']}") | |||
| @@ -74,21 +74,32 @@ def completion(tenant_id, agent_id, question, session_id=None, stream=True, **kw | |||
| else: | |||
| if "value" in ele: | |||
| ele.pop("value") | |||
| cvs.dsl = json.loads(str(canvas)) | |||
| temp_dsl = cvs.dsl | |||
| UserCanvasService.update_by_id(agent_id, cvs.to_dict()) | |||
| else: | |||
| temp_dsl = json.loads(cvs.dsl) | |||
| session_id = get_uuid() | |||
| cvs.dsl = json.loads(str(canvas)) | |||
| session_id=get_uuid() | |||
| conv = { | |||
| "id": session_id, | |||
| "dialog_id": cvs.id, | |||
| "user_id": kwargs.get("user_id", ""), | |||
| "user_id": kwargs.get("usr_id", "") if isinstance(kwargs, dict) else "", | |||
| "message": [{"role": "assistant", "content": canvas.get_prologue()}], | |||
| "source": "agent", | |||
| "dsl": temp_dsl | |||
| "dsl": cvs.dsl | |||
| } | |||
| API4ConversationService.save(**conv) | |||
| conv = API4Conversation(**conv) | |||
| if query: | |||
| yield "data:" + json.dumps({"code": 0, | |||
| "message": "", | |||
| "data": { | |||
| "session_id": session_id, | |||
| "answer": canvas.get_prologue(), | |||
| "reference": [], | |||
| "param": canvas.get_preset_param() | |||
| } | |||
| }, | |||
| ensure_ascii=False) + "\n\n" | |||
| yield "data:" + json.dumps({"code": 0, "message": "", "data": True}, ensure_ascii=False) + "\n\n" | |||
| return | |||
| else: | |||
| conv = API4Conversation(**conv) | |||
| else: | |||
| e, conv = API4ConversationService.get_by_id(session_id) | |||
| assert e, "Session not found!" | |||
| @@ -283,7 +283,10 @@ def construct_error_response(e): | |||
| def token_required(func): | |||
| @wraps(func) | |||
| def decorated_function(*args, **kwargs): | |||
| authorization_list=flask_request.headers.get('Authorization').split() | |||
| authorization_str=flask_request.headers.get('Authorization') | |||
| if not authorization_str: | |||
| return get_json_result(data=False,message="`Authorization` can't be empty") | |||
| authorization_list=authorization_str.split() | |||
| if len(authorization_list) < 2: | |||
| return get_json_result(data=False,message="Please check your authorization format.") | |||
| token = authorization_list[1] | |||
| @@ -1346,7 +1346,7 @@ Creates a chat assistant. | |||
| curl --request POST \ | |||
| --url http://{address}/api/v1/chats \ | |||
| --header 'Content-Type: application/json' \ | |||
| --header 'Authorization: Bearer <YOUR_API_KEY>' | |||
| --header 'Authorization: Bearer <YOUR_API_KEY>' \ | |||
| --data '{ | |||
| "dataset_ids": ["0b2cbc8c877f11ef89070242ac120005"], | |||
| "name":"new_chat_1" | |||
| @@ -2160,15 +2160,28 @@ Creates a session with an agent. | |||
| - `'content-Type: application/json'` | |||
| - `'Authorization: Bearer <YOUR_API_KEY>'` | |||
| - Body: | |||
| - the required parameters:`str` | |||
| - the optional parameters:`str` | |||
| ##### Request example | |||
| If `begin` component in the agent doesn't have required parameters: | |||
| ```bash | |||
| curl --request POST \ | |||
| --url http://{address}/api/v1/agents/{agent_id}/sessions \ | |||
| --header 'Content-Type: application/json' \ | |||
| --header 'Authorization: Bearer <YOUR_API_KEY>' \ | |||
| --data '{ | |||
| }' | |||
| ``` | |||
| If `begin` component in the agent has required parameters: | |||
| ```bash | |||
| curl --request POST \ | |||
| --url http://{address}/api/v1/agents/{agent_id}/sessions \ | |||
| --header 'Content-Type: application/json' \ | |||
| --header 'Authorization: Bearer <YOUR_API_KEY>' \ | |||
| --data '{ | |||
| "lang":"Japanese", | |||
| "file":"Who are you" | |||
| }' | |||
| ``` | |||
| @@ -2326,8 +2339,8 @@ Asks a specified agent a question to start an AI-powered conversation. | |||
| - `"session_id"`: `string` | |||
| - other parameters: `string` | |||
| ##### Request example | |||
| ```bash | |||
| If the `begin` component doesn't have parameters, the following code will create a session. | |||
| ```bash | |||
| curl --request POST \ | |||
| --url http://{address}/api/v1/agents/{agent_id}/completions \ | |||
| --header 'Content-Type: application/json' \ | |||
| @@ -2336,6 +2349,7 @@ curl --request POST \ | |||
| { | |||
| }' | |||
| ``` | |||
| If the `begin` component have parameters, the following code will create a session. | |||
| ```bash | |||
| curl --request POST \ | |||
| --url http://{address}/api/v1/agents/{agent_id}/completions \ | |||
| @@ -2343,11 +2357,11 @@ curl --request POST \ | |||
| --header 'Authorization: Bearer <YOUR_API_KEY>' \ | |||
| --data-binary ' | |||
| { | |||
| "question": "Hello", | |||
| "stream": true, | |||
| "session_id": "cb2f385cb86211efa36e0242ac120005" | |||
| "lang":"English", | |||
| "file":"How is the weather tomorrow?" | |||
| }' | |||
| ``` | |||
| The following code will execute the completion process | |||
| ```bash | |||
| curl --request POST \ | |||
| --url http://{address}/api/v1/agents/{agent_id}/completions \ | |||
| @@ -2355,8 +2369,9 @@ curl --request POST \ | |||
| --header 'Authorization: Bearer <YOUR_API_KEY>' \ | |||
| --data-binary ' | |||
| { | |||
| "lang":"English" | |||
| "file":"How is the weather tomorrow?" | |||
| "question": "Hello", | |||
| "stream": true, | |||
| "session_id": "cb2f385cb86211efa36e0242ac120005" | |||
| }' | |||
| ``` | |||
| @@ -2394,113 +2409,41 @@ data:{ | |||
| "data": true | |||
| } | |||
| ``` | |||
| Success with `session_id` provided and with no parameters in the `begin` component: | |||
| Success without `session_id` provided and with parameters in the `begin` component: | |||
| ```json | |||
| data:{ | |||
| "code": 0, | |||
| "message": "", | |||
| "data": { | |||
| "session_id": "eacb36a0bdff11ef97120242ac120006", | |||
| "answer": "", | |||
| "reference": [], | |||
| "id": "7ed5c2e4-aa28-4397-bbed-59664a332aa0", | |||
| "session_id": "ce1b4fa89c1811ef85720242ac120006" | |||
| } | |||
| } | |||
| data:{ | |||
| "code": 0, | |||
| "data": { | |||
| "answer": "Hello", | |||
| "reference": [], | |||
| "id": "7ed5c2e4-aa28-4397-bbed-59664a332aa0", | |||
| "session_id": "ce1b4fa89c1811ef85720242ac120006" | |||
| } | |||
| } | |||
| data:{ | |||
| "code": 0, | |||
| "data": { | |||
| "answer": "Hello!", | |||
| "reference": [], | |||
| "id": "7ed5c2e4-aa28-4397-bbed-59664a332aa0", | |||
| "session_id": "ce1b4fa89c1811ef85720242ac120006" | |||
| } | |||
| } | |||
| data:{ | |||
| "code": 0, | |||
| "data": { | |||
| "answer": "Hello! How", | |||
| "reference": [], | |||
| "id": "7ed5c2e4-aa28-4397-bbed-59664a332aa0", | |||
| "session_id": "ce1b4fa89c1811ef85720242ac120006" | |||
| } | |||
| } | |||
| data:{ | |||
| "code": 0, | |||
| "data": { | |||
| "answer": "Hello! How can", | |||
| "reference": [], | |||
| "id": "7ed5c2e4-aa28-4397-bbed-59664a332aa0", | |||
| "session_id": "ce1b4fa89c1811ef85720242ac120006" | |||
| } | |||
| } | |||
| data:{ | |||
| "code": 0, | |||
| "data": { | |||
| "answer": "Hello! How can I", | |||
| "reference": [], | |||
| "id": "7ed5c2e4-aa28-4397-bbed-59664a332aa0", | |||
| "session_id": "ce1b4fa89c1811ef85720242ac120006" | |||
| } | |||
| } | |||
| data:{ | |||
| "code": 0, | |||
| "data": { | |||
| "answer": "Hello! How can I assist", | |||
| "reference": [], | |||
| "id": "7ed5c2e4-aa28-4397-bbed-59664a332aa0", | |||
| "session_id": "ce1b4fa89c1811ef85720242ac120006" | |||
| } | |||
| } | |||
| data:{ | |||
| "code": 0, | |||
| "data": { | |||
| "answer": "Hello! How can I assist you", | |||
| "reference": [], | |||
| "id": "7ed5c2e4-aa28-4397-bbed-59664a332aa0", | |||
| "session_id": "ce1b4fa89c1811ef85720242ac120006" | |||
| } | |||
| } | |||
| data:{ | |||
| "code": 0, | |||
| "data": { | |||
| "answer": "Hello! How can I assist you today", | |||
| "reference": [], | |||
| "id": "7ed5c2e4-aa28-4397-bbed-59664a332aa0", | |||
| "session_id": "ce1b4fa89c1811ef85720242ac120006" | |||
| } | |||
| } | |||
| data:{ | |||
| "code": 0, | |||
| "data": { | |||
| "answer": "Hello! How can I assist you today?", | |||
| "reference": [], | |||
| "id": "7ed5c2e4-aa28-4397-bbed-59664a332aa0", | |||
| "session_id": "ce1b4fa89c1811ef85720242ac120006" | |||
| } | |||
| } | |||
| data:{ | |||
| "code": 0, | |||
| "data": { | |||
| "answer": "Hello! How can I assist you today?", | |||
| "reference": [], | |||
| "id": "7ed5c2e4-aa28-4397-bbed-59664a332aa0", | |||
| "session_id": "ce1b4fa89c1811ef85720242ac120006" | |||
| "param": [ | |||
| { | |||
| "key": "lang", | |||
| "name": "Target Language", | |||
| "optional": false, | |||
| "type": "line", | |||
| "value": "English" | |||
| }, | |||
| { | |||
| "key": "file", | |||
| "name": "Files", | |||
| "optional": false, | |||
| "type": "file", | |||
| "value": "How is the weather tomorrow?" | |||
| }, | |||
| { | |||
| "key": "hhyt", | |||
| "name": "hhty", | |||
| "optional": true, | |||
| "type": "line" | |||
| } | |||
| ] | |||
| } | |||
| } | |||
| data:{ | |||
| "code": 0, | |||
| "data": true | |||
| } | |||
| data: | |||
| ``` | |||
| Success with parameters in the `begin` component: | |||
| ```json | |||
| @@ -1,4 +1,4 @@ | |||
| --- | |||
| from scipy.special import kwargs--- | |||
| sidebar_position: 2 | |||
| slug: /python_api_reference | |||
| --- | |||
| @@ -1312,7 +1312,7 @@ assistant.delete_sessions(ids=["id_1","id_2"]) | |||
| ### Converse with chat assistant | |||
| ```python | |||
| Session.ask(question: str, stream: bool = False) -> Optional[Message, iter[Message]] | |||
| Session.ask(question: str = "", stream: bool = False, **kwargs) -> Optional[Message, iter[Message]] | |||
| ``` | |||
| Asks a specified chat assistant a question to start an AI-powered conversation. | |||
| @@ -1325,7 +1325,7 @@ In streaming mode, not all responses include a reference, as this depends on the | |||
| ##### question: `str`, *Required* | |||
| The question to start an AI-powered conversation. | |||
| The question to start an AI-powered conversation. Defalut to `""` | |||
| ##### stream: `bool` | |||
| @@ -1334,6 +1334,10 @@ Indicates whether to output responses in a streaming way: | |||
| - `True`: Enable streaming (default). | |||
| - `False`: Disable streaming. | |||
| ##### **kwargs | |||
| The parameters in prompt(system). | |||
| #### Returns | |||
| - A `Message` object containing the response to the question if `stream` is set to `False`. | |||
| @@ -1402,11 +1406,25 @@ while True: | |||
| ### Create session with agent | |||
| ```python | |||
| Agent.create_session(id,rag) -> Session | |||
| Agent.create_session(id,rag, **kwargs) -> Session | |||
| ``` | |||
| Creates a session with the current agent. | |||
| #### Parameters | |||
| ##### id: `str`, *Required* | |||
| The id of agent | |||
| ##### rag:`RAGFlow object` | |||
| The RAGFlow object | |||
| ##### **kwargs | |||
| The parameters in `begin` component. | |||
| #### Returns | |||
| - Success: A `Session` object containing the following attributes: | |||
| @@ -1430,7 +1448,7 @@ session = create_session(AGENT_ID,rag_object) | |||
| ### Converse with agent | |||
| ```python | |||
| Session.ask(question: str, stream: bool = False) -> Optional[Message, iter[Message]] | |||
| Session.ask(question: str="", stream: bool = False) -> Optional[Message, iter[Message]] | |||
| ``` | |||
| Asks a specified agent a question to start an AI-powered conversation. | |||
| @@ -1441,9 +1459,9 @@ In streaming mode, not all responses include a reference, as this depends on the | |||
| #### Parameters | |||
| ##### question: `str`, *Required* | |||
| ##### question: `str` | |||
| The question to start an AI-powered conversation. | |||
| The question to start an AI-powered conversation. If the `begin` component takes parameters, a question is not required. | |||
| ##### stream: `bool` | |||
| @@ -1,7 +1,6 @@ | |||
| from .base import Base | |||
| from .session import Session,Message | |||
| from .session import Session | |||
| import requests | |||
| import json | |||
| class Agent(Base): | |||
| @@ -52,8 +51,8 @@ class Agent(Base): | |||
| super().__init__(rag,res_dict) | |||
| @staticmethod | |||
| def create_session(id,rag) -> Session: | |||
| res = requests.post(f"{rag.api_url}/agents/{id}/sessions",headers={"Authorization": f"Bearer {rag.user_key}"},json={}) | |||
| def create_session(id,rag,**kwargs) -> Session: | |||
| res = requests.post(f"{rag.api_url}/agents/{id}/sessions",headers={"Authorization": f"Bearer {rag.user_key}"},json=kwargs) | |||
| res = res.json() | |||
| if res.get("code") == 0: | |||
| return Session(rag,res.get("data")) | |||
| @@ -74,30 +73,3 @@ class Agent(Base): | |||
| result_list.append(temp_agent) | |||
| return result_list | |||
| raise Exception(res.get("message")) | |||
| @staticmethod | |||
| def ask(agent_id,rag,stream=True,**kwargs): | |||
| url = f"{rag.api_url}/agents/{agent_id}/completions" | |||
| headers = {"Authorization": f"Bearer {rag.user_key}"} | |||
| res = requests.post(url=url, headers=headers, json=kwargs,stream=stream) | |||
| for line in res.iter_lines(): | |||
| line = line.decode("utf-8") | |||
| if line.startswith("{"): | |||
| json_data = json.loads(line) | |||
| raise Exception(json_data["message"]) | |||
| if line.startswith("data:"): | |||
| json_data = json.loads(line[5:]) | |||
| if json_data["data"] is not True: | |||
| if json_data["data"].get("running_status"): | |||
| continue | |||
| answer = json_data["data"]["answer"] | |||
| reference = json_data["data"]["reference"] | |||
| temp_dict = { | |||
| "content": answer, | |||
| "role": "assistant" | |||
| } | |||
| if "chunks" in reference: | |||
| chunks = reference["chunks"] | |||
| temp_dict["reference"] = chunks | |||
| message = Message(rag, temp_dict) | |||
| yield message | |||
| @@ -17,7 +17,7 @@ class Session(Base): | |||
| self.__session_type = "agent" | |||
| super().__init__(rag, res_dict) | |||
| def ask(self, question,stream=True,**kwargs): | |||
| def ask(self, question="",stream=True,**kwargs): | |||
| if self.__session_type == "agent": | |||
| res=self._ask_agent(question,stream) | |||
| elif self.__session_type == "chat": | |||
| @@ -27,23 +27,22 @@ class Session(Base): | |||
| if line.startswith("{"): | |||
| json_data = json.loads(line) | |||
| raise Exception(json_data["message"]) | |||
| if line.startswith("data:"): | |||
| json_data = json.loads(line[5:]) | |||
| if json_data["data"] is not True: | |||
| if json_data["data"].get("running_status"): | |||
| continue | |||
| answer = json_data["data"]["answer"] | |||
| reference = json_data["data"]["reference"] | |||
| temp_dict = { | |||
| "content": answer, | |||
| "role": "assistant" | |||
| } | |||
| if "chunks" in reference: | |||
| chunks = reference["chunks"] | |||
| temp_dict["reference"] = chunks | |||
| message = Message(self.rag, temp_dict) | |||
| yield message | |||
| if not line.startswith("data:"): | |||
| continue | |||
| json_data = json.loads(line[5:]) | |||
| if json_data["data"] is True or json_data["data"].get("running_status"): | |||
| continue | |||
| answer = json_data["data"]["answer"] | |||
| reference = json_data["data"].get("reference", {}) | |||
| temp_dict = { | |||
| "content": answer, | |||
| "role": "assistant" | |||
| } | |||
| if reference and "chunks" in reference: | |||
| chunks = reference["chunks"] | |||
| temp_dict["reference"] = chunks | |||
| message = Message(self.rag, temp_dict) | |||
| yield message | |||
| def _ask_chat(self, question: str, stream: bool,**kwargs): | |||
| json_data={"question": question, "stream": True,"session_id":self.id} | |||
| @@ -51,6 +50,7 @@ class Session(Base): | |||
| res = self.post(f"/chats/{self.chat_id}/completions", | |||
| json_data, stream=stream) | |||
| return res | |||
| def _ask_agent(self,question:str,stream:bool): | |||
| res = self.post(f"/agents/{self.agent_id}/completions", | |||
| {"question": question, "stream": True,"session_id":self.id}, stream=stream) | |||
| @@ -70,4 +70,4 @@ class Message(Base): | |||
| self.role = "assistant" | |||
| self.prompt = None | |||
| self.id = None | |||
| super().__init__(rag, res_dict) | |||
| super().__init__(rag, res_dict) | |||