mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-04-25 00:16:29 +02:00
Merge changes v1
This commit is contained in:
parent
b2fd9bf877
commit
24efe0e887
45 changed files with 2940 additions and 294 deletions
|
|
@ -1,74 +0,0 @@
|
|||
[tool.poetry]
|
||||
name = "agents"
|
||||
version = "0.1.0"
|
||||
description = "RowBoat Labs Agent OS"
|
||||
authors = ["Akhilesh <akhilesh@rowboatlabs.com>"]
|
||||
license = "MIT"
|
||||
readme = "README.md"
|
||||
homepage = "https://github.com/rowboatlabs/agents"
|
||||
package-mode = false
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
# Python
|
||||
python = ">=3.10,<4.0"
|
||||
|
||||
# Dependencies
|
||||
aiohttp = "^3.9.3"
|
||||
annotated-types = "^0.7.0"
|
||||
anyio = "^4.6.2"
|
||||
beautifulsoup4 = "^4.12.3"
|
||||
blinker = "^1.8.2"
|
||||
certifi = "^2024.8.30"
|
||||
charset-normalizer = "^3.4.0"
|
||||
click = "^8.1.7"
|
||||
distro = "^1.9.0"
|
||||
dnspython = "^2.7.0"
|
||||
et_xmlfile = "^2.0.0"
|
||||
eval_type_backport = "^0.2.0"
|
||||
firecrawl = "^1.4.0"
|
||||
Flask = "^3.0.3"
|
||||
gunicorn = "^23.0.0"
|
||||
h11 = "^0.14.0"
|
||||
httpcore = "^1.0.6"
|
||||
httpx = "^0.27.2"
|
||||
idna = "^3.10"
|
||||
itsdangerous = "^2.2.0"
|
||||
Jinja2 = "^3.1.4"
|
||||
jiter = "^0.6.1"
|
||||
jsonpath-python = "^1.0.6"
|
||||
lxml = "^5.3.0"
|
||||
markdownify = "^0.13.1"
|
||||
MarkupSafe = "^3.0.2"
|
||||
mcp = "*"
|
||||
motor = "^3.7.0"
|
||||
mypy-extensions = "^1.0.0"
|
||||
nest-asyncio = "^1.6.0"
|
||||
numpy = "^2.1.2"
|
||||
openai = "^1.52.2"
|
||||
openai-agents = "^0.0.4"
|
||||
openpyxl = "^3.1.5"
|
||||
pandas = "^2.2.3"
|
||||
pydantic = "^2.9.2"
|
||||
pydantic_core = "^2.23.4"
|
||||
pymongo = "^4.10.1"
|
||||
python-dateutil = "^2.8.2"
|
||||
python-docx = "^1.1.2"
|
||||
python-dotenv = "^1.0.1"
|
||||
pytz = "^2024.2"
|
||||
qdrant_client = "^1.13.3"
|
||||
redis = "^5.2.1"
|
||||
requests = "^2.32.3"
|
||||
setuptools = "^75.1.0"
|
||||
six = "^1.16.0"
|
||||
sniffio = "^1.3.1"
|
||||
soupsieve = "^2.6"
|
||||
tabulate = "^0.9.0"
|
||||
tqdm = "^4.66.5"
|
||||
typing-inspect = "^0.9.0"
|
||||
typing_extensions = "^4.12.2"
|
||||
tzdata = "^2024.2"
|
||||
urllib3 = "^2.2.3"
|
||||
waitress = "^2.1.2"
|
||||
websockets = "^13.1"
|
||||
Werkzeug = "^3.0.5"
|
||||
wheel = "^0.44.0"
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
from flask import Flask, request, jsonify, Response
|
||||
from datetime import datetime
|
||||
from functools import wraps
|
||||
import os
|
||||
import redis
|
||||
import uuid
|
||||
import json
|
||||
import time
|
||||
|
||||
from src.graph.core import run_turn
|
||||
from src.graph.tools import RAG_TOOL, CLOSE_CHAT_TOOL
|
||||
|
||||
from src.utils.common import common_logger, read_json_from_file
|
||||
logger = common_logger
|
||||
|
||||
redis_client = redis.from_url(os.environ.get('REDIS_URL', 'redis://localhost:6379'))
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route("/health", methods=["GET"])
|
||||
def health():
|
||||
return jsonify({"status": "ok"})
|
||||
|
||||
@app.route("/")
|
||||
def home():
|
||||
return "Hello, World!"
|
||||
|
||||
def require_api_key(f):
|
||||
@wraps(f)
|
||||
def decorated(*args, **kwargs):
|
||||
auth_header = request.headers.get('Authorization')
|
||||
if not auth_header or not auth_header.startswith('Bearer '):
|
||||
return jsonify({'error': 'Missing or invalid authorization header'}), 401
|
||||
|
||||
token = auth_header.split('Bearer ')[1]
|
||||
actual = os.environ.get('API_KEY', '').strip()
|
||||
if actual and token != actual:
|
||||
return jsonify({'error': 'Invalid API key'}), 403
|
||||
|
||||
return f(*args, **kwargs)
|
||||
return decorated
|
||||
|
||||
@app.route("/chat", methods=["POST"])
|
||||
@require_api_key
|
||||
def chat():
|
||||
logger.info('='*200)
|
||||
logger.info(f"{'*'*50}Running server mode{'*'*50}")
|
||||
try:
|
||||
data = request.get_json()
|
||||
logger.info('Complete request:')
|
||||
logger.info(data)
|
||||
logger.info('-'*200)
|
||||
|
||||
start_time = datetime.now()
|
||||
config = read_json_from_file("./configs/default_config.json")
|
||||
|
||||
logger.info('Beginning turn')
|
||||
resp_messages, resp_tokens_used, resp_state = run_turn(
|
||||
messages=data.get("messages", []),
|
||||
start_agent_name=data.get("startAgent", ""),
|
||||
agent_configs=data.get("agents", []),
|
||||
tool_configs=data.get("tools", []),
|
||||
start_turn_with_start_agent=config.get("start_turn_with_start_agent", False),
|
||||
state=data.get("state", {}),
|
||||
additional_tool_configs=[RAG_TOOL, CLOSE_CHAT_TOOL],
|
||||
complete_request=data
|
||||
)
|
||||
|
||||
logger.info('-'*200)
|
||||
logger.info('Raw output:')
|
||||
logger.info((resp_messages, resp_tokens_used, resp_state))
|
||||
|
||||
out = {
|
||||
"messages": resp_messages,
|
||||
"tokens_used": resp_tokens_used,
|
||||
"state": resp_state,
|
||||
}
|
||||
|
||||
logger.info("Output:")
|
||||
for k, v in out.items():
|
||||
logger.info(f"{k}: {v}")
|
||||
logger.info('*'*200)
|
||||
|
||||
logger.info('='*200)
|
||||
logger.info(f"Processing time: {datetime.now() - start_time}")
|
||||
|
||||
return jsonify(out)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error: {e}")
|
||||
return jsonify({"error": str(e)}), 500
|
||||
|
||||
@app.route("/chat_stream_init", methods=["POST"])
|
||||
@require_api_key
|
||||
def chat_stream_init():
|
||||
# create a uuid for the stream
|
||||
stream_id = str(uuid.uuid4())
|
||||
|
||||
# store the the request data in redis with 10 minute TTL
|
||||
# using the key name `stream_request_<stream_id>`
|
||||
# set ttl to 10 minutes
|
||||
redis_client.setex(f"stream_request_{stream_id}", 600, json.dumps(request.get_json()))
|
||||
|
||||
return jsonify({"stream_id": stream_id})
|
||||
|
||||
@app.route("/chat_stream/<stream_id>", methods=["GET"])
|
||||
@require_api_key
|
||||
def chat_stream(stream_id):
|
||||
# get the request data from redis
|
||||
request_data = redis_client.get(f"stream_request_{stream_id}")
|
||||
if not request_data:
|
||||
return jsonify({"error": "Stream not found"}), 404
|
||||
|
||||
# invoke run_streamed() from agents-sdk
|
||||
|
||||
def generate():
|
||||
# example of HTTP SSE event stream:
|
||||
# https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events
|
||||
# --------------------------------
|
||||
# id: <optional event id>
|
||||
# event: <event name>
|
||||
# data: {... event data ...}
|
||||
#
|
||||
# event: <event name>
|
||||
# data: {... event data ...}
|
||||
try:
|
||||
yield "event: message\n"
|
||||
yield "data: {\"role\": \"assistant\", \"content\": \"This is the first message!\"}\n\n" # double \n indicates end of message
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
yield "event: message\n"
|
||||
yield "data: {\"role\": \"assistant\", \"content\": \"This is the second message!\"}\n\n"
|
||||
|
||||
yield "event: done\n"
|
||||
yield "data: {... state data ...}\n\n"
|
||||
except Exception as e:
|
||||
yield "event: error\n"
|
||||
yield "data: {... error data ...}\n\n"
|
||||
|
||||
return Response(generate(), mimetype='text/event-stream')
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("Starting Flask server...")
|
||||
from waitress import serve
|
||||
serve(app, host="0.0.0.0", port=4040)
|
||||
1351
apps/agents/poetry.lock → apps/rowboat_agents/poetry.lock
generated
1351
apps/agents/poetry.lock → apps/rowboat_agents/poetry.lock
generated
File diff suppressed because it is too large
Load diff
109
apps/rowboat_agents/pyproject.toml
Normal file
109
apps/rowboat_agents/pyproject.toml
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
[tool.poetry]
|
||||
name = "agents"
|
||||
version = "0.1.0"
|
||||
description = "RowBoat Labs Agent OS"
|
||||
authors = ["Akhilesh <akhilesh@rowboatlabs.com>"]
|
||||
license = "MIT"
|
||||
readme = "README.md"
|
||||
homepage = "https://github.com/rowboatlabs/agents"
|
||||
package-mode = false
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = ">=3.10,<4.0"
|
||||
|
||||
# Dependencies
|
||||
aiohttp = "^3.9.3"
|
||||
annotated-types = "^0.7.0"
|
||||
anyio = "^4.8.0"
|
||||
asgiref = "*"
|
||||
beautifulsoup4 = "^4.12.3"
|
||||
blinker = "^1.9.0"
|
||||
build = "1.2.2.post1"
|
||||
CacheControl = "^0.14.2"
|
||||
certifi = "^2024.12.14"
|
||||
cffi = "^1.17.1"
|
||||
charset-normalizer = "^3.4.1"
|
||||
cleo = "^2.1.0"
|
||||
click = "^8.1.8"
|
||||
crashtest = "^0.4.1"
|
||||
distlib = "^0.3.9"
|
||||
distro = "^1.9.0"
|
||||
dnspython = "^2.7.0"
|
||||
dulwich = "^0.22.7"
|
||||
et_xmlfile = "^2.0.0"
|
||||
eval_type_backport = "^0.2.2"
|
||||
fastjsonschema = "^2.21.1"
|
||||
filelock = "^3.17.0"
|
||||
firecrawl = "^1.9.0"
|
||||
Flask = "^3.1.0"
|
||||
gunicorn = "^23.0.0"
|
||||
h11 = "^0.14.0"
|
||||
httpcore = "^1.0.7"
|
||||
httpx = "^0.27.2"
|
||||
hypercorn = "*"
|
||||
idna = "^3.10"
|
||||
installer = "^0.7.0"
|
||||
itsdangerous = "^2.2.0"
|
||||
"jaraco.classes" = "^3.4.0"
|
||||
"jaraco.context" = "^6.0.1"
|
||||
"jaraco.functools" = "^4.1.0"
|
||||
Jinja2 = "^3.1.5"
|
||||
jiter = "^0.6.1"
|
||||
jsonpath-python = "^1.0.6"
|
||||
keyring = "^25.6.0"
|
||||
lxml = "^5.3.0"
|
||||
markdownify = "^0.13.1"
|
||||
MarkupSafe = "^3.0.2"
|
||||
mcp = "*"
|
||||
more-itertools = "^10.6.0"
|
||||
motor = "*"
|
||||
msgpack = "^1.1.0"
|
||||
mypy-extensions = "^1.0.0"
|
||||
nest-asyncio = "^1.6.0"
|
||||
numpy = "^2.2.1"
|
||||
openai = "*"
|
||||
openai-agents = "*"
|
||||
openpyxl = "^3.1.5"
|
||||
packaging = "^24.2"
|
||||
pandas = "^2.2.3"
|
||||
pkginfo = "^1.12.0"
|
||||
platformdirs = "^4.3.6"
|
||||
poetry = "^2.0.1"
|
||||
poetry-core = "^2.0.1"
|
||||
pycparser = "^2.22"
|
||||
pydantic = "^2.10.5"
|
||||
pydantic_core = "^2.27.2"
|
||||
pymongo = "^4.10.1"
|
||||
pyproject_hooks = "^1.2.0"
|
||||
python-dateutil = "^2.9.0.post0"
|
||||
python-docx = "^1.1.2"
|
||||
python-dotenv = "^1.0.1"
|
||||
pytz = "^2024.2"
|
||||
qdrant-client = "*"
|
||||
RapidFuzz = "^3.11.0"
|
||||
redis = "^5.2.1"
|
||||
requests = "^2.32.3"
|
||||
requests-toolbelt = "^1.0.0"
|
||||
setuptools = "^75.8.0"
|
||||
shellingham = "^1.5.4"
|
||||
six = "^1.17.0"
|
||||
sniffio = "^1.3.1"
|
||||
soupsieve = "^2.6"
|
||||
tabulate = "^0.9.0"
|
||||
tomlkit = "^0.13.2"
|
||||
tqdm = "^4.67.1"
|
||||
trove-classifiers = "^2025.1.15.22"
|
||||
typing-inspect = "^0.9.0"
|
||||
typing_extensions = "^4.12.2"
|
||||
tzdata = "^2024.2"
|
||||
urllib3 = "^2.3.0"
|
||||
virtualenv = "^20.29.1"
|
||||
waitress = "^2.1.2"
|
||||
websockets = "^13.1"
|
||||
Werkzeug = "^3.1.3"
|
||||
wheel = "^0.44.0"
|
||||
xattr = "^1.1.4"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
aiohttp==3.9.3
|
||||
annotated-types==0.7.0
|
||||
anyio==4.8.0
|
||||
asgiref
|
||||
beautifulsoup4==4.12.3
|
||||
blinker==1.9.0
|
||||
build==1.2.2.post1
|
||||
|
|
@ -25,6 +26,7 @@ gunicorn==23.0.0
|
|||
h11==0.14.0
|
||||
httpcore==1.0.7
|
||||
httpx==0.27.2
|
||||
hypercorn
|
||||
idna==3.10
|
||||
installer==0.7.0
|
||||
itsdangerous==2.2.0
|
||||
|
|
@ -40,12 +42,13 @@ markdownify==0.13.1
|
|||
MarkupSafe==3.0.2
|
||||
mcp
|
||||
more-itertools==10.6.0
|
||||
motor
|
||||
msgpack==1.1.0
|
||||
mypy-extensions==1.0.0
|
||||
nest-asyncio==1.6.0
|
||||
numpy==2.2.1
|
||||
openai==1.59.7
|
||||
openai-agents==0.0.4
|
||||
openai
|
||||
openai-agents
|
||||
openpyxl==3.1.5
|
||||
packaging==24.2
|
||||
pandas==2.2.3
|
||||
|
|
@ -62,7 +65,9 @@ python-dateutil==2.9.0.post0
|
|||
python-docx==1.1.2
|
||||
python-dotenv==1.0.1
|
||||
pytz==2024.2
|
||||
qdrant-client
|
||||
RapidFuzz==3.11.0
|
||||
redis==5.2.1
|
||||
requests==2.32.3
|
||||
requests-toolbelt==1.0.0
|
||||
setuptools==75.8.0
|
||||
|
|
@ -83,4 +88,4 @@ waitress==2.1.2
|
|||
websockets==13.1
|
||||
Werkzeug==3.1.3
|
||||
wheel==0.44.0
|
||||
xattr==1.1.4
|
||||
xattr==1.1.4
|
||||
200
apps/rowboat_agents/src/app/main.py
Normal file
200
apps/rowboat_agents/src/app/main.py
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
from flask import Flask, request, jsonify, Response
|
||||
from datetime import datetime
|
||||
from functools import wraps
|
||||
import os
|
||||
import redis
|
||||
import uuid
|
||||
import json
|
||||
import asyncio
|
||||
from hypercorn.config import Config
|
||||
from hypercorn.asyncio import serve
|
||||
|
||||
from src.graph.core import run_turn, run_turn_streamed
|
||||
from src.graph.tools import RAG_TOOL, CLOSE_CHAT_TOOL
|
||||
from src.utils.common import common_logger, read_json_from_file
|
||||
|
||||
from pprint import pprint
|
||||
|
||||
logger = common_logger
|
||||
redis_client = redis.from_url(os.environ.get('REDIS_URL', 'redis://localhost:6379'))
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route("/health", methods=["GET"])
|
||||
def health():
|
||||
return jsonify({"status": "ok"})
|
||||
|
||||
@app.route("/")
|
||||
def home():
|
||||
return "Hello, World!"
|
||||
|
||||
def require_api_key(f):
|
||||
@wraps(f)
|
||||
def decorated(*args, **kwargs):
|
||||
auth_header = request.headers.get('Authorization')
|
||||
if not auth_header or not auth_header.startswith('Bearer '):
|
||||
return jsonify({'error': 'Missing or invalid authorization header'}), 401
|
||||
|
||||
token = auth_header.split('Bearer ')[1]
|
||||
actual = os.environ.get('API_KEY', '').strip()
|
||||
if actual and token != actual:
|
||||
return jsonify({'error': 'Invalid API key'}), 403
|
||||
|
||||
return f(*args, **kwargs)
|
||||
return decorated
|
||||
|
||||
@app.route("/chat", methods=["POST"])
|
||||
@require_api_key
|
||||
def chat():
|
||||
logger.info('='*100)
|
||||
logger.info(f"{'*'*100}Running server mode{'*'*100}")
|
||||
try:
|
||||
data = request.get_json()
|
||||
logger.info('Complete request:')
|
||||
logger.info(data)
|
||||
logger.info('-'*100)
|
||||
|
||||
start_time = datetime.now()
|
||||
config = read_json_from_file("./configs/default_config.json")
|
||||
|
||||
logger.info('Beginning turn')
|
||||
resp_messages, resp_tokens_used, resp_state = run_turn(
|
||||
messages=data.get("messages", []),
|
||||
start_agent_name=data.get("startAgent", ""),
|
||||
agent_configs=data.get("agents", []),
|
||||
tool_configs=data.get("tools", []),
|
||||
start_turn_with_start_agent=config.get("start_turn_with_start_agent", False),
|
||||
state=data.get("state", {}),
|
||||
additional_tool_configs=[RAG_TOOL, CLOSE_CHAT_TOOL],
|
||||
complete_request=data
|
||||
)
|
||||
|
||||
logger.info('-'*100)
|
||||
logger.info('Raw output:')
|
||||
logger.info((resp_messages, resp_tokens_used, resp_state))
|
||||
|
||||
out = {
|
||||
"messages": resp_messages,
|
||||
"tokens_used": resp_tokens_used,
|
||||
"state": resp_state,
|
||||
}
|
||||
|
||||
logger.info("Output:")
|
||||
for k, v in out.items():
|
||||
logger.info(f"{k}: {v}")
|
||||
logger.info('*'*100)
|
||||
|
||||
logger.info('='*100)
|
||||
logger.info(f"Processing time: {datetime.now() - start_time}")
|
||||
|
||||
return jsonify(out)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error: {e}")
|
||||
return jsonify({"error": str(e)}), 500
|
||||
|
||||
@app.route("/chat_stream_init", methods=["POST"])
|
||||
@require_api_key
|
||||
def chat_stream_init():
|
||||
# create a uuid for the stream
|
||||
stream_id = str(uuid.uuid4())
|
||||
|
||||
# store the request data in redis with 10 minute TTL
|
||||
data = request.get_json()
|
||||
redis_client.setex(f"stream_request_{stream_id}", 600, json.dumps(data))
|
||||
|
||||
return jsonify({"stream_id": stream_id})
|
||||
|
||||
@app.route("/chat_stream/<stream_id>", methods=["GET"])
|
||||
@require_api_key
|
||||
def chat_stream(stream_id):
|
||||
# get the request data from redis
|
||||
request_data = redis_client.get(f"stream_request_{stream_id}")
|
||||
if not request_data:
|
||||
return jsonify({"error": "Stream not found"}), 404
|
||||
|
||||
request_data = json.loads(request_data)
|
||||
config = read_json_from_file("./configs/default_config.json")
|
||||
|
||||
# Preprocess messages to handle null content and role issues
|
||||
for msg in request_data["messages"]:
|
||||
# Handle null content in assistant messages with tool calls
|
||||
if (msg.get("role") == "assistant" and
|
||||
msg.get("content") is None and
|
||||
msg.get("tool_calls") is not None and
|
||||
len(msg.get("tool_calls")) > 0):
|
||||
msg["content"] = "Calling tool"
|
||||
|
||||
# Handle role issues
|
||||
if msg.get("role") == "tool":
|
||||
msg["role"] = "developer"
|
||||
elif not msg.get("role"):
|
||||
msg["role"] = "user"
|
||||
|
||||
print('*'*200)
|
||||
print("Request:")
|
||||
print('*'*200)
|
||||
pprint(request_data)
|
||||
print('='*200)
|
||||
|
||||
|
||||
async def process_stream():
|
||||
try:
|
||||
async for event_type, event_data in run_turn_streamed(
|
||||
messages=request_data.get("messages", []),
|
||||
start_agent_name=request_data.get("startAgent", ""),
|
||||
agent_configs=request_data.get("agents", []),
|
||||
tool_configs=request_data.get("tools", []),
|
||||
start_turn_with_start_agent=config.get("start_turn_with_start_agent", False),
|
||||
state=request_data.get("state", {}),
|
||||
additional_tool_configs=[RAG_TOOL, CLOSE_CHAT_TOOL],
|
||||
complete_request=request_data
|
||||
):
|
||||
if event_type == 'message':
|
||||
print('*'*200)
|
||||
print("Yielding message:")
|
||||
print('*'*200)
|
||||
to_yield = f"event: message\ndata: {json.dumps(event_data)}\n\n"
|
||||
print(to_yield)
|
||||
print('='*200)
|
||||
yield to_yield
|
||||
elif event_type == 'done':
|
||||
print('*'*200)
|
||||
print("Yielding done:")
|
||||
print('*'*200)
|
||||
to_yield = f"event: done\ndata: {json.dumps(event_data)}\n\n"
|
||||
print(to_yield)
|
||||
print('='*200)
|
||||
yield to_yield
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Streaming error: {str(e)}")
|
||||
yield f"event: error\ndata: {json.dumps({'error': str(e)})}\n\n"
|
||||
|
||||
def generate():
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
|
||||
try:
|
||||
async def get_all_chunks():
|
||||
chunks = []
|
||||
async for chunk in process_stream():
|
||||
chunks.append(chunk)
|
||||
return chunks
|
||||
|
||||
chunks = loop.run_until_complete(get_all_chunks())
|
||||
for chunk in chunks:
|
||||
yield chunk
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in generate: {e}")
|
||||
raise
|
||||
finally:
|
||||
loop.close()
|
||||
|
||||
return Response(generate(), mimetype='text/event-stream')
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("Starting async server...")
|
||||
config = Config()
|
||||
config.bind = ["0.0.0.0:4040"]
|
||||
asyncio.run(serve(app, config))
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
from copy import deepcopy
|
||||
from datetime import datetime
|
||||
|
||||
import logging
|
||||
from .helpers.access import (
|
||||
|
|
@ -9,14 +10,14 @@ from .helpers.state import (
|
|||
construct_state_from_response
|
||||
)
|
||||
from .helpers.control import get_latest_assistant_msg, get_latest_non_assistant_messages, get_last_agent_name
|
||||
from .swarm_wrapper import run as swarm_run, create_response, get_agents
|
||||
from .swarm_wrapper import run as swarm_run, run_streamed as swarm_run_streamed, create_response, get_agents
|
||||
from src.utils.common import common_logger as logger
|
||||
import asyncio
|
||||
|
||||
# Create a dedicated logger for swarm wrapper
|
||||
logger.setLevel(logging.INFO)
|
||||
print("Logger level set to INFO")
|
||||
|
||||
|
||||
def order_messages(messages):
|
||||
"""
|
||||
Sorts each message's keys in a specified order and returns a new list of ordered messages.
|
||||
|
|
@ -227,3 +228,140 @@ def run_turn(
|
|||
tokens_used=tokens_used,
|
||||
all_agents=new_agents
|
||||
)
|
||||
|
||||
async def run_turn_streamed(
|
||||
messages,
|
||||
start_agent_name,
|
||||
agent_configs,
|
||||
tool_configs,
|
||||
start_turn_with_start_agent,
|
||||
state={},
|
||||
additional_tool_configs=[],
|
||||
complete_request={}
|
||||
):
|
||||
final_state = None # Initialize outside try block
|
||||
try:
|
||||
# Initialize agents and get external tools
|
||||
new_agents = get_agents(agent_configs=agent_configs, tool_configs=tool_configs, complete_request=complete_request)
|
||||
last_agent_name = get_last_agent_name(
|
||||
state=state,
|
||||
agent_configs=agent_configs,
|
||||
start_agent_name=start_agent_name,
|
||||
msg_type="user",
|
||||
latest_assistant_msg=None,
|
||||
start_turn_with_start_agent=start_turn_with_start_agent
|
||||
)
|
||||
last_new_agent = get_agent_by_name(last_agent_name, new_agents)
|
||||
external_tools = get_external_tools(tool_configs)
|
||||
|
||||
current_agent = last_new_agent
|
||||
tokens_used = {"total": 0, "prompt": 0, "completion": 0}
|
||||
|
||||
stream_result = await swarm_run_streamed(
|
||||
agent=last_new_agent,
|
||||
messages=messages,
|
||||
external_tools=external_tools,
|
||||
tokens_used=tokens_used
|
||||
)
|
||||
|
||||
# Process streaming events
|
||||
async for event in stream_result.stream_events():
|
||||
# print('='*50)
|
||||
# print("Received event: ", event)
|
||||
# print('-'*50)
|
||||
|
||||
# Handle raw response events and accumulate tokens
|
||||
if event.type == "raw_response_event":
|
||||
if hasattr(event.data, 'type') and event.data.type == "response.completed":
|
||||
if hasattr(event.data.response, 'usage'):
|
||||
tokens_used["total"] += event.data.response.usage.total_tokens
|
||||
tokens_used["prompt"] += event.data.response.usage.input_tokens
|
||||
tokens_used["completion"] += event.data.response.usage.output_tokens
|
||||
print('-'*50)
|
||||
print(f"Found usage information. Updated cumulative tokens: {tokens_used}")
|
||||
print('-'*50)
|
||||
continue
|
||||
|
||||
# Update current agent when it changes
|
||||
elif event.type == "agent_updated_stream_event":
|
||||
current_agent = event.new_agent
|
||||
message = {
|
||||
'content': f"Agent changed to {current_agent.name}",
|
||||
'role': 'assistant',
|
||||
'sender': current_agent.name,
|
||||
'tool_calls': None,
|
||||
'tool_call_id': None,
|
||||
'response_type': 'internal'
|
||||
}
|
||||
print("Yielding message: ", message)
|
||||
yield ('message', message)
|
||||
continue
|
||||
|
||||
# Handle run items (tools, messages, etc)
|
||||
elif event.type == "run_item_stream_event":
|
||||
if event.item.type == "tool_call_item":
|
||||
message = {
|
||||
'content': None,
|
||||
'role': 'assistant',
|
||||
'sender': current_agent.name if current_agent else None,
|
||||
'tool_calls': [{
|
||||
'function': {
|
||||
'name': event.item.raw_item.name,
|
||||
'arguments': event.item.raw_item.arguments
|
||||
},
|
||||
'id': event.item.raw_item.id,
|
||||
'type': 'function'
|
||||
}],
|
||||
'tool_call_id': None,
|
||||
'tool_name': None,
|
||||
'response_type': 'internal'
|
||||
}
|
||||
print("Yielding message: ", message)
|
||||
yield ('message', message)
|
||||
|
||||
elif event.item.type == "tool_call_output_item":
|
||||
message = {
|
||||
'content': str(event.item.output),
|
||||
'role': 'tool',
|
||||
'sender': None,
|
||||
'tool_calls': None,
|
||||
'tool_call_id': event.item.raw_item['call_id'],
|
||||
'tool_name': event.item.raw_item.get('name', None),
|
||||
'response_type': 'internal'
|
||||
}
|
||||
print("Yielding message: ", message)
|
||||
yield ('message', message)
|
||||
|
||||
elif event.item.type == "message_output_item":
|
||||
content = ""
|
||||
if hasattr(event.item.raw_item, 'content'):
|
||||
for content_item in event.item.raw_item.content:
|
||||
if hasattr(content_item, 'text'):
|
||||
content += content_item.text
|
||||
|
||||
message = {
|
||||
'content': content,
|
||||
'role': 'assistant',
|
||||
'sender': current_agent.name,
|
||||
'tool_calls': None,
|
||||
'tool_call_id': None,
|
||||
'tool_name': None,
|
||||
'response_type': 'external'
|
||||
}
|
||||
print("Yielding message: ", message)
|
||||
yield ('message', message)
|
||||
|
||||
print(f"\n{'='*50}\n")
|
||||
|
||||
# After all events are processed, set final state
|
||||
final_state = {
|
||||
"last_agent_name": current_agent.name if current_agent else None,
|
||||
"tokens": tokens_used
|
||||
}
|
||||
yield ('done', {'state': final_state})
|
||||
|
||||
except Exception as e:
|
||||
import traceback
|
||||
print(traceback.format_exc())
|
||||
print(f"Error in stream processing: {str(e)}")
|
||||
yield ('error', {'error': str(e), 'state': final_state}) # Include final_state in error response
|
||||
|
|
@ -184,6 +184,7 @@ def get_agents(agent_configs, tool_configs, complete_request):
|
|||
# Create Agent objects from config
|
||||
for agent_config in agent_configs:
|
||||
logger.debug(f"Processing config for agent: {agent_config['name']}")
|
||||
print("="*100)
|
||||
print(f"Processing config for agent: {agent_config['name']}")
|
||||
|
||||
# If hasRagSources, append the RAG tool to the agent's tools
|
||||
|
|
@ -199,7 +200,6 @@ def get_agents(agent_configs, tool_configs, complete_request):
|
|||
print(f"Agent {agent_config['name']} has {len(agent_config['tools'])} configured tools")
|
||||
|
||||
new_tools = []
|
||||
print(agent_config)
|
||||
rag_tool = get_rag_tool(agent_config, complete_request)
|
||||
if rag_tool:
|
||||
new_tools.append(rag_tool)
|
||||
|
|
@ -259,6 +259,8 @@ def get_agents(agent_configs, tool_configs, complete_request):
|
|||
# Look up the agent's children from the old agent and create a list called handoffs in new_agent with pointers to the children in new_agents
|
||||
new_agent.handoffs = [new_agents[new_agent_name_to_index[child]] for child in new_agent_to_children[new_agent.name]]
|
||||
|
||||
print("Returning created agents")
|
||||
print("="*100)
|
||||
return new_agents
|
||||
|
||||
|
||||
|
|
@ -341,4 +343,49 @@ def run(
|
|||
|
||||
logger.info(f"Completed Swarm run for agent: {agent.name}")
|
||||
print(f"Completed Swarm run for agent: {agent.name}")
|
||||
return response
|
||||
return response
|
||||
|
||||
async def run_streamed(
|
||||
agent,
|
||||
messages,
|
||||
external_tools=None,
|
||||
tokens_used=None
|
||||
):
|
||||
"""
|
||||
Wrapper function for initializing and running the Swarm client in streaming mode.
|
||||
"""
|
||||
logger.info(f"Initializing Swarm streaming client for agent: {agent.name}")
|
||||
print(f"Initializing Swarm streaming client for agent: {agent.name}")
|
||||
|
||||
# Initialize default parameters
|
||||
if external_tools is None:
|
||||
external_tools = []
|
||||
if tokens_used is None:
|
||||
tokens_used = {}
|
||||
|
||||
# Format messages to ensure they're compatible with the OpenAI API
|
||||
formatted_messages = []
|
||||
for msg in messages:
|
||||
if isinstance(msg, dict) and "content" in msg:
|
||||
formatted_msg = {
|
||||
"role": msg.get("role", "user"),
|
||||
"content": msg["content"]
|
||||
}
|
||||
formatted_messages.append(formatted_msg)
|
||||
else:
|
||||
formatted_messages.append({
|
||||
"role": "user",
|
||||
"content": str(msg)
|
||||
})
|
||||
|
||||
logger.info("Beginning Swarm streaming run")
|
||||
print("Beginning Swarm streaming run")
|
||||
|
||||
try:
|
||||
# Use the Runner.run_streamed method
|
||||
stream_result = Runner.run_streamed(agent, formatted_messages)
|
||||
return stream_result
|
||||
except Exception as e:
|
||||
logger.error(f"Error during streaming run: {str(e)}")
|
||||
print(f"Error during streaming run: {str(e)}")
|
||||
raise
|
||||
174
apps/rowboat_agents/tests/app_client_streaming.py
Normal file
174
apps/rowboat_agents/tests/app_client_streaming.py
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
from src.utils.common import common_logger, read_json_from_file
|
||||
import requests
|
||||
import json
|
||||
import argparse
|
||||
from datetime import datetime
|
||||
|
||||
logger = common_logger
|
||||
logger.info("Running app_client_streaming.py")
|
||||
|
||||
def preprocess_messages(messages):
|
||||
# Preprocess messages to handle null content and role issues
|
||||
for msg in messages:
|
||||
# Handle null content in assistant messages with tool calls
|
||||
if (msg.get("role") == "assistant" and
|
||||
msg.get("content") is None and
|
||||
msg.get("tool_calls") is not None and
|
||||
len(msg.get("tool_calls")) > 0):
|
||||
msg["content"] = "Calling tool"
|
||||
|
||||
# Handle role issues
|
||||
if msg.get("role") == "tool":
|
||||
msg["role"] = "developer"
|
||||
elif not msg.get("role"):
|
||||
msg["role"] = "user"
|
||||
|
||||
return messages
|
||||
|
||||
def stream_chat(host, request_data, api_key):
|
||||
start_time = datetime.now()
|
||||
print("\n" + "="*80)
|
||||
print(f"Starting streaming chat at {start_time}")
|
||||
print(f"Host: {host}")
|
||||
print("="*80 + "\n")
|
||||
|
||||
# First, initialize the stream
|
||||
try:
|
||||
print("\n" + "-"*80)
|
||||
print("Initializing stream...")
|
||||
init_response = requests.post(
|
||||
f"{host}/chat_stream_init",
|
||||
json=request_data,
|
||||
headers={'Authorization': f'Bearer {api_key}'}
|
||||
)
|
||||
print(f"Init Response Status: {init_response.status_code}")
|
||||
print(f"Init Response Text: {init_response.text}")
|
||||
print("-"*80 + "\n")
|
||||
|
||||
if init_response.status_code != 200:
|
||||
logger.error(f"Error initializing stream. Status code: {init_response.status_code}")
|
||||
logger.error(f"Response: {init_response.text}")
|
||||
return
|
||||
|
||||
init_data = init_response.json()
|
||||
|
||||
if 'error' in init_data:
|
||||
logger.error(f"Error initializing stream: {init_data['error']}")
|
||||
return
|
||||
|
||||
stream_id = init_data['stream_id']
|
||||
print(f"Stream initialized successfully with ID: {stream_id}")
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.error(f"Request error during stream initialization: {e}")
|
||||
return
|
||||
except json.JSONDecodeError as e:
|
||||
logger.error(f"Failed to decode JSON response: {e}")
|
||||
logger.error(f"Raw response: {init_response.text}")
|
||||
return
|
||||
|
||||
# Now connect to the stream
|
||||
try:
|
||||
print("\n" + "-"*80)
|
||||
print(f"Connecting to stream {stream_id}...")
|
||||
stream_response = requests.get(
|
||||
f"{host}/chat_stream/{stream_id}",
|
||||
headers={
|
||||
'Authorization': f'Bearer {api_key}',
|
||||
'Accept': 'text/event-stream'
|
||||
},
|
||||
stream=True
|
||||
)
|
||||
|
||||
if stream_response.status_code != 200:
|
||||
logger.error(f"Error connecting to stream. Status code: {stream_response.status_code}")
|
||||
logger.error(f"Response: {stream_response.text}")
|
||||
return
|
||||
|
||||
print(f"Successfully connected to stream")
|
||||
print("-"*80 + "\n")
|
||||
|
||||
event_count = 0
|
||||
current_data = []
|
||||
|
||||
try:
|
||||
print("\n" + "-"*80)
|
||||
print("Starting to process events...")
|
||||
print("-"*80 + "\n")
|
||||
|
||||
for line in stream_response.iter_lines(decode_unicode=True):
|
||||
if line:
|
||||
if line.startswith('data: '):
|
||||
data = line[6:] # Remove 'data: ' prefix
|
||||
try:
|
||||
event_data = json.loads(data)
|
||||
event_count += 1
|
||||
print("\n" + "*"*80)
|
||||
print(f"Event #{event_count}")
|
||||
|
||||
if isinstance(event_data, dict):
|
||||
# Pretty print the event data
|
||||
print("Event Data:")
|
||||
print(json.dumps(event_data, indent=2))
|
||||
|
||||
# Special handling for message events
|
||||
if 'content' in event_data:
|
||||
print("\nMessage Content:", event_data['content'])
|
||||
if event_data.get('tool_calls'):
|
||||
print("Tool Calls:", json.dumps(event_data['tool_calls'], indent=2))
|
||||
else:
|
||||
print("Event Data:", event_data)
|
||||
print("*"*80 + "\n")
|
||||
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"Error decoding event data: {e}")
|
||||
print(f"Raw data: {data}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error processing stream: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
print("\n" + "-"*80)
|
||||
print(f"Closing stream after processing {event_count} events")
|
||||
print("-"*80 + "\n")
|
||||
stream_response.close()
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"Request error during streaming: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
end_time = datetime.now()
|
||||
duration = end_time - start_time
|
||||
print("\n" + "="*80)
|
||||
print(f"Streaming session completed at {end_time}")
|
||||
print(f"Total duration: {duration}")
|
||||
print("="*80 + "\n")
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--sample_request', type=str, required=False, default='tmp.json',
|
||||
help='Sample request JSON file name under tests/sample_requests/')
|
||||
parser.add_argument('--api_key', type=str, required=False, default='test',
|
||||
help='API key to use for authentication')
|
||||
parser.add_argument('--host', type=str, default='http://localhost:4040',
|
||||
help='Host to use for the request')
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
print("\n" + "="*80)
|
||||
print("Loading request data...")
|
||||
request = read_json_from_file(f"./tests/sample_requests/{args.sample_request}").get("lastRequest", {})
|
||||
print("Request data:")
|
||||
print(json.dumps(request, indent=2))
|
||||
print("Starting streaming request...")
|
||||
print("="*80 + "\n")
|
||||
|
||||
stream_chat(args.host, request, args.api_key)
|
||||
except Exception as e:
|
||||
print("\n" + "!"*80)
|
||||
print(f"Error in main: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
print("!"*80 + "\n")
|
||||
|
|
@ -2,12 +2,76 @@ import copy
|
|||
from datetime import datetime
|
||||
import json
|
||||
import sys
|
||||
import asyncio
|
||||
|
||||
from src.graph.core import run_turn, order_messages
|
||||
from src.graph.core import order_messages, run_turn_streamed
|
||||
from src.graph.tools import respond_to_tool_raise_error, respond_to_tool_close_chat, RAG_TOOL, CLOSE_CHAT_TOOL
|
||||
from src.utils.common import common_logger, read_json_from_file
|
||||
logger = common_logger
|
||||
|
||||
def preprocess_messages(messages):
|
||||
# Preprocess messages to handle null content and role issues
|
||||
for msg in messages:
|
||||
# Handle null content in assistant messages with tool calls
|
||||
if (msg.get("role") == "assistant" and
|
||||
msg.get("content") is None and
|
||||
msg.get("tool_calls") is not None and
|
||||
len(msg.get("tool_calls")) > 0):
|
||||
msg["content"] = "Calling tool"
|
||||
|
||||
# Handle role issues
|
||||
if msg.get("role") == "tool":
|
||||
msg["role"] = "developer"
|
||||
elif not msg.get("role"):
|
||||
msg["role"] = "user"
|
||||
|
||||
return messages
|
||||
|
||||
async def process_turn(messages, agent_configs, tool_configs, prompt_configs, start_agent_name, state, config, complete_request):
|
||||
"""Processes a single turn using streaming API"""
|
||||
print(f"\n{'*'*50}\nLatest Request:\n{'*'*50}")
|
||||
request_json = {
|
||||
"messages": [{k: v for k, v in msg.items() if k != 'current_turn'} for msg in messages],
|
||||
"state": state,
|
||||
"agents": agent_configs,
|
||||
"tools": tool_configs,
|
||||
"prompts": prompt_configs,
|
||||
"startAgent": start_agent_name
|
||||
}
|
||||
print(json.dumps(request_json, indent=2))
|
||||
|
||||
collected_messages = []
|
||||
|
||||
async for event_type, event_data in run_turn_streamed(
|
||||
messages=messages,
|
||||
start_agent_name=start_agent_name,
|
||||
agent_configs=agent_configs,
|
||||
tool_configs=tool_configs,
|
||||
start_turn_with_start_agent=config.get("start_turn_with_start_agent", False),
|
||||
state=state,
|
||||
additional_tool_configs=[RAG_TOOL, CLOSE_CHAT_TOOL],
|
||||
complete_request=complete_request
|
||||
):
|
||||
if event_type == "message":
|
||||
# Add each message to collected_messages
|
||||
collected_messages.append(event_data)
|
||||
|
||||
elif event_type == "done":
|
||||
print(f"\n\n{'*'*50}\nLatest Response:\n{'*'*50}")
|
||||
response_json = {
|
||||
"messages": collected_messages,
|
||||
"state": event_data.get('state', {}),
|
||||
}
|
||||
print("Turn completed. Here are the streamed messages and final state:")
|
||||
print(json.dumps(response_json, indent=2))
|
||||
print('='*50)
|
||||
|
||||
return collected_messages, event_data.get('state', {})
|
||||
|
||||
elif event_type == "error":
|
||||
print(f"\nError: {event_data.get('error', 'Unknown error')}")
|
||||
return [], state
|
||||
|
||||
if __name__ == "__main__":
|
||||
logger.info(f"{'*'*50}Running interactive mode{'*'*50}")
|
||||
|
||||
|
|
@ -16,20 +80,23 @@ if __name__ == "__main__":
|
|||
tool_configs = complete_request.get("tools", [])
|
||||
prompt_configs = complete_request.get("prompts", [])
|
||||
start_agent_name = complete_request.get("startAgent", "")
|
||||
|
||||
|
||||
return agent_configs, tool_configs, prompt_configs, start_agent_name
|
||||
|
||||
|
||||
external_tool_mappings = {
|
||||
"raise_error": respond_to_tool_raise_error,
|
||||
"close_chat": respond_to_tool_close_chat
|
||||
}
|
||||
|
||||
|
||||
config_file = sys.argv[sys.argv.index("--config") + 1] if "--config" in sys.argv else "default_config.json"
|
||||
sample_request_file = sys.argv[sys.argv.index("--sample_request") + 1] if "--sample_request" in sys.argv else "default_example.json"
|
||||
|
||||
|
||||
print(f"Config file: {config_file}")
|
||||
print(f"Sample request file: {sample_request_file}")
|
||||
|
||||
config = read_json_from_file(f"./configs/{config_file}")
|
||||
example_request = read_json_from_file(f"./tests/sample_requests/{sample_request_file}").get("lastRequest", {})
|
||||
|
||||
|
||||
if "--load_messages" in sys.argv:
|
||||
messages = example_request.get("messages", [])
|
||||
messages = order_messages(messages)
|
||||
|
|
@ -57,7 +124,7 @@ if __name__ == "__main__":
|
|||
agent_configs, tool_configs, prompt_configs, start_agent_name = extract_request_fields(complete_request)
|
||||
|
||||
print(f"\nUsing agent: {last_agent_name}")
|
||||
|
||||
|
||||
if user_input_needed:
|
||||
user_inp = input('\nUSER: ')
|
||||
messages.append({
|
||||
|
|
@ -71,43 +138,28 @@ if __name__ == "__main__":
|
|||
break
|
||||
logger.info("Added user message to conversation")
|
||||
|
||||
print(f"\n{'*'*50}\nLatest Request:\n{'*'*50}")
|
||||
request_json = {
|
||||
"messages": [{k: v for k, v in msg.items() if k != 'current_turn'} for msg in messages],
|
||||
"state": state,
|
||||
"agents": agent_configs,
|
||||
"tools": tool_configs,
|
||||
"prompts": prompt_configs,
|
||||
"startAgent": start_agent_name
|
||||
}
|
||||
print(json.dumps(request_json, indent=2))
|
||||
print(complete_request)
|
||||
resp_messages, resp_tokens_used, resp_state = run_turn(
|
||||
# Preprocess messages to replace role tool with role developer and add role user to empty roles
|
||||
print("Preprocessing messages to replace role tool with role developer and add role user to empty roles")
|
||||
messages = preprocess_messages(messages)
|
||||
complete_request["messages"] = preprocess_messages(complete_request["messages"])
|
||||
|
||||
# Run the streaming turn
|
||||
resp_messages, resp_state = asyncio.run(process_turn(
|
||||
messages=messages,
|
||||
start_agent_name=start_agent_name,
|
||||
agent_configs=agent_configs,
|
||||
tool_configs=tool_configs,
|
||||
start_turn_with_start_agent=config.get("start_turn_with_start_agent", False),
|
||||
prompt_configs=prompt_configs,
|
||||
start_agent_name=start_agent_name,
|
||||
state=state,
|
||||
additional_tool_configs=[RAG_TOOL, CLOSE_CHAT_TOOL],
|
||||
config=config,
|
||||
complete_request=complete_request
|
||||
)
|
||||
))
|
||||
|
||||
state = resp_state
|
||||
resp_messages = order_messages(resp_messages)
|
||||
|
||||
print(f"\n{'*'*50}\nLatest Response:\n{'*'*50}")
|
||||
response_json = {
|
||||
"messages": resp_messages,
|
||||
"state": state,
|
||||
"tokens_used": resp_tokens_used
|
||||
}
|
||||
print(json.dumps(response_json, indent=2))
|
||||
|
||||
last_msg = resp_messages[-1]
|
||||
print(f"\nBOT: {last_msg}\n")
|
||||
last_msg = resp_messages[-1] if resp_messages else {}
|
||||
tool_calls = last_msg.get("tool_calls", [])
|
||||
sender = last_msg.get("sender", "")
|
||||
|
||||
|
||||
if config.get("return_diff_messages", True):
|
||||
messages.extend(resp_messages)
|
||||
else:
|
||||
|
|
@ -134,7 +186,7 @@ if __name__ == "__main__":
|
|||
current_tool_duration = round((datetime.now() - tool_start_time).total_seconds() * 10) / 10
|
||||
logger.info(f"Tool response duration: {current_tool_duration:.1f}s")
|
||||
tool_duration += current_tool_duration
|
||||
|
||||
|
||||
if tool_name == "close_chat":
|
||||
user_input_needed = False
|
||||
logger.info("Closing chat")
|
||||
|
|
@ -142,10 +194,12 @@ if __name__ == "__main__":
|
|||
|
||||
if should_break:
|
||||
break
|
||||
|
||||
|
||||
else:
|
||||
user_input_needed = True
|
||||
print(f"Turn Duration: {round((datetime.now() - turn_start_time).total_seconds() * 10) / 10:.1f}s\n")
|
||||
print(f"Tool Response Duration: {round(tool_duration * 10) / 10:.1f}s\n")
|
||||
|
||||
print("Quick stats")
|
||||
print(f"Turn Duration: {round((datetime.now() - turn_start_time).total_seconds() * 10) / 10:.1f}s")
|
||||
print(f"Tool Response Duration: {round(tool_duration * 10) / 10:.1f}s")
|
||||
print('='*50)
|
||||
|
||||
print("\n" + "-" * 80)
|
||||
176
apps/rowboat_agents/tests/sample_requests/tmp1.json
Normal file
176
apps/rowboat_agents/tests/sample_requests/tmp1.json
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
{
|
||||
"lastRequest": {
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": ""
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "hi"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"sender": "Door Dash Hub",
|
||||
"content": "Hello! Are you facing issues with your order items or delivery timing? How can I assist you today?",
|
||||
"created_at": "2025-03-24T17:33:27.564940"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "my order is missing fries"
|
||||
},
|
||||
{
|
||||
"content": "Agent changed to Door Dash Hub",
|
||||
"role": "assistant",
|
||||
"sender": "Door Dash Hub",
|
||||
"tool_calls": null,
|
||||
"tool_call_id": null,
|
||||
"response_type": "internal"
|
||||
},
|
||||
{
|
||||
"content": "Agent changed to Order Issue",
|
||||
"role": "assistant",
|
||||
"sender": "Order Issue",
|
||||
"tool_calls": null,
|
||||
"tool_call_id": null,
|
||||
"response_type": "internal"
|
||||
},
|
||||
{
|
||||
"content": "I can help with that. Could you please provide your order ID so I can check the details?",
|
||||
"role": "assistant",
|
||||
"sender": "Order Issue",
|
||||
"tool_calls": null,
|
||||
"tool_call_id": null,
|
||||
"tool_name": null,
|
||||
"response_type": "external"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "12312"
|
||||
}
|
||||
],
|
||||
"state": {
|
||||
"last_agent_name": "Order Issue",
|
||||
"tokens": {
|
||||
"total": 1521,
|
||||
"prompt": 1486,
|
||||
"completion": 35
|
||||
}
|
||||
},
|
||||
"agents": [
|
||||
{
|
||||
"name": "Door Dash Hub",
|
||||
"type": "conversation",
|
||||
"description": "Hub agent to manage Door Dash-related queries.",
|
||||
"instructions": "## \ud83e\uddd1\u200d\ud83d\udcbc Role:\nYou are responsible for directing Door Dash-related queries to appropriate agents.\n\n---\n## \u2699\ufe0f Steps to Follow:\n1. Greet the user and ask which Door Dash-related query they need help with (e.g., 'Are you facing issues with your order items or delivery timing?').\n2. If the query matches a specific task, direct the user to the corresponding agent:\n - Order Issue \u2192 [@agent:Order Issue]\n - Delayed Delivery \u2192 [@agent:Delayed Delivery]\n3. If the query doesn't match any specific task, respond with 'I'm sorry, I didn't understand. Could you clarify your request?' or escalate to human support.\n\n---\n## \ud83c\udfaf Scope:\n\u2705 In Scope:\n- Issues with order items\n- Delayed delivery issues\n\n\u274c Out of Scope:\n- Issues unrelated to Door Dash\n- General knowledge queries\n\n---\n## \ud83d\udccb Guidelines:\n\u2714\ufe0f Dos:\n- Direct queries to specific Door Dash agents promptly.\n- Call [@agent:Escalation] agent for unrecognized queries.\n\n\ud83d\udeab Don'ts:\n- Engage in detailed support.\n- Extend the conversation beyond Door Dash.\n- Provide user-facing text such as 'I will connect you now...' when calling another agent\n\n# Examples\n- **User** : I need help with my order items.\n - **Agent actions**: [@agent:Order Issue](#mention)\n\n- **User** : My delivery is delayed.\n - **Agent actions**: Call [@agent:Delayed Delivery](#mention)\n\n- **User** : I'm not sure where my order is.\n - **Agent actions**: Call [@agent:Delayed Delivery](#mention)\n\n- **User** : Can you reset my order settings?\n - **Agent actions**: [@agent:Escalation](#mention)\n\n- **User** : How are you today?\n - **Agent response**: I'm doing great. What would like help with today?",
|
||||
"model": "gpt-4o-mini",
|
||||
"hasRagSources": false,
|
||||
"controlType": "retain",
|
||||
"tools": [],
|
||||
"prompts": [],
|
||||
"connectedAgents": [
|
||||
"Order Issue",
|
||||
"Delayed Delivery",
|
||||
"Escalation"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Post process",
|
||||
"type": "post_process",
|
||||
"description": "",
|
||||
"instructions": "Ensure that the agent response is terse and to the point.",
|
||||
"model": "gpt-4o-mini",
|
||||
"hasRagSources": false,
|
||||
"controlType": "retain",
|
||||
"tools": [],
|
||||
"prompts": [],
|
||||
"connectedAgents": []
|
||||
},
|
||||
{
|
||||
"name": "Escalation",
|
||||
"type": "escalation",
|
||||
"description": "",
|
||||
"instructions": "Get the user's contact information and let them know that their request has been escalated.",
|
||||
"model": "gpt-4o-mini",
|
||||
"hasRagSources": false,
|
||||
"controlType": "retain",
|
||||
"tools": [],
|
||||
"prompts": [],
|
||||
"connectedAgents": []
|
||||
},
|
||||
{
|
||||
"name": "Order Issue",
|
||||
"type": "conversation",
|
||||
"description": "Agent to assist users with missing or incorrect order items.",
|
||||
"instructions": "## \ud83e\uddd1\u200d\ud83d\udcbc Role:\nAssist users with issues related to missing or incorrect order items.\n\n---\n## \u2699\ufe0f Steps to Follow:\n1. Fetch the order details using the [@tool:get_order_details] tool.\n2. Confirm the issue with the user.\n3. Provide solutions or escalate if unresolved.\n\n---\n## \ud83c\udfaf Scope:\n\u2705 In Scope:\n- Handling missing or incorrect order items\n\n\u274c Out of Scope:\n- Delayed delivery issues\n- General knowledge queries\n\n---\n## \ud83d\udccb Guidelines:\n\u2714\ufe0f Dos:\n- Ensure the user is aware of the order details before proceeding.\n\n\ud83d\udeab Don'ts:\n- Extend the conversation beyond order issues.\n\n# Examples\n- **User** : I received the wrong item in my order.\n - **Agent response**: I can help with that. Let me fetch your order details first.\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : My order is missing an item.\n - **Agent response**: Let's check your order details and resolve this issue.\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : I got someone else's order.\n - **Agent response**: I apologize for the mix-up. I'll fetch your order details to sort this out.\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : Can you help me with a missing item?\n - **Agent response**: Certainly, I'll look into your order details right away.\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : There's an issue with my order items.\n - **Agent response**: Let's verify your order details to address this issue.\n - **Agent actions**: Call [@tool:get_order_details](#mention)",
|
||||
"model": "gpt-4o",
|
||||
"hasRagSources": false,
|
||||
"controlType": "retain",
|
||||
"tools": [
|
||||
"get_order_details"
|
||||
],
|
||||
"prompts": [],
|
||||
"connectedAgents": []
|
||||
},
|
||||
{
|
||||
"name": "Delayed Delivery",
|
||||
"type": "conversation",
|
||||
"description": "Agent to assist users with delayed delivery issues.",
|
||||
"instructions": "## \ud83e\uddd1\u200d\ud83d\udcbc Role:\nAssist users with issues related to delayed delivery.\n\n---\n## \u2699\ufe0f Steps to Follow:\n1. Fetch the delivery status using the [@tool:get_delivery_status] tool.\n2. Confirm the delay with the user.\n3. Provide solutions or escalate if unresolved.\n\n---\n## \ud83c\udfaf Scope:\n\u2705 In Scope:\n- Handling delayed delivery issues\n\n\u274c Out of Scope:\n- Missing or incorrect order items\n- General knowledge queries\n\n---\n## \ud83d\udccb Guidelines:\n\u2714\ufe0f Dos:\n- Ensure the user is aware of the delivery status before proceeding.\n\n\ud83d\udeab Don'ts:\n- Extend the conversation beyond delivery issues.\n\n# Examples\n- **User** : My delivery is late.\n - **Agent response**: I can help with that. Let me fetch your delivery status first.\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : Where is my order? It's delayed.\n - **Agent response**: Let's check your delivery status and resolve this issue.\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : My order hasn't arrived yet.\n - **Agent response**: I apologize for the delay. I'll fetch your delivery status to sort this out.\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : Can you help me with a delayed delivery?\n - **Agent response**: Certainly, I'll look into your delivery status right away.\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : There's an issue with my delivery timing.\n - **Agent response**: Let's verify your delivery status to address this issue.\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)",
|
||||
"model": "gpt-4o",
|
||||
"hasRagSources": false,
|
||||
"controlType": "retain",
|
||||
"tools": [
|
||||
"get_delivery_status"
|
||||
],
|
||||
"prompts": [],
|
||||
"connectedAgents": []
|
||||
}
|
||||
],
|
||||
"tools": [
|
||||
{
|
||||
"name": "get_order_details",
|
||||
"description": "Tool to fetch details about the user's order.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"order_id": {
|
||||
"type": "string",
|
||||
"description": "The unique identifier for the order."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"order_id"
|
||||
]
|
||||
},
|
||||
"mockTool": true,
|
||||
"mockInstructions": "Return a mock response for Door Dash order details."
|
||||
},
|
||||
{
|
||||
"name": "get_delivery_status",
|
||||
"description": "Tool to fetch the current status of the delivery.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"order_id": {
|
||||
"type": "string",
|
||||
"description": "The unique identifier for the order."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"order_id"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"prompts": [
|
||||
{
|
||||
"name": "Style prompt",
|
||||
"type": "style_prompt",
|
||||
"prompt": "You should be empathetic and helpful."
|
||||
}
|
||||
],
|
||||
"startAgent": "Door Dash Hub"
|
||||
}
|
||||
|
||||
}
|
||||
223
apps/rowboat_agents/tests/sample_requests/tmp2.json
Normal file
223
apps/rowboat_agents/tests/sample_requests/tmp2.json
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
{
|
||||
"lastRequest": {
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": ""
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "hi"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"sender": "Door Dash Hub",
|
||||
"content": "Hello! Are you facing issues with your order items or delivery timing? How can I assist you today?",
|
||||
"created_at": "2025-03-24T17:33:27.564940"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "my order is missing fries"
|
||||
},
|
||||
{
|
||||
"content": "Agent changed to Door Dash Hub",
|
||||
"role": "assistant",
|
||||
"sender": "Door Dash Hub",
|
||||
"tool_calls": null,
|
||||
"tool_call_id": null,
|
||||
"response_type": "internal"
|
||||
},
|
||||
{
|
||||
"content": "Agent changed to Order Issue",
|
||||
"role": "assistant",
|
||||
"sender": "Order Issue",
|
||||
"tool_calls": null,
|
||||
"tool_call_id": null,
|
||||
"response_type": "internal"
|
||||
},
|
||||
{
|
||||
"content": "Let's resolve this issue by checking your order details. Could you please provide the order ID?",
|
||||
"role": "assistant",
|
||||
"sender": "Order Issue",
|
||||
"tool_calls": null,
|
||||
"tool_call_id": null,
|
||||
"tool_name": null,
|
||||
"response_type": "external"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "123412"
|
||||
},
|
||||
{
|
||||
"content": "Agent changed to Order Issue",
|
||||
"role": "assistant",
|
||||
"sender": "Order Issue",
|
||||
"tool_calls": null,
|
||||
"tool_call_id": null,
|
||||
"response_type": "internal"
|
||||
},
|
||||
{
|
||||
"content": null,
|
||||
"role": "assistant",
|
||||
"sender": "Order Issue",
|
||||
"tool_calls": [
|
||||
{
|
||||
"function": {
|
||||
"name": "get_order_details",
|
||||
"arguments": "{\"order_id\":\"123412\"}"
|
||||
},
|
||||
"id": "fc_67e37c622f208192aceec557fbd3125609b4eca638eb3571",
|
||||
"type": "function"
|
||||
}
|
||||
],
|
||||
"tool_call_id": null,
|
||||
"tool_name": null,
|
||||
"response_type": "internal"
|
||||
},
|
||||
{
|
||||
"content": "Order Details for Order ID 123412:\n\n- **Restaurant**: Luigi's Pizzeria \n- **Items Ordered**: \n - 2x Margherita Pizza \n - 1x Garlic Bread \n - 1x Caesar Salad \n- **Estimated Delivery Time**: 7:45 PM \n- **Delivery Address**: 123 Elm Street, Apt 4B \n- **Order Status**: Out for delivery \n- **Total Amount**: $32.75 \n- **Payment Method**: Credit Card (**** **** **** 5678) \n- **Contact**: (123) 456-7890 \n- **Special Instructions**: Leave at the door.",
|
||||
"role": "tool",
|
||||
"sender": null,
|
||||
"tool_calls": null,
|
||||
"tool_call_id": "call_dqCMC5oreOoS9znDDJ7PqWha",
|
||||
"tool_name": null,
|
||||
"response_type": "internal"
|
||||
},
|
||||
{
|
||||
"content": "I checked your order details, and it seems the fries were not included. Could you confirm if there was an oversight in placing the order, or were they supposed to be included?",
|
||||
"role": "assistant",
|
||||
"sender": "Order Issue",
|
||||
"tool_calls": null,
|
||||
"tool_call_id": null,
|
||||
"tool_name": null,
|
||||
"response_type": "external"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Fries were supposed to be in"
|
||||
}
|
||||
],
|
||||
"state": {
|
||||
"last_agent_name": "Order Issue",
|
||||
"tokens": {
|
||||
"total": 1699,
|
||||
"prompt": 1643,
|
||||
"completion": 56
|
||||
}
|
||||
},
|
||||
"agents": [
|
||||
{
|
||||
"name": "Door Dash Hub",
|
||||
"type": "conversation",
|
||||
"description": "Hub agent to manage Door Dash-related queries.",
|
||||
"instructions": "## \ud83e\uddd1\u200d\ud83d\udcbc Role:\nYou are responsible for directing Door Dash-related queries to appropriate agents.\n\n---\n## \u2699\ufe0f Steps to Follow:\n1. Greet the user and ask which Door Dash-related query they need help with (e.g., 'Are you facing issues with your order items or delivery timing?').\n2. If the query matches a specific task, direct the user to the corresponding agent:\n - Order Issue \u2192 [@agent:Order Issue]\n - Delayed Delivery \u2192 [@agent:Delayed Delivery]\n3. If the query doesn't match any specific task, respond with 'I'm sorry, I didn't understand. Could you clarify your request?' or escalate to human support.\n\n---\n## \ud83c\udfaf Scope:\n\u2705 In Scope:\n- Issues with order items\n- Delayed delivery issues\n\n\u274c Out of Scope:\n- Issues unrelated to Door Dash\n- General knowledge queries\n\n---\n## \ud83d\udccb Guidelines:\n\u2714\ufe0f Dos:\n- Direct queries to specific Door Dash agents promptly.\n- Call [@agent:Escalation] agent for unrecognized queries.\n\n\ud83d\udeab Don'ts:\n- Engage in detailed support.\n- Extend the conversation beyond Door Dash.\n- Provide user-facing text such as 'I will connect you now...' when calling another agent\n\n# Examples\n- **User** : I need help with my order items.\n - **Agent actions**: [@agent:Order Issue](#mention)\n\n- **User** : My delivery is delayed.\n - **Agent actions**: Call [@agent:Delayed Delivery](#mention)\n\n- **User** : I'm not sure where my order is.\n - **Agent actions**: Call [@agent:Delayed Delivery](#mention)\n\n- **User** : Can you reset my order settings?\n - **Agent actions**: [@agent:Escalation](#mention)\n\n- **User** : How are you today?\n - **Agent response**: I'm doing great. What would like help with today?",
|
||||
"model": "gpt-4o-mini",
|
||||
"hasRagSources": false,
|
||||
"controlType": "retain",
|
||||
"tools": [],
|
||||
"prompts": [],
|
||||
"connectedAgents": [
|
||||
"Order Issue",
|
||||
"Delayed Delivery",
|
||||
"Escalation"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Post process",
|
||||
"type": "post_process",
|
||||
"description": "",
|
||||
"instructions": "Ensure that the agent response is terse and to the point.",
|
||||
"model": "gpt-4o-mini",
|
||||
"hasRagSources": false,
|
||||
"controlType": "retain",
|
||||
"tools": [],
|
||||
"prompts": [],
|
||||
"connectedAgents": []
|
||||
},
|
||||
{
|
||||
"name": "Escalation",
|
||||
"type": "escalation",
|
||||
"description": "",
|
||||
"instructions": "Get the user's contact information and let them know that their request has been escalated.",
|
||||
"model": "gpt-4o-mini",
|
||||
"hasRagSources": false,
|
||||
"controlType": "retain",
|
||||
"tools": [],
|
||||
"prompts": [],
|
||||
"connectedAgents": []
|
||||
},
|
||||
{
|
||||
"name": "Order Issue",
|
||||
"type": "conversation",
|
||||
"description": "Agent to assist users with missing or incorrect order items.",
|
||||
"instructions": "## \ud83e\uddd1\u200d\ud83d\udcbc Role:\nAssist users with issues related to missing or incorrect order items.\n\n---\n## \u2699\ufe0f Steps to Follow:\n1. Fetch the order details using the [@tool:get_order_details] tool.\n2. Confirm the issue with the user.\n3. Provide solutions or escalate if unresolved.\n\n---\n## \ud83c\udfaf Scope:\n\u2705 In Scope:\n- Handling missing or incorrect order items\n\n\u274c Out of Scope:\n- Delayed delivery issues\n- General knowledge queries\n\n---\n## \ud83d\udccb Guidelines:\n\u2714\ufe0f Dos:\n- Ensure the user is aware of the order details before proceeding.\n\n\ud83d\udeab Don'ts:\n- Extend the conversation beyond order issues.\n\n# Examples\n- **User** : I received the wrong item in my order.\n - **Agent response**: I can help with that. Let me fetch your order details first.\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : My order is missing an item.\n - **Agent response**: Let's check your order details and resolve this issue.\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : I got someone else's order.\n - **Agent response**: I apologize for the mix-up. I'll fetch your order details to sort this out.\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : Can you help me with a missing item?\n - **Agent response**: Certainly, I'll look into your order details right away.\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : There's an issue with my order items.\n - **Agent response**: Let's verify your order details to address this issue.\n - **Agent actions**: Call [@tool:get_order_details](#mention)",
|
||||
"model": "gpt-4o",
|
||||
"hasRagSources": false,
|
||||
"controlType": "retain",
|
||||
"tools": [
|
||||
"get_order_details"
|
||||
],
|
||||
"prompts": [],
|
||||
"connectedAgents": []
|
||||
},
|
||||
{
|
||||
"name": "Delayed Delivery",
|
||||
"type": "conversation",
|
||||
"description": "Agent to assist users with delayed delivery issues.",
|
||||
"instructions": "## \ud83e\uddd1\u200d\ud83d\udcbc Role:\nAssist users with issues related to delayed delivery.\n\n---\n## \u2699\ufe0f Steps to Follow:\n1. Fetch the delivery status using the [@tool:get_delivery_status] tool.\n2. Confirm the delay with the user.\n3. Provide solutions or escalate if unresolved.\n\n---\n## \ud83c\udfaf Scope:\n\u2705 In Scope:\n- Handling delayed delivery issues\n\n\u274c Out of Scope:\n- Missing or incorrect order items\n- General knowledge queries\n\n---\n## \ud83d\udccb Guidelines:\n\u2714\ufe0f Dos:\n- Ensure the user is aware of the delivery status before proceeding.\n\n\ud83d\udeab Don'ts:\n- Extend the conversation beyond delivery issues.\n\n# Examples\n- **User** : My delivery is late.\n - **Agent response**: I can help with that. Let me fetch your delivery status first.\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : Where is my order? It's delayed.\n - **Agent response**: Let's check your delivery status and resolve this issue.\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : My order hasn't arrived yet.\n - **Agent response**: I apologize for the delay. I'll fetch your delivery status to sort this out.\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : Can you help me with a delayed delivery?\n - **Agent response**: Certainly, I'll look into your delivery status right away.\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : There's an issue with my delivery timing.\n - **Agent response**: Let's verify your delivery status to address this issue.\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)",
|
||||
"model": "gpt-4o",
|
||||
"hasRagSources": false,
|
||||
"controlType": "retain",
|
||||
"tools": [
|
||||
"get_delivery_status"
|
||||
],
|
||||
"prompts": [],
|
||||
"connectedAgents": []
|
||||
}
|
||||
],
|
||||
"tools": [
|
||||
{
|
||||
"name": "get_order_details",
|
||||
"description": "Tool to fetch details about the user's order.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"order_id": {
|
||||
"type": "string",
|
||||
"description": "The unique identifier for the order."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"order_id"
|
||||
]
|
||||
},
|
||||
"mockTool": true,
|
||||
"mockInstructions": "Return a mock response for Door Dash order details."
|
||||
},
|
||||
{
|
||||
"name": "get_delivery_status",
|
||||
"description": "Tool to fetch the current status of the delivery.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"order_id": {
|
||||
"type": "string",
|
||||
"description": "The unique identifier for the order."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"order_id"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"prompts": [
|
||||
{
|
||||
"name": "Style prompt",
|
||||
"type": "style_prompt",
|
||||
"prompt": "You should be empathetic and helpful."
|
||||
}
|
||||
],
|
||||
"startAgent": "Door Dash Hub"
|
||||
}
|
||||
}
|
||||
270
apps/rowboat_agents/tests/sample_requests/tmp3.json
Normal file
270
apps/rowboat_agents/tests/sample_requests/tmp3.json
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
{
|
||||
"lastRequest": {
|
||||
"projectId": "4ebd5e81-010a-4bc6-91e0-0aa98173dbac",
|
||||
"messages": [
|
||||
{
|
||||
"content": "",
|
||||
"role": "system",
|
||||
"sender": null,
|
||||
"tool_calls": null,
|
||||
"tool_call_id": null,
|
||||
"tool_name": null
|
||||
},
|
||||
{
|
||||
"content": "Hello! How can I assist you with your DoorDash query today? Are you inquiring about a missing item, delivery status, or subscription details?",
|
||||
"role": "assistant",
|
||||
"sender": "DoorDash Support Hub",
|
||||
"tool_calls": null,
|
||||
"tool_call_id": null,
|
||||
"tool_name": null,
|
||||
"response_type": "internal"
|
||||
},
|
||||
{
|
||||
"content": "Hello! How can I assist you with your DoorDash query today? Are you inquiring about a missing item, delivery status, or subscription details?",
|
||||
"role": "assistant",
|
||||
"sender": "DoorDash Support Hub >> External",
|
||||
"tool_calls": null,
|
||||
"tool_call_id": null,
|
||||
"tool_name": null,
|
||||
"response_type": "external"
|
||||
},
|
||||
{
|
||||
"content": "hi",
|
||||
"role": "user",
|
||||
"sender": null,
|
||||
"tool_calls": null,
|
||||
"tool_call_id": null,
|
||||
"tool_name": null
|
||||
}
|
||||
],
|
||||
"state": {
|
||||
"agent_data": [
|
||||
{
|
||||
"instructions": "## 🧑💼 Role:\nYou are responsible for directing DoorDash-related queries to appropriate agents.\n\n---\n## ⚙️ Steps to Follow:\n1. Greet the user and ask which DoorDash-related query they need help with (e.g., 'Are you inquiring about a missing item, delivery status, or subscription details?').\n2. If the query matches a specific task, direct the user to the corresponding agent:\n - Missing Items → [@agent:Missing Items]\n - Delivery Status → [@agent:Delivery Status]\n - Subscription Info → [@agent:Subscription Info]\n3. If the query doesn't match any specific task, respond with 'I'm sorry, I didn't understand. Could you clarify your request?' or escalate to human support.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Missing items queries\n- Delivery status queries\n- Subscription-related queries\n\n❌ Out of Scope:\n- Issues unrelated to DoorDash\n- General knowledge queries\n\n---\n## 📋 Guidelines:\n✔️ Dos:\n- Direct queries to specific DoorDash agents promptly.\n- Call [@agent:Escalation] agent for unrecognized queries.\n\n🚫 Don'ts:\n- Engage in detailed support.\n- Extend the conversation beyond DoorDash.\n- Provide user-facing text such as 'I will connect you now...' when calling another agent\n\n# Examples\n- **User** : I need help with a missing item in my order.\n - **Agent actions**: Call [@agent:Missing Items](#mention)\n\n- **User** : Can you tell me the status of my delivery?\n - **Agent actions**: Call [@agent:Delivery Status](#mention)\n\n- **User** : How are you today?\n - **Agent response**: I'm doing great. What would you like help with today?\n\n- **User** : Can you reset my account settings?\n - **Agent actions**: Call [@agent:Escalation](#mention)\n\n- **User** : I have a question about my order.\n - **Agent response**: Could you specify if it's about a missing item, delivery status, or subscription details?\n\n- **User** : What are the available subscription plans?\n - **Agent actions**: Call [@agent:Subscription Info](#mention)",
|
||||
"name": "DoorDash Support Hub"
|
||||
},
|
||||
{
|
||||
"instructions": "Ensure that the agent response is terse and to the point.",
|
||||
"name": "Post process"
|
||||
},
|
||||
{
|
||||
"instructions": "Get the user's contact information and let them know that their request has been escalated.",
|
||||
"name": "Escalation"
|
||||
},
|
||||
{
|
||||
"instructions": "## 🧑💼 Role:\nHelp users resolve issues with missing items in their orders.\n\n---\n## ⚙️ Steps to Follow:\n1. Fetch the order details using the [@tool:get_order_details] tool.\n2. Confirm the missing items with the user.\n3. Provide resolution options or escalate if unresolved.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Resolving missing items issues\n\n❌ Out of Scope:\n- Delivery status queries\n- General knowledge queries\n\n---\n## 📋 Guidelines:\n✔️ Dos:\n- Use [@tool:get_order_details](#mention) to fetch accurate order information.\n- Provide clear resolution options.\n\n🚫 Don'ts:\n- Assume missing items without user confirmation.\n- Extend the conversation beyond missing items.\n\n# Examples\n- **User** : I didn't receive my fries with my order.\n - **Agent response**: Let me check your order details. Could you please provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : My order is missing a drink.\n - **Agent response**: I apologize for the inconvenience. Let's verify your order details. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : I didn't get the extra sauce I ordered.\n - **Agent response**: Let's check your order details to confirm. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : My burger is missing from the order.\n - **Agent response**: I'm sorry to hear that. Let's verify your order details. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : I didn't get my dessert.\n - **Agent response**: Let's check your order details to confirm. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)",
|
||||
"name": "Missing Items"
|
||||
},
|
||||
{
|
||||
"instructions": "## 🧑💼 Role:\nHelp users with queries related to the delivery status of their orders.\n\n---\n## ⚙️ Steps to Follow:\n1. Fetch the delivery status using the [@tool:get_delivery_status] tool.\n2. Provide the user with the current delivery status.\n3. Offer additional assistance if needed.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Providing delivery status updates\n\n❌ Out of Scope:\n- Resolving missing items issues\n- General knowledge queries\n\n---\n## 📋 Guidelines:\n✔️ Dos:\n- Use [@tool:get_delivery_status](#mention) to fetch accurate delivery information.\n- Provide clear and concise status updates.\n\n🚫 Don'ts:\n- Provide status updates without fetching current information.\n- Extend the conversation beyond delivery status.\n\n# Examples\n- **User** : Where is my order?\n - **Agent response**: Let me check the delivery status for you. Could you please provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : Is my order on the way?\n - **Agent response**: I'll check the delivery status for you. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : When will my order arrive?\n - **Agent response**: Let me find out the delivery status. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : How long until my order gets here?\n - **Agent response**: I'll check the delivery status for you. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : Is my order delayed?\n - **Agent response**: Let me check the delivery status for you. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)",
|
||||
"name": "Delivery Status"
|
||||
},
|
||||
{
|
||||
"instructions": "## 🧑💼 Role:\nProvide information and answer questions related to subscriptions using RAG.\n\n---\n## ⚙️ Steps to Follow:\n1. Use RAG to retrieve relevant information about subscriptions.\n2. Answer the user's questions based on the retrieved information.\n3. If the user's query is outside the scope of subscriptions, inform them politely.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Subscription plans and pricing\n- Subscription features and benefits\n\n❌ Out of Scope:\n- Non-subscription-related queries\n- Detailed account management\n\n---\n## 📋 Guidelines:\n✔️ Dos:\n- Use RAG to provide accurate and up-to-date information.\n- Be clear and concise in your responses.\n\n🚫 Don'ts:\n- Provide information without using RAG.\n- Extend the conversation beyond subscription topics.\n\n# Examples\n- **User** : What are the available subscription plans?\n - **Agent response**: Let me check the available subscription plans for you.\n\n- **User** : How much does the premium subscription cost?\n - **Agent response**: I'll find the current pricing for the premium subscription.\n\n- **User** : Can I change my subscription plan?\n - **Agent response**: I'll provide information on how to change your subscription plan.\n\n- **User** : What benefits do I get with a subscription?\n - **Agent response**: Let me retrieve the benefits associated with our subscription plans.\n\n- **User** : Is there a free trial available?\n - **Agent response**: I'll check if there's a free trial available for our subscriptions.",
|
||||
"name": "Subscription Info"
|
||||
}
|
||||
],
|
||||
"last_agent_name": "DoorDash Support Hub"
|
||||
},
|
||||
"agents": [
|
||||
{
|
||||
"name": "DoorDash Support Hub",
|
||||
"type": "conversation",
|
||||
"description": "Hub agent to manage DoorDash-related queries.",
|
||||
"instructions": "## 🧑💼 Role:\nYou are responsible for directing DoorDash-related queries to appropriate agents.\n\n---\n## ⚙️ Steps to Follow:\n1. Greet the user and ask which DoorDash-related query they need help with (e.g., 'Are you inquiring about a missing item, delivery status, or subscription details?').\n2. If the query matches a specific task, direct the user to the corresponding agent:\n - Missing Items → [@agent:Missing Items]\n - Delivery Status → [@agent:Delivery Status]\n - Subscription Info → [@agent:Subscription Info]\n3. If the query doesn't match any specific task, respond with 'I'm sorry, I didn't understand. Could you clarify your request?' or escalate to human support.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Missing items queries\n- Delivery status queries\n- Subscription-related queries\n\n❌ Out of Scope:\n- Issues unrelated to DoorDash\n- General knowledge queries\n\n---\n## 📋 Guidelines:\n✔️ Dos:\n- Direct queries to specific DoorDash agents promptly.\n- Call [@agent:Escalation] agent for unrecognized queries.\n\n🚫 Don'ts:\n- Engage in detailed support.\n- Extend the conversation beyond DoorDash.\n- Provide user-facing text such as 'I will connect you now...' when calling another agent\n\n# Examples\n- **User** : I need help with a missing item in my order.\n - **Agent actions**: Call [@agent:Missing Items](#mention)\n\n- **User** : Can you tell me the status of my delivery?\n - **Agent actions**: Call [@agent:Delivery Status](#mention)\n\n- **User** : How are you today?\n - **Agent response**: I'm doing great. What would you like help with today?\n\n- **User** : Can you reset my account settings?\n - **Agent actions**: Call [@agent:Escalation](#mention)\n\n- **User** : I have a question about my order.\n - **Agent response**: Could you specify if it's about a missing item, delivery status, or subscription details?\n\n- **User** : What are the available subscription plans?\n - **Agent actions**: Call [@agent:Subscription Info](#mention)",
|
||||
"model": "gpt-4o",
|
||||
"controlType": "retain",
|
||||
"ragK": 3,
|
||||
"ragReturnType": "chunks",
|
||||
"tools": [],
|
||||
"prompts": [],
|
||||
"connectedAgents": [
|
||||
"Missing Items",
|
||||
"Delivery Status",
|
||||
"Subscription Info",
|
||||
"Escalation"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Post process",
|
||||
"type": "post_process",
|
||||
"description": "",
|
||||
"instructions": "Ensure that the agent response is terse and to the point.",
|
||||
"model": "gpt-4o-mini",
|
||||
"controlType": "retain",
|
||||
"ragK": 3,
|
||||
"ragReturnType": "chunks",
|
||||
"tools": [],
|
||||
"prompts": [],
|
||||
"connectedAgents": []
|
||||
},
|
||||
{
|
||||
"name": "Escalation",
|
||||
"type": "escalation",
|
||||
"description": "",
|
||||
"instructions": "Get the user's contact information and let them know that their request has been escalated.",
|
||||
"model": "gpt-4o-mini",
|
||||
"controlType": "retain",
|
||||
"ragK": 3,
|
||||
"ragReturnType": "chunks",
|
||||
"tools": [],
|
||||
"prompts": [],
|
||||
"connectedAgents": []
|
||||
},
|
||||
{
|
||||
"name": "Missing Items",
|
||||
"type": "conversation",
|
||||
"description": "Agent to assist users with missing items in their orders.",
|
||||
"instructions": "## 🧑💼 Role:\nHelp users resolve issues with missing items in their orders.\n\n---\n## ⚙️ Steps to Follow:\n1. Fetch the order details using the [@tool:get_order_details] tool.\n2. Confirm the missing items with the user.\n3. Provide resolution options or escalate if unresolved.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Resolving missing items issues\n\n❌ Out of Scope:\n- Delivery status queries\n- General knowledge queries\n\n---\n## 📋 Guidelines:\n✔️ Dos:\n- Use [@tool:get_order_details](#mention) to fetch accurate order information.\n- Provide clear resolution options.\n\n🚫 Don'ts:\n- Assume missing items without user confirmation.\n- Extend the conversation beyond missing items.\n\n# Examples\n- **User** : I didn't receive my fries with my order.\n - **Agent response**: Let me check your order details. Could you please provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : My order is missing a drink.\n - **Agent response**: I apologize for the inconvenience. Let's verify your order details. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : I didn't get the extra sauce I ordered.\n - **Agent response**: Let's check your order details to confirm. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : My burger is missing from the order.\n - **Agent response**: I'm sorry to hear that. Let's verify your order details. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : I didn't get my dessert.\n - **Agent response**: Let's check your order details to confirm. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)",
|
||||
"model": "gpt-4o",
|
||||
"controlType": "retain",
|
||||
"ragK": 3,
|
||||
"ragReturnType": "chunks",
|
||||
"tools": [
|
||||
"get_order_details"
|
||||
],
|
||||
"prompts": [],
|
||||
"connectedAgents": []
|
||||
},
|
||||
{
|
||||
"name": "Delivery Status",
|
||||
"type": "conversation",
|
||||
"description": "Agent to assist users with delivery status queries.",
|
||||
"instructions": "## 🧑💼 Role:\nHelp users with queries related to the delivery status of their orders.\n\n---\n## ⚙️ Steps to Follow:\n1. Fetch the delivery status using the [@tool:get_delivery_status] tool.\n2. Provide the user with the current delivery status.\n3. Offer additional assistance if needed.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Providing delivery status updates\n\n❌ Out of Scope:\n- Resolving missing items issues\n- General knowledge queries\n\n---\n## 📋 Guidelines:\n✔️ Dos:\n- Use [@tool:get_delivery_status](#mention) to fetch accurate delivery information.\n- Provide clear and concise status updates.\n\n🚫 Don'ts:\n- Provide status updates without fetching current information.\n- Extend the conversation beyond delivery status.\n\n# Examples\n- **User** : Where is my order?\n - **Agent response**: Let me check the delivery status for you. Could you please provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : Is my order on the way?\n - **Agent response**: I'll check the delivery status for you. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : When will my order arrive?\n - **Agent response**: Let me find out the delivery status. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : How long until my order gets here?\n - **Agent response**: I'll check the delivery status for you. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : Is my order delayed?\n - **Agent response**: Let me check the delivery status for you. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)",
|
||||
"model": "gpt-4o",
|
||||
"controlType": "retain",
|
||||
"ragK": 3,
|
||||
"ragReturnType": "chunks",
|
||||
"tools": [
|
||||
"get_delivery_status"
|
||||
],
|
||||
"prompts": [],
|
||||
"connectedAgents": []
|
||||
},
|
||||
{
|
||||
"name": "Subscription Info",
|
||||
"type": "conversation",
|
||||
"description": "Agent to assist users with subscription-related queries.",
|
||||
"instructions": "## 🧑💼 Role:\nProvide information and answer questions related to subscriptions using RAG.\n\n---\n## ⚙️ Steps to Follow:\n1. Use RAG to retrieve relevant information about subscriptions.\n2. Answer the user's questions based on the retrieved information.\n3. If the user's query is outside the scope of subscriptions, inform them politely.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Subscription plans and pricing\n- Subscription features and benefits\n\n❌ Out of Scope:\n- Non-subscription-related queries\n- Detailed account management\n\n---\n## 📋 Guidelines:\n✔️ Dos:\n- Use RAG to provide accurate and up-to-date information.\n- Be clear and concise in your responses.\n\n🚫 Don'ts:\n- Provide information without using RAG.\n- Extend the conversation beyond subscription topics.\n\n# Examples\n- **User** : What are the available subscription plans?\n - **Agent response**: Let me check the available subscription plans for you.\n\n- **User** : How much does the premium subscription cost?\n - **Agent response**: I'll find the current pricing for the premium subscription.\n\n- **User** : Can I change my subscription plan?\n - **Agent response**: I'll provide information on how to change your subscription plan.\n\n- **User** : What benefits do I get with a subscription?\n - **Agent response**: Let me retrieve the benefits associated with our subscription plans.\n\n- **User** : Is there a free trial available?\n - **Agent response**: I'll check if there's a free trial available for our subscriptions.",
|
||||
"model": "gpt-4o",
|
||||
"controlType": "relinquish_to_parent",
|
||||
"ragDataSources": [
|
||||
"67e1612510540d9027909e10"
|
||||
],
|
||||
"ragK": 3,
|
||||
"ragReturnType": "content",
|
||||
"tools": [],
|
||||
"prompts": [],
|
||||
"connectedAgents": []
|
||||
}
|
||||
],
|
||||
"tools": [
|
||||
{
|
||||
"name": "get_order_details",
|
||||
"description": "Tool to fetch the user's order details.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"order_id": {
|
||||
"type": "string",
|
||||
"description": "The unique identifier for the order."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"order_id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "get_delivery_status",
|
||||
"description": "Tool to fetch the delivery status of an order.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"order_id": {
|
||||
"type": "string",
|
||||
"description": "The unique identifier for the order."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"order_id"
|
||||
]
|
||||
},
|
||||
"mockTool": true,
|
||||
"mockInstructions": "Give a mock response for a door dash order delivery status."
|
||||
}
|
||||
],
|
||||
"prompts": [
|
||||
{
|
||||
"name": "Style prompt",
|
||||
"type": "style_prompt",
|
||||
"prompt": "You should be empathetic and helpful."
|
||||
},
|
||||
{
|
||||
"name": "Greeting",
|
||||
"type": "greeting",
|
||||
"prompt": "Hello! How can I help you?"
|
||||
}
|
||||
],
|
||||
"startAgent": "DoorDash Support Hub",
|
||||
"mcpServers": [
|
||||
{
|
||||
"name": "delivery",
|
||||
"url": "http://localhost:8000/sse"
|
||||
}
|
||||
],
|
||||
"toolWebhookUrl": "http://127.0.0.1:4020/tool_call"
|
||||
},
|
||||
"lastResponse": {
|
||||
"messages": [
|
||||
{
|
||||
"content": "Hi there! How can I help you with your DoorDash query? Are you inquiring about a missing item, delivery status, or subscription details?",
|
||||
"created_at": null,
|
||||
"response_type": "internal",
|
||||
"role": "assistant",
|
||||
"sender": "DoorDash Support Hub"
|
||||
},
|
||||
{
|
||||
"content": "Hi there! How can I help you with your DoorDash query? Are you inquiring about a missing item, delivery status, or subscription details?",
|
||||
"created_at": null,
|
||||
"response_type": "external",
|
||||
"role": "assistant",
|
||||
"sender": "DoorDash Support Hub >> External"
|
||||
}
|
||||
],
|
||||
"state": {
|
||||
"agent_data": [
|
||||
{
|
||||
"instructions": "## 🧑💼 Role:\nYou are responsible for directing DoorDash-related queries to appropriate agents.\n\n---\n## ⚙️ Steps to Follow:\n1. Greet the user and ask which DoorDash-related query they need help with (e.g., 'Are you inquiring about a missing item, delivery status, or subscription details?').\n2. If the query matches a specific task, direct the user to the corresponding agent:\n - Missing Items → [@agent:Missing Items]\n - Delivery Status → [@agent:Delivery Status]\n - Subscription Info → [@agent:Subscription Info]\n3. If the query doesn't match any specific task, respond with 'I'm sorry, I didn't understand. Could you clarify your request?' or escalate to human support.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Missing items queries\n- Delivery status queries\n- Subscription-related queries\n\n❌ Out of Scope:\n- Issues unrelated to DoorDash\n- General knowledge queries\n\n---\n## 📋 Guidelines:\n✔️ Dos:\n- Direct queries to specific DoorDash agents promptly.\n- Call [@agent:Escalation] agent for unrecognized queries.\n\n🚫 Don'ts:\n- Engage in detailed support.\n- Extend the conversation beyond DoorDash.\n- Provide user-facing text such as 'I will connect you now...' when calling another agent\n\n# Examples\n- **User** : I need help with a missing item in my order.\n - **Agent actions**: Call [@agent:Missing Items](#mention)\n\n- **User** : Can you tell me the status of my delivery?\n - **Agent actions**: Call [@agent:Delivery Status](#mention)\n\n- **User** : How are you today?\n - **Agent response**: I'm doing great. What would you like help with today?\n\n- **User** : Can you reset my account settings?\n - **Agent actions**: Call [@agent:Escalation](#mention)\n\n- **User** : I have a question about my order.\n - **Agent response**: Could you specify if it's about a missing item, delivery status, or subscription details?\n\n- **User** : What are the available subscription plans?\n - **Agent actions**: Call [@agent:Subscription Info](#mention)",
|
||||
"name": "DoorDash Support Hub"
|
||||
},
|
||||
{
|
||||
"instructions": "Ensure that the agent response is terse and to the point.",
|
||||
"name": "Post process"
|
||||
},
|
||||
{
|
||||
"instructions": "Get the user's contact information and let them know that their request has been escalated.",
|
||||
"name": "Escalation"
|
||||
},
|
||||
{
|
||||
"instructions": "## 🧑💼 Role:\nHelp users resolve issues with missing items in their orders.\n\n---\n## ⚙️ Steps to Follow:\n1. Fetch the order details using the [@tool:get_order_details] tool.\n2. Confirm the missing items with the user.\n3. Provide resolution options or escalate if unresolved.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Resolving missing items issues\n\n❌ Out of Scope:\n- Delivery status queries\n- General knowledge queries\n\n---\n## 📋 Guidelines:\n✔️ Dos:\n- Use [@tool:get_order_details](#mention) to fetch accurate order information.\n- Provide clear resolution options.\n\n🚫 Don'ts:\n- Assume missing items without user confirmation.\n- Extend the conversation beyond missing items.\n\n# Examples\n- **User** : I didn't receive my fries with my order.\n - **Agent response**: Let me check your order details. Could you please provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : My order is missing a drink.\n - **Agent response**: I apologize for the inconvenience. Let's verify your order details. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : I didn't get the extra sauce I ordered.\n - **Agent response**: Let's check your order details to confirm. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : My burger is missing from the order.\n - **Agent response**: I'm sorry to hear that. Let's verify your order details. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : I didn't get my dessert.\n - **Agent response**: Let's check your order details to confirm. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)",
|
||||
"name": "Missing Items"
|
||||
},
|
||||
{
|
||||
"instructions": "## 🧑💼 Role:\nHelp users with queries related to the delivery status of their orders.\n\n---\n## ⚙️ Steps to Follow:\n1. Fetch the delivery status using the [@tool:get_delivery_status] tool.\n2. Provide the user with the current delivery status.\n3. Offer additional assistance if needed.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Providing delivery status updates\n\n❌ Out of Scope:\n- Resolving missing items issues\n- General knowledge queries\n\n---\n## 📋 Guidelines:\n✔️ Dos:\n- Use [@tool:get_delivery_status](#mention) to fetch accurate delivery information.\n- Provide clear and concise status updates.\n\n🚫 Don'ts:\n- Provide status updates without fetching current information.\n- Extend the conversation beyond delivery status.\n\n# Examples\n- **User** : Where is my order?\n - **Agent response**: Let me check the delivery status for you. Could you please provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : Is my order on the way?\n - **Agent response**: I'll check the delivery status for you. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : When will my order arrive?\n - **Agent response**: Let me find out the delivery status. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : How long until my order gets here?\n - **Agent response**: I'll check the delivery status for you. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : Is my order delayed?\n - **Agent response**: Let me check the delivery status for you. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)",
|
||||
"name": "Delivery Status"
|
||||
},
|
||||
{
|
||||
"instructions": "## 🧑💼 Role:\nProvide information and answer questions related to subscriptions using RAG.\n\n---\n## ⚙️ Steps to Follow:\n1. Use RAG to retrieve relevant information about subscriptions.\n2. Answer the user's questions based on the retrieved information.\n3. If the user's query is outside the scope of subscriptions, inform them politely.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Subscription plans and pricing\n- Subscription features and benefits\n\n❌ Out of Scope:\n- Non-subscription-related queries\n- Detailed account management\n\n---\n## 📋 Guidelines:\n✔️ Dos:\n- Use RAG to provide accurate and up-to-date information.\n- Be clear and concise in your responses.\n\n🚫 Don'ts:\n- Provide information without using RAG.\n- Extend the conversation beyond subscription topics.\n\n# Examples\n- **User** : What are the available subscription plans?\n - **Agent response**: Let me check the available subscription plans for you.\n\n- **User** : How much does the premium subscription cost?\n - **Agent response**: I'll find the current pricing for the premium subscription.\n\n- **User** : Can I change my subscription plan?\n - **Agent response**: I'll provide information on how to change your subscription plan.\n\n- **User** : What benefits do I get with a subscription?\n - **Agent response**: Let me retrieve the benefits associated with our subscription plans.\n\n- **User** : Is there a free trial available?\n - **Agent response**: I'll check if there's a free trial available for our subscriptions.",
|
||||
"name": "Subscription Info"
|
||||
}
|
||||
],
|
||||
"last_agent_name": "DoorDash Support Hub"
|
||||
},
|
||||
"tokens_used": {
|
||||
"completion": 50,
|
||||
"prompt": 50,
|
||||
"total": 100
|
||||
}
|
||||
}
|
||||
}
|
||||
166
apps/rowboat_agents/tests/sample_requests/tmp4.json
Normal file
166
apps/rowboat_agents/tests/sample_requests/tmp4.json
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
{
|
||||
"lastRequest": {
|
||||
"projectId": "4ebd5e81-010a-4bc6-91e0-0aa98173dbac",
|
||||
"messages": [
|
||||
{
|
||||
"content": "",
|
||||
"role": "system",
|
||||
"sender": null,
|
||||
"tool_calls": null,
|
||||
"tool_call_id": null,
|
||||
"tool_name": null
|
||||
}
|
||||
],
|
||||
"state": {
|
||||
"last_agent_name": "DoorDash Support Hub"
|
||||
},
|
||||
"agents": [
|
||||
{
|
||||
"name": "DoorDash Support Hub",
|
||||
"type": "conversation",
|
||||
"description": "Hub agent to manage DoorDash-related queries.",
|
||||
"instructions": "## 🧑💼 Role:\nYou are responsible for directing DoorDash-related queries to appropriate agents.\n\n---\n## ⚙️ Steps to Follow:\n1. Greet the user and ask which DoorDash-related query they need help with (e.g., 'Are you inquiring about a missing item, delivery status, or subscription details?').\n2. If the query matches a specific task, direct the user to the corresponding agent:\n - Missing Items → [@agent:Missing Items]\n - Delivery Status → [@agent:Delivery Status]\n - Subscription Info → [@agent:Subscription Info]\n3. If the query doesn't match any specific task, respond with 'I'm sorry, I didn't understand. Could you clarify your request?' or escalate to human support.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Missing items queries\n- Delivery status queries\n- Subscription-related queries\n\n❌ Out of Scope:\n- Issues unrelated to DoorDash\n- General knowledge queries\n\n---\n## 📋 Guidelines:\n✔️ Dos:\n- Direct queries to specific DoorDash agents promptly.\n- Call [@agent:Escalation] agent for unrecognized queries.\n\n🚫 Don'ts:\n- Engage in detailed support.\n- Extend the conversation beyond DoorDash.\n- Provide user-facing text such as 'I will connect you now...' when calling another agent\n\n# Examples\n- **User** : I need help with a missing item in my order.\n - **Agent actions**: Call [@agent:Missing Items](#mention)\n\n- **User** : Can you tell me the status of my delivery?\n - **Agent actions**: Call [@agent:Delivery Status](#mention)\n\n- **User** : How are you today?\n - **Agent response**: I'm doing great. What would you like help with today?\n\n- **User** : Can you reset my account settings?\n - **Agent actions**: Call [@agent:Escalation](#mention)\n\n- **User** : I have a question about my order.\n - **Agent response**: Could you specify if it's about a missing item, delivery status, or subscription details?\n\n- **User** : What are the available subscription plans?\n - **Agent actions**: Call [@agent:Subscription Info](#mention)",
|
||||
"model": "gpt-4o",
|
||||
"controlType": "retain",
|
||||
"ragK": 3,
|
||||
"ragReturnType": "chunks",
|
||||
"tools": [],
|
||||
"prompts": [],
|
||||
"connectedAgents": [
|
||||
"Missing Items",
|
||||
"Delivery Status",
|
||||
"Subscription Info",
|
||||
"Escalation"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Post process",
|
||||
"type": "post_process",
|
||||
"description": "",
|
||||
"instructions": "Ensure that the agent response is terse and to the point.",
|
||||
"model": "gpt-4o-mini",
|
||||
"controlType": "retain",
|
||||
"ragK": 3,
|
||||
"ragReturnType": "chunks",
|
||||
"tools": [],
|
||||
"prompts": [],
|
||||
"connectedAgents": []
|
||||
},
|
||||
{
|
||||
"name": "Escalation",
|
||||
"type": "escalation",
|
||||
"description": "",
|
||||
"instructions": "Get the user's contact information and let them know that their request has been escalated.",
|
||||
"model": "gpt-4o-mini",
|
||||
"controlType": "retain",
|
||||
"ragK": 3,
|
||||
"ragReturnType": "chunks",
|
||||
"tools": [],
|
||||
"prompts": [],
|
||||
"connectedAgents": []
|
||||
},
|
||||
{
|
||||
"name": "Missing Items",
|
||||
"type": "conversation",
|
||||
"description": "Agent to assist users with missing items in their orders.",
|
||||
"instructions": "## 🧑💼 Role:\nHelp users resolve issues with missing items in their orders.\n\n---\n## ⚙️ Steps to Follow:\n1. Fetch the order details using the [@tool:get_order_details] tool.\n2. Confirm the missing items with the user.\n3. Provide resolution options or escalate if unresolved.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Resolving missing items issues\n\n❌ Out of Scope:\n- Delivery status queries\n- General knowledge queries\n\n---\n## 📋 Guidelines:\n✔️ Dos:\n- Use [@tool:get_order_details](#mention) to fetch accurate order information.\n- Provide clear resolution options.\n\n🚫 Don'ts:\n- Assume missing items without user confirmation.\n- Extend the conversation beyond missing items.\n\n# Examples\n- **User** : I didn't receive my fries with my order.\n - **Agent response**: Let me check your order details. Could you please provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : My order is missing a drink.\n - **Agent response**: I apologize for the inconvenience. Let's verify your order details. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : I didn't get the extra sauce I ordered.\n - **Agent response**: Let's check your order details to confirm. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : My burger is missing from the order.\n - **Agent response**: I'm sorry to hear that. Let's verify your order details. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : I didn't get my dessert.\n - **Agent response**: Let's check your order details to confirm. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)",
|
||||
"model": "gpt-4o",
|
||||
"controlType": "retain",
|
||||
"ragK": 3,
|
||||
"ragReturnType": "chunks",
|
||||
"tools": [
|
||||
"get_order_details"
|
||||
],
|
||||
"prompts": [],
|
||||
"connectedAgents": []
|
||||
},
|
||||
{
|
||||
"name": "Delivery Status",
|
||||
"type": "conversation",
|
||||
"description": "Agent to assist users with delivery status queries.",
|
||||
"instructions": "## 🧑💼 Role:\nHelp users with queries related to the delivery status of their orders.\n\n---\n## ⚙️ Steps to Follow:\n1. Fetch the delivery status using the [@tool:get_delivery_status] tool.\n2. Provide the user with the current delivery status.\n3. Offer additional assistance if needed.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Providing delivery status updates\n\n❌ Out of Scope:\n- Resolving missing items issues\n- General knowledge queries\n\n---\n## 📋 Guidelines:\n✔️ Dos:\n- Use [@tool:get_delivery_status](#mention) to fetch accurate delivery information.\n- Provide clear and concise status updates.\n\n🚫 Don'ts:\n- Provide status updates without fetching current information.\n- Extend the conversation beyond delivery status.\n\n# Examples\n- **User** : Where is my order?\n - **Agent response**: Let me check the delivery status for you. Could you please provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : Is my order on the way?\n - **Agent response**: I'll check the delivery status for you. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : When will my order arrive?\n - **Agent response**: Let me find out the delivery status. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : How long until my order gets here?\n - **Agent response**: I'll check the delivery status for you. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : Is my order delayed?\n - **Agent response**: Let me check the delivery status for you. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)",
|
||||
"model": "gpt-4o",
|
||||
"controlType": "retain",
|
||||
"ragK": 3,
|
||||
"ragReturnType": "chunks",
|
||||
"tools": [
|
||||
"get_delivery_status"
|
||||
],
|
||||
"prompts": [],
|
||||
"connectedAgents": []
|
||||
},
|
||||
{
|
||||
"name": "Subscription Info",
|
||||
"type": "conversation",
|
||||
"description": "Agent to assist users with subscription-related queries.",
|
||||
"instructions": "## 🧑💼 Role:\nProvide information and answer questions related to subscriptions using RAG.\n\n---\n## ⚙️ Steps to Follow:\n1. Use RAG to retrieve relevant information about subscriptions.\n2. Answer the user's questions based on the retrieved information.\n3. If the user's query is outside the scope of subscriptions, inform them politely.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Subscription plans and pricing\n- Subscription features and benefits\n\n❌ Out of Scope:\n- Non-subscription-related queries\n- Detailed account management\n\n---\n## 📋 Guidelines:\n✔️ Dos:\n- Use RAG to provide accurate and up-to-date information.\n- Be clear and concise in your responses.\n\n🚫 Don'ts:\n- Provide information without using RAG.\n- Extend the conversation beyond subscription topics.\n\n# Examples\n- **User** : What are the available subscription plans?\n - **Agent response**: Let me check the available subscription plans for you.\n\n- **User** : How much does the premium subscription cost?\n - **Agent response**: I'll find the current pricing for the premium subscription.\n\n- **User** : Can I change my subscription plan?\n - **Agent response**: I'll provide information on how to change your subscription plan.\n\n- **User** : What benefits do I get with a subscription?\n - **Agent response**: Let me retrieve the benefits associated with our subscription plans.\n\n- **User** : Is there a free trial available?\n - **Agent response**: I'll check if there's a free trial available for our subscriptions.",
|
||||
"model": "gpt-4o",
|
||||
"controlType": "relinquish_to_parent",
|
||||
"ragDataSources": [
|
||||
"67e1612510540d9027909e10"
|
||||
],
|
||||
"ragK": 3,
|
||||
"ragReturnType": "content",
|
||||
"tools": [],
|
||||
"prompts": [],
|
||||
"connectedAgents": []
|
||||
}
|
||||
],
|
||||
"tools": [
|
||||
{
|
||||
"name": "get_order_details",
|
||||
"description": "Tool to fetch the user's order details.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"order_id": {
|
||||
"type": "string",
|
||||
"description": "The unique identifier for the order."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"order_id"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "get_delivery_status",
|
||||
"description": "Tool to fetch the delivery status of an order.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"order_id": {
|
||||
"type": "string",
|
||||
"description": "The unique identifier for the order."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"order_id"
|
||||
]
|
||||
},
|
||||
"mockTool": true,
|
||||
"mockInstructions": "Give a mock response for a door dash order delivery status."
|
||||
}
|
||||
],
|
||||
"prompts": [
|
||||
{
|
||||
"name": "Style prompt",
|
||||
"type": "style_prompt",
|
||||
"prompt": "You should be empathetic and helpful."
|
||||
},
|
||||
{
|
||||
"name": "Greeting",
|
||||
"type": "greeting",
|
||||
"prompt": "Hello! How can I help you?"
|
||||
}
|
||||
],
|
||||
"startAgent": "DoorDash Support Hub",
|
||||
"mcpServers": [
|
||||
{
|
||||
"name": "delivery",
|
||||
"url": "http://localhost:8000/sse"
|
||||
}
|
||||
],
|
||||
"toolWebhookUrl": "http://127.0.0.1:4020/tool_call"
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@ services:
|
|||
- AUTH0_ISSUER_BASE_URL=${AUTH0_ISSUER_BASE_URL}
|
||||
- AUTH0_CLIENT_ID=${AUTH0_CLIENT_ID}
|
||||
- AUTH0_CLIENT_SECRET=${AUTH0_CLIENT_SECRET}
|
||||
- AGENTS_API_URL=http://agents:3001
|
||||
- AGENTS_API_URL=http://rowboat_agents:3001
|
||||
- AGENTS_API_KEY=${AGENTS_API_KEY}
|
||||
- COPILOT_API_URL=http://copilot:3002
|
||||
- COPILOT_API_KEY=${COPILOT_API_KEY}
|
||||
|
|
@ -37,9 +37,9 @@ services:
|
|||
- MAX_PROJECTS_PER_USER=${MAX_PROJECTS_PER_USER}
|
||||
restart: unless-stopped
|
||||
|
||||
agents:
|
||||
rowboat_agents:
|
||||
build:
|
||||
context: ./apps/agents
|
||||
context: ./apps/rowboat_agents
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- "3001:3001"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue