diff --git a/api/apps/sdk/chat.py b/api/apps/sdk/chat.py index 5f7aa6a5e..823208086 100644 --- a/api/apps/sdk/chat.py +++ b/api/apps/sdk/chat.py @@ -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") diff --git a/api/apps/sdk/session.py b/api/apps/sdk/session.py index 0e50eeddb..da4ea12a7 100644 --- a/api/apps/sdk/session.py +++ b/api/apps/sdk/session.py @@ -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']}") diff --git a/api/db/services/canvas_service.py b/api/db/services/canvas_service.py index 3da151e75..78f93b195 100644 --- a/api/db/services/canvas_service.py +++ b/api/db/services/canvas_service.py @@ -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!" diff --git a/api/utils/api_utils.py b/api/utils/api_utils.py index 635497d07..2b9fcff48 100644 --- a/api/utils/api_utils.py +++ b/api/utils/api_utils.py @@ -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] diff --git a/docs/references/http_api_reference.md b/docs/references/http_api_reference.md index 050a00aa6..200f7d19e 100644 --- a/docs/references/http_api_reference.md +++ b/docs/references/http_api_reference.md @@ -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 ' + --header 'Authorization: Bearer ' \ --data '{ "dataset_ids": ["0b2cbc8c877f11ef89070242ac120005"], "name":"new_chat_1" @@ -2160,9 +2160,11 @@ Creates a session with an agent. - `'content-Type: application/json'` - `'Authorization: Bearer '` - 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 \ @@ -2171,6 +2173,17 @@ curl --request POST \ --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 ' \ + --data '{ + "lang":"Japanese", + "file":"Who are you" + }' +``` ##### Request parameters @@ -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,19 @@ 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 \ + --header 'Content-Type: application/json' \ + --header 'Authorization: Bearer ' \ + --data-binary ' + { + "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 \ @@ -2348,17 +2374,6 @@ curl --request POST \ "session_id": "cb2f385cb86211efa36e0242ac120005" }' ``` -```bash -curl --request POST \ - --url http://{address}/api/v1/agents/{agent_id}/completions \ - --header 'Content-Type: application/json' \ - --header 'Authorization: Bearer ' \ - --data-binary ' - { - "lang":"English" - "file":"How is the weather tomorrow?" - }' -``` ##### Request Parameters @@ -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" + "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": { - "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" - } -} -data:{ - "code": 0, - "data": true -} +data: ``` Success with parameters in the `begin` component: ```json diff --git a/docs/references/python_api_reference.md b/docs/references/python_api_reference.md index 5b16f1998..0504d9a1c 100644 --- a/docs/references/python_api_reference.md +++ b/docs/references/python_api_reference.md @@ -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` diff --git a/sdk/python/ragflow_sdk/modules/agent.py b/sdk/python/ragflow_sdk/modules/agent.py index 5299c0581..9ca314128 100644 --- a/sdk/python/ragflow_sdk/modules/agent.py +++ b/sdk/python/ragflow_sdk/modules/agent.py @@ -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 diff --git a/sdk/python/ragflow_sdk/modules/session.py b/sdk/python/ragflow_sdk/modules/session.py index 15b1e5e3e..3ea275eb5 100644 --- a/sdk/python/ragflow_sdk/modules/session.py +++ b/sdk/python/ragflow_sdk/modules/session.py @@ -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) \ No newline at end of file + super().__init__(rag, res_dict)