Skip to content

Latest commit

 

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

QueueStorm Investigator — AI Support Copilot

An AI-powered customer support copilot API for mobile financial services (bKash context). Analyzes support tickets using hybrid deterministic rules + LLM reasoning, returns structured JSON decisions with strict safety guarantees.

Team: Dekha Jabe | Event: SUST CSE Carnival 2026 · Codex Hackathon


Quick Start

# Install
npm install

# Set environment variables
cp .env.example .env
# Edit .env with your Gemini API keys

# Run (production)
npm start

# Run (development with auto-reload)
npm run dev

Server starts on port 8000 (override with PORT env var).

Docker

Pull from Docker Hub (recommended)

docker pull menayeem/team-dekha-jabe
docker run -p 8000:8000 --env-file .env menayeem/team-dekha-jabe

Build locally

docker build -t team-dekha-jabe .
docker run -p 8000:8000 --env-file .env team-dekha-jabe

Image size: 69.5MB (node:20-slim, multi-stage build, no dev dependencies).

Verify

curl http://localhost:8000/health
# → {"status":"ok"}

Live Demo

Note: The Render free tier spins down after inactivity. The first request may take ~30 seconds to cold-start.


Environment Variables

Variable Required Description
PORT No Server port (default: 8000)
GEMINI_API_KEY_1 Yes Primary Gemini API key for LLM text generation
GEMINI_API_KEY_2 No Fallback key for rate-limit rotation
GEMINI_API_KEY_3 No Third fallback key

Keys are loaded from environment only — never committed to the repo.


Endpoints

GET /health

Returns instantly with no external dependencies.

{ "status": "ok" }

POST /analyze-ticket

Analyzes a customer support ticket and returns a structured decision.

Sample Request:

{
  "ticket_id": "TKT-001",
  "complaint": "I sent 5000 taka to a wrong number around 2pm today.",
  "language": "en",
  "channel": "in_app_chat",
  "user_type": "customer",
  "transaction_history": [
    {
      "transaction_id": "TXN-9101",
      "timestamp": "2026-04-14T14:08:22Z",
      "type": "transfer",
      "amount": 5000,
      "counterparty": "+8801719876543",
      "status": "completed"
    }
  ]
}

Sample Response:

{
  "ticket_id": "TKT-001",
  "relevant_transaction_id": "TXN-9101",
  "evidence_verdict": "consistent",
  "case_type": "wrong_transfer",
  "severity": "high",
  "department": "dispute_resolution",
  "agent_summary": "Customer reports wrong transfer to +8801719876543.",
  "recommended_next_action": "Route to dispute_resolution team for detailed investigation and reversal assessment.",
  "customer_reply": "We have noted your concern about transaction TXN-9101. Our dispute resolution team will review the case and contact you through official support channels. Please do not share your PIN or OTP with anyone.",
  "human_review_required": true,
  "confidence": 0.9,
  "reason_codes": ["wrong_transfer", "transaction_match"]
}

Tech Stack

  • Runtime: Node.js 20 + Express 5
  • Validation: Zod v4 (lenient input, strict output)
  • LLM: Google Gemini 1.5 Flash (external API)
  • Cache: In-memory (exact-match, SHA-256 keyed, 5-min TTL)
  • Security: Helmet, CORS, 32KB body limit

AI / Model Usage

Architecture: Hybrid deterministic + LLM

The core decision fields (evidence_verdict, case_type, department, severity, human_review_required, relevant_transaction_id) are computed deterministically using rule-based pattern matching and evidence analysis. The LLM is used only for natural language text generation (agent_summary, recommended_next_action, customer_reply).

This means:

  • Decisions are consistent and reproducible regardless of LLM availability
  • Safety is enforced structurally, not by prompting
  • The service remains fully functional if the LLM is down

Models Used

Model Where Why
Gemini 2.5 Flash External API (Google AI Studio) Fast inference, free tier, strong multilingual (EN/BN) support
  • Temperature: 0.3 for summaries/actions, 0.5 for customer replies
  • Multi-key rotation: 2-3 API keys with automatic failover on rate-limit (429)
  • Fallback chain: LLM key 1 → key 2/3 → templated fallback → safe default

Cost Reasoning

  • Free-tier Gemini API with multi-key rotation to stay within quota
  • In-memory cache deduplicates identical requests (cache hit = 0 LLM calls)
  • Deterministic fallback ensures zero LLM cost when API is unavailable
  • All three LLM calls (summary, action, reply) run in parallel to minimize latency

Safety Logic

Three Penalty Rules (deterministic post-filter)

Every generated response passes through a deterministic safety post-filter before leaving the system. The LLM cannot bypass this.

  1. Never request credentials (−15 pts): Scans customer_reply for any request for PIN, OTP, password, CVV, card number — in English, Bangla, and romanized Bangla. Warning the user ("never share your PIN") is allowed; asking is blocked.

  2. Never promise unauthorized actions (−10 pts): Scans both customer_reply and recommended_next_action for refund promises, account unblock confirmations, or guaranteed outcomes. Rewrites to safe language: "any eligible amount will be returned through official channels."

  3. Never direct to suspicious third parties (−10 pts): Scans for unofficial phone numbers, WhatsApp/Telegram/IMO links, and non-official URLs. Replaces with official channel guidance.

If any violation is detected → response is rewritten to a safe template and human_review_required is forced to true.

Safety Pre-Screen (input side)

Before any analysis, the complaint text is scanned for:

  • Credential mentions (PIN, OTP, password — EN/BN)
  • Phishing/social-engineering signals
  • Fraud/scam language
  • Prompt injection attempts ("ignore your rules", "bypass policies")

If flagged → human_review_required is forced to true regardless of LLM output.

Escalation Policy

  • Always escalate: wrong_transfer (with evidence), phishing, duplicate_payment, agent_cash_in_issue, inconsistent evidence
  • Safe to auto-resolve: routine refund requests, merchant settlement delays, payment failures with clear evidence
  • Default: when unsure, escalate (safety > confidence)

Assumptions & Known Limitations

  • Free-tier rate limits: Gemini free tier has RPM limits. Multi-key rotation and caching mitigate this, but under heavy burst the service falls back to templates.
  • Cold start: Free Render instances sleep after inactivity. An external pinger keeps the service warm during judging.
  • Pattern matching: Case classification uses regex patterns for EN and BN. Novel phrasings outside the pattern set fall to other and are handled conservatively.
  • No persistent storage: Cache is in-memory and resets on restart. This is intentional — no stale answers survive a restart.
  • LLM-generated text: When the LLM is available, text fields are richer but still pass through the deterministic safety filter. When unavailable, pre-built templates are used.

Confirmations

  • Synthetic data only: All test data is synthetic. No real customer, financial, or production data is used.
  • No secrets committed: API keys are loaded from environment variables only. .env is in .gitignore.

Project Structure

src/
├── server.js                  # Express entry point
├── routes/                    # Route definitions
├── controllers/               # Request handlers
├── services/                  # Business logic orchestration
├── schemas/                   # Zod input/output validation
├── lib/                       # Core logic modules
│   ├── transaction-matcher.js # Evidence matching (Step 2a)
│   ├── evidence-verdict.js    # Verdict decision (Step 2b)
│   ├── case-classifier.js     # Case classification (Step 2c)
│   ├── routing.js             # Department + severity (Step 2d)
│   ├── escalation.js          # Human review logic (Step 2e)
│   ├── llm-drafting.js        # LLM text generation (Step 2f)
│   ├── safety-pre-screen.js   # Input safety scan
│   ├── safety-post-filter.js  # Output safety filter
│   ├── cache.js               # In-memory cache
│   ├── timing.js              # Time budget tracking
│   └── safe-default.js        # Conservative fallback
├── constants/
│   └── enums.js               # All enum definitions
└── middleware/
    ├── validate.js            # Input validation
    └── error-handler.js       # Global error catch-all

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages