Fix bugs in agent api and update api document (#3996)
### What problem does this PR solve? Fix bugs in agent api and update api document ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) - [x] New Feature (non-breaking change which adds functionality) --------- Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
This commit is contained in:
parent
68d46b2a1e
commit
1ecb687c51
@ -185,6 +185,7 @@ class Canvas(ABC):
|
||||
self.path.append(["begin"])
|
||||
|
||||
self.path.append([])
|
||||
|
||||
ran = -1
|
||||
waiting = []
|
||||
without_dependent_checking = []
|
||||
|
||||
@ -73,6 +73,8 @@ 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 can't create a session directly")
|
||||
conv = {
|
||||
"id": get_uuid(),
|
||||
"dialog_id": cvs.id,
|
||||
@ -112,6 +114,8 @@ def update(tenant_id, chat_id, session_id):
|
||||
@token_required
|
||||
def chat_completion(tenant_id, chat_id):
|
||||
req = request.json
|
||||
if not req or not req.get("session_id"):
|
||||
req = {"question":""}
|
||||
if not DialogService.query(tenant_id=tenant_id,id=chat_id,status=StatusEnum.VALID.value):
|
||||
return get_error_data_result(f"You don't own the chat {chat_id}")
|
||||
if req.get("session_id"):
|
||||
@ -125,7 +129,6 @@ def chat_completion(tenant_id, chat_id):
|
||||
resp.headers.add_header("Content-Type", "text/event-stream; charset=utf-8")
|
||||
|
||||
return resp
|
||||
|
||||
else:
|
||||
answer = None
|
||||
for ans in rag_completion(tenant_id, chat_id, **req):
|
||||
@ -138,11 +141,15 @@ def chat_completion(tenant_id, chat_id):
|
||||
@token_required
|
||||
def agent_completions(tenant_id, agent_id):
|
||||
req = request.json
|
||||
if not UserCanvasService.query(user_id=tenant_id,id=agent_id):
|
||||
cvs = UserCanvasService.query(user_id=tenant_id, 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"):
|
||||
if not API4ConversationService.query(id=req["session_id"],dialog_id=agent_id):
|
||||
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']}")
|
||||
else:
|
||||
req["question"]=""
|
||||
if req.get("stream", True):
|
||||
resp = Response(agent_completion(tenant_id, agent_id, **req), mimetype="text/event-stream")
|
||||
resp.headers.add_header("Cache-control", "no-cache")
|
||||
@ -150,9 +157,11 @@ def agent_completions(tenant_id, agent_id):
|
||||
resp.headers.add_header("X-Accel-Buffering", "no")
|
||||
resp.headers.add_header("Content-Type", "text/event-stream; charset=utf-8")
|
||||
return resp
|
||||
|
||||
try:
|
||||
for answer in agent_completion(tenant_id, agent_id, **req):
|
||||
return get_result(data=answer)
|
||||
except Exception as e:
|
||||
return get_error_data_result(str(e))
|
||||
|
||||
|
||||
@manager.route('/chats/<chat_id>/sessions', methods=['GET']) # noqa: F821
|
||||
@ -420,3 +429,5 @@ def agent_bot_completions(agent_id):
|
||||
|
||||
for answer in agent_completion(objs[0].tenant_id, agent_id, **req):
|
||||
return get_result(data=answer)
|
||||
|
||||
|
||||
|
||||
@ -55,36 +55,39 @@ def completion(tenant_id, agent_id, question, session_id=None, stream=True, **kw
|
||||
e, cvs = UserCanvasService.get_by_id(agent_id)
|
||||
assert e, "Agent not found."
|
||||
assert cvs.user_id == tenant_id, "You do not own the agent."
|
||||
|
||||
if not isinstance(cvs.dsl,str):
|
||||
cvs.dsl = json.dumps(cvs.dsl, ensure_ascii=False)
|
||||
canvas = Canvas(cvs.dsl, tenant_id)
|
||||
canvas.reset()
|
||||
message_id = str(uuid4())
|
||||
|
||||
if not session_id:
|
||||
query = canvas.get_preset_param()
|
||||
if query:
|
||||
for ele in query:
|
||||
if not ele["optional"]:
|
||||
if not kwargs.get(ele["key"]):
|
||||
assert False, f"`{ele['key']}` is required"
|
||||
ele["value"] = kwargs[ele["key"]]
|
||||
if ele["optional"]:
|
||||
if kwargs.get(ele["key"]):
|
||||
ele["value"] = kwargs[ele['key']]
|
||||
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()
|
||||
conv = {
|
||||
"id": session_id,
|
||||
"dialog_id": cvs.id,
|
||||
"user_id": kwargs.get("user_id", ""),
|
||||
"source": "agent",
|
||||
"dsl": json.loads(cvs.dsl)
|
||||
"dsl": temp_dsl
|
||||
}
|
||||
API4ConversationService.save(**conv)
|
||||
if canvas.get_preset_param():
|
||||
yield "data:" + json.dumps({"code": 0,
|
||||
"message": "",
|
||||
"data": {
|
||||
"session_id": session_id,
|
||||
"answer": "",
|
||||
"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
|
||||
conv = API4Conversation(**conv)
|
||||
else:
|
||||
e, conv = API4ConversationService.get_by_id(session_id)
|
||||
@ -104,7 +107,6 @@ def completion(tenant_id, agent_id, question, session_id=None, stream=True, **kw
|
||||
conv.reference.append({"chunks": [], "doc_aggs": []})
|
||||
|
||||
final_ans = {"reference": [], "content": ""}
|
||||
|
||||
if stream:
|
||||
try:
|
||||
for ans in canvas.run(stream=stream):
|
||||
|
||||
@ -86,8 +86,9 @@ def completion(tenant_id, chat_id, question, name="New session", session_id=None
|
||||
assert dia, "You do not own the chat."
|
||||
|
||||
if not session_id:
|
||||
session_id = get_uuid()
|
||||
conv = {
|
||||
"id": get_uuid(),
|
||||
"id":session_id ,
|
||||
"dialog_id": chat_id,
|
||||
"name": name,
|
||||
"message": [{"role": "assistant", "content": dia[0].prompt_config.get("prologue")}]
|
||||
|
||||
@ -2015,11 +2015,20 @@ curl --request POST \
|
||||
--header 'Authorization: Bearer <YOUR_API_KEY>' \
|
||||
--data-binary '
|
||||
{
|
||||
"question": "What is RAGFlow?",
|
||||
"stream": true
|
||||
}'
|
||||
```
|
||||
|
||||
```bash
|
||||
curl --request POST \
|
||||
--url http://{address}/api/v1/chats/{chat_id}/completions \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer <YOUR_API_KEY>' \
|
||||
--data-binary '
|
||||
{
|
||||
"question": "Who are you",
|
||||
"stream": true,
|
||||
"session_id":"9fa7691cb85c11ef9c5f0242ac120005"
|
||||
}'
|
||||
```
|
||||
#### Request Parameters
|
||||
|
||||
- `chat_id`: (*Path parameter*)
|
||||
@ -2034,10 +2043,29 @@ curl --request POST \
|
||||
The ID of session. If it is not provided, a new session will be generated.
|
||||
|
||||
### Response
|
||||
Success without `session_id`:
|
||||
```text
|
||||
data:{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"data": {
|
||||
"answer": "Hi! I'm your assistant, what can I do for you?",
|
||||
"reference": {},
|
||||
"audio_binary": null,
|
||||
"id": null,
|
||||
"session_id": "b01eed84b85611efa0e90242ac120005"
|
||||
}
|
||||
}
|
||||
data:{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"data": true
|
||||
}
|
||||
```
|
||||
|
||||
Success:
|
||||
Success with `session_id`:
|
||||
|
||||
```json
|
||||
```text
|
||||
data:{
|
||||
"code": 0,
|
||||
"data": {
|
||||
@ -2121,6 +2149,7 @@ Failure:
|
||||
---
|
||||
|
||||
## Create session with agent
|
||||
*If there are parameters in the `begin` component, the session cannot be created in this way.*
|
||||
|
||||
**POST** `/api/v1/agents/{agent_id}/sessions`
|
||||
|
||||
@ -2159,16 +2188,101 @@ Success:
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"agent_id": "2e45b5209c1011efa3e90242ac120006",
|
||||
"id": "7869e9e49c1711ef92840242ac120006",
|
||||
"agent_id": "b4a39922b76611efaa1a0242ac120006",
|
||||
"dsl": {
|
||||
"answer": [],
|
||||
"components": {
|
||||
"Answer:GreenReadersDrum": {
|
||||
"downstream": [],
|
||||
"obj": {
|
||||
"component_name": "Answer",
|
||||
"inputs": [],
|
||||
"output": null,
|
||||
"params": {}
|
||||
},
|
||||
"upstream": []
|
||||
},
|
||||
"begin": {
|
||||
"downstream": [],
|
||||
"obj": {
|
||||
"component_name": "Begin",
|
||||
"inputs": [],
|
||||
"output": {},
|
||||
"params": {}
|
||||
},
|
||||
"upstream": []
|
||||
}
|
||||
},
|
||||
"embed_id": "",
|
||||
"graph": {
|
||||
"edges": [],
|
||||
"nodes": [
|
||||
{
|
||||
"data": {
|
||||
"label": "Begin",
|
||||
"name": "begin"
|
||||
},
|
||||
"dragging": false,
|
||||
"height": 44,
|
||||
"id": "begin",
|
||||
"position": {
|
||||
"x": 53.25688640427177,
|
||||
"y": 198.37155679786412
|
||||
},
|
||||
"positionAbsolute": {
|
||||
"x": 53.25688640427177,
|
||||
"y": 198.37155679786412
|
||||
},
|
||||
"selected": false,
|
||||
"sourcePosition": "left",
|
||||
"targetPosition": "right",
|
||||
"type": "beginNode",
|
||||
"width": 200
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"form": {},
|
||||
"label": "Answer",
|
||||
"name": "对话_0"
|
||||
},
|
||||
"dragging": false,
|
||||
"height": 44,
|
||||
"id": "Answer:GreenReadersDrum",
|
||||
"position": {
|
||||
"x": 360.43473114516974,
|
||||
"y": 207.29298425089348
|
||||
},
|
||||
"positionAbsolute": {
|
||||
"x": 360.43473114516974,
|
||||
"y": 207.29298425089348
|
||||
},
|
||||
"selected": false,
|
||||
"sourcePosition": "right",
|
||||
"targetPosition": "left",
|
||||
"type": "logicNode",
|
||||
"width": 200
|
||||
}
|
||||
]
|
||||
},
|
||||
"history": [],
|
||||
"messages": [],
|
||||
"path": [
|
||||
[
|
||||
"begin"
|
||||
],
|
||||
[]
|
||||
],
|
||||
"reference": []
|
||||
},
|
||||
"id": "2581031eb7a311efb5200242ac120005",
|
||||
"message": [
|
||||
{
|
||||
"content": "Hello! I am a recruiter at InfiniFlow. I learned that you are an expert in the field, and took the liberty of reaching out to you. There is an opportunity I would like to share with you. RAGFlow is currently looking for a senior engineer for your position. I was wondering if you might be interested?",
|
||||
"content": "Hi! I'm your smart assistant. What can I do for you?",
|
||||
"role": "assistant"
|
||||
}
|
||||
],
|
||||
"source": "agent",
|
||||
"user_id": ""
|
||||
"user_id": "69736c5e723611efb51b0242ac120007"
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -2216,7 +2330,7 @@ Asks a specified agent a question to start an AI-powered conversation.
|
||||
- `"question"`: `string`
|
||||
- `"stream"`: `boolean`
|
||||
- `"session_id"`: `string`
|
||||
|
||||
- other parameters: `string`
|
||||
#### Request example
|
||||
|
||||
```bash
|
||||
@ -2226,10 +2340,32 @@ curl --request POST \
|
||||
--header 'Authorization: Bearer <YOUR_API_KEY>' \
|
||||
--data-binary '
|
||||
{
|
||||
"question": "What is RAGFlow?",
|
||||
"stream": true
|
||||
}'
|
||||
```
|
||||
```bash
|
||||
curl --request POST \
|
||||
--url http://{address}/api/v1/agents/{agent_id}/completions \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer <YOUR_API_KEY>' \
|
||||
--data-binary '
|
||||
{
|
||||
"question": "Hello",
|
||||
"stream": true,
|
||||
"session_id": "cb2f385cb86211efa36e0242ac120005"
|
||||
}'
|
||||
```
|
||||
```bash
|
||||
curl --request POST \
|
||||
--url http://{address}/api/v1/agents/{agent_id}/completions \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer <YOUR_API_KEY>' \
|
||||
--data-binary '
|
||||
{
|
||||
"lang":"English"
|
||||
"file":"明天天气如何"
|
||||
}'
|
||||
```
|
||||
|
||||
|
||||
#### Request Parameters
|
||||
|
||||
@ -2243,10 +2379,28 @@ curl --request POST \
|
||||
- `false`: Disable streaming.
|
||||
- `"session_id"`: (*Body Parameter*)
|
||||
The ID of the session. If it is not provided, a new session will be generated.
|
||||
|
||||
- Other parameters: (*Body Parameter*)
|
||||
The parameters in the begin component.
|
||||
### Response
|
||||
|
||||
Success:
|
||||
success without `session_id` provided and with no parameters in the `begin` component:
|
||||
```text
|
||||
data:{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"data": {
|
||||
"answer": "Hi! I'm your smart assistant. What can I do for you?",
|
||||
"reference": {},
|
||||
"id": "31e6091d-88d4-441b-ac65-eae1c055be7b",
|
||||
"session_id": "2987ad3eb85f11efb2a70242ac120005"
|
||||
}
|
||||
}
|
||||
data:{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"data": true
|
||||
}
|
||||
```
|
||||
Success with `session_id` provided and with no parameters in the `begin` component:
|
||||
|
||||
```text
|
||||
data:{
|
||||
@ -2354,6 +2508,85 @@ data:{
|
||||
"data": true
|
||||
}
|
||||
```
|
||||
Success with parameters in the `begin` component:
|
||||
```text
|
||||
data:{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"data": {
|
||||
"answer": "How",
|
||||
"reference": {},
|
||||
"id": "0379ac4c-b26b-4a44-8b77-99cebf313fdf",
|
||||
"session_id": "4399c7d0b86311efac5b0242ac120005"
|
||||
}
|
||||
}
|
||||
data:{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"data": {
|
||||
"answer": "How is",
|
||||
"reference": {},
|
||||
"id": "0379ac4c-b26b-4a44-8b77-99cebf313fdf",
|
||||
"session_id": "4399c7d0b86311efac5b0242ac120005"
|
||||
}
|
||||
}
|
||||
data:{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"data": {
|
||||
"answer": "How is the",
|
||||
"reference": {},
|
||||
"id": "0379ac4c-b26b-4a44-8b77-99cebf313fdf",
|
||||
"session_id": "4399c7d0b86311efac5b0242ac120005"
|
||||
}
|
||||
}
|
||||
data:{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"data": {
|
||||
"answer": "How is the weather",
|
||||
"reference": {},
|
||||
"id": "0379ac4c-b26b-4a44-8b77-99cebf313fdf",
|
||||
"session_id": "4399c7d0b86311efac5b0242ac120005"
|
||||
}
|
||||
}
|
||||
data:{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"data": {
|
||||
"answer": "How is the weather tomorrow",
|
||||
"reference": {},
|
||||
"id": "0379ac4c-b26b-4a44-8b77-99cebf313fdf",
|
||||
"session_id": "4399c7d0b86311efac5b0242ac120005"
|
||||
}
|
||||
}
|
||||
data:{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"data": {
|
||||
"answer": "How is the weather tomorrow?",
|
||||
"reference": {},
|
||||
"id": "0379ac4c-b26b-4a44-8b77-99cebf313fdf",
|
||||
"session_id": "4399c7d0b86311efac5b0242ac120005"
|
||||
}
|
||||
}
|
||||
data:{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"data": {
|
||||
"answer": "How is the weather tomorrow?",
|
||||
"reference": {},
|
||||
"id": "0379ac4c-b26b-4a44-8b77-99cebf313fdf",
|
||||
"session_id": "4399c7d0b86311efac5b0242ac120005"
|
||||
}
|
||||
}
|
||||
data:{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"data": true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Failure:
|
||||
|
||||
|
||||
@ -14,6 +14,13 @@ Dataset Management
|
||||
:::
|
||||
|
||||
---
|
||||
### Install the RAGFlow SDK
|
||||
|
||||
To install the RAGFlow SDK, run the following command in your terminal:
|
||||
|
||||
```bash
|
||||
pip install ragflow-sdk
|
||||
```
|
||||
|
||||
## Create dataset
|
||||
|
||||
@ -1401,7 +1408,7 @@ while True:
|
||||
---
|
||||
|
||||
## Create session with agent
|
||||
|
||||
*If there are parameters in the `begin` component, the session cannot be created in this way.*
|
||||
```python
|
||||
Agent.create_session(id,rag) -> Session
|
||||
```
|
||||
@ -1428,7 +1435,7 @@ session = create_session(AGENT_ID,rag_object)
|
||||
|
||||
---
|
||||
|
||||
## Converse with agent
|
||||
## Converse with agent without `begin` component
|
||||
|
||||
```python
|
||||
Session.ask(question: str, stream: bool = False) -> Optional[Message, iter[Message]]
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
from .base import Base
|
||||
from .session import Session
|
||||
from .session import Session,Message
|
||||
import requests
|
||||
from typing import List
|
||||
import json
|
||||
|
||||
|
||||
class Agent(Base):
|
||||
def __init__(self,rag,res_dict):
|
||||
@ -73,3 +75,30 @@ 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
|
||||
|
||||
@ -29,7 +29,7 @@ class Session(Base):
|
||||
raise Exception(json_data["message"])
|
||||
if line.startswith("data:"):
|
||||
json_data = json.loads(line[5:])
|
||||
if not json_data["data"]:
|
||||
if json_data["data"] is not True:
|
||||
answer = json_data["data"]["answer"]
|
||||
reference = json_data["data"]["reference"]
|
||||
temp_dict = {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
from ragflow_sdk import RAGFlow
|
||||
from ragflow_sdk import RAGFlow,Agent
|
||||
from common import HOST_ADDRESS
|
||||
import pytest
|
||||
|
||||
@ -7,3 +7,13 @@ def test_list_agents_with_success(get_api_key_fixture):
|
||||
API_KEY=get_api_key_fixture
|
||||
rag = RAGFlow(API_KEY,HOST_ADDRESS)
|
||||
rag.list_agents()
|
||||
|
||||
|
||||
@pytest.mark.skip(reason="")
|
||||
def test_converse_with_agent_with_success(get_api_key_fixture):
|
||||
API_KEY = "ragflow-BkOGNhYjIyN2JiODExZWY5MzVhMDI0Mm"
|
||||
agent_id = "ebfada2eb2bc11ef968a0242ac120006"
|
||||
rag = RAGFlow(API_KEY,HOST_ADDRESS)
|
||||
lang = "Chinese"
|
||||
file = "How is the weather tomorrow?"
|
||||
Agent.ask(agent_id=agent_id,rag=rag,lang=lang,file=file)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user