Update docs to Plano (#639)

This commit is contained in:
Salman Paracha 2025-12-23 17:14:50 -08:00 committed by GitHub
parent 15fbb6c3af
commit e224cba3e3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
139 changed files with 4407 additions and 24735 deletions

View file

@ -26,12 +26,6 @@ endpoints:
system_prompt: |
You are a helpful assistant. Only respond to queries related to currency exchange. If there are any other questions, I can't help you.
prompt_guards:
input_guards:
jailbreak:
on_exception:
message: Looks like you're curious about my abilities, but I can only provide assistance for currency exchange.
prompt_targets:
- name: currency_exchange
description: Get currency exchange rate from USD to other currencies

View file

@ -1,16 +0,0 @@
FROM python:3.12 AS base
FROM base AS builder
WORKDIR /src
COPY requirements.txt /src/
RUN pip install --prefix=/runtime --force-reinstall -r requirements.txt
FROM python:3.12-slim AS output
COPY --from=builder /runtime /usr/local
WORKDIR /app
COPY . /app
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80", "--log-level", "info"]

View file

@ -1,29 +0,0 @@
# HR Agent Demo
This demo showcases how the **Arch** can be used to build an HR agent to manage workforce-related inquiries, workforce planning, and communication via Slack. It intelligently routes incoming prompts to the correct targets, providing concise and useful responses tailored for HR and workforce decision-making.
## Available Functions:
- **HR Q/A**: Handles general Q&A related to insurance policies.
- **Endpoint**: `/agent/hr_qa`
- **Workforce Data Retrieval**: Retrieves data related to workforce metrics like headcount, satisfaction, and staffing.
- **Endpoint**: `/agent/workforce`
- Parameters:
- `staffing_type` (str, required): Type of staffing (e.g., `contract`, `fte`, `agency`).
- `region` (str, required): Region for which the data is requested (e.g., `asia`, `europe`, `americas`).
- `point_in_time` (int, optional): Time point for data retrieval (e.g., `0 days ago`, `30 days ago`).
- **Initiate Policy**: Sends messages to a Slack channel
- **Endpoint**: `/agent/slack_message`
- Parameters:
- `slack_message` (str, required): The message content to be sent
# Starting the demo
1. Please make sure the [pre-requisites](https://github.com/katanemo/arch/?tab=readme-ov-file#prerequisites) are installed correctly
2. Start Arch
```sh
sh run_demo.sh
```
3. Navigate to http://localhost:18080/agent/chat
4. "Can you give me workforce data for asia?"

View file

@ -1,63 +0,0 @@
version: v0.1.0
listeners:
ingress_traffic:
address: 0.0.0.0
port: 10000
message_format: openai
timeout: 30s
# Centralized way to manage LLMs, manage keys, retry logic, failover and limits in a central way
llm_providers:
- access_key: $OPENAI_API_KEY
model: openai/gpt-4o-mini
default: true
# Arch creates a round-robin load balancing between different endpoints, managed via the cluster subsystem.
endpoints:
app_server:
# value could be ip address or a hostname with port
# this could also be a list of endpoints for load balancing
# for example endpoint: [ ip1:port, ip2:port ]
endpoint: host.docker.internal:18083
# max time to wait for a connection to be established
connect_timeout: 0.005s
# default system prompt used by all prompt targets
system_prompt: |
You are a Workforce assistant that helps on workforce planning and HR decision makers with reporting and workforce planning. Use following rules when responding,
- when you get data in json format, offer some summary but don't be too verbose
- be concise, to the point and do not over analyze the data
prompt_targets:
- name: workforce
description: Get workforce data like headcount and satisfaction levels by region and staffing type
endpoint:
name: app_server
path: /agent/workforce
http_method: POST
parameters:
- name: staffing_type
type: str
description: specific category or nature of employment used by an organization like fte, contract and agency
required: true
enum: [fte, contract, agency]
- name: region
type: str
required: true
description: Geographical region for which you want workforce data like asia, europe, americas.
- name: data_snapshot_days_ago
type: int
required: false
description: the snapshot day for which you want workforce data.
- name: slack_message
endpoint:
name: app_server
path: /agent/slack_message
http_method: POST
description: sends a slack message on a channel
parameters:
- name: slack_message
type: string
required: true
description: the message that should be sent to a slack channel

View file

@ -1,29 +0,0 @@
services:
api_server:
build:
context: .
environment:
- SLACK_BOT_TOKEN=${SLACK_BOT_TOKEN:-None}
- OPENAI_API_KEY=${OPENAI_API_KEY:?error}
- CHAT_COMPLETION_ENDPOINT=http://host.docker.internal:10000/v1
volumes:
- ./arch_config.yaml:/app/arch_config.yaml
ports:
- "18083:80"
healthcheck:
test: ["CMD", "curl" ,"http://localhost:80/healthz"]
interval: 5s
retries: 20
chatbot_ui:
build:
context: ../../shared/chatbot_ui
dockerfile: Dockerfile
ports:
- "18080:8080"
environment:
- CHAT_COMPLETION_ENDPOINT=http://host.docker.internal:10000/v1
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- ./arch_config.yaml:/app/arch_config.yaml

Binary file not shown.

Before

Width:  |  Height:  |  Size: 549 KiB

View file

@ -1,94 +0,0 @@
import os
import json
import pandas as pd
import gradio as gr
import logging
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field
from enum import Enum
from typing import List, Optional, Tuple
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError
from openai import OpenAI
app = FastAPI()
workforce_data_df = None
with open("workforce_data.json") as file:
workforce_data = json.load(file)
workforce_data_df = pd.json_normalize(
workforce_data,
record_path=["regions"],
meta=["data_snapshot_days_ago", "satisfaction"],
)
# Define the request model
class WorkforceRequest(BaseModel):
region: str
staffing_type: str
data_snapshot_days_ago: Optional[int] = None
class SlackRequest(BaseModel):
slack_message: str
class WorkforceResponse(BaseModel):
region: str
staffing_type: str
headcount: int
satisfaction: float
@app.post("/agent/slack_message")
def send_slack_message(request: SlackRequest):
"""
Endpoint that sends slack message
"""
slack_message = request.slack_message
# Load the bot token from an environment variable or replace it directly
slack_token = os.getenv(
"SLACK_BOT_TOKEN"
) # Replace with your token if needed: 'xoxb-your-token'
if slack_token is None:
print(f"Message for slack: {slack_message}")
else:
client = WebClient(token=slack_token)
channel = "hr_agent_demo"
try:
# Send the message
response = client.chat_postMessage(channel=channel, text=slack_message)
return f"Message sent to {channel}: {response['message']['text']}"
except SlackApiError as e:
print(f"Error sending message: {e.response['error']}")
# Post method for device summary
@app.post("/agent/workforce")
def get_workforce(request: WorkforceRequest):
"""
Endpoint to workforce data by region, staffing type at a given point in time.
"""
region = request.region.lower()
staffing_type = request.staffing_type.lower()
data_snapshot_days_ago = (
request.data_snapshot_days_ago
if request.data_snapshot_days_ago
else 0 # this param is not required.
)
response = {
"region": region,
"staffing_type": f"Staffing agency: {staffing_type}",
"headcount": f"Headcount: {int(workforce_data_df[(workforce_data_df['region']==region) & (workforce_data_df['data_snapshot_days_ago']==data_snapshot_days_ago)][staffing_type].values[0])}",
"satisfaction": f"Satisfaction: {float(workforce_data_df[(workforce_data_df['region']==region) & (workforce_data_df['data_snapshot_days_ago']==data_snapshot_days_ago)]['satisfaction'].values[0])}",
}
return response
if __name__ == "__main__":
app.run(debug=True)

View file

@ -1,14 +0,0 @@
fastapi
uvicorn
slack-sdk
typing
pandas
gradio==5.3.0
huggingface_hub<1.0.0
async_timeout==4.0.3
loguru==0.7.2
asyncio==3.4.3
httpx==0.27.0
python-dotenv==1.0.1
pydantic==2.8.2
openai==1.51.0

View file

@ -1,47 +0,0 @@
#!/bin/bash
set -e
# Function to start the demo
start_demo() {
# Step 1: Check if .env file exists
if [ -f ".env" ]; then
echo ".env file already exists. Skipping creation."
else
# Step 2: Create `.env` file and set OpenAI key
if [ -z "$OPENAI_API_KEY" ]; then
echo "Error: OPENAI_API_KEY environment variable is not set for the demo."
exit 1
fi
echo "Creating .env file..."
echo "OPENAI_API_KEY=$OPENAI_API_KEY" > .env
echo ".env file created with OPENAI_API_KEY."
fi
# Step 3: Start Arch
echo "Starting Arch with arch_config.yaml..."
archgw up arch_config.yaml
# Step 4: Start Network Agent
echo "Starting HR Agent using Docker Compose..."
docker compose up -d # Run in detached mode
}
# Function to stop the demo
stop_demo() {
# Step 1: Stop Docker Compose services
echo "Stopping HR Agent using Docker Compose..."
docker compose down
# Step 2: Stop Arch
echo "Stopping Arch..."
archgw down
}
# Main script logic
if [ "$1" == "down" ]; then
stop_demo
else
# Default action is to bring the demo up
start_demo
fi

View file

@ -1,14 +0,0 @@
test_cases:
- id: get workforce data
input:
messages:
- role: user
content: what is workforce data for asia for fte employees
expected_tools:
- type: function
function:
name: workforce
arguments:
staffing_type: fte
region: asia
expected_output_contains: asia

View file

@ -1,29 +0,0 @@
[
{
"data_snapshot_days_ago": 0,
"regions": [
{ "region": "asia", "contract": 100, "fte": 150, "agency": 2000 },
{ "region": "europe", "contract": 80, "fte": 120, "agency": 2500 },
{ "region": "americas", "contract": 90, "fte": 200, "agency": 3100 }
],
"satisfaction": 3.5
},
{
"data_snapshot_days_ago": 30,
"regions": [
{ "region": "asia", "contract": 110, "fte": 155, "agency": 1000 },
{ "region": "europe", "contract": 85, "fte": 130, "agency": 1600 },
{ "region": "americas", "contract": 95, "fte": 210, "agency": 3100 }
],
"satisfaction": 4.0
},
{
"data_snapshot_days_ago": 60,
"regions": [
{ "region": "asia", "contract": 115, "fte": 160, "agency": 500 },
{ "region": "europe", "contract": 90, "fte": 140, "agency": 700 },
{ "region": "americas", "contract": 100, "fte": 220, "agency": 1200 }
],
"satisfaction": 4.7
}
]

View file

@ -1,19 +0,0 @@
FROM python:3.12 AS base
FROM base AS builder
WORKDIR /src
COPY requirements.txt /src/
RUN pip install --prefix=/runtime --force-reinstall -r requirements.txt
COPY ../. /src
FROM python:3.12-slim AS output
COPY --from=builder /runtime /usr/local
COPY ../. /app
WORKDIR /app
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80", "--log-level", "info"]

View file

@ -1,42 +0,0 @@
# Network Agent Demo
This demo illustrates how **Arch** can be used to perform function calling with network-related tasks. In this demo, you act as a **network assistant** that provides factual information, without offering advice on manufacturers or purchasing decisions.
The assistant can perform several key operations, including rebooting devices, answering general networking questions, and retrieving device statistics. By default, the system prompt ensures that the assistant's responses are factual and neutral.
## Available Functions:
- **Reboot Devices**: Allows rebooting specific devices or device groups, with an optional time range for scheduling the reboot.
- Parameters:
- `device_ids` (required): A list of device IDs to reboot.
- `time_range` (optional): Specifies the time range in days, defaulting to 7 days if not provided.
- **Network Q/A**: Handles general Q&A related to networking. This function is the default target for general networking queries.
- **Device Summary**: Retrieves statistics for specific devices within a given time range.
- Parameters:
- `device_ids` (required): A list of device IDs for which statistics will be retrieved.
- `time_range` (optional): Specifies the time range in days for gathering statistics, with a default of 7 days.
# Starting the demo
1. Please make sure the [pre-requisites](https://github.com/katanemo/arch/?tab=readme-ov-file#prerequisites) are installed correctly
2. Start Arch
```sh
sh run_demo.sh
```
3. Navigate to http://localhost:18080/agent/chat
4. Tell me what can you do for me?"
# Observability
Arch gateway publishes stats endpoint at http://localhost:19901/stats. In this demo we are using prometheus to pull stats from arch and we are using grafana to visualize the stats in dashboard. To see grafana dashboard follow instructions below,
1. Start grafana and prometheus using following command
```yaml
docker compose --profile monitoring up
```
1. Navigate to http://localhost:3000/ to open grafana UI (use admin/grafana as credentials)
1. From grafana left nav click on dashboards and select "Intelligent Gateway Overview" to view arch gateway stats
Here is sample interaction
![alt text](image.png)

View file

@ -1,61 +0,0 @@
version: v0.1.0
listeners:
ingress_traffic:
address: 0.0.0.0
port: 10000
message_format: openai
timeout: 30s
# Centralized way to manage LLMs, manage keys, retry logic, failover and limits in a central way
llm_providers:
- access_key: $OPENAI_API_KEY
model: openai/gpt-4o
default: true
# default system prompt used by all prompt targets
system_prompt: |
You are a network assistant that helps operators with a better understanding of network traffic flow and perform actions on networking operations. No advice on manufacturers or purchasing decisions.
prompt_targets:
- name: device_summary
description: Retrieve network statistics for specific devices within a time range
endpoint:
name: app_server
path: /agent/device_summary
http_method: POST
parameters:
- name: device_id
type: str
description: A device identifier to retrieve statistics for.
required: true # device_ids are required to get device statistics
- name: days
type: int
description: The number of days for which to gather device statistics.
default: 7
- name: reboot_device
description: Reboot a device
endpoint:
name: app_server
path: /agent/device_reboot
http_method: POST
parameters:
- name: device_id
type: str
description: the device identifier
required: true
system_prompt: You will get a status JSON object. Simply summarize it
# Arch creates a round-robin load balancing between different endpoints, managed via the cluster subsystem.
endpoints:
app_server:
# value could be ip address or a hostname with port
# this could also be a list of endpoints for load balancing
# for example endpoint: [ ip1:port, ip2:port ]
endpoint: host.docker.internal:18083
# max time to wait for a connection to be established
connect_timeout: 0.005s
tracing:
random_sampling: 100
trace_arch_internal: true

View file

@ -1,28 +0,0 @@
services:
api_server:
build:
context: .
dockerfile: Dockerfile
ports:
- "18083:80"
chatbot_ui:
build:
context: ../../shared/chatbot_ui
dockerfile: Dockerfile
ports:
- "18080:8080"
environment:
- CHAT_COMPLETION_ENDPOINT=http://host.docker.internal:10000/v1
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- ./arch_config.yaml:/app/arch_config.yaml
jaeger:
build:
context: ../../shared/jaeger
ports:
- "16686:16686"
- "4317:4317"
- "4318:4318"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 636 KiB

View file

@ -1,92 +0,0 @@
import os
from typing import List, Optional
from fastapi import FastAPI, HTTPException
from openai import OpenAI
from pydantic import BaseModel, Field
app = FastAPI()
DEMO_DESCRIPTION = """This demo illustrates how **Arch** can be used to perform function calling
with network-related tasks. In this demo, you act as a **network assistant** that provides factual
information, without offering advice on manufacturers or purchasing decisions."""
# Define the request model
class DeviceSummaryRequest(BaseModel):
device_id: str
time_range: Optional[int] = Field(
default=7, description="Time range in days, defaults to 7"
)
# Define the response model
class DeviceStatistics(BaseModel):
device_id: str
time_range: str
data: str
class DeviceSummaryResponse(BaseModel):
statistics: List[DeviceStatistics]
# Request model for device reboot
class DeviceRebootRequest(BaseModel):
device_id: str
# Response model for the device reboot
class CoverageResponse(BaseModel):
status: str
summary: dict
@app.post("/agent/device_reboot", response_model=CoverageResponse)
def reboot_network_device(request_data: DeviceRebootRequest):
"""
Endpoint to reboot network devices based on device IDs and an optional time range.
"""
# Access data from the Pydantic model
device_id = request_data.device_id
# Validate 'device_id'
# (This is already validated by Pydantic, but additional logic can be added if needed)
if not device_id:
raise HTTPException(status_code=400, detail="'device_id' parameter is required")
# Simulate reboot operation and return the response
statistics = []
# Placeholder for actual data retrieval or device reboot logic
stats = {"data": f"Device {device_id} has been successfully rebooted."}
statistics.append(stats)
# Return the response with a summary
return CoverageResponse(status="success", summary={"device_id": device_id})
# Post method for device summary
@app.post("/agent/device_summary", response_model=DeviceSummaryResponse)
def get_device_summary(request: DeviceSummaryRequest):
"""
Endpoint to retrieve device statistics based on device IDs and an optional time range.
"""
# Extract 'device_id' and 'time_range' from the request
device_id = request.device_id
time_range = request.time_range
# Simulate retrieving statistics for the given device IDs and time range
statistics = []
minutes = 4
stats = {
"device_id": device_id,
"time_range": f"Last {time_range} days",
"data": f"""Device {device_id} over the last {time_range} days experienced {minutes}
minutes of downtime.""",
}
statistics.append(DeviceStatistics(**stats))
return DeviceSummaryResponse(statistics=statistics)

View file

@ -1,14 +0,0 @@
fastapi
uvicorn
pydantic
typing
pandas
gradio==5.3.0
huggingface_hub<1.0.0
async_timeout==4.0.3
loguru==0.7.2
asyncio==3.4.3
httpx==0.27.0
python-dotenv==1.0.1
pydantic==2.8.2
openai==1.51.0

View file

@ -1,47 +0,0 @@
#!/bin/bash
set -e
# Function to start the demo
start_demo() {
# Step 1: Check if .env file exists
if [ -f ".env" ]; then
echo ".env file already exists. Skipping creation."
else
# Step 2: Create `.env` file and set OpenAI key
if [ -z "$OPENAI_API_KEY" ]; then
echo "Error: OPENAI_API_KEY environment variable is not set for the demo."
exit 1
fi
echo "Creating .env file..."
echo "OPENAI_API_KEY=$OPENAI_API_KEY" > .env
echo ".env file created with OPENAI_API_KEY."
fi
# Step 3: Start Arch
echo "Starting Arch with arch_config.yaml..."
archgw up arch_config.yaml
# Step 4: Start developer services
echo "Starting Network Agent using Docker Compose..."
docker compose up -d # Run in detached mode
}
# Function to stop the demo
stop_demo() {
# Step 1: Stop Docker Compose services
echo "Stopping Network Agent using Docker Compose..."
docker compose down
# Step 2: Stop Arch
echo "Stopping Arch..."
archgw down
}
# Main script logic
if [ "$1" == "down" ]; then
stop_demo
else
# Default action is to bring the demo up
start_demo
fi

View file

@ -19,12 +19,6 @@ endpoints:
system_prompt: |
You are a helpful assistant.
prompt_guards:
input_guards:
jailbreak:
on_exception:
message: Looks like you're curious about my abilities, but I can only provide assistance for currency exchange.
prompt_targets:
- name: stock_quote
description: get current stock exchange rate for a given symbol

View file

@ -39,12 +39,6 @@ llm_providers:
system_prompt: |
You are a helpful assistant.
prompt_guards:
input_guards:
jailbreak:
on_exception:
message: Looks like you're curious about my abilities, but I can only provide assistance for weather forecasting.
prompt_targets:
- name: get_current_weather
description: Get current weather at a location.