Selaa lähdekoodia

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>
tags/v0.15.0
liuhua 10 kuukautta sitten
vanhempi
commit
1ecb687c51
No account linked to committer's email address

+ 1
- 0
agent/canvas.py Näytä tiedosto

@@ -185,6 +185,7 @@ class Canvas(ABC):
self.path.append(["begin"])

self.path.append([])

ran = -1
waiting = []
without_dependent_checking = []

+ 28
- 17
api/apps/sdk/session.py Näytä tiedosto

@@ -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):
@@ -137,22 +140,28 @@ def chat_completion(tenant_id, chat_id):
@manager.route('/agents/<agent_id>/completions', methods=['POST']) # noqa: F821
@token_required
def agent_completions(tenant_id, agent_id):
req = request.json
if not UserCanvasService.query(user_id=tenant_id,id=agent_id):
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):
return get_error_data_result(f"You don't own the session {req['session_id']}")
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")
resp.headers.add_header("Connection", "keep-alive")
resp.headers.add_header("X-Accel-Buffering", "no")
resp.headers.add_header("Content-Type", "text/event-stream; charset=utf-8")
return resp

for answer in agent_completion(tenant_id, agent_id, **req):
return get_result(data=answer)
req = request.json
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"):
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")
resp.headers.add_header("Connection", "keep-alive")
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)



+ 20
- 18
api/db/services/canvas_service.py Näytä tiedosto

@@ -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):
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):

+ 2
- 1
api/db/services/conversation_service.py Näytä tiedosto

@@ -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")}]

+ 248
- 15
docs/references/http_api_reference.md Näytä tiedosto

@@ -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,11 +2340,33 @@ 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

- `agent_id`: (*Path parameter*), `string`
@@ -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:


+ 9
- 2
docs/references/python_api_reference.md Näytä tiedosto

@@ -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]]

+ 30
- 1
sdk/python/ragflow_sdk/modules/agent.py Näytä tiedosto

@@ -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

+ 1
- 1
sdk/python/ragflow_sdk/modules/session.py Näytä tiedosto

@@ -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 = {

+ 12
- 2
sdk/python/test/test_sdk_api/t_agent.py Näytä tiedosto

@@ -1,4 +1,4 @@
from ragflow_sdk import RAGFlow
from ragflow_sdk import RAGFlow,Agent
from common import HOST_ADDRESS
import pytest

@@ -6,4 +6,14 @@ import pytest
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()
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…
Peruuta
Tallenna