hcm21 / CLAUDE.md
ParetoOptimal's picture
Fix GRPO all-zero rewards: parse JSON actions from completions
1ac70ff
|
Raw
History Blame Contribute Delete
9.1 kB

HR Productivity Environment β€” AgentX-AgentBeats

Overview

A fully-implemented HR simulation environment (OpenEnv-compliant) where an LLM agent serves as Chief Human Capital Officer (CHCO), managing a simulated company over 6 quarters. The agent uses Fitz-enz HR Analytics frameworks to optimize human capital metrics through strategic hiring, training, compensation, and retention decisions.

Repository Structure

/tmp/autoresearch/
β”œβ”€β”€ hr_env/
β”‚   └── server/
β”‚       β”œβ”€β”€ environment.py    # Main simulation loop (OpenEnv Environment)
β”‚       β”œβ”€β”€ company.py        # Company + Department models (Cobb-Douglas production)
β”‚       β”œβ”€β”€ employee.py       # Employee dataclass with lifecycle methods
β”‚       β”œβ”€β”€ metrics.py        # Fitz-enz metrics: HCVA, HCROI, QIPS, Five Indexes
β”‚       β”œβ”€β”€ scoring.py        # Reward computation + final score (normalized [0,1])
β”‚       β”œβ”€β”€ phases.py         # HCM:21 phase management (Scanningβ†’Planningβ†’Producingβ†’Controlling)
β”‚       β”œβ”€β”€ events.py         # Stochastic quarterly events (market, competitor, etc.)
β”‚       β”œβ”€β”€ data_gen.py       # Synthetic company generation (Faker + numpy)
β”‚       └── app.py            # OpenEnv server entrypoint
β”œβ”€β”€ agent/
β”‚   β”œβ”€β”€ hr_agent.py           # Claude-based CHCO agent with phase-aware prompting
β”‚   β”œβ”€β”€ prompts.py            # System prompt, phase prompts, summary prompts
β”‚   └── run.py                # Agent runner script
β”œβ”€β”€ tests/                    # Test suite
β”œβ”€β”€ openenv.yaml              # OpenEnv configuration
β”œβ”€β”€ pyproject.toml             # Python project config (uv)
└── Dockerfile                 # Container build

Development Commands

# Install dependencies
uv sync

# Run tests
uv run pytest tests/ -v

# Start OpenEnv server
uv run python -m hr_env.server.app

# Run agent against server
uv run python -m agent.run

# Docker build
docker build -t hr-productivity-env .

Architecture

Simulation Engine

  • Company Model: 5 departments (Engineering, Sales, Operations, HR, Finance) with Cobb-Douglas production functions
  • Employee Model: 17 tracked attributes including performance, engagement, flight_risk, promotability
  • Revenue: A * headcount^alpha * avg_skill^beta * engagement_mult * market_modifier per department
  • Turnover: Stochastic based on flight_risk (logistic function of pay, engagement, tenure, market)

Fitz-enz Metrics

  • HCVA: (Revenue - Non-Employment Costs) / FTE
  • HCROI: Revenue / Employment Cost
  • QIPS: Quality(0.25) + Innovation(0.25) + Productivity(0.30) + Service(0.20)
  • Five Indexes: Cost, Time, Quantity, Quality, Human Reactions (% change vs prior quarter)
  • Employee Value: avg(Productivity + Promotability + Transferability + Retainability)

HCM:21 Phase System (per quarter)

  1. Scanning (min 2 actions): query_department, query_employees, calculate_metric, review_financials
  2. Planning (min 1): set_hiring_target, set_training_budget, set_compensation_policy, set_retention_program
  3. Producing (min 1): execute_hiring, execute_promotion, execute_transfer, execute_training, execute_termination
  4. Controlling (min 1): submit_report, calculate_metric β†’ then advance_quarter

Scoring

  • Quarterly reward: HCVA improvement (40%) + HCROI (20%) + QIPS (20%) + Five Indexes (20%)
  • Final score [0,1]: HCVA trajectory (25%) + HCROI improvement (20%) + Employee Value (20%) + QIPS consistency (15%) + Five Indexes cumulative (10%) + Financial health (10%)

Stochastic Events

MarketDownturn, CompetitorPoaching, ProductLaunch, ExecDeparture, MinWageIncrease, EmployerAward, BudgetCut, TrainingBreakthrough β€” each with independent probability per quarter, max 2 per quarter.

Databricks Integration

The simulation is adapted into a Databricks notebook (/tmp/AimpointDigital/01_agentic_wikipedia_aimpoint_interview.ipynb) with:

  • Wikipedia knowledge layer: HR theory articles (Fitz-enz, HCM, talent management) indexed into FAISS via BGE-Large embeddings
  • LangGraph orchestration: StateGraph with 5 nodes (initialize β†’ agent_decide β†’ execute_tools β†’ check_done β†’ summarize)
  • RAG bridge: consult_hr_knowledge tool lets the agent ground decisions in Wikipedia-sourced HR theory
  • Databricks LLM: databricks-meta-llama-3-1-8b-instruct for agent reasoning

Key Conventions

  • Pydantic models for OpenEnv; plain dataclasses/dicts for Databricks adaptation
  • Phase-gated action space prevents random action sequences
  • Company generation uses Faker (names) + numpy (distributions) with deterministic seeds
  • Salary distributions: lognormal; tenure: exponential; engagement: beta(7,3)
  • Level distribution: pyramid [0.35, 0.30, 0.20, 0.10, 0.05] for levels 1-5
  • Recruiting cost: $8,000/hire; Benefits: 30% of salary; Training: $50/hr/employee

Databricks Deployment

Workspace

  • URL: https://dbc-c005fe3a-5584.cloud.databricks.com
  • Org ID: 7474655330631867
  • Target Folder ID: 1876640772048528
  • Folder URL: https://dbc-c005fe3a-5584.cloud.databricks.com/browse/folders/1876640772048528?o=7474655330631867
  • PAT: (stored in env / .databrickscfg β€” not committed)
  • User: n8.mauer@gmail.com
  • Edition: Community Edition (Free)
  • LLM endpoint: databricks-meta-llama-3-1-8b-instruct
  • Embedding endpoint: databricks-bge-large-en

.env file (for local development)

DATABRICKS_HOST=https://dbc-c005fe3a-5584.cloud.databricks.com
DATABRICKS_TOKEN=<your-token>
DATABRICKS_ORG_ID=7474655330631867

Cold-Start Setup

  1. pip install databricks-cli
  2. Write ~/.databrickscfg:
    [DEFAULT]
    host = https://dbc-c005fe3a-5584.cloud.databricks.com
    token = <your-token>
    
  3. Deploy notebook:
    databricks workspace import \
      "/tmp/AimpointDigital/01_agentic_wikipedia_aimpoint_interview.ipynb" \
      /Users/n8.mauer@gmail.com/01_agentic_wikipedia_aimpoint_interview \
      --format JUPYTER --language PYTHON --overwrite
    
  4. Open workspace URL β†’ attach cluster β†’ Run All

Deploy Script

./deploy.sh   # from /tmp/AimpointDigital/

Runtime Fixes Applied

  • Rate limiting: agent_decide LLM calls wrapped with backoff.on_exception (exponential, max 8 retries, 120s) + 1.5s proactive delay between calls. Community Edition has low QPS for foundation model endpoints.
  • MLflow tracing: mlflow.langchain.autolog() added at top of Cell A2 to enable tracing and suppress Databricks "Enhance GenAI observability" hint. mlflow-skinny[databricks] already in pip install cell.

GitHub Repo

  • URL: https://github.com/n8mauer/AimpointDigital
  • Contains: notebook, build script, deploy script, README (runbook + talk track), assignment PDF

TRL/GRPO Training (notebooks/hcm21_trl_training.ipynb)

Architecture

  • Model: unsloth/Qwen3-0.6B with LoRA (r=16, 4-bit quantization)
  • Method: GRPO (Group Relative Policy Optimization) via TRL's GRPOTrainer
  • Environment: HCM:21 OpenEnv on HF Spaces (https://paretooptimal-hcm21.hf.space)
  • Colab URL: https://colab.research.google.com/github/n8mauer/autoresearch/blob/main/notebooks/hcm21_trl_training.ipynb

GRPO Reward Strategy (JSON action parsing β€” no environment_factory)

The model generates text completions containing JSON action objects (one per line). reward_func parses these with regex (\{[^{}]*"action_type"[^{}]*\}), executes them in a fresh HCM21Env instance, and returns the environment's final score.

Why not environment_factory?

  • TRL's environment_factory exposes env methods as tools for tool-calling, but a 0.6B model can't reliably generate structured tool calls
  • environment_factory requires transformers>=5.2.0 which conflicts with Unsloth patches
  • Disabling Qwen3 thinking mode via chat_template.replace("enable_thinking", "") may break tool-calling templates
  • Direct JSON parsing in reward_func is simpler, more robust, and works with Unsloth

Key Implementation Details

  • SYSTEM_PROMPT instructs the model to output 20-40 JSON action objects covering 6 quarters
  • reward_func(completions, **kwargs) β€” no environments param (environments created internally)
  • GRPOTrainer has NO environment_factory argument
  • Evaluation (cell 20) generates one completion per seed, parses all actions, executes them
  • tokenizer.apply_chat_template() may return BatchEncoding β€” extract .input_ids before using .shape

Training Config

  • per_device_train_batch_size=2, gradient_accumulation_steps=4, num_generations=4
  • max_completion_length=2048, learning_rate=5e-6, fp16=True
  • Dataset: 20 prompts with different episode seeds

Verification Checklist

After running in Colab, confirm:

  • reward column shows non-zero values
  • reward_std is non-zero (learning signal exists)
  • Training Loss is non-zero (GRPO has gradients)
  • Rewards trend upward over training steps