| |
| """ |
| cli.py β Complaint Auto-Routing System Β· Command Line Interface |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ |
| |
| Usage examples: |
| # Submit a text complaint interactively |
| python app/cli.py |
| |
| # Submit text directly |
| python app/cli.py --text "Pothole on MG Road near hospital. Very dangerous!" |
| |
| # Submit an audio file |
| python app/cli.py --audio /path/to/complaint.mp3 |
| |
| # Submit a video file |
| python app/cli.py --video /path/to/complaint.mp4 |
| |
| # Control number of similar complaints shown |
| python app/cli.py --text "Power outage in Sector 14" --top-k 3 |
| """ |
|
|
| import argparse |
| import json |
| import os |
| import sys |
| import textwrap |
|
|
| sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) |
|
|
| from inference.engine import ComplaintRoutingEngine, SAVE_DIR |
|
|
|
|
| |
| class C: |
| RESET = "\033[0m" |
| BOLD = "\033[1m" |
| RED = "\033[91m" |
| YELLOW = "\033[93m" |
| GREEN = "\033[92m" |
| CYAN = "\033[96m" |
| BLUE = "\033[94m" |
| DIM = "\033[2m" |
|
|
| PRIORITY_COLOUR = {"High": C.RED, "Medium": C.YELLOW, "Low": C.GREEN} |
|
|
|
|
| def print_banner(): |
| print(f""" |
| {C.BOLD}{C.CYAN}ββββββββββββββββββββββββββββββββββββββββββββββββββββ |
| β COMPLAINT AUTO-ROUTING SYSTEM v1.0 β |
| β IVTEX Corporate Solutions Pvt. Ltd. β |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββ{C.RESET} |
| """) |
|
|
|
|
| def format_result(result: dict) -> str: |
| lines = [] |
| sep = "β" * 54 |
|
|
| |
| o = result["officer"] |
| lines.append(f"\n{C.BOLD}{'ASSIGNED OFFICER':β<54}{C.RESET}") |
| lines.append(f" {C.BOLD}Name :{C.RESET} {o['name']}") |
| lines.append(f" {C.BOLD}Department :{C.RESET} {o['department']}") |
| lines.append(f" {C.BOLD}Officer ID :{C.RESET} {o['id']}") |
| lines.append(f" {C.BOLD}Confidence :{C.RESET} {o['confidence']}%") |
|
|
| |
| p = result["priority"] |
| pc = PRIORITY_COLOUR.get(p["level"], C.RESET) |
| lines.append(f"\n{C.BOLD}{'PRIORITY':β<54}{C.RESET}") |
| lines.append(f" {C.BOLD}Level :{C.RESET} {pc}{C.BOLD}{p['level']}{C.RESET}") |
| lines.append(f" {C.BOLD}Confidence :{C.RESET} {p['confidence']}%") |
|
|
| |
| lines.append(f"\n{C.BOLD}{'ESTIMATED RESOLUTION TIME':β<54}{C.RESET}") |
| lines.append(f" {C.BOLD}ETA :{C.RESET} {C.CYAN}{result['eta_days']} day(s){C.RESET}") |
|
|
| |
| sims = result.get("similar_complaints", []) |
| lines.append(f"\n{C.BOLD}{'SIMILAR PAST COMPLAINTS':β<54}{C.RESET}") |
| if not sims: |
| lines.append(" (none found)") |
| for i, s in enumerate(sims, 1): |
| snippet = textwrap.shorten(s["text_snippet"], width=65) |
| lines.append( |
| f" {i}. [{s['complaint_id']}] " |
| f"Score={s['similarity_score']:.3f} " |
| f"{PRIORITY_COLOUR.get(s['priority'], '')}[{s['priority']}]{C.RESET}\n" |
| f" {C.DIM}{snippet}{C.RESET}" |
| ) |
|
|
| if result.get("modality") and result["modality"] != "text": |
| lines.append(f"\n{C.DIM} (Input modality: {result['modality']}){C.RESET}") |
|
|
| return "\n".join(lines) |
|
|
|
|
| def interactive_mode(engine: ComplaintRoutingEngine, top_k: int): |
| print(f"{C.DIM}Type your complaint and press Enter. " |
| f"Type 'quit' to exit.{C.RESET}\n") |
| while True: |
| try: |
| text = input(f"{C.BOLD}Enter complaint:{C.RESET} ").strip() |
| except (EOFError, KeyboardInterrupt): |
| print("\nGoodbye.") |
| break |
| if not text: |
| continue |
| if text.lower() in ("quit", "exit", "q"): |
| print("Goodbye.") |
| break |
| result = engine.predict(text, top_k_similar=top_k) |
| print(format_result(result)) |
| print() |
|
|
|
|
| def main(): |
| parser = argparse.ArgumentParser( |
| description="Complaint Auto-Routing System β CLI", |
| formatter_class=argparse.RawDescriptionHelpFormatter, |
| epilog=__doc__, |
| ) |
| parser.add_argument("--text", type=str, help="Complaint text (inline)") |
| parser.add_argument("--audio", type=str, help="Path to audio file (.wav/.mp3/β¦)") |
| parser.add_argument("--video", type=str, help="Path to video file (.mp4/.mkv/β¦)") |
| parser.add_argument("--top-k", type=int, default=5, |
| help="Number of similar complaints to retrieve (default: 5)") |
| parser.add_argument("--json", action="store_true", |
| help="Output raw JSON instead of formatted display") |
| args = parser.parse_args() |
|
|
| print_banner() |
| engine = ComplaintRoutingEngine().load(SAVE_DIR) |
|
|
| result = None |
|
|
| if args.text: |
| result = engine.process(text=args.text, top_k=args.top_k) |
| elif args.audio: |
| result = engine.process(audio_path=args.audio, top_k=args.top_k) |
| elif args.video: |
| result = engine.process(video_path=args.video, top_k=args.top_k) |
| else: |
| |
| interactive_mode(engine, args.top_k) |
| return |
|
|
| if args.json: |
| print(json.dumps(result, indent=2, ensure_ascii=False)) |
| else: |
| if result.get("modality") != "text": |
| print(f"{C.DIM}Transcription: {result.get('source_text', '')[:200]}β¦{C.RESET}\n") |
| print(format_result(result)) |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|