Add sdk for Agent API (#3220)

### What problem does this PR solve?

Add sdk for Agent API

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: liuhua <10215101452@stu.ecun.edu.cn>
This commit is contained in:
liuhua 2024-11-06 18:03:45 +08:00 committed by GitHub
parent 0dff64f6ad
commit f3aaa0d453
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 546 additions and 92 deletions

View File

@ -74,11 +74,12 @@ def create_agent_session(tenant_id, agent_id):
conv = {
"id": get_uuid(),
"dialog_id": cvs.id,
"user_id": req.get("user_id", ""),
"user_id": req.get("usr_id",""),
"message": [{"role": "assistant", "content": canvas.get_prologue()}],
"source": "agent"
}
API4ConversationService.save(**conv)
conv["agent_id"] = conv.pop("dialog_id")
return get_result(data=conv)
@ -150,6 +151,25 @@ def completion(tenant_id, chat_id):
conv.reference.append({"chunks": [], "doc_aggs": []})
def fillin_conv(ans):
reference = ans["reference"]
if "chunks" in reference:
chunks = reference.get("chunks")
chunk_list = []
for chunk in chunks:
new_chunk = {
"id": chunk["chunk_id"],
"content": chunk["content_with_weight"],
"document_id": chunk["doc_id"],
"document_name": chunk["docnm_kwd"],
"dataset_id": chunk["kb_id"],
"image_id": chunk["img_id"],
"similarity": chunk["similarity"],
"vector_similarity": chunk["vector_similarity"],
"term_similarity": chunk["term_similarity"],
"positions": chunk["positions"],
}
chunk_list.append(new_chunk)
reference["chunks"] = chunk_list
nonlocal conv, message_id
if not conv.reference:
conv.reference.append(ans["reference"])
@ -179,6 +199,7 @@ def completion(tenant_id, chat_id):
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
else:
@ -195,6 +216,7 @@ def completion(tenant_id, chat_id):
@token_required
def agent_completion(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.")
@ -202,25 +224,14 @@ def agent_completion(tenant_id, agent_id):
return get_error_data_result(message="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)
msg = []
for m in req["messages"]:
if m["role"] == "system":
continue
if m["role"] == "assistant" and not msg:
continue
msg.append(m)
if not msg[-1].get("id"): msg[-1]["id"] = get_uuid()
message_id = msg[-1]["id"]
if not req.get("session_id"):
session_id = get_uuid()
conv = {
"id": session_id,
"dialog_id": cvs.id,
"user_id": req.get("user_id", ""),
"user_id": req.get("user_id",""),
"message": [{"role": "assistant", "content": canvas.get_prologue()}],
"source": "agent"
}
@ -232,10 +243,49 @@ def agent_completion(tenant_id, agent_id):
if not e:
return get_error_data_result(message="Session not found!")
messages = conv.message
question = req.get("question")
if not question:
return get_error_data_result("`question` is required.")
question={
"role":"user",
"content":question,
"id": str(uuid4())
}
messages.append(question)
msg = []
for m in messages:
if m["role"] == "system":
continue
if m["role"] == "assistant" and not msg:
continue
msg.append(m)
if not msg[-1].get("id"): msg[-1]["id"] = get_uuid()
message_id = msg[-1]["id"]
if "quote" not in req: req["quote"] = False
stream = req.get("stream", True)
def fillin_conv(ans):
reference = ans["reference"]
if "chunks" in reference:
chunks = reference.get("chunks")
chunk_list = []
for chunk in chunks:
new_chunk = {
"id": chunk["chunk_id"],
"content": chunk["content_with_weight"],
"document_id": chunk["doc_id"],
"document_name": chunk["docnm_kwd"],
"dataset_id": chunk["kb_id"],
"image_id": chunk["img_id"],
"similarity": chunk["similarity"],
"vector_similarity": chunk["vector_similarity"],
"term_similarity": chunk["term_similarity"],
"positions": chunk["positions"],
}
chunk_list.append(new_chunk)
reference["chunks"] = chunk_list
nonlocal conv, message_id
if not conv.reference:
conv.reference.append(ans["reference"])

View File

@ -2018,59 +2018,54 @@ curl --request POST \
Success:
```json
data: {
```text
data:{
"code": 0,
"data": {
"answer": "I am an intelligent assistant designed to help you with your inquiries. I can provide",
"answer": "I am an intelligent assistant designed to help answer questions by summarizing content from a",
"reference": {},
"audio_binary": null,
"id": "d8e5ebb6-6b52-4fd1-bd02-35b52ba3acaa",
"session_id": "e14344d08d1a11efb6210242ac120004"
"id": "a84c5dd4-97b4-4624-8c3b-974012c8000d",
"session_id": "82b0ab2a9c1911ef9d870242ac120006"
}
}
data: {
data:{
"code": 0,
"data": {
"answer": "I am an intelligent assistant designed to help you with your inquiries. I can provide information, answer questions, and assist with tasks based on the knowledge available to me",
"answer": "I am an intelligent assistant designed to help answer questions by summarizing content from a knowledge base. My responses are based on the information available in the knowledge base and",
"reference": {},
"audio_binary": null,
"id": "d8e5ebb6-6b52-4fd1-bd02-35b52ba3acaa",
"session_id": "e14344d08d1a11efb6210242ac120004"
"id": "a84c5dd4-97b4-4624-8c3b-974012c8000d",
"session_id": "82b0ab2a9c1911ef9d870242ac120006"
}
}
data: {
data:{
"code": 0,
"data": {
"answer": "I am an intelligent assistant designed to help you with your inquiries. I can provide information, answer questions, and assist with tasks based on the knowledge available to me. How can I assist you today?",
"answer": "I am an intelligent assistant designed to help answer questions by summarizing content from a knowledge base. My responses are based on the information available in the knowledge base and any relevant chat history.",
"reference": {},
"audio_binary": null,
"id": "d8e5ebb6-6b52-4fd1-bd02-35b52ba3acaa",
"session_id": "e14344d08d1a11efb6210242ac120004"
"id": "a84c5dd4-97b4-4624-8c3b-974012c8000d",
"session_id": "82b0ab2a9c1911ef9d870242ac120006"
}
}
data: {
data:{
"code": 0,
"data": {
"answer": "I am an intelligent assistant designed to help you with your inquiries. I can provide information, answer questions, and assist with tasks based on the knowledge available to me ##0$$. How can I assist you today?",
"answer": "I am an intelligent assistant designed to help answer questions by summarizing content from a knowledge base ##0$$. My responses are based on the information available in the knowledge base and any relevant chat history.",
"reference": {
"total": 8,
"total": 1,
"chunks": [
{
"chunk_id": "895d34de762e674b43e8613c6fb54c6d",
"content_ltks": "xxxx\r\n\r\n\"\"\"\r\nyou are an intellig assistant. pleas summar the content of the knowledg base to answer the question. pleas list thedata in the knowledg base and answer in detail. when all knowledg base content is irrelev to the question , your answer must includ the sentenc\"the answer you are lookfor isnot found in the knowledg base!\" answer needto consid chat history.\r\n here is the knowledg base:\r\n{ knowledg}\r\nthe abov is the knowledg base.\r\n\"\"\"\r\n1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\nxxxx ",
"content_with_weight": "xxxx\r\n\r\n\"\"\"\r\nYou are an intelligent assistant. Please summarize the content of the knowledge base to answer the question. Please list the data in the knowledge base and answer in detail. When all knowledge base content is irrelevant to the question, your answer must include the sentence \"The answer you are looking for is not found in the knowledge base!\" Answers need to consider chat history.\r\n ",
"doc_id": "5c5999ec7be811ef9cab0242ac120005",
"docnm_kwd": "1.txt",
"kb_id": "c7ee74067a2c11efb21c0242ac120006",
"important_kwd": [],
"img_id": "",
"similarity": 0.4442746624416507,
"vector_similarity": 0.3843936320913369,
"term_similarity": 0.4699379611632138,
"id": "faf26c791128f2d5e821f822671063bd",
"content": "xxxxxxxx",
"document_id": "dd58f58e888511ef89c90242ac120006",
"document_name": "1.txt",
"dataset_id": "8e83e57a884611ef9d760242ac120006",
"image_id": "",
"similarity": 0.7,
"vector_similarity": 0.0,
"term_similarity": 1.0,
"positions": [
""
]
@ -2079,17 +2074,16 @@ data: {
"doc_aggs": [
{
"doc_name": "1.txt",
"doc_id": "5c5999ec7be811ef9cab0242ac120005",
"doc_id": "dd58f58e888511ef89c90242ac120006",
"count": 1
}
]
},
"prompt": "xxxx\r\n\r\n\"\"\"\r\nYou are an intelligent assistant. Please summarize the content of the knowledge base to answer the question. Please list the data in the knowledge base and answer in detail. When all knowledge base content is irrelevant to the question, your answer must include the sentence \"The answer you are looking for is not found in the knowledge base!\" Answers need to consider chat history.\r\n \r\n\"\"\"\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\nxxxx\n\n### Query:\nwho are you,please answer me in English\n\n### Elapsed\n - Retrieval: 332.2 ms\n - LLM: 2972.1 ms",
"id": "d8e5ebb6-6b52-4fd1-bd02-35b52ba3acaa",
"session_id": "e14344d08d1a11efb6210242ac120004"
"prompt": "xxxxxxxxxxx",
"id": "a84c5dd4-97b4-4624-8c3b-974012c8000d",
"session_id": "82b0ab2a9c1911ef9d870242ac120006"
}
}
data:{
"code": 0,
"data": true
@ -2103,4 +2097,244 @@ Failure:
"code": 102,
"message": "Please input your question."
}
```
## Create agent session
**POST** `/api/v1/agents/{agent_id}/sessions`
Creates an agent session.
### Request
- Method: POST
- URL: `/api/v1/agents/{agent_id}/sessions`
- Headers:
- `'content-Type: application/json'`
- `'Authorization: Bearer <YOUR_API_KEY>'`
- Body:
#### Request example
```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 '{
}'
```
#### Request parameters
- `agent_id`: (*Path parameter*)
The ID of the associated agent assistant.
### Response
Success:
```json
{
"code": 0,
"data": {
"agent_id": "2e45b5209c1011efa3e90242ac120006",
"id": "7869e9e49c1711ef92840242ac120006",
"message": [
{
"content": "Hello! I am the HR responsible for recruitment at Infineon. I learned that you are an expert in this field, and I 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?",
"role": "assistant"
}
],
"source": "agent",
"user_id": ""
}
}
```
Failure:
```json
{
"code": 102,
"message": "Agent not found."
}
```
## Converse through agent
**POST** `/api/v1/agents/{agent_id}/completions`
#######
Asks a question to start an AI-powered conversation.
### Request
- Method: POST
- URL: `/api/v1/agents/{agent_id}/completions`
- Headers:
- `'content-Type: application/json'`
- `'Authorization: Bearer <YOUR_API_KEY>'`
- Body:
- `"question"`: `string`
- `"stream"`: `boolean`
- `"session_id"`: `string`
#### Request example
```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": "What is RAGFlow?",
"stream": true
}'
```
#### Request Parameters
- `agent_id`: (*Path parameter*)
The ID of the associated agent assistant.
- `"question"`: (*Body Parameter*), `string` *Required*
The question to start an AI-powered conversation.
- `"stream"`: (*Body Parameter*), `boolean`
Indicates whether to output responses in a streaming way:
- `true`: Enable streaming.
- `false`: Disable streaming (default).
- `"session_id"`: (*Body Parameter*)
The ID of session. If it is not provided, a new session will be generated.
### Response
Success:
```text
data:{
"code": 0,
"message": "",
"data": {
"answer": "",
"reference": [],
"id": "7ed5c2e4-aa28-4397-bbed-59664a332aa0",
"session_id": "ce1b4fa89c1811ef85720242ac120006"
}
}
data:{
"code": 0,
"message": "",
"data": {
"answer": "Hello",
"reference": [],
"id": "7ed5c2e4-aa28-4397-bbed-59664a332aa0",
"session_id": "ce1b4fa89c1811ef85720242ac120006"
}
}
data:{
"code": 0,
"message": "",
"data": {
"answer": "Hello!",
"reference": [],
"id": "7ed5c2e4-aa28-4397-bbed-59664a332aa0",
"session_id": "ce1b4fa89c1811ef85720242ac120006"
}
}
data:{
"code": 0,
"message": "",
"data": {
"answer": "Hello! How",
"reference": [],
"id": "7ed5c2e4-aa28-4397-bbed-59664a332aa0",
"session_id": "ce1b4fa89c1811ef85720242ac120006"
}
}
data:{
"code": 0,
"message": "",
"data": {
"answer": "Hello! How can",
"reference": [],
"id": "7ed5c2e4-aa28-4397-bbed-59664a332aa0",
"session_id": "ce1b4fa89c1811ef85720242ac120006"
}
}
data:{
"code": 0,
"message": "",
"data": {
"answer": "Hello! How can I",
"reference": [],
"id": "7ed5c2e4-aa28-4397-bbed-59664a332aa0",
"session_id": "ce1b4fa89c1811ef85720242ac120006"
}
}
data:{
"code": 0,
"message": "",
"data": {
"answer": "Hello! How can I assist",
"reference": [],
"id": "7ed5c2e4-aa28-4397-bbed-59664a332aa0",
"session_id": "ce1b4fa89c1811ef85720242ac120006"
}
}
data:{
"code": 0,
"message": "",
"data": {
"answer": "Hello! How can I assist you",
"reference": [],
"id": "7ed5c2e4-aa28-4397-bbed-59664a332aa0",
"session_id": "ce1b4fa89c1811ef85720242ac120006"
}
}
data:{
"code": 0,
"message": "",
"data": {
"answer": "Hello! How can I assist you today",
"reference": [],
"id": "7ed5c2e4-aa28-4397-bbed-59664a332aa0",
"session_id": "ce1b4fa89c1811ef85720242ac120006"
}
}
data:{
"code": 0,
"message": "",
"data": {
"answer": "Hello! How can I assist you today?",
"reference": [],
"id": "7ed5c2e4-aa28-4397-bbed-59664a332aa0",
"session_id": "ce1b4fa89c1811ef85720242ac120006"
}
}
data:{
"code": 0,
"message": "",
"data": {
"answer": "Hello! How can I assist you today?",
"reference": [],
"id": "7ed5c2e4-aa28-4397-bbed-59664a332aa0",
"session_id": "ce1b4fa89c1811ef85720242ac120006"
}
}
data:{
"code": 0,
"message": "",
"data": true
}
```
Failure:
```json
{
"code": 102,
"message": "`question` is required."
}
```

View File

@ -1387,6 +1387,117 @@ while True:
cont = ""
for ans in session.ask(question, stream=True):
print(answer.content[len(cont):], end='', flush=True)
cont = answer.content
print(ans.content[len(cont):], end='', flush=True)
cont = ans.content
```
---
## Create agent session
```python
Agent.create_session(id,rag) -> Session
```
Creates a agemt session.
### Returns
- Success: A `Session` object containing the following attributes:
- `id`: `str` The auto-generated unique identifier of the created session.
- `message`: `list[Message]` The messages of the created session assistant. Default: `[{"role": "assistant", "content": "Hi! I am your assistantcan I help you?"}]`
- `agnet_id`: `str` The ID of the associated agent assistant.
- Failure: `Exception`
### Examples
```python
from ragflow_sdk import RAGFlow
rag_object = RAGFlow(api_key="<YOUR_API_KEY>", base_url="http://<YOUR_BASE_URL>:9380")
AGENT_ID = "AGENT_ID"
session = create_session(AGENT_ID,rag_object)
```
---
## Converse through agent
```python
Session.ask(question: str, stream: bool = False) -> Optional[Message, iter[Message]]
```
Asks a question to start an AI-powered conversation.
### Parameters
#### question: `str` *Required*
The question to start an AI-powered conversation.
#### stream: `bool`
Indicates whether to output responses in a streaming way:
- `True`: Enable streaming.
- `False`: Disable streaming (default).
### Returns
- A `Message` object containing the response to the question if `stream` is set to `False`
- An iterator containing multiple `message` objects (`iter[Message]`) if `stream` is set to `True`
The following shows the attributes of a `Message` object:
#### id: `str`
The auto-generated message ID.
#### content: `str`
The content of the message. Defaults to `"Hi! I am your assistant, can I help you?"`.
#### reference: `list[Chunk]`
A list of `Chunk` objects representing references to the message, each containing the following attributes:
- `id` `str`
The chunk ID.
- `content` `str`
The content of the chunk.
- `image_id` `str`
The ID of the snapshot of the chunk. Applicable only when the source of the chunk is an image, PPT, PPTX, or PDF file.
- `document_id` `str`
The ID of the referenced document.
- `document_name` `str`
The name of the referenced document.
- `position` `list[str]`
The location information of the chunk within the referenced document.
- `dataset_id` `str`
The ID of the dataset to which the referenced document belongs.
- `similarity` `float`
A composite similarity score of the chunk ranging from `0` to `1`, with a higher value indicating greater similarity. It is the weighted sum of `vector_similarity` and `term_similarity`.
- `vector_similarity` `float`
A vector similarity score of the chunk ranging from `0` to `1`, with a higher value indicating greater similarity between vector embeddings.
- `term_similarity` `float`
A keyword similarity score of the chunk ranging from `0` to `1`, with a higher value indicating greater similarity between keywords.
### Examples
```python
from ragflow_sdk import RAGFlow,Agent
rag_object = RAGFlow(api_key="<YOUR_API_KEY>", base_url="http://<YOUR_BASE_URL>:9380")
AGENT_id = "AGENT_ID"
session = Agent.create_session(AGENT_id,rag_object)
print("\n==================== Miss R =====================\n")
print("Hello. What can I do for you?")
while True:
question = input("\n==================== User =====================\n> ")
print("\n==================== Miss R =====================\n")
cont = ""
for ans in session.ask(question, stream=True):
print(ans.content[len(cont):], end='', flush=True)
cont = ans.content
```

View File

@ -7,4 +7,5 @@ from .modules.dataset import DataSet
from .modules.chat import Chat
from .modules.session import Session
from .modules.document import Document
from .modules.chunk import Chunk
from .modules.chunk import Chunk
from .modules.agent import Agent

View File

@ -0,0 +1,59 @@
from .base import Base
from .session import Session
import requests
class Agent(Base):
def __init__(self,rag,res_dict):
self.id = None
self.avatar = None
self.canvas_type = None
self.description = None
self.dsl = None
super().__init__(rag, res_dict)
class Dsl(Base):
def __init__(self,rag,res_dict):
self.answer = []
self.components = {
"begin": {
"downstream": ["Answer:China"],
"obj": {
"component_name": "Begin",
"params": {}
},
"upstream": []
}
}
self.graph = {
"edges": [],
"nodes": [
{
"data": {
"label": "Begin",
"name": "begin"
},
"id": "begin",
"position": {
"x": 50,
"y": 200
},
"sourcePosition": "left",
"targetPosition": "right",
"type": "beginNode"
}
]
}
self.history = []
self.messages = []
self.path = []
self.reference = []
super().__init__(rag,res_dict)
@staticmethod
def create_session(id,rag) -> Session:
res = requests.post(f"http://127.0.0.1:9380/api/v1/agents/{id}/sessions",headers={"Authorization": f"Bearer {rag.user_key}"},json={})
res = res.json()
if res.get("code") == 0:
return Session(rag,res.get("data"))
raise Exception(res.get("message"))

View File

@ -9,14 +9,19 @@ class Session(Base):
self.name = "New session"
self.messages = [{"role": "assistant", "content": "Hi! I am your assistantcan I help you?"}]
self.chat_id = None
self.agent_id = None
for key,value in res_dict.items():
if key =="chat_id" and value is not None:
self.__session_type = "chat"
if key == "agent_id" and value is not None:
self.__session_type = "agent"
super().__init__(rag, res_dict)
def ask(self, question: str, stream: bool = False):
for message in self.messages:
if "reference" in message:
message.pop("reference")
res = self.post(f"/chats/{self.chat_id}/completions",
{"question": question, "stream": True,"session_id":self.id}, stream=stream)
def ask(self, question):
if self.__session_type == "agent":
res=self._ask_agent(question)
elif self.__session_type == "chat":
res=self._ask_chat(question)
for line in res.iter_lines():
line = line.decode("utf-8")
if line.startswith("{"):
@ -33,25 +38,20 @@ class Session(Base):
}
if "chunks" in reference:
chunks = reference["chunks"]
chunk_list = []
for chunk in chunks:
new_chunk = {
"id": chunk["chunk_id"],
"content": chunk["content_with_weight"],
"document_id": chunk["doc_id"],
"document_name": chunk["docnm_kwd"],
"dataset_id": chunk["kb_id"],
"image_id": chunk["img_id"],
"similarity": chunk["similarity"],
"vector_similarity": chunk["vector_similarity"],
"term_similarity": chunk["term_similarity"],
"positions": chunk["positions"],
}
chunk_list.append(new_chunk)
temp_dict["reference"] = chunk_list
temp_dict["reference"] = chunks
message = Message(self.rag, temp_dict)
yield message
def _ask_chat(self, question: str, stream: bool = False):
res = self.post(f"/chats/{self.chat_id}/completions",
{"question": question, "stream": True,"session_id":self.id}, stream=stream)
return res
def _ask_agent(self,question:str,stream:bool=False):
res = self.post(f"/agents/{self.agent_id}/completions",
{"question": question, "stream": True,"session_id":self.id}, stream=stream)
return res
def update(self,update_message):
res = self.put(f"/chats/{self.chat_id}/sessions/{self.id}",
update_message)
@ -66,20 +66,4 @@ class Message(Base):
self.role = "assistant"
self.prompt = None
self.id = None
super().__init__(rag, res_dict)
class Chunk(Base):
def __init__(self, rag, res_dict):
self.id = None
self.content = None
self.document_id = ""
self.document_name = ""
self.dataset_id = ""
self.image_id = ""
self.similarity = None
self.vector_similarity = None
self.term_similarity = None
self.positions = None
super().__init__(rag, res_dict)
super().__init__(rag, res_dict)

View File

@ -1,5 +1,6 @@
from ragflow_sdk import RAGFlow
from ragflow_sdk import RAGFlow,Agent
from common import HOST_ADDRESS
import pytest
def test_create_session_with_success(get_api_key_fixture):
@ -58,6 +59,7 @@ def test_delete_sessions_with_success(get_api_key_fixture):
session = assistant.create_session()
assistant.delete_sessions(ids=[session.id])
def test_update_session_with_name(get_api_key_fixture):
API_KEY = get_api_key_fixture
rag = RAGFlow(API_KEY, HOST_ADDRESS)
@ -92,4 +94,17 @@ def test_list_sessions_with_success(get_api_key_fixture):
assistant=rag.create_chat("test_list_session", dataset_ids=[kb.id])
assistant.create_session("test_1")
assistant.create_session("test_2")
assistant.list_sessions()
assistant.list_sessions()
@pytest.mark.skip(reason="")
def test_create_agent_session_with_success(get_api_key_fixture):
API_KEY = "ragflow-BkOGNhYjIyN2JiODExZWY5MzVhMDI0Mm"
rag = RAGFlow(API_KEY,HOST_ADDRESS)
Agent.create_session("2e45b5209c1011efa3e90242ac120006", rag)
@pytest.mark.skip(reason="")
def test_create_agent_conversation_with_success(get_api_key_fixture):
API_KEY = "ragflow-BkOGNhYjIyN2JiODExZWY5MzVhMDI0Mm"
rag = RAGFlow(API_KEY,HOST_ADDRESS)
session = Agent.create_session("2e45b5209c1011efa3e90242ac120006", rag)
session.ask("What is this job")