Skip to content

Latest commit

 

History

History
210 lines (177 loc) · 6.61 KB

File metadata and controls

210 lines (177 loc) · 6.61 KB

ACSA — Architecture Reference

System Overview

User
 │
 │  WebSocket (ws://localhost:8000/ws/chat)
 ▼
Intent Classifier
 │ confidence score (0.0 – 1.0)
 ├──── > 0.7 ────────────────────────────┐
 │                                       ▼
 │                              Autonomous ReAct Agent
 │                                       │
 │                            ┌──────────┼──────────┐
 │                            ▼          ▼          ▼
 │                        KB Search  Order Status  Ticket Creator
 │                        (ChromaDB) (Mock API)    (Redis)
 │                            │
 │                            ▼
 │                      Confidence Checker (Critic)
 │                            │
 │                 ┌──────────┴──────────┐
 │                 │ PASS                │ ESCALATE
 │                 ▼                    ▼
 │           Response → User      Human Handoff Queue (Redis)
 │                                      │
 └──── < 0.7 ──────────────────────────┘
                                        ▼
                               Human Agent Dashboard

Agent Graph Nodes (LangGraph)

Node File Responsibility
classifier agents/classifier.py LLM call → topic + confidence float
react_agent agents/react_agent.py ReAct loop, calls tools iteratively
critic agents/critic.py Scores draft response → PASS / ESCALATE
escalator agents/escalator.py Packages full context for human queue
responder agents/responder.py Sends final answer over WebSocket
graph agents/graph.py LangGraph compiled graph, all edges

Agent State (TypedDict)

class AgentState(TypedDict):
    session_id: str
    user_message: str
    chat_history: Annotated[list, operator.add]
    topic: str
    confidence: float
    tool_calls_made: Annotated[list, operator.add]
    draft_response: str
    critic_score: float
    escalated: bool
    final_response: str

Tools

Tool File What it does
kb_search tools/kb_search.py Semantic search over FAQ in ChromaDB
order_status tools/order_status.py Returns mock order data from JSON
ticket_creator tools/ticket_creator.py Creates ticket dict, stores in Redis

Data Flow: Happy Path (autonomous resolution)

  1. User sends message over WebSocket
  2. classifier calls Groq → returns {topic: "refund", confidence: 0.87}
  3. Confidence > 0.7 → routed to react_agent
  4. react_agent runs ReAct loop:
    • Thought: "I need to check the refund policy"
    • Action: kb_search("refund policy")
    • Observation: returns top 3 FAQ chunks
    • Thought: "I have enough context to answer"
    • Final answer generated
  5. critic scores the draft → returns 0.82 (PASS threshold: 0.6)
  6. responder sends answer to user over WebSocket
  7. Metrics updated in Redis (resolution_count++)

Data Flow: Escalation Path

Triggered when:

  • classifier confidence < 0.7 (unclear intent), OR
  • critic score < 0.6 (low quality draft after ReAct)

Escalation payload sent to Redis human queue:

{
  "session_id": "abc123",
  "user_message": "My order is messed up and I want compensation",
  "chat_history": [...],
  "topic": "complaint",
  "confidence": 0.45,
  "tool_calls_made": ["kb_search", "order_status"],
  "draft_response": "...",
  "critic_score": 0.38,
  "escalated_at": "2025-01-01T10:00:00Z",
  "escalation_reason": "low_critic_score"
}

Tech Stack

Layer Technology Why
LLM Groq llama-3.3-70b-versatile Free tier, fast (200+ tok/s), no daily limit
Embeddings sentence-transformers (local) No API key, free, runs on CPU
Vector DB ChromaDB (local) No Docker, pip install, persistent
Session store Redis (local) Human queue + session state
Agent framework LangGraph Same as EADA, familiar
Backend FastAPI + WebSocket Production-grade, async
Frontend React + TypeScript Phase 4 only
Package manager uv Same as EADA
CI GitHub Actions ruff lint + pytest

Directory Structure

support-agent/
├── backend/
│   ├── agents/
│   │   ├── __init__.py
│   │   ├── state.py          ← AgentState TypedDict
│   │   ├── classifier.py     ← intent + confidence
│   │   ├── react_agent.py    ← ReAct loop
│   │   ├── critic.py         ← quality scorer
│   │   ├── escalator.py      ← human handoff
│   │   ├── responder.py      ← sends to user
│   │   └── graph.py          ← compiled LangGraph
│   ├── tools/
│   │   ├── __init__.py
│   │   ├── kb_search.py
│   │   ├── order_status.py
│   │   └── ticket_creator.py
│   ├── api/
│   │   ├── __init__.py
│   │   ├── websocket.py      ← ws/chat endpoint
│   │   └── metrics.py        ← GET /metrics
│   ├── db/
│   │   ├── __init__.py
│   │   ├── chroma.py         ← ChromaDB client + helpers
│   │   └── redis_client.py   ← Redis client + helpers
│   ├── config.py             ← Pydantic Settings
│   └── main.py               ← FastAPI app
├── frontend/                 ← Phase 4
├── data/
│   ├── sample_faq.json       ← seeded into ChromaDB on startup
│   └── mock_orders.json      ← used by order_status tool
├── tests/
│   └── unit/
├── scripts/
│   └── ingest_faq.py         ← one-time KB ingestion script
├── PROGRESS.md
├── ARCHITECTURE.md
├── pyproject.toml
├── .env.example
└── .gitignore

Configuration (.env)

# LLM
GROQ_API_KEY=your_groq_key_here

# Redis
REDIS_URL=redis://localhost:6379

# ChromaDB
CHROMA_PERSIST_PATH=./chroma_db

# Agent tuning
CONFIDENCE_THRESHOLD=0.7
CRITIC_PASS_THRESHOLD=0.6
MAX_REACT_ITERATIONS=5

# App
APP_ENV=development
LOG_LEVEL=INFO

Evaluation Metrics (Phase 4 Dashboard)

Metric How calculated
Resolution rate resolved / total_sessions * 100
Escalation rate escalated / total_sessions * 100
Avg latency Mean time from message received to response sent
Top topics Count by topic field from classifier
Critic score distribution Histogram of critic scores