mirror of
https://github.com/katanemo/plano.git
synced 2026-06-17 15:25:17 +02:00
committing to merge with main
This commit is contained in:
parent
d799fc98fd
commit
aa21f41d0b
6 changed files with 111 additions and 53 deletions
|
|
@ -5,6 +5,7 @@ FROM base AS builder
|
|||
WORKDIR /src
|
||||
|
||||
COPY requirements.txt /src/
|
||||
COPY workforce_data.json /src/
|
||||
RUN pip install --prefix=/runtime --force-reinstall -r requirements.txt
|
||||
|
||||
COPY . /src
|
||||
|
|
|
|||
|
|
@ -27,11 +27,17 @@ system_prompt: |
|
|||
You are a HR agent assistant that helps HR decision makers with reporting and workfoce planning. Nothing else. Please stay on topic of HR.
|
||||
|
||||
prompt_targets:
|
||||
- name: headcount
|
||||
description: Get headcount data for a region by staffing type
|
||||
- name: hr_qa
|
||||
endpoint:
|
||||
name: app_server
|
||||
path: /agent/headcount
|
||||
path: /agent/hr_qa
|
||||
description: Handle general Q/A related to HR.
|
||||
default: true
|
||||
- name: workforce
|
||||
description: Get workforce data like headcount and satisfacton levels by region and staffing type
|
||||
endpoint:
|
||||
name: app_server
|
||||
path: /agent/workforce
|
||||
parameters:
|
||||
- name: staffing_type
|
||||
type: str
|
||||
|
|
@ -40,10 +46,18 @@ prompt_targets:
|
|||
- name: region
|
||||
type: str
|
||||
required: true
|
||||
description: the geographical region for which you want headcount data.
|
||||
- name: hr_qa
|
||||
description: the geographical region for which you want workforce data.
|
||||
- name: point_in_time
|
||||
type: int
|
||||
required: false
|
||||
description: a point in time for which to retrieve data. For e.g 0 days ago, 30 days ago, etc.
|
||||
- name: slack_message
|
||||
endpoint:
|
||||
name: app_server
|
||||
path: /agent/hr_qa
|
||||
description: Handle general Q/A related to HR.
|
||||
default: true
|
||||
path: /agent/slack_message
|
||||
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
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ services:
|
|||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
environment:
|
||||
- SLACK_BOT_TOKEN=${SLACK_BOT_TOKEN:?error}
|
||||
ports:
|
||||
- "18083:80"
|
||||
healthcheck:
|
||||
|
|
|
|||
|
|
@ -1,72 +1,82 @@
|
|||
import os
|
||||
import json
|
||||
import pandas as pd
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import List, Optional
|
||||
from typing import Optional
|
||||
from enum import Enum
|
||||
import re
|
||||
from slack_sdk import WebClient
|
||||
from slack_sdk.errors import SlackApiError
|
||||
|
||||
app = FastAPI()
|
||||
workforce_data_df = None
|
||||
|
||||
|
||||
class StaffingType(Enum):
|
||||
FTE = "fte"
|
||||
AGENCY = "agency"
|
||||
CONTRACT = "contract"
|
||||
|
||||
|
||||
class RegionType(Enum):
|
||||
ASIA = "asia"
|
||||
EUROPE = "europe"
|
||||
AMERICAS = "americas"
|
||||
with open("workforce_data.json") as file:
|
||||
workforce_data = json.load(file)
|
||||
workforce_data_df = pd.json_normalize(
|
||||
workforce_data, record_path=["regions"], meta=["point_in_time", "satisfaction"]
|
||||
)
|
||||
|
||||
|
||||
# Define the request model
|
||||
class HeadcountRequest(BaseModel):
|
||||
region: RegionType
|
||||
staffing_type: StaffingType
|
||||
|
||||
|
||||
class HeadcountResponseSummary(BaseModel):
|
||||
class WorkforceRequset(BaseModel):
|
||||
region: str
|
||||
headcount: int
|
||||
staffing_type: str
|
||||
point_in_time: Optional[int] = None
|
||||
|
||||
|
||||
HEADCOUNT = {
|
||||
RegionType.ASIA: {
|
||||
StaffingType.CONTRACT: 100,
|
||||
StaffingType.FTE: 150,
|
||||
StaffingType.AGENCY: 2000,
|
||||
},
|
||||
RegionType.EUROPE: {
|
||||
StaffingType.CONTRACT: 80,
|
||||
StaffingType.FTE: 120,
|
||||
StaffingType.AGENCY: 2500,
|
||||
},
|
||||
RegionType.AMERICAS: {
|
||||
StaffingType.CONTRACT: 90,
|
||||
StaffingType.FTE: 200,
|
||||
StaffingType.AGENCY: 3000,
|
||||
},
|
||||
}
|
||||
class SlackRequest(BaseModel):
|
||||
slack_message: str
|
||||
|
||||
|
||||
class WorkforceResponse(BaseModel):
|
||||
region: str
|
||||
staffing_type: str
|
||||
headcount: int
|
||||
satisfaction: float
|
||||
|
||||
|
||||
# Post method for device summary
|
||||
@app.post("/agent/headcount")
|
||||
def get_headcount(request: HeadcountRequest):
|
||||
@app.post("/agent/workforce")
|
||||
def get_workforce(request: WorkforceRequset):
|
||||
"""
|
||||
Endpoint to headcount data by region, staffing type over time range
|
||||
Endpoint to workforce data by region, staffing type at a given point in time.
|
||||
"""
|
||||
headcount = HEADCOUNT[request.region][request.staffing_type]
|
||||
region = request.region.lower()
|
||||
staffing_type = request.staffing_type.lower()
|
||||
point_in_time = request.point_in_time if request.point_in_time else 0
|
||||
|
||||
response = {
|
||||
"region": request.region.value,
|
||||
"staffing_type": f"Staffing agency: {request.staffing_type}",
|
||||
"headcount": f"Headcount: {headcount}",
|
||||
"region": region,
|
||||
"staffing_type": f"Staffing agency: {staffing_type}",
|
||||
"headcount": f"Headcount: {int(workforce_data_df[(workforce_data_df['region']==region) & (workforce_data_df['point_in_time']==point_in_time)][staffing_type].values[0])}",
|
||||
"satisfaction": f"Satisifaction: {float(workforce_data_df[(workforce_data_df['region']==region) & (workforce_data_df['point_in_time']==point_in_time)][satisfaction].values[0])}",
|
||||
}
|
||||
|
||||
return response
|
||||
|
||||
|
||||
@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'
|
||||
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']}")
|
||||
|
||||
|
||||
@app.post("/agent/hr_qa")
|
||||
async def general_hr_qa():
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
fastapi
|
||||
uvicorn
|
||||
pydantic
|
||||
slack-sdk
|
||||
typing
|
||||
pandas
|
||||
|
|
|
|||
29
demos/hr_agent/workforce_data.json
Normal file
29
demos/hr_agent/workforce_data.json
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
[
|
||||
{
|
||||
"point_in_time": 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
|
||||
},
|
||||
{
|
||||
"point_in_time": 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
|
||||
},
|
||||
{
|
||||
"point_in_time": 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
|
||||
}
|
||||
]
|
||||
Loading…
Add table
Add a link
Reference in a new issue