Rohit Patil commited on
Commit Β·
753201e
0
Parent(s):
RingGuard Phase 3 - initial HF Spaces deploy
Browse filesGraph-based fraud ring detection for Razorpay merchants.
FastAPI dashboard serving precomputed detection results.
Stack: Python 3.11, FastAPI, LightGBM, LangGraph, NetworkX, Groq, Razorpay SDK
- .env.example +4 -0
- .gitignore +16 -0
- Dockerfile +29 -0
- LICENSE +21 -0
- README.md +320 -0
- agent/.gitkeep +1 -0
- agent/graph.py +265 -0
- agent/investigator.py +264 -0
- agent/policy.py +65 -0
- agent/run_demo.py +121 -0
- api/.gitkeep +1 -0
- api/main.py +357 -0
- audit/.gitkeep +1 -0
- audit/audit_log.jsonl +28 -0
- audit/generate_audit_log.py +87 -0
- audit/logger.py +162 -0
- data/augment_demo_dataset.py +272 -0
- data/generate_synthetic_data.py +661 -0
- data/synthetic/.gitkeep +1 -0
- data/synthetic/addresses.json +1430 -0
- data/synthetic/candidate_clusters.json +784 -0
- data/synthetic/cases_demo.json +1027 -0
- data/synthetic/customers.json +0 -0
- data/synthetic/devices.json +1622 -0
- data/synthetic/ground_truth.json +165 -0
- data/synthetic/orders.json +0 -0
- data/synthetic/payment_instruments.json +1932 -0
- data/synthetic/scored_clusters.json +812 -0
- eval/.gitkeep +1 -0
- eval/eval_results.json +24 -0
- eval/evaluate.py +153 -0
- graph/.gitkeep +1 -0
- graph/build_graph.py +299 -0
- graph/detect_communities.py +466 -0
- integration/.gitkeep +1 -0
- integration/razorpay_actions.py +310 -0
- requirements.txt +62 -0
- scoring/.gitkeep +1 -0
- scoring/features.py +293 -0
- scoring/holdout_split.json +464 -0
- scoring/model.lgb +2054 -0
- scoring/score_demo.py +81 -0
- scoring/train_model.py +156 -0
.env.example
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Not required for Phase 1. Needed starting Phase 2/3.
|
| 2 |
+
GROQ_API_KEY=
|
| 3 |
+
RAZORPAY_KEY_ID=
|
| 4 |
+
RAZORPAY_KEY_SECRET=
|
.gitignore
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
ο»Ώvenv/
|
| 2 |
+
__pycache__/
|
| 3 |
+
*.pyc
|
| 4 |
+
.env
|
| 5 |
+
.DS_Store
|
| 6 |
+
data/synthetic/graph.gpickle
|
| 7 |
+
data/synthetic_train/graph.gpickle
|
| 8 |
+
|
| 9 |
+
# Phase execution plans and summaries - keep local only, not in public repo
|
| 10 |
+
phase-1-execution-plan.md
|
| 11 |
+
phase-2-execution-plan.md
|
| 12 |
+
phase-3-execution-plan.md
|
| 13 |
+
phase1_summary.md
|
| 14 |
+
phase2_summary.md
|
| 15 |
+
phase3_summary.md
|
| 16 |
+
data/synthetic_train/
|
Dockerfile
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.11-slim
|
| 2 |
+
|
| 3 |
+
# Phase 3 deployment β RingGuard FastAPI dashboard
|
| 4 |
+
# Razorpay actions are precomputed and baked into cases_demo.json / audit_log.jsonl.
|
| 5 |
+
# The deployed container only DISPLAYS these precomputed results; it does NOT
|
| 6 |
+
# re-execute Razorpay calls or LLM calls on page load (per Phase 3 Section 6.2).
|
| 7 |
+
|
| 8 |
+
WORKDIR /app
|
| 9 |
+
|
| 10 |
+
# Install dependencies
|
| 11 |
+
COPY requirements.txt .
|
| 12 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
| 13 |
+
|
| 14 |
+
# Copy source code and precomputed results
|
| 15 |
+
COPY agent/ agent/
|
| 16 |
+
COPY api/ api/
|
| 17 |
+
COPY audit/ audit/
|
| 18 |
+
COPY data/ data/
|
| 19 |
+
COPY graph/ graph/
|
| 20 |
+
COPY integration/ integration/
|
| 21 |
+
COPY scoring/ scoring/
|
| 22 |
+
COPY eval/ eval/
|
| 23 |
+
|
| 24 |
+
# HuggingFace Spaces expects port 7860
|
| 25 |
+
ENV PORT=7860
|
| 26 |
+
EXPOSE 7860
|
| 27 |
+
|
| 28 |
+
# Start the FastAPI dashboard
|
| 29 |
+
CMD ["uvicorn", "api.main:app", "--host", "0.0.0.0", "--port", "7860"]
|
LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2026 Rohit Patil
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
+
in the Software without restriction, including without limitation the rights
|
| 8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
+
furnished to do so, subject to the following conditions:
|
| 11 |
+
|
| 12 |
+
The above copyright notice and this permission notice shall be included in all
|
| 13 |
+
copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 21 |
+
SOFTWARE.
|
README.md
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
ο»Ώ---
|
| 2 |
+
title: RingGuard
|
| 3 |
+
colorFrom: red
|
| 4 |
+
colorTo: orange
|
| 5 |
+
sdk: docker
|
| 6 |
+
pinned: true
|
| 7 |
+
license: mit
|
| 8 |
+
short_description: Graph-based fraud ring detection for Razorpay merchants
|
| 9 |
+
---
|
| 10 |
+
# RingGuard
|
| 11 |
+
|
| 12 |
+
    
|
| 13 |
+
|
| 14 |
+
**Coordinated fraud detection for Razorpay merchants Γ’β¬β finding the rings per-order scoring can't see.**
|
| 15 |
+
|
| 16 |
+
RingGuard analyzes a merchant's own order and account data to detect coordinated abuse Γ’β¬β accounts secretly linked by shared devices, addresses, or payment instruments, working together to exploit returns, promo codes, or chargebacks. Instead of scoring one order at a time, it builds a graph of the merchant's entire transaction history, finds the structure a per-order model is blind to, and hands a human reviewer an explainable case file instead of a black-box flag. Built for Track 02 Γ’β¬β AI Risk Manager.
|
| 17 |
+
|
| 18 |
+
---
|
| 19 |
+
|
| 20 |
+
## Table of Contents
|
| 21 |
+
|
| 22 |
+
1. [The Problem](#the-problem)
|
| 23 |
+
2. [The Solution](#the-solution)
|
| 24 |
+
3. [Why This, Not Thirdwatch](#why-this-not-thirdwatch)
|
| 25 |
+
4. [How It Works](#how-it-works)
|
| 26 |
+
5. [AI Judgment Γ’β¬β Where Each Tool Is Used](#ai-judgment--where-each-tool-is-used)
|
| 27 |
+
6. [System Architecture](#system-architecture)
|
| 28 |
+
7. [Tech Stack](#tech-stack)
|
| 29 |
+
8. [Repository Structure](#repository-structure)
|
| 30 |
+
9. [Getting Started](#getting-started)
|
| 31 |
+
10. [Usage](#usage)
|
| 32 |
+
11. [Evaluation & Metrics](#evaluation--metrics)
|
| 33 |
+
12. [Known Limitations](#known-limitations)
|
| 34 |
+
13. [Policy & Safety Boundaries](#policy--safety-boundaries)
|
| 35 |
+
14. [Audit Trail](#audit-trail)
|
| 36 |
+
15. [Roadmap](#roadmap)
|
| 37 |
+
16. [Demo](#demo)
|
| 38 |
+
17. [Acknowledgments](#acknowledgments)
|
| 39 |
+
18. [License](#license)
|
| 40 |
+
|
| 41 |
+
---
|
| 42 |
+
|
| 43 |
+
## The Problem
|
| 44 |
+
|
| 45 |
+
Cash-on-delivery return-to-origin rates in Indian e-commerce run as high as 30Γ’β¬β40%, and coordinated abuse Γ’β¬β not isolated bad actors Γ’β¬β is a meaningful share of that loss. Fraud rings deliberately spread activity across multiple "different" accounts specifically so that any system scoring one order at a time sees N separate low-risk transactions instead of one high-risk network. Per-order risk engines, however sophisticated, are structurally blind to this by design Γ’β¬β they were never built to look across accounts.
|
| 46 |
+
|
| 47 |
+
## The Solution
|
| 48 |
+
|
| 49 |
+
RingGuard is a defensive, AI-assisted investigation agent that:
|
| 50 |
+
|
| 51 |
+
- **Ingests** a merchant's order, customer, device, address, and payment data (Razorpay test-mode-shaped).
|
| 52 |
+
- **Builds a graph** connecting accounts through shared devices, payment instruments, addresses, and contact details.
|
| 53 |
+
- **Detects communities** in that graph Γ’β¬β clusters of accounts more connected to each other than chance would suggest.
|
| 54 |
+
- **Scores each cluster** with a trained model, not hand-tuned rules, using graph structure and behavioral features.
|
| 55 |
+
- **Explains the finding** in plain language via an LLM that reads only the structured evidence it's given Γ’β¬β never free-reasoning, never inventing facts.
|
| 56 |
+
- **Recommends a bounded action** Γ’β¬β flag, hold, or escalate Γ’β¬β gated by deterministic policy rules, with a human always in the loop for anything above the auto-hold threshold.
|
| 57 |
+
|
| 58 |
+
It never bans an account or seizes funds. It flags, it explains, and it waits for a human on anything that matters.
|
| 59 |
+
|
| 60 |
+
## Why This, Not Thirdwatch
|
| 61 |
+
|
| 62 |
+
Razorpay has owned Thirdwatch since 2019 Γ’β¬β a mature fraud/RTO engine scoring individual orders on roughly 300 device and behavioral signals. Razorpay's Agent Studio also ships a Dispute Responder Agent (chargeback evidence) and a Subscription Recovery Agent. None of these look *across* orders and accounts for structure Γ’β¬β they operate at the level of one order or one case at a time.
|
| 63 |
+
|
| 64 |
+
RingGuard is not a better per-order scorer. It's a different problem shape: network-level detection of coordinated behavior that is invisible when you only ever look at one order at a time. That's the entire differentiation argument, and it's intentional that it's stated here, first, rather than left for a judge to have to ask about.
|
| 65 |
+
|
| 66 |
+
## How It Works
|
| 67 |
+
|
| 68 |
+
```
|
| 69 |
+
Synthetic order/account stream (Razorpay Orders/Payments-shaped)
|
| 70 |
+
Γ’ββ
|
| 71 |
+
Γ’βΒΌ
|
| 72 |
+
Entity resolution Γ’β¬β normalize phone/email/address, hash device + payment fields
|
| 73 |
+
Γ’ββ
|
| 74 |
+
Γ’βΒΌ
|
| 75 |
+
Graph construction Γ’β¬β Customer / Device / Address / PaymentInstrument nodes
|
| 76 |
+
Γ’ββ
|
| 77 |
+
Γ’βΒΌ
|
| 78 |
+
Community detection Γ’β¬β connected components + Louvain (deterministic, seed=42)
|
| 79 |
+
Γ’ββ
|
| 80 |
+
Γ’βΒΌ
|
| 81 |
+
Feature extraction Γ’β¬β cluster size, strong/weak link ratio, order velocity,
|
| 82 |
+
return rate, promo usage, Γ’βΒΉ exposure (13 features)
|
| 83 |
+
Γ’ββ
|
| 84 |
+
Γ’βΒΌ
|
| 85 |
+
LightGBM risk model Γ’β¬β single learned probability, no hand-blended scoring
|
| 86 |
+
Γ’ββ
|
| 87 |
+
Γ’βΒΌ
|
| 88 |
+
Policy gate (deterministic, v3.0)
|
| 89 |
+
Γ’βΕΓ’ββ¬Γ’ββ¬ risk Γ’β°Β₯ 0.85 and exposure Γ’β°Β€ Γ’βΒΉ25,000 Γ’β β bounded auto-hold (test mode, Razorpay API)
|
| 90 |
+
Γ’βΕΓ’ββ¬Γ’ββ¬ risk Γ’β°Β₯ 0.85 and exposure > Γ’βΒΉ25,000 Γ’β β escalate, no auto-action
|
| 91 |
+
Γ’βΕΓ’ββ¬Γ’ββ¬ 0.5 Γ’β°Β€ risk < 0.85 Γ’β β escalate to human review queue
|
| 92 |
+
Γ’ββΓ’ββ¬Γ’ββ¬ risk < 0.5 Γ’β β log only
|
| 93 |
+
Γ’ββ
|
| 94 |
+
Γ’βΒΌ
|
| 95 |
+
Investigator agent (LangGraph + Groq LLM) Γ’β¬β evidence bundle in, case narrative out
|
| 96 |
+
Γ’ββ
|
| 97 |
+
Γ’βΒΌ
|
| 98 |
+
Razorpay test-mode action (order.create + order.edit notes)
|
| 99 |
+
Γ’ββ
|
| 100 |
+
Γ’βΒΌ
|
| 101 |
+
Audit logger Γ’β¬β every stage, every decision, timestamped (audit_log.jsonl)
|
| 102 |
+
```
|
| 103 |
+
|
| 104 |
+
A cluster built entirely from **weak links** (e.g., three accounts sharing only an address Γ’β¬β plausible for a family household) is designed to score low. Distinguishing that from a **strong-link** cluster (shared device fingerprint or payment instrument) is what keeps false positives down, and it's built into the feature set from day one, not patched in afterward.
|
| 105 |
+
|
| 106 |
+
## AI Judgment Γ’β¬β Where Each Tool Is Used
|
| 107 |
+
|
| 108 |
+
| Stage | Tool | Why this tool, not another |
|
| 109 |
+
|---|---|---|
|
| 110 |
+
| Graph construction, edge rules, policy gate | Deterministic code | Money-adjacent decisions need to be boring and auditable Γ’β¬β no model judgment here |
|
| 111 |
+
| Community detection, clustering | Classical graph algorithms (Louvain, connected components) | Structural pattern detection, not a language problem |
|
| 112 |
+
| Ring risk scoring | LightGBM (supervised, tabular) | Faster, cheaper, and more auditable than an LLM for a numeric classification task |
|
| 113 |
+
| Case narrative + human-readable explanation | LLM (Groq Γ’β¬β `openai/gpt-oss-120b`) | The one place synthesizing evidence into something a reviewer can act on quickly genuinely benefits from language generation |
|
| 114 |
+
| Final action | Deterministic policy gate, human-approved above threshold | The LLM never has authority to move money or take action on its own |
|
| 115 |
+
|
| 116 |
+
## System Architecture
|
| 117 |
+
|
| 118 |
+
```mermaid
|
| 119 |
+
flowchart TD
|
| 120 |
+
A[Synthetic Order Stream] --> B[Entity Resolution]
|
| 121 |
+
B --> C[Graph Construction - NetworkX]
|
| 122 |
+
C --> D[Community Detection - Louvain]
|
| 123 |
+
D --> E[Feature Extraction]
|
| 124 |
+
E --> F[LightGBM Risk Model]
|
| 125 |
+
F --> G{Policy Gate}
|
| 126 |
+
G -->|risk >= 0.85, exposure <= 25k| H[Auto-Hold via Razorpay API]
|
| 127 |
+
G -->|risk >= 0.85, exposure > 25k| I[Escalate - Human Review]
|
| 128 |
+
G -->|0.5 <= risk < 0.85| I
|
| 129 |
+
G -->|risk < 0.5| J[Log Only]
|
| 130 |
+
H --> K[Investigator Agent - Groq LLM]
|
| 131 |
+
I --> K
|
| 132 |
+
K --> L[Case Narrative + Confidence]
|
| 133 |
+
L --> M[Audit Log + Dashboard]
|
| 134 |
+
J --> M
|
| 135 |
+
```
|
| 136 |
+
|
| 137 |
+
## Tech Stack
|
| 138 |
+
|
| 139 |
+
| Layer | Choice |
|
| 140 |
+
|---|---|
|
| 141 |
+
| Language / API | Python 3.11, FastAPI |
|
| 142 |
+
| Graph | NetworkX + python-louvain |
|
| 143 |
+
| Scoring | LightGBM |
|
| 144 |
+
| Agent orchestration | LangGraph |
|
| 145 |
+
| LLM | Groq (`openai/gpt-oss-120b`, plain chat completion Γ’β¬β no tools) |
|
| 146 |
+
| Razorpay integration | Official Razorpay Python SDK v2.0.1 (test-mode API calls verified) |
|
| 147 |
+
| Synthetic data | Faker |
|
| 148 |
+
| Dashboard | HTML served by FastAPI |
|
| 149 |
+
| Deployment | HuggingFace Spaces (Docker) |
|
| 150 |
+
|
| 151 |
+
No paid dependencies anywhere in this stack.
|
| 152 |
+
|
| 153 |
+
## Repository Structure
|
| 154 |
+
|
| 155 |
+
```
|
| 156 |
+
ringguard/
|
| 157 |
+
Γ’βΕΓ’ββ¬Γ’ββ¬ README.md
|
| 158 |
+
Γ’βΕΓ’ββ¬Γ’ββ¬ requirements.txt
|
| 159 |
+
Γ’βΕΓ’ββ¬Γ’ββ¬ .env.example
|
| 160 |
+
Γ’βΕΓ’ββ¬Γ’ββ¬ Dockerfile
|
| 161 |
+
Γ’βΕΓ’ββ¬Γ’ββ¬ data/
|
| 162 |
+
Γ’ββ Γ’βΕΓ’ββ¬Γ’ββ¬ generate_synthetic_data.py
|
| 163 |
+
Γ’ββ Γ’βΕΓ’ββ¬Γ’ββ¬ augment_demo_dataset.py Γ’β Β Phase 3: adds RING11 + BOUNDARY01
|
| 164 |
+
Γ’ββ Γ’ββΓ’ββ¬Γ’ββ¬ synthetic/
|
| 165 |
+
Γ’ββ Γ’βΕΓ’ββ¬Γ’ββ¬ cases_demo.json Γ’β Β 28 cases with Razorpay action_taken
|
| 166 |
+
Γ’ββ Γ’ββΓ’ββ¬Γ’ββ¬ ...
|
| 167 |
+
Γ’βΕΓ’ββ¬Γ’ββ¬ graph/
|
| 168 |
+
Γ’ββ Γ’βΕΓ’ββ¬Γ’ββ¬ build_graph.py
|
| 169 |
+
Γ’ββ Γ’ββΓ’ββ¬Γ’ββ¬ detect_communities.py
|
| 170 |
+
Γ’βΕΓ’ββ¬Γ’ββ¬ scoring/
|
| 171 |
+
Γ’ββ Γ’βΕΓ’ββ¬Γ’ββ¬ features.py
|
| 172 |
+
Γ’ββ Γ’βΕΓ’ββ¬Γ’ββ¬ train_model.py
|
| 173 |
+
Γ’ββ Γ’βΕΓ’ββ¬Γ’ββ¬ score_demo.py
|
| 174 |
+
Γ’ββ Γ’ββΓ’ββ¬Γ’ββ¬ model.lgb
|
| 175 |
+
Γ’βΕΓ’ββ¬Γ’ββ¬ agent/
|
| 176 |
+
Γ’ββ Γ’βΕΓ’ββ¬Γ’ββ¬ graph.py
|
| 177 |
+
Γ’ββ Γ’βΕΓ’ββ¬Γ’ββ¬ investigator.py
|
| 178 |
+
Γ’ββ Γ’βΕΓ’ββ¬Γ’ββ¬ policy.py
|
| 179 |
+
Γ’ββ Γ’ββΓ’ββ¬Γ’ββ¬ run_demo.py
|
| 180 |
+
Γ’βΕΓ’ββ¬Γ’ββ¬ integration/
|
| 181 |
+
Γ’ββ Γ’ββΓ’ββ¬Γ’ββ¬ razorpay_actions.py Γ’β Β Phase 3: real test-mode Razorpay calls
|
| 182 |
+
Γ’βΕΓ’ββ¬Γ’ββ¬ api/
|
| 183 |
+
Γ’ββ Γ’ββΓ’ββ¬Γ’ββ¬ main.py Γ’β Β Phase 3: FastAPI dashboard
|
| 184 |
+
Γ’βΕΓ’ββ¬Γ’ββ¬ eval/
|
| 185 |
+
Γ’ββ Γ’ββΓ’ββ¬Γ’ββ¬ evaluate.py
|
| 186 |
+
Γ’ββΓ’ββ¬Γ’ββ¬ audit/
|
| 187 |
+
Γ’βΕΓ’ββ¬Γ’ββ¬ logger.py Γ’β Β Phase 3: append-only audit log
|
| 188 |
+
Γ’βΕΓ’ββ¬Γ’ββ¬ generate_audit_log.py
|
| 189 |
+
Γ’ββΓ’ββ¬Γ’ββ¬ audit_log.jsonl
|
| 190 |
+
```
|
| 191 |
+
|
| 192 |
+
## Getting Started
|
| 193 |
+
|
| 194 |
+
### Prerequisites
|
| 195 |
+
|
| 196 |
+
- Python 3.11+
|
| 197 |
+
- A free [Groq API key](https://console.groq.com)
|
| 198 |
+
- Razorpay test-mode API keys (`rzp_test_...`) from the [Razorpay Dashboard](https://dashboard.razorpay.com)
|
| 199 |
+
|
| 200 |
+
### Installation
|
| 201 |
+
|
| 202 |
+
```bash
|
| 203 |
+
git clone https://github.com/rohitdecodes/ringguard.git
|
| 204 |
+
cd ringguard
|
| 205 |
+
python -m venv venv
|
| 206 |
+
source venv/bin/activate # Windows: venv\Scripts\activate
|
| 207 |
+
pip install -r requirements.txt
|
| 208 |
+
cp .env.example .env # then fill in GROQ_API_KEY, RAZORPAY_KEY_ID, RAZORPAY_KEY_SECRET
|
| 209 |
+
```
|
| 210 |
+
|
| 211 |
+
## Usage
|
| 212 |
+
|
| 213 |
+
```bash
|
| 214 |
+
# 1. (One-time) Augment the demo dataset with RING11 + BOUNDARY01
|
| 215 |
+
python data/augment_demo_dataset.py
|
| 216 |
+
|
| 217 |
+
# 2. Build the graph and detect candidate clusters
|
| 218 |
+
python graph/build_graph.py --data-dir data/synthetic
|
| 219 |
+
python graph/detect_communities.py --data-dir data/synthetic
|
| 220 |
+
|
| 221 |
+
# 3. Score clusters and run the LangGraph agent
|
| 222 |
+
python scoring/score_demo.py
|
| 223 |
+
python agent/run_demo.py
|
| 224 |
+
|
| 225 |
+
# 4. Execute Razorpay test-mode actions
|
| 226 |
+
python integration/razorpay_actions.py
|
| 227 |
+
|
| 228 |
+
# 5. Generate the audit log
|
| 229 |
+
python audit/generate_audit_log.py
|
| 230 |
+
|
| 231 |
+
# 6. Launch the dashboard
|
| 232 |
+
uvicorn api.main:app --reload --port 7860
|
| 233 |
+
# open http://localhost:7860
|
| 234 |
+
```
|
| 235 |
+
|
| 236 |
+
## Evaluation & Metrics
|
| 237 |
+
|
| 238 |
+
Measured on a held-out split at the **cluster level** (no ring's accounts appear in both train and test). Fixed seed=42, stratified 80/20 split.
|
| 239 |
+
|
| 240 |
+
| Metric | Value |
|
| 241 |
+
|---|---|
|
| 242 |
+
| **Precision** (ring detection) | **1.0000** |
|
| 243 |
+
| **Recall** (ring detection) | **1.0000** |
|
| 244 |
+
| **F1** | **1.0000** |
|
| 245 |
+
| False-positive cost (Γ’βΒΉ, held orders wrongly flagged) | **Γ’βΒΉ0.00** |
|
| 246 |
+
| End-to-end latency (feature extraction + inference) | **0.043 ms/cluster** |
|
| 247 |
+
|
| 248 |
+
Holdout: 22 clusters (12 positive fraud rings, 10 negative benign clusters).
|
| 249 |
+
|
| 250 |
+
### Policy action breakdown on held-out set
|
| 251 |
+
| Action | Count |
|
| 252 |
+
|---|---|
|
| 253 |
+
| auto_hold | 0 |
|
| 254 |
+
| escalate | 12 |
|
| 255 |
+
| log_only | 10 |
|
| 256 |
+
|
| 257 |
+
### Demo dataset (28 clusters, post Phase 3 augmentation)
|
| 258 |
+
| Action | Count |
|
| 259 |
+
|---|---|
|
| 260 |
+
| auto_hold | 1 (RING11) |
|
| 261 |
+
| escalate | 10 |
|
| 262 |
+
| log_only | 17 (includes BOUNDARY01) |
|
| 263 |
+
|
| 264 |
+
## Known Limitations
|
| 265 |
+
|
| 266 |
+
**Read this before evaluating the precision/recall numbers above.**
|
| 267 |
+
|
| 268 |
+
The current P=R=F1=1.0 figures reflect that the synthetic training data does not yet contain genuinely ambiguous or partially-ring-like examples. The model has not been tested on a hard case Γ’β¬β one where real human experts would disagree. Specifically:
|
| 269 |
+
|
| 270 |
+
1. **Training distribution boundary:** The Phase 2 model uses `avg_order_amount` as its strongest feature (importance=145 vs. 120 for chargeback_rate). Positive training examples have `avg_order_amount Γ’β°Β₯ Γ’βΒΉ3,249`; all negatives are below Γ’βΒΉ3,171. This creates a near-hard threshold. Real rings could fall on either side of it.
|
| 271 |
+
|
| 272 |
+
2. **Auto-hold threshold calibration (Phase 3 change):** The original Γ’βΒΉ5,000 auto-hold exposure cap is mathematically incompatible with the training distribution Γ’β¬β a 3-member ring with just enough orders to form strong links (2 per customer Γβ Γ’βΒΉ3,300 each) totals Γ’β°ΛΓ’βΒΉ19,800. The threshold was updated to Γ’βΒΉ25,000 in Phase 3 (v3.0). This is a legitimate calibration, but it means the original threshold was never validated against real data either.
|
| 273 |
+
|
| 274 |
+
3. **Razorpay MCP server not available:** The `@razorpay/mcp-server` npm package returns 404 on the npm registry. Razorpay actions were executed via the official Python SDK (`razorpay==2.0.1`), which calls the same REST API. All calls are real, test-mode, and verified Γ’β¬β but the MCP-specific tooling described in the original plan is not available.
|
| 275 |
+
|
| 276 |
+
4. **Synthetic data only:** All evaluation is against Faker-generated data. Real merchants have messier entity resolution challenges, more diverse ring structures, and ambiguous cases the current training data cannot represent. Real-world P/R/F1 should be expected to be significantly lower.
|
| 277 |
+
|
| 278 |
+
5. **`BOUNDARY01` detection behavior:** This deliberately ambiguous cluster (3 accounts sharing one address, no chargebacks, low return rate) scored `risk=0.0035` and was correctly routed to `log_only` Γ’β¬β not `auto_hold`. The model correctly declined to flag it. However, this isn't a hard-won result from a genuinely difficult case; it's the model doing nothing to an input that looks entirely unlike its training positives.
|
| 279 |
+
|
| 280 |
+
Real-world performance validation requires labeled production data. The current metrics are a correctness proof-of-concept, not a deployment readiness certificate.
|
| 281 |
+
|
| 282 |
+
## Policy & Safety Boundaries
|
| 283 |
+
|
| 284 |
+
RingGuard is **defense-only**, per Track 02's rules:
|
| 285 |
+
|
| 286 |
+
- It can flag, hold, and escalate. It cannot ban, seize funds, or take any irreversible action.
|
| 287 |
+
- Auto-hold only fires below Γ’βΒΉ25,000 total cluster exposure (Phase 3 v3.0 calibration) and only at high confidence (risk Γ’β°Β₯ 0.85).
|
| 288 |
+
- Anything above that threshold, or in the mid-confidence band, goes to a human review queue Γ’β¬β never auto-actioned.
|
| 289 |
+
- The LLM has no authority to trigger an action. It explains a decision the policy gate already made.
|
| 290 |
+
- The LLM (`openai/gpt-oss-120b`) is called as a plain chat completion with no `tools` parameter Γ’β¬β it has no web-search or code-execution access. It only knows what's in the evidence bundle.
|
| 291 |
+
|
| 292 |
+
## Audit Trail
|
| 293 |
+
|
| 294 |
+
Every case logs: `case_id, timestamp, cluster_members, evidence_bundle, graph_score_inputs, lightgbm_probability, llm_narrative, llm_confidence_statement, policy_decision, action_taken, human_reviewer (if escalated), outcome, reason_if_not_auto_actioned`.
|
| 295 |
+
|
| 296 |
+
Available as `audit/audit_log.jsonl` (one JSON object per line, append-only). Every case in `cases_demo.json` has a matching audit entry, including log_only cases. The dashboard at `GET /cases/{case_id}/detail` shows the full audit chain for each case.
|
| 297 |
+
|
| 298 |
+
## Roadmap
|
| 299 |
+
|
| 300 |
+
Building in three phases. Detailed, task-level execution plans for each phase Γ’β¬β written for agentic AI coding execution Γ’β¬β are maintained separately.
|
| 301 |
+
|
| 302 |
+
- Γ’Εβ¦ **Phase 1 Γ’β¬β Detection Core:** synthetic data generation, entity resolution, graph construction, community detection. Output: a working, deterministic pipeline that turns raw order data into flagged candidate clusters.
|
| 303 |
+
- Γ’Εβ¦ **Phase 2 Γ’β¬β Intelligence Layer:** feature extraction, LightGBM risk model, held-out evaluation, LangGraph agent orchestration, Investigator LLM node, policy gate. Output: scored, explained, policy-gated cases.
|
| 304 |
+
- Γ’Εβ¦ **Phase 3 Γ’β¬β Integration & Submission:** dataset augmentation (RING11 + BOUNDARY01), model swap (`openai/gpt-oss-120b`), Razorpay test-mode integration, audit trail, FastAPI dashboard, deployment, final evaluation, demo, submission.
|
| 305 |
+
|
| 306 |
+
## Demo
|
| 307 |
+
|
| 308 |
+
*Live deployment: HuggingFace Spaces Γ’β¬β see phase3_summary.md for URL.*
|
| 309 |
+
|
| 310 |
+
*Pitch video: to be recorded.*
|
| 311 |
+
|
| 312 |
+
## Acknowledgments
|
| 313 |
+
|
| 314 |
+
Built with [LangGraph](https://langchain-ai.github.io/langgraph/), [Groq](https://groq.com) (`openai/gpt-oss-120b`), [LightGBM](https://lightgbm.readthedocs.io/), [NetworkX](https://networkx.org/), and the [Razorpay Python SDK](https://github.com/razorpay/razorpay-python).
|
| 315 |
+
|
| 316 |
+
## License
|
| 317 |
+
|
| 318 |
+
MIT Γ’β¬β see [LICENSE](LICENSE).
|
| 319 |
+
|
| 320 |
+
|
agent/.gitkeep
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
|
agent/graph.py
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
graph.py
|
| 3 |
+
--------
|
| 4 |
+
LangGraph orchestration for RingGuard fraud investigation.
|
| 5 |
+
|
| 6 |
+
State: RingGuardState
|
| 7 |
+
cluster β the candidate cluster record
|
| 8 |
+
features β extracted feature dict
|
| 9 |
+
risk_probability β model score
|
| 10 |
+
policy_decision β "auto_hold" | "escalate" | "log_only"
|
| 11 |
+
llm_narrative β LLM explanation (None if log_only or if GROQ unavailable)
|
| 12 |
+
llm_confidence β LLM confidence statement (None if log_only)
|
| 13 |
+
|
| 14 |
+
Flow:
|
| 15 |
+
score_node β policy_node β [conditional] investigator_node β END
|
| 16 |
+
(investigator_node is SKIPPED for log_only decisions)
|
| 17 |
+
|
| 18 |
+
Usage:
|
| 19 |
+
from agent.graph import build_graph, run_cluster
|
| 20 |
+
results = run_cluster(cluster, features, risk_probability)
|
| 21 |
+
"""
|
| 22 |
+
|
| 23 |
+
import os
|
| 24 |
+
import sys
|
| 25 |
+
from typing import Optional, TypedDict
|
| 26 |
+
|
| 27 |
+
from langgraph.graph import StateGraph, END
|
| 28 |
+
|
| 29 |
+
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 30 |
+
sys.path.insert(0, BASE_DIR)
|
| 31 |
+
|
| 32 |
+
from agent.policy import decide as policy_decide
|
| 33 |
+
from agent.investigator import investigate
|
| 34 |
+
|
| 35 |
+
# Audit logger β imported lazily to keep graph.py usable without audit module
|
| 36 |
+
_AUDIT_ENABLED = True
|
| 37 |
+
try:
|
| 38 |
+
from audit.logger import log_case as _log_case
|
| 39 |
+
except ImportError:
|
| 40 |
+
_AUDIT_ENABLED = False
|
| 41 |
+
_log_case = None
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
# ---------------------------------------------------------------------------
|
| 45 |
+
# State definition
|
| 46 |
+
# ---------------------------------------------------------------------------
|
| 47 |
+
|
| 48 |
+
class RingGuardState(TypedDict):
|
| 49 |
+
cluster: dict
|
| 50 |
+
features: dict
|
| 51 |
+
risk_probability: float
|
| 52 |
+
policy_decision: Optional[str]
|
| 53 |
+
llm_narrative: Optional[str]
|
| 54 |
+
llm_confidence: Optional[str]
|
| 55 |
+
grounding_ok: Optional[bool]
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
# ---------------------------------------------------------------------------
|
| 59 |
+
# Nodes
|
| 60 |
+
# ---------------------------------------------------------------------------
|
| 61 |
+
|
| 62 |
+
def score_node(state: RingGuardState) -> RingGuardState:
|
| 63 |
+
"""
|
| 64 |
+
Score node: wraps the already-computed risk_probability from the model.
|
| 65 |
+
The probability was computed externally (by scoring/score_demo.py or live
|
| 66 |
+
inference) and passed in via state β this node simply forwards it.
|
| 67 |
+
"""
|
| 68 |
+
# risk_probability is already set in state by the caller
|
| 69 |
+
return state
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
def policy_node(state: RingGuardState) -> RingGuardState:
|
| 73 |
+
"""
|
| 74 |
+
Policy gate: deterministic decision based on risk_probability + exposure.
|
| 75 |
+
Exposure = total_amount from features (Phase 3 will use real Razorpay data).
|
| 76 |
+
"""
|
| 77 |
+
risk_prob = state["risk_probability"]
|
| 78 |
+
exposure = state["features"].get("total_amount", 0.0)
|
| 79 |
+
decision = policy_decide(risk_prob, exposure)
|
| 80 |
+
|
| 81 |
+
return {**state, "policy_decision": decision}
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
def investigator_node(state: RingGuardState) -> RingGuardState:
|
| 85 |
+
"""
|
| 86 |
+
LLM investigator: generates a narrative for high-risk clusters.
|
| 87 |
+
Only called when policy_decision is 'auto_hold' or 'escalate'.
|
| 88 |
+
Catches errors so a single LLM failure does not abort the whole pipeline.
|
| 89 |
+
"""
|
| 90 |
+
try:
|
| 91 |
+
result = investigate(
|
| 92 |
+
cluster=state["cluster"],
|
| 93 |
+
features=state["features"],
|
| 94 |
+
risk_probability=state["risk_probability"],
|
| 95 |
+
policy_decision=state["policy_decision"],
|
| 96 |
+
)
|
| 97 |
+
return {
|
| 98 |
+
**state,
|
| 99 |
+
"llm_narrative": result["narrative"],
|
| 100 |
+
"llm_confidence": result["confidence_statement"],
|
| 101 |
+
"grounding_ok": result["grounding_ok"],
|
| 102 |
+
}
|
| 103 |
+
except Exception as e:
|
| 104 |
+
return {
|
| 105 |
+
**state,
|
| 106 |
+
"llm_narrative": f"[LLM_ERROR] {e}",
|
| 107 |
+
"llm_confidence": None,
|
| 108 |
+
"grounding_ok": None,
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
# ---------------------------------------------------------------------------
|
| 113 |
+
# Conditional routing
|
| 114 |
+
# ---------------------------------------------------------------------------
|
| 115 |
+
|
| 116 |
+
def should_investigate(state: RingGuardState) -> str:
|
| 117 |
+
"""
|
| 118 |
+
Route to investigator only for auto_hold or escalate decisions.
|
| 119 |
+
Skip for log_only β no reason to spend an LLM call on it.
|
| 120 |
+
"""
|
| 121 |
+
if state.get("policy_decision") in ("auto_hold", "escalate"):
|
| 122 |
+
return "investigate"
|
| 123 |
+
return "skip"
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
# ---------------------------------------------------------------------------
|
| 127 |
+
# Graph construction
|
| 128 |
+
# ---------------------------------------------------------------------------
|
| 129 |
+
|
| 130 |
+
def build_graph():
|
| 131 |
+
"""Build and compile the RingGuard LangGraph state machine."""
|
| 132 |
+
builder = StateGraph(RingGuardState)
|
| 133 |
+
|
| 134 |
+
builder.add_node("score_node", score_node)
|
| 135 |
+
builder.add_node("policy_node", policy_node)
|
| 136 |
+
builder.add_node("investigator_node", investigator_node)
|
| 137 |
+
|
| 138 |
+
builder.set_entry_point("score_node")
|
| 139 |
+
|
| 140 |
+
builder.add_edge("score_node", "policy_node")
|
| 141 |
+
|
| 142 |
+
builder.add_conditional_edges(
|
| 143 |
+
"policy_node",
|
| 144 |
+
should_investigate,
|
| 145 |
+
{
|
| 146 |
+
"investigate": "investigator_node",
|
| 147 |
+
"skip": END,
|
| 148 |
+
},
|
| 149 |
+
)
|
| 150 |
+
|
| 151 |
+
builder.add_edge("investigator_node", END)
|
| 152 |
+
|
| 153 |
+
return builder.compile()
|
| 154 |
+
|
| 155 |
+
|
| 156 |
+
# ---------------------------------------------------------------------------
|
| 157 |
+
# Convenience runner
|
| 158 |
+
# ---------------------------------------------------------------------------
|
| 159 |
+
|
| 160 |
+
def run_cluster(
|
| 161 |
+
cluster: dict,
|
| 162 |
+
features: dict,
|
| 163 |
+
risk_probability: float,
|
| 164 |
+
case_id: str = None,
|
| 165 |
+
action_taken: dict = None,
|
| 166 |
+
) -> dict:
|
| 167 |
+
"""
|
| 168 |
+
Run the full pipeline for a single cluster.
|
| 169 |
+
|
| 170 |
+
Returns final state dict with policy_decision, llm_narrative, etc.
|
| 171 |
+
Catches LLM errors and records them in llm_narrative rather than crashing.
|
| 172 |
+
|
| 173 |
+
Parameters
|
| 174 |
+
----------
|
| 175 |
+
cluster : candidate cluster record
|
| 176 |
+
features : extracted feature dict
|
| 177 |
+
risk_probability : model score
|
| 178 |
+
case_id : optional case ID for audit logging (e.g. "CASE08")
|
| 179 |
+
action_taken : optional Razorpay action dict (populated by Section 3)
|
| 180 |
+
"""
|
| 181 |
+
graph = build_graph()
|
| 182 |
+
|
| 183 |
+
initial_state: RingGuardState = {
|
| 184 |
+
"cluster": cluster,
|
| 185 |
+
"features": features,
|
| 186 |
+
"risk_probability": risk_probability,
|
| 187 |
+
"policy_decision": None,
|
| 188 |
+
"llm_narrative": None,
|
| 189 |
+
"llm_confidence": None,
|
| 190 |
+
"grounding_ok": None,
|
| 191 |
+
}
|
| 192 |
+
|
| 193 |
+
try:
|
| 194 |
+
final_state = graph.invoke(initial_state)
|
| 195 |
+
except RuntimeError as e:
|
| 196 |
+
# LLM failures (missing key, parse errors) are caught here.
|
| 197 |
+
# The policy decision was already set before the LLM call.
|
| 198 |
+
# We log the error rather than crashing the whole pipeline.
|
| 199 |
+
final_state = {
|
| 200 |
+
**initial_state,
|
| 201 |
+
"policy_decision": policy_decide(risk_probability, features.get("total_amount", 0.0)),
|
| 202 |
+
"llm_narrative": f"[LLM_ERROR] {e}",
|
| 203 |
+
"llm_confidence": None,
|
| 204 |
+
"grounding_ok": None,
|
| 205 |
+
}
|
| 206 |
+
|
| 207 |
+
result = dict(final_state)
|
| 208 |
+
|
| 209 |
+
# Phase 3 Section 4.2 β write audit log entry for every run
|
| 210 |
+
if _AUDIT_ENABLED and _log_case is not None:
|
| 211 |
+
try:
|
| 212 |
+
from datetime import datetime, timezone
|
| 213 |
+
audit_case = {
|
| 214 |
+
"case_id": case_id or cluster.get("cluster_id", "?"),
|
| 215 |
+
"cluster_id": cluster.get("cluster_id"),
|
| 216 |
+
"customer_ids": cluster.get("customer_ids", []),
|
| 217 |
+
"risk_probability": risk_probability,
|
| 218 |
+
"policy_decision": result.get("policy_decision"),
|
| 219 |
+
"llm_narrative": result.get("llm_narrative"),
|
| 220 |
+
"llm_confidence_statement": result.get("llm_confidence"),
|
| 221 |
+
"action_taken": action_taken,
|
| 222 |
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
| 223 |
+
}
|
| 224 |
+
_log_case(audit_case, features)
|
| 225 |
+
except Exception:
|
| 226 |
+
pass # never crash the pipeline due to audit errors
|
| 227 |
+
|
| 228 |
+
return result
|
| 229 |
+
|
| 230 |
+
|
| 231 |
+
# ---------------------------------------------------------------------------
|
| 232 |
+
# CLI test β run on a single demo cluster
|
| 233 |
+
# ---------------------------------------------------------------------------
|
| 234 |
+
|
| 235 |
+
if __name__ == "__main__":
|
| 236 |
+
import json
|
| 237 |
+
|
| 238 |
+
demo_dir = os.path.join(BASE_DIR, "data", "synthetic")
|
| 239 |
+
scored_path = os.path.join(demo_dir, "scored_clusters.json")
|
| 240 |
+
orders_path = os.path.join(demo_dir, "orders.json")
|
| 241 |
+
graph_path = os.path.join(demo_dir, "graph.gpickle")
|
| 242 |
+
|
| 243 |
+
with open(scored_path) as f:
|
| 244 |
+
scored = json.load(f)
|
| 245 |
+
|
| 246 |
+
with open(orders_path) as f:
|
| 247 |
+
orders = json.load(f)
|
| 248 |
+
|
| 249 |
+
from scoring.features import extract_features, _load_graph
|
| 250 |
+
graph_obj = _load_graph(graph_path) if os.path.exists(graph_path) else None
|
| 251 |
+
|
| 252 |
+
# Use the first high-risk cluster as a test
|
| 253 |
+
test_cluster = scored[0]
|
| 254 |
+
features = extract_features(test_cluster, orders, graph=graph_obj)
|
| 255 |
+
risk_prob = test_cluster["risk_probability"]
|
| 256 |
+
|
| 257 |
+
print(f"Testing graph on {test_cluster['cluster_id']} "
|
| 258 |
+
f"(risk={risk_prob:.4f})...")
|
| 259 |
+
|
| 260 |
+
result = run_cluster(test_cluster, features, risk_prob)
|
| 261 |
+
|
| 262 |
+
print(f" Policy decision : {result['policy_decision']}")
|
| 263 |
+
print(f" LLM narrative : {result['llm_narrative']}")
|
| 264 |
+
print(f" LLM confidence : {result['llm_confidence']}")
|
| 265 |
+
print(f" Grounding OK : {result['grounding_ok']}")
|
agent/investigator.py
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
investigator.py
|
| 3 |
+
---------------
|
| 4 |
+
LLM investigator node for RingGuard.
|
| 5 |
+
|
| 6 |
+
Calls Groq (llama-3.3-70b-versatile) to generate a short narrative explaining
|
| 7 |
+
why a cluster was flagged. Only called for auto_hold and escalate decisions
|
| 8 |
+
(not log_only β no reason to spend an LLM call on something nobody will review).
|
| 9 |
+
|
| 10 |
+
Requires GROQ_API_KEY in environment (from .env).
|
| 11 |
+
If GROQ_API_KEY is not set, raises RuntimeError rather than silently continuing.
|
| 12 |
+
|
| 13 |
+
Anti-hallucination boundary:
|
| 14 |
+
- The LLM only sees the evidence bundle (aggregated features), never raw
|
| 15 |
+
order-level or PII data.
|
| 16 |
+
- System prompt instructs the model to ONLY reference facts present in the
|
| 17 |
+
evidence bundle.
|
| 18 |
+
- Any customer ID mentioned in the narrative must be a member of the bundle's
|
| 19 |
+
customer_ids list (checked by run_grounding_check).
|
| 20 |
+
- Output validated against InvestigatorOutput Pydantic schema; retried once
|
| 21 |
+
with stricter reminder if parse fails.
|
| 22 |
+
|
| 23 |
+
Usage:
|
| 24 |
+
from agent.investigator import investigate, run_grounding_check
|
| 25 |
+
result = investigate(cluster, features, risk_probability, policy_decision)
|
| 26 |
+
is_clean = run_grounding_check(result["narrative"], cluster["customer_ids"])
|
| 27 |
+
"""
|
| 28 |
+
|
| 29 |
+
import json
|
| 30 |
+
import os
|
| 31 |
+
import re
|
| 32 |
+
import sys
|
| 33 |
+
|
| 34 |
+
from dotenv import load_dotenv
|
| 35 |
+
from pydantic import BaseModel, ValidationError
|
| 36 |
+
|
| 37 |
+
load_dotenv()
|
| 38 |
+
|
| 39 |
+
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 40 |
+
sys.path.insert(0, BASE_DIR)
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
# ---------------------------------------------------------------------------
|
| 44 |
+
# Output schema
|
| 45 |
+
# ---------------------------------------------------------------------------
|
| 46 |
+
|
| 47 |
+
class InvestigatorOutput(BaseModel):
|
| 48 |
+
narrative: str
|
| 49 |
+
confidence_statement: str
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
# ---------------------------------------------------------------------------
|
| 53 |
+
# Evidence bundle builder
|
| 54 |
+
# ---------------------------------------------------------------------------
|
| 55 |
+
|
| 56 |
+
def build_evidence_bundle(
|
| 57 |
+
cluster: dict,
|
| 58 |
+
features: dict,
|
| 59 |
+
risk_probability: float,
|
| 60 |
+
policy_decision: str,
|
| 61 |
+
) -> dict:
|
| 62 |
+
"""
|
| 63 |
+
Build the evidence bundle passed to the LLM.
|
| 64 |
+
Contains only the aggregated facts listed in spec 10.3 β no raw PII.
|
| 65 |
+
"""
|
| 66 |
+
return {
|
| 67 |
+
"customer_ids": cluster["customer_ids"],
|
| 68 |
+
"size": cluster["size"],
|
| 69 |
+
"strong_link_count": cluster["strong_link_count"],
|
| 70 |
+
"weak_link_count": cluster["weak_link_count"],
|
| 71 |
+
"formation_type": cluster.get("formation_type", "unknown"),
|
| 72 |
+
"return_rate": features.get("return_rate", 0.0),
|
| 73 |
+
"chargeback_rate": features.get("chargeback_rate", 0.0),
|
| 74 |
+
"shared_coupon_count": features.get("shared_coupon_count", 0),
|
| 75 |
+
"total_amount": features.get("total_amount", 0.0),
|
| 76 |
+
"risk_probability": risk_probability,
|
| 77 |
+
"policy_decision": policy_decision,
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
# ---------------------------------------------------------------------------
|
| 82 |
+
# System prompt
|
| 83 |
+
# ---------------------------------------------------------------------------
|
| 84 |
+
|
| 85 |
+
SYSTEM_PROMPT = """You are a fraud analyst assistant for RingGuard, a fraud detection system.
|
| 86 |
+
|
| 87 |
+
You will receive a JSON evidence bundle describing a cluster of customers flagged as high-risk.
|
| 88 |
+
|
| 89 |
+
Your task is to write a short fraud narrative and a confidence statement.
|
| 90 |
+
|
| 91 |
+
STRICT RULES β violating any of these makes your response unusable:
|
| 92 |
+
1. ONLY reference facts that are explicitly present in the evidence bundle.
|
| 93 |
+
2. Do NOT invent customer names, order details, locations, or any fact not in the bundle.
|
| 94 |
+
3. Do NOT mention any customer_id that is not in the bundle's customer_ids list.
|
| 95 |
+
4. Do NOT recommend an action β the policy gate has already decided that.
|
| 96 |
+
5. Do NOT speculate beyond what the evidence shows.
|
| 97 |
+
6. Keep the narrative to 2-4 sentences. Keep the confidence statement to 1 sentence.
|
| 98 |
+
|
| 99 |
+
Respond with ONLY a valid JSON object in this exact format (no markdown, no preamble):
|
| 100 |
+
{"narrative": "...", "confidence_statement": "..."}"""
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
# ---------------------------------------------------------------------------
|
| 104 |
+
# Main investigate function
|
| 105 |
+
# ---------------------------------------------------------------------------
|
| 106 |
+
|
| 107 |
+
def _call_groq(evidence_bundle: dict, retry_strict: bool = False) -> str:
|
| 108 |
+
"""
|
| 109 |
+
Call Groq API and return the raw response text. Retries on rate limits.
|
| 110 |
+
|
| 111 |
+
Phase 3 model selection:
|
| 112 |
+
- groq/compound-mini was used in Phase 2 as an interim substitute.
|
| 113 |
+
- Phase 3 plan requires replacing it with a plain, non-agentic model.
|
| 114 |
+
- Available models checked at execution time: openai/gpt-oss-120b (works,
|
| 115 |
+
returns valid JSON directly), qwen/qwen3.6-27b (uses extended thinking,
|
| 116 |
+
requires higher token budget to clear <think> block before JSON).
|
| 117 |
+
- Selected: openai/gpt-oss-120b β standard chat completion, no tool calls,
|
| 118 |
+
deterministic JSON output, sufficient token budget at 500 tokens.
|
| 119 |
+
- No `tools` parameter is passed anywhere in this function (hard requirement
|
| 120 |
+
from Phase 3 plan Section 2.2).
|
| 121 |
+
"""
|
| 122 |
+
import time
|
| 123 |
+
from groq import Groq, RateLimitError
|
| 124 |
+
|
| 125 |
+
api_key = os.environ.get("GROQ_API_KEY", "")
|
| 126 |
+
if not api_key:
|
| 127 |
+
raise RuntimeError(
|
| 128 |
+
"GROQ_API_KEY is not set in environment. "
|
| 129 |
+
"Add it to .env and reload before running the investigator."
|
| 130 |
+
)
|
| 131 |
+
|
| 132 |
+
client = Groq(api_key=api_key)
|
| 133 |
+
|
| 134 |
+
user_message = json.dumps(evidence_bundle, indent=2)
|
| 135 |
+
if retry_strict:
|
| 136 |
+
user_message += (
|
| 137 |
+
"\n\nIMPORTANT: Your previous response did not parse as valid JSON. "
|
| 138 |
+
"Respond ONLY with a JSON object: "
|
| 139 |
+
'{"narrative": "...", "confidence_statement": "..."} β no other text.'
|
| 140 |
+
)
|
| 141 |
+
|
| 142 |
+
# Phase 3: openai/gpt-oss-120b β plain chat completion, no tools parameter.
|
| 143 |
+
# Configurable via GROQ_MODEL env var for future model swaps.
|
| 144 |
+
# groq/compound-mini (Phase 2 default) is not an acceptable substitute here β
|
| 145 |
+
# it is an agentic model with tool/web-search access, violating Plan Section 2.2.
|
| 146 |
+
model_name = os.environ.get("GROQ_MODEL", "openai/gpt-oss-120b")
|
| 147 |
+
|
| 148 |
+
for attempt in range(3):
|
| 149 |
+
try:
|
| 150 |
+
response = client.chat.completions.create(
|
| 151 |
+
model=model_name,
|
| 152 |
+
messages=[
|
| 153 |
+
{"role": "system", "content": SYSTEM_PROMPT},
|
| 154 |
+
{"role": "user", "content": user_message},
|
| 155 |
+
],
|
| 156 |
+
temperature=0.1, # low temperature for deterministic output
|
| 157 |
+
max_tokens=500, # no `tools` parameter β plain chat completion
|
| 158 |
+
)
|
| 159 |
+
return response.choices[0].message.content.strip()
|
| 160 |
+
except RateLimitError as e:
|
| 161 |
+
if attempt < 2:
|
| 162 |
+
wait = 30 * (attempt + 1)
|
| 163 |
+
print(f"\n [rate_limit] waiting {wait}s before retry {attempt+2}/3...")
|
| 164 |
+
time.sleep(wait)
|
| 165 |
+
else:
|
| 166 |
+
raise
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
def _parse_response(raw: str) -> InvestigatorOutput:
|
| 170 |
+
"""Parse and validate the LLM response against InvestigatorOutput schema."""
|
| 171 |
+
# Strip any accidental markdown fencing
|
| 172 |
+
raw = raw.strip()
|
| 173 |
+
if raw.startswith("```"):
|
| 174 |
+
raw = re.sub(r"^```[a-z]*\n?", "", raw)
|
| 175 |
+
raw = re.sub(r"\n?```$", "", raw)
|
| 176 |
+
raw = raw.strip()
|
| 177 |
+
|
| 178 |
+
data = json.loads(raw)
|
| 179 |
+
return InvestigatorOutput(**data)
|
| 180 |
+
|
| 181 |
+
|
| 182 |
+
def investigate(
|
| 183 |
+
cluster: dict,
|
| 184 |
+
features: dict,
|
| 185 |
+
risk_probability: float,
|
| 186 |
+
policy_decision: str,
|
| 187 |
+
) -> dict:
|
| 188 |
+
"""
|
| 189 |
+
Call the LLM investigator for a flagged cluster.
|
| 190 |
+
|
| 191 |
+
Parameters
|
| 192 |
+
----------
|
| 193 |
+
cluster : dict
|
| 194 |
+
Candidate cluster record (from candidate_clusters.json or scored_clusters.json).
|
| 195 |
+
features : dict
|
| 196 |
+
Feature dict for this cluster (from scoring/features.py).
|
| 197 |
+
risk_probability : float
|
| 198 |
+
Risk probability from the model.
|
| 199 |
+
policy_decision : str
|
| 200 |
+
Policy decision (must be "auto_hold" or "escalate" β callers should not
|
| 201 |
+
call this for "log_only" decisions).
|
| 202 |
+
|
| 203 |
+
Returns
|
| 204 |
+
-------
|
| 205 |
+
dict with keys: narrative, confidence_statement, grounding_ok, raw_response
|
| 206 |
+
"""
|
| 207 |
+
evidence = build_evidence_bundle(cluster, features, risk_probability, policy_decision)
|
| 208 |
+
|
| 209 |
+
# First attempt
|
| 210 |
+
raw = _call_groq(evidence)
|
| 211 |
+
parse_error = None
|
| 212 |
+
output = None
|
| 213 |
+
|
| 214 |
+
try:
|
| 215 |
+
output = _parse_response(raw)
|
| 216 |
+
except (json.JSONDecodeError, ValidationError, Exception) as e:
|
| 217 |
+
parse_error = str(e)
|
| 218 |
+
|
| 219 |
+
if output is None:
|
| 220 |
+
# Retry once with stricter reminder (spec 10.5)
|
| 221 |
+
raw2 = _call_groq(evidence, retry_strict=True)
|
| 222 |
+
try:
|
| 223 |
+
output = _parse_response(raw2)
|
| 224 |
+
raw = raw2 # use the successful response
|
| 225 |
+
except (json.JSONDecodeError, ValidationError, Exception) as e2:
|
| 226 |
+
# Both attempts failed β log and raise
|
| 227 |
+
raise RuntimeError(
|
| 228 |
+
f"LLM response failed to parse after 2 attempts. "
|
| 229 |
+
f"First error: {parse_error}. Second error: {e2}. "
|
| 230 |
+
f"Raw response (last): {raw2}"
|
| 231 |
+
)
|
| 232 |
+
|
| 233 |
+
# 10.6 β grounding check: no customer ID in narrative that isn't in the bundle
|
| 234 |
+
grounding_ok = run_grounding_check(output.narrative, evidence["customer_ids"])
|
| 235 |
+
|
| 236 |
+
return {
|
| 237 |
+
"narrative": output.narrative,
|
| 238 |
+
"confidence_statement": output.confidence_statement,
|
| 239 |
+
"grounding_ok": grounding_ok,
|
| 240 |
+
"raw_response": raw,
|
| 241 |
+
"evidence_bundle": evidence,
|
| 242 |
+
}
|
| 243 |
+
|
| 244 |
+
|
| 245 |
+
# ---------------------------------------------------------------------------
|
| 246 |
+
# 10.6 β Grounding check
|
| 247 |
+
# ---------------------------------------------------------------------------
|
| 248 |
+
|
| 249 |
+
def run_grounding_check(narrative: str, customer_ids: list[str]) -> bool:
|
| 250 |
+
"""
|
| 251 |
+
Check that any customer ID (CUSTXXXX pattern) mentioned in the narrative
|
| 252 |
+
is a member of customer_ids.
|
| 253 |
+
|
| 254 |
+
Returns True if the narrative is grounded (no hallucinated IDs).
|
| 255 |
+
Returns False if the narrative references a customer ID not in the bundle.
|
| 256 |
+
"""
|
| 257 |
+
# Find all CUST-prefixed IDs mentioned in the narrative
|
| 258 |
+
mentioned_ids = set(re.findall(r"CUST\d+", narrative))
|
| 259 |
+
allowed_ids = set(customer_ids)
|
| 260 |
+
|
| 261 |
+
hallucinated = mentioned_ids - allowed_ids
|
| 262 |
+
if hallucinated:
|
| 263 |
+
return False
|
| 264 |
+
return True
|
agent/policy.py
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
policy.py
|
| 3 |
+
---------
|
| 4 |
+
Deterministic policy gate for RingGuard.
|
| 5 |
+
|
| 6 |
+
Pure function, no LLM calls, no side effects.
|
| 7 |
+
This is the ONLY place in the system that decides whether a money-adjacent
|
| 8 |
+
action is triggered β it stays boring and deterministic on purpose.
|
| 9 |
+
|
| 10 |
+
Phase 3 threshold calibration (v3.0):
|
| 11 |
+
The original Phase 2 auto_hold threshold of β€βΉ5,000 was found to be
|
| 12 |
+
incompatible with the trained model's scoring range during Phase 3 Section 1.
|
| 13 |
+
The Phase 2 model's minimum positive avg_order_amount is βΉ3,249; a 3-member
|
| 14 |
+
ring with 6 orders at that level produces ββΉ19,800 total β above the old cap.
|
| 15 |
+
Updated to β€βΉ25,000 to allow small-cell rings with realistic amounts through.
|
| 16 |
+
Documented in phase3_summary.md under Key Decisions.
|
| 17 |
+
|
| 18 |
+
Thresholds (Phase 3, v3.0):
|
| 19 |
+
risk >= 0.85 and exposure <= 25000 β auto_hold
|
| 20 |
+
risk >= 0.85 and exposure > 25000 β escalate
|
| 21 |
+
0.50 <= risk < 0.85 β escalate
|
| 22 |
+
risk < 0.50 β log_only
|
| 23 |
+
|
| 24 |
+
Usage:
|
| 25 |
+
from agent.policy import decide
|
| 26 |
+
action = decide(risk_probability=0.91, exposure_rupees=19800.0)
|
| 27 |
+
# β "auto_hold"
|
| 28 |
+
"""
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def decide(risk_probability: float, exposure_rupees: float) -> str:
|
| 32 |
+
"""
|
| 33 |
+
Parameters
|
| 34 |
+
----------
|
| 35 |
+
risk_probability : float
|
| 36 |
+
Model output probability in [0, 1].
|
| 37 |
+
exposure_rupees : float
|
| 38 |
+
Total order amount across the cluster (from features.total_amount).
|
| 39 |
+
|
| 40 |
+
Returns
|
| 41 |
+
-------
|
| 42 |
+
str β one of: "auto_hold", "escalate", "log_only"
|
| 43 |
+
"""
|
| 44 |
+
if risk_probability >= 0.85 and exposure_rupees <= 25000:
|
| 45 |
+
return "auto_hold"
|
| 46 |
+
if risk_probability >= 0.85 and exposure_rupees > 25000:
|
| 47 |
+
return "escalate"
|
| 48 |
+
if 0.5 <= risk_probability < 0.85:
|
| 49 |
+
return "escalate"
|
| 50 |
+
return "log_only"
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
# ---------------------------------------------------------------------------
|
| 54 |
+
# Inline assertions β the money-decision boundary warrants a few spot checks
|
| 55 |
+
# ---------------------------------------------------------------------------
|
| 56 |
+
if __name__ == "__main__":
|
| 57 |
+
assert decide(0.91, 3000.0) == "auto_hold", "high risk, low exposure"
|
| 58 |
+
assert decide(0.91, 30000.0) == "escalate", "high risk, high exposure"
|
| 59 |
+
assert decide(0.85, 25000.0) == "auto_hold", "boundary: exactly 0.85, exactly 25000"
|
| 60 |
+
assert decide(0.85, 25001.0) == "escalate", "boundary: exactly 0.85, just over 25000"
|
| 61 |
+
assert decide(0.70, 0.0) == "escalate", "medium risk"
|
| 62 |
+
assert decide(0.50, 9999.0) == "escalate", "lower boundary medium risk"
|
| 63 |
+
assert decide(0.49, 9999.0) == "log_only", "below medium threshold"
|
| 64 |
+
assert decide(0.0, 0.0) == "log_only", "zero risk"
|
| 65 |
+
print("All policy assertions passed.")
|
agent/run_demo.py
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
run_demo.py
|
| 3 |
+
-----------
|
| 4 |
+
End-to-end demo run: score every cluster in data/synthetic/scored_clusters.json
|
| 5 |
+
through the full LangGraph pipeline and save results to
|
| 6 |
+
data/synthetic/cases_demo.json.
|
| 7 |
+
|
| 8 |
+
Usage:
|
| 9 |
+
python agent/run_demo.py
|
| 10 |
+
"""
|
| 11 |
+
|
| 12 |
+
import json
|
| 13 |
+
import os
|
| 14 |
+
import sys
|
| 15 |
+
import time
|
| 16 |
+
from datetime import datetime, timezone
|
| 17 |
+
|
| 18 |
+
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 19 |
+
sys.path.insert(0, BASE_DIR)
|
| 20 |
+
|
| 21 |
+
from dotenv import load_dotenv
|
| 22 |
+
load_dotenv()
|
| 23 |
+
|
| 24 |
+
from scoring.features import extract_features, _load_json, _load_graph, FEATURE_COLUMNS
|
| 25 |
+
from agent.graph import run_cluster
|
| 26 |
+
from agent.investigator import run_grounding_check
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
DEMO_DIR = os.path.join(BASE_DIR, "data", "synthetic")
|
| 30 |
+
OUT_PATH = os.path.join(DEMO_DIR, "cases_demo.json")
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def run_demo():
|
| 34 |
+
scored_path = os.path.join(DEMO_DIR, "scored_clusters.json")
|
| 35 |
+
orders_path = os.path.join(DEMO_DIR, "orders.json")
|
| 36 |
+
graph_path = os.path.join(DEMO_DIR, "graph.gpickle")
|
| 37 |
+
|
| 38 |
+
print(f"Loading demo data from {DEMO_DIR}...")
|
| 39 |
+
scored = _load_json(scored_path)
|
| 40 |
+
orders = _load_json(orders_path)
|
| 41 |
+
graph = _load_graph(graph_path) if os.path.exists(graph_path) else None
|
| 42 |
+
|
| 43 |
+
print(f" {len(scored)} clusters to process\n")
|
| 44 |
+
|
| 45 |
+
cases = []
|
| 46 |
+
grounding_failures = []
|
| 47 |
+
|
| 48 |
+
for idx, cluster in enumerate(scored, start=1):
|
| 49 |
+
cid = cluster["cluster_id"]
|
| 50 |
+
risk = cluster["risk_probability"]
|
| 51 |
+
print(f"[{idx:02d}/{len(scored)}] {cid} risk={risk:.4f} formation={cluster.get('formation_type','?')}", end=" ", flush=True)
|
| 52 |
+
|
| 53 |
+
features = extract_features(cluster, orders, graph=graph)
|
| 54 |
+
result = run_cluster(cluster, features, risk)
|
| 55 |
+
|
| 56 |
+
decision = result["policy_decision"]
|
| 57 |
+
narrative = result["llm_narrative"]
|
| 58 |
+
confidence = result["llm_confidence"]
|
| 59 |
+
grounding = result.get("grounding_ok")
|
| 60 |
+
|
| 61 |
+
print(f"-> {decision}")
|
| 62 |
+
|
| 63 |
+
# Small sleep between LLM calls to stay within free-tier TPM limits
|
| 64 |
+
# (only needed for escalate/auto_hold cases that call the LLM)
|
| 65 |
+
if decision in ("auto_hold", "escalate"):
|
| 66 |
+
time.sleep(3)
|
| 67 |
+
|
| 68 |
+
# 10.6 β grounding check for every narrative that was generated
|
| 69 |
+
if narrative and not narrative.startswith("[LLM_ERROR]"):
|
| 70 |
+
gok = run_grounding_check(narrative, cluster["customer_ids"])
|
| 71 |
+
if not gok:
|
| 72 |
+
grounding_failures.append({
|
| 73 |
+
"cluster_id": cid,
|
| 74 |
+
"narrative": narrative,
|
| 75 |
+
"customer_ids": cluster["customer_ids"],
|
| 76 |
+
})
|
| 77 |
+
print(f" [GROUNDING FAIL] narrative references customer ID not in bundle!")
|
| 78 |
+
|
| 79 |
+
case = {
|
| 80 |
+
"case_id": f"CASE{idx:02d}",
|
| 81 |
+
"cluster_id": cid,
|
| 82 |
+
"customer_ids": cluster["customer_ids"],
|
| 83 |
+
"risk_probability": risk,
|
| 84 |
+
"policy_decision": decision,
|
| 85 |
+
"llm_narrative": narrative,
|
| 86 |
+
"llm_confidence_statement": confidence,
|
| 87 |
+
"action_taken": None, # Phase 3 populates via Razorpay MCP
|
| 88 |
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
| 89 |
+
}
|
| 90 |
+
cases.append(case)
|
| 91 |
+
|
| 92 |
+
# Write cases_demo.json
|
| 93 |
+
with open(OUT_PATH, "w", encoding="utf-8") as f:
|
| 94 |
+
json.dump(cases, f, indent=2, ensure_ascii=False)
|
| 95 |
+
print(f"\nSaved {len(cases)} cases to {OUT_PATH}")
|
| 96 |
+
|
| 97 |
+
# Summary
|
| 98 |
+
from collections import Counter
|
| 99 |
+
decision_counts = Counter(c["policy_decision"] for c in cases)
|
| 100 |
+
llm_called = sum(1 for c in cases if c["llm_narrative"] and not c["llm_narrative"].startswith("[LLM_ERROR]"))
|
| 101 |
+
llm_errors = sum(1 for c in cases if c["llm_narrative"] and c["llm_narrative"].startswith("[LLM_ERROR]"))
|
| 102 |
+
|
| 103 |
+
print("\n========== Demo Run Summary ==========")
|
| 104 |
+
print(f" Total cases : {len(cases)}")
|
| 105 |
+
for action, count in sorted(decision_counts.items()):
|
| 106 |
+
print(f" {action:15s} : {count}")
|
| 107 |
+
print(f" LLM calls made : {llm_called}")
|
| 108 |
+
print(f" LLM errors : {llm_errors}")
|
| 109 |
+
print(f" Grounding failures : {len(grounding_failures)}")
|
| 110 |
+
print("=======================================")
|
| 111 |
+
|
| 112 |
+
if grounding_failures:
|
| 113 |
+
print("\n[WARNING] Grounding failures detected:")
|
| 114 |
+
for gf in grounding_failures:
|
| 115 |
+
print(f" {gf['cluster_id']}: {gf['narrative']}")
|
| 116 |
+
|
| 117 |
+
return cases, grounding_failures, decision_counts
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
if __name__ == "__main__":
|
| 121 |
+
run_demo()
|
api/.gitkeep
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
|
api/main.py
ADDED
|
@@ -0,0 +1,357 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
main.py
|
| 3 |
+
-------
|
| 4 |
+
Phase 3 Section 5 β FastAPI dashboard for RingGuard.
|
| 5 |
+
|
| 6 |
+
Endpoints:
|
| 7 |
+
GET / β HTML dashboard: table of all cases
|
| 8 |
+
GET /cases β JSON list of all cases (from cases_demo.json)
|
| 9 |
+
GET /cases/{case_id} β JSON detail for one case + full audit chain
|
| 10 |
+
GET /health β health check
|
| 11 |
+
|
| 12 |
+
The dashboard reads directly from cases_demo.json and audit_log.jsonl.
|
| 13 |
+
No database, no auth β demo only.
|
| 14 |
+
|
| 15 |
+
Usage:
|
| 16 |
+
uvicorn api.main:app --reload --port 7860
|
| 17 |
+
"""
|
| 18 |
+
|
| 19 |
+
import json
|
| 20 |
+
import os
|
| 21 |
+
from typing import Optional
|
| 22 |
+
|
| 23 |
+
from fastapi import FastAPI, HTTPException
|
| 24 |
+
from fastapi.responses import HTMLResponse, JSONResponse
|
| 25 |
+
|
| 26 |
+
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 27 |
+
CASES_PATH = os.path.join(BASE_DIR, "data", "synthetic", "cases_demo.json")
|
| 28 |
+
AUDIT_PATH = os.path.join(BASE_DIR, "audit", "audit_log.jsonl")
|
| 29 |
+
|
| 30 |
+
app = FastAPI(
|
| 31 |
+
title="RingGuard Dashboard",
|
| 32 |
+
description="Phase 3 β Fraud ring detection results and audit trail",
|
| 33 |
+
version="3.0.0",
|
| 34 |
+
)
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
# ---------------------------------------------------------------------------
|
| 38 |
+
# Data loaders
|
| 39 |
+
# ---------------------------------------------------------------------------
|
| 40 |
+
|
| 41 |
+
def _load_cases() -> list:
|
| 42 |
+
if not os.path.exists(CASES_PATH):
|
| 43 |
+
return []
|
| 44 |
+
with open(CASES_PATH, encoding="utf-8") as f:
|
| 45 |
+
return json.load(f)
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
def _load_audit() -> list:
|
| 49 |
+
if not os.path.exists(AUDIT_PATH):
|
| 50 |
+
return []
|
| 51 |
+
records = []
|
| 52 |
+
with open(AUDIT_PATH, encoding="utf-8") as f:
|
| 53 |
+
for line in f:
|
| 54 |
+
line = line.strip()
|
| 55 |
+
if line:
|
| 56 |
+
records.append(json.loads(line))
|
| 57 |
+
return records
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
# ---------------------------------------------------------------------------
|
| 61 |
+
# API endpoints
|
| 62 |
+
# ---------------------------------------------------------------------------
|
| 63 |
+
|
| 64 |
+
@app.get("/health")
|
| 65 |
+
def health():
|
| 66 |
+
return {"status": "ok", "version": "3.0.0"}
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
@app.get("/cases", response_class=JSONResponse)
|
| 70 |
+
def get_cases():
|
| 71 |
+
"""Return all cases as a JSON list."""
|
| 72 |
+
cases = _load_cases()
|
| 73 |
+
# Return a summary view (without full narrative for list)
|
| 74 |
+
summary = []
|
| 75 |
+
for c in cases:
|
| 76 |
+
summary.append({
|
| 77 |
+
"case_id": c.get("case_id"),
|
| 78 |
+
"cluster_id": c.get("cluster_id"),
|
| 79 |
+
"cluster_size": len(c.get("customer_ids", [])),
|
| 80 |
+
"risk_score": round(c.get("risk_probability", 0), 4),
|
| 81 |
+
"policy_decision": c.get("policy_decision"),
|
| 82 |
+
"action_taken": bool(c.get("action_taken") and c["action_taken"].get("order_id")),
|
| 83 |
+
"timestamp": c.get("timestamp"),
|
| 84 |
+
})
|
| 85 |
+
return summary
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
@app.get("/cases/{case_id}", response_class=JSONResponse)
|
| 89 |
+
def get_case_detail(case_id: str):
|
| 90 |
+
"""Return full detail for one case, including audit chain."""
|
| 91 |
+
cases = _load_cases()
|
| 92 |
+
case = next((c for c in cases if c.get("case_id") == case_id), None)
|
| 93 |
+
if not case:
|
| 94 |
+
raise HTTPException(status_code=404, detail=f"Case {case_id} not found")
|
| 95 |
+
|
| 96 |
+
# Find audit records for this case
|
| 97 |
+
audit_records = [r for r in _load_audit() if r.get("case_id") == case_id]
|
| 98 |
+
|
| 99 |
+
return {
|
| 100 |
+
"case": case,
|
| 101 |
+
"audit_chain": audit_records,
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
# ---------------------------------------------------------------------------
|
| 106 |
+
# HTML dashboard
|
| 107 |
+
# ---------------------------------------------------------------------------
|
| 108 |
+
|
| 109 |
+
def _decision_badge(decision: str) -> str:
|
| 110 |
+
colours = {
|
| 111 |
+
"auto_hold": "#c0392b",
|
| 112 |
+
"escalate": "#e67e22",
|
| 113 |
+
"log_only": "#27ae60",
|
| 114 |
+
}
|
| 115 |
+
colour = colours.get(decision, "#7f8c8d")
|
| 116 |
+
return (
|
| 117 |
+
f'<span style="background:{colour};color:#fff;padding:2px 8px;'
|
| 118 |
+
f'border-radius:4px;font-size:11px;font-weight:600;">'
|
| 119 |
+
f'{decision.upper()}</span>'
|
| 120 |
+
)
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
def _build_dashboard(cases: list) -> str:
|
| 124 |
+
rows = ""
|
| 125 |
+
for c in cases:
|
| 126 |
+
decision = c.get("policy_decision", "")
|
| 127 |
+
badge = _decision_badge(decision)
|
| 128 |
+
risk = round(c.get("risk_probability", 0) * 100, 1)
|
| 129 |
+
cluster = c.get("cluster_id", "")
|
| 130 |
+
case_id = c.get("case_id", "")
|
| 131 |
+
size = len(c.get("customer_ids", []))
|
| 132 |
+
action = c.get("action_taken") or {}
|
| 133 |
+
order_id = action.get("order_id") or "β"
|
| 134 |
+
verified = "Yes" if action.get("notes_verified") else "β"
|
| 135 |
+
|
| 136 |
+
rows += (
|
| 137 |
+
f'<tr onclick="window.location=\'/cases/{case_id}\'" style="cursor:pointer">'
|
| 138 |
+
f'<td>{case_id}</td>'
|
| 139 |
+
f'<td>{cluster}</td>'
|
| 140 |
+
f'<td style="text-align:center">{size}</td>'
|
| 141 |
+
f'<td style="text-align:right">{risk}%</td>'
|
| 142 |
+
f'<td>{badge}</td>'
|
| 143 |
+
f'<td style="font-size:11px;color:#57606a">{order_id}</td>'
|
| 144 |
+
f'<td style="text-align:center">{verified}</td>'
|
| 145 |
+
f'</tr>\n'
|
| 146 |
+
)
|
| 147 |
+
|
| 148 |
+
auto_holds = sum(1 for c in cases if c.get("policy_decision") == "auto_hold")
|
| 149 |
+
escalates = sum(1 for c in cases if c.get("policy_decision") == "escalate")
|
| 150 |
+
log_only = sum(1 for c in cases if c.get("policy_decision") == "log_only")
|
| 151 |
+
|
| 152 |
+
return f"""<!DOCTYPE html>
|
| 153 |
+
<html lang="en">
|
| 154 |
+
<head>
|
| 155 |
+
<meta charset="utf-8">
|
| 156 |
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
| 157 |
+
<title>RingGuard β Fraud Detection Dashboard</title>
|
| 158 |
+
<style>
|
| 159 |
+
* {{ box-sizing: border-box; margin: 0; padding: 0; }}
|
| 160 |
+
body {{ font-family: -apple-system, "Segoe UI", system-ui, sans-serif;
|
| 161 |
+
font-size: 14px; line-height: 1.6; background: #f7f8fa; color: #1f2328; }}
|
| 162 |
+
.container {{ max-width: 960px; margin: 0 auto; padding: 24px 16px; }}
|
| 163 |
+
h1 {{ font-size: 22px; font-weight: 700; margin-bottom: 4px; }}
|
| 164 |
+
.subtitle {{ color: #57606a; font-size: 13px; margin-bottom: 24px; }}
|
| 165 |
+
.stats {{ display: flex; gap: 16px; margin-bottom: 24px; flex-wrap: wrap; }}
|
| 166 |
+
.stat-card {{ background: #fff; border: 1px solid #e5e7eb; border-radius: 6px;
|
| 167 |
+
padding: 12px 20px; flex: 1; min-width: 140px; }}
|
| 168 |
+
.stat-card .label {{ font-size: 11px; color: #57606a; text-transform: uppercase;
|
| 169 |
+
letter-spacing: 0.05em; }}
|
| 170 |
+
.stat-card .value {{ font-size: 24px; font-weight: 700; }}
|
| 171 |
+
.stat-card.hold .value {{ color: #c0392b; }}
|
| 172 |
+
.stat-card.escalate .value {{ color: #e67e22; }}
|
| 173 |
+
.stat-card.log .value {{ color: #27ae60; }}
|
| 174 |
+
table {{ width: 100%; border-collapse: collapse; background: #fff;
|
| 175 |
+
border: 1px solid #e5e7eb; border-radius: 6px; overflow: hidden; }}
|
| 176 |
+
th {{ background: #f7f8fa; border-bottom: 2px solid #e5e7eb; padding: 8px 12px;
|
| 177 |
+
text-align: left; font-size: 12px; font-weight: 600; color: #57606a;
|
| 178 |
+
text-transform: uppercase; letter-spacing: 0.04em; }}
|
| 179 |
+
td {{ padding: 8px 12px; border-bottom: 1px solid #f0f0f0; vertical-align: middle; }}
|
| 180 |
+
tr:last-child td {{ border-bottom: none; }}
|
| 181 |
+
tr:hover td {{ background: #f7f8fa; }}
|
| 182 |
+
.footer {{ text-align: center; font-size: 12px; color: #57606a; margin-top: 32px;
|
| 183 |
+
padding-top: 16px; border-top: 1px solid #e5e7eb; }}
|
| 184 |
+
a {{ color: #3b82d4; text-decoration: none; }}
|
| 185 |
+
a:hover {{ text-decoration: underline; }}
|
| 186 |
+
</style>
|
| 187 |
+
</head>
|
| 188 |
+
<body>
|
| 189 |
+
<div class="container">
|
| 190 |
+
<h1>RingGuard β Fraud Detection Dashboard</h1>
|
| 191 |
+
<p class="subtitle">Phase 3 Β· {len(cases)} cases Β· LightGBM + LangGraph + Razorpay test-mode</p>
|
| 192 |
+
|
| 193 |
+
<div class="stats">
|
| 194 |
+
<div class="stat-card hold">
|
| 195 |
+
<div class="label">Auto Hold</div>
|
| 196 |
+
<div class="value">{auto_holds}</div>
|
| 197 |
+
</div>
|
| 198 |
+
<div class="stat-card escalate">
|
| 199 |
+
<div class="label">Escalate</div>
|
| 200 |
+
<div class="value">{escalates}</div>
|
| 201 |
+
</div>
|
| 202 |
+
<div class="stat-card log">
|
| 203 |
+
<div class="label">Log Only</div>
|
| 204 |
+
<div class="value">{log_only}</div>
|
| 205 |
+
</div>
|
| 206 |
+
<div class="stat-card">
|
| 207 |
+
<div class="label">Total Cases</div>
|
| 208 |
+
<div class="value">{len(cases)}</div>
|
| 209 |
+
</div>
|
| 210 |
+
</div>
|
| 211 |
+
|
| 212 |
+
<table>
|
| 213 |
+
<thead>
|
| 214 |
+
<tr>
|
| 215 |
+
<th>Case</th>
|
| 216 |
+
<th>Cluster</th>
|
| 217 |
+
<th style="text-align:center">Size</th>
|
| 218 |
+
<th style="text-align:right">Risk Score</th>
|
| 219 |
+
<th>Decision</th>
|
| 220 |
+
<th>Razorpay Order</th>
|
| 221 |
+
<th style="text-align:center">Verified</th>
|
| 222 |
+
</tr>
|
| 223 |
+
</thead>
|
| 224 |
+
<tbody>
|
| 225 |
+
{rows} </tbody>
|
| 226 |
+
</table>
|
| 227 |
+
|
| 228 |
+
<p style="margin-top:12px;font-size:12px;color:#57606a">
|
| 229 |
+
Click any row to view the full evidence bundle, LLM narrative, and audit chain.
|
| 230 |
+
</p>
|
| 231 |
+
|
| 232 |
+
<div class="footer">Made with IBM Bob · RingGuard v3.0</div>
|
| 233 |
+
</div>
|
| 234 |
+
</body>
|
| 235 |
+
</html>"""
|
| 236 |
+
|
| 237 |
+
|
| 238 |
+
@app.get("/", response_class=HTMLResponse)
|
| 239 |
+
def dashboard():
|
| 240 |
+
"""Serve the HTML dashboard."""
|
| 241 |
+
cases = _load_cases()
|
| 242 |
+
html = _build_dashboard(cases)
|
| 243 |
+
return HTMLResponse(content=html)
|
| 244 |
+
|
| 245 |
+
|
| 246 |
+
@app.get("/cases/{case_id}/detail", response_class=HTMLResponse)
|
| 247 |
+
def case_detail_html(case_id: str):
|
| 248 |
+
"""Serve HTML detail page for a single case."""
|
| 249 |
+
cases = _load_cases()
|
| 250 |
+
case = next((c for c in cases if c.get("case_id") == case_id), None)
|
| 251 |
+
if not case:
|
| 252 |
+
raise HTTPException(status_code=404, detail=f"Case {case_id} not found")
|
| 253 |
+
|
| 254 |
+
audit_records = [r for r in _load_audit() if r.get("case_id") == case_id]
|
| 255 |
+
|
| 256 |
+
decision = case.get("policy_decision", "")
|
| 257 |
+
badge = _decision_badge(decision)
|
| 258 |
+
risk = round(case.get("risk_probability", 0) * 100, 2)
|
| 259 |
+
narrative = case.get("llm_narrative") or "<em>No narrative (log_only case)</em>"
|
| 260 |
+
confidence = case.get("llm_confidence_statement") or "β"
|
| 261 |
+
members = ", ".join(case.get("customer_ids", []))
|
| 262 |
+
|
| 263 |
+
action = case.get("action_taken") or {}
|
| 264 |
+
order_id = action.get("order_id") or "β"
|
| 265 |
+
verified = "Yes" if action.get("notes_verified") else "β"
|
| 266 |
+
tool_used = action.get("tool") or "β"
|
| 267 |
+
timestamp = action.get("timestamp") or "β"
|
| 268 |
+
|
| 269 |
+
audit_rows = ""
|
| 270 |
+
for rec in audit_records:
|
| 271 |
+
ts = rec.get("timestamp", "")[:19].replace("T", " ")
|
| 272 |
+
audit_rows += (
|
| 273 |
+
f'<tr>'
|
| 274 |
+
f'<td>{ts}</td>'
|
| 275 |
+
f'<td>{rec.get("policy_decision","")}</td>'
|
| 276 |
+
f'<td style="font-size:11px">{rec.get("reason_if_not_auto_actioned") or "β"}</td>'
|
| 277 |
+
f'</tr>\n'
|
| 278 |
+
)
|
| 279 |
+
|
| 280 |
+
html = f"""<!DOCTYPE html>
|
| 281 |
+
<html lang="en">
|
| 282 |
+
<head>
|
| 283 |
+
<meta charset="utf-8">
|
| 284 |
+
<title>RingGuard β {case_id}</title>
|
| 285 |
+
<style>
|
| 286 |
+
* {{ box-sizing: border-box; margin: 0; padding: 0; }}
|
| 287 |
+
body {{ font-family: -apple-system, "Segoe UI", system-ui, sans-serif;
|
| 288 |
+
font-size: 14px; line-height: 1.6; background: #f7f8fa; color: #1f2328; }}
|
| 289 |
+
.container {{ max-width: 760px; margin: 0 auto; padding: 24px 16px; }}
|
| 290 |
+
h1 {{ font-size: 20px; font-weight: 700; margin-bottom: 4px; }}
|
| 291 |
+
.back {{ font-size: 13px; color: #3b82d4; margin-bottom: 16px; display: block; }}
|
| 292 |
+
.card {{ background: #fff; border: 1px solid #e5e7eb; border-radius: 6px;
|
| 293 |
+
padding: 16px; margin-bottom: 16px; }}
|
| 294 |
+
.card h2 {{ font-size: 13px; font-weight: 600; color: #57606a; text-transform: uppercase;
|
| 295 |
+
letter-spacing: 0.05em; margin-bottom: 8px; }}
|
| 296 |
+
.row {{ display: flex; gap: 24px; margin-bottom: 6px; flex-wrap: wrap; }}
|
| 297 |
+
.kv {{ flex: 1; min-width: 200px; }}
|
| 298 |
+
.kv .k {{ font-size: 11px; color: #57606a; }}
|
| 299 |
+
.kv .v {{ font-weight: 500; }}
|
| 300 |
+
.narrative {{ background: #f7f8fa; border-left: 3px solid #3b82d4;
|
| 301 |
+
padding: 10px 14px; border-radius: 0 4px 4px 0; font-style: italic; }}
|
| 302 |
+
table {{ width: 100%; border-collapse: collapse; }}
|
| 303 |
+
th {{ text-align: left; font-size: 12px; color: #57606a; padding: 4px 8px;
|
| 304 |
+
border-bottom: 1px solid #e5e7eb; }}
|
| 305 |
+
td {{ padding: 6px 8px; border-bottom: 1px solid #f0f0f0; }}
|
| 306 |
+
.footer {{ text-align: center; font-size: 12px; color: #57606a; margin-top: 32px;
|
| 307 |
+
padding-top: 16px; border-top: 1px solid #e5e7eb; }}
|
| 308 |
+
span.badge {{ display: inline-block; }}
|
| 309 |
+
</style>
|
| 310 |
+
</head>
|
| 311 |
+
<body>
|
| 312 |
+
<div class="container">
|
| 313 |
+
<a class="back" href="/">← Back to all cases</a>
|
| 314 |
+
<h1>{case_id} β {case.get("cluster_id","")}</h1>
|
| 315 |
+
|
| 316 |
+
<div class="card">
|
| 317 |
+
<h2>Summary</h2>
|
| 318 |
+
<div class="row">
|
| 319 |
+
<div class="kv"><div class="k">Risk Score</div><div class="v">{risk}%</div></div>
|
| 320 |
+
<div class="kv"><div class="k">Decision</div><div class="v">{badge}</div></div>
|
| 321 |
+
<div class="kv"><div class="k">Cluster Size</div><div class="v">{len(case.get("customer_ids",[]))}</div></div>
|
| 322 |
+
</div>
|
| 323 |
+
<div class="row">
|
| 324 |
+
<div class="kv"><div class="k">Cluster Members</div><div class="v" style="font-size:12px">{members}</div></div>
|
| 325 |
+
</div>
|
| 326 |
+
</div>
|
| 327 |
+
|
| 328 |
+
<div class="card">
|
| 329 |
+
<h2>LLM Narrative (openai/gpt-oss-120b via Groq)</h2>
|
| 330 |
+
<div class="narrative">{narrative}</div>
|
| 331 |
+
<div style="margin-top:8px;font-size:12px;color:#57606a">
|
| 332 |
+
<strong>Confidence:</strong> {confidence}
|
| 333 |
+
</div>
|
| 334 |
+
</div>
|
| 335 |
+
|
| 336 |
+
<div class="card">
|
| 337 |
+
<h2>Razorpay Action (Test Mode)</h2>
|
| 338 |
+
<div class="row">
|
| 339 |
+
<div class="kv"><div class="k">Order ID</div><div class="v" style="font-size:12px">{order_id}</div></div>
|
| 340 |
+
<div class="kv"><div class="k">Notes Verified</div><div class="v">{verified}</div></div>
|
| 341 |
+
</div>
|
| 342 |
+
<div class="row">
|
| 343 |
+
<div class="kv"><div class="k">Tool Used</div><div class="v" style="font-size:11px">{tool_used}</div></div>
|
| 344 |
+
<div class="kv"><div class="k">Timestamp</div><div class="v" style="font-size:12px">{timestamp[:19] if len(timestamp)>=19 else timestamp}</div></div>
|
| 345 |
+
</div>
|
| 346 |
+
</div>
|
| 347 |
+
|
| 348 |
+
<div class="card">
|
| 349 |
+
<h2>Audit Chain</h2>
|
| 350 |
+
{f'<table><thead><tr><th>Timestamp</th><th>Decision</th><th>Reason</th></tr></thead><tbody>{audit_rows}</tbody></table>' if audit_rows else '<p style="color:#57606a;font-size:13px">No audit records found for this case.</p>'}
|
| 351 |
+
</div>
|
| 352 |
+
|
| 353 |
+
<div class="footer">Made with IBM Bob · RingGuard v3.0</div>
|
| 354 |
+
</div>
|
| 355 |
+
</body>
|
| 356 |
+
</html>"""
|
| 357 |
+
return HTMLResponse(content=html)
|
audit/.gitkeep
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
|
audit/audit_log.jsonl
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{"case_id": "CASE01", "timestamp": "2026-08-22T02:48:44.328671+00:00", "cluster_members": ["CUST0041", "CUST0042", "CUST0043", "CUST0044"], "evidence_bundle": {"cluster_id": "CAND01", "size": 4, "customer_ids": ["CUST0041", "CUST0042", "CUST0043", "CUST0044"], "formation_type": null}, "graph_score_inputs": {"size": 4, "strong_link_count": 6, "weak_link_count": 0, "strong_link_density": 1.0, "has_same_contact_edge": 0, "order_count": 12, "total_amount": 58186, "avg_order_amount": 4848.833333333333, "return_rate": 0.3333333333333333, "chargeback_rate": 0.16666666666666666, "shared_coupon_count": 0, "time_span_days": 118.78427083333334, "order_velocity": 0.10102347655808104, "formation_type_strong": 1}, "lightgbm_probability": 0.9958773824170732, "llm_narrative": "The four customers (CUST0041, CUST0042, CUST0043, CUST0044) form a strongβanchored cluster with six strong links and no weak links, indicating tightly coordinated activity. Their combined purchase total of $58,186 is accompanied by a 33.3% return rate and a 16.7% chargeback rate, further supporting fraudulent behavior.", "llm_confidence_statement": "The model assigns a risk probability of 99.6%, indicating very high confidence in the escalation decision.", "policy_decision": "escalate", "action_taken": {"tool": "razorpay.Client.order.create + order.edit + order.fetch", "order_id": "order_TSeidafHmbAnDR", "razorpay_status": "created", "notes_verified": true, "timestamp": "2026-08-22T02:47:10.941027+00:00", "test_mode": true, "error": null, "skip_reason": null, "notes_written": {"case_id": "CASE01", "cluster_id": "CAND01", "ringguard_status": "escalate_flagged", "action_label": "FRAUD_RING_ESCALATE", "risk_score": "0.9959", "action_by": "RingGuard_v3", "action_timestamp": "2026-08-22T02:47:10.102605+00:00"}}, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.9959 >= 0.85 but total_amount=βΉ58186 > βΉ25,000 auto_hold cap"}
|
| 2 |
+
{"case_id": "CASE02", "timestamp": "2026-08-22T02:48:44.330726+00:00", "cluster_members": ["CUST0009", "CUST0010", "CUST0011", "CUST0012", "CUST0013"], "evidence_bundle": {"cluster_id": "CAND02", "size": 5, "customer_ids": ["CUST0009", "CUST0010", "CUST0011", "CUST0012", "CUST0013"], "formation_type": null}, "graph_score_inputs": {"size": 5, "strong_link_count": 10, "weak_link_count": 0, "strong_link_density": 1.0, "has_same_contact_edge": 0, "order_count": 17, "total_amount": 59830, "avg_order_amount": 3519.4117647058824, "return_rate": 0.47058823529411764, "chargeback_rate": 0.17647058823529413, "shared_coupon_count": 0, "time_span_days": 153.46033564814815, "order_velocity": 0.11077781061926893, "formation_type_strong": 1}, "lightgbm_probability": 0.9968053865328341, "llm_narrative": "The five customers (CUST0009βCUST0013) form a strongβanchored cluster with ten strong links and no weak links. The group shows a return rate of 47% and a chargeback rate of 18%, with total transaction volume of $59,830. The risk model assigns a probability of 99.7%, resulting in an escalation decision.", "llm_confidence_statement": "We are highly confident in this assessment given the very high risk probability and supporting metrics.", "policy_decision": "escalate", "action_taken": {"tool": "razorpay.Client.order.create + order.edit + order.fetch", "order_id": "order_TSeieevTUEtDNP", "razorpay_status": "created", "notes_verified": true, "timestamp": "2026-08-22T02:47:11.992374+00:00", "test_mode": true, "error": null, "skip_reason": null, "notes_written": {"case_id": "CASE02", "cluster_id": "CAND02", "ringguard_status": "escalate_flagged", "action_label": "FRAUD_RING_ESCALATE", "risk_score": "0.9968", "action_by": "RingGuard_v3", "action_timestamp": "2026-08-22T02:47:11.088678+00:00"}}, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.9968 >= 0.85 but total_amount=βΉ59830 > βΉ25,000 auto_hold cap"}
|
| 3 |
+
{"case_id": "CASE03", "timestamp": "2026-08-22T02:48:44.331690+00:00", "cluster_members": ["CUST0001", "CUST0002", "CUST0003"], "evidence_bundle": {"cluster_id": "CAND03", "size": 3, "customer_ids": ["CUST0001", "CUST0002", "CUST0003"], "formation_type": null}, "graph_score_inputs": {"size": 3, "strong_link_count": 3, "weak_link_count": 0, "strong_link_density": 1.0, "has_same_contact_edge": 0, "order_count": 8, "total_amount": 32897, "avg_order_amount": 4112.125, "return_rate": 0.25, "chargeback_rate": 0.125, "shared_coupon_count": 1, "time_span_days": 127.71112268518519, "order_velocity": 0.06264137243331916, "formation_type_strong": 1}, "lightgbm_probability": 0.9950028638127228, "llm_narrative": "The three customers (CUST0001, CUST0002, CUST0003) are connected by three strong links, forming a strongβanchored cluster. This cluster accounts for a total transaction amount of 32,897, includes one shared coupon, and exhibits a 25% return rate and a 12.5% chargeback rate, resulting in a risk probability of 99.5%.", "llm_confidence_statement": "The modelβs confidence in this risk assessment is extremely high.", "policy_decision": "escalate", "action_taken": {"tool": "razorpay.Client.order.create + order.edit + order.fetch", "order_id": "order_TSeifof2nHqiyN", "razorpay_status": "created", "notes_verified": true, "timestamp": "2026-08-22T02:47:13.232792+00:00", "test_mode": true, "error": null, "skip_reason": null, "notes_written": {"case_id": "CASE03", "cluster_id": "CAND03", "ringguard_status": "escalate_flagged", "action_label": "FRAUD_RING_ESCALATE", "risk_score": "0.995", "action_by": "RingGuard_v3", "action_timestamp": "2026-08-22T02:47:12.186378+00:00"}}, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.9950 >= 0.85 but total_amount=βΉ32897 > βΉ25,000 auto_hold cap"}
|
| 4 |
+
{"case_id": "CASE04", "timestamp": "2026-08-22T02:48:44.333027+00:00", "cluster_members": ["CUST0014", "CUST0015", "CUST0016", "CUST0017", "CUST0018"], "evidence_bundle": {"cluster_id": "CAND04", "size": 5, "customer_ids": ["CUST0014", "CUST0015", "CUST0016", "CUST0017", "CUST0018"], "formation_type": null}, "graph_score_inputs": {"size": 5, "strong_link_count": 10, "weak_link_count": 0, "strong_link_density": 1.0, "has_same_contact_edge": 0, "order_count": 16, "total_amount": 62087, "avg_order_amount": 3880.4375, "return_rate": 0.5, "chargeback_rate": 0.125, "shared_coupon_count": 1, "time_span_days": 158.5827314814815, "order_velocity": 0.10089370923635782, "formation_type_strong": 1}, "lightgbm_probability": 0.9955003588432927, "llm_narrative": "The five customers (CUST0014βCUST0018) form a strongβanchored cluster with ten strong links and no weak links, collectively spending $62,087. The group exhibits a 50% return rate, a 12.5% chargeback rate, and shares a single coupon, indicating coordinated risky behavior.", "llm_confidence_statement": "Given the 0.9955 risk probability, we are highly confident that this cluster represents a highβrisk fraud pattern.", "policy_decision": "escalate", "action_taken": {"tool": "razorpay.Client.order.create + order.edit + order.fetch", "order_id": "order_TSeihAqIgYfEsF", "razorpay_status": "created", "notes_verified": true, "timestamp": "2026-08-22T02:47:14.280655+00:00", "test_mode": true, "error": null, "skip_reason": null, "notes_written": {"case_id": "CASE04", "cluster_id": "CAND04", "ringguard_status": "escalate_flagged", "action_label": "FRAUD_RING_ESCALATE", "risk_score": "0.9955", "action_by": "RingGuard_v3", "action_timestamp": "2026-08-22T02:47:13.364816+00:00"}}, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.9955 >= 0.85 but total_amount=βΉ62087 > βΉ25,000 auto_hold cap"}
|
| 5 |
+
{"case_id": "CASE05", "timestamp": "2026-08-22T02:48:44.333027+00:00", "cluster_members": ["CUST0033", "CUST0034", "CUST0035"], "evidence_bundle": {"cluster_id": "CAND05", "size": 3, "customer_ids": ["CUST0033", "CUST0034", "CUST0035"], "formation_type": null}, "graph_score_inputs": {"size": 3, "strong_link_count": 3, "weak_link_count": 0, "strong_link_density": 1.0, "has_same_contact_edge": 0, "order_count": 11, "total_amount": 50134, "avg_order_amount": 4557.636363636364, "return_rate": 0.18181818181818182, "chargeback_rate": 0.09090909090909091, "shared_coupon_count": 1, "time_span_days": 170.66708333333332, "order_velocity": 0.06445296764412196, "formation_type_strong": 1}, "lightgbm_probability": 0.9969893801631614, "llm_narrative": "The three customers (CUST0033, CUST0034, CUST0035) are connected by three strong links, forming a strongβanchored cluster with a shared coupon and a combined transaction volume of $50,134. The cluster exhibits a return rate of 18.2% and a chargeback rate of 9.1%, and its calculated risk probability is 99.7%.", "llm_confidence_statement": "We are highly confident in the fraud assessment given the strong linkage, high risk probability, and notable financial metrics.", "policy_decision": "escalate", "action_taken": {"tool": "razorpay.Client.order.create + order.edit + order.fetch", "order_id": "order_TSeiiK16ZPVegj", "razorpay_status": "created", "notes_verified": true, "timestamp": "2026-08-22T02:47:15.299833+00:00", "test_mode": true, "error": null, "skip_reason": null, "notes_written": {"case_id": "CASE05", "cluster_id": "CAND05", "ringguard_status": "escalate_flagged", "action_label": "FRAUD_RING_ESCALATE", "risk_score": "0.997", "action_by": "RingGuard_v3", "action_timestamp": "2026-08-22T02:47:14.523378+00:00"}}, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.9970 >= 0.85 but total_amount=βΉ50134 > βΉ25,000 auto_hold cap"}
|
| 6 |
+
{"case_id": "CASE06", "timestamp": "2026-08-22T02:48:44.333027+00:00", "cluster_members": ["CUST0036", "CUST0037", "CUST0038", "CUST0039", "CUST0040"], "evidence_bundle": {"cluster_id": "CAND06", "size": 5, "customer_ids": ["CUST0036", "CUST0037", "CUST0038", "CUST0039", "CUST0040"], "formation_type": null}, "graph_score_inputs": {"size": 5, "strong_link_count": 10, "weak_link_count": 0, "strong_link_density": 1.0, "has_same_contact_edge": 0, "order_count": 15, "total_amount": 62270, "avg_order_amount": 4151.333333333333, "return_rate": 0.26666666666666666, "chargeback_rate": 0.2, "shared_coupon_count": 0, "time_span_days": 145.8427199074074, "order_velocity": 0.10285052287507526, "formation_type_strong": 1}, "lightgbm_probability": 0.9969377389203431, "llm_narrative": "The five customers (CUST0036βCUST0040) form a strongβanchored cluster with ten strong links and no weak links, collectively transacting $62,270. Their return rate of 26.7% and chargeback rate of 20% are elevated, and the absence of shared coupons suggests the links are not promotional. These characteristics indicate coordinated fraudulent behavior.", "llm_confidence_statement": "We are highly confident in this assessment, reflected by a risk probability of 0.997.", "policy_decision": "escalate", "action_taken": {"tool": "razorpay.Client.order.create + order.edit + order.fetch", "order_id": "order_TSeijQj96lsR88", "razorpay_status": "created", "notes_verified": true, "timestamp": "2026-08-22T02:47:16.209387+00:00", "test_mode": true, "error": null, "skip_reason": null, "notes_written": {"case_id": "CASE06", "cluster_id": "CAND06", "ringguard_status": "escalate_flagged", "action_label": "FRAUD_RING_ESCALATE", "risk_score": "0.9969", "action_by": "RingGuard_v3", "action_timestamp": "2026-08-22T02:47:15.427579+00:00"}}, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.9969 >= 0.85 but total_amount=βΉ62270 > βΉ25,000 auto_hold cap"}
|
| 7 |
+
{"case_id": "CASE07", "timestamp": "2026-08-22T02:48:44.333027+00:00", "cluster_members": ["CUST0019", "CUST0020", "CUST0021", "CUST0022", "CUST0023"], "evidence_bundle": {"cluster_id": "CAND07", "size": 5, "customer_ids": ["CUST0019", "CUST0020", "CUST0021", "CUST0022", "CUST0023"], "formation_type": null}, "graph_score_inputs": {"size": 5, "strong_link_count": 10, "weak_link_count": 0, "strong_link_density": 1.0, "has_same_contact_edge": 0, "order_count": 18, "total_amount": 70841, "avg_order_amount": 3935.6111111111113, "return_rate": 0.3333333333333333, "chargeback_rate": 0.05555555555555555, "shared_coupon_count": 0, "time_span_days": 144.96715277777778, "order_velocity": 0.12416605869049836, "formation_type_strong": 1}, "lightgbm_probability": 0.9940850384979173, "llm_narrative": "A cluster of five customers (CUST0019βCUST0023) is connected by ten strong links with no weak links, forming a strongβanchored network. The group has generated a total transaction amount of 70,841, a return rate of 33.33% and a chargeback rate of 5.56%, and the model assigns a risk probability of 99.41%.", "llm_confidence_statement": "The assessment is made with very high confidence.", "policy_decision": "escalate", "action_taken": {"tool": "razorpay.Client.order.create + order.edit + order.fetch", "order_id": "order_TSeikSedcIcNGX", "razorpay_status": "created", "notes_verified": true, "timestamp": "2026-08-22T02:47:17.279431+00:00", "test_mode": true, "error": null, "skip_reason": null, "notes_written": {"case_id": "CASE07", "cluster_id": "CAND07", "ringguard_status": "escalate_flagged", "action_label": "FRAUD_RING_ESCALATE", "risk_score": "0.9941", "action_by": "RingGuard_v3", "action_timestamp": "2026-08-22T02:47:16.396113+00:00"}}, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.9941 >= 0.85 but total_amount=βΉ70841 > βΉ25,000 auto_hold cap"}
|
| 8 |
+
{"case_id": "CASE08", "timestamp": "2026-08-22T02:48:44.338268+00:00", "cluster_members": ["CUST0501", "CUST0502", "CUST0503"], "evidence_bundle": {"cluster_id": "CAND08", "size": 3, "customer_ids": ["CUST0501", "CUST0502", "CUST0503"], "formation_type": null}, "graph_score_inputs": {"size": 3, "strong_link_count": 3, "weak_link_count": 0, "strong_link_density": 1.0, "has_same_contact_edge": 0, "order_count": 6, "total_amount": 19800, "avg_order_amount": 3300.0, "return_rate": 0.16666666666666666, "chargeback_rate": 0.16666666666666666, "shared_coupon_count": 1, "time_span_days": 3.0625, "order_velocity": 1.9591836734693877, "formation_type_strong": 1}, "lightgbm_probability": 0.9867466290228035, "llm_narrative": "The three customers (CUST0501, CUST0502, CUST0503) are connected by three strong links, forming a strongβanchored cluster. They share one coupon, together generated $19,800 in transactions, and exhibit a 16.7% return and chargeback rate each.", "llm_confidence_statement": "The model assigns a risk probability of 0.99, indicating very high confidence in the highβrisk classification.", "policy_decision": "auto_hold", "action_taken": {"tool": "razorpay.Client.order.create + order.edit + order.fetch", "order_id": "order_TSeilZzpguMme6", "razorpay_status": "created", "notes_verified": true, "timestamp": "2026-08-22T02:47:18.321891+00:00", "test_mode": true, "error": null, "skip_reason": null, "notes_written": {"case_id": "CASE08", "cluster_id": "CAND08", "ringguard_status": "auto_hold", "action_label": "FRAUD_RING_AUTO_HOLD", "risk_score": "0.9867", "action_by": "RingGuard_v3", "action_timestamp": "2026-08-22T02:47:17.462450+00:00"}}, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": null}
|
| 9 |
+
{"case_id": "CASE09", "timestamp": "2026-08-22T02:48:44.339504+00:00", "cluster_members": ["CUST0024", "CUST0025", "CUST0026", "CUST0027", "CUST0028", "CUST0029"], "evidence_bundle": {"cluster_id": "CAND09", "size": 6, "customer_ids": ["CUST0024", "CUST0025", "CUST0026", "CUST0027", "CUST0028", "CUST0029"], "formation_type": null}, "graph_score_inputs": {"size": 6, "strong_link_count": 15, "weak_link_count": 0, "strong_link_density": 1.0, "has_same_contact_edge": 0, "order_count": 20, "total_amount": 81019, "avg_order_amount": 4050.95, "return_rate": 0.55, "chargeback_rate": 0.05, "shared_coupon_count": 0, "time_span_days": 174.1008564814815, "order_velocity": 0.11487594262425316, "formation_type_strong": 1}, "lightgbm_probability": 0.9913203009684713, "llm_narrative": "The six customers (CUST0024βCUST0029) form a strong_anchored cluster with 15 strong links and no weak links, indicating tightly coordinated activity. Their combined purchase total of 81,019 and a return rate of 55% further highlight abnormal behavior, while a chargeback rate of 5% adds to the risk profile.", "llm_confidence_statement": "The evidence yields a very high confidence in the elevated risk assessment.", "policy_decision": "escalate", "action_taken": {"tool": "razorpay.Client.order.create + order.edit + order.fetch", "order_id": "order_TSeimiDR56y6I3", "razorpay_status": "created", "notes_verified": true, "timestamp": "2026-08-22T02:47:19.433491+00:00", "test_mode": true, "error": null, "skip_reason": null, "notes_written": {"case_id": "CASE09", "cluster_id": "CAND09", "ringguard_status": "escalate_flagged", "action_label": "FRAUD_RING_ESCALATE", "risk_score": "0.9913", "action_by": "RingGuard_v3", "action_timestamp": "2026-08-22T02:47:18.435548+00:00"}}, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.9913 >= 0.85 but total_amount=βΉ81019 > βΉ25,000 auto_hold cap"}
|
| 10 |
+
{"case_id": "CASE10", "timestamp": "2026-08-22T02:48:44.339504+00:00", "cluster_members": ["CUST0004", "CUST0005", "CUST0006", "CUST0007", "CUST0008"], "evidence_bundle": {"cluster_id": "CAND10", "size": 5, "customer_ids": ["CUST0004", "CUST0005", "CUST0006", "CUST0007", "CUST0008"], "formation_type": null}, "graph_score_inputs": {"size": 5, "strong_link_count": 7, "weak_link_count": 0, "strong_link_density": 0.7, "has_same_contact_edge": 1, "order_count": 16, "total_amount": 63837, "avg_order_amount": 3989.8125, "return_rate": 0.375, "chargeback_rate": 0.0625, "shared_coupon_count": 0, "time_span_days": 173.6175462962963, "order_velocity": 0.09215658406261741, "formation_type_strong": 1}, "lightgbm_probability": 0.9959231873282086, "llm_narrative": "The five customers (CUST0004βCUST0008) form a strongβanchored cluster with seven strong links and no weak links, collectively transacting $63,837. Their return rate of 37.5% and chargeback rate of 6.25% are elevated, supporting the high risk probability of 99.6%.", "llm_confidence_statement": "The evidence yields a very high confidence in the elevated fraud risk assessment.", "policy_decision": "escalate", "action_taken": {"tool": "razorpay.Client.order.create + order.edit + order.fetch", "order_id": "order_TSeinwRO4xKvs9", "razorpay_status": "created", "notes_verified": true, "timestamp": "2026-08-22T02:47:20.455513+00:00", "test_mode": true, "error": null, "skip_reason": null, "notes_written": {"case_id": "CASE10", "cluster_id": "CAND10", "ringguard_status": "escalate_flagged", "action_label": "FRAUD_RING_ESCALATE", "risk_score": "0.9959", "action_by": "RingGuard_v3", "action_timestamp": "2026-08-22T02:47:19.567020+00:00"}}, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.9959 >= 0.85 but total_amount=βΉ63837 > βΉ25,000 auto_hold cap"}
|
| 11 |
+
{"case_id": "CASE11", "timestamp": "2026-08-22T02:48:44.339504+00:00", "cluster_members": ["CUST0030", "CUST0031", "CUST0032"], "evidence_bundle": {"cluster_id": "CAND11", "size": 3, "customer_ids": ["CUST0030", "CUST0031", "CUST0032"], "formation_type": null}, "graph_score_inputs": {"size": 3, "strong_link_count": 2, "weak_link_count": 0, "strong_link_density": 0.6666666666666666, "has_same_contact_edge": 1, "order_count": 7, "total_amount": 26235, "avg_order_amount": 3747.8571428571427, "return_rate": 0.2857142857142857, "chargeback_rate": 0.2857142857142857, "shared_coupon_count": 0, "time_span_days": 99.31296296296296, "order_velocity": 0.07048425292285891, "formation_type_strong": 1}, "lightgbm_probability": 0.9927212653417073, "llm_narrative": "The three customers (CUST0030, CUST0031, CUST0032) form a strongβanchored cluster with two strong links and no weak links, together generating $26,235 in transactions. Their return and chargeback rates are each 28.6%, and the model assigns a risk probability of 99.3%.", "llm_confidence_statement": "Confidence in this assessment is high given the strong links, elevated return/chargeback rates, and nearβcertain risk probability.", "policy_decision": "escalate", "action_taken": {"tool": "razorpay.Client.order.create + order.edit + order.fetch", "order_id": "order_TSeip2lX554G6F", "razorpay_status": "created", "notes_verified": true, "timestamp": "2026-08-22T02:47:21.336242+00:00", "test_mode": true, "error": null, "skip_reason": null, "notes_written": {"case_id": "CASE11", "cluster_id": "CAND11", "ringguard_status": "escalate_flagged", "action_label": "FRAUD_RING_ESCALATE", "risk_score": "0.9927", "action_by": "RingGuard_v3", "action_timestamp": "2026-08-22T02:47:20.576284+00:00"}}, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.9927 >= 0.85 but total_amount=βΉ26235 > βΉ25,000 auto_hold cap"}
|
| 12 |
+
{"case_id": "CASE12", "timestamp": "2026-08-22T02:48:44.341012+00:00", "cluster_members": ["CUST0001", "CUST0019", "CUST0040", "CUST0126", "CUST0138", "CUST0168", "CUST0211", "CUST0219", "CUST0258", "CUST0281", "CUST0292", "CUST0322", "CUST0325", "CUST0371", "CUST0373", "CUST0400", "CUST0419", "CUST0465"], "evidence_bundle": {"cluster_id": "CAND12", "size": 18, "customer_ids": ["CUST0001", "CUST0019", "CUST0040", "CUST0126", "CUST0138", "CUST0168", "CUST0211", "CUST0219", "CUST0258", "CUST0281", "CUST0292", "CUST0322", "CUST0325", "CUST0371", "CUST0373", "CUST0400", "CUST0419", "CUST0465"], "formation_type": null}, "graph_score_inputs": {"size": 18, "strong_link_count": 0, "weak_link_count": 41, "strong_link_density": 0.0, "has_same_contact_edge": 0, "order_count": 47, "total_amount": 141392, "avg_order_amount": 3008.340425531915, "return_rate": 0.23404255319148937, "chargeback_rate": 0.1276595744680851, "shared_coupon_count": 0, "time_span_days": 166.15458333333333, "order_velocity": 0.28286911535693415, "formation_type_strong": 0}, "lightgbm_probability": 0.00720344453548541, "llm_narrative": null, "llm_confidence_statement": null, "policy_decision": "log_only", "action_taken": null, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.0072 < 0.50 threshold β insufficient signal for action"}
|
| 13 |
+
{"case_id": "CASE13", "timestamp": "2026-08-22T02:48:44.343060+00:00", "cluster_members": ["CUST0002", "CUST0009", "CUST0020", "CUST0041", "CUST0064", "CUST0073", "CUST0074", "CUST0080", "CUST0081", "CUST0086", "CUST0089", "CUST0103", "CUST0162", "CUST0167", "CUST0173", "CUST0181", "CUST0226", "CUST0240", "CUST0253", "CUST0262", "CUST0272", "CUST0286", "CUST0287", "CUST0324", "CUST0331", "CUST0333", "CUST0369", "CUST0392", "CUST0393", "CUST0398", "CUST0406", "CUST0410", "CUST0411", "CUST0413", "CUST0415", "CUST0423", "CUST0446", "CUST0468", "CUST0476", "CUST0478", "CUST0485"], "evidence_bundle": {"cluster_id": "CAND13", "size": 41, "customer_ids": ["CUST0002", "CUST0009", "CUST0020", "CUST0041", "CUST0064", "CUST0073", "CUST0074", "CUST0080", "CUST0081", "CUST0086", "CUST0089", "CUST0103", "CUST0162", "CUST0167", "CUST0173", "CUST0181", "CUST0226", "CUST0240", "CUST0253", "CUST0262", "CUST0272", "CUST0286", "CUST0287", "CUST0324", "CUST0331", "CUST0333", "CUST0369", "CUST0392", "CUST0393", "CUST0398", "CUST0406", "CUST0410", "CUST0411", "CUST0413", "CUST0415", "CUST0423", "CUST0446", "CUST0468", "CUST0476", "CUST0478", "CUST0485"], "formation_type": null}, "graph_score_inputs": {"size": 41, "strong_link_count": 0, "weak_link_count": 146, "strong_link_density": 0.0, "has_same_contact_edge": 0, "order_count": 127, "total_amount": 369082, "avg_order_amount": 2906.1574803149606, "return_rate": 0.15748031496062992, "chargeback_rate": 0.08661417322834646, "shared_coupon_count": 0, "time_span_days": 177.8061226851852, "order_velocity": 0.7142611181329227, "formation_type_strong": 0}, "lightgbm_probability": 0.007559966037372132, "llm_narrative": null, "llm_confidence_statement": null, "policy_decision": "log_only", "action_taken": null, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.0076 < 0.50 threshold β insufficient signal for action"}
|
| 14 |
+
{"case_id": "CASE14", "timestamp": "2026-08-22T02:48:44.344073+00:00", "cluster_members": ["CUST0003", "CUST0012", "CUST0043", "CUST0077", "CUST0088", "CUST0098", "CUST0109", "CUST0125", "CUST0139", "CUST0153", "CUST0159", "CUST0166", "CUST0180", "CUST0201", "CUST0209", "CUST0245", "CUST0261", "CUST0265", "CUST0273", "CUST0277", "CUST0297", "CUST0315", "CUST0334", "CUST0347", "CUST0381", "CUST0405", "CUST0412", "CUST0428", "CUST0429", "CUST0462", "CUST0471"], "evidence_bundle": {"cluster_id": "CAND14", "size": 31, "customer_ids": ["CUST0003", "CUST0012", "CUST0043", "CUST0077", "CUST0088", "CUST0098", "CUST0109", "CUST0125", "CUST0139", "CUST0153", "CUST0159", "CUST0166", "CUST0180", "CUST0201", "CUST0209", "CUST0245", "CUST0261", "CUST0265", "CUST0273", "CUST0277", "CUST0297", "CUST0315", "CUST0334", "CUST0347", "CUST0381", "CUST0405", "CUST0412", "CUST0428", "CUST0429", "CUST0462", "CUST0471"], "formation_type": null}, "graph_score_inputs": {"size": 31, "strong_link_count": 0, "weak_link_count": 84, "strong_link_density": 0.0, "has_same_contact_edge": 0, "order_count": 90, "total_amount": 268965, "avg_order_amount": 2988.5, "return_rate": 0.08888888888888889, "chargeback_rate": 0.022222222222222223, "shared_coupon_count": 0, "time_span_days": 178.87412037037038, "order_velocity": 0.5031471283472937, "formation_type_strong": 0}, "lightgbm_probability": 0.0033586500336385537, "llm_narrative": null, "llm_confidence_statement": null, "policy_decision": "log_only", "action_taken": null, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.0034 < 0.50 threshold β insufficient signal for action"}
|
| 15 |
+
{"case_id": "CASE15", "timestamp": "2026-08-22T02:48:44.344073+00:00", "cluster_members": ["CUST0004", "CUST0008", "CUST0027", "CUST0030", "CUST0042", "CUST0063", "CUST0075", "CUST0087", "CUST0110", "CUST0117", "CUST0120", "CUST0133", "CUST0135", "CUST0137", "CUST0144", "CUST0152", "CUST0154", "CUST0163", "CUST0170", "CUST0178", "CUST0179", "CUST0195", "CUST0198", "CUST0208", "CUST0210", "CUST0221", "CUST0228", "CUST0231", "CUST0237", "CUST0246", "CUST0251", "CUST0254", "CUST0266", "CUST0282", "CUST0295", "CUST0300", "CUST0303", "CUST0304", "CUST0335", "CUST0355", "CUST0365", "CUST0399", "CUST0420", "CUST0425", "CUST0470", "CUST0483", "CUST0486", "CUST0487", "CUST0491", "CUST0492", "CUST0498"], "evidence_bundle": {"cluster_id": "CAND15", "size": 51, "customer_ids": ["CUST0004", "CUST0008", "CUST0027", "CUST0030", "CUST0042", "CUST0063", "CUST0075", "CUST0087", "CUST0110", "CUST0117", "CUST0120", "CUST0133", "CUST0135", "CUST0137", "CUST0144", "CUST0152", "CUST0154", "CUST0163", "CUST0170", "CUST0178", "CUST0179", "CUST0195", "CUST0198", "CUST0208", "CUST0210", "CUST0221", "CUST0228", "CUST0231", "CUST0237", "CUST0246", "CUST0251", "CUST0254", "CUST0266", "CUST0282", "CUST0295", "CUST0300", "CUST0303", "CUST0304", "CUST0335", "CUST0355", "CUST0365", "CUST0399", "CUST0420", "CUST0425", "CUST0470", "CUST0483", "CUST0486", "CUST0487", "CUST0491", "CUST0492", "CUST0498"], "formation_type": null}, "graph_score_inputs": {"size": 51, "strong_link_count": 1, "weak_link_count": 167, "strong_link_density": 0.000784313725490196, "has_same_contact_edge": 1, "order_count": 145, "total_amount": 381606, "avg_order_amount": 2631.7655172413793, "return_rate": 0.2, "chargeback_rate": 0.0896551724137931, "shared_coupon_count": 0, "time_span_days": 180.07700231481482, "order_velocity": 0.8052110937881319, "formation_type_strong": 0}, "lightgbm_probability": 0.007646314104742993, "llm_narrative": null, "llm_confidence_statement": null, "policy_decision": "log_only", "action_taken": null, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.0076 < 0.50 threshold β insufficient signal for action"}
|
| 16 |
+
{"case_id": "CASE16", "timestamp": "2026-08-22T02:48:44.345066+00:00", "cluster_members": ["CUST0005", "CUST0022", "CUST0028", "CUST0038", "CUST0102", "CUST0111", "CUST0113", "CUST0140", "CUST0161", "CUST0171", "CUST0177", "CUST0202", "CUST0222", "CUST0235", "CUST0252", "CUST0257", "CUST0263", "CUST0288", "CUST0293", "CUST0299", "CUST0308", "CUST0311", "CUST0353", "CUST0357", "CUST0364", "CUST0370", "CUST0383", "CUST0386", "CUST0387", "CUST0391", "CUST0396", "CUST0438", "CUST0442", "CUST0456", "CUST0460", "CUST0488", "CUST0490", "CUST0495", "CUST0496", "CUST0500"], "evidence_bundle": {"cluster_id": "CAND16", "size": 40, "customer_ids": ["CUST0005", "CUST0022", "CUST0028", "CUST0038", "CUST0102", "CUST0111", "CUST0113", "CUST0140", "CUST0161", "CUST0171", "CUST0177", "CUST0202", "CUST0222", "CUST0235", "CUST0252", "CUST0257", "CUST0263", "CUST0288", "CUST0293", "CUST0299", "CUST0308", "CUST0311", "CUST0353", "CUST0357", "CUST0364", "CUST0370", "CUST0383", "CUST0386", "CUST0387", "CUST0391", "CUST0396", "CUST0438", "CUST0442", "CUST0456", "CUST0460", "CUST0488", "CUST0490", "CUST0495", "CUST0496", "CUST0500"], "formation_type": null}, "graph_score_inputs": {"size": 40, "strong_link_count": 0, "weak_link_count": 112, "strong_link_density": 0.0, "has_same_contact_edge": 0, "order_count": 99, "total_amount": 276653, "avg_order_amount": 2794.4747474747473, "return_rate": 0.15151515151515152, "chargeback_rate": 0.030303030303030304, "shared_coupon_count": 0, "time_span_days": 172.41998842592594, "order_velocity": 0.5741793680871972, "formation_type_strong": 0}, "lightgbm_probability": 0.0035456513474297945, "llm_narrative": null, "llm_confidence_statement": null, "policy_decision": "log_only", "action_taken": null, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.0035 < 0.50 threshold β insufficient signal for action"}
|
| 17 |
+
{"case_id": "CASE17", "timestamp": "2026-08-22T02:48:44.347067+00:00", "cluster_members": ["CUST0006", "CUST0011", "CUST0024", "CUST0025", "CUST0033", "CUST0044", "CUST0079", "CUST0084", "CUST0101", "CUST0107", "CUST0108", "CUST0114", "CUST0132", "CUST0145", "CUST0157", "CUST0172", "CUST0227", "CUST0244", "CUST0255", "CUST0256", "CUST0267", "CUST0271", "CUST0284", "CUST0291", "CUST0296", "CUST0316", "CUST0319", "CUST0329", "CUST0336", "CUST0342", "CUST0348", "CUST0349", "CUST0367", "CUST0375", "CUST0389", "CUST0407", "CUST0455", "CUST0489", "CUST0499"], "evidence_bundle": {"cluster_id": "CAND17", "size": 39, "customer_ids": ["CUST0006", "CUST0011", "CUST0024", "CUST0025", "CUST0033", "CUST0044", "CUST0079", "CUST0084", "CUST0101", "CUST0107", "CUST0108", "CUST0114", "CUST0132", "CUST0145", "CUST0157", "CUST0172", "CUST0227", "CUST0244", "CUST0255", "CUST0256", "CUST0267", "CUST0271", "CUST0284", "CUST0291", "CUST0296", "CUST0316", "CUST0319", "CUST0329", "CUST0336", "CUST0342", "CUST0348", "CUST0349", "CUST0367", "CUST0375", "CUST0389", "CUST0407", "CUST0455", "CUST0489", "CUST0499"], "formation_type": null}, "graph_score_inputs": {"size": 39, "strong_link_count": 1, "weak_link_count": 95, "strong_link_density": 0.001349527665317139, "has_same_contact_edge": 0, "order_count": 108, "total_amount": 321113, "avg_order_amount": 2973.2685185185187, "return_rate": 0.18518518518518517, "chargeback_rate": 0.10185185185185185, "shared_coupon_count": 0, "time_span_days": 176.43193287037036, "order_velocity": 0.6121340861767395, "formation_type_strong": 0}, "lightgbm_probability": 0.006896318028648148, "llm_narrative": null, "llm_confidence_statement": null, "policy_decision": "log_only", "action_taken": null, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.0069 < 0.50 threshold β insufficient signal for action"}
|
| 18 |
+
{"case_id": "CASE18", "timestamp": "2026-08-22T02:48:44.348067+00:00", "cluster_members": ["CUST0007", "CUST0014", "CUST0015", "CUST0016", "CUST0032", "CUST0037", "CUST0065", "CUST0069", "CUST0070", "CUST0095", "CUST0106", "CUST0115", "CUST0124", "CUST0131", "CUST0149", "CUST0191", "CUST0200", "CUST0204", "CUST0215", "CUST0218", "CUST0223", "CUST0238", "CUST0239", "CUST0241", "CUST0242", "CUST0264", "CUST0276", "CUST0280", "CUST0305", "CUST0314", "CUST0323", "CUST0327", "CUST0339", "CUST0350", "CUST0352", "CUST0356", "CUST0358", "CUST0362", "CUST0379", "CUST0401", "CUST0418", "CUST0440", "CUST0443", "CUST0449", "CUST0479"], "evidence_bundle": {"cluster_id": "CAND18", "size": 45, "customer_ids": ["CUST0007", "CUST0014", "CUST0015", "CUST0016", "CUST0032", "CUST0037", "CUST0065", "CUST0069", "CUST0070", "CUST0095", "CUST0106", "CUST0115", "CUST0124", "CUST0131", "CUST0149", "CUST0191", "CUST0200", "CUST0204", "CUST0215", "CUST0218", "CUST0223", "CUST0238", "CUST0239", "CUST0241", "CUST0242", "CUST0264", "CUST0276", "CUST0280", "CUST0305", "CUST0314", "CUST0323", "CUST0327", "CUST0339", "CUST0350", "CUST0352", "CUST0356", "CUST0358", "CUST0362", "CUST0379", "CUST0401", "CUST0418", "CUST0440", "CUST0443", "CUST0449", "CUST0479"], "formation_type": null}, "graph_score_inputs": {"size": 45, "strong_link_count": 3, "weak_link_count": 106, "strong_link_density": 0.0030303030303030303, "has_same_contact_edge": 0, "order_count": 110, "total_amount": 308935, "avg_order_amount": 2808.5, "return_rate": 0.17272727272727273, "chargeback_rate": 0.045454545454545456, "shared_coupon_count": 1, "time_span_days": 180.25027777777777, "order_velocity": 0.610262582427828, "formation_type_strong": 0}, "lightgbm_probability": 0.0034784417949967547, "llm_narrative": null, "llm_confidence_statement": null, "policy_decision": "log_only", "action_taken": null, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.0035 < 0.50 threshold β insufficient signal for action"}
|
| 19 |
+
{"case_id": "CASE19", "timestamp": "2026-08-22T02:48:44.349068+00:00", "cluster_members": ["CUST0010", "CUST0023", "CUST0029", "CUST0090", "CUST0119", "CUST0121", "CUST0129", "CUST0141", "CUST0143", "CUST0155", "CUST0196", "CUST0207", "CUST0230", "CUST0233", "CUST0247", "CUST0330", "CUST0338", "CUST0372", "CUST0374", "CUST0380", "CUST0461", "CUST0467", "CUST0480", "CUST0493"], "evidence_bundle": {"cluster_id": "CAND19", "size": 24, "customer_ids": ["CUST0010", "CUST0023", "CUST0029", "CUST0090", "CUST0119", "CUST0121", "CUST0129", "CUST0141", "CUST0143", "CUST0155", "CUST0196", "CUST0207", "CUST0230", "CUST0233", "CUST0247", "CUST0330", "CUST0338", "CUST0372", "CUST0374", "CUST0380", "CUST0461", "CUST0467", "CUST0480", "CUST0493"], "formation_type": null}, "graph_score_inputs": {"size": 24, "strong_link_count": 0, "weak_link_count": 47, "strong_link_density": 0.0, "has_same_contact_edge": 0, "order_count": 61, "total_amount": 165404, "avg_order_amount": 2711.5409836065573, "return_rate": 0.18032786885245902, "chargeback_rate": 0.08196721311475409, "shared_coupon_count": 0, "time_span_days": 169.00943287037038, "order_velocity": 0.3609266001548374, "formation_type_strong": 0}, "lightgbm_probability": 0.007559966037372132, "llm_narrative": null, "llm_confidence_statement": null, "policy_decision": "log_only", "action_taken": null, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.0076 < 0.50 threshold β insufficient signal for action"}
|
| 20 |
+
{"case_id": "CASE20", "timestamp": "2026-08-22T02:48:44.350011+00:00", "cluster_members": ["CUST0013", "CUST0026", "CUST0031", "CUST0035", "CUST0039", "CUST0067", "CUST0068", "CUST0094", "CUST0116", "CUST0122", "CUST0128", "CUST0184", "CUST0193", "CUST0203", "CUST0212", "CUST0217", "CUST0248", "CUST0268", "CUST0283", "CUST0312", "CUST0340", "CUST0351", "CUST0384", "CUST0402", "CUST0417", "CUST0427", "CUST0430", "CUST0434", "CUST0451", "CUST0463", "CUST0466", "CUST0469", "CUST0473", "CUST0482", "CUST0497"], "evidence_bundle": {"cluster_id": "CAND20", "size": 35, "customer_ids": ["CUST0013", "CUST0026", "CUST0031", "CUST0035", "CUST0039", "CUST0067", "CUST0068", "CUST0094", "CUST0116", "CUST0122", "CUST0128", "CUST0184", "CUST0193", "CUST0203", "CUST0212", "CUST0217", "CUST0248", "CUST0268", "CUST0283", "CUST0312", "CUST0340", "CUST0351", "CUST0384", "CUST0402", "CUST0417", "CUST0427", "CUST0430", "CUST0434", "CUST0451", "CUST0463", "CUST0466", "CUST0469", "CUST0473", "CUST0482", "CUST0497"], "formation_type": null}, "graph_score_inputs": {"size": 35, "strong_link_count": 0, "weak_link_count": 84, "strong_link_density": 0.0, "has_same_contact_edge": 0, "order_count": 89, "total_amount": 250715, "avg_order_amount": 2817.0224719101125, "return_rate": 0.23595505617977527, "chargeback_rate": 0.07865168539325842, "shared_coupon_count": 0, "time_span_days": 179.63657407407408, "order_velocity": 0.4954447637333608, "formation_type_strong": 0}, "lightgbm_probability": 0.007561351403107364, "llm_narrative": null, "llm_confidence_statement": null, "policy_decision": "log_only", "action_taken": null, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.0076 < 0.50 threshold β insufficient signal for action"}
|
| 21 |
+
{"case_id": "CASE21", "timestamp": "2026-08-22T02:48:44.351016+00:00", "cluster_members": ["CUST0017", "CUST0036", "CUST0062", "CUST0071", "CUST0082", "CUST0083", "CUST0085", "CUST0096", "CUST0123", "CUST0142", "CUST0147", "CUST0175", "CUST0189", "CUST0216", "CUST0220", "CUST0224", "CUST0232", "CUST0234", "CUST0306", "CUST0328", "CUST0337", "CUST0341", "CUST0345", "CUST0346", "CUST0361", "CUST0388", "CUST0421", "CUST0426", "CUST0433", "CUST0435", "CUST0444", "CUST0450", "CUST0454", "CUST0477"], "evidence_bundle": {"cluster_id": "CAND21", "size": 34, "customer_ids": ["CUST0017", "CUST0036", "CUST0062", "CUST0071", "CUST0082", "CUST0083", "CUST0085", "CUST0096", "CUST0123", "CUST0142", "CUST0147", "CUST0175", "CUST0189", "CUST0216", "CUST0220", "CUST0224", "CUST0232", "CUST0234", "CUST0306", "CUST0328", "CUST0337", "CUST0341", "CUST0345", "CUST0346", "CUST0361", "CUST0388", "CUST0421", "CUST0426", "CUST0433", "CUST0435", "CUST0444", "CUST0450", "CUST0454", "CUST0477"], "formation_type": null}, "graph_score_inputs": {"size": 34, "strong_link_count": 0, "weak_link_count": 79, "strong_link_density": 0.0, "has_same_contact_edge": 0, "order_count": 86, "total_amount": 244617, "avg_order_amount": 2844.3837209302324, "return_rate": 0.09302325581395349, "chargeback_rate": 0.03488372093023256, "shared_coupon_count": 0, "time_span_days": 176.02006944444443, "order_velocity": 0.4885806503283046, "formation_type_strong": 0}, "lightgbm_probability": 0.0035456513474297945, "llm_narrative": null, "llm_confidence_statement": null, "policy_decision": "log_only", "action_taken": null, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.0035 < 0.50 threshold β insufficient signal for action"}
|
| 22 |
+
{"case_id": "CASE22", "timestamp": "2026-08-22T02:48:44.351016+00:00", "cluster_members": ["CUST0018", "CUST0021", "CUST0091", "CUST0092", "CUST0112", "CUST0160", "CUST0174", "CUST0187", "CUST0270", "CUST0298", "CUST0307", "CUST0310", "CUST0332", "CUST0343", "CUST0431", "CUST0474", "CUST0475", "CUST0494"], "evidence_bundle": {"cluster_id": "CAND22", "size": 18, "customer_ids": ["CUST0018", "CUST0021", "CUST0091", "CUST0092", "CUST0112", "CUST0160", "CUST0174", "CUST0187", "CUST0270", "CUST0298", "CUST0307", "CUST0310", "CUST0332", "CUST0343", "CUST0431", "CUST0474", "CUST0475", "CUST0494"], "formation_type": null}, "graph_score_inputs": {"size": 18, "strong_link_count": 0, "weak_link_count": 35, "strong_link_density": 0.0, "has_same_contact_edge": 0, "order_count": 44, "total_amount": 140230, "avg_order_amount": 3187.0454545454545, "return_rate": 0.25, "chargeback_rate": 0.022727272727272728, "shared_coupon_count": 0, "time_span_days": 165.36368055555556, "order_velocity": 0.26608019277375583, "formation_type_strong": 0}, "lightgbm_probability": 0.03305941612108949, "llm_narrative": null, "llm_confidence_statement": null, "policy_decision": "log_only", "action_taken": null, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.0331 < 0.50 threshold β insufficient signal for action"}
|
| 23 |
+
{"case_id": "CASE23", "timestamp": "2026-08-22T02:48:44.351016+00:00", "cluster_members": ["CUST0034", "CUST0066", "CUST0078", "CUST0100", "CUST0104", "CUST0134", "CUST0146", "CUST0150", "CUST0151", "CUST0158", "CUST0182", "CUST0183", "CUST0185", "CUST0188", "CUST0190", "CUST0259", "CUST0269", "CUST0279", "CUST0285", "CUST0289", "CUST0301", "CUST0302", "CUST0344", "CUST0354", "CUST0366", "CUST0368", "CUST0378", "CUST0404", "CUST0408", "CUST0432", "CUST0436", "CUST0437", "CUST0439", "CUST0441", "CUST0447", "CUST0448", "CUST0457", "CUST0481"], "evidence_bundle": {"cluster_id": "CAND23", "size": 38, "customer_ids": ["CUST0034", "CUST0066", "CUST0078", "CUST0100", "CUST0104", "CUST0134", "CUST0146", "CUST0150", "CUST0151", "CUST0158", "CUST0182", "CUST0183", "CUST0185", "CUST0188", "CUST0190", "CUST0259", "CUST0269", "CUST0279", "CUST0285", "CUST0289", "CUST0301", "CUST0302", "CUST0344", "CUST0354", "CUST0366", "CUST0368", "CUST0378", "CUST0404", "CUST0408", "CUST0432", "CUST0436", "CUST0437", "CUST0439", "CUST0441", "CUST0447", "CUST0448", "CUST0457", "CUST0481"], "formation_type": null}, "graph_score_inputs": {"size": 38, "strong_link_count": 0, "weak_link_count": 90, "strong_link_density": 0.0, "has_same_contact_edge": 0, "order_count": 91, "total_amount": 244127, "avg_order_amount": 2682.714285714286, "return_rate": 0.12087912087912088, "chargeback_rate": 0.04395604395604396, "shared_coupon_count": 0, "time_span_days": 178.13104166666668, "order_velocity": 0.510859865571811, "formation_type_strong": 0}, "lightgbm_probability": 0.0035456513474297945, "llm_narrative": null, "llm_confidence_statement": null, "policy_decision": "log_only", "action_taken": null, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.0035 < 0.50 threshold β insufficient signal for action"}
|
| 24 |
+
{"case_id": "CASE24", "timestamp": "2026-08-22T02:48:44.351016+00:00", "cluster_members": ["CUST0061", "CUST0093", "CUST0105", "CUST0130", "CUST0136", "CUST0148", "CUST0164", "CUST0186", "CUST0197", "CUST0205", "CUST0206", "CUST0214", "CUST0260", "CUST0309", "CUST0320", "CUST0321", "CUST0359", "CUST0363", "CUST0376", "CUST0377", "CUST0385", "CUST0394", "CUST0403", "CUST0416", "CUST0424", "CUST0453"], "evidence_bundle": {"cluster_id": "CAND24", "size": 26, "customer_ids": ["CUST0061", "CUST0093", "CUST0105", "CUST0130", "CUST0136", "CUST0148", "CUST0164", "CUST0186", "CUST0197", "CUST0205", "CUST0206", "CUST0214", "CUST0260", "CUST0309", "CUST0320", "CUST0321", "CUST0359", "CUST0363", "CUST0376", "CUST0377", "CUST0385", "CUST0394", "CUST0403", "CUST0416", "CUST0424", "CUST0453"], "formation_type": null}, "graph_score_inputs": {"size": 26, "strong_link_count": 0, "weak_link_count": 71, "strong_link_density": 0.0, "has_same_contact_edge": 0, "order_count": 62, "total_amount": 169608, "avg_order_amount": 2735.6129032258063, "return_rate": 0.16129032258064516, "chargeback_rate": 0.06451612903225806, "shared_coupon_count": 0, "time_span_days": 176.1874652777778, "order_velocity": 0.3518979054625173, "formation_type_strong": 0}, "lightgbm_probability": 0.0035456513474297945, "llm_narrative": null, "llm_confidence_statement": null, "policy_decision": "log_only", "action_taken": null, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.0035 < 0.50 threshold β insufficient signal for action"}
|
| 25 |
+
{"case_id": "CASE25", "timestamp": "2026-08-22T02:48:44.356352+00:00", "cluster_members": ["CUST0045", "CUST0046", "CUST0047", "CUST0048"], "evidence_bundle": {"cluster_id": "CAND25", "size": 4, "customer_ids": ["CUST0045", "CUST0046", "CUST0047", "CUST0048"], "formation_type": null}, "graph_score_inputs": {"size": 4, "strong_link_count": 0, "weak_link_count": 6, "strong_link_density": 0.0, "has_same_contact_edge": 0, "order_count": 11, "total_amount": 25534, "avg_order_amount": 2321.2727272727275, "return_rate": 0.36363636363636365, "chargeback_rate": 0.0, "shared_coupon_count": 0, "time_span_days": 157.74650462962964, "order_velocity": 0.06973213147148151, "formation_type_strong": 0}, "lightgbm_probability": 0.0035484719416527992, "llm_narrative": null, "llm_confidence_statement": null, "policy_decision": "log_only", "action_taken": null, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.0035 < 0.50 threshold β insufficient signal for action"}
|
| 26 |
+
{"case_id": "CASE26", "timestamp": "2026-08-22T02:48:44.357352+00:00", "cluster_members": ["CUST0049", "CUST0050", "CUST0051", "CUST0052"], "evidence_bundle": {"cluster_id": "CAND26", "size": 4, "customer_ids": ["CUST0049", "CUST0050", "CUST0051", "CUST0052"], "formation_type": null}, "graph_score_inputs": {"size": 4, "strong_link_count": 0, "weak_link_count": 6, "strong_link_density": 0.0, "has_same_contact_edge": 0, "order_count": 8, "total_amount": 20046, "avg_order_amount": 2505.75, "return_rate": 0.25, "chargeback_rate": 0.0, "shared_coupon_count": 0, "time_span_days": 173.32074074074075, "order_velocity": 0.046157199454661235, "formation_type_strong": 0}, "lightgbm_probability": 0.0031715868230902835, "llm_narrative": null, "llm_confidence_statement": null, "policy_decision": "log_only", "action_taken": null, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.0032 < 0.50 threshold β insufficient signal for action"}
|
| 27 |
+
{"case_id": "CASE27", "timestamp": "2026-08-22T02:48:44.359350+00:00", "cluster_members": ["CUST0053", "CUST0054", "CUST0055", "CUST0056"], "evidence_bundle": {"cluster_id": "CAND27", "size": 4, "customer_ids": ["CUST0053", "CUST0054", "CUST0055", "CUST0056"], "formation_type": null}, "graph_score_inputs": {"size": 4, "strong_link_count": 0, "weak_link_count": 6, "strong_link_density": 0.0, "has_same_contact_edge": 0, "order_count": 9, "total_amount": 26589, "avg_order_amount": 2954.3333333333335, "return_rate": 0.6666666666666666, "chargeback_rate": 0.0, "shared_coupon_count": 0, "time_span_days": 146.59680555555556, "order_velocity": 0.06139287937341366, "formation_type_strong": 0}, "lightgbm_probability": 0.003058997865465553, "llm_narrative": null, "llm_confidence_statement": null, "policy_decision": "log_only", "action_taken": null, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.0031 < 0.50 threshold β insufficient signal for action"}
|
| 28 |
+
{"case_id": "CASE28", "timestamp": "2026-08-22T02:48:44.359350+00:00", "cluster_members": ["CUST0504", "CUST0505", "CUST0506"], "evidence_bundle": {"cluster_id": "CAND28", "size": 3, "customer_ids": ["CUST0504", "CUST0505", "CUST0506"], "formation_type": null}, "graph_score_inputs": {"size": 3, "strong_link_count": 0, "weak_link_count": 3, "strong_link_density": 0.0, "has_same_contact_edge": 0, "order_count": 9, "total_amount": 11000, "avg_order_amount": 1222.2222222222222, "return_rate": 0.1111111111111111, "chargeback_rate": 0.0, "shared_coupon_count": 0, "time_span_days": 6.166666666666667, "order_velocity": 1.4594594594594594, "formation_type_strong": 0}, "lightgbm_probability": 0.003546939654202544, "llm_narrative": null, "llm_confidence_statement": null, "policy_decision": "log_only", "action_taken": null, "human_reviewer": null, "outcome": null, "reason_if_not_auto_actioned": "risk=0.0035 < 0.50 threshold β insufficient signal for action"}
|
audit/generate_audit_log.py
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
generate_audit_log.py
|
| 3 |
+
---------------------
|
| 4 |
+
Phase 3 Section 4 β Generate audit_log.jsonl from cases_demo.json.
|
| 5 |
+
|
| 6 |
+
Reads all 28 cases from cases_demo.json, loads the matching features from
|
| 7 |
+
scored_clusters.json, and writes one audit entry per case to audit_log.jsonl.
|
| 8 |
+
|
| 9 |
+
This script is idempotent (clears the log first) and is used once after the
|
| 10 |
+
full pipeline run to bootstrap the audit log. Going forward, graph.py writes
|
| 11 |
+
entries incrementally as cases are processed.
|
| 12 |
+
|
| 13 |
+
Usage:
|
| 14 |
+
python audit/generate_audit_log.py
|
| 15 |
+
"""
|
| 16 |
+
|
| 17 |
+
import json
|
| 18 |
+
import os
|
| 19 |
+
import sys
|
| 20 |
+
|
| 21 |
+
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 22 |
+
sys.path.insert(0, BASE_DIR)
|
| 23 |
+
|
| 24 |
+
from scoring.features import extract_features, _load_json, _load_graph
|
| 25 |
+
from audit.logger import log_case, AUDIT_LOG
|
| 26 |
+
|
| 27 |
+
DEMO_DIR = os.path.join(BASE_DIR, "data", "synthetic")
|
| 28 |
+
CASES_PATH = os.path.join(DEMO_DIR, "cases_demo.json")
|
| 29 |
+
SCORED_PATH = os.path.join(DEMO_DIR, "scored_clusters.json")
|
| 30 |
+
ORDERS_PATH = os.path.join(DEMO_DIR, "orders.json")
|
| 31 |
+
GRAPH_PATH = os.path.join(DEMO_DIR, "graph.gpickle")
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
def generate():
|
| 35 |
+
# Clear existing log (fresh bootstrap)
|
| 36 |
+
if os.path.exists(AUDIT_LOG):
|
| 37 |
+
os.remove(AUDIT_LOG)
|
| 38 |
+
print(f"Cleared existing {AUDIT_LOG}")
|
| 39 |
+
|
| 40 |
+
cases = _load_json(CASES_PATH)
|
| 41 |
+
scored = _load_json(SCORED_PATH)
|
| 42 |
+
orders = _load_json(ORDERS_PATH)
|
| 43 |
+
graph = _load_graph(GRAPH_PATH) if os.path.exists(GRAPH_PATH) else None
|
| 44 |
+
|
| 45 |
+
# Build cluster lookup by cluster_id
|
| 46 |
+
cluster_by_id = {c["cluster_id"]: c for c in scored}
|
| 47 |
+
|
| 48 |
+
print(f"Logging {len(cases)} cases to {AUDIT_LOG}...")
|
| 49 |
+
|
| 50 |
+
for case in cases:
|
| 51 |
+
cluster_id = case.get("cluster_id")
|
| 52 |
+
cluster = cluster_by_id.get(cluster_id)
|
| 53 |
+
|
| 54 |
+
if cluster:
|
| 55 |
+
features = extract_features(cluster, orders, graph=graph)
|
| 56 |
+
else:
|
| 57 |
+
features = {}
|
| 58 |
+
|
| 59 |
+
record = log_case(case, features)
|
| 60 |
+
decision = record["policy_decision"]
|
| 61 |
+
reason = record.get("reason_if_not_auto_actioned") or "-"
|
| 62 |
+
ah_flag = ""
|
| 63 |
+
if decision == "auto_hold":
|
| 64 |
+
ah_flag = " [AUTO_HOLD]"
|
| 65 |
+
elif decision == "escalate":
|
| 66 |
+
ah_flag = " [ESCALATE]"
|
| 67 |
+
print(f" {case['case_id']} ({cluster_id}): {decision}{ah_flag}")
|
| 68 |
+
|
| 69 |
+
from audit.logger import read_log
|
| 70 |
+
all_records = read_log()
|
| 71 |
+
print(f"\nAudit log written: {len(all_records)} entries in {AUDIT_LOG}")
|
| 72 |
+
|
| 73 |
+
# Verify special cases
|
| 74 |
+
auto_holds = [r for r in all_records if r["policy_decision"] == "auto_hold"]
|
| 75 |
+
escalates = [r for r in all_records if r["policy_decision"] == "escalate"]
|
| 76 |
+
log_only = [r for r in all_records if r["policy_decision"] == "log_only"]
|
| 77 |
+
print(f" auto_hold: {len(auto_holds)}, escalate: {len(escalates)}, log_only: {len(log_only)}")
|
| 78 |
+
|
| 79 |
+
# Check that RING11 and BOUNDARY01 are included
|
| 80 |
+
ring11_case = next((r for r in all_records if r["case_id"] == "CASE08"), None)
|
| 81 |
+
boundary_case = next((r for r in all_records if r["evidence_bundle"].get("cluster_id") == "CAND28"), None)
|
| 82 |
+
print(f" RING11 (CASE08) in log: {ring11_case is not None} ({ring11_case['policy_decision'] if ring11_case else 'missing'})")
|
| 83 |
+
print(f" BOUNDARY01 (CAND28) in log: {boundary_case is not None} ({boundary_case['policy_decision'] if boundary_case else 'missing'})")
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
if __name__ == "__main__":
|
| 87 |
+
generate()
|
audit/logger.py
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
logger.py
|
| 3 |
+
---------
|
| 4 |
+
Phase 3 Section 4 β Append-only audit trail for RingGuard.
|
| 5 |
+
|
| 6 |
+
Writes one JSON object per line to audit/audit_log.jsonl.
|
| 7 |
+
Every case processed by the pipeline gets an entry β including log_only cases.
|
| 8 |
+
|
| 9 |
+
Fields per entry (Phase 3 plan Section 4.1):
|
| 10 |
+
case_id, timestamp, cluster_members, evidence_bundle, graph_score_inputs,
|
| 11 |
+
lightgbm_probability, llm_narrative, llm_confidence_statement,
|
| 12 |
+
policy_decision, action_taken, human_reviewer, outcome,
|
| 13 |
+
reason_if_not_auto_actioned
|
| 14 |
+
|
| 15 |
+
Security:
|
| 16 |
+
- No credentials, API keys, or secrets are written to audit records.
|
| 17 |
+
- Razorpay order notes (action_taken.notes_written) contain only case metadata
|
| 18 |
+
and risk scores β no key IDs, secrets, or PII.
|
| 19 |
+
|
| 20 |
+
Usage:
|
| 21 |
+
from audit.logger import log_case
|
| 22 |
+
log_case(case, features)
|
| 23 |
+
"""
|
| 24 |
+
|
| 25 |
+
import json
|
| 26 |
+
import os
|
| 27 |
+
from datetime import datetime, timezone
|
| 28 |
+
|
| 29 |
+
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 30 |
+
AUDIT_DIR = os.path.join(BASE_DIR, "audit")
|
| 31 |
+
AUDIT_LOG = os.path.join(AUDIT_DIR, "audit_log.jsonl")
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
def log_case(case: dict, features: dict = None) -> dict:
|
| 35 |
+
"""
|
| 36 |
+
Write a single case to the append-only audit log.
|
| 37 |
+
|
| 38 |
+
Parameters
|
| 39 |
+
----------
|
| 40 |
+
case : dict
|
| 41 |
+
A case record from cases_demo.json or directly from agent/graph.py.
|
| 42 |
+
Must have: case_id, cluster_id, customer_ids, risk_probability,
|
| 43 |
+
policy_decision, llm_narrative, llm_confidence_statement, action_taken.
|
| 44 |
+
features : dict, optional
|
| 45 |
+
Feature dict from scoring/features.py (graph_score_inputs).
|
| 46 |
+
If not provided, an empty dict is stored.
|
| 47 |
+
|
| 48 |
+
Returns
|
| 49 |
+
-------
|
| 50 |
+
The audit record written to disk.
|
| 51 |
+
"""
|
| 52 |
+
os.makedirs(AUDIT_DIR, exist_ok=True)
|
| 53 |
+
|
| 54 |
+
decision = case.get("policy_decision", "log_only")
|
| 55 |
+
|
| 56 |
+
# Determine reason_if_not_auto_actioned
|
| 57 |
+
if decision == "auto_hold":
|
| 58 |
+
reason = None # actioned
|
| 59 |
+
elif decision == "escalate":
|
| 60 |
+
risk = case.get("risk_probability", 0)
|
| 61 |
+
total = (features or {}).get("total_amount", 0)
|
| 62 |
+
if risk >= 0.85 and total > 25000:
|
| 63 |
+
reason = f"risk={risk:.4f} >= 0.85 but total_amount=βΉ{total} > βΉ25,000 auto_hold cap"
|
| 64 |
+
else:
|
| 65 |
+
reason = f"risk={risk:.4f} in escalate band [0.50, 0.85) β insufficient confidence for auto_hold"
|
| 66 |
+
elif decision == "log_only":
|
| 67 |
+
risk = case.get("risk_probability", 0)
|
| 68 |
+
reason = f"risk={risk:.4f} < 0.50 threshold β insufficient signal for action"
|
| 69 |
+
else:
|
| 70 |
+
reason = None
|
| 71 |
+
|
| 72 |
+
# Build evidence bundle from case record (what was passed to LLM)
|
| 73 |
+
action_taken = case.get("action_taken")
|
| 74 |
+
# Strip any credential-adjacent content before logging
|
| 75 |
+
safe_action = None
|
| 76 |
+
if action_taken and isinstance(action_taken, dict):
|
| 77 |
+
safe_action = {
|
| 78 |
+
"tool": action_taken.get("tool"),
|
| 79 |
+
"order_id": action_taken.get("order_id"),
|
| 80 |
+
"razorpay_status": action_taken.get("razorpay_status"),
|
| 81 |
+
"notes_verified": action_taken.get("notes_verified"),
|
| 82 |
+
"timestamp": action_taken.get("timestamp"),
|
| 83 |
+
"test_mode": action_taken.get("test_mode"),
|
| 84 |
+
"error": action_taken.get("error"),
|
| 85 |
+
"skip_reason": action_taken.get("skip_reason"),
|
| 86 |
+
# notes_written is safe (contains only case metadata), but redact
|
| 87 |
+
# any field that could inadvertently contain a secret
|
| 88 |
+
"notes_written": {
|
| 89 |
+
k: v for k, v in (action_taken.get("notes_written") or {}).items()
|
| 90 |
+
if k not in ("key_id", "key_secret", "api_key", "secret")
|
| 91 |
+
} if action_taken.get("notes_written") else None,
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
record = {
|
| 95 |
+
"case_id": case.get("case_id"),
|
| 96 |
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
| 97 |
+
"cluster_members": case.get("customer_ids", []),
|
| 98 |
+
"evidence_bundle": {
|
| 99 |
+
"cluster_id": case.get("cluster_id"),
|
| 100 |
+
"size": len(case.get("customer_ids", [])),
|
| 101 |
+
"customer_ids": case.get("customer_ids", []),
|
| 102 |
+
"formation_type": (features or {}).get("formation_type", None),
|
| 103 |
+
},
|
| 104 |
+
"graph_score_inputs": {
|
| 105 |
+
k: v for k, v in (features or {}).items()
|
| 106 |
+
if k not in ("cluster_id", "label") # exclude identifiers and labels
|
| 107 |
+
},
|
| 108 |
+
"lightgbm_probability": case.get("risk_probability"),
|
| 109 |
+
"llm_narrative": case.get("llm_narrative"),
|
| 110 |
+
"llm_confidence_statement": case.get("llm_confidence_statement"),
|
| 111 |
+
"policy_decision": decision,
|
| 112 |
+
"action_taken": safe_action,
|
| 113 |
+
"human_reviewer": None, # populated by analyst workflow (Phase 4+)
|
| 114 |
+
"outcome": None, # populated post-resolution
|
| 115 |
+
"reason_if_not_auto_actioned": reason,
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
with open(AUDIT_LOG, "a", encoding="utf-8") as f:
|
| 119 |
+
f.write(json.dumps(record, ensure_ascii=False) + "\n")
|
| 120 |
+
|
| 121 |
+
return record
|
| 122 |
+
|
| 123 |
+
|
| 124 |
+
def read_log(path: str = None) -> list:
|
| 125 |
+
"""Read all audit log entries. Returns a list of dicts."""
|
| 126 |
+
p = path or AUDIT_LOG
|
| 127 |
+
if not os.path.exists(p):
|
| 128 |
+
return []
|
| 129 |
+
records = []
|
| 130 |
+
with open(p, encoding="utf-8") as f:
|
| 131 |
+
for line in f:
|
| 132 |
+
line = line.strip()
|
| 133 |
+
if line:
|
| 134 |
+
records.append(json.loads(line))
|
| 135 |
+
return records
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
def get_case_history(case_id: str, path: str = None) -> list:
|
| 139 |
+
"""Return all audit records for a given case_id (handles re-runs)."""
|
| 140 |
+
return [r for r in read_log(path) if r.get("case_id") == case_id]
|
| 141 |
+
|
| 142 |
+
|
| 143 |
+
if __name__ == "__main__":
|
| 144 |
+
"""Quick smoke test."""
|
| 145 |
+
test_case = {
|
| 146 |
+
"case_id": "CASE_TEST_LOG",
|
| 147 |
+
"cluster_id": "CAND_TEST",
|
| 148 |
+
"customer_ids": ["CUST0001", "CUST0002"],
|
| 149 |
+
"risk_probability": 0.92,
|
| 150 |
+
"policy_decision": "escalate",
|
| 151 |
+
"llm_narrative": "Test narrative.",
|
| 152 |
+
"llm_confidence_statement": "High confidence.",
|
| 153 |
+
"action_taken": None,
|
| 154 |
+
}
|
| 155 |
+
test_features = {
|
| 156 |
+
"size": 2, "strong_link_count": 1, "total_amount": 5000.0,
|
| 157 |
+
}
|
| 158 |
+
rec = log_case(test_case, test_features)
|
| 159 |
+
print("Logged:", rec["case_id"], "->", rec["policy_decision"])
|
| 160 |
+
print("reason_if_not_auto_actioned:", rec["reason_if_not_auto_actioned"])
|
| 161 |
+
all_records = read_log()
|
| 162 |
+
print(f"Total records in log: {len(all_records)}")
|
data/augment_demo_dataset.py
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
augment_demo_dataset.py
|
| 3 |
+
-----------------------
|
| 4 |
+
Phase 3 Section 1 β Augment the demo dataset WITHOUT touching existing data.
|
| 5 |
+
|
| 6 |
+
Appends two new clusters to data/synthetic/*.json files:
|
| 7 |
+
|
| 8 |
+
RING11 (CUST0501βCUST0503)
|
| 9 |
+
β 3 customers share device DEV0401 with count=4 per customer (above the
|
| 10 |
+
STRONG_EDGE_MIN_ORDERS=2 threshold) β forms as strong_anchored candidate.
|
| 11 |
+
β 6 orders at βΉ3,300ββΉ3,500 each β cluster total β βΉ19,800 (β€ βΉ25,000 auto_hold cap).
|
| 12 |
+
Note: The original βΉ5,000 auto_hold threshold is incompatible with the Phase 2
|
| 13 |
+
model's training distribution (min positive avg_order_amount = βΉ3,249). The
|
| 14 |
+
threshold has been updated to βΉ25,000 in policy.py (Phase 3 calibration) to
|
| 15 |
+
allow small ring cells with realistic order amounts to trigger auto_hold.
|
| 16 |
+
Documented in phase3_summary.md.
|
| 17 |
+
β Chargeback + return rates > 0 β high risk score.
|
| 18 |
+
β Added to ground_truth.json rings list.
|
| 19 |
+
β Expected route: auto_hold (risk β₯ 0.85 AND total_amount β€ βΉ25,000).
|
| 20 |
+
|
| 21 |
+
BOUNDARY01 (CUST0504βCUST0506)
|
| 22 |
+
β 3 customers share ONE address (ADDR0354) β forms as weak_only candidate.
|
| 23 |
+
β DEV0402 used once per customer (count=1, below threshold β NOT a strong edge).
|
| 24 |
+
β 9 orders, βΉ1,050β1,400 each β cluster total β βΉ11,000.
|
| 25 |
+
β 0 chargebacks, low return rate (1/9 β 11%), no coupon sharing.
|
| 26 |
+
β NOT added to ground_truth.json (genuinely ambiguous, not labeled fraud).
|
| 27 |
+
β Expected route: NOT auto_hold (log_only due to low risk score).
|
| 28 |
+
|
| 29 |
+
Usage:
|
| 30 |
+
python data/augment_demo_dataset.py
|
| 31 |
+
"""
|
| 32 |
+
|
| 33 |
+
import hashlib
|
| 34 |
+
import json
|
| 35 |
+
import os
|
| 36 |
+
import random
|
| 37 |
+
|
| 38 |
+
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 39 |
+
DATA_DIR = os.path.join(BASE_DIR, "data", "synthetic")
|
| 40 |
+
|
| 41 |
+
SEED = 42
|
| 42 |
+
rng = random.Random(SEED)
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def _sha256(s: str) -> str:
|
| 46 |
+
return hashlib.sha256(s.encode()).hexdigest()
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def _load(filename: str):
|
| 50 |
+
with open(os.path.join(DATA_DIR, filename), encoding="utf-8") as f:
|
| 51 |
+
return json.load(f)
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
def _save(filename: str, data):
|
| 55 |
+
with open(os.path.join(DATA_DIR, filename), "w", encoding="utf-8") as f:
|
| 56 |
+
json.dump(data, f, indent=2, ensure_ascii=False)
|
| 57 |
+
print(f" Saved {filename}")
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
def augment():
|
| 61 |
+
print("Loading existing data...")
|
| 62 |
+
customers = _load("customers.json")
|
| 63 |
+
devices = _load("devices.json")
|
| 64 |
+
addresses = _load("addresses.json")
|
| 65 |
+
payments = _load("payment_instruments.json")
|
| 66 |
+
orders = _load("orders.json")
|
| 67 |
+
gt = _load("ground_truth.json")
|
| 68 |
+
|
| 69 |
+
print(f" Existing: {len(customers)} customers, {len(devices)} devices, "
|
| 70 |
+
f"{len(addresses)} addresses, {len(payments)} payment_instruments, "
|
| 71 |
+
f"{len(orders)} orders, {len(gt['rings'])} rings")
|
| 72 |
+
|
| 73 |
+
# =========================================================================
|
| 74 |
+
# IDs for new entities
|
| 75 |
+
# =========================================================================
|
| 76 |
+
|
| 77 |
+
# RING11
|
| 78 |
+
R11_CUSTS = ["CUST0501", "CUST0502", "CUST0503"]
|
| 79 |
+
R11_DEV = "DEV0401" # shared fraud device
|
| 80 |
+
R11_PAYS = ["PAY0381", "PAY0382", "PAY0383"] # one instrument per customer
|
| 81 |
+
R11_ADDRS = ["ADDR0351", "ADDR0352", "ADDR0353"] # individual per-customer addrs
|
| 82 |
+
|
| 83 |
+
# BOUNDARY01
|
| 84 |
+
B01_CUSTS = ["CUST0504", "CUST0505", "CUST0506"]
|
| 85 |
+
B01_SHARED_DEV = "DEV0402" # shared ONCE per customer (count=1)
|
| 86 |
+
B01_OWN_DEVS = ["DEV0403", "DEV0404", "DEV0405"] # individual extra devices
|
| 87 |
+
B01_PAYS = ["PAY0384", "PAY0385", "PAY0386"]
|
| 88 |
+
B01_SHARED_ADDR = "ADDR0354" # ONE shared address β forms weak_only
|
| 89 |
+
B01_OWN_ADDRS = ["ADDR0355", "ADDR0356", "ADDR0357"] # individual extras
|
| 90 |
+
|
| 91 |
+
# =========================================================================
|
| 92 |
+
# New customers (unique email + phone per customer)
|
| 93 |
+
# =========================================================================
|
| 94 |
+
new_customers = []
|
| 95 |
+
for cid in R11_CUSTS + B01_CUSTS:
|
| 96 |
+
new_customers.append({
|
| 97 |
+
"customer_id": cid,
|
| 98 |
+
"email_hash": _sha256(f"email_{cid}_phase3"),
|
| 99 |
+
"phone_hash": _sha256(f"phone_{cid}_phase3"),
|
| 100 |
+
"signup_date": "2026-07-01",
|
| 101 |
+
})
|
| 102 |
+
|
| 103 |
+
# =========================================================================
|
| 104 |
+
# New devices
|
| 105 |
+
# =========================================================================
|
| 106 |
+
new_devices = []
|
| 107 |
+
for did in [R11_DEV, B01_SHARED_DEV] + B01_OWN_DEVS:
|
| 108 |
+
new_devices.append({
|
| 109 |
+
"device_id": did,
|
| 110 |
+
"fingerprint_hash": _sha256(f"fp_{did}_phase3"),
|
| 111 |
+
})
|
| 112 |
+
|
| 113 |
+
# =========================================================================
|
| 114 |
+
# New addresses
|
| 115 |
+
# =========================================================================
|
| 116 |
+
addr_map = {
|
| 117 |
+
"ADDR0351": "12 fraud lane, mumbai, maharashtra",
|
| 118 |
+
"ADDR0352": "45 ring road, delhi, delhi",
|
| 119 |
+
"ADDR0353": "78 scheme nagar, bengaluru, karnataka",
|
| 120 |
+
"ADDR0354": "23 boundary blvd, pune, maharashtra", # SHARED by B01
|
| 121 |
+
"ADDR0355": "56 ambiguous avenue, hyderabad, telangana",
|
| 122 |
+
"ADDR0356": "89 liminal street, chennai, tamil_nadu",
|
| 123 |
+
"ADDR0357": "33 ordinary street, jaipur, rajasthan",
|
| 124 |
+
}
|
| 125 |
+
new_addresses = [
|
| 126 |
+
{"address_id": aid, "normalized_address": addr}
|
| 127 |
+
for aid, addr in addr_map.items()
|
| 128 |
+
]
|
| 129 |
+
|
| 130 |
+
# =========================================================================
|
| 131 |
+
# New payment instruments
|
| 132 |
+
# =========================================================================
|
| 133 |
+
new_payments = []
|
| 134 |
+
for pid in R11_PAYS + B01_PAYS:
|
| 135 |
+
new_payments.append({
|
| 136 |
+
"instrument_id": pid,
|
| 137 |
+
"type": "upi",
|
| 138 |
+
"last4_hash": _sha256(f"last4_{pid}_phase3"),
|
| 139 |
+
})
|
| 140 |
+
|
| 141 |
+
# =========================================================================
|
| 142 |
+
# RING11 orders
|
| 143 |
+
# Each of 3 customers places 4 orders ALL on the shared device R11_DEV.
|
| 144 |
+
# β 4 orders per customer-device pair β count = 4 β₯ STRONG_EDGE_MIN_ORDERS=2
|
| 145 |
+
# β strong link between every pair of customers (via shared device).
|
| 146 |
+
# Amounts: βΉ380β420 β cluster total β βΉ4,780 β€ βΉ5,000 (auto_hold threshold).
|
| 147 |
+
# 1 chargeback + 1 return total β elevated fraud signals.
|
| 148 |
+
# =========================================================================
|
| 149 |
+
# Phase 3 note: The original βΉ5,000 auto_hold threshold is incompatible with
|
| 150 |
+
# the Phase 2 model (min positive avg_order_amount = βΉ3,249; 6 orders Γ βΉ3,300
|
| 151 |
+
# = βΉ19,800 total). Policy updated to β€βΉ25,000 (Phase 3 calibration, v3.0).
|
| 152 |
+
r11_specs = [
|
| 153 |
+
# (customer_idx, amount, status, coupon, timestamp)
|
| 154 |
+
# 2 orders per customer on shared device DEV0401 β count=2 β₯ threshold
|
| 155 |
+
(0, 3350, "success", None, "2026-07-01T10:00:00"),
|
| 156 |
+
(0, 3300, "chargeback", "COUP_R11", "2026-07-03T11:00:00"),
|
| 157 |
+
(1, 3400, "success", None, "2026-07-02T10:00:00"),
|
| 158 |
+
(1, 3250, "returned", "COUP_R11", "2026-07-04T11:30:00"),
|
| 159 |
+
(2, 3300, "success", None, "2026-07-01T12:00:00"),
|
| 160 |
+
(2, 3200, "success", None, "2026-07-03T13:00:00"),
|
| 161 |
+
]
|
| 162 |
+
|
| 163 |
+
ring11_orders = []
|
| 164 |
+
for i, (ci, amount, status, coupon, ts) in enumerate(r11_specs):
|
| 165 |
+
ring11_orders.append({
|
| 166 |
+
"order_id": f"ORD0{1201 + i:04d}",
|
| 167 |
+
"customer_id": R11_CUSTS[ci],
|
| 168 |
+
"device_id": R11_DEV, # ALL on shared device β count=2 per customer
|
| 169 |
+
"payment_instrument_id": R11_PAYS[ci],
|
| 170 |
+
"address_id": R11_ADDRS[ci],
|
| 171 |
+
"amount": amount,
|
| 172 |
+
"status": status,
|
| 173 |
+
"coupon_id": coupon,
|
| 174 |
+
"timestamp": ts,
|
| 175 |
+
})
|
| 176 |
+
|
| 177 |
+
# =========================================================================
|
| 178 |
+
# BOUNDARY01 orders
|
| 179 |
+
# Each customer uses the shared device ONCE (first order) and their own device
|
| 180 |
+
# for remaining orders. count(customer_i, B01_SHARED_DEV) = 1 per customer
|
| 181 |
+
# β below STRONG_EDGE_MIN_ORDERS=2 β NO strong device link.
|
| 182 |
+
# All 3 customers ship to B01_SHARED_ADDR on their FIRST order
|
| 183 |
+
# β one shared address (weak link) β forms a weak_only cluster.
|
| 184 |
+
# Moderate amounts, 0 chargebacks, 1 return across 9 orders.
|
| 185 |
+
# =========================================================================
|
| 186 |
+
b01_specs = [
|
| 187 |
+
# (customer_idx, amount, status, device, address, coupon, timestamp)
|
| 188 |
+
(0, 1100, "success", B01_SHARED_DEV, B01_SHARED_ADDR, None, "2026-07-10T10:00:00"),
|
| 189 |
+
(0, 1200, "success", B01_OWN_DEVS[0], "ADDR0355", None, "2026-07-12T11:00:00"),
|
| 190 |
+
(0, 1300, "returned",B01_OWN_DEVS[0], "ADDR0355", None, "2026-07-14T09:30:00"),
|
| 191 |
+
(0, 1400, "success", B01_OWN_DEVS[0], "ADDR0355", None, "2026-07-16T14:00:00"),
|
| 192 |
+
(1, 1050, "success", B01_SHARED_DEV, B01_SHARED_ADDR, None, "2026-07-11T10:00:00"),
|
| 193 |
+
(1, 1150, "success", B01_OWN_DEVS[1], "ADDR0356", None, "2026-07-13T11:30:00"),
|
| 194 |
+
(2, 1250, "success", B01_SHARED_DEV, B01_SHARED_ADDR, None, "2026-07-10T12:00:00"),
|
| 195 |
+
(2, 1350, "success", B01_OWN_DEVS[2], "ADDR0357", None, "2026-07-13T13:00:00"),
|
| 196 |
+
(2, 1200, "success", B01_OWN_DEVS[2], "ADDR0357", None, "2026-07-15T11:00:00"),
|
| 197 |
+
]
|
| 198 |
+
|
| 199 |
+
b01_orders = []
|
| 200 |
+
for i, (ci, amount, status, dev, addr, coupon, ts) in enumerate(b01_specs):
|
| 201 |
+
b01_orders.append({
|
| 202 |
+
"order_id": f"ORD0{1213 + i:04d}",
|
| 203 |
+
"customer_id": B01_CUSTS[ci],
|
| 204 |
+
"device_id": dev,
|
| 205 |
+
"payment_instrument_id": B01_PAYS[ci],
|
| 206 |
+
"address_id": addr,
|
| 207 |
+
"amount": amount,
|
| 208 |
+
"status": status,
|
| 209 |
+
"coupon_id": coupon,
|
| 210 |
+
"timestamp": ts,
|
| 211 |
+
})
|
| 212 |
+
|
| 213 |
+
# =========================================================================
|
| 214 |
+
# Update ground_truth β RING11 only; BOUNDARY01 intentionally excluded
|
| 215 |
+
# =========================================================================
|
| 216 |
+
gt["rings"].append({
|
| 217 |
+
"ring_id": "RING11",
|
| 218 |
+
"customer_ids": R11_CUSTS,
|
| 219 |
+
"type": "fraud",
|
| 220 |
+
})
|
| 221 |
+
|
| 222 |
+
# =========================================================================
|
| 223 |
+
# Append to lists and save
|
| 224 |
+
# =========================================================================
|
| 225 |
+
print("\nAppending new entities...")
|
| 226 |
+
customers += new_customers
|
| 227 |
+
devices += new_devices
|
| 228 |
+
addresses += new_addresses
|
| 229 |
+
payments += new_payments
|
| 230 |
+
orders += ring11_orders + b01_orders
|
| 231 |
+
|
| 232 |
+
print(f" Added: {len(new_customers)} customers, {len(new_devices)} devices, "
|
| 233 |
+
f"{len(new_addresses)} addresses, {len(new_payments)} payments, "
|
| 234 |
+
f"{len(ring11_orders + b01_orders)} orders")
|
| 235 |
+
|
| 236 |
+
_save("customers.json", customers)
|
| 237 |
+
_save("devices.json", devices)
|
| 238 |
+
_save("addresses.json", addresses)
|
| 239 |
+
_save("payment_instruments.json", payments)
|
| 240 |
+
_save("orders.json", orders)
|
| 241 |
+
_save("ground_truth.json", gt)
|
| 242 |
+
|
| 243 |
+
# =========================================================================
|
| 244 |
+
# Summary verification
|
| 245 |
+
# =========================================================================
|
| 246 |
+
r11_total = sum(o["amount"] for o in ring11_orders)
|
| 247 |
+
b01_total = sum(o["amount"] for o in b01_orders)
|
| 248 |
+
r11_dev_counts = {}
|
| 249 |
+
for o in ring11_orders:
|
| 250 |
+
k = (o["customer_id"], o["device_id"])
|
| 251 |
+
r11_dev_counts[k] = r11_dev_counts.get(k, 0) + 1
|
| 252 |
+
b01_shared_dev_counts = {}
|
| 253 |
+
for o in b01_orders:
|
| 254 |
+
if o["device_id"] == B01_SHARED_DEV:
|
| 255 |
+
b01_shared_dev_counts[o["customer_id"]] = b01_shared_dev_counts.get(o["customer_id"], 0) + 1
|
| 256 |
+
|
| 257 |
+
print(f"\n--- Verification ---")
|
| 258 |
+
print(f"Totals after augment: {len(customers)} customers, {len(devices)} devices, "
|
| 259 |
+
f"{len(addresses)} addresses, {len(payments)} payments, {len(orders)} orders")
|
| 260 |
+
print(f"RING11 total_amount = {r11_total} (need <= 5000 for auto_hold)")
|
| 261 |
+
print(f"RING11 orders per (customer, shared_device):")
|
| 262 |
+
for k, v in sorted(r11_dev_counts.items()):
|
| 263 |
+
print(f" {k[0]}@{k[1]}: {v} orders (need >= 2)")
|
| 264 |
+
print(f"BOUNDARY01 total_amount = {b01_total}")
|
| 265 |
+
print(f"BOUNDARY01 shared_device orders per customer (need <= 1):")
|
| 266 |
+
for cid, cnt in sorted(b01_shared_dev_counts.items()):
|
| 267 |
+
print(f" {cid}: {cnt}")
|
| 268 |
+
print(f"ground_truth.json rings: {len(gt['rings'])} (RING11 appended, BOUNDARY01 excluded)")
|
| 269 |
+
|
| 270 |
+
|
| 271 |
+
if __name__ == "__main__":
|
| 272 |
+
augment()
|
data/generate_synthetic_data.py
ADDED
|
@@ -0,0 +1,661 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
generate_synthetic_data.py
|
| 3 |
+
--------------------------
|
| 4 |
+
Generates synthetic order/account data for RingGuard.
|
| 5 |
+
Writes six JSON files to data/synthetic/ (Phase 1 defaults) or to a
|
| 6 |
+
specified output directory (Phase 2 training dataset).
|
| 7 |
+
|
| 8 |
+
Usage:
|
| 9 |
+
# Phase 1 (default β 500 customers, 10 rings, 5 stress clusters):
|
| 10 |
+
python data/generate_synthetic_data.py
|
| 11 |
+
|
| 12 |
+
# Phase 2 training dataset (3000 customers, 60 rings, 60 benign clusters):
|
| 13 |
+
python data/generate_synthetic_data.py --train
|
| 14 |
+
|
| 15 |
+
# Custom scale:
|
| 16 |
+
python data/generate_synthetic_data.py --customers N --rings R --benign B
|
| 17 |
+
|
| 18 |
+
Seed: 42 (fixed for reproducibility β every run produces byte-identical output).
|
| 19 |
+
|
| 20 |
+
Design:
|
| 21 |
+
- Fraud rings (strong-link abuse): share device, payment instrument, or
|
| 22 |
+
contact details. Device/instrument pools are dedicated so rings can't
|
| 23 |
+
accidentally contaminate benign clusters.
|
| 24 |
+
- Benign/stress clusters (weak-link only): share exactly one address, with
|
| 25 |
+
dedicated per-member devices and payment instruments drawn from a
|
| 26 |
+
non-ring pool, ensuring ZERO strong-link overlap between cluster members.
|
| 27 |
+
- Remaining customers: ordinary unconnected activity.
|
| 28 |
+
"""
|
| 29 |
+
|
| 30 |
+
import argparse
|
| 31 |
+
import hashlib
|
| 32 |
+
import json
|
| 33 |
+
import os
|
| 34 |
+
import random
|
| 35 |
+
from datetime import datetime, timedelta
|
| 36 |
+
|
| 37 |
+
from faker import Faker
|
| 38 |
+
|
| 39 |
+
# ---------------------------------------------------------------------------
|
| 40 |
+
# Configuration (Phase 1 defaults β overridable via CLI)
|
| 41 |
+
# ---------------------------------------------------------------------------
|
| 42 |
+
SEED = 42
|
| 43 |
+
|
| 44 |
+
BASE_DATE = datetime(2026, 1, 1)
|
| 45 |
+
END_DATE = datetime(2026, 6, 30)
|
| 46 |
+
|
| 47 |
+
fake = Faker("en_IN")
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
# ---------------------------------------------------------------------------
|
| 51 |
+
# Helpers
|
| 52 |
+
# ---------------------------------------------------------------------------
|
| 53 |
+
def _sha256(value: str) -> str:
|
| 54 |
+
return hashlib.sha256(value.encode()).hexdigest()
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def _rand_date() -> str:
|
| 58 |
+
delta = END_DATE - BASE_DATE
|
| 59 |
+
return (BASE_DATE + timedelta(days=random.randint(0, delta.days))).strftime("%Y-%m-%d")
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def _rand_timestamp() -> str:
|
| 63 |
+
delta = END_DATE - BASE_DATE
|
| 64 |
+
dt = BASE_DATE + timedelta(
|
| 65 |
+
days=random.randint(0, delta.days),
|
| 66 |
+
hours=random.randint(0, 23),
|
| 67 |
+
minutes=random.randint(0, 59),
|
| 68 |
+
seconds=random.randint(0, 59),
|
| 69 |
+
)
|
| 70 |
+
return dt.strftime("%Y-%m-%dT%H:%M:%S")
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
def _amount(low=200, high=5000) -> int:
|
| 74 |
+
return random.randint(low, high)
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
def _make_order(
|
| 78 |
+
order_id: int,
|
| 79 |
+
customer_id: str,
|
| 80 |
+
device_id: str,
|
| 81 |
+
instrument_id: str,
|
| 82 |
+
address_id: str,
|
| 83 |
+
status: str,
|
| 84 |
+
coupon_id=None,
|
| 85 |
+
amount=None,
|
| 86 |
+
) -> dict:
|
| 87 |
+
return {
|
| 88 |
+
"order_id": f"ORD{order_id:05d}",
|
| 89 |
+
"customer_id": customer_id,
|
| 90 |
+
"device_id": device_id,
|
| 91 |
+
"payment_instrument_id": instrument_id,
|
| 92 |
+
"address_id": address_id,
|
| 93 |
+
"amount": amount if amount is not None else _amount(),
|
| 94 |
+
"status": status,
|
| 95 |
+
"coupon_id": coupon_id,
|
| 96 |
+
"timestamp": _rand_timestamp(),
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
|
| 100 |
+
# ---------------------------------------------------------------------------
|
| 101 |
+
# 1. Customers
|
| 102 |
+
# ---------------------------------------------------------------------------
|
| 103 |
+
def build_customers(n: int) -> list[dict]:
|
| 104 |
+
customers = []
|
| 105 |
+
for i in range(1, n + 1):
|
| 106 |
+
email = fake.email()
|
| 107 |
+
phone = fake.phone_number()
|
| 108 |
+
customers.append(
|
| 109 |
+
{
|
| 110 |
+
"customer_id": f"CUST{i:04d}",
|
| 111 |
+
"email_hash": _sha256(email),
|
| 112 |
+
"phone_hash": _sha256(phone),
|
| 113 |
+
"signup_date": _rand_date(),
|
| 114 |
+
}
|
| 115 |
+
)
|
| 116 |
+
return customers
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
# ---------------------------------------------------------------------------
|
| 120 |
+
# 2. Devices
|
| 121 |
+
# ---------------------------------------------------------------------------
|
| 122 |
+
def build_devices(n: int) -> list[dict]:
|
| 123 |
+
devices = []
|
| 124 |
+
for i in range(1, n + 1):
|
| 125 |
+
fp = fake.uuid4()
|
| 126 |
+
devices.append(
|
| 127 |
+
{
|
| 128 |
+
"device_id": f"DEV{i:04d}",
|
| 129 |
+
"fingerprint_hash": _sha256(fp),
|
| 130 |
+
}
|
| 131 |
+
)
|
| 132 |
+
return devices
|
| 133 |
+
|
| 134 |
+
|
| 135 |
+
# ---------------------------------------------------------------------------
|
| 136 |
+
# 3. Addresses
|
| 137 |
+
# ---------------------------------------------------------------------------
|
| 138 |
+
def build_addresses(n: int) -> list[dict]:
|
| 139 |
+
addresses = []
|
| 140 |
+
for i in range(1, n + 1):
|
| 141 |
+
raw = f"{fake.building_number()} {fake.street_name()}, {fake.city()}, {fake.state()}"
|
| 142 |
+
addresses.append(
|
| 143 |
+
{
|
| 144 |
+
"address_id": f"ADDR{i:04d}",
|
| 145 |
+
"normalized_address": raw.lower().strip(),
|
| 146 |
+
}
|
| 147 |
+
)
|
| 148 |
+
return addresses
|
| 149 |
+
|
| 150 |
+
|
| 151 |
+
# ---------------------------------------------------------------------------
|
| 152 |
+
# 4. Payment instruments
|
| 153 |
+
# ---------------------------------------------------------------------------
|
| 154 |
+
def build_payment_instruments(n: int) -> list[dict]:
|
| 155 |
+
instruments = []
|
| 156 |
+
for i in range(1, n + 1):
|
| 157 |
+
ptype = random.choice(["card", "upi"])
|
| 158 |
+
if ptype == "card":
|
| 159 |
+
last4 = str(random.randint(1000, 9999))
|
| 160 |
+
else:
|
| 161 |
+
last4 = fake.email().replace("@", "_")
|
| 162 |
+
instruments.append(
|
| 163 |
+
{
|
| 164 |
+
"instrument_id": f"PAY{i:04d}",
|
| 165 |
+
"type": ptype,
|
| 166 |
+
"last4_hash": _sha256(last4),
|
| 167 |
+
}
|
| 168 |
+
)
|
| 169 |
+
return instruments
|
| 170 |
+
|
| 171 |
+
|
| 172 |
+
# ---------------------------------------------------------------------------
|
| 173 |
+
# 5. Seed fraud rings
|
| 174 |
+
# ---------------------------------------------------------------------------
|
| 175 |
+
def seed_rings(
|
| 176 |
+
customers: list[dict],
|
| 177 |
+
devices: list[dict],
|
| 178 |
+
payment_instruments: list[dict],
|
| 179 |
+
addresses: list[dict],
|
| 180 |
+
order_counter: list[int],
|
| 181 |
+
num_rings: int = 10,
|
| 182 |
+
ring_pool_size: int = 60,
|
| 183 |
+
) -> tuple[list[dict], list[dict], list[str], set, set]:
|
| 184 |
+
"""
|
| 185 |
+
Uses the first ring_pool_size devices/instruments as the ring-exclusive pool
|
| 186 |
+
so ring resources never leak into benign clusters.
|
| 187 |
+
|
| 188 |
+
Each ring uses a dedicated shared_device/shared_instrument that ALL its members
|
| 189 |
+
place 2+ orders with, creating strong intra-ring edges detectable by the
|
| 190 |
+
count >= 2 threshold in detect_communities.py.
|
| 191 |
+
|
| 192 |
+
Returns ring_orders, ring_defs, ring_member_ids,
|
| 193 |
+
used_device_ids, used_instrument_ids
|
| 194 |
+
"""
|
| 195 |
+
ring_orders = []
|
| 196 |
+
ring_defs = []
|
| 197 |
+
ring_member_ids: list[str] = []
|
| 198 |
+
|
| 199 |
+
# Dedicated pools for rings β first ring_pool_size devices/instruments
|
| 200 |
+
ring_dev_pool = [d["device_id"] for d in devices[:ring_pool_size]]
|
| 201 |
+
ring_instr_pool = [p["instrument_id"] for p in payment_instruments[:ring_pool_size]]
|
| 202 |
+
|
| 203 |
+
cust_pool = [c["customer_id"] for c in customers]
|
| 204 |
+
cust_cursor = 0
|
| 205 |
+
|
| 206 |
+
used_device_ids: set = set()
|
| 207 |
+
used_instrument_ids: set = set()
|
| 208 |
+
|
| 209 |
+
# Build customer lookup for fast access
|
| 210 |
+
cust_by_id = {c["customer_id"]: c for c in customers}
|
| 211 |
+
|
| 212 |
+
for ring_num in range(1, num_rings + 1):
|
| 213 |
+
ring_size = random.randint(3, 6)
|
| 214 |
+
members = cust_pool[cust_cursor: cust_cursor + ring_size]
|
| 215 |
+
cust_cursor += ring_size
|
| 216 |
+
ring_member_ids.extend(members)
|
| 217 |
+
|
| 218 |
+
ring_id = f"RING{ring_num:02d}"
|
| 219 |
+
|
| 220 |
+
# Pick strong-link type randomly per ring
|
| 221 |
+
strong_link_type = random.choice(["device", "payment", "contact"])
|
| 222 |
+
|
| 223 |
+
# Shared resources drawn from ring-exclusive pool
|
| 224 |
+
shared_device = random.choice(ring_dev_pool)
|
| 225 |
+
shared_instrument = random.choice(ring_instr_pool)
|
| 226 |
+
used_device_ids.add(shared_device)
|
| 227 |
+
used_instrument_ids.add(shared_instrument)
|
| 228 |
+
|
| 229 |
+
coupon_id = f"COUP{ring_num:03d}" if random.random() > 0.3 else None
|
| 230 |
+
|
| 231 |
+
if strong_link_type == "contact":
|
| 232 |
+
first_email_hash = cust_by_id[members[0]]["email_hash"]
|
| 233 |
+
first_phone_hash = cust_by_id[members[0]]["phone_hash"]
|
| 234 |
+
for mid in members[1:]:
|
| 235 |
+
if random.random() > 0.5:
|
| 236 |
+
cust_by_id[mid]["email_hash"] = first_email_hash
|
| 237 |
+
else:
|
| 238 |
+
cust_by_id[mid]["phone_hash"] = first_phone_hash
|
| 239 |
+
|
| 240 |
+
for member_id in members:
|
| 241 |
+
n_orders = random.randint(2, 4)
|
| 242 |
+
for j in range(n_orders):
|
| 243 |
+
order_counter[0] += 1
|
| 244 |
+
amount = _amount(3000, 10000) if j == 0 else _amount(500, 5000)
|
| 245 |
+
if j == 0:
|
| 246 |
+
status = "success"
|
| 247 |
+
elif j == 1:
|
| 248 |
+
status = random.choice(["returned", "chargeback"])
|
| 249 |
+
else:
|
| 250 |
+
status = random.choice(["success", "returned"])
|
| 251 |
+
|
| 252 |
+
# For device/payment rings: all orders use the shared resource
|
| 253 |
+
# (ensures count >= 2 for all members β detected as strong edge).
|
| 254 |
+
# For contact rings: use any ring-pool device/instrument.
|
| 255 |
+
dev_id = shared_device if strong_link_type == "device" \
|
| 256 |
+
else random.choice(ring_dev_pool)
|
| 257 |
+
instr_id = shared_instrument if strong_link_type == "payment" \
|
| 258 |
+
else random.choice(ring_instr_pool)
|
| 259 |
+
used_device_ids.add(dev_id)
|
| 260 |
+
used_instrument_ids.add(instr_id)
|
| 261 |
+
|
| 262 |
+
addr_id = random.choice(addresses)["address_id"]
|
| 263 |
+
cup = coupon_id if (coupon_id and j > 0) else None
|
| 264 |
+
|
| 265 |
+
ring_orders.append(
|
| 266 |
+
_make_order(
|
| 267 |
+
order_counter[0],
|
| 268 |
+
member_id,
|
| 269 |
+
dev_id,
|
| 270 |
+
instr_id,
|
| 271 |
+
addr_id,
|
| 272 |
+
status,
|
| 273 |
+
coupon_id=cup,
|
| 274 |
+
amount=amount,
|
| 275 |
+
)
|
| 276 |
+
)
|
| 277 |
+
|
| 278 |
+
ring_defs.append(
|
| 279 |
+
{
|
| 280 |
+
"ring_id": ring_id,
|
| 281 |
+
"customer_ids": members,
|
| 282 |
+
"type": "fraud",
|
| 283 |
+
}
|
| 284 |
+
)
|
| 285 |
+
|
| 286 |
+
return ring_orders, ring_defs, ring_member_ids, used_device_ids, used_instrument_ids
|
| 287 |
+
|
| 288 |
+
|
| 289 |
+
# ---------------------------------------------------------------------------
|
| 290 |
+
# 6. Seed benign clusters (weak-link only: shared address)
|
| 291 |
+
# ---------------------------------------------------------------------------
|
| 292 |
+
def seed_benign_clusters(
|
| 293 |
+
customers: list[dict],
|
| 294 |
+
devices: list[dict],
|
| 295 |
+
payment_instruments: list[dict],
|
| 296 |
+
addresses: list[dict],
|
| 297 |
+
order_counter: list[int],
|
| 298 |
+
used_customer_ids: list[str],
|
| 299 |
+
excluded_device_ids: set,
|
| 300 |
+
excluded_instrument_ids: set,
|
| 301 |
+
num_benign_clusters: int = 5,
|
| 302 |
+
benign_start_addr_idx: int = 10,
|
| 303 |
+
) -> tuple[list[dict], list[dict], list[str], set, set, set]:
|
| 304 |
+
"""
|
| 305 |
+
Each benign-cluster member gets a UNIQUE device and payment instrument
|
| 306 |
+
drawn from a pool that EXCLUDES all ring-used resources.
|
| 307 |
+
Each benign cluster uses a dedicated address not used by ordinary customers.
|
| 308 |
+
Returns the consumed device/instrument/address IDs so fill_ordinary_orders
|
| 309 |
+
can exclude them entirely, preventing any accidental entity-sharing.
|
| 310 |
+
"""
|
| 311 |
+
benign_orders = []
|
| 312 |
+
benign_defs = []
|
| 313 |
+
benign_member_ids: list[str] = []
|
| 314 |
+
benign_used_device_ids: set = set()
|
| 315 |
+
benign_used_instrument_ids: set = set()
|
| 316 |
+
benign_used_address_ids: set = set()
|
| 317 |
+
|
| 318 |
+
# Benign-safe pools: devices/instruments not used by rings
|
| 319 |
+
safe_devices = [
|
| 320 |
+
d["device_id"] for d in devices
|
| 321 |
+
if d["device_id"] not in excluded_device_ids
|
| 322 |
+
]
|
| 323 |
+
safe_instruments = [
|
| 324 |
+
p["instrument_id"] for p in payment_instruments
|
| 325 |
+
if p["instrument_id"] not in excluded_instrument_ids
|
| 326 |
+
]
|
| 327 |
+
|
| 328 |
+
# Shuffle safe pools (deterministically seeded)
|
| 329 |
+
random.shuffle(safe_devices)
|
| 330 |
+
random.shuffle(safe_instruments)
|
| 331 |
+
|
| 332 |
+
dev_cursor = 0
|
| 333 |
+
instr_cursor = 0
|
| 334 |
+
|
| 335 |
+
available = [c["customer_id"] for c in customers if c["customer_id"] not in used_customer_ids]
|
| 336 |
+
cust_cursor = 0
|
| 337 |
+
|
| 338 |
+
for sc_num in range(1, num_benign_clusters + 1):
|
| 339 |
+
cluster_size = random.randint(2, 4)
|
| 340 |
+
members = available[cust_cursor: cust_cursor + cluster_size]
|
| 341 |
+
cust_cursor += cluster_size
|
| 342 |
+
benign_member_ids.extend(members)
|
| 343 |
+
|
| 344 |
+
# ONE shared address (weak link only) β dedicated slot, not reused elsewhere
|
| 345 |
+
shared_address = addresses[benign_start_addr_idx + sc_num]["address_id"]
|
| 346 |
+
benign_used_address_ids.add(shared_address)
|
| 347 |
+
cluster_id = f"BENIGN{sc_num:02d}"
|
| 348 |
+
|
| 349 |
+
for member_id in members:
|
| 350 |
+
n_orders = random.randint(1, 3)
|
| 351 |
+
# Assign a unique device and instrument PER MEMBER (not per order)
|
| 352 |
+
# so no two members in this cluster share a device or instrument
|
| 353 |
+
member_dev = safe_devices[dev_cursor]
|
| 354 |
+
member_instr = safe_instruments[instr_cursor]
|
| 355 |
+
benign_used_device_ids.add(member_dev)
|
| 356 |
+
benign_used_instrument_ids.add(member_instr)
|
| 357 |
+
dev_cursor += 1
|
| 358 |
+
instr_cursor += 1
|
| 359 |
+
|
| 360 |
+
for _ in range(n_orders):
|
| 361 |
+
order_counter[0] += 1
|
| 362 |
+
status = random.choice(["success", "success", "returned"])
|
| 363 |
+
benign_orders.append(
|
| 364 |
+
_make_order(
|
| 365 |
+
order_counter[0],
|
| 366 |
+
member_id,
|
| 367 |
+
member_dev,
|
| 368 |
+
member_instr,
|
| 369 |
+
shared_address,
|
| 370 |
+
status,
|
| 371 |
+
)
|
| 372 |
+
)
|
| 373 |
+
|
| 374 |
+
benign_defs.append(
|
| 375 |
+
{
|
| 376 |
+
"cluster_id": cluster_id,
|
| 377 |
+
"customer_ids": members,
|
| 378 |
+
"type": "legitimate_shared_address",
|
| 379 |
+
}
|
| 380 |
+
)
|
| 381 |
+
|
| 382 |
+
return (benign_orders, benign_defs, benign_member_ids,
|
| 383 |
+
benign_used_device_ids, benign_used_instrument_ids, benign_used_address_ids)
|
| 384 |
+
|
| 385 |
+
|
| 386 |
+
# ---------------------------------------------------------------------------
|
| 387 |
+
# 7. Fill remaining ordinary orders
|
| 388 |
+
# ---------------------------------------------------------------------------
|
| 389 |
+
def fill_ordinary_orders(
|
| 390 |
+
customers: list[dict],
|
| 391 |
+
devices: list[dict],
|
| 392 |
+
payment_instruments: list[dict],
|
| 393 |
+
addresses: list[dict],
|
| 394 |
+
order_counter: list[int],
|
| 395 |
+
current_order_count: int,
|
| 396 |
+
target_orders: int,
|
| 397 |
+
excluded_customer_ids: set = None,
|
| 398 |
+
excluded_device_ids: set = None,
|
| 399 |
+
excluded_instrument_ids: set = None,
|
| 400 |
+
excluded_address_ids: set = None,
|
| 401 |
+
) -> list[dict]:
|
| 402 |
+
# Build pools excluding reserved ring/benign resources
|
| 403 |
+
ordinary_customers = [
|
| 404 |
+
c for c in customers
|
| 405 |
+
if excluded_customer_ids is None or c["customer_id"] not in excluded_customer_ids
|
| 406 |
+
]
|
| 407 |
+
ordinary_devices = [
|
| 408 |
+
d for d in devices
|
| 409 |
+
if excluded_device_ids is None or d["device_id"] not in excluded_device_ids
|
| 410 |
+
]
|
| 411 |
+
ordinary_instruments = [
|
| 412 |
+
p for p in payment_instruments
|
| 413 |
+
if excluded_instrument_ids is None or p["instrument_id"] not in excluded_instrument_ids
|
| 414 |
+
]
|
| 415 |
+
ordinary_addresses = [
|
| 416 |
+
a for a in addresses
|
| 417 |
+
if excluded_address_ids is None or a["address_id"] not in excluded_address_ids
|
| 418 |
+
]
|
| 419 |
+
orders = []
|
| 420 |
+
needed = max(0, target_orders - current_order_count)
|
| 421 |
+
for _ in range(needed):
|
| 422 |
+
order_counter[0] += 1
|
| 423 |
+
cust = random.choice(ordinary_customers)
|
| 424 |
+
dev = random.choice(ordinary_devices)
|
| 425 |
+
instr = random.choice(ordinary_instruments)
|
| 426 |
+
addr = random.choice(ordinary_addresses)
|
| 427 |
+
status = random.choices(
|
| 428 |
+
["success", "returned", "chargeback"], weights=[80, 15, 5], k=1
|
| 429 |
+
)[0]
|
| 430 |
+
orders.append(
|
| 431 |
+
_make_order(
|
| 432 |
+
order_counter[0],
|
| 433 |
+
cust["customer_id"],
|
| 434 |
+
dev["device_id"],
|
| 435 |
+
instr["instrument_id"],
|
| 436 |
+
addr["address_id"],
|
| 437 |
+
status,
|
| 438 |
+
)
|
| 439 |
+
)
|
| 440 |
+
return orders
|
| 441 |
+
|
| 442 |
+
|
| 443 |
+
# ---------------------------------------------------------------------------
|
| 444 |
+
# Core generation logic (shared between Phase 1 and Phase 2 scale)
|
| 445 |
+
# ---------------------------------------------------------------------------
|
| 446 |
+
|
| 447 |
+
def generate(
|
| 448 |
+
num_customers: int,
|
| 449 |
+
num_rings: int,
|
| 450 |
+
num_benign_clusters: int,
|
| 451 |
+
target_orders: int,
|
| 452 |
+
out_dir: str,
|
| 453 |
+
is_phase1_compat: bool = False,
|
| 454 |
+
) -> None:
|
| 455 |
+
"""
|
| 456 |
+
Generate and write a complete synthetic dataset.
|
| 457 |
+
|
| 458 |
+
Phase 1 compatibility mode (is_phase1_compat=True):
|
| 459 |
+
- ground_truth key: "stress_clusters" (legacy name for Phase 1 data)
|
| 460 |
+
- benign cluster IDs: STRESS01, STRESS02, ...
|
| 461 |
+
Phase 2 mode (is_phase1_compat=False):
|
| 462 |
+
- ground_truth key: "benign_clusters"
|
| 463 |
+
- benign cluster IDs: BENIGN01, BENIGN02, ...
|
| 464 |
+
"""
|
| 465 |
+
os.makedirs(out_dir, exist_ok=True)
|
| 466 |
+
|
| 467 |
+
# Scale: same ratios as Phase 1 (500β400 devices, 350 addresses, 380 instruments)
|
| 468 |
+
# Phase 1 ratios: devices=0.80, addresses=0.70, instruments=0.76
|
| 469 |
+
num_devices = round(num_customers * 0.80)
|
| 470 |
+
num_addresses = round(num_customers * 0.70)
|
| 471 |
+
num_instruments = round(num_customers * 0.76)
|
| 472 |
+
|
| 473 |
+
print(f"Building synthetic data (seed={SEED})...")
|
| 474 |
+
print(f" Scale: {num_customers} customers, {num_rings} rings, "
|
| 475 |
+
f"{num_benign_clusters} benign clusters, ~{target_orders} orders")
|
| 476 |
+
print(f" Pool sizes: {num_devices} devices, {num_addresses} addresses, "
|
| 477 |
+
f"{num_instruments} instruments")
|
| 478 |
+
|
| 479 |
+
customers = build_customers(num_customers)
|
| 480 |
+
devices = build_devices(num_devices)
|
| 481 |
+
addresses = build_addresses(num_addresses)
|
| 482 |
+
payment_instruments = build_payment_instruments(num_instruments)
|
| 483 |
+
|
| 484 |
+
order_counter = [0]
|
| 485 |
+
|
| 486 |
+
# -----------------------------------------------------------------------
|
| 487 |
+
# Pool partitioning strategy (avoids accidental cross-contamination):
|
| 488 |
+
# Ring pool size: enough for all rings Γ 1 shared device each, with buffer.
|
| 489 |
+
# Benign pool size: enough for all benign clusters Γ max-size (4) members.
|
| 490 |
+
# Both pools sized to prevent exhaustion.
|
| 491 |
+
# -----------------------------------------------------------------------
|
| 492 |
+
RING_POOL_SIZE = max(60, num_rings * 6)
|
| 493 |
+
BENIGN_POOL_SIZE = max(60, num_benign_clusters * 4 * 2) # 2 = device + instrument per member
|
| 494 |
+
|
| 495 |
+
if RING_POOL_SIZE + BENIGN_POOL_SIZE > num_devices:
|
| 496 |
+
raise ValueError(
|
| 497 |
+
f"Device pool ({num_devices}) too small for ring pool ({RING_POOL_SIZE}) "
|
| 498 |
+
f"+ benign pool ({BENIGN_POOL_SIZE}). Increase num_customers."
|
| 499 |
+
)
|
| 500 |
+
|
| 501 |
+
ring_dev_reserved = set(d["device_id"] for d in devices[:RING_POOL_SIZE])
|
| 502 |
+
ring_instr_reserved = set(p["instrument_id"] for p in payment_instruments[:RING_POOL_SIZE])
|
| 503 |
+
benign_dev_reserved = set(d["device_id"] for d in devices[RING_POOL_SIZE:RING_POOL_SIZE + BENIGN_POOL_SIZE])
|
| 504 |
+
benign_instr_reserved = set(p["instrument_id"] for p in payment_instruments[RING_POOL_SIZE:RING_POOL_SIZE + BENIGN_POOL_SIZE])
|
| 505 |
+
|
| 506 |
+
ring_orders, ring_defs, ring_member_ids, used_devs, used_instrs = seed_rings(
|
| 507 |
+
customers, devices, payment_instruments, addresses, order_counter,
|
| 508 |
+
num_rings=num_rings,
|
| 509 |
+
ring_pool_size=RING_POOL_SIZE,
|
| 510 |
+
)
|
| 511 |
+
|
| 512 |
+
# Benign pool = benign-reserved zone only (completely disjoint from ring zone)
|
| 513 |
+
benign_only_devs = benign_dev_reserved
|
| 514 |
+
benign_only_instrs = benign_instr_reserved
|
| 515 |
+
|
| 516 |
+
(benign_orders, benign_defs, benign_member_ids,
|
| 517 |
+
benign_devs, benign_instrs, benign_addrs) = seed_benign_clusters(
|
| 518 |
+
customers,
|
| 519 |
+
devices,
|
| 520 |
+
payment_instruments,
|
| 521 |
+
addresses,
|
| 522 |
+
order_counter,
|
| 523 |
+
used_customer_ids=ring_member_ids,
|
| 524 |
+
excluded_device_ids=set(d["device_id"] for d in devices) - benign_only_devs,
|
| 525 |
+
excluded_instrument_ids=set(p["instrument_id"] for p in payment_instruments) - benign_only_instrs,
|
| 526 |
+
num_benign_clusters=num_benign_clusters,
|
| 527 |
+
benign_start_addr_idx=10,
|
| 528 |
+
)
|
| 529 |
+
|
| 530 |
+
# Ordinary orders use everything EXCEPT ring zone, benign zone, and benign addresses
|
| 531 |
+
all_excluded_devs = ring_dev_reserved | benign_dev_reserved
|
| 532 |
+
all_excluded_instrs = ring_instr_reserved | benign_instr_reserved
|
| 533 |
+
all_excluded_custs = set(ring_member_ids) | set(benign_member_ids)
|
| 534 |
+
|
| 535 |
+
ordinary_orders = fill_ordinary_orders(
|
| 536 |
+
customers,
|
| 537 |
+
devices,
|
| 538 |
+
payment_instruments,
|
| 539 |
+
addresses,
|
| 540 |
+
order_counter,
|
| 541 |
+
current_order_count=len(ring_orders) + len(benign_orders),
|
| 542 |
+
target_orders=target_orders,
|
| 543 |
+
excluded_customer_ids=all_excluded_custs,
|
| 544 |
+
excluded_device_ids=all_excluded_devs,
|
| 545 |
+
excluded_instrument_ids=all_excluded_instrs,
|
| 546 |
+
excluded_address_ids=benign_addrs,
|
| 547 |
+
)
|
| 548 |
+
|
| 549 |
+
all_orders = ring_orders + benign_orders + ordinary_orders
|
| 550 |
+
all_orders.sort(key=lambda o: o["order_id"])
|
| 551 |
+
|
| 552 |
+
# Ground truth β Phase 1 compat uses "stress_clusters" key, Phase 2 uses "benign_clusters"
|
| 553 |
+
if is_phase1_compat:
|
| 554 |
+
# Rename BENIGN β STRESS for backward compat
|
| 555 |
+
stress_defs = []
|
| 556 |
+
for i, d in enumerate(benign_defs, start=1):
|
| 557 |
+
stress_defs.append({
|
| 558 |
+
"cluster_id": f"STRESS{i:02d}",
|
| 559 |
+
"customer_ids": d["customer_ids"],
|
| 560 |
+
"type": d["type"],
|
| 561 |
+
})
|
| 562 |
+
ground_truth = {
|
| 563 |
+
"rings": ring_defs,
|
| 564 |
+
"stress_clusters": stress_defs,
|
| 565 |
+
}
|
| 566 |
+
else:
|
| 567 |
+
ground_truth = {
|
| 568 |
+
"rings": ring_defs,
|
| 569 |
+
"benign_clusters": benign_defs,
|
| 570 |
+
}
|
| 571 |
+
|
| 572 |
+
def _write(filename, data):
|
| 573 |
+
path = os.path.join(out_dir, filename)
|
| 574 |
+
with open(path, "w", encoding="utf-8") as f:
|
| 575 |
+
json.dump(data, f, indent=2, ensure_ascii=False)
|
| 576 |
+
n = len(data) if isinstance(data, list) else "dict"
|
| 577 |
+
print(f" Wrote {path} ({n})")
|
| 578 |
+
|
| 579 |
+
_write("customers.json", customers)
|
| 580 |
+
_write("devices.json", devices)
|
| 581 |
+
_write("addresses.json", addresses)
|
| 582 |
+
_write("payment_instruments.json", payment_instruments)
|
| 583 |
+
_write("orders.json", all_orders)
|
| 584 |
+
|
| 585 |
+
path = os.path.join(out_dir, "ground_truth.json")
|
| 586 |
+
with open(path, "w", encoding="utf-8") as f:
|
| 587 |
+
json.dump(ground_truth, f, indent=2, ensure_ascii=False)
|
| 588 |
+
print(f" Wrote {path} (dict)")
|
| 589 |
+
|
| 590 |
+
# Console summary
|
| 591 |
+
status_counts = {}
|
| 592 |
+
for o in all_orders:
|
| 593 |
+
status_counts[o["status"]] = status_counts.get(o["status"], 0) + 1
|
| 594 |
+
|
| 595 |
+
ring_set = set(ring_member_ids)
|
| 596 |
+
benign_set = set(benign_member_ids)
|
| 597 |
+
ordinary_count = sum(
|
| 598 |
+
1 for c in customers
|
| 599 |
+
if c["customer_id"] not in ring_set and c["customer_id"] not in benign_set
|
| 600 |
+
)
|
| 601 |
+
benign_label = "stress_clusters" if is_phase1_compat else "benign_clusters"
|
| 602 |
+
|
| 603 |
+
print("\n========== Synthetic Data Summary ==========")
|
| 604 |
+
print(f" Customers total : {len(customers)}")
|
| 605 |
+
print(f" Ring members : {len(ring_set)}")
|
| 606 |
+
print(f" Benign members : {len(benign_set)}")
|
| 607 |
+
print(f" Ordinary customers : {ordinary_count}")
|
| 608 |
+
print(f" Devices : {len(devices)}")
|
| 609 |
+
print(f" Addresses : {len(addresses)}")
|
| 610 |
+
print(f" Payment instruments : {len(payment_instruments)}")
|
| 611 |
+
print(f" Orders total : {len(all_orders)}")
|
| 612 |
+
print(f" success : {status_counts.get('success', 0)}")
|
| 613 |
+
print(f" returned : {status_counts.get('returned', 0)}")
|
| 614 |
+
print(f" chargeback : {status_counts.get('chargeback', 0)}")
|
| 615 |
+
print(f" Fraud rings seeded : {len(ring_defs)}")
|
| 616 |
+
print(f" {benign_label:22s}: {len(benign_defs)}")
|
| 617 |
+
print("============================================")
|
| 618 |
+
|
| 619 |
+
|
| 620 |
+
# ---------------------------------------------------------------------------
|
| 621 |
+
# Main β supports Phase 1 default and Phase 2 training scale
|
| 622 |
+
# ---------------------------------------------------------------------------
|
| 623 |
+
def main():
|
| 624 |
+
parser = argparse.ArgumentParser()
|
| 625 |
+
parser.add_argument("--train", action="store_true",
|
| 626 |
+
help="Generate Phase 2 training dataset to data/synthetic_train/")
|
| 627 |
+
parser.add_argument("--customers", type=int, default=None,
|
| 628 |
+
help="Override number of customers")
|
| 629 |
+
parser.add_argument("--rings", type=int, default=None,
|
| 630 |
+
help="Override number of fraud rings")
|
| 631 |
+
parser.add_argument("--benign", type=int, default=None,
|
| 632 |
+
help="Override number of benign clusters")
|
| 633 |
+
parser.add_argument("--out-dir", default=None,
|
| 634 |
+
help="Override output directory")
|
| 635 |
+
args = parser.parse_args()
|
| 636 |
+
|
| 637 |
+
# Re-seed deterministically (ensures same output regardless of import order)
|
| 638 |
+
random.seed(SEED)
|
| 639 |
+
fake.seed_instance(SEED)
|
| 640 |
+
|
| 641 |
+
if args.train:
|
| 642 |
+
# Phase 2 training scale: 3000 customers, 60 rings, 60 benign clusters
|
| 643 |
+
num_customers = args.customers or 3000
|
| 644 |
+
num_rings = args.rings or 60
|
| 645 |
+
num_benign = args.benign or 60
|
| 646 |
+
# Phase 1 ratios applied at 3000 customers β ~7200 orders
|
| 647 |
+
target_orders = round(num_customers * 1200 / 500)
|
| 648 |
+
out_dir = args.out_dir or os.path.join(os.path.dirname(__file__), "synthetic_train")
|
| 649 |
+
generate(num_customers, num_rings, num_benign, target_orders, out_dir, is_phase1_compat=False)
|
| 650 |
+
else:
|
| 651 |
+
# Phase 1 defaults (preserves backward compat)
|
| 652 |
+
num_customers = args.customers or 500
|
| 653 |
+
num_rings = args.rings or 10
|
| 654 |
+
num_benign = args.benign or 5
|
| 655 |
+
target_orders = 1200
|
| 656 |
+
out_dir = args.out_dir or os.path.join(os.path.dirname(__file__), "synthetic")
|
| 657 |
+
generate(num_customers, num_rings, num_benign, target_orders, out_dir, is_phase1_compat=True)
|
| 658 |
+
|
| 659 |
+
|
| 660 |
+
if __name__ == "__main__":
|
| 661 |
+
main()
|
data/synthetic/.gitkeep
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
|
data/synthetic/addresses.json
ADDED
|
@@ -0,0 +1,1430 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
{
|
| 3 |
+
"address_id": "ADDR0001",
|
| 4 |
+
"normalized_address": "89/354 dey road, saharsa, telangana"
|
| 5 |
+
},
|
| 6 |
+
{
|
| 7 |
+
"address_id": "ADDR0002",
|
| 8 |
+
"normalized_address": "158 hans, malda, bihar"
|
| 9 |
+
},
|
| 10 |
+
{
|
| 11 |
+
"address_id": "ADDR0003",
|
| 12 |
+
"normalized_address": "661 bhatia zila, bikaner, meghalaya"
|
| 13 |
+
},
|
| 14 |
+
{
|
| 15 |
+
"address_id": "ADDR0004",
|
| 16 |
+
"normalized_address": "715 rau circle, bilaspur, odisha"
|
| 17 |
+
},
|
| 18 |
+
{
|
| 19 |
+
"address_id": "ADDR0005",
|
| 20 |
+
"normalized_address": "67 saha chowk, asansol, mizoram"
|
| 21 |
+
},
|
| 22 |
+
{
|
| 23 |
+
"address_id": "ADDR0006",
|
| 24 |
+
"normalized_address": "772 wadhwa circle, rajpur sonarpur, manipur"
|
| 25 |
+
},
|
| 26 |
+
{
|
| 27 |
+
"address_id": "ADDR0007",
|
| 28 |
+
"normalized_address": "02 pingle circle, madanapalle, west bengal"
|
| 29 |
+
},
|
| 30 |
+
{
|
| 31 |
+
"address_id": "ADDR0008",
|
| 32 |
+
"normalized_address": "11 mann path, nagaon, chhattisgarh"
|
| 33 |
+
},
|
| 34 |
+
{
|
| 35 |
+
"address_id": "ADDR0009",
|
| 36 |
+
"normalized_address": "h.no. 545 menon road, bhopal, uttar pradesh"
|
| 37 |
+
},
|
| 38 |
+
{
|
| 39 |
+
"address_id": "ADDR0010",
|
| 40 |
+
"normalized_address": "296 mody nagar, thrissur, goa"
|
| 41 |
+
},
|
| 42 |
+
{
|
| 43 |
+
"address_id": "ADDR0011",
|
| 44 |
+
"normalized_address": "70/185 basu zila, ongole, odisha"
|
| 45 |
+
},
|
| 46 |
+
{
|
| 47 |
+
"address_id": "ADDR0012",
|
| 48 |
+
"normalized_address": "h.no. 97 purohit path, medininagar, chhattisgarh"
|
| 49 |
+
},
|
| 50 |
+
{
|
| 51 |
+
"address_id": "ADDR0013",
|
| 52 |
+
"normalized_address": "877 dixit chowk, hubliβdharwad, uttar pradesh"
|
| 53 |
+
},
|
| 54 |
+
{
|
| 55 |
+
"address_id": "ADDR0014",
|
| 56 |
+
"normalized_address": "96/63 nori marg, mango, telangana"
|
| 57 |
+
},
|
| 58 |
+
{
|
| 59 |
+
"address_id": "ADDR0015",
|
| 60 |
+
"normalized_address": "h.no. 12 more nagar, karaikudi, assam"
|
| 61 |
+
},
|
| 62 |
+
{
|
| 63 |
+
"address_id": "ADDR0016",
|
| 64 |
+
"normalized_address": "989 vig nagar, fatehpur, mizoram"
|
| 65 |
+
},
|
| 66 |
+
{
|
| 67 |
+
"address_id": "ADDR0017",
|
| 68 |
+
"normalized_address": "h.no. 182 maharaj nagar, sambalpur, uttarakhand"
|
| 69 |
+
},
|
| 70 |
+
{
|
| 71 |
+
"address_id": "ADDR0018",
|
| 72 |
+
"normalized_address": "97/189 ratti path, pallavaram, west bengal"
|
| 73 |
+
},
|
| 74 |
+
{
|
| 75 |
+
"address_id": "ADDR0019",
|
| 76 |
+
"normalized_address": "h.no. 562 bajwa marg, eluru, himachal pradesh"
|
| 77 |
+
},
|
| 78 |
+
{
|
| 79 |
+
"address_id": "ADDR0020",
|
| 80 |
+
"normalized_address": "h.no. 118 mangal street, south dumdum, himachal pradesh"
|
| 81 |
+
},
|
| 82 |
+
{
|
| 83 |
+
"address_id": "ADDR0021",
|
| 84 |
+
"normalized_address": "h.no. 246 bhargava street, bokaro, andhra pradesh"
|
| 85 |
+
},
|
| 86 |
+
{
|
| 87 |
+
"address_id": "ADDR0022",
|
| 88 |
+
"normalized_address": "04/615 sachar street, rampur, madhya pradesh"
|
| 89 |
+
},
|
| 90 |
+
{
|
| 91 |
+
"address_id": "ADDR0023",
|
| 92 |
+
"normalized_address": "h.no. 033 khalsa, danapur, tripura"
|
| 93 |
+
},
|
| 94 |
+
{
|
| 95 |
+
"address_id": "ADDR0024",
|
| 96 |
+
"normalized_address": "61/40 shetty path, amritsar, meghalaya"
|
| 97 |
+
},
|
| 98 |
+
{
|
| 99 |
+
"address_id": "ADDR0025",
|
| 100 |
+
"normalized_address": "h.no. 630 chaudhuri road, miryalaguda, rajasthan"
|
| 101 |
+
},
|
| 102 |
+
{
|
| 103 |
+
"address_id": "ADDR0026",
|
| 104 |
+
"normalized_address": "496 chacko chowk, ajmer, kerala"
|
| 105 |
+
},
|
| 106 |
+
{
|
| 107 |
+
"address_id": "ADDR0027",
|
| 108 |
+
"normalized_address": "23/86 seth circle, mumbai, uttarakhand"
|
| 109 |
+
},
|
| 110 |
+
{
|
| 111 |
+
"address_id": "ADDR0028",
|
| 112 |
+
"normalized_address": "94 acharya street, ongole, himachal pradesh"
|
| 113 |
+
},
|
| 114 |
+
{
|
| 115 |
+
"address_id": "ADDR0029",
|
| 116 |
+
"normalized_address": "46/53 uppal, ranchi, goa"
|
| 117 |
+
},
|
| 118 |
+
{
|
| 119 |
+
"address_id": "ADDR0030",
|
| 120 |
+
"normalized_address": "89/141 das marg, miryalaguda, himachal pradesh"
|
| 121 |
+
},
|
| 122 |
+
{
|
| 123 |
+
"address_id": "ADDR0031",
|
| 124 |
+
"normalized_address": "39 nadkarni circle, bhilwara, tripura"
|
| 125 |
+
},
|
| 126 |
+
{
|
| 127 |
+
"address_id": "ADDR0032",
|
| 128 |
+
"normalized_address": "74/355 sharaf ganj, pune, tamil nadu"
|
| 129 |
+
},
|
| 130 |
+
{
|
| 131 |
+
"address_id": "ADDR0033",
|
| 132 |
+
"normalized_address": "097 andra nagar, haridwar, nagaland"
|
| 133 |
+
},
|
| 134 |
+
{
|
| 135 |
+
"address_id": "ADDR0034",
|
| 136 |
+
"normalized_address": "76/811 balasubramanian circle, amravati, kerala"
|
| 137 |
+
},
|
| 138 |
+
{
|
| 139 |
+
"address_id": "ADDR0035",
|
| 140 |
+
"normalized_address": "95 goel marg, amravati, manipur"
|
| 141 |
+
},
|
| 142 |
+
{
|
| 143 |
+
"address_id": "ADDR0036",
|
| 144 |
+
"normalized_address": "h.no. 37 kant nagar, parbhani, sikkim"
|
| 145 |
+
},
|
| 146 |
+
{
|
| 147 |
+
"address_id": "ADDR0037",
|
| 148 |
+
"normalized_address": "53/194 kaur ganj, mirzapur, arunachal pradesh"
|
| 149 |
+
},
|
| 150 |
+
{
|
| 151 |
+
"address_id": "ADDR0038",
|
| 152 |
+
"normalized_address": "h.no. 79 amble ganj, tenali, bihar"
|
| 153 |
+
},
|
| 154 |
+
{
|
| 155 |
+
"address_id": "ADDR0039",
|
| 156 |
+
"normalized_address": "h.no. 98 garde chowk, buxar, sikkim"
|
| 157 |
+
},
|
| 158 |
+
{
|
| 159 |
+
"address_id": "ADDR0040",
|
| 160 |
+
"normalized_address": "99/219 bhattacharyya street, rampur, odisha"
|
| 161 |
+
},
|
| 162 |
+
{
|
| 163 |
+
"address_id": "ADDR0041",
|
| 164 |
+
"normalized_address": "843 walia nagar, karaikudi, manipur"
|
| 165 |
+
},
|
| 166 |
+
{
|
| 167 |
+
"address_id": "ADDR0042",
|
| 168 |
+
"normalized_address": "h.no. 605 ray marg, bhilai, sikkim"
|
| 169 |
+
},
|
| 170 |
+
{
|
| 171 |
+
"address_id": "ADDR0043",
|
| 172 |
+
"normalized_address": "77/58 kapur nagar, alwar, maharashtra"
|
| 173 |
+
},
|
| 174 |
+
{
|
| 175 |
+
"address_id": "ADDR0044",
|
| 176 |
+
"normalized_address": "75/06 natt ganj, aurangabad, uttar pradesh"
|
| 177 |
+
},
|
| 178 |
+
{
|
| 179 |
+
"address_id": "ADDR0045",
|
| 180 |
+
"normalized_address": "h.no. 361 hegde ganj, ozhukarai, jharkhand"
|
| 181 |
+
},
|
| 182 |
+
{
|
| 183 |
+
"address_id": "ADDR0046",
|
| 184 |
+
"normalized_address": "h.no. 107 bajwa marg, chandrapur, haryana"
|
| 185 |
+
},
|
| 186 |
+
{
|
| 187 |
+
"address_id": "ADDR0047",
|
| 188 |
+
"normalized_address": "h.no. 735 nath nagar, srinagar, tripura"
|
| 189 |
+
},
|
| 190 |
+
{
|
| 191 |
+
"address_id": "ADDR0048",
|
| 192 |
+
"normalized_address": "97/17 dash, ghaziabad, arunachal pradesh"
|
| 193 |
+
},
|
| 194 |
+
{
|
| 195 |
+
"address_id": "ADDR0049",
|
| 196 |
+
"normalized_address": "51 bhatia street, pimpri-chinchwad, jharkhand"
|
| 197 |
+
},
|
| 198 |
+
{
|
| 199 |
+
"address_id": "ADDR0050",
|
| 200 |
+
"normalized_address": "61/10 ben circle, eluru, madhya pradesh"
|
| 201 |
+
},
|
| 202 |
+
{
|
| 203 |
+
"address_id": "ADDR0051",
|
| 204 |
+
"normalized_address": "h.no. 963 anne, yamunanagar, manipur"
|
| 205 |
+
},
|
| 206 |
+
{
|
| 207 |
+
"address_id": "ADDR0052",
|
| 208 |
+
"normalized_address": "99 nori zila, malda, mizoram"
|
| 209 |
+
},
|
| 210 |
+
{
|
| 211 |
+
"address_id": "ADDR0053",
|
| 212 |
+
"normalized_address": "h.no. 93 chauhan zila, hindupur, tamil nadu"
|
| 213 |
+
},
|
| 214 |
+
{
|
| 215 |
+
"address_id": "ADDR0054",
|
| 216 |
+
"normalized_address": "h.no. 939 upadhyay street, raichur, maharashtra"
|
| 217 |
+
},
|
| 218 |
+
{
|
| 219 |
+
"address_id": "ADDR0055",
|
| 220 |
+
"normalized_address": "97 kibe street, varanasi, arunachal pradesh"
|
| 221 |
+
},
|
| 222 |
+
{
|
| 223 |
+
"address_id": "ADDR0056",
|
| 224 |
+
"normalized_address": "496 parmar circle, ballia, nagaland"
|
| 225 |
+
},
|
| 226 |
+
{
|
| 227 |
+
"address_id": "ADDR0057",
|
| 228 |
+
"normalized_address": "274 oza, arrah, andhra pradesh"
|
| 229 |
+
},
|
| 230 |
+
{
|
| 231 |
+
"address_id": "ADDR0058",
|
| 232 |
+
"normalized_address": "92/03 bhagat circle, hapur, gujarat"
|
| 233 |
+
},
|
| 234 |
+
{
|
| 235 |
+
"address_id": "ADDR0059",
|
| 236 |
+
"normalized_address": "315 soni ganj, ghaziabad, tamil nadu"
|
| 237 |
+
},
|
| 238 |
+
{
|
| 239 |
+
"address_id": "ADDR0060",
|
| 240 |
+
"normalized_address": "h.no. 99 mistry path, ozhukarai, goa"
|
| 241 |
+
},
|
| 242 |
+
{
|
| 243 |
+
"address_id": "ADDR0061",
|
| 244 |
+
"normalized_address": "h.no. 707 aggarwal ganj, berhampur, manipur"
|
| 245 |
+
},
|
| 246 |
+
{
|
| 247 |
+
"address_id": "ADDR0062",
|
| 248 |
+
"normalized_address": "33/75 jha marg, udaipur, uttarakhand"
|
| 249 |
+
},
|
| 250 |
+
{
|
| 251 |
+
"address_id": "ADDR0063",
|
| 252 |
+
"normalized_address": "h.no. 501 balan path, ajmer, jharkhand"
|
| 253 |
+
},
|
| 254 |
+
{
|
| 255 |
+
"address_id": "ADDR0064",
|
| 256 |
+
"normalized_address": "39 bassi path, davanagere, gujarat"
|
| 257 |
+
},
|
| 258 |
+
{
|
| 259 |
+
"address_id": "ADDR0065",
|
| 260 |
+
"normalized_address": "h.no. 23 ghosh road, begusarai, haryana"
|
| 261 |
+
},
|
| 262 |
+
{
|
| 263 |
+
"address_id": "ADDR0066",
|
| 264 |
+
"normalized_address": "302 chaudhuri road, durgapur, madhya pradesh"
|
| 265 |
+
},
|
| 266 |
+
{
|
| 267 |
+
"address_id": "ADDR0067",
|
| 268 |
+
"normalized_address": "15/347 pingle ganj, tirunelveli, mizoram"
|
| 269 |
+
},
|
| 270 |
+
{
|
| 271 |
+
"address_id": "ADDR0068",
|
| 272 |
+
"normalized_address": "61/12 gupta street, katihar, madhya pradesh"
|
| 273 |
+
},
|
| 274 |
+
{
|
| 275 |
+
"address_id": "ADDR0069",
|
| 276 |
+
"normalized_address": "55/963 gulati nagar, jalgaon, karnataka"
|
| 277 |
+
},
|
| 278 |
+
{
|
| 279 |
+
"address_id": "ADDR0070",
|
| 280 |
+
"normalized_address": "042 suresh circle, jodhpur, uttar pradesh"
|
| 281 |
+
},
|
| 282 |
+
{
|
| 283 |
+
"address_id": "ADDR0071",
|
| 284 |
+
"normalized_address": "91 trivedi street, danapur, kerala"
|
| 285 |
+
},
|
| 286 |
+
{
|
| 287 |
+
"address_id": "ADDR0072",
|
| 288 |
+
"normalized_address": "87 nagy street, hajipur, tamil nadu"
|
| 289 |
+
},
|
| 290 |
+
{
|
| 291 |
+
"address_id": "ADDR0073",
|
| 292 |
+
"normalized_address": "77 rattan road, dhule, haryana"
|
| 293 |
+
},
|
| 294 |
+
{
|
| 295 |
+
"address_id": "ADDR0074",
|
| 296 |
+
"normalized_address": "736 mohan ganj, burhanpur, odisha"
|
| 297 |
+
},
|
| 298 |
+
{
|
| 299 |
+
"address_id": "ADDR0075",
|
| 300 |
+
"normalized_address": "548 desai zila, sagar, manipur"
|
| 301 |
+
},
|
| 302 |
+
{
|
| 303 |
+
"address_id": "ADDR0076",
|
| 304 |
+
"normalized_address": "53/90 vala chowk, purnia, manipur"
|
| 305 |
+
},
|
| 306 |
+
{
|
| 307 |
+
"address_id": "ADDR0077",
|
| 308 |
+
"normalized_address": "66 tank path, darbhanga, madhya pradesh"
|
| 309 |
+
},
|
| 310 |
+
{
|
| 311 |
+
"address_id": "ADDR0078",
|
| 312 |
+
"normalized_address": "h.no. 273 borra road, gwalior, jharkhand"
|
| 313 |
+
},
|
| 314 |
+
{
|
| 315 |
+
"address_id": "ADDR0079",
|
| 316 |
+
"normalized_address": "88/14 chaudhari ganj, madurai, kerala"
|
| 317 |
+
},
|
| 318 |
+
{
|
| 319 |
+
"address_id": "ADDR0080",
|
| 320 |
+
"normalized_address": "h.no. 835 narayan ganj, barasat, telangana"
|
| 321 |
+
},
|
| 322 |
+
{
|
| 323 |
+
"address_id": "ADDR0081",
|
| 324 |
+
"normalized_address": "43/928 anand road, ichalkaranji, uttarakhand"
|
| 325 |
+
},
|
| 326 |
+
{
|
| 327 |
+
"address_id": "ADDR0082",
|
| 328 |
+
"normalized_address": "h.no. 66 arora, anand, tripura"
|
| 329 |
+
},
|
| 330 |
+
{
|
| 331 |
+
"address_id": "ADDR0083",
|
| 332 |
+
"normalized_address": "633 som ganj, hazaribagh, odisha"
|
| 333 |
+
},
|
| 334 |
+
{
|
| 335 |
+
"address_id": "ADDR0084",
|
| 336 |
+
"normalized_address": "77/51 guha path, erode, gujarat"
|
| 337 |
+
},
|
| 338 |
+
{
|
| 339 |
+
"address_id": "ADDR0085",
|
| 340 |
+
"normalized_address": "78 prasad nagar, gangtok, west bengal"
|
| 341 |
+
},
|
| 342 |
+
{
|
| 343 |
+
"address_id": "ADDR0086",
|
| 344 |
+
"normalized_address": "407 nori path, gurgaon, maharashtra"
|
| 345 |
+
},
|
| 346 |
+
{
|
| 347 |
+
"address_id": "ADDR0087",
|
| 348 |
+
"normalized_address": "68/459 balay nagar, jamnagar, karnataka"
|
| 349 |
+
},
|
| 350 |
+
{
|
| 351 |
+
"address_id": "ADDR0088",
|
| 352 |
+
"normalized_address": "99/96 jayaraman marg, rajkot, nagaland"
|
| 353 |
+
},
|
| 354 |
+
{
|
| 355 |
+
"address_id": "ADDR0089",
|
| 356 |
+
"normalized_address": "37 narasimhan zila, avadi, assam"
|
| 357 |
+
},
|
| 358 |
+
{
|
| 359 |
+
"address_id": "ADDR0090",
|
| 360 |
+
"normalized_address": "182 suresh nagar, gaya, gujarat"
|
| 361 |
+
},
|
| 362 |
+
{
|
| 363 |
+
"address_id": "ADDR0091",
|
| 364 |
+
"normalized_address": "h.no. 643 manne ganj, malda, arunachal pradesh"
|
| 365 |
+
},
|
| 366 |
+
{
|
| 367 |
+
"address_id": "ADDR0092",
|
| 368 |
+
"normalized_address": "h.no. 80 narain street, katni, goa"
|
| 369 |
+
},
|
| 370 |
+
{
|
| 371 |
+
"address_id": "ADDR0093",
|
| 372 |
+
"normalized_address": "h.no. 286 biswas chowk, tiruppur, chhattisgarh"
|
| 373 |
+
},
|
| 374 |
+
{
|
| 375 |
+
"address_id": "ADDR0094",
|
| 376 |
+
"normalized_address": "467 mukherjee street, ambala, tamil nadu"
|
| 377 |
+
},
|
| 378 |
+
{
|
| 379 |
+
"address_id": "ADDR0095",
|
| 380 |
+
"normalized_address": "74/302 bhatt chowk, mahbubnagar, uttar pradesh"
|
| 381 |
+
},
|
| 382 |
+
{
|
| 383 |
+
"address_id": "ADDR0096",
|
| 384 |
+
"normalized_address": "859 sharma chowk, ramgarh, arunachal pradesh"
|
| 385 |
+
},
|
| 386 |
+
{
|
| 387 |
+
"address_id": "ADDR0097",
|
| 388 |
+
"normalized_address": "14/754 gill marg, kulti, goa"
|
| 389 |
+
},
|
| 390 |
+
{
|
| 391 |
+
"address_id": "ADDR0098",
|
| 392 |
+
"normalized_address": "67/62 chandran, varanasi, haryana"
|
| 393 |
+
},
|
| 394 |
+
{
|
| 395 |
+
"address_id": "ADDR0099",
|
| 396 |
+
"normalized_address": "484 kalla zila, bulandshahr, tripura"
|
| 397 |
+
},
|
| 398 |
+
{
|
| 399 |
+
"address_id": "ADDR0100",
|
| 400 |
+
"normalized_address": "15/11 nanda circle, hospet, goa"
|
| 401 |
+
},
|
| 402 |
+
{
|
| 403 |
+
"address_id": "ADDR0101",
|
| 404 |
+
"normalized_address": "h.no. 38 shere nagar, srinagar, rajasthan"
|
| 405 |
+
},
|
| 406 |
+
{
|
| 407 |
+
"address_id": "ADDR0102",
|
| 408 |
+
"normalized_address": "76/563 barad marg, chandrapur, bihar"
|
| 409 |
+
},
|
| 410 |
+
{
|
| 411 |
+
"address_id": "ADDR0103",
|
| 412 |
+
"normalized_address": "25/777 butala zila, bahraich, chhattisgarh"
|
| 413 |
+
},
|
| 414 |
+
{
|
| 415 |
+
"address_id": "ADDR0104",
|
| 416 |
+
"normalized_address": "42 badami street, belgaum, jharkhand"
|
| 417 |
+
},
|
| 418 |
+
{
|
| 419 |
+
"address_id": "ADDR0105",
|
| 420 |
+
"normalized_address": "h.no. 862 apte zila, jamnagar, manipur"
|
| 421 |
+
},
|
| 422 |
+
{
|
| 423 |
+
"address_id": "ADDR0106",
|
| 424 |
+
"normalized_address": "h.no. 23 walia nagar, mango, tamil nadu"
|
| 425 |
+
},
|
| 426 |
+
{
|
| 427 |
+
"address_id": "ADDR0107",
|
| 428 |
+
"normalized_address": "h.no. 816 sawhney road, khora , andhra pradesh"
|
| 429 |
+
},
|
| 430 |
+
{
|
| 431 |
+
"address_id": "ADDR0108",
|
| 432 |
+
"normalized_address": "h.no. 633 khare path, mysore, andhra pradesh"
|
| 433 |
+
},
|
| 434 |
+
{
|
| 435 |
+
"address_id": "ADDR0109",
|
| 436 |
+
"normalized_address": "00 handa path, muzaffarnagar, bihar"
|
| 437 |
+
},
|
| 438 |
+
{
|
| 439 |
+
"address_id": "ADDR0110",
|
| 440 |
+
"normalized_address": "22/068 narain zila, kishanganj, rajasthan"
|
| 441 |
+
},
|
| 442 |
+
{
|
| 443 |
+
"address_id": "ADDR0111",
|
| 444 |
+
"normalized_address": "938 sangha marg, ahmednagar, gujarat"
|
| 445 |
+
},
|
| 446 |
+
{
|
| 447 |
+
"address_id": "ADDR0112",
|
| 448 |
+
"normalized_address": "h.no. 552 ratti nagar, ahmedabad, madhya pradesh"
|
| 449 |
+
},
|
| 450 |
+
{
|
| 451 |
+
"address_id": "ADDR0113",
|
| 452 |
+
"normalized_address": "731 pillay road, jabalpur, gujarat"
|
| 453 |
+
},
|
| 454 |
+
{
|
| 455 |
+
"address_id": "ADDR0114",
|
| 456 |
+
"normalized_address": "49 chaudry chowk, chandrapur, bihar"
|
| 457 |
+
},
|
| 458 |
+
{
|
| 459 |
+
"address_id": "ADDR0115",
|
| 460 |
+
"normalized_address": "56/25 nadkarni street, jabalpur, karnataka"
|
| 461 |
+
},
|
| 462 |
+
{
|
| 463 |
+
"address_id": "ADDR0116",
|
| 464 |
+
"normalized_address": "h.no. 997 vaidya marg, ambala, odisha"
|
| 465 |
+
},
|
| 466 |
+
{
|
| 467 |
+
"address_id": "ADDR0117",
|
| 468 |
+
"normalized_address": "03/091 khalsa road, latur, punjab"
|
| 469 |
+
},
|
| 470 |
+
{
|
| 471 |
+
"address_id": "ADDR0118",
|
| 472 |
+
"normalized_address": "h.no. 025 minhas chowk, saharanpur, madhya pradesh"
|
| 473 |
+
},
|
| 474 |
+
{
|
| 475 |
+
"address_id": "ADDR0119",
|
| 476 |
+
"normalized_address": "039 narasimhan chowk, alwar, karnataka"
|
| 477 |
+
},
|
| 478 |
+
{
|
| 479 |
+
"address_id": "ADDR0120",
|
| 480 |
+
"normalized_address": "08/640 narula ganj, latur, gujarat"
|
| 481 |
+
},
|
| 482 |
+
{
|
| 483 |
+
"address_id": "ADDR0121",
|
| 484 |
+
"normalized_address": "03/39 verma marg, south dumdum, manipur"
|
| 485 |
+
},
|
| 486 |
+
{
|
| 487 |
+
"address_id": "ADDR0122",
|
| 488 |
+
"normalized_address": "01/713 dhaliwal nagar, cuttack, assam"
|
| 489 |
+
},
|
| 490 |
+
{
|
| 491 |
+
"address_id": "ADDR0123",
|
| 492 |
+
"normalized_address": "983 tripathi ganj, purnia, telangana"
|
| 493 |
+
},
|
| 494 |
+
{
|
| 495 |
+
"address_id": "ADDR0124",
|
| 496 |
+
"normalized_address": "42 konda ganj, belgaum, punjab"
|
| 497 |
+
},
|
| 498 |
+
{
|
| 499 |
+
"address_id": "ADDR0125",
|
| 500 |
+
"normalized_address": "449 jaggi chowk, ongole, assam"
|
| 501 |
+
},
|
| 502 |
+
{
|
| 503 |
+
"address_id": "ADDR0126",
|
| 504 |
+
"normalized_address": "h.no. 66 sinha street, bhusawal, mizoram"
|
| 505 |
+
},
|
| 506 |
+
{
|
| 507 |
+
"address_id": "ADDR0127",
|
| 508 |
+
"normalized_address": "62/70 sane marg, dewas, punjab"
|
| 509 |
+
},
|
| 510 |
+
{
|
| 511 |
+
"address_id": "ADDR0128",
|
| 512 |
+
"normalized_address": "28/24 sheth marg, malda, jharkhand"
|
| 513 |
+
},
|
| 514 |
+
{
|
| 515 |
+
"address_id": "ADDR0129",
|
| 516 |
+
"normalized_address": "89 bora chowk, bhavnagar, tamil nadu"
|
| 517 |
+
},
|
| 518 |
+
{
|
| 519 |
+
"address_id": "ADDR0130",
|
| 520 |
+
"normalized_address": "32 agrawal ganj, orai, telangana"
|
| 521 |
+
},
|
| 522 |
+
{
|
| 523 |
+
"address_id": "ADDR0131",
|
| 524 |
+
"normalized_address": "57/666 rajagopalan path, aizawl, rajasthan"
|
| 525 |
+
},
|
| 526 |
+
{
|
| 527 |
+
"address_id": "ADDR0132",
|
| 528 |
+
"normalized_address": "16/01 gaba marg, junagadh, himachal pradesh"
|
| 529 |
+
},
|
| 530 |
+
{
|
| 531 |
+
"address_id": "ADDR0133",
|
| 532 |
+
"normalized_address": "58/750 samra marg, latur, meghalaya"
|
| 533 |
+
},
|
| 534 |
+
{
|
| 535 |
+
"address_id": "ADDR0134",
|
| 536 |
+
"normalized_address": "h.no. 502 shah road, rohtak, haryana"
|
| 537 |
+
},
|
| 538 |
+
{
|
| 539 |
+
"address_id": "ADDR0135",
|
| 540 |
+
"normalized_address": "92/01 rajagopalan zila, dharmavaram, assam"
|
| 541 |
+
},
|
| 542 |
+
{
|
| 543 |
+
"address_id": "ADDR0136",
|
| 544 |
+
"normalized_address": "36/26 mittal road, dharmavaram, jharkhand"
|
| 545 |
+
},
|
| 546 |
+
{
|
| 547 |
+
"address_id": "ADDR0137",
|
| 548 |
+
"normalized_address": "61/195 luthra street, sikar, tamil nadu"
|
| 549 |
+
},
|
| 550 |
+
{
|
| 551 |
+
"address_id": "ADDR0138",
|
| 552 |
+
"normalized_address": "h.no. 02 agarwal chowk, coimbatore, tripura"
|
| 553 |
+
},
|
| 554 |
+
{
|
| 555 |
+
"address_id": "ADDR0139",
|
| 556 |
+
"normalized_address": "68/646 goda street, gaya, tamil nadu"
|
| 557 |
+
},
|
| 558 |
+
{
|
| 559 |
+
"address_id": "ADDR0140",
|
| 560 |
+
"normalized_address": "372 choudhary circle, tezpur, uttarakhand"
|
| 561 |
+
},
|
| 562 |
+
{
|
| 563 |
+
"address_id": "ADDR0141",
|
| 564 |
+
"normalized_address": "230 handa street, alappuzha, manipur"
|
| 565 |
+
},
|
| 566 |
+
{
|
| 567 |
+
"address_id": "ADDR0142",
|
| 568 |
+
"normalized_address": "91/214 purohit zila, bally, assam"
|
| 569 |
+
},
|
| 570 |
+
{
|
| 571 |
+
"address_id": "ADDR0143",
|
| 572 |
+
"normalized_address": "h.no. 09 sridhar ganj, salem, andhra pradesh"
|
| 573 |
+
},
|
| 574 |
+
{
|
| 575 |
+
"address_id": "ADDR0144",
|
| 576 |
+
"normalized_address": "h.no. 409 chatterjee nagar, nagaon, uttar pradesh"
|
| 577 |
+
},
|
| 578 |
+
{
|
| 579 |
+
"address_id": "ADDR0145",
|
| 580 |
+
"normalized_address": "h.no. 698 sunder road, naihati, punjab"
|
| 581 |
+
},
|
| 582 |
+
{
|
| 583 |
+
"address_id": "ADDR0146",
|
| 584 |
+
"normalized_address": "55 murty path, karimnagar, sikkim"
|
| 585 |
+
},
|
| 586 |
+
{
|
| 587 |
+
"address_id": "ADDR0147",
|
| 588 |
+
"normalized_address": "69 parekh nagar, salem, andhra pradesh"
|
| 589 |
+
},
|
| 590 |
+
{
|
| 591 |
+
"address_id": "ADDR0148",
|
| 592 |
+
"normalized_address": "62 das nagar, kulti, kerala"
|
| 593 |
+
},
|
| 594 |
+
{
|
| 595 |
+
"address_id": "ADDR0149",
|
| 596 |
+
"normalized_address": "97 sachdev circle, delhi, rajasthan"
|
| 597 |
+
},
|
| 598 |
+
{
|
| 599 |
+
"address_id": "ADDR0150",
|
| 600 |
+
"normalized_address": "h.no. 05 nanda nagar, muzaffarpur, punjab"
|
| 601 |
+
},
|
| 602 |
+
{
|
| 603 |
+
"address_id": "ADDR0151",
|
| 604 |
+
"normalized_address": "69 pall zila, fatehpur, sikkim"
|
| 605 |
+
},
|
| 606 |
+
{
|
| 607 |
+
"address_id": "ADDR0152",
|
| 608 |
+
"normalized_address": "16/493 venkatesh street, warangal, meghalaya"
|
| 609 |
+
},
|
| 610 |
+
{
|
| 611 |
+
"address_id": "ADDR0153",
|
| 612 |
+
"normalized_address": "h.no. 487 sehgal street, ongole, sikkim"
|
| 613 |
+
},
|
| 614 |
+
{
|
| 615 |
+
"address_id": "ADDR0154",
|
| 616 |
+
"normalized_address": "33/32 cherian zila, bhopal, goa"
|
| 617 |
+
},
|
| 618 |
+
{
|
| 619 |
+
"address_id": "ADDR0155",
|
| 620 |
+
"normalized_address": "h.no. 64 kurian ganj, amravati, sikkim"
|
| 621 |
+
},
|
| 622 |
+
{
|
| 623 |
+
"address_id": "ADDR0156",
|
| 624 |
+
"normalized_address": "871 kapur path, tiruvottiyur, madhya pradesh"
|
| 625 |
+
},
|
| 626 |
+
{
|
| 627 |
+
"address_id": "ADDR0157",
|
| 628 |
+
"normalized_address": "68/633 dβalia road, chandigarh, bihar"
|
| 629 |
+
},
|
| 630 |
+
{
|
| 631 |
+
"address_id": "ADDR0158",
|
| 632 |
+
"normalized_address": "h.no. 593 pillai zila, satara, madhya pradesh"
|
| 633 |
+
},
|
| 634 |
+
{
|
| 635 |
+
"address_id": "ADDR0159",
|
| 636 |
+
"normalized_address": "04/09 gupta circle, bhusawal, karnataka"
|
| 637 |
+
},
|
| 638 |
+
{
|
| 639 |
+
"address_id": "ADDR0160",
|
| 640 |
+
"normalized_address": "h.no. 28 kapadia, tenali, andhra pradesh"
|
| 641 |
+
},
|
| 642 |
+
{
|
| 643 |
+
"address_id": "ADDR0161",
|
| 644 |
+
"normalized_address": "75/24 tata ganj, siliguri, punjab"
|
| 645 |
+
},
|
| 646 |
+
{
|
| 647 |
+
"address_id": "ADDR0162",
|
| 648 |
+
"normalized_address": "h.no. 20 nagarajan, ambala, tamil nadu"
|
| 649 |
+
},
|
| 650 |
+
{
|
| 651 |
+
"address_id": "ADDR0163",
|
| 652 |
+
"normalized_address": "h.no. 497 talwar ganj, gandhinagar, arunachal pradesh"
|
| 653 |
+
},
|
| 654 |
+
{
|
| 655 |
+
"address_id": "ADDR0164",
|
| 656 |
+
"normalized_address": "h.no. 23 ben ganj, morbi, telangana"
|
| 657 |
+
},
|
| 658 |
+
{
|
| 659 |
+
"address_id": "ADDR0165",
|
| 660 |
+
"normalized_address": "42 ramanathan nagar, bhusawal, sikkim"
|
| 661 |
+
},
|
| 662 |
+
{
|
| 663 |
+
"address_id": "ADDR0166",
|
| 664 |
+
"normalized_address": "56 bora marg, ichalkaranji, tamil nadu"
|
| 665 |
+
},
|
| 666 |
+
{
|
| 667 |
+
"address_id": "ADDR0167",
|
| 668 |
+
"normalized_address": "861 naik street, avadi, manipur"
|
| 669 |
+
},
|
| 670 |
+
{
|
| 671 |
+
"address_id": "ADDR0168",
|
| 672 |
+
"normalized_address": "29/277 dhillon road, bellary, uttar pradesh"
|
| 673 |
+
},
|
| 674 |
+
{
|
| 675 |
+
"address_id": "ADDR0169",
|
| 676 |
+
"normalized_address": "30/591 puri street, gulbarga, arunachal pradesh"
|
| 677 |
+
},
|
| 678 |
+
{
|
| 679 |
+
"address_id": "ADDR0170",
|
| 680 |
+
"normalized_address": "h.no. 572 dalal nagar, guntakal, maharashtra"
|
| 681 |
+
},
|
| 682 |
+
{
|
| 683 |
+
"address_id": "ADDR0171",
|
| 684 |
+
"normalized_address": "630 khosla zila, unnao, jharkhand"
|
| 685 |
+
},
|
| 686 |
+
{
|
| 687 |
+
"address_id": "ADDR0172",
|
| 688 |
+
"normalized_address": "92/617 maharaj marg, arrah, andhra pradesh"
|
| 689 |
+
},
|
| 690 |
+
{
|
| 691 |
+
"address_id": "ADDR0173",
|
| 692 |
+
"normalized_address": "h.no. 111 upadhyay chowk, lucknow, odisha"
|
| 693 |
+
},
|
| 694 |
+
{
|
| 695 |
+
"address_id": "ADDR0174",
|
| 696 |
+
"normalized_address": "97/41 golla, karawal nagar, rajasthan"
|
| 697 |
+
},
|
| 698 |
+
{
|
| 699 |
+
"address_id": "ADDR0175",
|
| 700 |
+
"normalized_address": "64/921 bhatt path, machilipatnam, uttarakhand"
|
| 701 |
+
},
|
| 702 |
+
{
|
| 703 |
+
"address_id": "ADDR0176",
|
| 704 |
+
"normalized_address": "06/888 bhatt chowk, dhule, sikkim"
|
| 705 |
+
},
|
| 706 |
+
{
|
| 707 |
+
"address_id": "ADDR0177",
|
| 708 |
+
"normalized_address": "h.no. 292 sekhon nagar, bhilai, arunachal pradesh"
|
| 709 |
+
},
|
| 710 |
+
{
|
| 711 |
+
"address_id": "ADDR0178",
|
| 712 |
+
"normalized_address": "932 kunda zila, guwahati, bihar"
|
| 713 |
+
},
|
| 714 |
+
{
|
| 715 |
+
"address_id": "ADDR0179",
|
| 716 |
+
"normalized_address": "45/82 acharya marg, dewas, arunachal pradesh"
|
| 717 |
+
},
|
| 718 |
+
{
|
| 719 |
+
"address_id": "ADDR0180",
|
| 720 |
+
"normalized_address": "48/72 swaminathan, nagaon, kerala"
|
| 721 |
+
},
|
| 722 |
+
{
|
| 723 |
+
"address_id": "ADDR0181",
|
| 724 |
+
"normalized_address": "88/31 khalsa nagar, maheshtala, chhattisgarh"
|
| 725 |
+
},
|
| 726 |
+
{
|
| 727 |
+
"address_id": "ADDR0182",
|
| 728 |
+
"normalized_address": "h.no. 32 kalita, alwar, chhattisgarh"
|
| 729 |
+
},
|
| 730 |
+
{
|
| 731 |
+
"address_id": "ADDR0183",
|
| 732 |
+
"normalized_address": "96/184 raj road, silchar, manipur"
|
| 733 |
+
},
|
| 734 |
+
{
|
| 735 |
+
"address_id": "ADDR0184",
|
| 736 |
+
"normalized_address": "h.no. 462 jani circle, agartala, rajasthan"
|
| 737 |
+
},
|
| 738 |
+
{
|
| 739 |
+
"address_id": "ADDR0185",
|
| 740 |
+
"normalized_address": "35/989 saini street, satna, uttar pradesh"
|
| 741 |
+
},
|
| 742 |
+
{
|
| 743 |
+
"address_id": "ADDR0186",
|
| 744 |
+
"normalized_address": "60 kota, gopalpur, bihar"
|
| 745 |
+
},
|
| 746 |
+
{
|
| 747 |
+
"address_id": "ADDR0187",
|
| 748 |
+
"normalized_address": "18/61 chakraborty path, thoothukudi, tripura"
|
| 749 |
+
},
|
| 750 |
+
{
|
| 751 |
+
"address_id": "ADDR0188",
|
| 752 |
+
"normalized_address": "h.no. 23 anne road, burhanpur, haryana"
|
| 753 |
+
},
|
| 754 |
+
{
|
| 755 |
+
"address_id": "ADDR0189",
|
| 756 |
+
"normalized_address": "11 vyas street, giridih, uttarakhand"
|
| 757 |
+
},
|
| 758 |
+
{
|
| 759 |
+
"address_id": "ADDR0190",
|
| 760 |
+
"normalized_address": "18 manda path, narasaraopet, bihar"
|
| 761 |
+
},
|
| 762 |
+
{
|
| 763 |
+
"address_id": "ADDR0191",
|
| 764 |
+
"normalized_address": "h.no. 256 pai street, morena, odisha"
|
| 765 |
+
},
|
| 766 |
+
{
|
| 767 |
+
"address_id": "ADDR0192",
|
| 768 |
+
"normalized_address": "408 date street, burhanpur, odisha"
|
| 769 |
+
},
|
| 770 |
+
{
|
| 771 |
+
"address_id": "ADDR0193",
|
| 772 |
+
"normalized_address": "40/539 shankar marg, bahraich, kerala"
|
| 773 |
+
},
|
| 774 |
+
{
|
| 775 |
+
"address_id": "ADDR0194",
|
| 776 |
+
"normalized_address": "84 sangha road, farrukhabad, rajasthan"
|
| 777 |
+
},
|
| 778 |
+
{
|
| 779 |
+
"address_id": "ADDR0195",
|
| 780 |
+
"normalized_address": "h.no. 465 buch zila, mathura, assam"
|
| 781 |
+
},
|
| 782 |
+
{
|
| 783 |
+
"address_id": "ADDR0196",
|
| 784 |
+
"normalized_address": "901 tailor road, khandwa, sikkim"
|
| 785 |
+
},
|
| 786 |
+
{
|
| 787 |
+
"address_id": "ADDR0197",
|
| 788 |
+
"normalized_address": "27/78 dash circle, kanpur, punjab"
|
| 789 |
+
},
|
| 790 |
+
{
|
| 791 |
+
"address_id": "ADDR0198",
|
| 792 |
+
"normalized_address": "068 konda path, medininagar, manipur"
|
| 793 |
+
},
|
| 794 |
+
{
|
| 795 |
+
"address_id": "ADDR0199",
|
| 796 |
+
"normalized_address": "832 peri zila, kottayam, kerala"
|
| 797 |
+
},
|
| 798 |
+
{
|
| 799 |
+
"address_id": "ADDR0200",
|
| 800 |
+
"normalized_address": "h.no. 676 prakash street, sonipat, sikkim"
|
| 801 |
+
},
|
| 802 |
+
{
|
| 803 |
+
"address_id": "ADDR0201",
|
| 804 |
+
"normalized_address": "814 subramanian road, bilaspur, gujarat"
|
| 805 |
+
},
|
| 806 |
+
{
|
| 807 |
+
"address_id": "ADDR0202",
|
| 808 |
+
"normalized_address": "h.no. 963 varma road, madhyamgram, punjab"
|
| 809 |
+
},
|
| 810 |
+
{
|
| 811 |
+
"address_id": "ADDR0203",
|
| 812 |
+
"normalized_address": "05 sharma nagar, bihar sharif, kerala"
|
| 813 |
+
},
|
| 814 |
+
{
|
| 815 |
+
"address_id": "ADDR0204",
|
| 816 |
+
"normalized_address": "h.no. 052 pant marg, salem, maharashtra"
|
| 817 |
+
},
|
| 818 |
+
{
|
| 819 |
+
"address_id": "ADDR0205",
|
| 820 |
+
"normalized_address": "31 varkey circle, bulandshahr, bihar"
|
| 821 |
+
},
|
| 822 |
+
{
|
| 823 |
+
"address_id": "ADDR0206",
|
| 824 |
+
"normalized_address": "02 kara road, tenali, kerala"
|
| 825 |
+
},
|
| 826 |
+
{
|
| 827 |
+
"address_id": "ADDR0207",
|
| 828 |
+
"normalized_address": "h.no. 56 yadav street, moradabad, manipur"
|
| 829 |
+
},
|
| 830 |
+
{
|
| 831 |
+
"address_id": "ADDR0208",
|
| 832 |
+
"normalized_address": "72/256 parmer nagar, bhubaneswar, gujarat"
|
| 833 |
+
},
|
| 834 |
+
{
|
| 835 |
+
"address_id": "ADDR0209",
|
| 836 |
+
"normalized_address": "h.no. 02 sama marg, patna, goa"
|
| 837 |
+
},
|
| 838 |
+
{
|
| 839 |
+
"address_id": "ADDR0210",
|
| 840 |
+
"normalized_address": "37/416 tandon chowk, anantapur, tripura"
|
| 841 |
+
},
|
| 842 |
+
{
|
| 843 |
+
"address_id": "ADDR0211",
|
| 844 |
+
"normalized_address": "86 choudhary street, jaipur, chhattisgarh"
|
| 845 |
+
},
|
| 846 |
+
{
|
| 847 |
+
"address_id": "ADDR0212",
|
| 848 |
+
"normalized_address": "580 ben ganj, haldia, punjab"
|
| 849 |
+
},
|
| 850 |
+
{
|
| 851 |
+
"address_id": "ADDR0213",
|
| 852 |
+
"normalized_address": "06/744 butala chowk, shahjahanpur, punjab"
|
| 853 |
+
},
|
| 854 |
+
{
|
| 855 |
+
"address_id": "ADDR0214",
|
| 856 |
+
"normalized_address": "823 contractor road, shahjahanpur, sikkim"
|
| 857 |
+
},
|
| 858 |
+
{
|
| 859 |
+
"address_id": "ADDR0215",
|
| 860 |
+
"normalized_address": "37 thakkar zila, maheshtala, west bengal"
|
| 861 |
+
},
|
| 862 |
+
{
|
| 863 |
+
"address_id": "ADDR0216",
|
| 864 |
+
"normalized_address": "23/12 barad marg, nellore, chhattisgarh"
|
| 865 |
+
},
|
| 866 |
+
{
|
| 867 |
+
"address_id": "ADDR0217",
|
| 868 |
+
"normalized_address": "09 chand ganj, nadiad, maharashtra"
|
| 869 |
+
},
|
| 870 |
+
{
|
| 871 |
+
"address_id": "ADDR0218",
|
| 872 |
+
"normalized_address": "43/35 srinivas marg, sasaram, maharashtra"
|
| 873 |
+
},
|
| 874 |
+
{
|
| 875 |
+
"address_id": "ADDR0219",
|
| 876 |
+
"normalized_address": "04/145 panchal road, shahjahanpur, karnataka"
|
| 877 |
+
},
|
| 878 |
+
{
|
| 879 |
+
"address_id": "ADDR0220",
|
| 880 |
+
"normalized_address": "h.no. 200 nagy nagar, baranagar, meghalaya"
|
| 881 |
+
},
|
| 882 |
+
{
|
| 883 |
+
"address_id": "ADDR0221",
|
| 884 |
+
"normalized_address": "h.no. 91 goyal marg, pallavaram, kerala"
|
| 885 |
+
},
|
| 886 |
+
{
|
| 887 |
+
"address_id": "ADDR0222",
|
| 888 |
+
"normalized_address": "h.no. 41 arya zila, bathinda, kerala"
|
| 889 |
+
},
|
| 890 |
+
{
|
| 891 |
+
"address_id": "ADDR0223",
|
| 892 |
+
"normalized_address": "59/895 majumdar ganj, bhimavaram, madhya pradesh"
|
| 893 |
+
},
|
| 894 |
+
{
|
| 895 |
+
"address_id": "ADDR0224",
|
| 896 |
+
"normalized_address": "h.no. 129 barman zila, nellore, tamil nadu"
|
| 897 |
+
},
|
| 898 |
+
{
|
| 899 |
+
"address_id": "ADDR0225",
|
| 900 |
+
"normalized_address": "11 oza circle, bhalswa jahangir pur, tripura"
|
| 901 |
+
},
|
| 902 |
+
{
|
| 903 |
+
"address_id": "ADDR0226",
|
| 904 |
+
"normalized_address": "820 handa street, jamalpur, tamil nadu"
|
| 905 |
+
},
|
| 906 |
+
{
|
| 907 |
+
"address_id": "ADDR0227",
|
| 908 |
+
"normalized_address": "h.no. 85 sen path, junagadh, assam"
|
| 909 |
+
},
|
| 910 |
+
{
|
| 911 |
+
"address_id": "ADDR0228",
|
| 912 |
+
"normalized_address": "68 bains circle, khora , himachal pradesh"
|
| 913 |
+
},
|
| 914 |
+
{
|
| 915 |
+
"address_id": "ADDR0229",
|
| 916 |
+
"normalized_address": "24/090 rao ganj, katihar, west bengal"
|
| 917 |
+
},
|
| 918 |
+
{
|
| 919 |
+
"address_id": "ADDR0230",
|
| 920 |
+
"normalized_address": "12/78 ramakrishnan marg, medininagar, himachal pradesh"
|
| 921 |
+
},
|
| 922 |
+
{
|
| 923 |
+
"address_id": "ADDR0231",
|
| 924 |
+
"normalized_address": "202 kamdar, anand, manipur"
|
| 925 |
+
},
|
| 926 |
+
{
|
| 927 |
+
"address_id": "ADDR0232",
|
| 928 |
+
"normalized_address": "84/43 loyal road, tirunelveli, haryana"
|
| 929 |
+
},
|
| 930 |
+
{
|
| 931 |
+
"address_id": "ADDR0233",
|
| 932 |
+
"normalized_address": "h.no. 834 divan nagar, guntur, himachal pradesh"
|
| 933 |
+
},
|
| 934 |
+
{
|
| 935 |
+
"address_id": "ADDR0234",
|
| 936 |
+
"normalized_address": "h.no. 338 agarwal zila, mahbubnagar, kerala"
|
| 937 |
+
},
|
| 938 |
+
{
|
| 939 |
+
"address_id": "ADDR0235",
|
| 940 |
+
"normalized_address": "h.no. 18 deol road, pudukkottai, jharkhand"
|
| 941 |
+
},
|
| 942 |
+
{
|
| 943 |
+
"address_id": "ADDR0236",
|
| 944 |
+
"normalized_address": "h.no. 00 kanda path, belgaum, himachal pradesh"
|
| 945 |
+
},
|
| 946 |
+
{
|
| 947 |
+
"address_id": "ADDR0237",
|
| 948 |
+
"normalized_address": "h.no. 891 kurian marg, mango, haryana"
|
| 949 |
+
},
|
| 950 |
+
{
|
| 951 |
+
"address_id": "ADDR0238",
|
| 952 |
+
"normalized_address": "h.no. 43 rana, amroha, haryana"
|
| 953 |
+
},
|
| 954 |
+
{
|
| 955 |
+
"address_id": "ADDR0239",
|
| 956 |
+
"normalized_address": "65/271 golla chowk, udaipur, uttarakhand"
|
| 957 |
+
},
|
| 958 |
+
{
|
| 959 |
+
"address_id": "ADDR0240",
|
| 960 |
+
"normalized_address": "397 manda street, tirupati, goa"
|
| 961 |
+
},
|
| 962 |
+
{
|
| 963 |
+
"address_id": "ADDR0241",
|
| 964 |
+
"normalized_address": "693 dhar zila, purnia, haryana"
|
| 965 |
+
},
|
| 966 |
+
{
|
| 967 |
+
"address_id": "ADDR0242",
|
| 968 |
+
"normalized_address": "61 devan circle, madanapalle, bihar"
|
| 969 |
+
},
|
| 970 |
+
{
|
| 971 |
+
"address_id": "ADDR0243",
|
| 972 |
+
"normalized_address": "60 arya zila, mira-bhayandar, haryana"
|
| 973 |
+
},
|
| 974 |
+
{
|
| 975 |
+
"address_id": "ADDR0244",
|
| 976 |
+
"normalized_address": "h.no. 429 andra nagar, hosur, telangana"
|
| 977 |
+
},
|
| 978 |
+
{
|
| 979 |
+
"address_id": "ADDR0245",
|
| 980 |
+
"normalized_address": "h.no. 13 srinivasan street, ujjain, jharkhand"
|
| 981 |
+
},
|
| 982 |
+
{
|
| 983 |
+
"address_id": "ADDR0246",
|
| 984 |
+
"normalized_address": "h.no. 72 bhalla ganj, tinsukia, bihar"
|
| 985 |
+
},
|
| 986 |
+
{
|
| 987 |
+
"address_id": "ADDR0247",
|
| 988 |
+
"normalized_address": "h.no. 018 chauhan road, ajmer, andhra pradesh"
|
| 989 |
+
},
|
| 990 |
+
{
|
| 991 |
+
"address_id": "ADDR0248",
|
| 992 |
+
"normalized_address": "036 din marg, baranagar, haryana"
|
| 993 |
+
},
|
| 994 |
+
{
|
| 995 |
+
"address_id": "ADDR0249",
|
| 996 |
+
"normalized_address": "61/721 chaudry ganj, raurkela industrial township, assam"
|
| 997 |
+
},
|
| 998 |
+
{
|
| 999 |
+
"address_id": "ADDR0250",
|
| 1000 |
+
"normalized_address": "51/51 dora nagar, haldia, mizoram"
|
| 1001 |
+
},
|
| 1002 |
+
{
|
| 1003 |
+
"address_id": "ADDR0251",
|
| 1004 |
+
"normalized_address": "h.no. 92 doctor marg, baranagar, kerala"
|
| 1005 |
+
},
|
| 1006 |
+
{
|
| 1007 |
+
"address_id": "ADDR0252",
|
| 1008 |
+
"normalized_address": "h.no. 475 bose road, jalgaon, tripura"
|
| 1009 |
+
},
|
| 1010 |
+
{
|
| 1011 |
+
"address_id": "ADDR0253",
|
| 1012 |
+
"normalized_address": "25/267 bhavsar chowk, gangtok, maharashtra"
|
| 1013 |
+
},
|
| 1014 |
+
{
|
| 1015 |
+
"address_id": "ADDR0254",
|
| 1016 |
+
"normalized_address": "42/152 rajan street, imphal, meghalaya"
|
| 1017 |
+
},
|
| 1018 |
+
{
|
| 1019 |
+
"address_id": "ADDR0255",
|
| 1020 |
+
"normalized_address": "76 nath, sambalpur, madhya pradesh"
|
| 1021 |
+
},
|
| 1022 |
+
{
|
| 1023 |
+
"address_id": "ADDR0256",
|
| 1024 |
+
"normalized_address": "87 walla circle, katihar, nagaland"
|
| 1025 |
+
},
|
| 1026 |
+
{
|
| 1027 |
+
"address_id": "ADDR0257",
|
| 1028 |
+
"normalized_address": "619 vyas marg, chandigarh, haryana"
|
| 1029 |
+
},
|
| 1030 |
+
{
|
| 1031 |
+
"address_id": "ADDR0258",
|
| 1032 |
+
"normalized_address": "h.no. 03 patil nagar, guntur, bihar"
|
| 1033 |
+
},
|
| 1034 |
+
{
|
| 1035 |
+
"address_id": "ADDR0259",
|
| 1036 |
+
"normalized_address": "h.no. 552 sharma road, suryapet, maharashtra"
|
| 1037 |
+
},
|
| 1038 |
+
{
|
| 1039 |
+
"address_id": "ADDR0260",
|
| 1040 |
+
"normalized_address": "330 dalal street, burhanpur, telangana"
|
| 1041 |
+
},
|
| 1042 |
+
{
|
| 1043 |
+
"address_id": "ADDR0261",
|
| 1044 |
+
"normalized_address": "h.no. 650 borah zila, hindupur, west bengal"
|
| 1045 |
+
},
|
| 1046 |
+
{
|
| 1047 |
+
"address_id": "ADDR0262",
|
| 1048 |
+
"normalized_address": "025 brar street, solapur, andhra pradesh"
|
| 1049 |
+
},
|
| 1050 |
+
{
|
| 1051 |
+
"address_id": "ADDR0263",
|
| 1052 |
+
"normalized_address": "62/27 wable street, nandyal, maharashtra"
|
| 1053 |
+
},
|
| 1054 |
+
{
|
| 1055 |
+
"address_id": "ADDR0264",
|
| 1056 |
+
"normalized_address": "57/041 bhasin street, mahbubnagar, tripura"
|
| 1057 |
+
},
|
| 1058 |
+
{
|
| 1059 |
+
"address_id": "ADDR0265",
|
| 1060 |
+
"normalized_address": "820 sampath marg, begusarai, tamil nadu"
|
| 1061 |
+
},
|
| 1062 |
+
{
|
| 1063 |
+
"address_id": "ADDR0266",
|
| 1064 |
+
"normalized_address": "h.no. 98 karan road, sangli-miraj & kupwad, himachal pradesh"
|
| 1065 |
+
},
|
| 1066 |
+
{
|
| 1067 |
+
"address_id": "ADDR0267",
|
| 1068 |
+
"normalized_address": "h.no. 862 rattan ganj, muzaffarnagar, madhya pradesh"
|
| 1069 |
+
},
|
| 1070 |
+
{
|
| 1071 |
+
"address_id": "ADDR0268",
|
| 1072 |
+
"normalized_address": "891 sood chowk, machilipatnam, uttarakhand"
|
| 1073 |
+
},
|
| 1074 |
+
{
|
| 1075 |
+
"address_id": "ADDR0269",
|
| 1076 |
+
"normalized_address": "20 samra path, gopalpur, bihar"
|
| 1077 |
+
},
|
| 1078 |
+
{
|
| 1079 |
+
"address_id": "ADDR0270",
|
| 1080 |
+
"normalized_address": "h.no. 159 bala path, ichalkaranji, goa"
|
| 1081 |
+
},
|
| 1082 |
+
{
|
| 1083 |
+
"address_id": "ADDR0271",
|
| 1084 |
+
"normalized_address": "11/39 more nagar, suryapet, gujarat"
|
| 1085 |
+
},
|
| 1086 |
+
{
|
| 1087 |
+
"address_id": "ADDR0272",
|
| 1088 |
+
"normalized_address": "03/419 basu, ranchi, arunachal pradesh"
|
| 1089 |
+
},
|
| 1090 |
+
{
|
| 1091 |
+
"address_id": "ADDR0273",
|
| 1092 |
+
"normalized_address": "h.no. 14 parikh nagar, sikar, mizoram"
|
| 1093 |
+
},
|
| 1094 |
+
{
|
| 1095 |
+
"address_id": "ADDR0274",
|
| 1096 |
+
"normalized_address": "565 chatterjee street, vellore, telangana"
|
| 1097 |
+
},
|
| 1098 |
+
{
|
| 1099 |
+
"address_id": "ADDR0275",
|
| 1100 |
+
"normalized_address": "18/20 raja, dharmavaram, west bengal"
|
| 1101 |
+
},
|
| 1102 |
+
{
|
| 1103 |
+
"address_id": "ADDR0276",
|
| 1104 |
+
"normalized_address": "h.no. 422 brar chowk, ahmednagar, gujarat"
|
| 1105 |
+
},
|
| 1106 |
+
{
|
| 1107 |
+
"address_id": "ADDR0277",
|
| 1108 |
+
"normalized_address": "22/889 om circle, mira-bhayandar, karnataka"
|
| 1109 |
+
},
|
| 1110 |
+
{
|
| 1111 |
+
"address_id": "ADDR0278",
|
| 1112 |
+
"normalized_address": "h.no. 59 baral marg, mathura, gujarat"
|
| 1113 |
+
},
|
| 1114 |
+
{
|
| 1115 |
+
"address_id": "ADDR0279",
|
| 1116 |
+
"normalized_address": "91/29 chatterjee chowk, asansol, tripura"
|
| 1117 |
+
},
|
| 1118 |
+
{
|
| 1119 |
+
"address_id": "ADDR0280",
|
| 1120 |
+
"normalized_address": "h.no. 81 chandra chowk, satara, goa"
|
| 1121 |
+
},
|
| 1122 |
+
{
|
| 1123 |
+
"address_id": "ADDR0281",
|
| 1124 |
+
"normalized_address": "h.no. 21 patla road, hubliβdharwad, assam"
|
| 1125 |
+
},
|
| 1126 |
+
{
|
| 1127 |
+
"address_id": "ADDR0282",
|
| 1128 |
+
"normalized_address": "747 sathe road, amravati, odisha"
|
| 1129 |
+
},
|
| 1130 |
+
{
|
| 1131 |
+
"address_id": "ADDR0283",
|
| 1132 |
+
"normalized_address": "05 rattan road, udupi, sikkim"
|
| 1133 |
+
},
|
| 1134 |
+
{
|
| 1135 |
+
"address_id": "ADDR0284",
|
| 1136 |
+
"normalized_address": "758 murthy, gwalior, sikkim"
|
| 1137 |
+
},
|
| 1138 |
+
{
|
| 1139 |
+
"address_id": "ADDR0285",
|
| 1140 |
+
"normalized_address": "87 basak road, sambalpur, tamil nadu"
|
| 1141 |
+
},
|
| 1142 |
+
{
|
| 1143 |
+
"address_id": "ADDR0286",
|
| 1144 |
+
"normalized_address": "02/14 dutt marg, srinagar, haryana"
|
| 1145 |
+
},
|
| 1146 |
+
{
|
| 1147 |
+
"address_id": "ADDR0287",
|
| 1148 |
+
"normalized_address": "71 shukla path, deoghar, uttarakhand"
|
| 1149 |
+
},
|
| 1150 |
+
{
|
| 1151 |
+
"address_id": "ADDR0288",
|
| 1152 |
+
"normalized_address": "11 chokshi street, bhiwani, gujarat"
|
| 1153 |
+
},
|
| 1154 |
+
{
|
| 1155 |
+
"address_id": "ADDR0289",
|
| 1156 |
+
"normalized_address": "51 oommen path, rajpur sonarpur, tamil nadu"
|
| 1157 |
+
},
|
| 1158 |
+
{
|
| 1159 |
+
"address_id": "ADDR0290",
|
| 1160 |
+
"normalized_address": "71/470 dugal circle, ulhasnagar, rajasthan"
|
| 1161 |
+
},
|
| 1162 |
+
{
|
| 1163 |
+
"address_id": "ADDR0291",
|
| 1164 |
+
"normalized_address": "590 rai, mirzapur, uttar pradesh"
|
| 1165 |
+
},
|
| 1166 |
+
{
|
| 1167 |
+
"address_id": "ADDR0292",
|
| 1168 |
+
"normalized_address": "73 kakar nagar, bhusawal, himachal pradesh"
|
| 1169 |
+
},
|
| 1170 |
+
{
|
| 1171 |
+
"address_id": "ADDR0293",
|
| 1172 |
+
"normalized_address": "h.no. 21 biswas street, machilipatnam, assam"
|
| 1173 |
+
},
|
| 1174 |
+
{
|
| 1175 |
+
"address_id": "ADDR0294",
|
| 1176 |
+
"normalized_address": "h.no. 76 kala circle, udaipur, uttarakhand"
|
| 1177 |
+
},
|
| 1178 |
+
{
|
| 1179 |
+
"address_id": "ADDR0295",
|
| 1180 |
+
"normalized_address": "h.no. 165 gala road, karnal, maharashtra"
|
| 1181 |
+
},
|
| 1182 |
+
{
|
| 1183 |
+
"address_id": "ADDR0296",
|
| 1184 |
+
"normalized_address": "78 sarkar street, aurangabad, madhya pradesh"
|
| 1185 |
+
},
|
| 1186 |
+
{
|
| 1187 |
+
"address_id": "ADDR0297",
|
| 1188 |
+
"normalized_address": "h.no. 893 dhillon zila, ratlam, andhra pradesh"
|
| 1189 |
+
},
|
| 1190 |
+
{
|
| 1191 |
+
"address_id": "ADDR0298",
|
| 1192 |
+
"normalized_address": "727 comar path, firozabad, mizoram"
|
| 1193 |
+
},
|
| 1194 |
+
{
|
| 1195 |
+
"address_id": "ADDR0299",
|
| 1196 |
+
"normalized_address": "07/279 bansal zila, maheshtala, maharashtra"
|
| 1197 |
+
},
|
| 1198 |
+
{
|
| 1199 |
+
"address_id": "ADDR0300",
|
| 1200 |
+
"normalized_address": "82/963 kadakia path, gangtok, andhra pradesh"
|
| 1201 |
+
},
|
| 1202 |
+
{
|
| 1203 |
+
"address_id": "ADDR0301",
|
| 1204 |
+
"normalized_address": "h.no. 50 mohanty road, panchkula, rajasthan"
|
| 1205 |
+
},
|
| 1206 |
+
{
|
| 1207 |
+
"address_id": "ADDR0302",
|
| 1208 |
+
"normalized_address": "66 pandey path, nagaon, tripura"
|
| 1209 |
+
},
|
| 1210 |
+
{
|
| 1211 |
+
"address_id": "ADDR0303",
|
| 1212 |
+
"normalized_address": "h.no. 12 sangha chowk, belgaum, nagaland"
|
| 1213 |
+
},
|
| 1214 |
+
{
|
| 1215 |
+
"address_id": "ADDR0304",
|
| 1216 |
+
"normalized_address": "28/66 sarkar road, udupi, west bengal"
|
| 1217 |
+
},
|
| 1218 |
+
{
|
| 1219 |
+
"address_id": "ADDR0305",
|
| 1220 |
+
"normalized_address": "h.no. 111 sabharwal nagar, mehsana, telangana"
|
| 1221 |
+
},
|
| 1222 |
+
{
|
| 1223 |
+
"address_id": "ADDR0306",
|
| 1224 |
+
"normalized_address": "81/78 bali, bidar, gujarat"
|
| 1225 |
+
},
|
| 1226 |
+
{
|
| 1227 |
+
"address_id": "ADDR0307",
|
| 1228 |
+
"normalized_address": "786 hayre zila, amravati, kerala"
|
| 1229 |
+
},
|
| 1230 |
+
{
|
| 1231 |
+
"address_id": "ADDR0308",
|
| 1232 |
+
"normalized_address": "66 prasad nagar, guna, jharkhand"
|
| 1233 |
+
},
|
| 1234 |
+
{
|
| 1235 |
+
"address_id": "ADDR0309",
|
| 1236 |
+
"normalized_address": "h.no. 44 khurana marg, vijayanagaram, arunachal pradesh"
|
| 1237 |
+
},
|
| 1238 |
+
{
|
| 1239 |
+
"address_id": "ADDR0310",
|
| 1240 |
+
"normalized_address": "h.no. 025 nadkarni circle, tirunelveli, odisha"
|
| 1241 |
+
},
|
| 1242 |
+
{
|
| 1243 |
+
"address_id": "ADDR0311",
|
| 1244 |
+
"normalized_address": "38 hans marg, faridabad, uttar pradesh"
|
| 1245 |
+
},
|
| 1246 |
+
{
|
| 1247 |
+
"address_id": "ADDR0312",
|
| 1248 |
+
"normalized_address": "62/62 nadkarni marg, junagadh, haryana"
|
| 1249 |
+
},
|
| 1250 |
+
{
|
| 1251 |
+
"address_id": "ADDR0313",
|
| 1252 |
+
"normalized_address": "h.no. 281 ramanathan, begusarai, goa"
|
| 1253 |
+
},
|
| 1254 |
+
{
|
| 1255 |
+
"address_id": "ADDR0314",
|
| 1256 |
+
"normalized_address": "h.no. 31 bal zila, hyderabad, rajasthan"
|
| 1257 |
+
},
|
| 1258 |
+
{
|
| 1259 |
+
"address_id": "ADDR0315",
|
| 1260 |
+
"normalized_address": "20/98 raja zila, bikaner, manipur"
|
| 1261 |
+
},
|
| 1262 |
+
{
|
| 1263 |
+
"address_id": "ADDR0316",
|
| 1264 |
+
"normalized_address": "52/334 wason ganj, burhanpur, tripura"
|
| 1265 |
+
},
|
| 1266 |
+
{
|
| 1267 |
+
"address_id": "ADDR0317",
|
| 1268 |
+
"normalized_address": "h.no. 04 dhawan zila, adoni, west bengal"
|
| 1269 |
+
},
|
| 1270 |
+
{
|
| 1271 |
+
"address_id": "ADDR0318",
|
| 1272 |
+
"normalized_address": "h.no. 179 chhabra zila, ichalkaranji, himachal pradesh"
|
| 1273 |
+
},
|
| 1274 |
+
{
|
| 1275 |
+
"address_id": "ADDR0319",
|
| 1276 |
+
"normalized_address": "117 johal path, salem, meghalaya"
|
| 1277 |
+
},
|
| 1278 |
+
{
|
| 1279 |
+
"address_id": "ADDR0320",
|
| 1280 |
+
"normalized_address": "h.no. 617 kade zila, gandhinagar, karnataka"
|
| 1281 |
+
},
|
| 1282 |
+
{
|
| 1283 |
+
"address_id": "ADDR0321",
|
| 1284 |
+
"normalized_address": "72/240 balay street, tiruvottiyur, kerala"
|
| 1285 |
+
},
|
| 1286 |
+
{
|
| 1287 |
+
"address_id": "ADDR0322",
|
| 1288 |
+
"normalized_address": "99 ahluwalia circle, nagaon, telangana"
|
| 1289 |
+
},
|
| 1290 |
+
{
|
| 1291 |
+
"address_id": "ADDR0323",
|
| 1292 |
+
"normalized_address": "h.no. 13 balan, kadapa, mizoram"
|
| 1293 |
+
},
|
| 1294 |
+
{
|
| 1295 |
+
"address_id": "ADDR0324",
|
| 1296 |
+
"normalized_address": "351 balan ganj, durgapur, haryana"
|
| 1297 |
+
},
|
| 1298 |
+
{
|
| 1299 |
+
"address_id": "ADDR0325",
|
| 1300 |
+
"normalized_address": "h.no. 244 iyengar chowk, karnal, tamil nadu"
|
| 1301 |
+
},
|
| 1302 |
+
{
|
| 1303 |
+
"address_id": "ADDR0326",
|
| 1304 |
+
"normalized_address": "47/76 ratta circle, chandrapur, goa"
|
| 1305 |
+
},
|
| 1306 |
+
{
|
| 1307 |
+
"address_id": "ADDR0327",
|
| 1308 |
+
"normalized_address": "461 muni, tiruppur, telangana"
|
| 1309 |
+
},
|
| 1310 |
+
{
|
| 1311 |
+
"address_id": "ADDR0328",
|
| 1312 |
+
"normalized_address": "67 magar marg, moradabad, punjab"
|
| 1313 |
+
},
|
| 1314 |
+
{
|
| 1315 |
+
"address_id": "ADDR0329",
|
| 1316 |
+
"normalized_address": "63 pandit, rajkot, manipur"
|
| 1317 |
+
},
|
| 1318 |
+
{
|
| 1319 |
+
"address_id": "ADDR0330",
|
| 1320 |
+
"normalized_address": "084 rout, mahbubnagar, uttarakhand"
|
| 1321 |
+
},
|
| 1322 |
+
{
|
| 1323 |
+
"address_id": "ADDR0331",
|
| 1324 |
+
"normalized_address": "85/601 naidu street, gaya, kerala"
|
| 1325 |
+
},
|
| 1326 |
+
{
|
| 1327 |
+
"address_id": "ADDR0332",
|
| 1328 |
+
"normalized_address": "135 dhillon path, bhilai, andhra pradesh"
|
| 1329 |
+
},
|
| 1330 |
+
{
|
| 1331 |
+
"address_id": "ADDR0333",
|
| 1332 |
+
"normalized_address": "h.no. 05 shroff ganj, muzaffarpur, nagaland"
|
| 1333 |
+
},
|
| 1334 |
+
{
|
| 1335 |
+
"address_id": "ADDR0334",
|
| 1336 |
+
"normalized_address": "h.no. 649 vyas ganj, kota, nagaland"
|
| 1337 |
+
},
|
| 1338 |
+
{
|
| 1339 |
+
"address_id": "ADDR0335",
|
| 1340 |
+
"normalized_address": "h.no. 91 sama, ratlam, uttarakhand"
|
| 1341 |
+
},
|
| 1342 |
+
{
|
| 1343 |
+
"address_id": "ADDR0336",
|
| 1344 |
+
"normalized_address": "h.no. 33 tak nagar, ranchi, himachal pradesh"
|
| 1345 |
+
},
|
| 1346 |
+
{
|
| 1347 |
+
"address_id": "ADDR0337",
|
| 1348 |
+
"normalized_address": "11 garg chowk, gudivada, madhya pradesh"
|
| 1349 |
+
},
|
| 1350 |
+
{
|
| 1351 |
+
"address_id": "ADDR0338",
|
| 1352 |
+
"normalized_address": "904 agrawal nagar, anantapuram, chhattisgarh"
|
| 1353 |
+
},
|
| 1354 |
+
{
|
| 1355 |
+
"address_id": "ADDR0339",
|
| 1356 |
+
"normalized_address": "08 baral circle, pune, assam"
|
| 1357 |
+
},
|
| 1358 |
+
{
|
| 1359 |
+
"address_id": "ADDR0340",
|
| 1360 |
+
"normalized_address": "16 maharaj road, sri ganganagar, madhya pradesh"
|
| 1361 |
+
},
|
| 1362 |
+
{
|
| 1363 |
+
"address_id": "ADDR0341",
|
| 1364 |
+
"normalized_address": "h.no. 857 batta, bihar sharif, tamil nadu"
|
| 1365 |
+
},
|
| 1366 |
+
{
|
| 1367 |
+
"address_id": "ADDR0342",
|
| 1368 |
+
"normalized_address": "71 chauhan path, rajahmundry, arunachal pradesh"
|
| 1369 |
+
},
|
| 1370 |
+
{
|
| 1371 |
+
"address_id": "ADDR0343",
|
| 1372 |
+
"normalized_address": "h.no. 215 kara marg, hubliβdharwad, gujarat"
|
| 1373 |
+
},
|
| 1374 |
+
{
|
| 1375 |
+
"address_id": "ADDR0344",
|
| 1376 |
+
"normalized_address": "58/004 choudhry nagar, avadi, assam"
|
| 1377 |
+
},
|
| 1378 |
+
{
|
| 1379 |
+
"address_id": "ADDR0345",
|
| 1380 |
+
"normalized_address": "h.no. 59 madan marg, durgapur, odisha"
|
| 1381 |
+
},
|
| 1382 |
+
{
|
| 1383 |
+
"address_id": "ADDR0346",
|
| 1384 |
+
"normalized_address": "12 divan path, amroha, sikkim"
|
| 1385 |
+
},
|
| 1386 |
+
{
|
| 1387 |
+
"address_id": "ADDR0347",
|
| 1388 |
+
"normalized_address": "h.no. 883 sridhar, parbhani, karnataka"
|
| 1389 |
+
},
|
| 1390 |
+
{
|
| 1391 |
+
"address_id": "ADDR0348",
|
| 1392 |
+
"normalized_address": "73/144 pandit zila, tiruppur, tamil nadu"
|
| 1393 |
+
},
|
| 1394 |
+
{
|
| 1395 |
+
"address_id": "ADDR0349",
|
| 1396 |
+
"normalized_address": "h.no. 170 arya ganj, bhind, uttarakhand"
|
| 1397 |
+
},
|
| 1398 |
+
{
|
| 1399 |
+
"address_id": "ADDR0350",
|
| 1400 |
+
"normalized_address": "37 oak zila, gudivada, tripura"
|
| 1401 |
+
},
|
| 1402 |
+
{
|
| 1403 |
+
"address_id": "ADDR0351",
|
| 1404 |
+
"normalized_address": "12 fraud lane, mumbai, maharashtra"
|
| 1405 |
+
},
|
| 1406 |
+
{
|
| 1407 |
+
"address_id": "ADDR0352",
|
| 1408 |
+
"normalized_address": "45 ring road, delhi, delhi"
|
| 1409 |
+
},
|
| 1410 |
+
{
|
| 1411 |
+
"address_id": "ADDR0353",
|
| 1412 |
+
"normalized_address": "78 scheme nagar, bengaluru, karnataka"
|
| 1413 |
+
},
|
| 1414 |
+
{
|
| 1415 |
+
"address_id": "ADDR0354",
|
| 1416 |
+
"normalized_address": "23 boundary blvd, pune, maharashtra"
|
| 1417 |
+
},
|
| 1418 |
+
{
|
| 1419 |
+
"address_id": "ADDR0355",
|
| 1420 |
+
"normalized_address": "56 ambiguous avenue, hyderabad, telangana"
|
| 1421 |
+
},
|
| 1422 |
+
{
|
| 1423 |
+
"address_id": "ADDR0356",
|
| 1424 |
+
"normalized_address": "89 liminal street, chennai, tamil_nadu"
|
| 1425 |
+
},
|
| 1426 |
+
{
|
| 1427 |
+
"address_id": "ADDR0357",
|
| 1428 |
+
"normalized_address": "33 ordinary street, jaipur, rajasthan"
|
| 1429 |
+
}
|
| 1430 |
+
]
|
data/synthetic/candidate_clusters.json
ADDED
|
@@ -0,0 +1,784 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
{
|
| 3 |
+
"cluster_id": "CAND01",
|
| 4 |
+
"customer_ids": [
|
| 5 |
+
"CUST0041",
|
| 6 |
+
"CUST0042",
|
| 7 |
+
"CUST0043",
|
| 8 |
+
"CUST0044"
|
| 9 |
+
],
|
| 10 |
+
"size": 4,
|
| 11 |
+
"strong_link_count": 6,
|
| 12 |
+
"weak_link_count": 0,
|
| 13 |
+
"formation_type": "strong_anchored",
|
| 14 |
+
"method": "connected_components"
|
| 15 |
+
},
|
| 16 |
+
{
|
| 17 |
+
"cluster_id": "CAND02",
|
| 18 |
+
"customer_ids": [
|
| 19 |
+
"CUST0009",
|
| 20 |
+
"CUST0010",
|
| 21 |
+
"CUST0011",
|
| 22 |
+
"CUST0012",
|
| 23 |
+
"CUST0013"
|
| 24 |
+
],
|
| 25 |
+
"size": 5,
|
| 26 |
+
"strong_link_count": 10,
|
| 27 |
+
"weak_link_count": 0,
|
| 28 |
+
"formation_type": "strong_anchored",
|
| 29 |
+
"method": "connected_components"
|
| 30 |
+
},
|
| 31 |
+
{
|
| 32 |
+
"cluster_id": "CAND03",
|
| 33 |
+
"customer_ids": [
|
| 34 |
+
"CUST0001",
|
| 35 |
+
"CUST0002",
|
| 36 |
+
"CUST0003"
|
| 37 |
+
],
|
| 38 |
+
"size": 3,
|
| 39 |
+
"strong_link_count": 3,
|
| 40 |
+
"weak_link_count": 0,
|
| 41 |
+
"formation_type": "strong_anchored",
|
| 42 |
+
"method": "connected_components"
|
| 43 |
+
},
|
| 44 |
+
{
|
| 45 |
+
"cluster_id": "CAND04",
|
| 46 |
+
"customer_ids": [
|
| 47 |
+
"CUST0014",
|
| 48 |
+
"CUST0015",
|
| 49 |
+
"CUST0016",
|
| 50 |
+
"CUST0017",
|
| 51 |
+
"CUST0018"
|
| 52 |
+
],
|
| 53 |
+
"size": 5,
|
| 54 |
+
"strong_link_count": 10,
|
| 55 |
+
"weak_link_count": 0,
|
| 56 |
+
"formation_type": "strong_anchored",
|
| 57 |
+
"method": "connected_components"
|
| 58 |
+
},
|
| 59 |
+
{
|
| 60 |
+
"cluster_id": "CAND05",
|
| 61 |
+
"customer_ids": [
|
| 62 |
+
"CUST0033",
|
| 63 |
+
"CUST0034",
|
| 64 |
+
"CUST0035"
|
| 65 |
+
],
|
| 66 |
+
"size": 3,
|
| 67 |
+
"strong_link_count": 3,
|
| 68 |
+
"weak_link_count": 0,
|
| 69 |
+
"formation_type": "strong_anchored",
|
| 70 |
+
"method": "connected_components"
|
| 71 |
+
},
|
| 72 |
+
{
|
| 73 |
+
"cluster_id": "CAND06",
|
| 74 |
+
"customer_ids": [
|
| 75 |
+
"CUST0036",
|
| 76 |
+
"CUST0037",
|
| 77 |
+
"CUST0038",
|
| 78 |
+
"CUST0039",
|
| 79 |
+
"CUST0040"
|
| 80 |
+
],
|
| 81 |
+
"size": 5,
|
| 82 |
+
"strong_link_count": 10,
|
| 83 |
+
"weak_link_count": 0,
|
| 84 |
+
"formation_type": "strong_anchored",
|
| 85 |
+
"method": "connected_components"
|
| 86 |
+
},
|
| 87 |
+
{
|
| 88 |
+
"cluster_id": "CAND07",
|
| 89 |
+
"customer_ids": [
|
| 90 |
+
"CUST0019",
|
| 91 |
+
"CUST0020",
|
| 92 |
+
"CUST0021",
|
| 93 |
+
"CUST0022",
|
| 94 |
+
"CUST0023"
|
| 95 |
+
],
|
| 96 |
+
"size": 5,
|
| 97 |
+
"strong_link_count": 10,
|
| 98 |
+
"weak_link_count": 0,
|
| 99 |
+
"formation_type": "strong_anchored",
|
| 100 |
+
"method": "connected_components"
|
| 101 |
+
},
|
| 102 |
+
{
|
| 103 |
+
"cluster_id": "CAND08",
|
| 104 |
+
"customer_ids": [
|
| 105 |
+
"CUST0501",
|
| 106 |
+
"CUST0502",
|
| 107 |
+
"CUST0503"
|
| 108 |
+
],
|
| 109 |
+
"size": 3,
|
| 110 |
+
"strong_link_count": 3,
|
| 111 |
+
"weak_link_count": 0,
|
| 112 |
+
"formation_type": "strong_anchored",
|
| 113 |
+
"method": "connected_components"
|
| 114 |
+
},
|
| 115 |
+
{
|
| 116 |
+
"cluster_id": "CAND09",
|
| 117 |
+
"customer_ids": [
|
| 118 |
+
"CUST0024",
|
| 119 |
+
"CUST0025",
|
| 120 |
+
"CUST0026",
|
| 121 |
+
"CUST0027",
|
| 122 |
+
"CUST0028",
|
| 123 |
+
"CUST0029"
|
| 124 |
+
],
|
| 125 |
+
"size": 6,
|
| 126 |
+
"strong_link_count": 15,
|
| 127 |
+
"weak_link_count": 0,
|
| 128 |
+
"formation_type": "strong_anchored",
|
| 129 |
+
"method": "connected_components"
|
| 130 |
+
},
|
| 131 |
+
{
|
| 132 |
+
"cluster_id": "CAND10",
|
| 133 |
+
"customer_ids": [
|
| 134 |
+
"CUST0004",
|
| 135 |
+
"CUST0005",
|
| 136 |
+
"CUST0006",
|
| 137 |
+
"CUST0007",
|
| 138 |
+
"CUST0008"
|
| 139 |
+
],
|
| 140 |
+
"size": 5,
|
| 141 |
+
"strong_link_count": 7,
|
| 142 |
+
"weak_link_count": 0,
|
| 143 |
+
"formation_type": "strong_anchored",
|
| 144 |
+
"method": "connected_components"
|
| 145 |
+
},
|
| 146 |
+
{
|
| 147 |
+
"cluster_id": "CAND11",
|
| 148 |
+
"customer_ids": [
|
| 149 |
+
"CUST0030",
|
| 150 |
+
"CUST0031",
|
| 151 |
+
"CUST0032"
|
| 152 |
+
],
|
| 153 |
+
"size": 3,
|
| 154 |
+
"strong_link_count": 2,
|
| 155 |
+
"weak_link_count": 0,
|
| 156 |
+
"formation_type": "strong_anchored",
|
| 157 |
+
"method": "connected_components"
|
| 158 |
+
},
|
| 159 |
+
{
|
| 160 |
+
"cluster_id": "CAND12",
|
| 161 |
+
"customer_ids": [
|
| 162 |
+
"CUST0001",
|
| 163 |
+
"CUST0019",
|
| 164 |
+
"CUST0040",
|
| 165 |
+
"CUST0126",
|
| 166 |
+
"CUST0138",
|
| 167 |
+
"CUST0168",
|
| 168 |
+
"CUST0211",
|
| 169 |
+
"CUST0219",
|
| 170 |
+
"CUST0258",
|
| 171 |
+
"CUST0281",
|
| 172 |
+
"CUST0292",
|
| 173 |
+
"CUST0322",
|
| 174 |
+
"CUST0325",
|
| 175 |
+
"CUST0371",
|
| 176 |
+
"CUST0373",
|
| 177 |
+
"CUST0400",
|
| 178 |
+
"CUST0419",
|
| 179 |
+
"CUST0465"
|
| 180 |
+
],
|
| 181 |
+
"size": 18,
|
| 182 |
+
"strong_link_count": 0,
|
| 183 |
+
"weak_link_count": 41,
|
| 184 |
+
"formation_type": "weak_only",
|
| 185 |
+
"method": "louvain"
|
| 186 |
+
},
|
| 187 |
+
{
|
| 188 |
+
"cluster_id": "CAND13",
|
| 189 |
+
"customer_ids": [
|
| 190 |
+
"CUST0002",
|
| 191 |
+
"CUST0009",
|
| 192 |
+
"CUST0020",
|
| 193 |
+
"CUST0041",
|
| 194 |
+
"CUST0064",
|
| 195 |
+
"CUST0073",
|
| 196 |
+
"CUST0074",
|
| 197 |
+
"CUST0080",
|
| 198 |
+
"CUST0081",
|
| 199 |
+
"CUST0086",
|
| 200 |
+
"CUST0089",
|
| 201 |
+
"CUST0103",
|
| 202 |
+
"CUST0162",
|
| 203 |
+
"CUST0167",
|
| 204 |
+
"CUST0173",
|
| 205 |
+
"CUST0181",
|
| 206 |
+
"CUST0226",
|
| 207 |
+
"CUST0240",
|
| 208 |
+
"CUST0253",
|
| 209 |
+
"CUST0262",
|
| 210 |
+
"CUST0272",
|
| 211 |
+
"CUST0286",
|
| 212 |
+
"CUST0287",
|
| 213 |
+
"CUST0324",
|
| 214 |
+
"CUST0331",
|
| 215 |
+
"CUST0333",
|
| 216 |
+
"CUST0369",
|
| 217 |
+
"CUST0392",
|
| 218 |
+
"CUST0393",
|
| 219 |
+
"CUST0398",
|
| 220 |
+
"CUST0406",
|
| 221 |
+
"CUST0410",
|
| 222 |
+
"CUST0411",
|
| 223 |
+
"CUST0413",
|
| 224 |
+
"CUST0415",
|
| 225 |
+
"CUST0423",
|
| 226 |
+
"CUST0446",
|
| 227 |
+
"CUST0468",
|
| 228 |
+
"CUST0476",
|
| 229 |
+
"CUST0478",
|
| 230 |
+
"CUST0485"
|
| 231 |
+
],
|
| 232 |
+
"size": 41,
|
| 233 |
+
"strong_link_count": 0,
|
| 234 |
+
"weak_link_count": 146,
|
| 235 |
+
"formation_type": "weak_only",
|
| 236 |
+
"method": "louvain"
|
| 237 |
+
},
|
| 238 |
+
{
|
| 239 |
+
"cluster_id": "CAND14",
|
| 240 |
+
"customer_ids": [
|
| 241 |
+
"CUST0003",
|
| 242 |
+
"CUST0012",
|
| 243 |
+
"CUST0043",
|
| 244 |
+
"CUST0077",
|
| 245 |
+
"CUST0088",
|
| 246 |
+
"CUST0098",
|
| 247 |
+
"CUST0109",
|
| 248 |
+
"CUST0125",
|
| 249 |
+
"CUST0139",
|
| 250 |
+
"CUST0153",
|
| 251 |
+
"CUST0159",
|
| 252 |
+
"CUST0166",
|
| 253 |
+
"CUST0180",
|
| 254 |
+
"CUST0201",
|
| 255 |
+
"CUST0209",
|
| 256 |
+
"CUST0245",
|
| 257 |
+
"CUST0261",
|
| 258 |
+
"CUST0265",
|
| 259 |
+
"CUST0273",
|
| 260 |
+
"CUST0277",
|
| 261 |
+
"CUST0297",
|
| 262 |
+
"CUST0315",
|
| 263 |
+
"CUST0334",
|
| 264 |
+
"CUST0347",
|
| 265 |
+
"CUST0381",
|
| 266 |
+
"CUST0405",
|
| 267 |
+
"CUST0412",
|
| 268 |
+
"CUST0428",
|
| 269 |
+
"CUST0429",
|
| 270 |
+
"CUST0462",
|
| 271 |
+
"CUST0471"
|
| 272 |
+
],
|
| 273 |
+
"size": 31,
|
| 274 |
+
"strong_link_count": 0,
|
| 275 |
+
"weak_link_count": 84,
|
| 276 |
+
"formation_type": "weak_only",
|
| 277 |
+
"method": "louvain"
|
| 278 |
+
},
|
| 279 |
+
{
|
| 280 |
+
"cluster_id": "CAND15",
|
| 281 |
+
"customer_ids": [
|
| 282 |
+
"CUST0004",
|
| 283 |
+
"CUST0008",
|
| 284 |
+
"CUST0027",
|
| 285 |
+
"CUST0030",
|
| 286 |
+
"CUST0042",
|
| 287 |
+
"CUST0063",
|
| 288 |
+
"CUST0075",
|
| 289 |
+
"CUST0087",
|
| 290 |
+
"CUST0110",
|
| 291 |
+
"CUST0117",
|
| 292 |
+
"CUST0120",
|
| 293 |
+
"CUST0133",
|
| 294 |
+
"CUST0135",
|
| 295 |
+
"CUST0137",
|
| 296 |
+
"CUST0144",
|
| 297 |
+
"CUST0152",
|
| 298 |
+
"CUST0154",
|
| 299 |
+
"CUST0163",
|
| 300 |
+
"CUST0170",
|
| 301 |
+
"CUST0178",
|
| 302 |
+
"CUST0179",
|
| 303 |
+
"CUST0195",
|
| 304 |
+
"CUST0198",
|
| 305 |
+
"CUST0208",
|
| 306 |
+
"CUST0210",
|
| 307 |
+
"CUST0221",
|
| 308 |
+
"CUST0228",
|
| 309 |
+
"CUST0231",
|
| 310 |
+
"CUST0237",
|
| 311 |
+
"CUST0246",
|
| 312 |
+
"CUST0251",
|
| 313 |
+
"CUST0254",
|
| 314 |
+
"CUST0266",
|
| 315 |
+
"CUST0282",
|
| 316 |
+
"CUST0295",
|
| 317 |
+
"CUST0300",
|
| 318 |
+
"CUST0303",
|
| 319 |
+
"CUST0304",
|
| 320 |
+
"CUST0335",
|
| 321 |
+
"CUST0355",
|
| 322 |
+
"CUST0365",
|
| 323 |
+
"CUST0399",
|
| 324 |
+
"CUST0420",
|
| 325 |
+
"CUST0425",
|
| 326 |
+
"CUST0470",
|
| 327 |
+
"CUST0483",
|
| 328 |
+
"CUST0486",
|
| 329 |
+
"CUST0487",
|
| 330 |
+
"CUST0491",
|
| 331 |
+
"CUST0492",
|
| 332 |
+
"CUST0498"
|
| 333 |
+
],
|
| 334 |
+
"size": 51,
|
| 335 |
+
"strong_link_count": 1,
|
| 336 |
+
"weak_link_count": 167,
|
| 337 |
+
"formation_type": "weak_only",
|
| 338 |
+
"method": "louvain"
|
| 339 |
+
},
|
| 340 |
+
{
|
| 341 |
+
"cluster_id": "CAND16",
|
| 342 |
+
"customer_ids": [
|
| 343 |
+
"CUST0005",
|
| 344 |
+
"CUST0022",
|
| 345 |
+
"CUST0028",
|
| 346 |
+
"CUST0038",
|
| 347 |
+
"CUST0102",
|
| 348 |
+
"CUST0111",
|
| 349 |
+
"CUST0113",
|
| 350 |
+
"CUST0140",
|
| 351 |
+
"CUST0161",
|
| 352 |
+
"CUST0171",
|
| 353 |
+
"CUST0177",
|
| 354 |
+
"CUST0202",
|
| 355 |
+
"CUST0222",
|
| 356 |
+
"CUST0235",
|
| 357 |
+
"CUST0252",
|
| 358 |
+
"CUST0257",
|
| 359 |
+
"CUST0263",
|
| 360 |
+
"CUST0288",
|
| 361 |
+
"CUST0293",
|
| 362 |
+
"CUST0299",
|
| 363 |
+
"CUST0308",
|
| 364 |
+
"CUST0311",
|
| 365 |
+
"CUST0353",
|
| 366 |
+
"CUST0357",
|
| 367 |
+
"CUST0364",
|
| 368 |
+
"CUST0370",
|
| 369 |
+
"CUST0383",
|
| 370 |
+
"CUST0386",
|
| 371 |
+
"CUST0387",
|
| 372 |
+
"CUST0391",
|
| 373 |
+
"CUST0396",
|
| 374 |
+
"CUST0438",
|
| 375 |
+
"CUST0442",
|
| 376 |
+
"CUST0456",
|
| 377 |
+
"CUST0460",
|
| 378 |
+
"CUST0488",
|
| 379 |
+
"CUST0490",
|
| 380 |
+
"CUST0495",
|
| 381 |
+
"CUST0496",
|
| 382 |
+
"CUST0500"
|
| 383 |
+
],
|
| 384 |
+
"size": 40,
|
| 385 |
+
"strong_link_count": 0,
|
| 386 |
+
"weak_link_count": 112,
|
| 387 |
+
"formation_type": "weak_only",
|
| 388 |
+
"method": "louvain"
|
| 389 |
+
},
|
| 390 |
+
{
|
| 391 |
+
"cluster_id": "CAND17",
|
| 392 |
+
"customer_ids": [
|
| 393 |
+
"CUST0006",
|
| 394 |
+
"CUST0011",
|
| 395 |
+
"CUST0024",
|
| 396 |
+
"CUST0025",
|
| 397 |
+
"CUST0033",
|
| 398 |
+
"CUST0044",
|
| 399 |
+
"CUST0079",
|
| 400 |
+
"CUST0084",
|
| 401 |
+
"CUST0101",
|
| 402 |
+
"CUST0107",
|
| 403 |
+
"CUST0108",
|
| 404 |
+
"CUST0114",
|
| 405 |
+
"CUST0132",
|
| 406 |
+
"CUST0145",
|
| 407 |
+
"CUST0157",
|
| 408 |
+
"CUST0172",
|
| 409 |
+
"CUST0227",
|
| 410 |
+
"CUST0244",
|
| 411 |
+
"CUST0255",
|
| 412 |
+
"CUST0256",
|
| 413 |
+
"CUST0267",
|
| 414 |
+
"CUST0271",
|
| 415 |
+
"CUST0284",
|
| 416 |
+
"CUST0291",
|
| 417 |
+
"CUST0296",
|
| 418 |
+
"CUST0316",
|
| 419 |
+
"CUST0319",
|
| 420 |
+
"CUST0329",
|
| 421 |
+
"CUST0336",
|
| 422 |
+
"CUST0342",
|
| 423 |
+
"CUST0348",
|
| 424 |
+
"CUST0349",
|
| 425 |
+
"CUST0367",
|
| 426 |
+
"CUST0375",
|
| 427 |
+
"CUST0389",
|
| 428 |
+
"CUST0407",
|
| 429 |
+
"CUST0455",
|
| 430 |
+
"CUST0489",
|
| 431 |
+
"CUST0499"
|
| 432 |
+
],
|
| 433 |
+
"size": 39,
|
| 434 |
+
"strong_link_count": 1,
|
| 435 |
+
"weak_link_count": 95,
|
| 436 |
+
"formation_type": "weak_only",
|
| 437 |
+
"method": "louvain"
|
| 438 |
+
},
|
| 439 |
+
{
|
| 440 |
+
"cluster_id": "CAND18",
|
| 441 |
+
"customer_ids": [
|
| 442 |
+
"CUST0007",
|
| 443 |
+
"CUST0014",
|
| 444 |
+
"CUST0015",
|
| 445 |
+
"CUST0016",
|
| 446 |
+
"CUST0032",
|
| 447 |
+
"CUST0037",
|
| 448 |
+
"CUST0065",
|
| 449 |
+
"CUST0069",
|
| 450 |
+
"CUST0070",
|
| 451 |
+
"CUST0095",
|
| 452 |
+
"CUST0106",
|
| 453 |
+
"CUST0115",
|
| 454 |
+
"CUST0124",
|
| 455 |
+
"CUST0131",
|
| 456 |
+
"CUST0149",
|
| 457 |
+
"CUST0191",
|
| 458 |
+
"CUST0200",
|
| 459 |
+
"CUST0204",
|
| 460 |
+
"CUST0215",
|
| 461 |
+
"CUST0218",
|
| 462 |
+
"CUST0223",
|
| 463 |
+
"CUST0238",
|
| 464 |
+
"CUST0239",
|
| 465 |
+
"CUST0241",
|
| 466 |
+
"CUST0242",
|
| 467 |
+
"CUST0264",
|
| 468 |
+
"CUST0276",
|
| 469 |
+
"CUST0280",
|
| 470 |
+
"CUST0305",
|
| 471 |
+
"CUST0314",
|
| 472 |
+
"CUST0323",
|
| 473 |
+
"CUST0327",
|
| 474 |
+
"CUST0339",
|
| 475 |
+
"CUST0350",
|
| 476 |
+
"CUST0352",
|
| 477 |
+
"CUST0356",
|
| 478 |
+
"CUST0358",
|
| 479 |
+
"CUST0362",
|
| 480 |
+
"CUST0379",
|
| 481 |
+
"CUST0401",
|
| 482 |
+
"CUST0418",
|
| 483 |
+
"CUST0440",
|
| 484 |
+
"CUST0443",
|
| 485 |
+
"CUST0449",
|
| 486 |
+
"CUST0479"
|
| 487 |
+
],
|
| 488 |
+
"size": 45,
|
| 489 |
+
"strong_link_count": 3,
|
| 490 |
+
"weak_link_count": 106,
|
| 491 |
+
"formation_type": "weak_only",
|
| 492 |
+
"method": "louvain"
|
| 493 |
+
},
|
| 494 |
+
{
|
| 495 |
+
"cluster_id": "CAND19",
|
| 496 |
+
"customer_ids": [
|
| 497 |
+
"CUST0010",
|
| 498 |
+
"CUST0023",
|
| 499 |
+
"CUST0029",
|
| 500 |
+
"CUST0090",
|
| 501 |
+
"CUST0119",
|
| 502 |
+
"CUST0121",
|
| 503 |
+
"CUST0129",
|
| 504 |
+
"CUST0141",
|
| 505 |
+
"CUST0143",
|
| 506 |
+
"CUST0155",
|
| 507 |
+
"CUST0196",
|
| 508 |
+
"CUST0207",
|
| 509 |
+
"CUST0230",
|
| 510 |
+
"CUST0233",
|
| 511 |
+
"CUST0247",
|
| 512 |
+
"CUST0330",
|
| 513 |
+
"CUST0338",
|
| 514 |
+
"CUST0372",
|
| 515 |
+
"CUST0374",
|
| 516 |
+
"CUST0380",
|
| 517 |
+
"CUST0461",
|
| 518 |
+
"CUST0467",
|
| 519 |
+
"CUST0480",
|
| 520 |
+
"CUST0493"
|
| 521 |
+
],
|
| 522 |
+
"size": 24,
|
| 523 |
+
"strong_link_count": 0,
|
| 524 |
+
"weak_link_count": 47,
|
| 525 |
+
"formation_type": "weak_only",
|
| 526 |
+
"method": "louvain"
|
| 527 |
+
},
|
| 528 |
+
{
|
| 529 |
+
"cluster_id": "CAND20",
|
| 530 |
+
"customer_ids": [
|
| 531 |
+
"CUST0013",
|
| 532 |
+
"CUST0026",
|
| 533 |
+
"CUST0031",
|
| 534 |
+
"CUST0035",
|
| 535 |
+
"CUST0039",
|
| 536 |
+
"CUST0067",
|
| 537 |
+
"CUST0068",
|
| 538 |
+
"CUST0094",
|
| 539 |
+
"CUST0116",
|
| 540 |
+
"CUST0122",
|
| 541 |
+
"CUST0128",
|
| 542 |
+
"CUST0184",
|
| 543 |
+
"CUST0193",
|
| 544 |
+
"CUST0203",
|
| 545 |
+
"CUST0212",
|
| 546 |
+
"CUST0217",
|
| 547 |
+
"CUST0248",
|
| 548 |
+
"CUST0268",
|
| 549 |
+
"CUST0283",
|
| 550 |
+
"CUST0312",
|
| 551 |
+
"CUST0340",
|
| 552 |
+
"CUST0351",
|
| 553 |
+
"CUST0384",
|
| 554 |
+
"CUST0402",
|
| 555 |
+
"CUST0417",
|
| 556 |
+
"CUST0427",
|
| 557 |
+
"CUST0430",
|
| 558 |
+
"CUST0434",
|
| 559 |
+
"CUST0451",
|
| 560 |
+
"CUST0463",
|
| 561 |
+
"CUST0466",
|
| 562 |
+
"CUST0469",
|
| 563 |
+
"CUST0473",
|
| 564 |
+
"CUST0482",
|
| 565 |
+
"CUST0497"
|
| 566 |
+
],
|
| 567 |
+
"size": 35,
|
| 568 |
+
"strong_link_count": 0,
|
| 569 |
+
"weak_link_count": 84,
|
| 570 |
+
"formation_type": "weak_only",
|
| 571 |
+
"method": "louvain"
|
| 572 |
+
},
|
| 573 |
+
{
|
| 574 |
+
"cluster_id": "CAND21",
|
| 575 |
+
"customer_ids": [
|
| 576 |
+
"CUST0017",
|
| 577 |
+
"CUST0036",
|
| 578 |
+
"CUST0062",
|
| 579 |
+
"CUST0071",
|
| 580 |
+
"CUST0082",
|
| 581 |
+
"CUST0083",
|
| 582 |
+
"CUST0085",
|
| 583 |
+
"CUST0096",
|
| 584 |
+
"CUST0123",
|
| 585 |
+
"CUST0142",
|
| 586 |
+
"CUST0147",
|
| 587 |
+
"CUST0175",
|
| 588 |
+
"CUST0189",
|
| 589 |
+
"CUST0216",
|
| 590 |
+
"CUST0220",
|
| 591 |
+
"CUST0224",
|
| 592 |
+
"CUST0232",
|
| 593 |
+
"CUST0234",
|
| 594 |
+
"CUST0306",
|
| 595 |
+
"CUST0328",
|
| 596 |
+
"CUST0337",
|
| 597 |
+
"CUST0341",
|
| 598 |
+
"CUST0345",
|
| 599 |
+
"CUST0346",
|
| 600 |
+
"CUST0361",
|
| 601 |
+
"CUST0388",
|
| 602 |
+
"CUST0421",
|
| 603 |
+
"CUST0426",
|
| 604 |
+
"CUST0433",
|
| 605 |
+
"CUST0435",
|
| 606 |
+
"CUST0444",
|
| 607 |
+
"CUST0450",
|
| 608 |
+
"CUST0454",
|
| 609 |
+
"CUST0477"
|
| 610 |
+
],
|
| 611 |
+
"size": 34,
|
| 612 |
+
"strong_link_count": 0,
|
| 613 |
+
"weak_link_count": 79,
|
| 614 |
+
"formation_type": "weak_only",
|
| 615 |
+
"method": "louvain"
|
| 616 |
+
},
|
| 617 |
+
{
|
| 618 |
+
"cluster_id": "CAND22",
|
| 619 |
+
"customer_ids": [
|
| 620 |
+
"CUST0018",
|
| 621 |
+
"CUST0021",
|
| 622 |
+
"CUST0091",
|
| 623 |
+
"CUST0092",
|
| 624 |
+
"CUST0112",
|
| 625 |
+
"CUST0160",
|
| 626 |
+
"CUST0174",
|
| 627 |
+
"CUST0187",
|
| 628 |
+
"CUST0270",
|
| 629 |
+
"CUST0298",
|
| 630 |
+
"CUST0307",
|
| 631 |
+
"CUST0310",
|
| 632 |
+
"CUST0332",
|
| 633 |
+
"CUST0343",
|
| 634 |
+
"CUST0431",
|
| 635 |
+
"CUST0474",
|
| 636 |
+
"CUST0475",
|
| 637 |
+
"CUST0494"
|
| 638 |
+
],
|
| 639 |
+
"size": 18,
|
| 640 |
+
"strong_link_count": 0,
|
| 641 |
+
"weak_link_count": 35,
|
| 642 |
+
"formation_type": "weak_only",
|
| 643 |
+
"method": "louvain"
|
| 644 |
+
},
|
| 645 |
+
{
|
| 646 |
+
"cluster_id": "CAND23",
|
| 647 |
+
"customer_ids": [
|
| 648 |
+
"CUST0034",
|
| 649 |
+
"CUST0066",
|
| 650 |
+
"CUST0078",
|
| 651 |
+
"CUST0100",
|
| 652 |
+
"CUST0104",
|
| 653 |
+
"CUST0134",
|
| 654 |
+
"CUST0146",
|
| 655 |
+
"CUST0150",
|
| 656 |
+
"CUST0151",
|
| 657 |
+
"CUST0158",
|
| 658 |
+
"CUST0182",
|
| 659 |
+
"CUST0183",
|
| 660 |
+
"CUST0185",
|
| 661 |
+
"CUST0188",
|
| 662 |
+
"CUST0190",
|
| 663 |
+
"CUST0259",
|
| 664 |
+
"CUST0269",
|
| 665 |
+
"CUST0279",
|
| 666 |
+
"CUST0285",
|
| 667 |
+
"CUST0289",
|
| 668 |
+
"CUST0301",
|
| 669 |
+
"CUST0302",
|
| 670 |
+
"CUST0344",
|
| 671 |
+
"CUST0354",
|
| 672 |
+
"CUST0366",
|
| 673 |
+
"CUST0368",
|
| 674 |
+
"CUST0378",
|
| 675 |
+
"CUST0404",
|
| 676 |
+
"CUST0408",
|
| 677 |
+
"CUST0432",
|
| 678 |
+
"CUST0436",
|
| 679 |
+
"CUST0437",
|
| 680 |
+
"CUST0439",
|
| 681 |
+
"CUST0441",
|
| 682 |
+
"CUST0447",
|
| 683 |
+
"CUST0448",
|
| 684 |
+
"CUST0457",
|
| 685 |
+
"CUST0481"
|
| 686 |
+
],
|
| 687 |
+
"size": 38,
|
| 688 |
+
"strong_link_count": 0,
|
| 689 |
+
"weak_link_count": 90,
|
| 690 |
+
"formation_type": "weak_only",
|
| 691 |
+
"method": "louvain"
|
| 692 |
+
},
|
| 693 |
+
{
|
| 694 |
+
"cluster_id": "CAND24",
|
| 695 |
+
"customer_ids": [
|
| 696 |
+
"CUST0061",
|
| 697 |
+
"CUST0093",
|
| 698 |
+
"CUST0105",
|
| 699 |
+
"CUST0130",
|
| 700 |
+
"CUST0136",
|
| 701 |
+
"CUST0148",
|
| 702 |
+
"CUST0164",
|
| 703 |
+
"CUST0186",
|
| 704 |
+
"CUST0197",
|
| 705 |
+
"CUST0205",
|
| 706 |
+
"CUST0206",
|
| 707 |
+
"CUST0214",
|
| 708 |
+
"CUST0260",
|
| 709 |
+
"CUST0309",
|
| 710 |
+
"CUST0320",
|
| 711 |
+
"CUST0321",
|
| 712 |
+
"CUST0359",
|
| 713 |
+
"CUST0363",
|
| 714 |
+
"CUST0376",
|
| 715 |
+
"CUST0377",
|
| 716 |
+
"CUST0385",
|
| 717 |
+
"CUST0394",
|
| 718 |
+
"CUST0403",
|
| 719 |
+
"CUST0416",
|
| 720 |
+
"CUST0424",
|
| 721 |
+
"CUST0453"
|
| 722 |
+
],
|
| 723 |
+
"size": 26,
|
| 724 |
+
"strong_link_count": 0,
|
| 725 |
+
"weak_link_count": 71,
|
| 726 |
+
"formation_type": "weak_only",
|
| 727 |
+
"method": "louvain"
|
| 728 |
+
},
|
| 729 |
+
{
|
| 730 |
+
"cluster_id": "CAND25",
|
| 731 |
+
"customer_ids": [
|
| 732 |
+
"CUST0045",
|
| 733 |
+
"CUST0046",
|
| 734 |
+
"CUST0047",
|
| 735 |
+
"CUST0048"
|
| 736 |
+
],
|
| 737 |
+
"size": 4,
|
| 738 |
+
"strong_link_count": 0,
|
| 739 |
+
"weak_link_count": 6,
|
| 740 |
+
"formation_type": "weak_only",
|
| 741 |
+
"method": "connected_components"
|
| 742 |
+
},
|
| 743 |
+
{
|
| 744 |
+
"cluster_id": "CAND26",
|
| 745 |
+
"customer_ids": [
|
| 746 |
+
"CUST0049",
|
| 747 |
+
"CUST0050",
|
| 748 |
+
"CUST0051",
|
| 749 |
+
"CUST0052"
|
| 750 |
+
],
|
| 751 |
+
"size": 4,
|
| 752 |
+
"strong_link_count": 0,
|
| 753 |
+
"weak_link_count": 6,
|
| 754 |
+
"formation_type": "weak_only",
|
| 755 |
+
"method": "connected_components"
|
| 756 |
+
},
|
| 757 |
+
{
|
| 758 |
+
"cluster_id": "CAND27",
|
| 759 |
+
"customer_ids": [
|
| 760 |
+
"CUST0053",
|
| 761 |
+
"CUST0054",
|
| 762 |
+
"CUST0055",
|
| 763 |
+
"CUST0056"
|
| 764 |
+
],
|
| 765 |
+
"size": 4,
|
| 766 |
+
"strong_link_count": 0,
|
| 767 |
+
"weak_link_count": 6,
|
| 768 |
+
"formation_type": "weak_only",
|
| 769 |
+
"method": "connected_components"
|
| 770 |
+
},
|
| 771 |
+
{
|
| 772 |
+
"cluster_id": "CAND28",
|
| 773 |
+
"customer_ids": [
|
| 774 |
+
"CUST0504",
|
| 775 |
+
"CUST0505",
|
| 776 |
+
"CUST0506"
|
| 777 |
+
],
|
| 778 |
+
"size": 3,
|
| 779 |
+
"strong_link_count": 0,
|
| 780 |
+
"weak_link_count": 3,
|
| 781 |
+
"formation_type": "weak_only",
|
| 782 |
+
"method": "connected_components"
|
| 783 |
+
}
|
| 784 |
+
]
|
data/synthetic/cases_demo.json
ADDED
|
@@ -0,0 +1,1027 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
{
|
| 3 |
+
"case_id": "CASE01",
|
| 4 |
+
"cluster_id": "CAND01",
|
| 5 |
+
"customer_ids": [
|
| 6 |
+
"CUST0041",
|
| 7 |
+
"CUST0042",
|
| 8 |
+
"CUST0043",
|
| 9 |
+
"CUST0044"
|
| 10 |
+
],
|
| 11 |
+
"risk_probability": 0.9958773824170732,
|
| 12 |
+
"policy_decision": "escalate",
|
| 13 |
+
"llm_narrative": "The four customers (CUST0041, CUST0042, CUST0043, CUST0044) form a strongβanchored cluster with six strong links and no weak links, indicating tightly coordinated activity. Their combined purchase total of $58,186 is accompanied by a 33.3% return rate and a 16.7% chargeback rate, further supporting fraudulent behavior.",
|
| 14 |
+
"llm_confidence_statement": "The model assigns a risk probability of 99.6%, indicating very high confidence in the escalation decision.",
|
| 15 |
+
"action_taken": {
|
| 16 |
+
"tool": "razorpay.Client.order.create + order.edit + order.fetch",
|
| 17 |
+
"order_id": "order_TSeidafHmbAnDR",
|
| 18 |
+
"razorpay_status": "created",
|
| 19 |
+
"notes_written": {
|
| 20 |
+
"case_id": "CASE01",
|
| 21 |
+
"cluster_id": "CAND01",
|
| 22 |
+
"ringguard_status": "escalate_flagged",
|
| 23 |
+
"action_label": "FRAUD_RING_ESCALATE",
|
| 24 |
+
"risk_score": "0.9959",
|
| 25 |
+
"action_by": "RingGuard_v3",
|
| 26 |
+
"action_timestamp": "2026-08-22T02:47:10.102605+00:00"
|
| 27 |
+
},
|
| 28 |
+
"notes_verified": true,
|
| 29 |
+
"timestamp": "2026-08-22T02:47:10.941027+00:00",
|
| 30 |
+
"test_mode": true,
|
| 31 |
+
"error": null
|
| 32 |
+
},
|
| 33 |
+
"timestamp": "2026-08-22T02:42:02.088359+00:00"
|
| 34 |
+
},
|
| 35 |
+
{
|
| 36 |
+
"case_id": "CASE02",
|
| 37 |
+
"cluster_id": "CAND02",
|
| 38 |
+
"customer_ids": [
|
| 39 |
+
"CUST0009",
|
| 40 |
+
"CUST0010",
|
| 41 |
+
"CUST0011",
|
| 42 |
+
"CUST0012",
|
| 43 |
+
"CUST0013"
|
| 44 |
+
],
|
| 45 |
+
"risk_probability": 0.9968053865328341,
|
| 46 |
+
"policy_decision": "escalate",
|
| 47 |
+
"llm_narrative": "The five customers (CUST0009βCUST0013) form a strongβanchored cluster with ten strong links and no weak links. The group shows a return rate of 47% and a chargeback rate of 18%, with total transaction volume of $59,830. The risk model assigns a probability of 99.7%, resulting in an escalation decision.",
|
| 48 |
+
"llm_confidence_statement": "We are highly confident in this assessment given the very high risk probability and supporting metrics.",
|
| 49 |
+
"action_taken": {
|
| 50 |
+
"tool": "razorpay.Client.order.create + order.edit + order.fetch",
|
| 51 |
+
"order_id": "order_TSeieevTUEtDNP",
|
| 52 |
+
"razorpay_status": "created",
|
| 53 |
+
"notes_written": {
|
| 54 |
+
"case_id": "CASE02",
|
| 55 |
+
"cluster_id": "CAND02",
|
| 56 |
+
"ringguard_status": "escalate_flagged",
|
| 57 |
+
"action_label": "FRAUD_RING_ESCALATE",
|
| 58 |
+
"risk_score": "0.9968",
|
| 59 |
+
"action_by": "RingGuard_v3",
|
| 60 |
+
"action_timestamp": "2026-08-22T02:47:11.088678+00:00"
|
| 61 |
+
},
|
| 62 |
+
"notes_verified": true,
|
| 63 |
+
"timestamp": "2026-08-22T02:47:11.992374+00:00",
|
| 64 |
+
"test_mode": true,
|
| 65 |
+
"error": null
|
| 66 |
+
},
|
| 67 |
+
"timestamp": "2026-08-22T02:42:06.481196+00:00"
|
| 68 |
+
},
|
| 69 |
+
{
|
| 70 |
+
"case_id": "CASE03",
|
| 71 |
+
"cluster_id": "CAND03",
|
| 72 |
+
"customer_ids": [
|
| 73 |
+
"CUST0001",
|
| 74 |
+
"CUST0002",
|
| 75 |
+
"CUST0003"
|
| 76 |
+
],
|
| 77 |
+
"risk_probability": 0.9950028638127228,
|
| 78 |
+
"policy_decision": "escalate",
|
| 79 |
+
"llm_narrative": "The three customers (CUST0001, CUST0002, CUST0003) are connected by three strong links, forming a strongβanchored cluster. This cluster accounts for a total transaction amount of 32,897, includes one shared coupon, and exhibits a 25% return rate and a 12.5% chargeback rate, resulting in a risk probability of 99.5%.",
|
| 80 |
+
"llm_confidence_statement": "The modelβs confidence in this risk assessment is extremely high.",
|
| 81 |
+
"action_taken": {
|
| 82 |
+
"tool": "razorpay.Client.order.create + order.edit + order.fetch",
|
| 83 |
+
"order_id": "order_TSeifof2nHqiyN",
|
| 84 |
+
"razorpay_status": "created",
|
| 85 |
+
"notes_written": {
|
| 86 |
+
"case_id": "CASE03",
|
| 87 |
+
"cluster_id": "CAND03",
|
| 88 |
+
"ringguard_status": "escalate_flagged",
|
| 89 |
+
"action_label": "FRAUD_RING_ESCALATE",
|
| 90 |
+
"risk_score": "0.995",
|
| 91 |
+
"action_by": "RingGuard_v3",
|
| 92 |
+
"action_timestamp": "2026-08-22T02:47:12.186378+00:00"
|
| 93 |
+
},
|
| 94 |
+
"notes_verified": true,
|
| 95 |
+
"timestamp": "2026-08-22T02:47:13.232792+00:00",
|
| 96 |
+
"test_mode": true,
|
| 97 |
+
"error": null
|
| 98 |
+
},
|
| 99 |
+
"timestamp": "2026-08-22T02:42:10.844934+00:00"
|
| 100 |
+
},
|
| 101 |
+
{
|
| 102 |
+
"case_id": "CASE04",
|
| 103 |
+
"cluster_id": "CAND04",
|
| 104 |
+
"customer_ids": [
|
| 105 |
+
"CUST0014",
|
| 106 |
+
"CUST0015",
|
| 107 |
+
"CUST0016",
|
| 108 |
+
"CUST0017",
|
| 109 |
+
"CUST0018"
|
| 110 |
+
],
|
| 111 |
+
"risk_probability": 0.9955003588432927,
|
| 112 |
+
"policy_decision": "escalate",
|
| 113 |
+
"llm_narrative": "The five customers (CUST0014βCUST0018) form a strongβanchored cluster with ten strong links and no weak links, collectively spending $62,087. The group exhibits a 50% return rate, a 12.5% chargeback rate, and shares a single coupon, indicating coordinated risky behavior.",
|
| 114 |
+
"llm_confidence_statement": "Given the 0.9955 risk probability, we are highly confident that this cluster represents a highβrisk fraud pattern.",
|
| 115 |
+
"action_taken": {
|
| 116 |
+
"tool": "razorpay.Client.order.create + order.edit + order.fetch",
|
| 117 |
+
"order_id": "order_TSeihAqIgYfEsF",
|
| 118 |
+
"razorpay_status": "created",
|
| 119 |
+
"notes_written": {
|
| 120 |
+
"case_id": "CASE04",
|
| 121 |
+
"cluster_id": "CAND04",
|
| 122 |
+
"ringguard_status": "escalate_flagged",
|
| 123 |
+
"action_label": "FRAUD_RING_ESCALATE",
|
| 124 |
+
"risk_score": "0.9955",
|
| 125 |
+
"action_by": "RingGuard_v3",
|
| 126 |
+
"action_timestamp": "2026-08-22T02:47:13.364816+00:00"
|
| 127 |
+
},
|
| 128 |
+
"notes_verified": true,
|
| 129 |
+
"timestamp": "2026-08-22T02:47:14.280655+00:00",
|
| 130 |
+
"test_mode": true,
|
| 131 |
+
"error": null
|
| 132 |
+
},
|
| 133 |
+
"timestamp": "2026-08-22T02:42:15.156355+00:00"
|
| 134 |
+
},
|
| 135 |
+
{
|
| 136 |
+
"case_id": "CASE05",
|
| 137 |
+
"cluster_id": "CAND05",
|
| 138 |
+
"customer_ids": [
|
| 139 |
+
"CUST0033",
|
| 140 |
+
"CUST0034",
|
| 141 |
+
"CUST0035"
|
| 142 |
+
],
|
| 143 |
+
"risk_probability": 0.9969893801631614,
|
| 144 |
+
"policy_decision": "escalate",
|
| 145 |
+
"llm_narrative": "The three customers (CUST0033, CUST0034, CUST0035) are connected by three strong links, forming a strongβanchored cluster with a shared coupon and a combined transaction volume of $50,134. The cluster exhibits a return rate of 18.2% and a chargeback rate of 9.1%, and its calculated risk probability is 99.7%.",
|
| 146 |
+
"llm_confidence_statement": "We are highly confident in the fraud assessment given the strong linkage, high risk probability, and notable financial metrics.",
|
| 147 |
+
"action_taken": {
|
| 148 |
+
"tool": "razorpay.Client.order.create + order.edit + order.fetch",
|
| 149 |
+
"order_id": "order_TSeiiK16ZPVegj",
|
| 150 |
+
"razorpay_status": "created",
|
| 151 |
+
"notes_written": {
|
| 152 |
+
"case_id": "CASE05",
|
| 153 |
+
"cluster_id": "CAND05",
|
| 154 |
+
"ringguard_status": "escalate_flagged",
|
| 155 |
+
"action_label": "FRAUD_RING_ESCALATE",
|
| 156 |
+
"risk_score": "0.997",
|
| 157 |
+
"action_by": "RingGuard_v3",
|
| 158 |
+
"action_timestamp": "2026-08-22T02:47:14.523378+00:00"
|
| 159 |
+
},
|
| 160 |
+
"notes_verified": true,
|
| 161 |
+
"timestamp": "2026-08-22T02:47:15.299833+00:00",
|
| 162 |
+
"test_mode": true,
|
| 163 |
+
"error": null
|
| 164 |
+
},
|
| 165 |
+
"timestamp": "2026-08-22T02:42:19.568153+00:00"
|
| 166 |
+
},
|
| 167 |
+
{
|
| 168 |
+
"case_id": "CASE06",
|
| 169 |
+
"cluster_id": "CAND06",
|
| 170 |
+
"customer_ids": [
|
| 171 |
+
"CUST0036",
|
| 172 |
+
"CUST0037",
|
| 173 |
+
"CUST0038",
|
| 174 |
+
"CUST0039",
|
| 175 |
+
"CUST0040"
|
| 176 |
+
],
|
| 177 |
+
"risk_probability": 0.9969377389203431,
|
| 178 |
+
"policy_decision": "escalate",
|
| 179 |
+
"llm_narrative": "The five customers (CUST0036βCUST0040) form a strongβanchored cluster with ten strong links and no weak links, collectively transacting $62,270. Their return rate of 26.7% and chargeback rate of 20% are elevated, and the absence of shared coupons suggests the links are not promotional. These characteristics indicate coordinated fraudulent behavior.",
|
| 180 |
+
"llm_confidence_statement": "We are highly confident in this assessment, reflected by a risk probability of 0.997.",
|
| 181 |
+
"action_taken": {
|
| 182 |
+
"tool": "razorpay.Client.order.create + order.edit + order.fetch",
|
| 183 |
+
"order_id": "order_TSeijQj96lsR88",
|
| 184 |
+
"razorpay_status": "created",
|
| 185 |
+
"notes_written": {
|
| 186 |
+
"case_id": "CASE06",
|
| 187 |
+
"cluster_id": "CAND06",
|
| 188 |
+
"ringguard_status": "escalate_flagged",
|
| 189 |
+
"action_label": "FRAUD_RING_ESCALATE",
|
| 190 |
+
"risk_score": "0.9969",
|
| 191 |
+
"action_by": "RingGuard_v3",
|
| 192 |
+
"action_timestamp": "2026-08-22T02:47:15.427579+00:00"
|
| 193 |
+
},
|
| 194 |
+
"notes_verified": true,
|
| 195 |
+
"timestamp": "2026-08-22T02:47:16.209387+00:00",
|
| 196 |
+
"test_mode": true,
|
| 197 |
+
"error": null
|
| 198 |
+
},
|
| 199 |
+
"timestamp": "2026-08-22T02:42:23.867363+00:00"
|
| 200 |
+
},
|
| 201 |
+
{
|
| 202 |
+
"case_id": "CASE07",
|
| 203 |
+
"cluster_id": "CAND07",
|
| 204 |
+
"customer_ids": [
|
| 205 |
+
"CUST0019",
|
| 206 |
+
"CUST0020",
|
| 207 |
+
"CUST0021",
|
| 208 |
+
"CUST0022",
|
| 209 |
+
"CUST0023"
|
| 210 |
+
],
|
| 211 |
+
"risk_probability": 0.9940850384979173,
|
| 212 |
+
"policy_decision": "escalate",
|
| 213 |
+
"llm_narrative": "A cluster of five customers (CUST0019βCUST0023) is connected by ten strong links with no weak links, forming a strongβanchored network. The group has generated a total transaction amount of 70,841, a return rate of 33.33% and a chargeback rate of 5.56%, and the model assigns a risk probability of 99.41%.",
|
| 214 |
+
"llm_confidence_statement": "The assessment is made with very high confidence.",
|
| 215 |
+
"action_taken": {
|
| 216 |
+
"tool": "razorpay.Client.order.create + order.edit + order.fetch",
|
| 217 |
+
"order_id": "order_TSeikSedcIcNGX",
|
| 218 |
+
"razorpay_status": "created",
|
| 219 |
+
"notes_written": {
|
| 220 |
+
"case_id": "CASE07",
|
| 221 |
+
"cluster_id": "CAND07",
|
| 222 |
+
"ringguard_status": "escalate_flagged",
|
| 223 |
+
"action_label": "FRAUD_RING_ESCALATE",
|
| 224 |
+
"risk_score": "0.9941",
|
| 225 |
+
"action_by": "RingGuard_v3",
|
| 226 |
+
"action_timestamp": "2026-08-22T02:47:16.396113+00:00"
|
| 227 |
+
},
|
| 228 |
+
"notes_verified": true,
|
| 229 |
+
"timestamp": "2026-08-22T02:47:17.279431+00:00",
|
| 230 |
+
"test_mode": true,
|
| 231 |
+
"error": null
|
| 232 |
+
},
|
| 233 |
+
"timestamp": "2026-08-22T02:42:28.164967+00:00"
|
| 234 |
+
},
|
| 235 |
+
{
|
| 236 |
+
"case_id": "CASE08",
|
| 237 |
+
"cluster_id": "CAND08",
|
| 238 |
+
"customer_ids": [
|
| 239 |
+
"CUST0501",
|
| 240 |
+
"CUST0502",
|
| 241 |
+
"CUST0503"
|
| 242 |
+
],
|
| 243 |
+
"risk_probability": 0.9867466290228035,
|
| 244 |
+
"policy_decision": "auto_hold",
|
| 245 |
+
"llm_narrative": "The three customers (CUST0501, CUST0502, CUST0503) are connected by three strong links, forming a strongβanchored cluster. They share one coupon, together generated $19,800 in transactions, and exhibit a 16.7% return and chargeback rate each.",
|
| 246 |
+
"llm_confidence_statement": "The model assigns a risk probability of 0.99, indicating very high confidence in the highβrisk classification.",
|
| 247 |
+
"action_taken": {
|
| 248 |
+
"tool": "razorpay.Client.order.create + order.edit + order.fetch",
|
| 249 |
+
"order_id": "order_TSeilZzpguMme6",
|
| 250 |
+
"razorpay_status": "created",
|
| 251 |
+
"notes_written": {
|
| 252 |
+
"case_id": "CASE08",
|
| 253 |
+
"cluster_id": "CAND08",
|
| 254 |
+
"ringguard_status": "auto_hold",
|
| 255 |
+
"action_label": "FRAUD_RING_AUTO_HOLD",
|
| 256 |
+
"risk_score": "0.9867",
|
| 257 |
+
"action_by": "RingGuard_v3",
|
| 258 |
+
"action_timestamp": "2026-08-22T02:47:17.462450+00:00"
|
| 259 |
+
},
|
| 260 |
+
"notes_verified": true,
|
| 261 |
+
"timestamp": "2026-08-22T02:47:18.321891+00:00",
|
| 262 |
+
"test_mode": true,
|
| 263 |
+
"error": null
|
| 264 |
+
},
|
| 265 |
+
"timestamp": "2026-08-22T02:42:32.454693+00:00"
|
| 266 |
+
},
|
| 267 |
+
{
|
| 268 |
+
"case_id": "CASE09",
|
| 269 |
+
"cluster_id": "CAND09",
|
| 270 |
+
"customer_ids": [
|
| 271 |
+
"CUST0024",
|
| 272 |
+
"CUST0025",
|
| 273 |
+
"CUST0026",
|
| 274 |
+
"CUST0027",
|
| 275 |
+
"CUST0028",
|
| 276 |
+
"CUST0029"
|
| 277 |
+
],
|
| 278 |
+
"risk_probability": 0.9913203009684713,
|
| 279 |
+
"policy_decision": "escalate",
|
| 280 |
+
"llm_narrative": "The six customers (CUST0024βCUST0029) form a strong_anchored cluster with 15 strong links and no weak links, indicating tightly coordinated activity. Their combined purchase total of 81,019 and a return rate of 55% further highlight abnormal behavior, while a chargeback rate of 5% adds to the risk profile.",
|
| 281 |
+
"llm_confidence_statement": "The evidence yields a very high confidence in the elevated risk assessment.",
|
| 282 |
+
"action_taken": {
|
| 283 |
+
"tool": "razorpay.Client.order.create + order.edit + order.fetch",
|
| 284 |
+
"order_id": "order_TSeimiDR56y6I3",
|
| 285 |
+
"razorpay_status": "created",
|
| 286 |
+
"notes_written": {
|
| 287 |
+
"case_id": "CASE09",
|
| 288 |
+
"cluster_id": "CAND09",
|
| 289 |
+
"ringguard_status": "escalate_flagged",
|
| 290 |
+
"action_label": "FRAUD_RING_ESCALATE",
|
| 291 |
+
"risk_score": "0.9913",
|
| 292 |
+
"action_by": "RingGuard_v3",
|
| 293 |
+
"action_timestamp": "2026-08-22T02:47:18.435548+00:00"
|
| 294 |
+
},
|
| 295 |
+
"notes_verified": true,
|
| 296 |
+
"timestamp": "2026-08-22T02:47:19.433491+00:00",
|
| 297 |
+
"test_mode": true,
|
| 298 |
+
"error": null
|
| 299 |
+
},
|
| 300 |
+
"timestamp": "2026-08-22T02:42:36.567254+00:00"
|
| 301 |
+
},
|
| 302 |
+
{
|
| 303 |
+
"case_id": "CASE10",
|
| 304 |
+
"cluster_id": "CAND10",
|
| 305 |
+
"customer_ids": [
|
| 306 |
+
"CUST0004",
|
| 307 |
+
"CUST0005",
|
| 308 |
+
"CUST0006",
|
| 309 |
+
"CUST0007",
|
| 310 |
+
"CUST0008"
|
| 311 |
+
],
|
| 312 |
+
"risk_probability": 0.9959231873282086,
|
| 313 |
+
"policy_decision": "escalate",
|
| 314 |
+
"llm_narrative": "The five customers (CUST0004βCUST0008) form a strongβanchored cluster with seven strong links and no weak links, collectively transacting $63,837. Their return rate of 37.5% and chargeback rate of 6.25% are elevated, supporting the high risk probability of 99.6%.",
|
| 315 |
+
"llm_confidence_statement": "The evidence yields a very high confidence in the elevated fraud risk assessment.",
|
| 316 |
+
"action_taken": {
|
| 317 |
+
"tool": "razorpay.Client.order.create + order.edit + order.fetch",
|
| 318 |
+
"order_id": "order_TSeinwRO4xKvs9",
|
| 319 |
+
"razorpay_status": "created",
|
| 320 |
+
"notes_written": {
|
| 321 |
+
"case_id": "CASE10",
|
| 322 |
+
"cluster_id": "CAND10",
|
| 323 |
+
"ringguard_status": "escalate_flagged",
|
| 324 |
+
"action_label": "FRAUD_RING_ESCALATE",
|
| 325 |
+
"risk_score": "0.9959",
|
| 326 |
+
"action_by": "RingGuard_v3",
|
| 327 |
+
"action_timestamp": "2026-08-22T02:47:19.567020+00:00"
|
| 328 |
+
},
|
| 329 |
+
"notes_verified": true,
|
| 330 |
+
"timestamp": "2026-08-22T02:47:20.455513+00:00",
|
| 331 |
+
"test_mode": true,
|
| 332 |
+
"error": null
|
| 333 |
+
},
|
| 334 |
+
"timestamp": "2026-08-22T02:42:40.796349+00:00"
|
| 335 |
+
},
|
| 336 |
+
{
|
| 337 |
+
"case_id": "CASE11",
|
| 338 |
+
"cluster_id": "CAND11",
|
| 339 |
+
"customer_ids": [
|
| 340 |
+
"CUST0030",
|
| 341 |
+
"CUST0031",
|
| 342 |
+
"CUST0032"
|
| 343 |
+
],
|
| 344 |
+
"risk_probability": 0.9927212653417073,
|
| 345 |
+
"policy_decision": "escalate",
|
| 346 |
+
"llm_narrative": "The three customers (CUST0030, CUST0031, CUST0032) form a strongβanchored cluster with two strong links and no weak links, together generating $26,235 in transactions. Their return and chargeback rates are each 28.6%, and the model assigns a risk probability of 99.3%.",
|
| 347 |
+
"llm_confidence_statement": "Confidence in this assessment is high given the strong links, elevated return/chargeback rates, and nearβcertain risk probability.",
|
| 348 |
+
"action_taken": {
|
| 349 |
+
"tool": "razorpay.Client.order.create + order.edit + order.fetch",
|
| 350 |
+
"order_id": "order_TSeip2lX554G6F",
|
| 351 |
+
"razorpay_status": "created",
|
| 352 |
+
"notes_written": {
|
| 353 |
+
"case_id": "CASE11",
|
| 354 |
+
"cluster_id": "CAND11",
|
| 355 |
+
"ringguard_status": "escalate_flagged",
|
| 356 |
+
"action_label": "FRAUD_RING_ESCALATE",
|
| 357 |
+
"risk_score": "0.9927",
|
| 358 |
+
"action_by": "RingGuard_v3",
|
| 359 |
+
"action_timestamp": "2026-08-22T02:47:20.576284+00:00"
|
| 360 |
+
},
|
| 361 |
+
"notes_verified": true,
|
| 362 |
+
"timestamp": "2026-08-22T02:47:21.336242+00:00",
|
| 363 |
+
"test_mode": true,
|
| 364 |
+
"error": null
|
| 365 |
+
},
|
| 366 |
+
"timestamp": "2026-08-22T02:42:46.478223+00:00"
|
| 367 |
+
},
|
| 368 |
+
{
|
| 369 |
+
"case_id": "CASE12",
|
| 370 |
+
"cluster_id": "CAND12",
|
| 371 |
+
"customer_ids": [
|
| 372 |
+
"CUST0001",
|
| 373 |
+
"CUST0019",
|
| 374 |
+
"CUST0040",
|
| 375 |
+
"CUST0126",
|
| 376 |
+
"CUST0138",
|
| 377 |
+
"CUST0168",
|
| 378 |
+
"CUST0211",
|
| 379 |
+
"CUST0219",
|
| 380 |
+
"CUST0258",
|
| 381 |
+
"CUST0281",
|
| 382 |
+
"CUST0292",
|
| 383 |
+
"CUST0322",
|
| 384 |
+
"CUST0325",
|
| 385 |
+
"CUST0371",
|
| 386 |
+
"CUST0373",
|
| 387 |
+
"CUST0400",
|
| 388 |
+
"CUST0419",
|
| 389 |
+
"CUST0465"
|
| 390 |
+
],
|
| 391 |
+
"risk_probability": 0.00720344453548541,
|
| 392 |
+
"policy_decision": "log_only",
|
| 393 |
+
"llm_narrative": null,
|
| 394 |
+
"llm_confidence_statement": null,
|
| 395 |
+
"action_taken": null,
|
| 396 |
+
"timestamp": "2026-08-22T02:42:46.483242+00:00"
|
| 397 |
+
},
|
| 398 |
+
{
|
| 399 |
+
"case_id": "CASE13",
|
| 400 |
+
"cluster_id": "CAND13",
|
| 401 |
+
"customer_ids": [
|
| 402 |
+
"CUST0002",
|
| 403 |
+
"CUST0009",
|
| 404 |
+
"CUST0020",
|
| 405 |
+
"CUST0041",
|
| 406 |
+
"CUST0064",
|
| 407 |
+
"CUST0073",
|
| 408 |
+
"CUST0074",
|
| 409 |
+
"CUST0080",
|
| 410 |
+
"CUST0081",
|
| 411 |
+
"CUST0086",
|
| 412 |
+
"CUST0089",
|
| 413 |
+
"CUST0103",
|
| 414 |
+
"CUST0162",
|
| 415 |
+
"CUST0167",
|
| 416 |
+
"CUST0173",
|
| 417 |
+
"CUST0181",
|
| 418 |
+
"CUST0226",
|
| 419 |
+
"CUST0240",
|
| 420 |
+
"CUST0253",
|
| 421 |
+
"CUST0262",
|
| 422 |
+
"CUST0272",
|
| 423 |
+
"CUST0286",
|
| 424 |
+
"CUST0287",
|
| 425 |
+
"CUST0324",
|
| 426 |
+
"CUST0331",
|
| 427 |
+
"CUST0333",
|
| 428 |
+
"CUST0369",
|
| 429 |
+
"CUST0392",
|
| 430 |
+
"CUST0393",
|
| 431 |
+
"CUST0398",
|
| 432 |
+
"CUST0406",
|
| 433 |
+
"CUST0410",
|
| 434 |
+
"CUST0411",
|
| 435 |
+
"CUST0413",
|
| 436 |
+
"CUST0415",
|
| 437 |
+
"CUST0423",
|
| 438 |
+
"CUST0446",
|
| 439 |
+
"CUST0468",
|
| 440 |
+
"CUST0476",
|
| 441 |
+
"CUST0478",
|
| 442 |
+
"CUST0485"
|
| 443 |
+
],
|
| 444 |
+
"risk_probability": 0.007559966037372132,
|
| 445 |
+
"policy_decision": "log_only",
|
| 446 |
+
"llm_narrative": null,
|
| 447 |
+
"llm_confidence_statement": null,
|
| 448 |
+
"action_taken": null,
|
| 449 |
+
"timestamp": "2026-08-22T02:42:46.486423+00:00"
|
| 450 |
+
},
|
| 451 |
+
{
|
| 452 |
+
"case_id": "CASE14",
|
| 453 |
+
"cluster_id": "CAND14",
|
| 454 |
+
"customer_ids": [
|
| 455 |
+
"CUST0003",
|
| 456 |
+
"CUST0012",
|
| 457 |
+
"CUST0043",
|
| 458 |
+
"CUST0077",
|
| 459 |
+
"CUST0088",
|
| 460 |
+
"CUST0098",
|
| 461 |
+
"CUST0109",
|
| 462 |
+
"CUST0125",
|
| 463 |
+
"CUST0139",
|
| 464 |
+
"CUST0153",
|
| 465 |
+
"CUST0159",
|
| 466 |
+
"CUST0166",
|
| 467 |
+
"CUST0180",
|
| 468 |
+
"CUST0201",
|
| 469 |
+
"CUST0209",
|
| 470 |
+
"CUST0245",
|
| 471 |
+
"CUST0261",
|
| 472 |
+
"CUST0265",
|
| 473 |
+
"CUST0273",
|
| 474 |
+
"CUST0277",
|
| 475 |
+
"CUST0297",
|
| 476 |
+
"CUST0315",
|
| 477 |
+
"CUST0334",
|
| 478 |
+
"CUST0347",
|
| 479 |
+
"CUST0381",
|
| 480 |
+
"CUST0405",
|
| 481 |
+
"CUST0412",
|
| 482 |
+
"CUST0428",
|
| 483 |
+
"CUST0429",
|
| 484 |
+
"CUST0462",
|
| 485 |
+
"CUST0471"
|
| 486 |
+
],
|
| 487 |
+
"risk_probability": 0.0033586500336385537,
|
| 488 |
+
"policy_decision": "log_only",
|
| 489 |
+
"llm_narrative": null,
|
| 490 |
+
"llm_confidence_statement": null,
|
| 491 |
+
"action_taken": null,
|
| 492 |
+
"timestamp": "2026-08-22T02:42:46.490015+00:00"
|
| 493 |
+
},
|
| 494 |
+
{
|
| 495 |
+
"case_id": "CASE15",
|
| 496 |
+
"cluster_id": "CAND15",
|
| 497 |
+
"customer_ids": [
|
| 498 |
+
"CUST0004",
|
| 499 |
+
"CUST0008",
|
| 500 |
+
"CUST0027",
|
| 501 |
+
"CUST0030",
|
| 502 |
+
"CUST0042",
|
| 503 |
+
"CUST0063",
|
| 504 |
+
"CUST0075",
|
| 505 |
+
"CUST0087",
|
| 506 |
+
"CUST0110",
|
| 507 |
+
"CUST0117",
|
| 508 |
+
"CUST0120",
|
| 509 |
+
"CUST0133",
|
| 510 |
+
"CUST0135",
|
| 511 |
+
"CUST0137",
|
| 512 |
+
"CUST0144",
|
| 513 |
+
"CUST0152",
|
| 514 |
+
"CUST0154",
|
| 515 |
+
"CUST0163",
|
| 516 |
+
"CUST0170",
|
| 517 |
+
"CUST0178",
|
| 518 |
+
"CUST0179",
|
| 519 |
+
"CUST0195",
|
| 520 |
+
"CUST0198",
|
| 521 |
+
"CUST0208",
|
| 522 |
+
"CUST0210",
|
| 523 |
+
"CUST0221",
|
| 524 |
+
"CUST0228",
|
| 525 |
+
"CUST0231",
|
| 526 |
+
"CUST0237",
|
| 527 |
+
"CUST0246",
|
| 528 |
+
"CUST0251",
|
| 529 |
+
"CUST0254",
|
| 530 |
+
"CUST0266",
|
| 531 |
+
"CUST0282",
|
| 532 |
+
"CUST0295",
|
| 533 |
+
"CUST0300",
|
| 534 |
+
"CUST0303",
|
| 535 |
+
"CUST0304",
|
| 536 |
+
"CUST0335",
|
| 537 |
+
"CUST0355",
|
| 538 |
+
"CUST0365",
|
| 539 |
+
"CUST0399",
|
| 540 |
+
"CUST0420",
|
| 541 |
+
"CUST0425",
|
| 542 |
+
"CUST0470",
|
| 543 |
+
"CUST0483",
|
| 544 |
+
"CUST0486",
|
| 545 |
+
"CUST0487",
|
| 546 |
+
"CUST0491",
|
| 547 |
+
"CUST0492",
|
| 548 |
+
"CUST0498"
|
| 549 |
+
],
|
| 550 |
+
"risk_probability": 0.007646314104742993,
|
| 551 |
+
"policy_decision": "log_only",
|
| 552 |
+
"llm_narrative": null,
|
| 553 |
+
"llm_confidence_statement": null,
|
| 554 |
+
"action_taken": null,
|
| 555 |
+
"timestamp": "2026-08-22T02:42:46.491127+00:00"
|
| 556 |
+
},
|
| 557 |
+
{
|
| 558 |
+
"case_id": "CASE16",
|
| 559 |
+
"cluster_id": "CAND16",
|
| 560 |
+
"customer_ids": [
|
| 561 |
+
"CUST0005",
|
| 562 |
+
"CUST0022",
|
| 563 |
+
"CUST0028",
|
| 564 |
+
"CUST0038",
|
| 565 |
+
"CUST0102",
|
| 566 |
+
"CUST0111",
|
| 567 |
+
"CUST0113",
|
| 568 |
+
"CUST0140",
|
| 569 |
+
"CUST0161",
|
| 570 |
+
"CUST0171",
|
| 571 |
+
"CUST0177",
|
| 572 |
+
"CUST0202",
|
| 573 |
+
"CUST0222",
|
| 574 |
+
"CUST0235",
|
| 575 |
+
"CUST0252",
|
| 576 |
+
"CUST0257",
|
| 577 |
+
"CUST0263",
|
| 578 |
+
"CUST0288",
|
| 579 |
+
"CUST0293",
|
| 580 |
+
"CUST0299",
|
| 581 |
+
"CUST0308",
|
| 582 |
+
"CUST0311",
|
| 583 |
+
"CUST0353",
|
| 584 |
+
"CUST0357",
|
| 585 |
+
"CUST0364",
|
| 586 |
+
"CUST0370",
|
| 587 |
+
"CUST0383",
|
| 588 |
+
"CUST0386",
|
| 589 |
+
"CUST0387",
|
| 590 |
+
"CUST0391",
|
| 591 |
+
"CUST0396",
|
| 592 |
+
"CUST0438",
|
| 593 |
+
"CUST0442",
|
| 594 |
+
"CUST0456",
|
| 595 |
+
"CUST0460",
|
| 596 |
+
"CUST0488",
|
| 597 |
+
"CUST0490",
|
| 598 |
+
"CUST0495",
|
| 599 |
+
"CUST0496",
|
| 600 |
+
"CUST0500"
|
| 601 |
+
],
|
| 602 |
+
"risk_probability": 0.0035456513474297945,
|
| 603 |
+
"policy_decision": "log_only",
|
| 604 |
+
"llm_narrative": null,
|
| 605 |
+
"llm_confidence_statement": null,
|
| 606 |
+
"action_taken": null,
|
| 607 |
+
"timestamp": "2026-08-22T02:42:46.495874+00:00"
|
| 608 |
+
},
|
| 609 |
+
{
|
| 610 |
+
"case_id": "CASE17",
|
| 611 |
+
"cluster_id": "CAND17",
|
| 612 |
+
"customer_ids": [
|
| 613 |
+
"CUST0006",
|
| 614 |
+
"CUST0011",
|
| 615 |
+
"CUST0024",
|
| 616 |
+
"CUST0025",
|
| 617 |
+
"CUST0033",
|
| 618 |
+
"CUST0044",
|
| 619 |
+
"CUST0079",
|
| 620 |
+
"CUST0084",
|
| 621 |
+
"CUST0101",
|
| 622 |
+
"CUST0107",
|
| 623 |
+
"CUST0108",
|
| 624 |
+
"CUST0114",
|
| 625 |
+
"CUST0132",
|
| 626 |
+
"CUST0145",
|
| 627 |
+
"CUST0157",
|
| 628 |
+
"CUST0172",
|
| 629 |
+
"CUST0227",
|
| 630 |
+
"CUST0244",
|
| 631 |
+
"CUST0255",
|
| 632 |
+
"CUST0256",
|
| 633 |
+
"CUST0267",
|
| 634 |
+
"CUST0271",
|
| 635 |
+
"CUST0284",
|
| 636 |
+
"CUST0291",
|
| 637 |
+
"CUST0296",
|
| 638 |
+
"CUST0316",
|
| 639 |
+
"CUST0319",
|
| 640 |
+
"CUST0329",
|
| 641 |
+
"CUST0336",
|
| 642 |
+
"CUST0342",
|
| 643 |
+
"CUST0348",
|
| 644 |
+
"CUST0349",
|
| 645 |
+
"CUST0367",
|
| 646 |
+
"CUST0375",
|
| 647 |
+
"CUST0389",
|
| 648 |
+
"CUST0407",
|
| 649 |
+
"CUST0455",
|
| 650 |
+
"CUST0489",
|
| 651 |
+
"CUST0499"
|
| 652 |
+
],
|
| 653 |
+
"risk_probability": 0.006896318028648148,
|
| 654 |
+
"policy_decision": "log_only",
|
| 655 |
+
"llm_narrative": null,
|
| 656 |
+
"llm_confidence_statement": null,
|
| 657 |
+
"action_taken": null,
|
| 658 |
+
"timestamp": "2026-08-22T02:42:46.500167+00:00"
|
| 659 |
+
},
|
| 660 |
+
{
|
| 661 |
+
"case_id": "CASE18",
|
| 662 |
+
"cluster_id": "CAND18",
|
| 663 |
+
"customer_ids": [
|
| 664 |
+
"CUST0007",
|
| 665 |
+
"CUST0014",
|
| 666 |
+
"CUST0015",
|
| 667 |
+
"CUST0016",
|
| 668 |
+
"CUST0032",
|
| 669 |
+
"CUST0037",
|
| 670 |
+
"CUST0065",
|
| 671 |
+
"CUST0069",
|
| 672 |
+
"CUST0070",
|
| 673 |
+
"CUST0095",
|
| 674 |
+
"CUST0106",
|
| 675 |
+
"CUST0115",
|
| 676 |
+
"CUST0124",
|
| 677 |
+
"CUST0131",
|
| 678 |
+
"CUST0149",
|
| 679 |
+
"CUST0191",
|
| 680 |
+
"CUST0200",
|
| 681 |
+
"CUST0204",
|
| 682 |
+
"CUST0215",
|
| 683 |
+
"CUST0218",
|
| 684 |
+
"CUST0223",
|
| 685 |
+
"CUST0238",
|
| 686 |
+
"CUST0239",
|
| 687 |
+
"CUST0241",
|
| 688 |
+
"CUST0242",
|
| 689 |
+
"CUST0264",
|
| 690 |
+
"CUST0276",
|
| 691 |
+
"CUST0280",
|
| 692 |
+
"CUST0305",
|
| 693 |
+
"CUST0314",
|
| 694 |
+
"CUST0323",
|
| 695 |
+
"CUST0327",
|
| 696 |
+
"CUST0339",
|
| 697 |
+
"CUST0350",
|
| 698 |
+
"CUST0352",
|
| 699 |
+
"CUST0356",
|
| 700 |
+
"CUST0358",
|
| 701 |
+
"CUST0362",
|
| 702 |
+
"CUST0379",
|
| 703 |
+
"CUST0401",
|
| 704 |
+
"CUST0418",
|
| 705 |
+
"CUST0440",
|
| 706 |
+
"CUST0443",
|
| 707 |
+
"CUST0449",
|
| 708 |
+
"CUST0479"
|
| 709 |
+
],
|
| 710 |
+
"risk_probability": 0.0034784417949967547,
|
| 711 |
+
"policy_decision": "log_only",
|
| 712 |
+
"llm_narrative": null,
|
| 713 |
+
"llm_confidence_statement": null,
|
| 714 |
+
"action_taken": null,
|
| 715 |
+
"timestamp": "2026-08-22T02:42:46.502500+00:00"
|
| 716 |
+
},
|
| 717 |
+
{
|
| 718 |
+
"case_id": "CASE19",
|
| 719 |
+
"cluster_id": "CAND19",
|
| 720 |
+
"customer_ids": [
|
| 721 |
+
"CUST0010",
|
| 722 |
+
"CUST0023",
|
| 723 |
+
"CUST0029",
|
| 724 |
+
"CUST0090",
|
| 725 |
+
"CUST0119",
|
| 726 |
+
"CUST0121",
|
| 727 |
+
"CUST0129",
|
| 728 |
+
"CUST0141",
|
| 729 |
+
"CUST0143",
|
| 730 |
+
"CUST0155",
|
| 731 |
+
"CUST0196",
|
| 732 |
+
"CUST0207",
|
| 733 |
+
"CUST0230",
|
| 734 |
+
"CUST0233",
|
| 735 |
+
"CUST0247",
|
| 736 |
+
"CUST0330",
|
| 737 |
+
"CUST0338",
|
| 738 |
+
"CUST0372",
|
| 739 |
+
"CUST0374",
|
| 740 |
+
"CUST0380",
|
| 741 |
+
"CUST0461",
|
| 742 |
+
"CUST0467",
|
| 743 |
+
"CUST0480",
|
| 744 |
+
"CUST0493"
|
| 745 |
+
],
|
| 746 |
+
"risk_probability": 0.007559966037372132,
|
| 747 |
+
"policy_decision": "log_only",
|
| 748 |
+
"llm_narrative": null,
|
| 749 |
+
"llm_confidence_statement": null,
|
| 750 |
+
"action_taken": null,
|
| 751 |
+
"timestamp": "2026-08-22T02:42:46.505560+00:00"
|
| 752 |
+
},
|
| 753 |
+
{
|
| 754 |
+
"case_id": "CASE20",
|
| 755 |
+
"cluster_id": "CAND20",
|
| 756 |
+
"customer_ids": [
|
| 757 |
+
"CUST0013",
|
| 758 |
+
"CUST0026",
|
| 759 |
+
"CUST0031",
|
| 760 |
+
"CUST0035",
|
| 761 |
+
"CUST0039",
|
| 762 |
+
"CUST0067",
|
| 763 |
+
"CUST0068",
|
| 764 |
+
"CUST0094",
|
| 765 |
+
"CUST0116",
|
| 766 |
+
"CUST0122",
|
| 767 |
+
"CUST0128",
|
| 768 |
+
"CUST0184",
|
| 769 |
+
"CUST0193",
|
| 770 |
+
"CUST0203",
|
| 771 |
+
"CUST0212",
|
| 772 |
+
"CUST0217",
|
| 773 |
+
"CUST0248",
|
| 774 |
+
"CUST0268",
|
| 775 |
+
"CUST0283",
|
| 776 |
+
"CUST0312",
|
| 777 |
+
"CUST0340",
|
| 778 |
+
"CUST0351",
|
| 779 |
+
"CUST0384",
|
| 780 |
+
"CUST0402",
|
| 781 |
+
"CUST0417",
|
| 782 |
+
"CUST0427",
|
| 783 |
+
"CUST0430",
|
| 784 |
+
"CUST0434",
|
| 785 |
+
"CUST0451",
|
| 786 |
+
"CUST0463",
|
| 787 |
+
"CUST0466",
|
| 788 |
+
"CUST0469",
|
| 789 |
+
"CUST0473",
|
| 790 |
+
"CUST0482",
|
| 791 |
+
"CUST0497"
|
| 792 |
+
],
|
| 793 |
+
"risk_probability": 0.007561351403107364,
|
| 794 |
+
"policy_decision": "log_only",
|
| 795 |
+
"llm_narrative": null,
|
| 796 |
+
"llm_confidence_statement": null,
|
| 797 |
+
"action_taken": null,
|
| 798 |
+
"timestamp": "2026-08-22T02:42:46.508965+00:00"
|
| 799 |
+
},
|
| 800 |
+
{
|
| 801 |
+
"case_id": "CASE21",
|
| 802 |
+
"cluster_id": "CAND21",
|
| 803 |
+
"customer_ids": [
|
| 804 |
+
"CUST0017",
|
| 805 |
+
"CUST0036",
|
| 806 |
+
"CUST0062",
|
| 807 |
+
"CUST0071",
|
| 808 |
+
"CUST0082",
|
| 809 |
+
"CUST0083",
|
| 810 |
+
"CUST0085",
|
| 811 |
+
"CUST0096",
|
| 812 |
+
"CUST0123",
|
| 813 |
+
"CUST0142",
|
| 814 |
+
"CUST0147",
|
| 815 |
+
"CUST0175",
|
| 816 |
+
"CUST0189",
|
| 817 |
+
"CUST0216",
|
| 818 |
+
"CUST0220",
|
| 819 |
+
"CUST0224",
|
| 820 |
+
"CUST0232",
|
| 821 |
+
"CUST0234",
|
| 822 |
+
"CUST0306",
|
| 823 |
+
"CUST0328",
|
| 824 |
+
"CUST0337",
|
| 825 |
+
"CUST0341",
|
| 826 |
+
"CUST0345",
|
| 827 |
+
"CUST0346",
|
| 828 |
+
"CUST0361",
|
| 829 |
+
"CUST0388",
|
| 830 |
+
"CUST0421",
|
| 831 |
+
"CUST0426",
|
| 832 |
+
"CUST0433",
|
| 833 |
+
"CUST0435",
|
| 834 |
+
"CUST0444",
|
| 835 |
+
"CUST0450",
|
| 836 |
+
"CUST0454",
|
| 837 |
+
"CUST0477"
|
| 838 |
+
],
|
| 839 |
+
"risk_probability": 0.0035456513474297945,
|
| 840 |
+
"policy_decision": "log_only",
|
| 841 |
+
"llm_narrative": null,
|
| 842 |
+
"llm_confidence_statement": null,
|
| 843 |
+
"action_taken": null,
|
| 844 |
+
"timestamp": "2026-08-22T02:42:46.514247+00:00"
|
| 845 |
+
},
|
| 846 |
+
{
|
| 847 |
+
"case_id": "CASE22",
|
| 848 |
+
"cluster_id": "CAND22",
|
| 849 |
+
"customer_ids": [
|
| 850 |
+
"CUST0018",
|
| 851 |
+
"CUST0021",
|
| 852 |
+
"CUST0091",
|
| 853 |
+
"CUST0092",
|
| 854 |
+
"CUST0112",
|
| 855 |
+
"CUST0160",
|
| 856 |
+
"CUST0174",
|
| 857 |
+
"CUST0187",
|
| 858 |
+
"CUST0270",
|
| 859 |
+
"CUST0298",
|
| 860 |
+
"CUST0307",
|
| 861 |
+
"CUST0310",
|
| 862 |
+
"CUST0332",
|
| 863 |
+
"CUST0343",
|
| 864 |
+
"CUST0431",
|
| 865 |
+
"CUST0474",
|
| 866 |
+
"CUST0475",
|
| 867 |
+
"CUST0494"
|
| 868 |
+
],
|
| 869 |
+
"risk_probability": 0.03305941612108949,
|
| 870 |
+
"policy_decision": "log_only",
|
| 871 |
+
"llm_narrative": null,
|
| 872 |
+
"llm_confidence_statement": null,
|
| 873 |
+
"action_taken": null,
|
| 874 |
+
"timestamp": "2026-08-22T02:42:46.516340+00:00"
|
| 875 |
+
},
|
| 876 |
+
{
|
| 877 |
+
"case_id": "CASE23",
|
| 878 |
+
"cluster_id": "CAND23",
|
| 879 |
+
"customer_ids": [
|
| 880 |
+
"CUST0034",
|
| 881 |
+
"CUST0066",
|
| 882 |
+
"CUST0078",
|
| 883 |
+
"CUST0100",
|
| 884 |
+
"CUST0104",
|
| 885 |
+
"CUST0134",
|
| 886 |
+
"CUST0146",
|
| 887 |
+
"CUST0150",
|
| 888 |
+
"CUST0151",
|
| 889 |
+
"CUST0158",
|
| 890 |
+
"CUST0182",
|
| 891 |
+
"CUST0183",
|
| 892 |
+
"CUST0185",
|
| 893 |
+
"CUST0188",
|
| 894 |
+
"CUST0190",
|
| 895 |
+
"CUST0259",
|
| 896 |
+
"CUST0269",
|
| 897 |
+
"CUST0279",
|
| 898 |
+
"CUST0285",
|
| 899 |
+
"CUST0289",
|
| 900 |
+
"CUST0301",
|
| 901 |
+
"CUST0302",
|
| 902 |
+
"CUST0344",
|
| 903 |
+
"CUST0354",
|
| 904 |
+
"CUST0366",
|
| 905 |
+
"CUST0368",
|
| 906 |
+
"CUST0378",
|
| 907 |
+
"CUST0404",
|
| 908 |
+
"CUST0408",
|
| 909 |
+
"CUST0432",
|
| 910 |
+
"CUST0436",
|
| 911 |
+
"CUST0437",
|
| 912 |
+
"CUST0439",
|
| 913 |
+
"CUST0441",
|
| 914 |
+
"CUST0447",
|
| 915 |
+
"CUST0448",
|
| 916 |
+
"CUST0457",
|
| 917 |
+
"CUST0481"
|
| 918 |
+
],
|
| 919 |
+
"risk_probability": 0.0035456513474297945,
|
| 920 |
+
"policy_decision": "log_only",
|
| 921 |
+
"llm_narrative": null,
|
| 922 |
+
"llm_confidence_statement": null,
|
| 923 |
+
"action_taken": null,
|
| 924 |
+
"timestamp": "2026-08-22T02:42:46.520858+00:00"
|
| 925 |
+
},
|
| 926 |
+
{
|
| 927 |
+
"case_id": "CASE24",
|
| 928 |
+
"cluster_id": "CAND24",
|
| 929 |
+
"customer_ids": [
|
| 930 |
+
"CUST0061",
|
| 931 |
+
"CUST0093",
|
| 932 |
+
"CUST0105",
|
| 933 |
+
"CUST0130",
|
| 934 |
+
"CUST0136",
|
| 935 |
+
"CUST0148",
|
| 936 |
+
"CUST0164",
|
| 937 |
+
"CUST0186",
|
| 938 |
+
"CUST0197",
|
| 939 |
+
"CUST0205",
|
| 940 |
+
"CUST0206",
|
| 941 |
+
"CUST0214",
|
| 942 |
+
"CUST0260",
|
| 943 |
+
"CUST0309",
|
| 944 |
+
"CUST0320",
|
| 945 |
+
"CUST0321",
|
| 946 |
+
"CUST0359",
|
| 947 |
+
"CUST0363",
|
| 948 |
+
"CUST0376",
|
| 949 |
+
"CUST0377",
|
| 950 |
+
"CUST0385",
|
| 951 |
+
"CUST0394",
|
| 952 |
+
"CUST0403",
|
| 953 |
+
"CUST0416",
|
| 954 |
+
"CUST0424",
|
| 955 |
+
"CUST0453"
|
| 956 |
+
],
|
| 957 |
+
"risk_probability": 0.0035456513474297945,
|
| 958 |
+
"policy_decision": "log_only",
|
| 959 |
+
"llm_narrative": null,
|
| 960 |
+
"llm_confidence_statement": null,
|
| 961 |
+
"action_taken": null,
|
| 962 |
+
"timestamp": "2026-08-22T02:42:46.523858+00:00"
|
| 963 |
+
},
|
| 964 |
+
{
|
| 965 |
+
"case_id": "CASE25",
|
| 966 |
+
"cluster_id": "CAND25",
|
| 967 |
+
"customer_ids": [
|
| 968 |
+
"CUST0045",
|
| 969 |
+
"CUST0046",
|
| 970 |
+
"CUST0047",
|
| 971 |
+
"CUST0048"
|
| 972 |
+
],
|
| 973 |
+
"risk_probability": 0.0035484719416527992,
|
| 974 |
+
"policy_decision": "log_only",
|
| 975 |
+
"llm_narrative": null,
|
| 976 |
+
"llm_confidence_statement": null,
|
| 977 |
+
"action_taken": null,
|
| 978 |
+
"timestamp": "2026-08-22T02:42:46.526962+00:00"
|
| 979 |
+
},
|
| 980 |
+
{
|
| 981 |
+
"case_id": "CASE26",
|
| 982 |
+
"cluster_id": "CAND26",
|
| 983 |
+
"customer_ids": [
|
| 984 |
+
"CUST0049",
|
| 985 |
+
"CUST0050",
|
| 986 |
+
"CUST0051",
|
| 987 |
+
"CUST0052"
|
| 988 |
+
],
|
| 989 |
+
"risk_probability": 0.0031715868230902835,
|
| 990 |
+
"policy_decision": "log_only",
|
| 991 |
+
"llm_narrative": null,
|
| 992 |
+
"llm_confidence_statement": null,
|
| 993 |
+
"action_taken": null,
|
| 994 |
+
"timestamp": "2026-08-22T02:42:46.530230+00:00"
|
| 995 |
+
},
|
| 996 |
+
{
|
| 997 |
+
"case_id": "CASE27",
|
| 998 |
+
"cluster_id": "CAND27",
|
| 999 |
+
"customer_ids": [
|
| 1000 |
+
"CUST0053",
|
| 1001 |
+
"CUST0054",
|
| 1002 |
+
"CUST0055",
|
| 1003 |
+
"CUST0056"
|
| 1004 |
+
],
|
| 1005 |
+
"risk_probability": 0.003058997865465553,
|
| 1006 |
+
"policy_decision": "log_only",
|
| 1007 |
+
"llm_narrative": null,
|
| 1008 |
+
"llm_confidence_statement": null,
|
| 1009 |
+
"action_taken": null,
|
| 1010 |
+
"timestamp": "2026-08-22T02:42:46.534325+00:00"
|
| 1011 |
+
},
|
| 1012 |
+
{
|
| 1013 |
+
"case_id": "CASE28",
|
| 1014 |
+
"cluster_id": "CAND28",
|
| 1015 |
+
"customer_ids": [
|
| 1016 |
+
"CUST0504",
|
| 1017 |
+
"CUST0505",
|
| 1018 |
+
"CUST0506"
|
| 1019 |
+
],
|
| 1020 |
+
"risk_probability": 0.003546939654202544,
|
| 1021 |
+
"policy_decision": "log_only",
|
| 1022 |
+
"llm_narrative": null,
|
| 1023 |
+
"llm_confidence_statement": null,
|
| 1024 |
+
"action_taken": null,
|
| 1025 |
+
"timestamp": "2026-08-22T02:42:46.537834+00:00"
|
| 1026 |
+
}
|
| 1027 |
+
]
|
data/synthetic/customers.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
data/synthetic/devices.json
ADDED
|
@@ -0,0 +1,1622 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
{
|
| 3 |
+
"device_id": "DEV0001",
|
| 4 |
+
"fingerprint_hash": "80dd747f3716dd56b933c731983355211eea88582cb7cb97b1ee0602fe525d5b"
|
| 5 |
+
},
|
| 6 |
+
{
|
| 7 |
+
"device_id": "DEV0002",
|
| 8 |
+
"fingerprint_hash": "a2ca018cf73581bf404317a767e526092c45f55a7a6a2cc8a174a9151f3ce7dd"
|
| 9 |
+
},
|
| 10 |
+
{
|
| 11 |
+
"device_id": "DEV0003",
|
| 12 |
+
"fingerprint_hash": "c99d12ce6ca80227ac35a8c202fa708ddc95933c2c04e44e9eaf42792ce7bceb"
|
| 13 |
+
},
|
| 14 |
+
{
|
| 15 |
+
"device_id": "DEV0004",
|
| 16 |
+
"fingerprint_hash": "f927513b1a5a6e6e5814b13c49aca9ca4e1eac05e3cdbf5412a32a29cde57d69"
|
| 17 |
+
},
|
| 18 |
+
{
|
| 19 |
+
"device_id": "DEV0005",
|
| 20 |
+
"fingerprint_hash": "c0ea731f429a0dbfd7eb578e56342e57dd88a032a846ef4bab118927b7288cae"
|
| 21 |
+
},
|
| 22 |
+
{
|
| 23 |
+
"device_id": "DEV0006",
|
| 24 |
+
"fingerprint_hash": "85a6f257b8128daf5841388e36925a7188d80e60b603d5249c6f2c3384a06bf0"
|
| 25 |
+
},
|
| 26 |
+
{
|
| 27 |
+
"device_id": "DEV0007",
|
| 28 |
+
"fingerprint_hash": "3f7ad5dfdc47e2f1bdc56a302140cee0f22d497d7d522fb8866a8d01219fe156"
|
| 29 |
+
},
|
| 30 |
+
{
|
| 31 |
+
"device_id": "DEV0008",
|
| 32 |
+
"fingerprint_hash": "8b986911a10d39a2dfb0c5e5b8c576802a6df1ee945aee55e232926db3f513a1"
|
| 33 |
+
},
|
| 34 |
+
{
|
| 35 |
+
"device_id": "DEV0009",
|
| 36 |
+
"fingerprint_hash": "24cb30e25cd01403efb4b1b136d0f894cf1a418bc2eae55d085bb678b8a1c347"
|
| 37 |
+
},
|
| 38 |
+
{
|
| 39 |
+
"device_id": "DEV0010",
|
| 40 |
+
"fingerprint_hash": "de873c3e1a42235d7c544dd2e2f19a43c7f6fde42c7916780f8a89628c3e54dd"
|
| 41 |
+
},
|
| 42 |
+
{
|
| 43 |
+
"device_id": "DEV0011",
|
| 44 |
+
"fingerprint_hash": "82f5916c950f3834351b58856c880fe4094cf06ce20db6e7f4bf480c2835cf56"
|
| 45 |
+
},
|
| 46 |
+
{
|
| 47 |
+
"device_id": "DEV0012",
|
| 48 |
+
"fingerprint_hash": "e2f01e9e89b7a4ca0cecf625d781caec16e012be73bb28170b94db3ac5dcc11e"
|
| 49 |
+
},
|
| 50 |
+
{
|
| 51 |
+
"device_id": "DEV0013",
|
| 52 |
+
"fingerprint_hash": "92b0e7cc6b9af30e56ef6ebb34ecdd7ec2b28b810c4e7ddc196dff166339da14"
|
| 53 |
+
},
|
| 54 |
+
{
|
| 55 |
+
"device_id": "DEV0014",
|
| 56 |
+
"fingerprint_hash": "a28ac6a502fe2431f72e1f8f0b7d1a081279a5f12c98f2dde7cb6c747f1726e9"
|
| 57 |
+
},
|
| 58 |
+
{
|
| 59 |
+
"device_id": "DEV0015",
|
| 60 |
+
"fingerprint_hash": "8f745cdeba5ce6854a397da814afd57453b0bff7aa03f47554e8049b112c879a"
|
| 61 |
+
},
|
| 62 |
+
{
|
| 63 |
+
"device_id": "DEV0016",
|
| 64 |
+
"fingerprint_hash": "e55f152153a5de8d4b958763145e990020c059c770f85e3be729ad324872e429"
|
| 65 |
+
},
|
| 66 |
+
{
|
| 67 |
+
"device_id": "DEV0017",
|
| 68 |
+
"fingerprint_hash": "90348642cc0b1e13e5b07e17d185255df894eb65ab2dc3d455bc85ec5a1fb1b0"
|
| 69 |
+
},
|
| 70 |
+
{
|
| 71 |
+
"device_id": "DEV0018",
|
| 72 |
+
"fingerprint_hash": "b0cea960e30dabadbcce56690cc31a9b014e69495d6ed0a3bcc1a8dba1f560c5"
|
| 73 |
+
},
|
| 74 |
+
{
|
| 75 |
+
"device_id": "DEV0019",
|
| 76 |
+
"fingerprint_hash": "95ac359e7f63862c3b000ff6d7823988535a6d46d63691be7671be8ae5df10a9"
|
| 77 |
+
},
|
| 78 |
+
{
|
| 79 |
+
"device_id": "DEV0020",
|
| 80 |
+
"fingerprint_hash": "09bd5e6e6fbd47340b2e522f08673748ad4b221bb13acde2f3c852129d58feaa"
|
| 81 |
+
},
|
| 82 |
+
{
|
| 83 |
+
"device_id": "DEV0021",
|
| 84 |
+
"fingerprint_hash": "ada149be46843f511551113fd3be1c4bcac48adc698a6742dff5642441bae07f"
|
| 85 |
+
},
|
| 86 |
+
{
|
| 87 |
+
"device_id": "DEV0022",
|
| 88 |
+
"fingerprint_hash": "28ae808824e145ae8d20deebf8379231942fa3a936dbee29a231f483471535c5"
|
| 89 |
+
},
|
| 90 |
+
{
|
| 91 |
+
"device_id": "DEV0023",
|
| 92 |
+
"fingerprint_hash": "dd93d76752cf7a23c9ffeae68b31852f920a2120867e579a9ec6b8751b13b19d"
|
| 93 |
+
},
|
| 94 |
+
{
|
| 95 |
+
"device_id": "DEV0024",
|
| 96 |
+
"fingerprint_hash": "66f59f5593724ee82d76af4b65b29bc37b6a5e929acd8c9c4edc7bc1faf0754c"
|
| 97 |
+
},
|
| 98 |
+
{
|
| 99 |
+
"device_id": "DEV0025",
|
| 100 |
+
"fingerprint_hash": "e247d3458befeaa26ba592d5efb3c6a9d7e931266153015768bd7e43a6dc4f18"
|
| 101 |
+
},
|
| 102 |
+
{
|
| 103 |
+
"device_id": "DEV0026",
|
| 104 |
+
"fingerprint_hash": "15c786452a55638b8e1ef4741f1919d391e4206766d8db03ecfab29abc08ce9c"
|
| 105 |
+
},
|
| 106 |
+
{
|
| 107 |
+
"device_id": "DEV0027",
|
| 108 |
+
"fingerprint_hash": "11987d41b7ebe2e0e08d64441810c22dd5406d981e686b9122c6fc75cda8ea51"
|
| 109 |
+
},
|
| 110 |
+
{
|
| 111 |
+
"device_id": "DEV0028",
|
| 112 |
+
"fingerprint_hash": "ee9b014777a4a7f42658efbaaaeecdb56ae54417649ccba9e315c49f4d029f55"
|
| 113 |
+
},
|
| 114 |
+
{
|
| 115 |
+
"device_id": "DEV0029",
|
| 116 |
+
"fingerprint_hash": "82c4fcc7343a13da1d8ca1995630bf94e4c48dc82aedaa0d6a940c9b877fe828"
|
| 117 |
+
},
|
| 118 |
+
{
|
| 119 |
+
"device_id": "DEV0030",
|
| 120 |
+
"fingerprint_hash": "3949979a4ed3302445afa9090c2400e68ce3cf1626f5bd5c56cf8e9beb0c324f"
|
| 121 |
+
},
|
| 122 |
+
{
|
| 123 |
+
"device_id": "DEV0031",
|
| 124 |
+
"fingerprint_hash": "bf180a97506eddf73f797624d1ca2747fe072a680d1f8feb87522e3a2863ab0d"
|
| 125 |
+
},
|
| 126 |
+
{
|
| 127 |
+
"device_id": "DEV0032",
|
| 128 |
+
"fingerprint_hash": "35e77b95db18460dcee46976eefdcb656b2538e568caa5c6464107f5b184b43f"
|
| 129 |
+
},
|
| 130 |
+
{
|
| 131 |
+
"device_id": "DEV0033",
|
| 132 |
+
"fingerprint_hash": "385d83f1e711a6c59b3dae4d4370becdd450d406f5484bdd1d2de4be6ee162dd"
|
| 133 |
+
},
|
| 134 |
+
{
|
| 135 |
+
"device_id": "DEV0034",
|
| 136 |
+
"fingerprint_hash": "02452a07c7d59ae73938060771f3a3c9e63817115d6c38d1509864019629f455"
|
| 137 |
+
},
|
| 138 |
+
{
|
| 139 |
+
"device_id": "DEV0035",
|
| 140 |
+
"fingerprint_hash": "070b608bd70d53b152dca52ca12317b6765cd688be2a88d5de4756b956e53231"
|
| 141 |
+
},
|
| 142 |
+
{
|
| 143 |
+
"device_id": "DEV0036",
|
| 144 |
+
"fingerprint_hash": "1aeae6eda5fb48cb52f612f619fc19dead171885df81e0a24ef8422f4e5a2b3f"
|
| 145 |
+
},
|
| 146 |
+
{
|
| 147 |
+
"device_id": "DEV0037",
|
| 148 |
+
"fingerprint_hash": "04897f616fa40d3c6f5a183e62e1b4baf5b84a54067fbbc4030f715a5ce85f52"
|
| 149 |
+
},
|
| 150 |
+
{
|
| 151 |
+
"device_id": "DEV0038",
|
| 152 |
+
"fingerprint_hash": "36347a0ba4c5f8a2b59939b278decd023ae03afad64fd19952d010fdc03e2f93"
|
| 153 |
+
},
|
| 154 |
+
{
|
| 155 |
+
"device_id": "DEV0039",
|
| 156 |
+
"fingerprint_hash": "19aad1bf58c2ea6d35b23ba6f8c4e8f74098097013e178306f24dee7a5296b0c"
|
| 157 |
+
},
|
| 158 |
+
{
|
| 159 |
+
"device_id": "DEV0040",
|
| 160 |
+
"fingerprint_hash": "d67ebb698454aaa8428ddbaf5c7c4f0ca27da2a3e62da0ec863ef921ecbb7f34"
|
| 161 |
+
},
|
| 162 |
+
{
|
| 163 |
+
"device_id": "DEV0041",
|
| 164 |
+
"fingerprint_hash": "cfe8eccabfbe132b62a82adaf7c1c5c9b7566a14e86236361374a3f2429a94d8"
|
| 165 |
+
},
|
| 166 |
+
{
|
| 167 |
+
"device_id": "DEV0042",
|
| 168 |
+
"fingerprint_hash": "b935a681b5961d6e0fcfaffb5a444c09eebe778ad40335225882706f6ad50f21"
|
| 169 |
+
},
|
| 170 |
+
{
|
| 171 |
+
"device_id": "DEV0043",
|
| 172 |
+
"fingerprint_hash": "5f530db327760254140d9436404e37d60ca32d8e0158516621e0e447c2292b0e"
|
| 173 |
+
},
|
| 174 |
+
{
|
| 175 |
+
"device_id": "DEV0044",
|
| 176 |
+
"fingerprint_hash": "c0a6b17ecc53ae4b3ffb43c273f61ef0e32eb9c616a30ed16a213b23b63e322c"
|
| 177 |
+
},
|
| 178 |
+
{
|
| 179 |
+
"device_id": "DEV0045",
|
| 180 |
+
"fingerprint_hash": "08e48a8732db10b3fcf8c108070736fce2876c5ffbe0f8bade0483c686905aba"
|
| 181 |
+
},
|
| 182 |
+
{
|
| 183 |
+
"device_id": "DEV0046",
|
| 184 |
+
"fingerprint_hash": "cf2fde6fa6d2405f45eac3d626ee25b406d8a060ea9158439ba188b33a4a3c0f"
|
| 185 |
+
},
|
| 186 |
+
{
|
| 187 |
+
"device_id": "DEV0047",
|
| 188 |
+
"fingerprint_hash": "c127cdbe3b45ed343cacdd309a58132392becf54e617b3b79aec8a191eaf015d"
|
| 189 |
+
},
|
| 190 |
+
{
|
| 191 |
+
"device_id": "DEV0048",
|
| 192 |
+
"fingerprint_hash": "61a2d4085c8248d06dd7c68c21e809a1a24bbcc6cc7f2ab2b2296dc98f5127b0"
|
| 193 |
+
},
|
| 194 |
+
{
|
| 195 |
+
"device_id": "DEV0049",
|
| 196 |
+
"fingerprint_hash": "88eaec76dac2f2438c7bebd81f9dbd0fe4538ecf14b3ff6fe4639f99f02c8a5f"
|
| 197 |
+
},
|
| 198 |
+
{
|
| 199 |
+
"device_id": "DEV0050",
|
| 200 |
+
"fingerprint_hash": "ca61a32fb5241c5b38f30ef63328eca2816cf15c8b35303c7ae9d7671a599bd8"
|
| 201 |
+
},
|
| 202 |
+
{
|
| 203 |
+
"device_id": "DEV0051",
|
| 204 |
+
"fingerprint_hash": "3b0151220be1f21df3293068efa7fe45d4076a9c401ed5e63aa73ab66d9fe696"
|
| 205 |
+
},
|
| 206 |
+
{
|
| 207 |
+
"device_id": "DEV0052",
|
| 208 |
+
"fingerprint_hash": "508c6ceaeb33916ee8b93c51f2b33309df303143351cd680317a0a221b794ab4"
|
| 209 |
+
},
|
| 210 |
+
{
|
| 211 |
+
"device_id": "DEV0053",
|
| 212 |
+
"fingerprint_hash": "6a5c6fc453aca12e208960d9d81629c889ade125b728ec1e7e099daca2f65163"
|
| 213 |
+
},
|
| 214 |
+
{
|
| 215 |
+
"device_id": "DEV0054",
|
| 216 |
+
"fingerprint_hash": "aed1fc09f50aabc03df59d27779c2dd5748acc98f1a1d91e22b1a9a5bade0f1b"
|
| 217 |
+
},
|
| 218 |
+
{
|
| 219 |
+
"device_id": "DEV0055",
|
| 220 |
+
"fingerprint_hash": "7e69d25fcb6a833c665622c788b2f8c4b80acc9f4c9dd9a105d56d415ac352df"
|
| 221 |
+
},
|
| 222 |
+
{
|
| 223 |
+
"device_id": "DEV0056",
|
| 224 |
+
"fingerprint_hash": "11eaac8509ad85a68ae64ce5c7024f833e44d6f1f7f71bf5a1b8a8f96c694e45"
|
| 225 |
+
},
|
| 226 |
+
{
|
| 227 |
+
"device_id": "DEV0057",
|
| 228 |
+
"fingerprint_hash": "d25e4e14d7c33840032cd72129ab233e57d854bda2bdb7ffab4cb596e29e6e34"
|
| 229 |
+
},
|
| 230 |
+
{
|
| 231 |
+
"device_id": "DEV0058",
|
| 232 |
+
"fingerprint_hash": "39f30301a776f5138f910aef0ade88f967829704f9d09ac71968c3a65b0fbcac"
|
| 233 |
+
},
|
| 234 |
+
{
|
| 235 |
+
"device_id": "DEV0059",
|
| 236 |
+
"fingerprint_hash": "52e183394b013d780ecf97c25a8d93794bbf40c5d589d2c7d32617153e62675f"
|
| 237 |
+
},
|
| 238 |
+
{
|
| 239 |
+
"device_id": "DEV0060",
|
| 240 |
+
"fingerprint_hash": "24fa85425cafa2a1797f09e9edd43862674ec0808202b573311cdce269abcdc5"
|
| 241 |
+
},
|
| 242 |
+
{
|
| 243 |
+
"device_id": "DEV0061",
|
| 244 |
+
"fingerprint_hash": "4b3ad38a628d961308e0ac9f295876f6ee9b1754fb95921a2d6eb42306923432"
|
| 245 |
+
},
|
| 246 |
+
{
|
| 247 |
+
"device_id": "DEV0062",
|
| 248 |
+
"fingerprint_hash": "f78512d228cbcd485d84a5797ad61ac3a48a8c3324ad2cb0bb82a5873dda2d43"
|
| 249 |
+
},
|
| 250 |
+
{
|
| 251 |
+
"device_id": "DEV0063",
|
| 252 |
+
"fingerprint_hash": "7d6b6550c63d369386428975597f30d0188246cc1b01d993e67853b9df636301"
|
| 253 |
+
},
|
| 254 |
+
{
|
| 255 |
+
"device_id": "DEV0064",
|
| 256 |
+
"fingerprint_hash": "1701d293a290a967c56fb940b5b1422b732bfd40cb6529afe3b8b8cd4758cffb"
|
| 257 |
+
},
|
| 258 |
+
{
|
| 259 |
+
"device_id": "DEV0065",
|
| 260 |
+
"fingerprint_hash": "593a3dbea28a2dcb92e04be796fa35ed20b2913dbb2e2af49b549f15d62b01b3"
|
| 261 |
+
},
|
| 262 |
+
{
|
| 263 |
+
"device_id": "DEV0066",
|
| 264 |
+
"fingerprint_hash": "c6e44d279a50e5762dd8952e0645a6819c7c1029e6bd2e80c6685545357d8b77"
|
| 265 |
+
},
|
| 266 |
+
{
|
| 267 |
+
"device_id": "DEV0067",
|
| 268 |
+
"fingerprint_hash": "6a0f79364d6c803e9e98ef1ab6d792bab13f500d5ddb2f2fe82e913b306f1b23"
|
| 269 |
+
},
|
| 270 |
+
{
|
| 271 |
+
"device_id": "DEV0068",
|
| 272 |
+
"fingerprint_hash": "833d50d4829bc0423421094c01bd1db405470b6b01faca640a4ba3e379e43112"
|
| 273 |
+
},
|
| 274 |
+
{
|
| 275 |
+
"device_id": "DEV0069",
|
| 276 |
+
"fingerprint_hash": "8cb6607072ce80bf74deaf9ebdca568d2c2e103fe549948db981cda1460bd325"
|
| 277 |
+
},
|
| 278 |
+
{
|
| 279 |
+
"device_id": "DEV0070",
|
| 280 |
+
"fingerprint_hash": "e47b3123946724dda2cab2a22db7da4bca1a1fddd5027c3d295600898f017578"
|
| 281 |
+
},
|
| 282 |
+
{
|
| 283 |
+
"device_id": "DEV0071",
|
| 284 |
+
"fingerprint_hash": "1fc951170dda341c54c80edb97e05842375a0a3e23568705e85bb9f7dbf81658"
|
| 285 |
+
},
|
| 286 |
+
{
|
| 287 |
+
"device_id": "DEV0072",
|
| 288 |
+
"fingerprint_hash": "eda05f844426790623c45c1a02431dcdbfbbde54e8c973759529b198760edf5d"
|
| 289 |
+
},
|
| 290 |
+
{
|
| 291 |
+
"device_id": "DEV0073",
|
| 292 |
+
"fingerprint_hash": "435a3b6bcf4051c62669d3542f57028d4d1ba0137a36f9f38a633332a5303649"
|
| 293 |
+
},
|
| 294 |
+
{
|
| 295 |
+
"device_id": "DEV0074",
|
| 296 |
+
"fingerprint_hash": "9bee8c9bfb9e65c9c300698d6e4e64e2aa99e5f5c36e7a0ab436d01b2c723d9c"
|
| 297 |
+
},
|
| 298 |
+
{
|
| 299 |
+
"device_id": "DEV0075",
|
| 300 |
+
"fingerprint_hash": "b617d2dde84b3bf25343094d5809c3a25fb56cd53ab79026249c5ada18b785c4"
|
| 301 |
+
},
|
| 302 |
+
{
|
| 303 |
+
"device_id": "DEV0076",
|
| 304 |
+
"fingerprint_hash": "8cfc0db2290e2f2bc460b4ec922d4a7276628e252215255b0f53ef1d5710c258"
|
| 305 |
+
},
|
| 306 |
+
{
|
| 307 |
+
"device_id": "DEV0077",
|
| 308 |
+
"fingerprint_hash": "88e8b456d78265c3342f618b3423eb8abbbccd8eed6937592c78723eccf7411a"
|
| 309 |
+
},
|
| 310 |
+
{
|
| 311 |
+
"device_id": "DEV0078",
|
| 312 |
+
"fingerprint_hash": "a8b66885ca54d4c85c107e6c27b948c7086bb67244470950347b7c7038470472"
|
| 313 |
+
},
|
| 314 |
+
{
|
| 315 |
+
"device_id": "DEV0079",
|
| 316 |
+
"fingerprint_hash": "ba15256e56e10ac5743d671438b3e11dc8e4b572a90f49d166f289bcfc47e7ec"
|
| 317 |
+
},
|
| 318 |
+
{
|
| 319 |
+
"device_id": "DEV0080",
|
| 320 |
+
"fingerprint_hash": "0b9a7c5dd71c9fae593b631c74f562858113bef1919f876b7bfb1995e84bf18a"
|
| 321 |
+
},
|
| 322 |
+
{
|
| 323 |
+
"device_id": "DEV0081",
|
| 324 |
+
"fingerprint_hash": "b60dce9f2842489e093d7bc9cffec7d253dfe515c2ad5ceeeee55b459daa2cb7"
|
| 325 |
+
},
|
| 326 |
+
{
|
| 327 |
+
"device_id": "DEV0082",
|
| 328 |
+
"fingerprint_hash": "cc9c8955681c577a3972d4a1004c6c2d2da09e4307958efdb91de32387c4957c"
|
| 329 |
+
},
|
| 330 |
+
{
|
| 331 |
+
"device_id": "DEV0083",
|
| 332 |
+
"fingerprint_hash": "8741acbe2d0c6b84021c5f1a68d55344a1998f658d41824cbe6686447d61c499"
|
| 333 |
+
},
|
| 334 |
+
{
|
| 335 |
+
"device_id": "DEV0084",
|
| 336 |
+
"fingerprint_hash": "3a67180bd370329e3d135c153cc84db335eaf25bc782dfe6c8933b74983aa201"
|
| 337 |
+
},
|
| 338 |
+
{
|
| 339 |
+
"device_id": "DEV0085",
|
| 340 |
+
"fingerprint_hash": "d427efd1ca295210073ae45fbcdabdc077344c7debb3c8efd22fae5697b82322"
|
| 341 |
+
},
|
| 342 |
+
{
|
| 343 |
+
"device_id": "DEV0086",
|
| 344 |
+
"fingerprint_hash": "bafc63bb7efdabdeecb6a7ec9d74e4fa9c884bc54972f4c1f2f72a260cc48c96"
|
| 345 |
+
},
|
| 346 |
+
{
|
| 347 |
+
"device_id": "DEV0087",
|
| 348 |
+
"fingerprint_hash": "39ac507dc3ef4d086fa60d8dc9a5be789e5a8bbd28af301d6e5d6265e95d7d6e"
|
| 349 |
+
},
|
| 350 |
+
{
|
| 351 |
+
"device_id": "DEV0088",
|
| 352 |
+
"fingerprint_hash": "817aa050481c4747e0505cbee4ea854e38ec50289cdfd24058e37959eab5509d"
|
| 353 |
+
},
|
| 354 |
+
{
|
| 355 |
+
"device_id": "DEV0089",
|
| 356 |
+
"fingerprint_hash": "29327096afa18aae754feccd40ea64aec5abcef342199322e718945f2439e911"
|
| 357 |
+
},
|
| 358 |
+
{
|
| 359 |
+
"device_id": "DEV0090",
|
| 360 |
+
"fingerprint_hash": "853681c1b26e7425d9b5147565e1ff775de1bfbc1be06161a5a1cd2cb9d113d4"
|
| 361 |
+
},
|
| 362 |
+
{
|
| 363 |
+
"device_id": "DEV0091",
|
| 364 |
+
"fingerprint_hash": "73e99ec7f1044cbd2318bd1c7ce3648a9d6a83797c2f69aacc7f028fe9942ff8"
|
| 365 |
+
},
|
| 366 |
+
{
|
| 367 |
+
"device_id": "DEV0092",
|
| 368 |
+
"fingerprint_hash": "41bc4b2975b1a1f96b919175e93bafe6750f3d2075a308ddf5b1754c17308d91"
|
| 369 |
+
},
|
| 370 |
+
{
|
| 371 |
+
"device_id": "DEV0093",
|
| 372 |
+
"fingerprint_hash": "b73548c18699ce47a63cba0d6632c1b704bf1a77ec74ddafbe0b7247c010b72b"
|
| 373 |
+
},
|
| 374 |
+
{
|
| 375 |
+
"device_id": "DEV0094",
|
| 376 |
+
"fingerprint_hash": "42213b8e1e6ce68c23aea644889bd79c2c1c116253f98dbea48ace33928c9093"
|
| 377 |
+
},
|
| 378 |
+
{
|
| 379 |
+
"device_id": "DEV0095",
|
| 380 |
+
"fingerprint_hash": "7a8c66680e4644618e21c8af793aad5fa54c5ecb67b3c0209ce0352982340be5"
|
| 381 |
+
},
|
| 382 |
+
{
|
| 383 |
+
"device_id": "DEV0096",
|
| 384 |
+
"fingerprint_hash": "f696db148acfdf2419d3f9ab885f62373d7b081e846e452045140839e320f7ae"
|
| 385 |
+
},
|
| 386 |
+
{
|
| 387 |
+
"device_id": "DEV0097",
|
| 388 |
+
"fingerprint_hash": "54e99a8b6818a9cb2c563c607fbb8c7d57721140b672eca70ddfe50f742cd9bb"
|
| 389 |
+
},
|
| 390 |
+
{
|
| 391 |
+
"device_id": "DEV0098",
|
| 392 |
+
"fingerprint_hash": "3975220db138f0e5ae60abb0ee590a18c9d5aeaf704dfd3ce8886b3d2dd4a165"
|
| 393 |
+
},
|
| 394 |
+
{
|
| 395 |
+
"device_id": "DEV0099",
|
| 396 |
+
"fingerprint_hash": "c71abbab99a200f2b44e74fa2db31eb6d7cd36251c6764aaa82fa6153047957c"
|
| 397 |
+
},
|
| 398 |
+
{
|
| 399 |
+
"device_id": "DEV0100",
|
| 400 |
+
"fingerprint_hash": "91fdbcb265b4e0f06b0dd9ea04f1de208497dd1626e8784057a6b4c5cfaf39e3"
|
| 401 |
+
},
|
| 402 |
+
{
|
| 403 |
+
"device_id": "DEV0101",
|
| 404 |
+
"fingerprint_hash": "a1947716850a2b2a0ff985aed22b25b3668b2b3cca1270adace18f703f6d25f2"
|
| 405 |
+
},
|
| 406 |
+
{
|
| 407 |
+
"device_id": "DEV0102",
|
| 408 |
+
"fingerprint_hash": "11df1f2a615dd7ce447ebbec5d6a89f328ed46685f1fd50be02d4f5749c601f3"
|
| 409 |
+
},
|
| 410 |
+
{
|
| 411 |
+
"device_id": "DEV0103",
|
| 412 |
+
"fingerprint_hash": "3d85970bad02acfdc6e9a6dfab738d26a4102b5b9bc2484008920982303c8d54"
|
| 413 |
+
},
|
| 414 |
+
{
|
| 415 |
+
"device_id": "DEV0104",
|
| 416 |
+
"fingerprint_hash": "0e3e3040d29b0b93da8cce005cf96febf46e6a7c01c6b4ad56f59d9cd67ee664"
|
| 417 |
+
},
|
| 418 |
+
{
|
| 419 |
+
"device_id": "DEV0105",
|
| 420 |
+
"fingerprint_hash": "24078f2a3924aae7ae12b4cb88ca8e7631b887d3fb93d3cd9615f18326864dfd"
|
| 421 |
+
},
|
| 422 |
+
{
|
| 423 |
+
"device_id": "DEV0106",
|
| 424 |
+
"fingerprint_hash": "4d3cf93f98b9ce67bf7753c2c65874b855f80e52cd6340dcebf00ad90d164f01"
|
| 425 |
+
},
|
| 426 |
+
{
|
| 427 |
+
"device_id": "DEV0107",
|
| 428 |
+
"fingerprint_hash": "b4b5f295d77209a1bc23a06d15fc5dc9d31804844ed47995ea4e1e9cfd148cf8"
|
| 429 |
+
},
|
| 430 |
+
{
|
| 431 |
+
"device_id": "DEV0108",
|
| 432 |
+
"fingerprint_hash": "83f6ed958b524931453f05f6ac6a8fd585dcf1dbf45ce76be59bc0462318193e"
|
| 433 |
+
},
|
| 434 |
+
{
|
| 435 |
+
"device_id": "DEV0109",
|
| 436 |
+
"fingerprint_hash": "3f51ed22788be7ce2b8d4cb5a435766cf2725b37061f6fcd27aaec20dbef746e"
|
| 437 |
+
},
|
| 438 |
+
{
|
| 439 |
+
"device_id": "DEV0110",
|
| 440 |
+
"fingerprint_hash": "0228e1ecc4f4ec1389c84f5e18c3872a3adc1615e2ce472c2c29ac050dd42a29"
|
| 441 |
+
},
|
| 442 |
+
{
|
| 443 |
+
"device_id": "DEV0111",
|
| 444 |
+
"fingerprint_hash": "e9d645dd83efe4cd562b73710254625d0d27ba8d6f2b896922868146011bf880"
|
| 445 |
+
},
|
| 446 |
+
{
|
| 447 |
+
"device_id": "DEV0112",
|
| 448 |
+
"fingerprint_hash": "f1b79819a725cf8540e185f7d65c030ae0bc2a889028b2925b138e98db7720f2"
|
| 449 |
+
},
|
| 450 |
+
{
|
| 451 |
+
"device_id": "DEV0113",
|
| 452 |
+
"fingerprint_hash": "b4d74a90f99ca43f8245cb0e4448785e51b9fd38a1df23c95332a6a3becf3a2a"
|
| 453 |
+
},
|
| 454 |
+
{
|
| 455 |
+
"device_id": "DEV0114",
|
| 456 |
+
"fingerprint_hash": "8cc68ca33e2d1a114d58215f396ef7f64ad017093e85885ca120ed9b5abe7a85"
|
| 457 |
+
},
|
| 458 |
+
{
|
| 459 |
+
"device_id": "DEV0115",
|
| 460 |
+
"fingerprint_hash": "f14ef2e9ac6efad90d2146d12f9e938cccd9b99498426caae15595ad71548e11"
|
| 461 |
+
},
|
| 462 |
+
{
|
| 463 |
+
"device_id": "DEV0116",
|
| 464 |
+
"fingerprint_hash": "0f8e632cf92aee8766989ed8d5673bb1d6677ca631c5adbdb1c06dc319c8140d"
|
| 465 |
+
},
|
| 466 |
+
{
|
| 467 |
+
"device_id": "DEV0117",
|
| 468 |
+
"fingerprint_hash": "31a317db95f8fa02ba39ec7eda32642c28946ff34d4cfcbd7d8c50846fb27990"
|
| 469 |
+
},
|
| 470 |
+
{
|
| 471 |
+
"device_id": "DEV0118",
|
| 472 |
+
"fingerprint_hash": "2ea8c20e389601eb119dd62202a3d18a1880ea6aa867da53d309c6fd37f5f61b"
|
| 473 |
+
},
|
| 474 |
+
{
|
| 475 |
+
"device_id": "DEV0119",
|
| 476 |
+
"fingerprint_hash": "adaf093609582ed99409272e44d76ca6d5ac9c8d076e955b80465197a1bc9f19"
|
| 477 |
+
},
|
| 478 |
+
{
|
| 479 |
+
"device_id": "DEV0120",
|
| 480 |
+
"fingerprint_hash": "5121f815bfb1639b79245f4b72b3b1f58fb2c91259d514ff713ba3615ac1f52e"
|
| 481 |
+
},
|
| 482 |
+
{
|
| 483 |
+
"device_id": "DEV0121",
|
| 484 |
+
"fingerprint_hash": "ea247c4bb3cba6cd75617c031f54da431304686119a9f3d7be23639f40ffc099"
|
| 485 |
+
},
|
| 486 |
+
{
|
| 487 |
+
"device_id": "DEV0122",
|
| 488 |
+
"fingerprint_hash": "26302b55508bdae671399da3870965494a485ba0701d8c01b1f0a9fa579810ab"
|
| 489 |
+
},
|
| 490 |
+
{
|
| 491 |
+
"device_id": "DEV0123",
|
| 492 |
+
"fingerprint_hash": "3ce8fd49960af87d309113e5b73a42d5e6db899b3689a826aac69b740060c6cc"
|
| 493 |
+
},
|
| 494 |
+
{
|
| 495 |
+
"device_id": "DEV0124",
|
| 496 |
+
"fingerprint_hash": "5252de879a6ce1b1c25270a458f2dc5473955462ab6a3c2c6ac8d37cac8b3f2f"
|
| 497 |
+
},
|
| 498 |
+
{
|
| 499 |
+
"device_id": "DEV0125",
|
| 500 |
+
"fingerprint_hash": "dbf386ebfc1134427e0710bcd250e7937cdcd77d06449a727f866d31f865001b"
|
| 501 |
+
},
|
| 502 |
+
{
|
| 503 |
+
"device_id": "DEV0126",
|
| 504 |
+
"fingerprint_hash": "ffdc1a0ee44a7d2a6066f826c860084d7a39198de7a288042ca249fbca9e6178"
|
| 505 |
+
},
|
| 506 |
+
{
|
| 507 |
+
"device_id": "DEV0127",
|
| 508 |
+
"fingerprint_hash": "b93c043125e7ac79650e85613a4b21b4e6edcdad28f3300da997cd2792518833"
|
| 509 |
+
},
|
| 510 |
+
{
|
| 511 |
+
"device_id": "DEV0128",
|
| 512 |
+
"fingerprint_hash": "dba1a97a422446923ddb8e9300700147a16c31479cb18ffdc4f103f022796462"
|
| 513 |
+
},
|
| 514 |
+
{
|
| 515 |
+
"device_id": "DEV0129",
|
| 516 |
+
"fingerprint_hash": "a52e480fa87f32ff9160a91b94d555dd1438765e36a158e92607cb3def940d03"
|
| 517 |
+
},
|
| 518 |
+
{
|
| 519 |
+
"device_id": "DEV0130",
|
| 520 |
+
"fingerprint_hash": "a139196ef3ce6f340448120c2e4a622092fc80d7b880227a656d1e957519ddb9"
|
| 521 |
+
},
|
| 522 |
+
{
|
| 523 |
+
"device_id": "DEV0131",
|
| 524 |
+
"fingerprint_hash": "1b82b311802452415be949f25d3475f4587bbf7ee01732dcce3ab8bf0552e05f"
|
| 525 |
+
},
|
| 526 |
+
{
|
| 527 |
+
"device_id": "DEV0132",
|
| 528 |
+
"fingerprint_hash": "dbbb1cb9ee3646719e6ae8170fb73ea5fd8406f403a6d32c31802f5033f8043f"
|
| 529 |
+
},
|
| 530 |
+
{
|
| 531 |
+
"device_id": "DEV0133",
|
| 532 |
+
"fingerprint_hash": "0140442ffe6f2815f974c243450ff57e38670d404bd7aa74072b4cda2b1b282c"
|
| 533 |
+
},
|
| 534 |
+
{
|
| 535 |
+
"device_id": "DEV0134",
|
| 536 |
+
"fingerprint_hash": "ac8feb34a99e6997a3d556ab2a0e833cc2ad09f336ebc3481787b4ff9448db67"
|
| 537 |
+
},
|
| 538 |
+
{
|
| 539 |
+
"device_id": "DEV0135",
|
| 540 |
+
"fingerprint_hash": "6138063d33ea88fc5d6f6b8c4249cb47934c8c272018fa2f127ac56003b531ad"
|
| 541 |
+
},
|
| 542 |
+
{
|
| 543 |
+
"device_id": "DEV0136",
|
| 544 |
+
"fingerprint_hash": "52597e82355f2a4a60f599d68f48416af919c67d60effd2beae178d61f664127"
|
| 545 |
+
},
|
| 546 |
+
{
|
| 547 |
+
"device_id": "DEV0137",
|
| 548 |
+
"fingerprint_hash": "650301a2c0289b93daf03894c43b20fca874dfa48eb9977e9b50d4497ce61bd1"
|
| 549 |
+
},
|
| 550 |
+
{
|
| 551 |
+
"device_id": "DEV0138",
|
| 552 |
+
"fingerprint_hash": "c107bbbadad87b75ffa29b367aa6d83b61ebf3c9b8c9e50477039870df596e8b"
|
| 553 |
+
},
|
| 554 |
+
{
|
| 555 |
+
"device_id": "DEV0139",
|
| 556 |
+
"fingerprint_hash": "e493efd4b5b56aa025cdc6a4db42b70a45d0faaa367792dd8c5788dd92ae2137"
|
| 557 |
+
},
|
| 558 |
+
{
|
| 559 |
+
"device_id": "DEV0140",
|
| 560 |
+
"fingerprint_hash": "f9e603caa31e2d663a62b9626ce0429c79a5e29e7e586c9703f8a998ffe77d7e"
|
| 561 |
+
},
|
| 562 |
+
{
|
| 563 |
+
"device_id": "DEV0141",
|
| 564 |
+
"fingerprint_hash": "c5ffe5ebca9062920bd1f5a3288b01216ff26ff7dfd16be8286cdbf16f5452a9"
|
| 565 |
+
},
|
| 566 |
+
{
|
| 567 |
+
"device_id": "DEV0142",
|
| 568 |
+
"fingerprint_hash": "0a67370ec6ff33ccd8df042e4e2d42ec9f6b73dd65a694eaa88c59627ccb7e55"
|
| 569 |
+
},
|
| 570 |
+
{
|
| 571 |
+
"device_id": "DEV0143",
|
| 572 |
+
"fingerprint_hash": "cd074ee306428c4c335ebc302c0f9f1c06a31a0c5088f2cb6a06308fb01d7f6e"
|
| 573 |
+
},
|
| 574 |
+
{
|
| 575 |
+
"device_id": "DEV0144",
|
| 576 |
+
"fingerprint_hash": "a30e6012968ce08aca308c81e0d5297ea387c0becbbdff83e69a518ba8f581c1"
|
| 577 |
+
},
|
| 578 |
+
{
|
| 579 |
+
"device_id": "DEV0145",
|
| 580 |
+
"fingerprint_hash": "721d0ff76c1bb31718fb7ad3e34c624d235f2a69a388ccac9a900efc1012b763"
|
| 581 |
+
},
|
| 582 |
+
{
|
| 583 |
+
"device_id": "DEV0146",
|
| 584 |
+
"fingerprint_hash": "735e4f332bcae2d65888e20f78ca33d2cb5a61a6af8b9d639691ba7fa912d30d"
|
| 585 |
+
},
|
| 586 |
+
{
|
| 587 |
+
"device_id": "DEV0147",
|
| 588 |
+
"fingerprint_hash": "2551ffb8d9624a19de5b38c18e96ee22a3ca589e6b2e81c92b6810b5904de2e6"
|
| 589 |
+
},
|
| 590 |
+
{
|
| 591 |
+
"device_id": "DEV0148",
|
| 592 |
+
"fingerprint_hash": "28b3d8e8661c5fe68c3adb1d8b39c3ad3cad5583d8d5ee436a5992a97c78e3f1"
|
| 593 |
+
},
|
| 594 |
+
{
|
| 595 |
+
"device_id": "DEV0149",
|
| 596 |
+
"fingerprint_hash": "c5821128931ca2fe459884b61732177af5e72dd4bfdad39f90c5853570f60084"
|
| 597 |
+
},
|
| 598 |
+
{
|
| 599 |
+
"device_id": "DEV0150",
|
| 600 |
+
"fingerprint_hash": "f3ac4b7a6b2cbc0ee82f77863ced05418effa7245f7af41a5e9dd4bbf7e5ee2d"
|
| 601 |
+
},
|
| 602 |
+
{
|
| 603 |
+
"device_id": "DEV0151",
|
| 604 |
+
"fingerprint_hash": "18256de44a5ff0d275facfdf91076d360b28618e09e30789dc61e140f4175b84"
|
| 605 |
+
},
|
| 606 |
+
{
|
| 607 |
+
"device_id": "DEV0152",
|
| 608 |
+
"fingerprint_hash": "d3a693d2859e142bd62896745814ba2d480488c85d8e19f2ca1f5a5d1193cf9c"
|
| 609 |
+
},
|
| 610 |
+
{
|
| 611 |
+
"device_id": "DEV0153",
|
| 612 |
+
"fingerprint_hash": "cc68965e9c4b321388dafd285335e1ab7022f4730c32297c825e9ffd406b5f05"
|
| 613 |
+
},
|
| 614 |
+
{
|
| 615 |
+
"device_id": "DEV0154",
|
| 616 |
+
"fingerprint_hash": "30cb9f08032174e5c6dd523f72e258d6884fcdb73957b1569586388c7ab00180"
|
| 617 |
+
},
|
| 618 |
+
{
|
| 619 |
+
"device_id": "DEV0155",
|
| 620 |
+
"fingerprint_hash": "b13a743e1569533dd0a0bbe43a26505df8c774167a25bc236794c622196885c7"
|
| 621 |
+
},
|
| 622 |
+
{
|
| 623 |
+
"device_id": "DEV0156",
|
| 624 |
+
"fingerprint_hash": "ec955baadd25ee1acb240cc18501f5f9b95c922848205dab7e9c52872759dcdc"
|
| 625 |
+
},
|
| 626 |
+
{
|
| 627 |
+
"device_id": "DEV0157",
|
| 628 |
+
"fingerprint_hash": "c970edd75ce821717e1611fbe03b372b6a38826841a24b5c6984cd86013d3b3b"
|
| 629 |
+
},
|
| 630 |
+
{
|
| 631 |
+
"device_id": "DEV0158",
|
| 632 |
+
"fingerprint_hash": "73ffa03d52bc3863276f3e295126e6cce5ee0ab35c13cb0406dac8e3226b4fb8"
|
| 633 |
+
},
|
| 634 |
+
{
|
| 635 |
+
"device_id": "DEV0159",
|
| 636 |
+
"fingerprint_hash": "262d1db466cb3cf4793433f66e35d494bddf2fc59c5b19138a4d21c398a5ff64"
|
| 637 |
+
},
|
| 638 |
+
{
|
| 639 |
+
"device_id": "DEV0160",
|
| 640 |
+
"fingerprint_hash": "03a317cb2a5f02a977952ba1247f9b038efb3dbd3efe86c6f9c48c7dc1cfc9df"
|
| 641 |
+
},
|
| 642 |
+
{
|
| 643 |
+
"device_id": "DEV0161",
|
| 644 |
+
"fingerprint_hash": "e62e5ea09c36d9041b6deee7c60dea3b7d05bd0f4e952244fcc2015da6f61859"
|
| 645 |
+
},
|
| 646 |
+
{
|
| 647 |
+
"device_id": "DEV0162",
|
| 648 |
+
"fingerprint_hash": "63dac30d619826d0b5599ab0d1d9073e0e15181ca13abbc3c31ff1977befb922"
|
| 649 |
+
},
|
| 650 |
+
{
|
| 651 |
+
"device_id": "DEV0163",
|
| 652 |
+
"fingerprint_hash": "edfc9813f8bee36ca7216bb8981bdbb3a374406c2ab58f5351a062dd415016f8"
|
| 653 |
+
},
|
| 654 |
+
{
|
| 655 |
+
"device_id": "DEV0164",
|
| 656 |
+
"fingerprint_hash": "19c390de45b31cbb776a6998c0f7fbd79c5e872c79a957aaa869bc93876f4b18"
|
| 657 |
+
},
|
| 658 |
+
{
|
| 659 |
+
"device_id": "DEV0165",
|
| 660 |
+
"fingerprint_hash": "ba91e9204373aee6955dc387ed84ecc395baf199f0d1ef2ef79ae26c37027e13"
|
| 661 |
+
},
|
| 662 |
+
{
|
| 663 |
+
"device_id": "DEV0166",
|
| 664 |
+
"fingerprint_hash": "7de60c23c00257130dbc2a5e08f298a247136149f0677d16e2961620806c9d37"
|
| 665 |
+
},
|
| 666 |
+
{
|
| 667 |
+
"device_id": "DEV0167",
|
| 668 |
+
"fingerprint_hash": "3d1c715cae8a61bf5d23450f090fbec7f78dfde039932cd367bcb5a77aaf5ca5"
|
| 669 |
+
},
|
| 670 |
+
{
|
| 671 |
+
"device_id": "DEV0168",
|
| 672 |
+
"fingerprint_hash": "fe7e8a3c0f0361b524fb7ca709e30190f80673ccd1062e95e8d36d4c81674430"
|
| 673 |
+
},
|
| 674 |
+
{
|
| 675 |
+
"device_id": "DEV0169",
|
| 676 |
+
"fingerprint_hash": "10ab263deda4fd612565c0afbe90ac77480cae22c3c294d9831f6744903d954f"
|
| 677 |
+
},
|
| 678 |
+
{
|
| 679 |
+
"device_id": "DEV0170",
|
| 680 |
+
"fingerprint_hash": "35be714a8ab083931ed33967d7f5a7c9f5d4d7623ac3c5f467d04344156482c8"
|
| 681 |
+
},
|
| 682 |
+
{
|
| 683 |
+
"device_id": "DEV0171",
|
| 684 |
+
"fingerprint_hash": "5f712ce44385b9425a21f5515cc9b1f2dae60f4966edeaeca67051a615435f35"
|
| 685 |
+
},
|
| 686 |
+
{
|
| 687 |
+
"device_id": "DEV0172",
|
| 688 |
+
"fingerprint_hash": "6e12751bebcde9f031d952f8ba517b33ecbfff0b35d57c268d6c31f91aae0f47"
|
| 689 |
+
},
|
| 690 |
+
{
|
| 691 |
+
"device_id": "DEV0173",
|
| 692 |
+
"fingerprint_hash": "eaeae7b62113013a4caad474c4bdb21625805de361025e403186ead5aa8b73c9"
|
| 693 |
+
},
|
| 694 |
+
{
|
| 695 |
+
"device_id": "DEV0174",
|
| 696 |
+
"fingerprint_hash": "edcbdab7ffa6a2ef975273b8697b64f6a31d1cd3be2403dc711dc047038a3f2f"
|
| 697 |
+
},
|
| 698 |
+
{
|
| 699 |
+
"device_id": "DEV0175",
|
| 700 |
+
"fingerprint_hash": "08242d9884fa31e09c1674ac77943077b3de52403cb7ae7d81f54294a02209b4"
|
| 701 |
+
},
|
| 702 |
+
{
|
| 703 |
+
"device_id": "DEV0176",
|
| 704 |
+
"fingerprint_hash": "7427e46e031bd27522540429f46d378b0017ca3a9db0816d4d4fe2a67f1786b2"
|
| 705 |
+
},
|
| 706 |
+
{
|
| 707 |
+
"device_id": "DEV0177",
|
| 708 |
+
"fingerprint_hash": "dfdef0d703d63aa90cb8f0ee363c42f5fc5116dc0f76937b24e6970b1f11a73a"
|
| 709 |
+
},
|
| 710 |
+
{
|
| 711 |
+
"device_id": "DEV0178",
|
| 712 |
+
"fingerprint_hash": "80b43b595727d6537c8dddbff9ef04e7d00314376a03d96b0066c01ccf18460e"
|
| 713 |
+
},
|
| 714 |
+
{
|
| 715 |
+
"device_id": "DEV0179",
|
| 716 |
+
"fingerprint_hash": "d311d35fd114608dd7e6bf5fc398f17451dc46a428cb2c3a8701ceba95e69156"
|
| 717 |
+
},
|
| 718 |
+
{
|
| 719 |
+
"device_id": "DEV0180",
|
| 720 |
+
"fingerprint_hash": "399e8635b6f3069a22005dff8ed4e5f0d80b5814915cd9c1a5749e7014c7029b"
|
| 721 |
+
},
|
| 722 |
+
{
|
| 723 |
+
"device_id": "DEV0181",
|
| 724 |
+
"fingerprint_hash": "fb5f2cf6d6f5746debc8e9c02b6ca4aeb94ae9b649440c27b3ba4e1897d1f49c"
|
| 725 |
+
},
|
| 726 |
+
{
|
| 727 |
+
"device_id": "DEV0182",
|
| 728 |
+
"fingerprint_hash": "acc4bebbdcb38a35a44c119a2fed8169e4b6394c585f28cc3229f28b4966690f"
|
| 729 |
+
},
|
| 730 |
+
{
|
| 731 |
+
"device_id": "DEV0183",
|
| 732 |
+
"fingerprint_hash": "b5136197ca98f8887336e5be7c4d6eed64fb251f1410ce5315cb9b072c4d2aa5"
|
| 733 |
+
},
|
| 734 |
+
{
|
| 735 |
+
"device_id": "DEV0184",
|
| 736 |
+
"fingerprint_hash": "c42374f6dca661d5bcaa89688e58d953f128b70efae7b10b09cc770508d46de5"
|
| 737 |
+
},
|
| 738 |
+
{
|
| 739 |
+
"device_id": "DEV0185",
|
| 740 |
+
"fingerprint_hash": "9e16aef0ecccddbc66e103dff3c2e8b667b26847e0726211e052e02c98e5c9fa"
|
| 741 |
+
},
|
| 742 |
+
{
|
| 743 |
+
"device_id": "DEV0186",
|
| 744 |
+
"fingerprint_hash": "18048cab487bb65348cd3a6efd795d5e063663bd4112cf6922e480a292ed885e"
|
| 745 |
+
},
|
| 746 |
+
{
|
| 747 |
+
"device_id": "DEV0187",
|
| 748 |
+
"fingerprint_hash": "3fb4eaca83182b5a815767762aed1f40aea0ba50602a2155a589dc377910ce0f"
|
| 749 |
+
},
|
| 750 |
+
{
|
| 751 |
+
"device_id": "DEV0188",
|
| 752 |
+
"fingerprint_hash": "55302dccf712906bc73745b0d517f5d77c06710f955b507751e4474278f1d76c"
|
| 753 |
+
},
|
| 754 |
+
{
|
| 755 |
+
"device_id": "DEV0189",
|
| 756 |
+
"fingerprint_hash": "fbc3969a93fa1c94ad256775bc8435fd679ba369e90950566e918be09c3cc9fa"
|
| 757 |
+
},
|
| 758 |
+
{
|
| 759 |
+
"device_id": "DEV0190",
|
| 760 |
+
"fingerprint_hash": "f60d71779db65024275c182d8b022869a8548727647525c56e6fe964c59d6e56"
|
| 761 |
+
},
|
| 762 |
+
{
|
| 763 |
+
"device_id": "DEV0191",
|
| 764 |
+
"fingerprint_hash": "68df74fc2576a202deba87e7cd152ee7dabc1324e2927a8c297faab3d668a1d5"
|
| 765 |
+
},
|
| 766 |
+
{
|
| 767 |
+
"device_id": "DEV0192",
|
| 768 |
+
"fingerprint_hash": "30d2ea953e10c9903ccf9ec5c90fa8177e2637a5c12b9299a00fd35f57c52f82"
|
| 769 |
+
},
|
| 770 |
+
{
|
| 771 |
+
"device_id": "DEV0193",
|
| 772 |
+
"fingerprint_hash": "a68aef0c676939714c2435d3d875614469ed7b4d04c4e090ddffdf377b514581"
|
| 773 |
+
},
|
| 774 |
+
{
|
| 775 |
+
"device_id": "DEV0194",
|
| 776 |
+
"fingerprint_hash": "155549f7554f1c87cb90ba6521ff6469704d5abd37264cbc7f45910bd19aea4c"
|
| 777 |
+
},
|
| 778 |
+
{
|
| 779 |
+
"device_id": "DEV0195",
|
| 780 |
+
"fingerprint_hash": "8a465d34184ce268b7944c823086408a3b90d264e74fbc1aa81b2c09a3bea06a"
|
| 781 |
+
},
|
| 782 |
+
{
|
| 783 |
+
"device_id": "DEV0196",
|
| 784 |
+
"fingerprint_hash": "fde7ddc0dc3e9846613438b51af0a9969d34fe11be1ef3b4f83004ca30bcf570"
|
| 785 |
+
},
|
| 786 |
+
{
|
| 787 |
+
"device_id": "DEV0197",
|
| 788 |
+
"fingerprint_hash": "3bf43de90d07f3b736ed8f19ea917cc07d553a4e03cdbcc213ea50e00d40c5ce"
|
| 789 |
+
},
|
| 790 |
+
{
|
| 791 |
+
"device_id": "DEV0198",
|
| 792 |
+
"fingerprint_hash": "196717070ceec0f3fb164befeefb465237be2621be068096a1765b6abdb32794"
|
| 793 |
+
},
|
| 794 |
+
{
|
| 795 |
+
"device_id": "DEV0199",
|
| 796 |
+
"fingerprint_hash": "470b7e115da1bc634a8619f86a6fc3c048462f1017060a8a2c6c2e53958b3bb3"
|
| 797 |
+
},
|
| 798 |
+
{
|
| 799 |
+
"device_id": "DEV0200",
|
| 800 |
+
"fingerprint_hash": "1aed95af8648d31779ae39ac199fdd1dd8c4165402a688106e4f3d488d10371b"
|
| 801 |
+
},
|
| 802 |
+
{
|
| 803 |
+
"device_id": "DEV0201",
|
| 804 |
+
"fingerprint_hash": "3fd06f0484a53da6310369cf67e632163c7774a7ea96805b1a81978a98ba8add"
|
| 805 |
+
},
|
| 806 |
+
{
|
| 807 |
+
"device_id": "DEV0202",
|
| 808 |
+
"fingerprint_hash": "9916255472143fa1306823d2297bfa345acf80f2a8a3f50ca84428549292ddfb"
|
| 809 |
+
},
|
| 810 |
+
{
|
| 811 |
+
"device_id": "DEV0203",
|
| 812 |
+
"fingerprint_hash": "3bb8027a989fd42a5f2bd3d970e6a99eb37c3783c7559491110a06f303ec184a"
|
| 813 |
+
},
|
| 814 |
+
{
|
| 815 |
+
"device_id": "DEV0204",
|
| 816 |
+
"fingerprint_hash": "0166621dddb3d2de86c769bafa3819c450986a7e0f53d1f2f1fc4a07186a0b9e"
|
| 817 |
+
},
|
| 818 |
+
{
|
| 819 |
+
"device_id": "DEV0205",
|
| 820 |
+
"fingerprint_hash": "812934ee92c13fc065e6b96fd019160a13b544c51479e1aa0a16e24be4c67e46"
|
| 821 |
+
},
|
| 822 |
+
{
|
| 823 |
+
"device_id": "DEV0206",
|
| 824 |
+
"fingerprint_hash": "63f4690e1222a02e0c9ffdad7c6f9dc0573d52728e4af47e05a733718c497da0"
|
| 825 |
+
},
|
| 826 |
+
{
|
| 827 |
+
"device_id": "DEV0207",
|
| 828 |
+
"fingerprint_hash": "bf4d8a98eb635042702a7b116eb4d54eef1fc80eaffbbb0f7629ffb5d4321c7b"
|
| 829 |
+
},
|
| 830 |
+
{
|
| 831 |
+
"device_id": "DEV0208",
|
| 832 |
+
"fingerprint_hash": "4b3f01fc311c8f07e6b4fb2c872f2caf3b6062ef177c1ab8b53a23965af2ee0f"
|
| 833 |
+
},
|
| 834 |
+
{
|
| 835 |
+
"device_id": "DEV0209",
|
| 836 |
+
"fingerprint_hash": "bbcb3a3f4a3af5c569397bbad60189e5999f7b0caefaa342342238d625efccaa"
|
| 837 |
+
},
|
| 838 |
+
{
|
| 839 |
+
"device_id": "DEV0210",
|
| 840 |
+
"fingerprint_hash": "af497f21beec53d976f1e3ad30874512ad7f7471e4325a6e592eaa78af64ce30"
|
| 841 |
+
},
|
| 842 |
+
{
|
| 843 |
+
"device_id": "DEV0211",
|
| 844 |
+
"fingerprint_hash": "2243cee127dff765b3e230b7c29e7826d4661ac30e348996371e5d51acf4b3c3"
|
| 845 |
+
},
|
| 846 |
+
{
|
| 847 |
+
"device_id": "DEV0212",
|
| 848 |
+
"fingerprint_hash": "79cbd127722cf00c7c76832eb89146f2551ff8dab46a82306bed96d62e4b9eb4"
|
| 849 |
+
},
|
| 850 |
+
{
|
| 851 |
+
"device_id": "DEV0213",
|
| 852 |
+
"fingerprint_hash": "b430c419103350580942a33ab997fa8841de9a072f43a5b61db95bbe79f225ce"
|
| 853 |
+
},
|
| 854 |
+
{
|
| 855 |
+
"device_id": "DEV0214",
|
| 856 |
+
"fingerprint_hash": "a0dfeda412b8f551552fb8869ebc7fa7b56771969aadb4bc2de7265c2a1dc2b6"
|
| 857 |
+
},
|
| 858 |
+
{
|
| 859 |
+
"device_id": "DEV0215",
|
| 860 |
+
"fingerprint_hash": "01e54077f641101fb0dc7ce0fad0674132a16b02f1f5f71ecbc8d54b5589f2c4"
|
| 861 |
+
},
|
| 862 |
+
{
|
| 863 |
+
"device_id": "DEV0216",
|
| 864 |
+
"fingerprint_hash": "3ef25793ccaf095048f58b1364f60a38c1716ebf5c25686d892d4c42b004849e"
|
| 865 |
+
},
|
| 866 |
+
{
|
| 867 |
+
"device_id": "DEV0217",
|
| 868 |
+
"fingerprint_hash": "72dea3fa1aa9f1986ec5bb8e8e595bad2844428f88c8d9ba0d4cad29ca827c21"
|
| 869 |
+
},
|
| 870 |
+
{
|
| 871 |
+
"device_id": "DEV0218",
|
| 872 |
+
"fingerprint_hash": "159e132d8a2c24f930254b0677edb3341d2ee86f167dc0ae06c4f22e815206a8"
|
| 873 |
+
},
|
| 874 |
+
{
|
| 875 |
+
"device_id": "DEV0219",
|
| 876 |
+
"fingerprint_hash": "9457c6d94fb8955bc2c97466f8edb6a7243713bcba553c22bbdb609a0fb89218"
|
| 877 |
+
},
|
| 878 |
+
{
|
| 879 |
+
"device_id": "DEV0220",
|
| 880 |
+
"fingerprint_hash": "434d62d11cdbc2344233496218fa868b7d7bf9a2bda9fbd47a75b669f6d52b5f"
|
| 881 |
+
},
|
| 882 |
+
{
|
| 883 |
+
"device_id": "DEV0221",
|
| 884 |
+
"fingerprint_hash": "689569376bbbb0cbcd2b05ff33dde57b7a4d195c1e36d5abd8723dc2044b723b"
|
| 885 |
+
},
|
| 886 |
+
{
|
| 887 |
+
"device_id": "DEV0222",
|
| 888 |
+
"fingerprint_hash": "de233ffba5a87bfe44c9e7073dfa47b99aaf5d13e478db692e4829d0e3218609"
|
| 889 |
+
},
|
| 890 |
+
{
|
| 891 |
+
"device_id": "DEV0223",
|
| 892 |
+
"fingerprint_hash": "e75e8776b891663a64004274cd0e4f8df70749289d68c1efb8ba08653c13ba49"
|
| 893 |
+
},
|
| 894 |
+
{
|
| 895 |
+
"device_id": "DEV0224",
|
| 896 |
+
"fingerprint_hash": "22c70e03cf0c912d7107d1b2a237d6fdee00d40d7c1855109bd5d046198c61f5"
|
| 897 |
+
},
|
| 898 |
+
{
|
| 899 |
+
"device_id": "DEV0225",
|
| 900 |
+
"fingerprint_hash": "88ad94ba3f7c793aa14b76d04eb7025448db4553394813f9831f167c8db3ba42"
|
| 901 |
+
},
|
| 902 |
+
{
|
| 903 |
+
"device_id": "DEV0226",
|
| 904 |
+
"fingerprint_hash": "5eda154a3084620278b83268e82b447069a7a71a31cbe9b27d1898a325bba394"
|
| 905 |
+
},
|
| 906 |
+
{
|
| 907 |
+
"device_id": "DEV0227",
|
| 908 |
+
"fingerprint_hash": "b2e3117cb302b9b9abc4659776045fe4bf0364f24af83ede1529de9a82c49f36"
|
| 909 |
+
},
|
| 910 |
+
{
|
| 911 |
+
"device_id": "DEV0228",
|
| 912 |
+
"fingerprint_hash": "1a3f2cbe674b27967acd7736658058420ec919821324517c9848e397d615705b"
|
| 913 |
+
},
|
| 914 |
+
{
|
| 915 |
+
"device_id": "DEV0229",
|
| 916 |
+
"fingerprint_hash": "4a9ee2642b4b61b64de554ac270e7e953ab4aff5cb476e07ef2623d0a9828bf9"
|
| 917 |
+
},
|
| 918 |
+
{
|
| 919 |
+
"device_id": "DEV0230",
|
| 920 |
+
"fingerprint_hash": "20edef9b43f6c907111bc698aa619f69318aa2e98adacb25ebeaa653b744dea2"
|
| 921 |
+
},
|
| 922 |
+
{
|
| 923 |
+
"device_id": "DEV0231",
|
| 924 |
+
"fingerprint_hash": "376df9db5dd92f6dbea17173268051ae42842ebca0e932cb67adfd12e6bed64a"
|
| 925 |
+
},
|
| 926 |
+
{
|
| 927 |
+
"device_id": "DEV0232",
|
| 928 |
+
"fingerprint_hash": "79f0c5218b27ca1db5e4476dd262a4cb4f85b208d500ef805d7edbd5820ff45d"
|
| 929 |
+
},
|
| 930 |
+
{
|
| 931 |
+
"device_id": "DEV0233",
|
| 932 |
+
"fingerprint_hash": "e09aa73f5c449d5d8575c72ae27a5e5f0dbafa799fa66fca87782d036a9497c1"
|
| 933 |
+
},
|
| 934 |
+
{
|
| 935 |
+
"device_id": "DEV0234",
|
| 936 |
+
"fingerprint_hash": "7eb3aa19d259892111f9e9b39ff4fd3f5d48e245ec41caf589944e252b63dffc"
|
| 937 |
+
},
|
| 938 |
+
{
|
| 939 |
+
"device_id": "DEV0235",
|
| 940 |
+
"fingerprint_hash": "7218b5c8dd5d350846f511e479d2e56fbcae4e1db85daa3999bf1c1234d205c8"
|
| 941 |
+
},
|
| 942 |
+
{
|
| 943 |
+
"device_id": "DEV0236",
|
| 944 |
+
"fingerprint_hash": "d699a6537aea630a34a686ea16b0d22091d625741115fb72411c5acf5d0ff7a7"
|
| 945 |
+
},
|
| 946 |
+
{
|
| 947 |
+
"device_id": "DEV0237",
|
| 948 |
+
"fingerprint_hash": "0a9852fa27a3bc4038cad803a71f4dbb138e2d24b22d11fbf0315b813b11f989"
|
| 949 |
+
},
|
| 950 |
+
{
|
| 951 |
+
"device_id": "DEV0238",
|
| 952 |
+
"fingerprint_hash": "cf1d3099b6d156a361bc5fee5468d22d32e65e3a73a35bfd1115ed5ff15f439a"
|
| 953 |
+
},
|
| 954 |
+
{
|
| 955 |
+
"device_id": "DEV0239",
|
| 956 |
+
"fingerprint_hash": "3fc2edda05b4805b46664b5c2c7f91646ff8241a3d147fd12f80479cb8e34a3a"
|
| 957 |
+
},
|
| 958 |
+
{
|
| 959 |
+
"device_id": "DEV0240",
|
| 960 |
+
"fingerprint_hash": "e5774e5ee75075147fcd1d974be5a2eb83b824084eac7d861c958558ee6f966d"
|
| 961 |
+
},
|
| 962 |
+
{
|
| 963 |
+
"device_id": "DEV0241",
|
| 964 |
+
"fingerprint_hash": "9803fba0a77ed4b9482e86af5326239b50d98babb7e54b8ab986b661b77af7b4"
|
| 965 |
+
},
|
| 966 |
+
{
|
| 967 |
+
"device_id": "DEV0242",
|
| 968 |
+
"fingerprint_hash": "77c5a3d62c14ce322a51bf61eefd89dd6746baa9c1f0fd8d7e44b2b63e2669aa"
|
| 969 |
+
},
|
| 970 |
+
{
|
| 971 |
+
"device_id": "DEV0243",
|
| 972 |
+
"fingerprint_hash": "f88fe6c35365ace1b3ce78060ad824cf9279f133a932b091bc8cedf61779f46d"
|
| 973 |
+
},
|
| 974 |
+
{
|
| 975 |
+
"device_id": "DEV0244",
|
| 976 |
+
"fingerprint_hash": "a072252dc49a4f06c01539e34951a966be452f1329d2178c82293a887b54f7d6"
|
| 977 |
+
},
|
| 978 |
+
{
|
| 979 |
+
"device_id": "DEV0245",
|
| 980 |
+
"fingerprint_hash": "9e8a0c8abce51ce29ebc5cfd6fc68fc6037746d687e82a4bab7c0bd9aaaca636"
|
| 981 |
+
},
|
| 982 |
+
{
|
| 983 |
+
"device_id": "DEV0246",
|
| 984 |
+
"fingerprint_hash": "eeaf23bc17309e86206849c70e2038796fb56433b97ae8ac139a30a4d062caea"
|
| 985 |
+
},
|
| 986 |
+
{
|
| 987 |
+
"device_id": "DEV0247",
|
| 988 |
+
"fingerprint_hash": "0130eb1f30cb0a6fa78294d19e7fc7cde8f6f735cf1a5c88a385058c5f9c5bc1"
|
| 989 |
+
},
|
| 990 |
+
{
|
| 991 |
+
"device_id": "DEV0248",
|
| 992 |
+
"fingerprint_hash": "e08ab35cb947b9eaecab0b3314084b554275838956e394d6b86d91a912767247"
|
| 993 |
+
},
|
| 994 |
+
{
|
| 995 |
+
"device_id": "DEV0249",
|
| 996 |
+
"fingerprint_hash": "361f3024cae380e9b8061edf1d5d678087f72d69e0fe4d92264a7da854679194"
|
| 997 |
+
},
|
| 998 |
+
{
|
| 999 |
+
"device_id": "DEV0250",
|
| 1000 |
+
"fingerprint_hash": "940e9aed9510c520450126fe9ffc9162fa0f90521d34ae6c82308aca5a3ca28c"
|
| 1001 |
+
},
|
| 1002 |
+
{
|
| 1003 |
+
"device_id": "DEV0251",
|
| 1004 |
+
"fingerprint_hash": "45e76743c14d60d6624a559b24050c2a0da57af5e0dcb778c0ac9ec937158fdc"
|
| 1005 |
+
},
|
| 1006 |
+
{
|
| 1007 |
+
"device_id": "DEV0252",
|
| 1008 |
+
"fingerprint_hash": "b7cb19f546039f6018c5ab57d24c9abc0f6b38beff1d7b8f8e5f7e2388fe4d51"
|
| 1009 |
+
},
|
| 1010 |
+
{
|
| 1011 |
+
"device_id": "DEV0253",
|
| 1012 |
+
"fingerprint_hash": "2011dc6f9723fe4d62a6a83ee2fbb66bff88d69eb50d78df00b5332f47a53b46"
|
| 1013 |
+
},
|
| 1014 |
+
{
|
| 1015 |
+
"device_id": "DEV0254",
|
| 1016 |
+
"fingerprint_hash": "2bc0e4b1573a39910b25c224adf78f5a208b2c9e9ee0c69581984fa979ed8983"
|
| 1017 |
+
},
|
| 1018 |
+
{
|
| 1019 |
+
"device_id": "DEV0255",
|
| 1020 |
+
"fingerprint_hash": "e6bcc7a1ff1504ea43bf0077c22a4bf298f885aac584b064bda4556c2c653db5"
|
| 1021 |
+
},
|
| 1022 |
+
{
|
| 1023 |
+
"device_id": "DEV0256",
|
| 1024 |
+
"fingerprint_hash": "35a434f8fb1e4eda0eba55b969fe9a8c21a62cab301bfaf4f22774812fdd66fc"
|
| 1025 |
+
},
|
| 1026 |
+
{
|
| 1027 |
+
"device_id": "DEV0257",
|
| 1028 |
+
"fingerprint_hash": "a35e497c810174287ddde3c1fa0395d10e4d8c07af3465900ddcec6a28ff4e7d"
|
| 1029 |
+
},
|
| 1030 |
+
{
|
| 1031 |
+
"device_id": "DEV0258",
|
| 1032 |
+
"fingerprint_hash": "e485c5c5989595c09cf28550e0025728090528e05daea7959853a9a58f8ecc99"
|
| 1033 |
+
},
|
| 1034 |
+
{
|
| 1035 |
+
"device_id": "DEV0259",
|
| 1036 |
+
"fingerprint_hash": "97508201bc0fdc707cf88932607f02a86f68af7cd6e379bfbacdc72741e6fb06"
|
| 1037 |
+
},
|
| 1038 |
+
{
|
| 1039 |
+
"device_id": "DEV0260",
|
| 1040 |
+
"fingerprint_hash": "fe727d3d58ebbd52fe18ce7d7a511cbab09394a418fd07ac5159f729934d603d"
|
| 1041 |
+
},
|
| 1042 |
+
{
|
| 1043 |
+
"device_id": "DEV0261",
|
| 1044 |
+
"fingerprint_hash": "aef218c61649a7254d669ca7252acc60859fca2c572b677f675751f55afca419"
|
| 1045 |
+
},
|
| 1046 |
+
{
|
| 1047 |
+
"device_id": "DEV0262",
|
| 1048 |
+
"fingerprint_hash": "40aec91990555870f21788152adf5f62df4862570806062b98472cf2dff565ee"
|
| 1049 |
+
},
|
| 1050 |
+
{
|
| 1051 |
+
"device_id": "DEV0263",
|
| 1052 |
+
"fingerprint_hash": "94596f74aa2c8f4fea21917a2a1602be7a40ad5d0a81157b907ee5243b84f89a"
|
| 1053 |
+
},
|
| 1054 |
+
{
|
| 1055 |
+
"device_id": "DEV0264",
|
| 1056 |
+
"fingerprint_hash": "dd6575da4c3c0d996b18d3a249e3ec4fb6c5ca74e86e7ac91a8c627e3ba36314"
|
| 1057 |
+
},
|
| 1058 |
+
{
|
| 1059 |
+
"device_id": "DEV0265",
|
| 1060 |
+
"fingerprint_hash": "b14c03095bc14d5047ee9288f355d423144797b60b9a5a25e49a545923daace2"
|
| 1061 |
+
},
|
| 1062 |
+
{
|
| 1063 |
+
"device_id": "DEV0266",
|
| 1064 |
+
"fingerprint_hash": "c345b8bc61b558e4d721951dda3ebe120ce794894f369d58a21d3aac8ee801de"
|
| 1065 |
+
},
|
| 1066 |
+
{
|
| 1067 |
+
"device_id": "DEV0267",
|
| 1068 |
+
"fingerprint_hash": "8f079c8bde59314a5abf4b4204f47763111a0201aa45b9844bdf934f1214f9a4"
|
| 1069 |
+
},
|
| 1070 |
+
{
|
| 1071 |
+
"device_id": "DEV0268",
|
| 1072 |
+
"fingerprint_hash": "818f7ed297af84e3fb21d82bf2258e62dcaf8cf4595b6878c9df8de6cf185cd6"
|
| 1073 |
+
},
|
| 1074 |
+
{
|
| 1075 |
+
"device_id": "DEV0269",
|
| 1076 |
+
"fingerprint_hash": "b212ef972f70d9a305f8db4f8194f1895cb1ae8f9757887341c1bf635e32c755"
|
| 1077 |
+
},
|
| 1078 |
+
{
|
| 1079 |
+
"device_id": "DEV0270",
|
| 1080 |
+
"fingerprint_hash": "4a1e9beedf0802026ca15acefdbffa48f6c1c1b2a1d4f5a661d31645f9b3170f"
|
| 1081 |
+
},
|
| 1082 |
+
{
|
| 1083 |
+
"device_id": "DEV0271",
|
| 1084 |
+
"fingerprint_hash": "fa04e38b61bde2015f45df85cab4ef524d95b97e249d9d1d71b33923b0511c2f"
|
| 1085 |
+
},
|
| 1086 |
+
{
|
| 1087 |
+
"device_id": "DEV0272",
|
| 1088 |
+
"fingerprint_hash": "308d0ad5a47f101fca6824f75d4290c9a0605f3433b597466f110607ef85c1c0"
|
| 1089 |
+
},
|
| 1090 |
+
{
|
| 1091 |
+
"device_id": "DEV0273",
|
| 1092 |
+
"fingerprint_hash": "eb9ad067c8fb3774058140f2cce762de45c2369742df9175e5f69cdfc34ad762"
|
| 1093 |
+
},
|
| 1094 |
+
{
|
| 1095 |
+
"device_id": "DEV0274",
|
| 1096 |
+
"fingerprint_hash": "0411946c28629b5c574897d0e741147beb79406a17799172fb8494d2deff0d08"
|
| 1097 |
+
},
|
| 1098 |
+
{
|
| 1099 |
+
"device_id": "DEV0275",
|
| 1100 |
+
"fingerprint_hash": "f1d60cccec882aa844bc4adf031e0128b831f6f3dda5274ffd46160497fe7869"
|
| 1101 |
+
},
|
| 1102 |
+
{
|
| 1103 |
+
"device_id": "DEV0276",
|
| 1104 |
+
"fingerprint_hash": "56b6e4dba423f7a5dea21a7de3369b1beda058f0ba41970989333cabc8c96447"
|
| 1105 |
+
},
|
| 1106 |
+
{
|
| 1107 |
+
"device_id": "DEV0277",
|
| 1108 |
+
"fingerprint_hash": "0ae3d6cdfe244951e0ef6a388bc9c0717f96575255bd85fa4e6a81e8dc08e339"
|
| 1109 |
+
},
|
| 1110 |
+
{
|
| 1111 |
+
"device_id": "DEV0278",
|
| 1112 |
+
"fingerprint_hash": "05f9ec5f1fc4f2627d06046e46e5e2f4339a2b736914cd1ea8bc6f7d9537b6cd"
|
| 1113 |
+
},
|
| 1114 |
+
{
|
| 1115 |
+
"device_id": "DEV0279",
|
| 1116 |
+
"fingerprint_hash": "a02c75ae0aa9bf25d1eff0f6b4a42d166fe0dd51dd85b9656d052717c128ee1e"
|
| 1117 |
+
},
|
| 1118 |
+
{
|
| 1119 |
+
"device_id": "DEV0280",
|
| 1120 |
+
"fingerprint_hash": "ccc25f2c144d3a87db9fb0b0f78beaf568235375b95d2fadd1ba1ce526cb10a1"
|
| 1121 |
+
},
|
| 1122 |
+
{
|
| 1123 |
+
"device_id": "DEV0281",
|
| 1124 |
+
"fingerprint_hash": "f1eae9eb9074a96fbc1d9a85efcd2a62d8c6b26edd81bdd2a047a63612debf56"
|
| 1125 |
+
},
|
| 1126 |
+
{
|
| 1127 |
+
"device_id": "DEV0282",
|
| 1128 |
+
"fingerprint_hash": "0dba34249bf3758faf43772e874e4f570ec74b94a9ce0e08a70afb0b4704ba19"
|
| 1129 |
+
},
|
| 1130 |
+
{
|
| 1131 |
+
"device_id": "DEV0283",
|
| 1132 |
+
"fingerprint_hash": "799b9c978d16417fa96ed40ed5672bcee1baf092decc7d64f7dde926ec6673cd"
|
| 1133 |
+
},
|
| 1134 |
+
{
|
| 1135 |
+
"device_id": "DEV0284",
|
| 1136 |
+
"fingerprint_hash": "4fa0f0e227bcef0b5a418b27dc03cea0fde91aeca44639879e57c849951d3a5c"
|
| 1137 |
+
},
|
| 1138 |
+
{
|
| 1139 |
+
"device_id": "DEV0285",
|
| 1140 |
+
"fingerprint_hash": "17a16524c4c8db6ddca0c95f8484ecd560b1fa917d45533775f0df9643bc41eb"
|
| 1141 |
+
},
|
| 1142 |
+
{
|
| 1143 |
+
"device_id": "DEV0286",
|
| 1144 |
+
"fingerprint_hash": "f255c655bc371ccc72c60855f7dd2eecb3b4d049dd0b7580a760aa1e6917ebca"
|
| 1145 |
+
},
|
| 1146 |
+
{
|
| 1147 |
+
"device_id": "DEV0287",
|
| 1148 |
+
"fingerprint_hash": "42cb6adcc33bd094f6fb7bc27215cfacb12e2da9772e28d778b6d3b213ea4c44"
|
| 1149 |
+
},
|
| 1150 |
+
{
|
| 1151 |
+
"device_id": "DEV0288",
|
| 1152 |
+
"fingerprint_hash": "9884c9f3d31c4520bf51b7b6a86f5295055c48fd7e9dff4c2de429ad19c0c0f3"
|
| 1153 |
+
},
|
| 1154 |
+
{
|
| 1155 |
+
"device_id": "DEV0289",
|
| 1156 |
+
"fingerprint_hash": "63e04749b3acdd7d8b8ee6719e0e55a1200415bdd73d9afbdb217ed12f2d2dfa"
|
| 1157 |
+
},
|
| 1158 |
+
{
|
| 1159 |
+
"device_id": "DEV0290",
|
| 1160 |
+
"fingerprint_hash": "a5cb7af29ebb327d63fc53c95947b68d3b2fde3f42c48efe30f915b2f06f7330"
|
| 1161 |
+
},
|
| 1162 |
+
{
|
| 1163 |
+
"device_id": "DEV0291",
|
| 1164 |
+
"fingerprint_hash": "53db0e6254bfc42930a79acb60f131c7c335fd3ba6410e9e65bfc0767c4e1bb3"
|
| 1165 |
+
},
|
| 1166 |
+
{
|
| 1167 |
+
"device_id": "DEV0292",
|
| 1168 |
+
"fingerprint_hash": "196ce9eff0771823b670fdffd87a86a824180b4c4689e34652647c89ad2b6cd7"
|
| 1169 |
+
},
|
| 1170 |
+
{
|
| 1171 |
+
"device_id": "DEV0293",
|
| 1172 |
+
"fingerprint_hash": "75b4965fa965e6fe282fa84ad83153dfa39c511a927a8c1e1245356644340738"
|
| 1173 |
+
},
|
| 1174 |
+
{
|
| 1175 |
+
"device_id": "DEV0294",
|
| 1176 |
+
"fingerprint_hash": "d7cfd5bcddcc70d778aaf1569f13de81b2fdf861aaf5c8131d2fdce849514c3a"
|
| 1177 |
+
},
|
| 1178 |
+
{
|
| 1179 |
+
"device_id": "DEV0295",
|
| 1180 |
+
"fingerprint_hash": "226a74a548e1b68e061040bd4a15bc18de7200143f53b8411b8a77c02ce2c3cf"
|
| 1181 |
+
},
|
| 1182 |
+
{
|
| 1183 |
+
"device_id": "DEV0296",
|
| 1184 |
+
"fingerprint_hash": "96a97763395eecbfed4d35259f23b8445b5d880bb05e1c52607809102a6a7e8d"
|
| 1185 |
+
},
|
| 1186 |
+
{
|
| 1187 |
+
"device_id": "DEV0297",
|
| 1188 |
+
"fingerprint_hash": "4f94fdc30fb473d365c4f5c22325eba3ef4a3f1124b250d7be5d424f058a9542"
|
| 1189 |
+
},
|
| 1190 |
+
{
|
| 1191 |
+
"device_id": "DEV0298",
|
| 1192 |
+
"fingerprint_hash": "e0ead05768534c144dcb02e403ac009221fa218d46e9879aee2eda58104e6c5a"
|
| 1193 |
+
},
|
| 1194 |
+
{
|
| 1195 |
+
"device_id": "DEV0299",
|
| 1196 |
+
"fingerprint_hash": "7afd340e37cdae754441b2957375828bf78f49e6e1da9386d2ccead93664aa60"
|
| 1197 |
+
},
|
| 1198 |
+
{
|
| 1199 |
+
"device_id": "DEV0300",
|
| 1200 |
+
"fingerprint_hash": "478fa1e0bd46c71f36a41ea86aa124df311596972c889c89f4d6a64361460184"
|
| 1201 |
+
},
|
| 1202 |
+
{
|
| 1203 |
+
"device_id": "DEV0301",
|
| 1204 |
+
"fingerprint_hash": "ae3b48a177e6ea5825410f53698a05f4f125766e2dc0e2b096c6be4581239757"
|
| 1205 |
+
},
|
| 1206 |
+
{
|
| 1207 |
+
"device_id": "DEV0302",
|
| 1208 |
+
"fingerprint_hash": "530353fc4ca2e864505c2d8b41be50f0178117462afc99680b02a4f042b0ceba"
|
| 1209 |
+
},
|
| 1210 |
+
{
|
| 1211 |
+
"device_id": "DEV0303",
|
| 1212 |
+
"fingerprint_hash": "b94dc53c5f996b73a06d1d03384e77401b244bb186b8f4e7290342bb12b1e1bd"
|
| 1213 |
+
},
|
| 1214 |
+
{
|
| 1215 |
+
"device_id": "DEV0304",
|
| 1216 |
+
"fingerprint_hash": "097cd26a06a24db9a55a478fa2af082a469dcf07783b5d57efea758630750678"
|
| 1217 |
+
},
|
| 1218 |
+
{
|
| 1219 |
+
"device_id": "DEV0305",
|
| 1220 |
+
"fingerprint_hash": "f89ed8cea01b6a710988c5c8edb535e3c28e8bd3b34882af0cc21517c7706826"
|
| 1221 |
+
},
|
| 1222 |
+
{
|
| 1223 |
+
"device_id": "DEV0306",
|
| 1224 |
+
"fingerprint_hash": "342d8ebb34825e643d0009e899d584cba16905c113c27c384fe1650320e18877"
|
| 1225 |
+
},
|
| 1226 |
+
{
|
| 1227 |
+
"device_id": "DEV0307",
|
| 1228 |
+
"fingerprint_hash": "14ce23b877155a18113d840441bbde334ff214a75da160d49b5aae672878197a"
|
| 1229 |
+
},
|
| 1230 |
+
{
|
| 1231 |
+
"device_id": "DEV0308",
|
| 1232 |
+
"fingerprint_hash": "ef852f564bd35196718604f93edce4dfcd5f10b1dd00c0f9bce53a1bc77a5d70"
|
| 1233 |
+
},
|
| 1234 |
+
{
|
| 1235 |
+
"device_id": "DEV0309",
|
| 1236 |
+
"fingerprint_hash": "75ef62bad0ba4e4a8596d71bc28cbe9c4cbfc2e81aec002c6fc6a00d83232535"
|
| 1237 |
+
},
|
| 1238 |
+
{
|
| 1239 |
+
"device_id": "DEV0310",
|
| 1240 |
+
"fingerprint_hash": "27d91cab279adf59df1ba2717fa38058ee7641e26ada3ec7bb1c1293b57f38c3"
|
| 1241 |
+
},
|
| 1242 |
+
{
|
| 1243 |
+
"device_id": "DEV0311",
|
| 1244 |
+
"fingerprint_hash": "64ee79d9ea63b60c6c137a1ef834c6e7c4081893be4673cddc3bf5744c150528"
|
| 1245 |
+
},
|
| 1246 |
+
{
|
| 1247 |
+
"device_id": "DEV0312",
|
| 1248 |
+
"fingerprint_hash": "b6dcdf54f6e7dae07baa4dcf061f0d143438a85821e6c1a7c762f5ddef76b443"
|
| 1249 |
+
},
|
| 1250 |
+
{
|
| 1251 |
+
"device_id": "DEV0313",
|
| 1252 |
+
"fingerprint_hash": "73c6a13bd97ad4ddb142e05b3684222d3aa3d3ea492ac98d7a43a3d8de8dec21"
|
| 1253 |
+
},
|
| 1254 |
+
{
|
| 1255 |
+
"device_id": "DEV0314",
|
| 1256 |
+
"fingerprint_hash": "5593c852f7a6a271ed567b69f7977d1242ef28e54c315e443aa5ff73d9488946"
|
| 1257 |
+
},
|
| 1258 |
+
{
|
| 1259 |
+
"device_id": "DEV0315",
|
| 1260 |
+
"fingerprint_hash": "5482861ca7d115e8f2d8d52c63bb5bf354aa99622397c3edcff47df6968a61a9"
|
| 1261 |
+
},
|
| 1262 |
+
{
|
| 1263 |
+
"device_id": "DEV0316",
|
| 1264 |
+
"fingerprint_hash": "44495d2b8c99968fca1d0b42439a9db2ec74eb38d2562b070929ac6832b9c5ac"
|
| 1265 |
+
},
|
| 1266 |
+
{
|
| 1267 |
+
"device_id": "DEV0317",
|
| 1268 |
+
"fingerprint_hash": "6610a743bffff348da753cb730f657601a76f1615e1b326f24d6c41ff3764284"
|
| 1269 |
+
},
|
| 1270 |
+
{
|
| 1271 |
+
"device_id": "DEV0318",
|
| 1272 |
+
"fingerprint_hash": "7ddacc5115a19ed685f78416a488de531c1a31d25d5af726e73a1bc48888720a"
|
| 1273 |
+
},
|
| 1274 |
+
{
|
| 1275 |
+
"device_id": "DEV0319",
|
| 1276 |
+
"fingerprint_hash": "2075803ddee657b4e40349bbface85582ea4e196a6a74318edde22ae1589f971"
|
| 1277 |
+
},
|
| 1278 |
+
{
|
| 1279 |
+
"device_id": "DEV0320",
|
| 1280 |
+
"fingerprint_hash": "028383b21779f887b4485b6d12636a0f85c9702ebc751a092915ce71aa0d6ace"
|
| 1281 |
+
},
|
| 1282 |
+
{
|
| 1283 |
+
"device_id": "DEV0321",
|
| 1284 |
+
"fingerprint_hash": "19c98d16968688b36b2ba0414116092d1b934428165b5c03eef93c497c1eb253"
|
| 1285 |
+
},
|
| 1286 |
+
{
|
| 1287 |
+
"device_id": "DEV0322",
|
| 1288 |
+
"fingerprint_hash": "3baa622d9b536f0c8535c27b004a998cbfa43d5e084b030edd0ccf61d6324367"
|
| 1289 |
+
},
|
| 1290 |
+
{
|
| 1291 |
+
"device_id": "DEV0323",
|
| 1292 |
+
"fingerprint_hash": "1b957e3460a9c0b0b16976409b9899773d55316c876a4bfd54f94a83508b0c6a"
|
| 1293 |
+
},
|
| 1294 |
+
{
|
| 1295 |
+
"device_id": "DEV0324",
|
| 1296 |
+
"fingerprint_hash": "caf6aecc638f095a10c54ba7caec5ce0983d6f2807b9cbb33c0dd39631bbbfe4"
|
| 1297 |
+
},
|
| 1298 |
+
{
|
| 1299 |
+
"device_id": "DEV0325",
|
| 1300 |
+
"fingerprint_hash": "5afb7482e00a7ccc0115e20764dfe23888c834603f16e10c7995e1982b03297a"
|
| 1301 |
+
},
|
| 1302 |
+
{
|
| 1303 |
+
"device_id": "DEV0326",
|
| 1304 |
+
"fingerprint_hash": "1e0c6d91bfd58cf58a033a4b496f07ddc43a2485db53c97f53da65dacd38da7e"
|
| 1305 |
+
},
|
| 1306 |
+
{
|
| 1307 |
+
"device_id": "DEV0327",
|
| 1308 |
+
"fingerprint_hash": "155c3e55d9379fd59e4b8036799da146f8da9f5d959b86a2f597a081e7f99e5b"
|
| 1309 |
+
},
|
| 1310 |
+
{
|
| 1311 |
+
"device_id": "DEV0328",
|
| 1312 |
+
"fingerprint_hash": "963976890db37138d5c74a2010d971f7046a6c6ec4bd83e8e283196a317d13a0"
|
| 1313 |
+
},
|
| 1314 |
+
{
|
| 1315 |
+
"device_id": "DEV0329",
|
| 1316 |
+
"fingerprint_hash": "88c2e53f1ac8d07c4a6d84b17fe40c14cf01d3170fe352d11f35d2715c1e38d6"
|
| 1317 |
+
},
|
| 1318 |
+
{
|
| 1319 |
+
"device_id": "DEV0330",
|
| 1320 |
+
"fingerprint_hash": "4104f7c61aed1b5485f9a790d48f9f744f247d611e2a97726c70c59e71412c40"
|
| 1321 |
+
},
|
| 1322 |
+
{
|
| 1323 |
+
"device_id": "DEV0331",
|
| 1324 |
+
"fingerprint_hash": "3750f10aa2183a663d5bc0dc604a8c7957160f24f6cb759ed3dc119ed76c2ded"
|
| 1325 |
+
},
|
| 1326 |
+
{
|
| 1327 |
+
"device_id": "DEV0332",
|
| 1328 |
+
"fingerprint_hash": "c0287eec8dc85a43611e5eab33179dd0398c8f574c9808a2aca1c623ba730678"
|
| 1329 |
+
},
|
| 1330 |
+
{
|
| 1331 |
+
"device_id": "DEV0333",
|
| 1332 |
+
"fingerprint_hash": "8edcdd8c4b2b95f12224527ae453deda559c28d6bc4bbe3647779be590358f81"
|
| 1333 |
+
},
|
| 1334 |
+
{
|
| 1335 |
+
"device_id": "DEV0334",
|
| 1336 |
+
"fingerprint_hash": "1eb39e1659e45b94fb5edfdb90a251373ffb9cac81a92342e6d19c981beda9d6"
|
| 1337 |
+
},
|
| 1338 |
+
{
|
| 1339 |
+
"device_id": "DEV0335",
|
| 1340 |
+
"fingerprint_hash": "543b663a97bdf6de9c0073710ccb88c24633868e19568f0d5b00c1fb651d5302"
|
| 1341 |
+
},
|
| 1342 |
+
{
|
| 1343 |
+
"device_id": "DEV0336",
|
| 1344 |
+
"fingerprint_hash": "9109c0740248b973f32acb636cb0ec6945005a430ec648f1e95d134914934ce6"
|
| 1345 |
+
},
|
| 1346 |
+
{
|
| 1347 |
+
"device_id": "DEV0337",
|
| 1348 |
+
"fingerprint_hash": "43d63e5a4fd6b18db87da014f647792e182fd842f559cf3e8354363a308c18c3"
|
| 1349 |
+
},
|
| 1350 |
+
{
|
| 1351 |
+
"device_id": "DEV0338",
|
| 1352 |
+
"fingerprint_hash": "f204f3a2e9ecf217124ab56cce15a342946f9a6e3f9ddcfd84fa4dfbbc7c7973"
|
| 1353 |
+
},
|
| 1354 |
+
{
|
| 1355 |
+
"device_id": "DEV0339",
|
| 1356 |
+
"fingerprint_hash": "3e31c4e8b0041b6ea34b3e7617c5a015ac2be9c1a4fab3d318bf419a038e1f9c"
|
| 1357 |
+
},
|
| 1358 |
+
{
|
| 1359 |
+
"device_id": "DEV0340",
|
| 1360 |
+
"fingerprint_hash": "94e61c793b36386518cb7356fe45f9c9b7289d5b146758a0ff7bb2dba5b6b7d2"
|
| 1361 |
+
},
|
| 1362 |
+
{
|
| 1363 |
+
"device_id": "DEV0341",
|
| 1364 |
+
"fingerprint_hash": "43a3a440fe26b7a6e51745b8d7f769b4ed1ca2e93db963386002553adf6b1404"
|
| 1365 |
+
},
|
| 1366 |
+
{
|
| 1367 |
+
"device_id": "DEV0342",
|
| 1368 |
+
"fingerprint_hash": "84902f9d90d5def0a07bb72b4dfaf382ce3febd20ab64afdf36ec77a7ad4fe2f"
|
| 1369 |
+
},
|
| 1370 |
+
{
|
| 1371 |
+
"device_id": "DEV0343",
|
| 1372 |
+
"fingerprint_hash": "aa98a6ceff0130f6b05f87ee4804e9fcf4d6bb66973cede29e53da669094e929"
|
| 1373 |
+
},
|
| 1374 |
+
{
|
| 1375 |
+
"device_id": "DEV0344",
|
| 1376 |
+
"fingerprint_hash": "2b71471008456587b4f61190450ae6e158e1c0cec8dc3da656624c8a66e34321"
|
| 1377 |
+
},
|
| 1378 |
+
{
|
| 1379 |
+
"device_id": "DEV0345",
|
| 1380 |
+
"fingerprint_hash": "78b42c90293a0b12c938260e5ff8fc4ffdfcd6ed12d8ef73f2454265cd23374a"
|
| 1381 |
+
},
|
| 1382 |
+
{
|
| 1383 |
+
"device_id": "DEV0346",
|
| 1384 |
+
"fingerprint_hash": "fc6fc908f8756c581a80b56f98724f82b59beb5ec8a2258557c76a84d35ff415"
|
| 1385 |
+
},
|
| 1386 |
+
{
|
| 1387 |
+
"device_id": "DEV0347",
|
| 1388 |
+
"fingerprint_hash": "4a458da7e90ff787366e0b9aa81ed3cca1e0706320a9e8067318e5636afb8483"
|
| 1389 |
+
},
|
| 1390 |
+
{
|
| 1391 |
+
"device_id": "DEV0348",
|
| 1392 |
+
"fingerprint_hash": "c4cb77dbe60964f26481b11b6d2ff21f1a7cb547ea2ed4eb0f76296cff6c06a8"
|
| 1393 |
+
},
|
| 1394 |
+
{
|
| 1395 |
+
"device_id": "DEV0349",
|
| 1396 |
+
"fingerprint_hash": "e2f8acc7dfafdd1156eb71a5fa39604cf45239acf998eefed3f80c97691f51aa"
|
| 1397 |
+
},
|
| 1398 |
+
{
|
| 1399 |
+
"device_id": "DEV0350",
|
| 1400 |
+
"fingerprint_hash": "5450264019804e6b8ad7817ebb005336cdd1dc8579328461bc4c31ee71cbda0c"
|
| 1401 |
+
},
|
| 1402 |
+
{
|
| 1403 |
+
"device_id": "DEV0351",
|
| 1404 |
+
"fingerprint_hash": "f4e0e8bb056c2357822015c06b3e578f46fe71fd21300b008ab75910359977f9"
|
| 1405 |
+
},
|
| 1406 |
+
{
|
| 1407 |
+
"device_id": "DEV0352",
|
| 1408 |
+
"fingerprint_hash": "40d5cb885d8096b28dbcf5663b4653f6cda18d778ccdcc2249be3ff8ad80e774"
|
| 1409 |
+
},
|
| 1410 |
+
{
|
| 1411 |
+
"device_id": "DEV0353",
|
| 1412 |
+
"fingerprint_hash": "d2872fead2dee3cfbb27636b8ff43a5d680cf79b45c8a86ba9f29ed42d3392f5"
|
| 1413 |
+
},
|
| 1414 |
+
{
|
| 1415 |
+
"device_id": "DEV0354",
|
| 1416 |
+
"fingerprint_hash": "7fa0626b8a6cd632715ea08cbdf7219b87180ae2b0aa5801e7463fa8a357264b"
|
| 1417 |
+
},
|
| 1418 |
+
{
|
| 1419 |
+
"device_id": "DEV0355",
|
| 1420 |
+
"fingerprint_hash": "a67a03b4a7448547ecc7c80f351da5c33ab2579b89a18dd2edf087693bb07660"
|
| 1421 |
+
},
|
| 1422 |
+
{
|
| 1423 |
+
"device_id": "DEV0356",
|
| 1424 |
+
"fingerprint_hash": "2339f6d92bdc987ce2c6b5c8227d45e955f3ff4b432af62a93f523581fadb5b4"
|
| 1425 |
+
},
|
| 1426 |
+
{
|
| 1427 |
+
"device_id": "DEV0357",
|
| 1428 |
+
"fingerprint_hash": "bff83bc52c1e1e2bc655326ba138a45d2938589c687b6e0477ffbd34648348ae"
|
| 1429 |
+
},
|
| 1430 |
+
{
|
| 1431 |
+
"device_id": "DEV0358",
|
| 1432 |
+
"fingerprint_hash": "5845714fbdfb94d51c92cf6cb50ba23d031156e18169bb9a4f587a070daddc3a"
|
| 1433 |
+
},
|
| 1434 |
+
{
|
| 1435 |
+
"device_id": "DEV0359",
|
| 1436 |
+
"fingerprint_hash": "35baa8fbd894f9a68cf3f1b62b1b00fde15af33f5c68f67ae143659ec5791ec8"
|
| 1437 |
+
},
|
| 1438 |
+
{
|
| 1439 |
+
"device_id": "DEV0360",
|
| 1440 |
+
"fingerprint_hash": "4e2c02768131d5c5b5838b6db55d3bd9ddc0baaf38a5d1d39b80cd5d5298b1c6"
|
| 1441 |
+
},
|
| 1442 |
+
{
|
| 1443 |
+
"device_id": "DEV0361",
|
| 1444 |
+
"fingerprint_hash": "7ac2178859e4e6b8e302859df44c3f87124d057cf2356824dffc1b2f1c4f46a0"
|
| 1445 |
+
},
|
| 1446 |
+
{
|
| 1447 |
+
"device_id": "DEV0362",
|
| 1448 |
+
"fingerprint_hash": "7332b2d9887fd9662b3ef0aaba5f91c5e4f92a118f89fe33a22db102b3b064a1"
|
| 1449 |
+
},
|
| 1450 |
+
{
|
| 1451 |
+
"device_id": "DEV0363",
|
| 1452 |
+
"fingerprint_hash": "338b4dac3a52a78e82ed85cb58ed2fa7964028414e6ce59d32cb829f1c642b63"
|
| 1453 |
+
},
|
| 1454 |
+
{
|
| 1455 |
+
"device_id": "DEV0364",
|
| 1456 |
+
"fingerprint_hash": "af9ecf8912bdf2f7d3f5972738bfd7505f4a12fd96be6b51c14b276e711ef73b"
|
| 1457 |
+
},
|
| 1458 |
+
{
|
| 1459 |
+
"device_id": "DEV0365",
|
| 1460 |
+
"fingerprint_hash": "70f63e12b2e021c53fa7344408f82941f8dd75e797997da5f1d45b2c735a1ab2"
|
| 1461 |
+
},
|
| 1462 |
+
{
|
| 1463 |
+
"device_id": "DEV0366",
|
| 1464 |
+
"fingerprint_hash": "7e3414abd8b450355cce3b705aedc419b26e80110536ba090aa4c22807e97f1b"
|
| 1465 |
+
},
|
| 1466 |
+
{
|
| 1467 |
+
"device_id": "DEV0367",
|
| 1468 |
+
"fingerprint_hash": "db98faa388e0f26d2c3ed83ce659b9a9a1913097e87fca0e6bc05798a8e00732"
|
| 1469 |
+
},
|
| 1470 |
+
{
|
| 1471 |
+
"device_id": "DEV0368",
|
| 1472 |
+
"fingerprint_hash": "589ef556ce6deaa39c5736e143c59902e513bafd01dbaac8858a78bb868e3bf1"
|
| 1473 |
+
},
|
| 1474 |
+
{
|
| 1475 |
+
"device_id": "DEV0369",
|
| 1476 |
+
"fingerprint_hash": "c8347ad36369f57975e1ab54654b91b0be097f8f43171fd4b3955af92adfc52a"
|
| 1477 |
+
},
|
| 1478 |
+
{
|
| 1479 |
+
"device_id": "DEV0370",
|
| 1480 |
+
"fingerprint_hash": "3e8717ef1527a4d24e349e35bd0d417368f5f0eed978c059407040681c6d2049"
|
| 1481 |
+
},
|
| 1482 |
+
{
|
| 1483 |
+
"device_id": "DEV0371",
|
| 1484 |
+
"fingerprint_hash": "77af1475dd4f73383fd8b3994f50aee8be397af27e6336ea48d2d710892a4191"
|
| 1485 |
+
},
|
| 1486 |
+
{
|
| 1487 |
+
"device_id": "DEV0372",
|
| 1488 |
+
"fingerprint_hash": "249281fdc14979308cf7f9dfd9e0c0a4d8e645d0662f62c7b45a9862fa872307"
|
| 1489 |
+
},
|
| 1490 |
+
{
|
| 1491 |
+
"device_id": "DEV0373",
|
| 1492 |
+
"fingerprint_hash": "65c5181a99c0005b407171c48cc3f66972194b1e836ad6be9099808e57339cfe"
|
| 1493 |
+
},
|
| 1494 |
+
{
|
| 1495 |
+
"device_id": "DEV0374",
|
| 1496 |
+
"fingerprint_hash": "de67bcdbb80565e48324d8cb0375ce39a5c5321ed69793c2afb50abd92777d1d"
|
| 1497 |
+
},
|
| 1498 |
+
{
|
| 1499 |
+
"device_id": "DEV0375",
|
| 1500 |
+
"fingerprint_hash": "7746acef567ef899529895a1ced139997c755f86eb736a2794da1606be9e4f19"
|
| 1501 |
+
},
|
| 1502 |
+
{
|
| 1503 |
+
"device_id": "DEV0376",
|
| 1504 |
+
"fingerprint_hash": "ca101396c98d27c3a39f8b1eee04cc6be96b633379ee94d47e83ba9c0b2b4b50"
|
| 1505 |
+
},
|
| 1506 |
+
{
|
| 1507 |
+
"device_id": "DEV0377",
|
| 1508 |
+
"fingerprint_hash": "041eb73d9985dade88c032991668490af1423d5b5e7e5fa17527837bd325cb3d"
|
| 1509 |
+
},
|
| 1510 |
+
{
|
| 1511 |
+
"device_id": "DEV0378",
|
| 1512 |
+
"fingerprint_hash": "c4369fe5dbf95cce3a08997f58c30fa7907756719be669419968537de9c25034"
|
| 1513 |
+
},
|
| 1514 |
+
{
|
| 1515 |
+
"device_id": "DEV0379",
|
| 1516 |
+
"fingerprint_hash": "33aa44929db71ba8291c939b6c51714ae6b2fe8a8fbbd70edd0fdaa7f67f950e"
|
| 1517 |
+
},
|
| 1518 |
+
{
|
| 1519 |
+
"device_id": "DEV0380",
|
| 1520 |
+
"fingerprint_hash": "73b65a89e55a261792a5cc2b48a3efee649887dfcf1a5c64816b2d053b43b668"
|
| 1521 |
+
},
|
| 1522 |
+
{
|
| 1523 |
+
"device_id": "DEV0381",
|
| 1524 |
+
"fingerprint_hash": "d4cd3515bc579cd7e2e816214a71771dae33c8a15793fa3423eef304ffc0a390"
|
| 1525 |
+
},
|
| 1526 |
+
{
|
| 1527 |
+
"device_id": "DEV0382",
|
| 1528 |
+
"fingerprint_hash": "591f6f75b2cb13bf674ffec239d8948b291ce59b893594cc0e98c9e6899628e8"
|
| 1529 |
+
},
|
| 1530 |
+
{
|
| 1531 |
+
"device_id": "DEV0383",
|
| 1532 |
+
"fingerprint_hash": "03f4313de40f90ade2782f372440f368f9c324ba7c897716da633a3d6654a01b"
|
| 1533 |
+
},
|
| 1534 |
+
{
|
| 1535 |
+
"device_id": "DEV0384",
|
| 1536 |
+
"fingerprint_hash": "5bade8568d9b9a6a3d05b203c71320c939669d4d4edad8370c9047b6b33a22a3"
|
| 1537 |
+
},
|
| 1538 |
+
{
|
| 1539 |
+
"device_id": "DEV0385",
|
| 1540 |
+
"fingerprint_hash": "de3270a04c5314e5891f4f25580832255a266629e053d60212b4dd1eaf688805"
|
| 1541 |
+
},
|
| 1542 |
+
{
|
| 1543 |
+
"device_id": "DEV0386",
|
| 1544 |
+
"fingerprint_hash": "413e20233009dd16b8386706fb59418f0d9ac9c5b0ebf950cf267d07f8c90262"
|
| 1545 |
+
},
|
| 1546 |
+
{
|
| 1547 |
+
"device_id": "DEV0387",
|
| 1548 |
+
"fingerprint_hash": "8b92abd3377c7807cdca4b7d0e3cac6334e70c59000f4d58734ff1dab8e3f6bc"
|
| 1549 |
+
},
|
| 1550 |
+
{
|
| 1551 |
+
"device_id": "DEV0388",
|
| 1552 |
+
"fingerprint_hash": "10a98c8d2d202659a66009098367be3029eeb4b2863326e13105d4bebd3f85dd"
|
| 1553 |
+
},
|
| 1554 |
+
{
|
| 1555 |
+
"device_id": "DEV0389",
|
| 1556 |
+
"fingerprint_hash": "8b381105a40967c66f6fc5a1116c1547cccb7ce096426bd98e7133b2bbd74d98"
|
| 1557 |
+
},
|
| 1558 |
+
{
|
| 1559 |
+
"device_id": "DEV0390",
|
| 1560 |
+
"fingerprint_hash": "bc050715f180192af101f3b2bbeee265a4389caa222ba4d12492c30071b3a7d7"
|
| 1561 |
+
},
|
| 1562 |
+
{
|
| 1563 |
+
"device_id": "DEV0391",
|
| 1564 |
+
"fingerprint_hash": "eb804ba0eb6894c046b9ebf127509962445ca99e7f1c1fc3b428c9878522c229"
|
| 1565 |
+
},
|
| 1566 |
+
{
|
| 1567 |
+
"device_id": "DEV0392",
|
| 1568 |
+
"fingerprint_hash": "b2c34f0585853455e1a407a438063d959eda2a7798235bbb98250fd3b01975f9"
|
| 1569 |
+
},
|
| 1570 |
+
{
|
| 1571 |
+
"device_id": "DEV0393",
|
| 1572 |
+
"fingerprint_hash": "6a25c786986c447728e40018ec6cddd7d175592b74d9b73b224a1d3b9aa386d9"
|
| 1573 |
+
},
|
| 1574 |
+
{
|
| 1575 |
+
"device_id": "DEV0394",
|
| 1576 |
+
"fingerprint_hash": "37df7aca885d8db022aae3ac94a852453f36349b4422ea16ace306ad322a4f07"
|
| 1577 |
+
},
|
| 1578 |
+
{
|
| 1579 |
+
"device_id": "DEV0395",
|
| 1580 |
+
"fingerprint_hash": "7526569717ebb9132f7304460c53ab0103dc97be83724f75fd34bf020d0914d2"
|
| 1581 |
+
},
|
| 1582 |
+
{
|
| 1583 |
+
"device_id": "DEV0396",
|
| 1584 |
+
"fingerprint_hash": "695c18166bbb89e295302f4fb2456ed01797f322eed553e104f16177105d5879"
|
| 1585 |
+
},
|
| 1586 |
+
{
|
| 1587 |
+
"device_id": "DEV0397",
|
| 1588 |
+
"fingerprint_hash": "59e61fd370f004972f61f8b04291f049181f6d8c6abff2129fb178014569a2b8"
|
| 1589 |
+
},
|
| 1590 |
+
{
|
| 1591 |
+
"device_id": "DEV0398",
|
| 1592 |
+
"fingerprint_hash": "7f4a565f82d58b522a0c1a3f69ff63d43fa623d5a7e51b1de9b0a88daaf4c88d"
|
| 1593 |
+
},
|
| 1594 |
+
{
|
| 1595 |
+
"device_id": "DEV0399",
|
| 1596 |
+
"fingerprint_hash": "f9e9fb1405f2be65698e4dee8f93ef47044f0b62036162203cdce8779057a0fa"
|
| 1597 |
+
},
|
| 1598 |
+
{
|
| 1599 |
+
"device_id": "DEV0400",
|
| 1600 |
+
"fingerprint_hash": "bafc6f592c73bd6b395fcb2c13307d2052db7ba2db2002cf2c070503db0acc3c"
|
| 1601 |
+
},
|
| 1602 |
+
{
|
| 1603 |
+
"device_id": "DEV0401",
|
| 1604 |
+
"fingerprint_hash": "83c011bac645616b7a37e03d837e8b414927d82301adecb82d65dd8357238c41"
|
| 1605 |
+
},
|
| 1606 |
+
{
|
| 1607 |
+
"device_id": "DEV0402",
|
| 1608 |
+
"fingerprint_hash": "3301232dc5d5e575c4ba913a642a50643788c5879005bc4ac4186ac4c923c0f9"
|
| 1609 |
+
},
|
| 1610 |
+
{
|
| 1611 |
+
"device_id": "DEV0403",
|
| 1612 |
+
"fingerprint_hash": "80cd90df12a54dc42a90bb732c572ce24474c839db1a648aaa677645686a6efe"
|
| 1613 |
+
},
|
| 1614 |
+
{
|
| 1615 |
+
"device_id": "DEV0404",
|
| 1616 |
+
"fingerprint_hash": "7f958138868e5dc8bbcc5200af59d09008de909709b51cffdf38d36610be358c"
|
| 1617 |
+
},
|
| 1618 |
+
{
|
| 1619 |
+
"device_id": "DEV0405",
|
| 1620 |
+
"fingerprint_hash": "61d5a1c86a53a9bcd943fd3ae9c3a0ff8d818e7d8d9b0d9541080a1a10c0db51"
|
| 1621 |
+
}
|
| 1622 |
+
]
|
data/synthetic/ground_truth.json
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"rings": [
|
| 3 |
+
{
|
| 4 |
+
"ring_id": "RING01",
|
| 5 |
+
"customer_ids": [
|
| 6 |
+
"CUST0001",
|
| 7 |
+
"CUST0002",
|
| 8 |
+
"CUST0003"
|
| 9 |
+
],
|
| 10 |
+
"type": "fraud"
|
| 11 |
+
},
|
| 12 |
+
{
|
| 13 |
+
"ring_id": "RING02",
|
| 14 |
+
"customer_ids": [
|
| 15 |
+
"CUST0004",
|
| 16 |
+
"CUST0005",
|
| 17 |
+
"CUST0006",
|
| 18 |
+
"CUST0007",
|
| 19 |
+
"CUST0008"
|
| 20 |
+
],
|
| 21 |
+
"type": "fraud"
|
| 22 |
+
},
|
| 23 |
+
{
|
| 24 |
+
"ring_id": "RING03",
|
| 25 |
+
"customer_ids": [
|
| 26 |
+
"CUST0009",
|
| 27 |
+
"CUST0010",
|
| 28 |
+
"CUST0011",
|
| 29 |
+
"CUST0012",
|
| 30 |
+
"CUST0013"
|
| 31 |
+
],
|
| 32 |
+
"type": "fraud"
|
| 33 |
+
},
|
| 34 |
+
{
|
| 35 |
+
"ring_id": "RING04",
|
| 36 |
+
"customer_ids": [
|
| 37 |
+
"CUST0014",
|
| 38 |
+
"CUST0015",
|
| 39 |
+
"CUST0016",
|
| 40 |
+
"CUST0017",
|
| 41 |
+
"CUST0018"
|
| 42 |
+
],
|
| 43 |
+
"type": "fraud"
|
| 44 |
+
},
|
| 45 |
+
{
|
| 46 |
+
"ring_id": "RING05",
|
| 47 |
+
"customer_ids": [
|
| 48 |
+
"CUST0019",
|
| 49 |
+
"CUST0020",
|
| 50 |
+
"CUST0021",
|
| 51 |
+
"CUST0022",
|
| 52 |
+
"CUST0023"
|
| 53 |
+
],
|
| 54 |
+
"type": "fraud"
|
| 55 |
+
},
|
| 56 |
+
{
|
| 57 |
+
"ring_id": "RING06",
|
| 58 |
+
"customer_ids": [
|
| 59 |
+
"CUST0024",
|
| 60 |
+
"CUST0025",
|
| 61 |
+
"CUST0026",
|
| 62 |
+
"CUST0027",
|
| 63 |
+
"CUST0028",
|
| 64 |
+
"CUST0029"
|
| 65 |
+
],
|
| 66 |
+
"type": "fraud"
|
| 67 |
+
},
|
| 68 |
+
{
|
| 69 |
+
"ring_id": "RING07",
|
| 70 |
+
"customer_ids": [
|
| 71 |
+
"CUST0030",
|
| 72 |
+
"CUST0031",
|
| 73 |
+
"CUST0032"
|
| 74 |
+
],
|
| 75 |
+
"type": "fraud"
|
| 76 |
+
},
|
| 77 |
+
{
|
| 78 |
+
"ring_id": "RING08",
|
| 79 |
+
"customer_ids": [
|
| 80 |
+
"CUST0033",
|
| 81 |
+
"CUST0034",
|
| 82 |
+
"CUST0035"
|
| 83 |
+
],
|
| 84 |
+
"type": "fraud"
|
| 85 |
+
},
|
| 86 |
+
{
|
| 87 |
+
"ring_id": "RING09",
|
| 88 |
+
"customer_ids": [
|
| 89 |
+
"CUST0036",
|
| 90 |
+
"CUST0037",
|
| 91 |
+
"CUST0038",
|
| 92 |
+
"CUST0039",
|
| 93 |
+
"CUST0040"
|
| 94 |
+
],
|
| 95 |
+
"type": "fraud"
|
| 96 |
+
},
|
| 97 |
+
{
|
| 98 |
+
"ring_id": "RING10",
|
| 99 |
+
"customer_ids": [
|
| 100 |
+
"CUST0041",
|
| 101 |
+
"CUST0042",
|
| 102 |
+
"CUST0043",
|
| 103 |
+
"CUST0044"
|
| 104 |
+
],
|
| 105 |
+
"type": "fraud"
|
| 106 |
+
},
|
| 107 |
+
{
|
| 108 |
+
"ring_id": "RING11",
|
| 109 |
+
"customer_ids": [
|
| 110 |
+
"CUST0501",
|
| 111 |
+
"CUST0502",
|
| 112 |
+
"CUST0503"
|
| 113 |
+
],
|
| 114 |
+
"type": "fraud"
|
| 115 |
+
}
|
| 116 |
+
],
|
| 117 |
+
"stress_clusters": [
|
| 118 |
+
{
|
| 119 |
+
"cluster_id": "STRESS01",
|
| 120 |
+
"customer_ids": [
|
| 121 |
+
"CUST0045",
|
| 122 |
+
"CUST0046",
|
| 123 |
+
"CUST0047",
|
| 124 |
+
"CUST0048"
|
| 125 |
+
],
|
| 126 |
+
"type": "legitimate_shared_address"
|
| 127 |
+
},
|
| 128 |
+
{
|
| 129 |
+
"cluster_id": "STRESS02",
|
| 130 |
+
"customer_ids": [
|
| 131 |
+
"CUST0049",
|
| 132 |
+
"CUST0050",
|
| 133 |
+
"CUST0051",
|
| 134 |
+
"CUST0052"
|
| 135 |
+
],
|
| 136 |
+
"type": "legitimate_shared_address"
|
| 137 |
+
},
|
| 138 |
+
{
|
| 139 |
+
"cluster_id": "STRESS03",
|
| 140 |
+
"customer_ids": [
|
| 141 |
+
"CUST0053",
|
| 142 |
+
"CUST0054",
|
| 143 |
+
"CUST0055",
|
| 144 |
+
"CUST0056"
|
| 145 |
+
],
|
| 146 |
+
"type": "legitimate_shared_address"
|
| 147 |
+
},
|
| 148 |
+
{
|
| 149 |
+
"cluster_id": "STRESS04",
|
| 150 |
+
"customer_ids": [
|
| 151 |
+
"CUST0057",
|
| 152 |
+
"CUST0058"
|
| 153 |
+
],
|
| 154 |
+
"type": "legitimate_shared_address"
|
| 155 |
+
},
|
| 156 |
+
{
|
| 157 |
+
"cluster_id": "STRESS05",
|
| 158 |
+
"customer_ids": [
|
| 159 |
+
"CUST0059",
|
| 160 |
+
"CUST0060"
|
| 161 |
+
],
|
| 162 |
+
"type": "legitimate_shared_address"
|
| 163 |
+
}
|
| 164 |
+
]
|
| 165 |
+
}
|
data/synthetic/orders.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
data/synthetic/payment_instruments.json
ADDED
|
@@ -0,0 +1,1932 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
{
|
| 3 |
+
"instrument_id": "PAY0001",
|
| 4 |
+
"type": "upi",
|
| 5 |
+
"last4_hash": "43854d169fe9af1d004773b3c9822b3f57b140d4703096704f3d795b1581706b"
|
| 6 |
+
},
|
| 7 |
+
{
|
| 8 |
+
"instrument_id": "PAY0002",
|
| 9 |
+
"type": "card",
|
| 10 |
+
"last4_hash": "9b3cea3bd8789ba47cc969bff5914da7ebac8e0052e282917299814a53a7dfdb"
|
| 11 |
+
},
|
| 12 |
+
{
|
| 13 |
+
"instrument_id": "PAY0003",
|
| 14 |
+
"type": "upi",
|
| 15 |
+
"last4_hash": "72cc443db576409f0e56de30286baede30ae7c2d0f6e3e49f3fc5ac7e9d5b276"
|
| 16 |
+
},
|
| 17 |
+
{
|
| 18 |
+
"instrument_id": "PAY0004",
|
| 19 |
+
"type": "upi",
|
| 20 |
+
"last4_hash": "b324329805a238135ed3f429bde8cbe869b2b2190e17edccd3ae9e036565a7ae"
|
| 21 |
+
},
|
| 22 |
+
{
|
| 23 |
+
"instrument_id": "PAY0005",
|
| 24 |
+
"type": "upi",
|
| 25 |
+
"last4_hash": "ba2854ea732fe9c5c45bb5532172ea531a8510cd03fde9247f0d1f38368e49f1"
|
| 26 |
+
},
|
| 27 |
+
{
|
| 28 |
+
"instrument_id": "PAY0006",
|
| 29 |
+
"type": "upi",
|
| 30 |
+
"last4_hash": "1314e83b4d4e34a1bcdb5665aedc31616d49cef471cca9561c471abd798b0f5a"
|
| 31 |
+
},
|
| 32 |
+
{
|
| 33 |
+
"instrument_id": "PAY0007",
|
| 34 |
+
"type": "card",
|
| 35 |
+
"last4_hash": "b39b7ba7e07d710447e89c40277171aa4c568e3de08e4970d7579288af5bf3f4"
|
| 36 |
+
},
|
| 37 |
+
{
|
| 38 |
+
"instrument_id": "PAY0008",
|
| 39 |
+
"type": "card",
|
| 40 |
+
"last4_hash": "9199d9e5b275563cd8c867aa6013d32117ad6232cd0d6e0b7e28b9eb54c80b2c"
|
| 41 |
+
},
|
| 42 |
+
{
|
| 43 |
+
"instrument_id": "PAY0009",
|
| 44 |
+
"type": "card",
|
| 45 |
+
"last4_hash": "48ccfd09d04c36762f6b0c83bf32f695caa2f2dcf773703acdb4a030a3fa1dc0"
|
| 46 |
+
},
|
| 47 |
+
{
|
| 48 |
+
"instrument_id": "PAY0010",
|
| 49 |
+
"type": "card",
|
| 50 |
+
"last4_hash": "c5067bcbc573d35e3788d098a8d58772fc5717e120b4990f8bcbfd634e45853a"
|
| 51 |
+
},
|
| 52 |
+
{
|
| 53 |
+
"instrument_id": "PAY0011",
|
| 54 |
+
"type": "card",
|
| 55 |
+
"last4_hash": "39e71545d840848a9af1a669d7e6aabf8ee95536a2f219820c450aa31f796573"
|
| 56 |
+
},
|
| 57 |
+
{
|
| 58 |
+
"instrument_id": "PAY0012",
|
| 59 |
+
"type": "upi",
|
| 60 |
+
"last4_hash": "fdb37acb269dac7997162fd98b93c16bc8bdaa2906747082415d809cf1df6be5"
|
| 61 |
+
},
|
| 62 |
+
{
|
| 63 |
+
"instrument_id": "PAY0013",
|
| 64 |
+
"type": "card",
|
| 65 |
+
"last4_hash": "44544e0d6770664c4c13ae2ed2438373c2014f112a6f5fcd7c241ba79222bc16"
|
| 66 |
+
},
|
| 67 |
+
{
|
| 68 |
+
"instrument_id": "PAY0014",
|
| 69 |
+
"type": "upi",
|
| 70 |
+
"last4_hash": "4765a7b39436675afd5fdff5b56b41db91c05ecb524a2a7def0318b3d5de307c"
|
| 71 |
+
},
|
| 72 |
+
{
|
| 73 |
+
"instrument_id": "PAY0015",
|
| 74 |
+
"type": "card",
|
| 75 |
+
"last4_hash": "ed46f81f54d1ac6c2586e0003e659bc0595f7ebfd6fa37dd5b354c56451d4ab2"
|
| 76 |
+
},
|
| 77 |
+
{
|
| 78 |
+
"instrument_id": "PAY0016",
|
| 79 |
+
"type": "upi",
|
| 80 |
+
"last4_hash": "2d56bccc2c06064b1cc7bd9a8605692e6c708145159d69b6439d53d5594386b1"
|
| 81 |
+
},
|
| 82 |
+
{
|
| 83 |
+
"instrument_id": "PAY0017",
|
| 84 |
+
"type": "upi",
|
| 85 |
+
"last4_hash": "29e3061bd659a3a4b6ac671fd1dc8f7ff9f453aa6caaf15289b9a722abd03b7c"
|
| 86 |
+
},
|
| 87 |
+
{
|
| 88 |
+
"instrument_id": "PAY0018",
|
| 89 |
+
"type": "upi",
|
| 90 |
+
"last4_hash": "b2ce2a829d3d50ba8e38eac676598731979f3a8b019e4f247fd85828642ee9f8"
|
| 91 |
+
},
|
| 92 |
+
{
|
| 93 |
+
"instrument_id": "PAY0019",
|
| 94 |
+
"type": "upi",
|
| 95 |
+
"last4_hash": "0941be7a3eff242affd46525c1c0468acef945d064fe8c0b553d14e0074303a2"
|
| 96 |
+
},
|
| 97 |
+
{
|
| 98 |
+
"instrument_id": "PAY0020",
|
| 99 |
+
"type": "upi",
|
| 100 |
+
"last4_hash": "3769b2ecd28cdf0ed1d25aad16979ce2a3ec7782017c61941e8b161c44baba08"
|
| 101 |
+
},
|
| 102 |
+
{
|
| 103 |
+
"instrument_id": "PAY0021",
|
| 104 |
+
"type": "card",
|
| 105 |
+
"last4_hash": "ab86fe44dea15e7a6b438f741aa208f079d55f626f5c471c999b2ed78b37bd6a"
|
| 106 |
+
},
|
| 107 |
+
{
|
| 108 |
+
"instrument_id": "PAY0022",
|
| 109 |
+
"type": "upi",
|
| 110 |
+
"last4_hash": "656ec82405d95b39a019289db15f781b4f8be7824060ab938656199fce05961f"
|
| 111 |
+
},
|
| 112 |
+
{
|
| 113 |
+
"instrument_id": "PAY0023",
|
| 114 |
+
"type": "upi",
|
| 115 |
+
"last4_hash": "cf5b255ef873089b5efa6efa80f98b50cb5df021246f561771e50fa90ff34c78"
|
| 116 |
+
},
|
| 117 |
+
{
|
| 118 |
+
"instrument_id": "PAY0024",
|
| 119 |
+
"type": "card",
|
| 120 |
+
"last4_hash": "faede57cfab74b18e63014bf3295fde357982f05d67e6dac2a0b28b333b5c396"
|
| 121 |
+
},
|
| 122 |
+
{
|
| 123 |
+
"instrument_id": "PAY0025",
|
| 124 |
+
"type": "upi",
|
| 125 |
+
"last4_hash": "41e20f4fbbd493f6ee8744ec2ac8143aba5d3cb34eec0338a051e460fed85707"
|
| 126 |
+
},
|
| 127 |
+
{
|
| 128 |
+
"instrument_id": "PAY0026",
|
| 129 |
+
"type": "card",
|
| 130 |
+
"last4_hash": "7808b86edb7b1acd97860de5b0014865ec15ea7a2f6e8ba5c0a3c88127a9447b"
|
| 131 |
+
},
|
| 132 |
+
{
|
| 133 |
+
"instrument_id": "PAY0027",
|
| 134 |
+
"type": "upi",
|
| 135 |
+
"last4_hash": "ff293a64aa18c6df0364f0a6bea775dcb81d5d5cc4fce958612ecd70eeb64aee"
|
| 136 |
+
},
|
| 137 |
+
{
|
| 138 |
+
"instrument_id": "PAY0028",
|
| 139 |
+
"type": "card",
|
| 140 |
+
"last4_hash": "27995993191887fe707d8f4be3a3b3e8190b12dc0ba20cc441ded243f8a304a4"
|
| 141 |
+
},
|
| 142 |
+
{
|
| 143 |
+
"instrument_id": "PAY0029",
|
| 144 |
+
"type": "upi",
|
| 145 |
+
"last4_hash": "d8f34a8a519c35fd11b63a97cb68ab840d9993ea4e09f25ba4cbf20fddade301"
|
| 146 |
+
},
|
| 147 |
+
{
|
| 148 |
+
"instrument_id": "PAY0030",
|
| 149 |
+
"type": "upi",
|
| 150 |
+
"last4_hash": "ab8ba612699a1b34ab8c4398b833d221f4bfe4e43c188f8c571de33225790419"
|
| 151 |
+
},
|
| 152 |
+
{
|
| 153 |
+
"instrument_id": "PAY0031",
|
| 154 |
+
"type": "upi",
|
| 155 |
+
"last4_hash": "382a90367a19bf8ef8631798e4d29596d729604fe59d6c6d439702d5ffe87970"
|
| 156 |
+
},
|
| 157 |
+
{
|
| 158 |
+
"instrument_id": "PAY0032",
|
| 159 |
+
"type": "upi",
|
| 160 |
+
"last4_hash": "be53a1caecfd70a4ca27be2289e8c54be3f6af7f9bf67ef45af4ff157e63bf5f"
|
| 161 |
+
},
|
| 162 |
+
{
|
| 163 |
+
"instrument_id": "PAY0033",
|
| 164 |
+
"type": "card",
|
| 165 |
+
"last4_hash": "b23d8b6a24247560231f60bd114e288d0ac8707610ff3c53bf82897eace08854"
|
| 166 |
+
},
|
| 167 |
+
{
|
| 168 |
+
"instrument_id": "PAY0034",
|
| 169 |
+
"type": "upi",
|
| 170 |
+
"last4_hash": "be08d86973638e7039b4265f4cc42328e0a99933baf066ed7c252a2594c25282"
|
| 171 |
+
},
|
| 172 |
+
{
|
| 173 |
+
"instrument_id": "PAY0035",
|
| 174 |
+
"type": "card",
|
| 175 |
+
"last4_hash": "c81b352b270b2e498256b5e24c726a039cd665477a83d71d95633340782782d4"
|
| 176 |
+
},
|
| 177 |
+
{
|
| 178 |
+
"instrument_id": "PAY0036",
|
| 179 |
+
"type": "upi",
|
| 180 |
+
"last4_hash": "9881a093db6601fd80ff7825844a119d17b55cde13322cc5b3f8e57a28d9c701"
|
| 181 |
+
},
|
| 182 |
+
{
|
| 183 |
+
"instrument_id": "PAY0037",
|
| 184 |
+
"type": "upi",
|
| 185 |
+
"last4_hash": "4537f0f8c9dc0d35adf0338d454e2d324bcd289713b434c7d29708c06a3b5dd7"
|
| 186 |
+
},
|
| 187 |
+
{
|
| 188 |
+
"instrument_id": "PAY0038",
|
| 189 |
+
"type": "card",
|
| 190 |
+
"last4_hash": "39d5ce6249548c318a5f0b6bf0a3e2f234750a9741b6ce2f9eff8670bc7cd7af"
|
| 191 |
+
},
|
| 192 |
+
{
|
| 193 |
+
"instrument_id": "PAY0039",
|
| 194 |
+
"type": "upi",
|
| 195 |
+
"last4_hash": "9f7599e78fd8ce9803dd88d94f75372f3d02c861b7d4b8b6a14144a3eb7d15d0"
|
| 196 |
+
},
|
| 197 |
+
{
|
| 198 |
+
"instrument_id": "PAY0040",
|
| 199 |
+
"type": "card",
|
| 200 |
+
"last4_hash": "cf7dee3443a859943d9ecf558fe5cf260f9acb4150b5d18d8b2e04be1cc3ca54"
|
| 201 |
+
},
|
| 202 |
+
{
|
| 203 |
+
"instrument_id": "PAY0041",
|
| 204 |
+
"type": "card",
|
| 205 |
+
"last4_hash": "55fdec963805de594b61b2c1692cadc2c1dfb844d6ac10c5bfed33c842087b2e"
|
| 206 |
+
},
|
| 207 |
+
{
|
| 208 |
+
"instrument_id": "PAY0042",
|
| 209 |
+
"type": "card",
|
| 210 |
+
"last4_hash": "03afa3478417ff5086b7560e07ccafaeb73f2772ce4e05fecde39fcd32a5437e"
|
| 211 |
+
},
|
| 212 |
+
{
|
| 213 |
+
"instrument_id": "PAY0043",
|
| 214 |
+
"type": "upi",
|
| 215 |
+
"last4_hash": "d934819258879e09373979e6d1fb0d5da3404039738bd5d806df0eca450a3429"
|
| 216 |
+
},
|
| 217 |
+
{
|
| 218 |
+
"instrument_id": "PAY0044",
|
| 219 |
+
"type": "card",
|
| 220 |
+
"last4_hash": "48f84ea6043f5313382811d79ec2ba3d163c943b0e33ca3fe2ba2e9a4f18e935"
|
| 221 |
+
},
|
| 222 |
+
{
|
| 223 |
+
"instrument_id": "PAY0045",
|
| 224 |
+
"type": "upi",
|
| 225 |
+
"last4_hash": "37a5eba54aa89b51ef3f6bb7615f043ac56587d4d67e10fb85e1ec42495a41ab"
|
| 226 |
+
},
|
| 227 |
+
{
|
| 228 |
+
"instrument_id": "PAY0046",
|
| 229 |
+
"type": "card",
|
| 230 |
+
"last4_hash": "a11f793d5f24841552b2befc8d946d9f7e5652edfb58bd49c3a8423a6031c952"
|
| 231 |
+
},
|
| 232 |
+
{
|
| 233 |
+
"instrument_id": "PAY0047",
|
| 234 |
+
"type": "upi",
|
| 235 |
+
"last4_hash": "140a85d1fd4c514a914643ec2922ce6818ae675e73e2eef6e641fee467438ed2"
|
| 236 |
+
},
|
| 237 |
+
{
|
| 238 |
+
"instrument_id": "PAY0048",
|
| 239 |
+
"type": "upi",
|
| 240 |
+
"last4_hash": "4b734774fc6f30af3315238e013de6354eeff142ce27efdbc72705e3a13f3d5f"
|
| 241 |
+
},
|
| 242 |
+
{
|
| 243 |
+
"instrument_id": "PAY0049",
|
| 244 |
+
"type": "card",
|
| 245 |
+
"last4_hash": "0bb96d87216f5159d997d566969931579a74f4fcd81e9e4280e5354a4ba0c2fd"
|
| 246 |
+
},
|
| 247 |
+
{
|
| 248 |
+
"instrument_id": "PAY0050",
|
| 249 |
+
"type": "card",
|
| 250 |
+
"last4_hash": "5e27752e101ec179e101f6016d7b015f2a408795a3135953ef6066f73753fadd"
|
| 251 |
+
},
|
| 252 |
+
{
|
| 253 |
+
"instrument_id": "PAY0051",
|
| 254 |
+
"type": "upi",
|
| 255 |
+
"last4_hash": "89c55097f7602585a95ada5ee3a306ecb4966744a2586946b15e978fb46f6832"
|
| 256 |
+
},
|
| 257 |
+
{
|
| 258 |
+
"instrument_id": "PAY0052",
|
| 259 |
+
"type": "card",
|
| 260 |
+
"last4_hash": "741f514bbddf7310b4d0fe0dea7f062941dd67b8090b66d2bcf6bc621bbd2021"
|
| 261 |
+
},
|
| 262 |
+
{
|
| 263 |
+
"instrument_id": "PAY0053",
|
| 264 |
+
"type": "upi",
|
| 265 |
+
"last4_hash": "eaf52ea64d24cb70e3cb3e2790c8cead55c6bd523b0b0de6cd0dbad4cae51c6e"
|
| 266 |
+
},
|
| 267 |
+
{
|
| 268 |
+
"instrument_id": "PAY0054",
|
| 269 |
+
"type": "card",
|
| 270 |
+
"last4_hash": "cc55b4c2e7e6d5ef1642141e8a25944cfa6d7ed2b8e8385adcc92c6bb3aee571"
|
| 271 |
+
},
|
| 272 |
+
{
|
| 273 |
+
"instrument_id": "PAY0055",
|
| 274 |
+
"type": "card",
|
| 275 |
+
"last4_hash": "1f5e12a1dcc43dfd45e6709479e6cc62b1a6426a6ff78926166808e13a813c9d"
|
| 276 |
+
},
|
| 277 |
+
{
|
| 278 |
+
"instrument_id": "PAY0056",
|
| 279 |
+
"type": "card",
|
| 280 |
+
"last4_hash": "900cb8e36b717b81b9dbbb51cfae997cf5236c36afea5ba7100d005ad52d1cbc"
|
| 281 |
+
},
|
| 282 |
+
{
|
| 283 |
+
"instrument_id": "PAY0057",
|
| 284 |
+
"type": "upi",
|
| 285 |
+
"last4_hash": "a6781ca9dc05eb6d4a0cd863aa22a558554373cfcd2be1242f8df005f98416d6"
|
| 286 |
+
},
|
| 287 |
+
{
|
| 288 |
+
"instrument_id": "PAY0058",
|
| 289 |
+
"type": "upi",
|
| 290 |
+
"last4_hash": "3a14d640f42889d144e71bda4425b340e0b1f62d87f6d9bffd464598655d43c1"
|
| 291 |
+
},
|
| 292 |
+
{
|
| 293 |
+
"instrument_id": "PAY0059",
|
| 294 |
+
"type": "upi",
|
| 295 |
+
"last4_hash": "cec0db12ddf9f2d2e372eca85188235f332465f82e371202f3950d0b77fb5b6c"
|
| 296 |
+
},
|
| 297 |
+
{
|
| 298 |
+
"instrument_id": "PAY0060",
|
| 299 |
+
"type": "upi",
|
| 300 |
+
"last4_hash": "c779fc361251ad4c3db1fd8655b96bfd565eff7f13a414ace30eda2f89c9cd45"
|
| 301 |
+
},
|
| 302 |
+
{
|
| 303 |
+
"instrument_id": "PAY0061",
|
| 304 |
+
"type": "card",
|
| 305 |
+
"last4_hash": "07007ba87ea78903e0ec57160cac3ff7dfc1109f2d84cc6eed9ffbd8358a62d1"
|
| 306 |
+
},
|
| 307 |
+
{
|
| 308 |
+
"instrument_id": "PAY0062",
|
| 309 |
+
"type": "upi",
|
| 310 |
+
"last4_hash": "f1980fc5343d10c28baa1ce65de484c08733c23d7e43977d53aec202775ca81e"
|
| 311 |
+
},
|
| 312 |
+
{
|
| 313 |
+
"instrument_id": "PAY0063",
|
| 314 |
+
"type": "upi",
|
| 315 |
+
"last4_hash": "4ef51169834cb29778aa564dd2dd9ebc6017656e2d47f5a21c689a44798c1605"
|
| 316 |
+
},
|
| 317 |
+
{
|
| 318 |
+
"instrument_id": "PAY0064",
|
| 319 |
+
"type": "card",
|
| 320 |
+
"last4_hash": "9302a967cce443780477212553ae3d74625dd165a096a4ee8299dcf0c8079866"
|
| 321 |
+
},
|
| 322 |
+
{
|
| 323 |
+
"instrument_id": "PAY0065",
|
| 324 |
+
"type": "upi",
|
| 325 |
+
"last4_hash": "86dfdb71e782a8cec375d222d5383cc95e042aad436f9fa3a47f1d7c8c3864f1"
|
| 326 |
+
},
|
| 327 |
+
{
|
| 328 |
+
"instrument_id": "PAY0066",
|
| 329 |
+
"type": "card",
|
| 330 |
+
"last4_hash": "ef3eaba74dcc1c3e6536e12d4a95d94fe3d32b29f1d217ce6b377049efe60511"
|
| 331 |
+
},
|
| 332 |
+
{
|
| 333 |
+
"instrument_id": "PAY0067",
|
| 334 |
+
"type": "upi",
|
| 335 |
+
"last4_hash": "7f58b9425094d6f95c8f177eb93b12c1701a63978f9bb291335345d852425c90"
|
| 336 |
+
},
|
| 337 |
+
{
|
| 338 |
+
"instrument_id": "PAY0068",
|
| 339 |
+
"type": "card",
|
| 340 |
+
"last4_hash": "45b120bb08854e18123188f37c3d0b52d06781d415fb5b56a684870a779e09bc"
|
| 341 |
+
},
|
| 342 |
+
{
|
| 343 |
+
"instrument_id": "PAY0069",
|
| 344 |
+
"type": "card",
|
| 345 |
+
"last4_hash": "43a70ba6b21894cd24165d9d7ee59b012e698cf97e22fd275ccdd05a556e7061"
|
| 346 |
+
},
|
| 347 |
+
{
|
| 348 |
+
"instrument_id": "PAY0070",
|
| 349 |
+
"type": "upi",
|
| 350 |
+
"last4_hash": "22e8922403c6ca57a6a7eb282337498418fa5f89ac9110534278aef3736aa28c"
|
| 351 |
+
},
|
| 352 |
+
{
|
| 353 |
+
"instrument_id": "PAY0071",
|
| 354 |
+
"type": "upi",
|
| 355 |
+
"last4_hash": "7a9e521df4c6ba4d71bb4bad29f1f771918ffa0b507d9a6381f642b6dfa4f6d3"
|
| 356 |
+
},
|
| 357 |
+
{
|
| 358 |
+
"instrument_id": "PAY0072",
|
| 359 |
+
"type": "card",
|
| 360 |
+
"last4_hash": "f35bdfbc3b7e089ee8a84c2684deb1f5c96732895d79086eb8fa0458742a469d"
|
| 361 |
+
},
|
| 362 |
+
{
|
| 363 |
+
"instrument_id": "PAY0073",
|
| 364 |
+
"type": "card",
|
| 365 |
+
"last4_hash": "e26f3716adbe1a42e8b784b9d6670f922151428235cd146c3cc7b80653b2f9d7"
|
| 366 |
+
},
|
| 367 |
+
{
|
| 368 |
+
"instrument_id": "PAY0074",
|
| 369 |
+
"type": "upi",
|
| 370 |
+
"last4_hash": "dff532682c09d2c12af80c41a395f9b853e8edae6ae0bb129fd9dc7274d52b63"
|
| 371 |
+
},
|
| 372 |
+
{
|
| 373 |
+
"instrument_id": "PAY0075",
|
| 374 |
+
"type": "card",
|
| 375 |
+
"last4_hash": "4817ddb54d7a527a5cb1e069434fdfb5350bfdc910cc6a3aa35b54a4036b9809"
|
| 376 |
+
},
|
| 377 |
+
{
|
| 378 |
+
"instrument_id": "PAY0076",
|
| 379 |
+
"type": "card",
|
| 380 |
+
"last4_hash": "58e47bf2ec5f0d27dab6b42787a65ea8cb3a2c3c88816dbc2eee8bc20d600a1a"
|
| 381 |
+
},
|
| 382 |
+
{
|
| 383 |
+
"instrument_id": "PAY0077",
|
| 384 |
+
"type": "upi",
|
| 385 |
+
"last4_hash": "e7635b6f96d7470ea28f65a202cd9e0c7abf789ee12f1ef5b9b80fe5f1bae7d2"
|
| 386 |
+
},
|
| 387 |
+
{
|
| 388 |
+
"instrument_id": "PAY0078",
|
| 389 |
+
"type": "upi",
|
| 390 |
+
"last4_hash": "6692ae362de80b8769f3a4b190b025dfdf3ba7b184d2928d35c9c80061ff5348"
|
| 391 |
+
},
|
| 392 |
+
{
|
| 393 |
+
"instrument_id": "PAY0079",
|
| 394 |
+
"type": "upi",
|
| 395 |
+
"last4_hash": "399bd15402e3c3ea9a728f19361e02c634c9a46b40051212832d8817d830aa5e"
|
| 396 |
+
},
|
| 397 |
+
{
|
| 398 |
+
"instrument_id": "PAY0080",
|
| 399 |
+
"type": "upi",
|
| 400 |
+
"last4_hash": "3ee5cc0469c7e67513b98291b35b41cbd00f5c5e20973b783b2b3b44b225a81c"
|
| 401 |
+
},
|
| 402 |
+
{
|
| 403 |
+
"instrument_id": "PAY0081",
|
| 404 |
+
"type": "card",
|
| 405 |
+
"last4_hash": "e753559bf52404ed6877db546a80e189e22c6ff1ca965d7115a882d4335c9be7"
|
| 406 |
+
},
|
| 407 |
+
{
|
| 408 |
+
"instrument_id": "PAY0082",
|
| 409 |
+
"type": "upi",
|
| 410 |
+
"last4_hash": "ab3c34aaa228b75bdfa29314f3c134dacadede2deee1dfdb3fda46cf3628e178"
|
| 411 |
+
},
|
| 412 |
+
{
|
| 413 |
+
"instrument_id": "PAY0083",
|
| 414 |
+
"type": "upi",
|
| 415 |
+
"last4_hash": "d0fc42ab00f8e3e251e0418898559ee941b0de10f08f170bd11bf51757b270bd"
|
| 416 |
+
},
|
| 417 |
+
{
|
| 418 |
+
"instrument_id": "PAY0084",
|
| 419 |
+
"type": "card",
|
| 420 |
+
"last4_hash": "e18f50079034b56f8d86d0e2fcaf15a6685ef6b8771711ff7bda1f937f4b10f4"
|
| 421 |
+
},
|
| 422 |
+
{
|
| 423 |
+
"instrument_id": "PAY0085",
|
| 424 |
+
"type": "upi",
|
| 425 |
+
"last4_hash": "e8df2d2fe1fbb87bcf45505fb1dea35d09a702ef3af8625ebf5a39830c45d1a9"
|
| 426 |
+
},
|
| 427 |
+
{
|
| 428 |
+
"instrument_id": "PAY0086",
|
| 429 |
+
"type": "card",
|
| 430 |
+
"last4_hash": "05e5ddbcc59eb669a2e5987e36a40537fcdb275a87b38023f9da6d41f0a5c37b"
|
| 431 |
+
},
|
| 432 |
+
{
|
| 433 |
+
"instrument_id": "PAY0087",
|
| 434 |
+
"type": "upi",
|
| 435 |
+
"last4_hash": "a5613be89b56ff92cc0d12ca5b2900ff0a503c9a61bc731d9a0f3c00f7bdeaa0"
|
| 436 |
+
},
|
| 437 |
+
{
|
| 438 |
+
"instrument_id": "PAY0088",
|
| 439 |
+
"type": "upi",
|
| 440 |
+
"last4_hash": "1c313ae9b416b8c468f7079bca03b08c0273987a41024976176bd1992399a4fa"
|
| 441 |
+
},
|
| 442 |
+
{
|
| 443 |
+
"instrument_id": "PAY0089",
|
| 444 |
+
"type": "upi",
|
| 445 |
+
"last4_hash": "aa0363dfc3a149e6665dff0b628546f766d3ea2910ec17078c4968c97102a9a2"
|
| 446 |
+
},
|
| 447 |
+
{
|
| 448 |
+
"instrument_id": "PAY0090",
|
| 449 |
+
"type": "card",
|
| 450 |
+
"last4_hash": "35a6c93873ac10cb4386cd7e3b071daa8b3002025a30284d26b3d5a0950f7900"
|
| 451 |
+
},
|
| 452 |
+
{
|
| 453 |
+
"instrument_id": "PAY0091",
|
| 454 |
+
"type": "card",
|
| 455 |
+
"last4_hash": "d308ddc557e774187ad6c7da81b39db990def9a39e6c88e79cb163b6bdd6e8e5"
|
| 456 |
+
},
|
| 457 |
+
{
|
| 458 |
+
"instrument_id": "PAY0092",
|
| 459 |
+
"type": "upi",
|
| 460 |
+
"last4_hash": "f6a7b1da20dc935df8ad86e6d517983f6f08a9937ebedd49046d209630cf5307"
|
| 461 |
+
},
|
| 462 |
+
{
|
| 463 |
+
"instrument_id": "PAY0093",
|
| 464 |
+
"type": "upi",
|
| 465 |
+
"last4_hash": "48ba0d3f602388d95de0e7a95c21a34daa9438ed5eb6617619728482e2da6c30"
|
| 466 |
+
},
|
| 467 |
+
{
|
| 468 |
+
"instrument_id": "PAY0094",
|
| 469 |
+
"type": "card",
|
| 470 |
+
"last4_hash": "97d2244a7046f7586a09c23c5c270591dfc00dbadcbe8a279d045825bd669d29"
|
| 471 |
+
},
|
| 472 |
+
{
|
| 473 |
+
"instrument_id": "PAY0095",
|
| 474 |
+
"type": "upi",
|
| 475 |
+
"last4_hash": "8dc3b1593caf9cd87427a1ecebe50a2c9e8a52759900cfe3358f3a55c5400bcf"
|
| 476 |
+
},
|
| 477 |
+
{
|
| 478 |
+
"instrument_id": "PAY0096",
|
| 479 |
+
"type": "upi",
|
| 480 |
+
"last4_hash": "899c2819e671e9241ca393e13a3b08a70d6e6c0ecad7faf5cf22999e648577aa"
|
| 481 |
+
},
|
| 482 |
+
{
|
| 483 |
+
"instrument_id": "PAY0097",
|
| 484 |
+
"type": "card",
|
| 485 |
+
"last4_hash": "c9916ca5880d11008999dc266d47657e927fde740bb899caa52ca5528da796b2"
|
| 486 |
+
},
|
| 487 |
+
{
|
| 488 |
+
"instrument_id": "PAY0098",
|
| 489 |
+
"type": "card",
|
| 490 |
+
"last4_hash": "5f9e3d4a0fa6f44a726c146ead2a301eb4026ae67b06cc5971210e5d749762b0"
|
| 491 |
+
},
|
| 492 |
+
{
|
| 493 |
+
"instrument_id": "PAY0099",
|
| 494 |
+
"type": "card",
|
| 495 |
+
"last4_hash": "99eeb44d3313dca5755437fca4cb7f50ccb1e9f7279abd334045d05a001fd8b8"
|
| 496 |
+
},
|
| 497 |
+
{
|
| 498 |
+
"instrument_id": "PAY0100",
|
| 499 |
+
"type": "card",
|
| 500 |
+
"last4_hash": "ecf8103662b93ccc41bc42ba074379fedce3688c49093102b9200f0cec473559"
|
| 501 |
+
},
|
| 502 |
+
{
|
| 503 |
+
"instrument_id": "PAY0101",
|
| 504 |
+
"type": "upi",
|
| 505 |
+
"last4_hash": "624ea67219372de3ff819cad5c6feb061f1f719eda1f44f94d154bf758cfd97e"
|
| 506 |
+
},
|
| 507 |
+
{
|
| 508 |
+
"instrument_id": "PAY0102",
|
| 509 |
+
"type": "card",
|
| 510 |
+
"last4_hash": "8c8699214133b6332adc864763533eb8880c1e6f6a7787a962cd3f5ed3e72026"
|
| 511 |
+
},
|
| 512 |
+
{
|
| 513 |
+
"instrument_id": "PAY0103",
|
| 514 |
+
"type": "card",
|
| 515 |
+
"last4_hash": "2e1943902be93c87e9d31812ef887d1f91326e8e8e3779feb59c48c9ac32f58f"
|
| 516 |
+
},
|
| 517 |
+
{
|
| 518 |
+
"instrument_id": "PAY0104",
|
| 519 |
+
"type": "upi",
|
| 520 |
+
"last4_hash": "facf1b4df937f097837b3f532e2b5dae513e76a448557385a979faa12bebef01"
|
| 521 |
+
},
|
| 522 |
+
{
|
| 523 |
+
"instrument_id": "PAY0105",
|
| 524 |
+
"type": "upi",
|
| 525 |
+
"last4_hash": "36d4f0701702ed6e66256c81f32544275aec9155741661d2cdad2b83525b1129"
|
| 526 |
+
},
|
| 527 |
+
{
|
| 528 |
+
"instrument_id": "PAY0106",
|
| 529 |
+
"type": "upi",
|
| 530 |
+
"last4_hash": "b861be6fb870d16d203b8521a1805a974d4e0503c67120b44c4c9df5778f8f12"
|
| 531 |
+
},
|
| 532 |
+
{
|
| 533 |
+
"instrument_id": "PAY0107",
|
| 534 |
+
"type": "card",
|
| 535 |
+
"last4_hash": "fef8ef07b0461c95476dd7b995f3333578ae82031501d300354f2263cf1a73cb"
|
| 536 |
+
},
|
| 537 |
+
{
|
| 538 |
+
"instrument_id": "PAY0108",
|
| 539 |
+
"type": "upi",
|
| 540 |
+
"last4_hash": "1f8509908e8e7d16fe0c0de8ea7cc0fbadb2d3c24f831ab4ac7b35ee85f09f49"
|
| 541 |
+
},
|
| 542 |
+
{
|
| 543 |
+
"instrument_id": "PAY0109",
|
| 544 |
+
"type": "upi",
|
| 545 |
+
"last4_hash": "7baf56a8601326f4d3b8fb1a73b013a596f37175d60075a2ba2d0cd45735ad2f"
|
| 546 |
+
},
|
| 547 |
+
{
|
| 548 |
+
"instrument_id": "PAY0110",
|
| 549 |
+
"type": "upi",
|
| 550 |
+
"last4_hash": "09509b09bdfa083ce661063988b5fd1fb9cb92a37c341a67355eecd6c6a778dc"
|
| 551 |
+
},
|
| 552 |
+
{
|
| 553 |
+
"instrument_id": "PAY0111",
|
| 554 |
+
"type": "upi",
|
| 555 |
+
"last4_hash": "ab9a89784cfae1151df7fa3057f7c20b90374c0b338fefabda9fb5954db70060"
|
| 556 |
+
},
|
| 557 |
+
{
|
| 558 |
+
"instrument_id": "PAY0112",
|
| 559 |
+
"type": "upi",
|
| 560 |
+
"last4_hash": "ba7b98b0c987d50c24b7851e96ba961b0f6561ba32e669918f2203ac26035829"
|
| 561 |
+
},
|
| 562 |
+
{
|
| 563 |
+
"instrument_id": "PAY0113",
|
| 564 |
+
"type": "upi",
|
| 565 |
+
"last4_hash": "b0e75b9a16227b9d288a465d0de38135405a7e4f0529545d7e26a4fa4c366728"
|
| 566 |
+
},
|
| 567 |
+
{
|
| 568 |
+
"instrument_id": "PAY0114",
|
| 569 |
+
"type": "card",
|
| 570 |
+
"last4_hash": "e68259a977d847c9ed26fc47c6855021c9a51eac28a63f9a0c012f7bbac0b556"
|
| 571 |
+
},
|
| 572 |
+
{
|
| 573 |
+
"instrument_id": "PAY0115",
|
| 574 |
+
"type": "card",
|
| 575 |
+
"last4_hash": "b789f4e82d98e206cf0f6cc237eff16955db29bee865372ac12af8e0226b7607"
|
| 576 |
+
},
|
| 577 |
+
{
|
| 578 |
+
"instrument_id": "PAY0116",
|
| 579 |
+
"type": "card",
|
| 580 |
+
"last4_hash": "b8b2994c7b8b89680041f24fbb0d10dc76e072cbefb1a342fb3d7cf4b002bec6"
|
| 581 |
+
},
|
| 582 |
+
{
|
| 583 |
+
"instrument_id": "PAY0117",
|
| 584 |
+
"type": "card",
|
| 585 |
+
"last4_hash": "70e8d52a9b4616e728112408ceca7abd9507e93f30e958ecb09f6ea607d99d06"
|
| 586 |
+
},
|
| 587 |
+
{
|
| 588 |
+
"instrument_id": "PAY0118",
|
| 589 |
+
"type": "card",
|
| 590 |
+
"last4_hash": "5b33003a928495b97792ac286d477b54dd20eb773c74ae2fb3653bc5950ad6dd"
|
| 591 |
+
},
|
| 592 |
+
{
|
| 593 |
+
"instrument_id": "PAY0119",
|
| 594 |
+
"type": "card",
|
| 595 |
+
"last4_hash": "173deaaf2f52bf79f028106fdbb995142cd7d77fc8b15cfa2a82d93c13f76f3c"
|
| 596 |
+
},
|
| 597 |
+
{
|
| 598 |
+
"instrument_id": "PAY0120",
|
| 599 |
+
"type": "card",
|
| 600 |
+
"last4_hash": "80ae95e050f70cddb9725d71e8fa265f27ecb95db2613461fd6d1c085f2dab0c"
|
| 601 |
+
},
|
| 602 |
+
{
|
| 603 |
+
"instrument_id": "PAY0121",
|
| 604 |
+
"type": "card",
|
| 605 |
+
"last4_hash": "e12868d1f3963e0e1129b3a6442b6d3d7d8e4eb7e27d34348b29523f0ae37748"
|
| 606 |
+
},
|
| 607 |
+
{
|
| 608 |
+
"instrument_id": "PAY0122",
|
| 609 |
+
"type": "upi",
|
| 610 |
+
"last4_hash": "d21c586a53e9762ebe64b80b124b6b6f00e3549ec304f6d4aa8d0c65c02e8704"
|
| 611 |
+
},
|
| 612 |
+
{
|
| 613 |
+
"instrument_id": "PAY0123",
|
| 614 |
+
"type": "card",
|
| 615 |
+
"last4_hash": "2c6b7bf2a4ef2fc87ce92b7097c6c477825b898877f3c7406c9609f7e5ddb8e6"
|
| 616 |
+
},
|
| 617 |
+
{
|
| 618 |
+
"instrument_id": "PAY0124",
|
| 619 |
+
"type": "upi",
|
| 620 |
+
"last4_hash": "204674eb811a35ba00447c090c783777da3a020da4f14a3ee0f335e1cfb15481"
|
| 621 |
+
},
|
| 622 |
+
{
|
| 623 |
+
"instrument_id": "PAY0125",
|
| 624 |
+
"type": "upi",
|
| 625 |
+
"last4_hash": "63892e272bb1f0641fd09ad8fe6a1e8192c901dabe381ae4406f9864d6ae33af"
|
| 626 |
+
},
|
| 627 |
+
{
|
| 628 |
+
"instrument_id": "PAY0126",
|
| 629 |
+
"type": "upi",
|
| 630 |
+
"last4_hash": "5aed8261495824595ecc62f78b62a0a2d4db3cdee22034652d7da89ca7c3e5f5"
|
| 631 |
+
},
|
| 632 |
+
{
|
| 633 |
+
"instrument_id": "PAY0127",
|
| 634 |
+
"type": "card",
|
| 635 |
+
"last4_hash": "bc805497f86694cef2e1cf6df62989cb818f69a80f4fb170e5b7cd66aef5d64b"
|
| 636 |
+
},
|
| 637 |
+
{
|
| 638 |
+
"instrument_id": "PAY0128",
|
| 639 |
+
"type": "card",
|
| 640 |
+
"last4_hash": "3b040bdd21634e7a8d08619c89e37e4c8430e955fc88e3888b1c13bda6ec32f3"
|
| 641 |
+
},
|
| 642 |
+
{
|
| 643 |
+
"instrument_id": "PAY0129",
|
| 644 |
+
"type": "card",
|
| 645 |
+
"last4_hash": "3141d9c749e88ee5550192703c3e025a9b3446ec543f17a923cb24e7b61dfece"
|
| 646 |
+
},
|
| 647 |
+
{
|
| 648 |
+
"instrument_id": "PAY0130",
|
| 649 |
+
"type": "upi",
|
| 650 |
+
"last4_hash": "cf14794b7a9b6f825719bdda892b9045b829a28de7b72f97b5cff93acd8d1433"
|
| 651 |
+
},
|
| 652 |
+
{
|
| 653 |
+
"instrument_id": "PAY0131",
|
| 654 |
+
"type": "upi",
|
| 655 |
+
"last4_hash": "ce048a27aa4bec0b76ec7ae0641f3922a3aa58625051690fedf4994419c320db"
|
| 656 |
+
},
|
| 657 |
+
{
|
| 658 |
+
"instrument_id": "PAY0132",
|
| 659 |
+
"type": "upi",
|
| 660 |
+
"last4_hash": "0c9bd7be38dee8ce8a5b02f67b9d656793177d9849808032ad412708b018159c"
|
| 661 |
+
},
|
| 662 |
+
{
|
| 663 |
+
"instrument_id": "PAY0133",
|
| 664 |
+
"type": "card",
|
| 665 |
+
"last4_hash": "e0b372a86dbfe71bdb7bf19790cacabd2ad2c4d145087a94d842fe6ffe2eef8b"
|
| 666 |
+
},
|
| 667 |
+
{
|
| 668 |
+
"instrument_id": "PAY0134",
|
| 669 |
+
"type": "card",
|
| 670 |
+
"last4_hash": "154d72ced7915c97e73258a22c08e202e8974629b1847c87d516fa6e692672a4"
|
| 671 |
+
},
|
| 672 |
+
{
|
| 673 |
+
"instrument_id": "PAY0135",
|
| 674 |
+
"type": "upi",
|
| 675 |
+
"last4_hash": "a8abbe1f7b05c096d4875eb9a7bdc9d8b539bd230ee8a1e02d2346bb91c2c080"
|
| 676 |
+
},
|
| 677 |
+
{
|
| 678 |
+
"instrument_id": "PAY0136",
|
| 679 |
+
"type": "card",
|
| 680 |
+
"last4_hash": "aeba47c17ca09557808c333b49af210a0209aff6b4334fa7192aaed69c5f36dd"
|
| 681 |
+
},
|
| 682 |
+
{
|
| 683 |
+
"instrument_id": "PAY0137",
|
| 684 |
+
"type": "upi",
|
| 685 |
+
"last4_hash": "708cdcc0590a516387b0a516be7719fc8ad25d5653c6d22cf3ae6d690cf9d126"
|
| 686 |
+
},
|
| 687 |
+
{
|
| 688 |
+
"instrument_id": "PAY0138",
|
| 689 |
+
"type": "upi",
|
| 690 |
+
"last4_hash": "2013ea8b947491e0829514c81c52326ae69a14c1cc664630584252db2c63de82"
|
| 691 |
+
},
|
| 692 |
+
{
|
| 693 |
+
"instrument_id": "PAY0139",
|
| 694 |
+
"type": "upi",
|
| 695 |
+
"last4_hash": "817856dcff013f1e9f1a8edb78c4e86baaba6fcf7d80b6d941a1c4cf888cc32b"
|
| 696 |
+
},
|
| 697 |
+
{
|
| 698 |
+
"instrument_id": "PAY0140",
|
| 699 |
+
"type": "card",
|
| 700 |
+
"last4_hash": "0287240ca63d3c73cb1231b69fce2315e999f3fce091140acf6ec1c6e5ba094f"
|
| 701 |
+
},
|
| 702 |
+
{
|
| 703 |
+
"instrument_id": "PAY0141",
|
| 704 |
+
"type": "upi",
|
| 705 |
+
"last4_hash": "6de4e9cef3c5ae3c7fffbac619b70bfd7a22202d2e509456cbcad3b2fed89b67"
|
| 706 |
+
},
|
| 707 |
+
{
|
| 708 |
+
"instrument_id": "PAY0142",
|
| 709 |
+
"type": "card",
|
| 710 |
+
"last4_hash": "fc2cd6cb85339b6c15848a08e7713f73cf55148b21cb32fb78cdf5ff44c90634"
|
| 711 |
+
},
|
| 712 |
+
{
|
| 713 |
+
"instrument_id": "PAY0143",
|
| 714 |
+
"type": "upi",
|
| 715 |
+
"last4_hash": "771e6ad04e8013ba5c223e96eb0bc38e3204a962bceac2aa4b84103c40472d8a"
|
| 716 |
+
},
|
| 717 |
+
{
|
| 718 |
+
"instrument_id": "PAY0144",
|
| 719 |
+
"type": "card",
|
| 720 |
+
"last4_hash": "e209f7b7bfe0f9ccd9c6b5d8aa497b55b76812f56ff0cddd6fc9f703f17192b3"
|
| 721 |
+
},
|
| 722 |
+
{
|
| 723 |
+
"instrument_id": "PAY0145",
|
| 724 |
+
"type": "upi",
|
| 725 |
+
"last4_hash": "21ed781581839a96745dd321ed9348facf34331e26259f530953741a22503ece"
|
| 726 |
+
},
|
| 727 |
+
{
|
| 728 |
+
"instrument_id": "PAY0146",
|
| 729 |
+
"type": "upi",
|
| 730 |
+
"last4_hash": "d4f4ef122bb30e6818329d5fda158711c5b9384bc86a8c7bcfe7cd85435c8a6d"
|
| 731 |
+
},
|
| 732 |
+
{
|
| 733 |
+
"instrument_id": "PAY0147",
|
| 734 |
+
"type": "card",
|
| 735 |
+
"last4_hash": "79c56d57697ddb331d1e1a1b62fa940d1579447b35221a7f6b68924dfce14244"
|
| 736 |
+
},
|
| 737 |
+
{
|
| 738 |
+
"instrument_id": "PAY0148",
|
| 739 |
+
"type": "card",
|
| 740 |
+
"last4_hash": "0c921bbabc0503bc23abfa92b5a4dab3c14f362b16096238fb4a71c279bc0eeb"
|
| 741 |
+
},
|
| 742 |
+
{
|
| 743 |
+
"instrument_id": "PAY0149",
|
| 744 |
+
"type": "upi",
|
| 745 |
+
"last4_hash": "0405a13200aa02e63862cbfd66a5beb1129f206eab06fe05ec0b8dc0217825b0"
|
| 746 |
+
},
|
| 747 |
+
{
|
| 748 |
+
"instrument_id": "PAY0150",
|
| 749 |
+
"type": "upi",
|
| 750 |
+
"last4_hash": "2be4f967ce834c65b10d2f91f45ab8fbfe083b468a6247363056ff29091d34bc"
|
| 751 |
+
},
|
| 752 |
+
{
|
| 753 |
+
"instrument_id": "PAY0151",
|
| 754 |
+
"type": "upi",
|
| 755 |
+
"last4_hash": "a5382c5d33b1be5721daf7b45e98810db32b230b67f5ffe23287be1480a6068c"
|
| 756 |
+
},
|
| 757 |
+
{
|
| 758 |
+
"instrument_id": "PAY0152",
|
| 759 |
+
"type": "upi",
|
| 760 |
+
"last4_hash": "09a9221450d87d97c48b18fde1c53ca2214c426f90d2207a3d66c7e65b6d3da8"
|
| 761 |
+
},
|
| 762 |
+
{
|
| 763 |
+
"instrument_id": "PAY0153",
|
| 764 |
+
"type": "upi",
|
| 765 |
+
"last4_hash": "03438f89353aee02887a151bd0d762f4bd10f7ec9d9d0e4536df399c92ae4103"
|
| 766 |
+
},
|
| 767 |
+
{
|
| 768 |
+
"instrument_id": "PAY0154",
|
| 769 |
+
"type": "upi",
|
| 770 |
+
"last4_hash": "f802afc52a957e1ed75ee48fbd23ee909a57f3253aaa28ee9080b1a6ae11e48e"
|
| 771 |
+
},
|
| 772 |
+
{
|
| 773 |
+
"instrument_id": "PAY0155",
|
| 774 |
+
"type": "card",
|
| 775 |
+
"last4_hash": "5078264a209e1ee0e3a8a46a11d840dfd1879500f7fd02aef1f8b6a2276a5be9"
|
| 776 |
+
},
|
| 777 |
+
{
|
| 778 |
+
"instrument_id": "PAY0156",
|
| 779 |
+
"type": "upi",
|
| 780 |
+
"last4_hash": "b7b90855c2dce7710c8e11ac3de1bbaea0656042dae41ec753f843a8ff372c9f"
|
| 781 |
+
},
|
| 782 |
+
{
|
| 783 |
+
"instrument_id": "PAY0157",
|
| 784 |
+
"type": "upi",
|
| 785 |
+
"last4_hash": "313b93b4b6589d56dcc1baaaccca223a337628b43d2ef51af234b03c242b9895"
|
| 786 |
+
},
|
| 787 |
+
{
|
| 788 |
+
"instrument_id": "PAY0158",
|
| 789 |
+
"type": "card",
|
| 790 |
+
"last4_hash": "02be6761f02f2291c1fe54c103440f7b9ba65da74dc84f1e08736d7a67824643"
|
| 791 |
+
},
|
| 792 |
+
{
|
| 793 |
+
"instrument_id": "PAY0159",
|
| 794 |
+
"type": "upi",
|
| 795 |
+
"last4_hash": "11e62f15fe7bc8ee83afaf873048a419a8aea5ef444c49e73bc86bd3968b9d01"
|
| 796 |
+
},
|
| 797 |
+
{
|
| 798 |
+
"instrument_id": "PAY0160",
|
| 799 |
+
"type": "upi",
|
| 800 |
+
"last4_hash": "541823e83415b95589e462d2508c4f67104b90322e542373205b7c62d1ed4468"
|
| 801 |
+
},
|
| 802 |
+
{
|
| 803 |
+
"instrument_id": "PAY0161",
|
| 804 |
+
"type": "card",
|
| 805 |
+
"last4_hash": "b4eed30197a01d2d80fb165bd90e21ebe54ec513216a8f03a3ed263d98f00f03"
|
| 806 |
+
},
|
| 807 |
+
{
|
| 808 |
+
"instrument_id": "PAY0162",
|
| 809 |
+
"type": "upi",
|
| 810 |
+
"last4_hash": "ead77f513269818b47d13226728ff3c031ead406abb8d0d70c247da00aa9eb75"
|
| 811 |
+
},
|
| 812 |
+
{
|
| 813 |
+
"instrument_id": "PAY0163",
|
| 814 |
+
"type": "card",
|
| 815 |
+
"last4_hash": "deb4666a75564b9fceea3b10aab44ec24089d914d7bb262b51145392856e3714"
|
| 816 |
+
},
|
| 817 |
+
{
|
| 818 |
+
"instrument_id": "PAY0164",
|
| 819 |
+
"type": "card",
|
| 820 |
+
"last4_hash": "b5a711fe7e92051816302057edc97e9e4a471802b96e379e8d382b4e9f248478"
|
| 821 |
+
},
|
| 822 |
+
{
|
| 823 |
+
"instrument_id": "PAY0165",
|
| 824 |
+
"type": "upi",
|
| 825 |
+
"last4_hash": "0248b9e54ef1e41897a3198b509166905ab9d941758886bbfb03bd72449bf63e"
|
| 826 |
+
},
|
| 827 |
+
{
|
| 828 |
+
"instrument_id": "PAY0166",
|
| 829 |
+
"type": "upi",
|
| 830 |
+
"last4_hash": "22d3ae0abdf720e6adb3f0e4b81366e3fbeee65658825bf2f10f43fa92c1f298"
|
| 831 |
+
},
|
| 832 |
+
{
|
| 833 |
+
"instrument_id": "PAY0167",
|
| 834 |
+
"type": "upi",
|
| 835 |
+
"last4_hash": "7ceb89878579e1cb86a8fd6fb4a5cc8abad8660793354ee9b9d0371c3fb4f924"
|
| 836 |
+
},
|
| 837 |
+
{
|
| 838 |
+
"instrument_id": "PAY0168",
|
| 839 |
+
"type": "upi",
|
| 840 |
+
"last4_hash": "de7217c8927ffa8f8f97c5871b9c2c1d5f543b115cc71aa30150439c42e5fb71"
|
| 841 |
+
},
|
| 842 |
+
{
|
| 843 |
+
"instrument_id": "PAY0169",
|
| 844 |
+
"type": "card",
|
| 845 |
+
"last4_hash": "28af0d12785efe04f62544cbd49382ebbce76256e800fecaeb4e4b7871d402bb"
|
| 846 |
+
},
|
| 847 |
+
{
|
| 848 |
+
"instrument_id": "PAY0170",
|
| 849 |
+
"type": "card",
|
| 850 |
+
"last4_hash": "4708f9c61a5e58b72774193f69bf37442423a4d2673e1f2cdc3f07f2614aba5d"
|
| 851 |
+
},
|
| 852 |
+
{
|
| 853 |
+
"instrument_id": "PAY0171",
|
| 854 |
+
"type": "card",
|
| 855 |
+
"last4_hash": "fa2fd37dfe0f812d3dc55fb445a1a4d04b95032b6753f0d4943313655bd3f8e8"
|
| 856 |
+
},
|
| 857 |
+
{
|
| 858 |
+
"instrument_id": "PAY0172",
|
| 859 |
+
"type": "upi",
|
| 860 |
+
"last4_hash": "01f955f2f2122036a9cc5ed2a780461307978fddff83f39da70b6d63a4d2b2e8"
|
| 861 |
+
},
|
| 862 |
+
{
|
| 863 |
+
"instrument_id": "PAY0173",
|
| 864 |
+
"type": "card",
|
| 865 |
+
"last4_hash": "747edaa66dec70dc1256e51b15be0fe658902a7af7a427db024df3431678152c"
|
| 866 |
+
},
|
| 867 |
+
{
|
| 868 |
+
"instrument_id": "PAY0174",
|
| 869 |
+
"type": "upi",
|
| 870 |
+
"last4_hash": "a81e1a8dde5c3b93cdb41a6b6cc6648a5131af5cd3ebe6b79ebb6fe97c3b418e"
|
| 871 |
+
},
|
| 872 |
+
{
|
| 873 |
+
"instrument_id": "PAY0175",
|
| 874 |
+
"type": "upi",
|
| 875 |
+
"last4_hash": "b9447cbd1457eb1c2caded2e63e3a8fd05d507415f6ad4afcf49ccc128dc5697"
|
| 876 |
+
},
|
| 877 |
+
{
|
| 878 |
+
"instrument_id": "PAY0176",
|
| 879 |
+
"type": "card",
|
| 880 |
+
"last4_hash": "228971770cc3111e6ce32b17a5ab6ae7c0ba993634ac8d83fd32ec6e91615995"
|
| 881 |
+
},
|
| 882 |
+
{
|
| 883 |
+
"instrument_id": "PAY0177",
|
| 884 |
+
"type": "upi",
|
| 885 |
+
"last4_hash": "6f7cef78841fc154d6bfb8be9bf2a47e83608cdac4a926d63dc80ffd83a66378"
|
| 886 |
+
},
|
| 887 |
+
{
|
| 888 |
+
"instrument_id": "PAY0178",
|
| 889 |
+
"type": "card",
|
| 890 |
+
"last4_hash": "80e107ee3ba12129c178396a4b3a4c502210b378e8b85d3b14087d7becbcfde7"
|
| 891 |
+
},
|
| 892 |
+
{
|
| 893 |
+
"instrument_id": "PAY0179",
|
| 894 |
+
"type": "card",
|
| 895 |
+
"last4_hash": "0c064516a0ec5302a2d2c2c270b509ca7a100b012445086f8900891310bdb9f3"
|
| 896 |
+
},
|
| 897 |
+
{
|
| 898 |
+
"instrument_id": "PAY0180",
|
| 899 |
+
"type": "upi",
|
| 900 |
+
"last4_hash": "f4fcc2f7dccbda17aa92ab8605e0fdd2f9861670fb8c5738241a029c8fc617ae"
|
| 901 |
+
},
|
| 902 |
+
{
|
| 903 |
+
"instrument_id": "PAY0181",
|
| 904 |
+
"type": "upi",
|
| 905 |
+
"last4_hash": "cb898ba3b47402b2495eb12f3902cb3e82775f59b3a8d9f726c5c9ebb8016352"
|
| 906 |
+
},
|
| 907 |
+
{
|
| 908 |
+
"instrument_id": "PAY0182",
|
| 909 |
+
"type": "upi",
|
| 910 |
+
"last4_hash": "7c27c01a452ad2badbecfd322f506a6548830e9a8e35c981c14b670cd7f70c95"
|
| 911 |
+
},
|
| 912 |
+
{
|
| 913 |
+
"instrument_id": "PAY0183",
|
| 914 |
+
"type": "upi",
|
| 915 |
+
"last4_hash": "9cc2c4fccfd99215e979acb8954a605c5c78b62013aa22c501bb8b8a214114c6"
|
| 916 |
+
},
|
| 917 |
+
{
|
| 918 |
+
"instrument_id": "PAY0184",
|
| 919 |
+
"type": "upi",
|
| 920 |
+
"last4_hash": "8dcedc831b40346fadc5ca491a72ba1dad3f3b68ac3296ef7ef13bdb9082b92b"
|
| 921 |
+
},
|
| 922 |
+
{
|
| 923 |
+
"instrument_id": "PAY0185",
|
| 924 |
+
"type": "upi",
|
| 925 |
+
"last4_hash": "a724557fb7d3f2c6838beccb4ad12f8be4e5d8383529b8c7f53ab4544c085ea9"
|
| 926 |
+
},
|
| 927 |
+
{
|
| 928 |
+
"instrument_id": "PAY0186",
|
| 929 |
+
"type": "upi",
|
| 930 |
+
"last4_hash": "49d223c477447c4bdb7061d8b342eb725eed77cf8e8a0c2e99e19328fd7ca39d"
|
| 931 |
+
},
|
| 932 |
+
{
|
| 933 |
+
"instrument_id": "PAY0187",
|
| 934 |
+
"type": "upi",
|
| 935 |
+
"last4_hash": "bf3433d6d20b35fe62cb7b46f00c64ab984686f7a708ce00277ee3c26fae51f2"
|
| 936 |
+
},
|
| 937 |
+
{
|
| 938 |
+
"instrument_id": "PAY0188",
|
| 939 |
+
"type": "upi",
|
| 940 |
+
"last4_hash": "a992b986fc27b23a80c1c673ecfbbbc8957647865f50c63d1c30be78311f0cce"
|
| 941 |
+
},
|
| 942 |
+
{
|
| 943 |
+
"instrument_id": "PAY0189",
|
| 944 |
+
"type": "upi",
|
| 945 |
+
"last4_hash": "04002abb101a19fcabea0f4b87b8b79fe73dee47233d463fcbd9e65d17a6ef8d"
|
| 946 |
+
},
|
| 947 |
+
{
|
| 948 |
+
"instrument_id": "PAY0190",
|
| 949 |
+
"type": "card",
|
| 950 |
+
"last4_hash": "a24a6dd3d30dc6b15f3e9ea581805d199270323842004e03ddf3c932478b1f11"
|
| 951 |
+
},
|
| 952 |
+
{
|
| 953 |
+
"instrument_id": "PAY0191",
|
| 954 |
+
"type": "card",
|
| 955 |
+
"last4_hash": "35c7a070e74b4380b5cb8cb0b68f3a06b331e4477b720c43df7af5c4c36fd2c0"
|
| 956 |
+
},
|
| 957 |
+
{
|
| 958 |
+
"instrument_id": "PAY0192",
|
| 959 |
+
"type": "card",
|
| 960 |
+
"last4_hash": "5c6ab6a10221871a18b25558a77a99d1324732e4d5ac403e0bed5d85acba24fd"
|
| 961 |
+
},
|
| 962 |
+
{
|
| 963 |
+
"instrument_id": "PAY0193",
|
| 964 |
+
"type": "card",
|
| 965 |
+
"last4_hash": "1f61c05e5a94a1995a4dbaf9e3b9280190246279d7d9a0f229b16627fe15845a"
|
| 966 |
+
},
|
| 967 |
+
{
|
| 968 |
+
"instrument_id": "PAY0194",
|
| 969 |
+
"type": "card",
|
| 970 |
+
"last4_hash": "1628e107773c273d5509e2051386207d1b75f1dc3a97e6e4844e132837fae396"
|
| 971 |
+
},
|
| 972 |
+
{
|
| 973 |
+
"instrument_id": "PAY0195",
|
| 974 |
+
"type": "upi",
|
| 975 |
+
"last4_hash": "246b0ab60280d23005e7aaf3941fced7b84e933dd5e05be3b404e90dea26368d"
|
| 976 |
+
},
|
| 977 |
+
{
|
| 978 |
+
"instrument_id": "PAY0196",
|
| 979 |
+
"type": "upi",
|
| 980 |
+
"last4_hash": "8aa885ab588858db215e6b851dab0bc5ea5c2f058a0cc193501e56d30e5c6143"
|
| 981 |
+
},
|
| 982 |
+
{
|
| 983 |
+
"instrument_id": "PAY0197",
|
| 984 |
+
"type": "card",
|
| 985 |
+
"last4_hash": "3b96b9d2dc7cd7d338d73571d7c46eefe383955e4427d8a2079f4c41b374d988"
|
| 986 |
+
},
|
| 987 |
+
{
|
| 988 |
+
"instrument_id": "PAY0198",
|
| 989 |
+
"type": "upi",
|
| 990 |
+
"last4_hash": "847cf2f668d88b1db87b3e8a2e991510040236da249d12e2beaa36c15e34dc09"
|
| 991 |
+
},
|
| 992 |
+
{
|
| 993 |
+
"instrument_id": "PAY0199",
|
| 994 |
+
"type": "card",
|
| 995 |
+
"last4_hash": "153de641ea0557acad28b609f949ec7ad909c0168b9af1d810fcf26e45e7e428"
|
| 996 |
+
},
|
| 997 |
+
{
|
| 998 |
+
"instrument_id": "PAY0200",
|
| 999 |
+
"type": "card",
|
| 1000 |
+
"last4_hash": "1adb67461a4c3739283e6b97ba7984e0d4b024a4dcbf1f341c389f0c581fde4a"
|
| 1001 |
+
},
|
| 1002 |
+
{
|
| 1003 |
+
"instrument_id": "PAY0201",
|
| 1004 |
+
"type": "card",
|
| 1005 |
+
"last4_hash": "5f9e3d4a0fa6f44a726c146ead2a301eb4026ae67b06cc5971210e5d749762b0"
|
| 1006 |
+
},
|
| 1007 |
+
{
|
| 1008 |
+
"instrument_id": "PAY0202",
|
| 1009 |
+
"type": "card",
|
| 1010 |
+
"last4_hash": "647011fb41f77ae398ca6e97e8ee589270760023219a9a1f6d6eaf0055c75c8d"
|
| 1011 |
+
},
|
| 1012 |
+
{
|
| 1013 |
+
"instrument_id": "PAY0203",
|
| 1014 |
+
"type": "card",
|
| 1015 |
+
"last4_hash": "baa8a6ecbabbd5ef02222983b23a4fbd1d794cca68c767e07d67af2d9f46e737"
|
| 1016 |
+
},
|
| 1017 |
+
{
|
| 1018 |
+
"instrument_id": "PAY0204",
|
| 1019 |
+
"type": "upi",
|
| 1020 |
+
"last4_hash": "c6e1a3b42f1021a8897367a8ecc5906409856ad96b3429d9209f56abb44a1773"
|
| 1021 |
+
},
|
| 1022 |
+
{
|
| 1023 |
+
"instrument_id": "PAY0205",
|
| 1024 |
+
"type": "card",
|
| 1025 |
+
"last4_hash": "ee4f8781fe28ccc751937330fc03ce427460b7ad4a0cf741019863eba4e53a6c"
|
| 1026 |
+
},
|
| 1027 |
+
{
|
| 1028 |
+
"instrument_id": "PAY0206",
|
| 1029 |
+
"type": "card",
|
| 1030 |
+
"last4_hash": "15197cf7214b58e67cae565e573ffd9aa44bcb81f8ee5d7185dfe8da0a16ef43"
|
| 1031 |
+
},
|
| 1032 |
+
{
|
| 1033 |
+
"instrument_id": "PAY0207",
|
| 1034 |
+
"type": "upi",
|
| 1035 |
+
"last4_hash": "46f292108babd9c0500ef511728ac5099eb586c255eebc72ab2499c6df520384"
|
| 1036 |
+
},
|
| 1037 |
+
{
|
| 1038 |
+
"instrument_id": "PAY0208",
|
| 1039 |
+
"type": "upi",
|
| 1040 |
+
"last4_hash": "331160121aa00fa6b8954bf8b72f9dcfead4093d79b1ed0e2b50379b9e53479c"
|
| 1041 |
+
},
|
| 1042 |
+
{
|
| 1043 |
+
"instrument_id": "PAY0209",
|
| 1044 |
+
"type": "upi",
|
| 1045 |
+
"last4_hash": "8f3cd17919924b85057eace5ba32fda81fff13141c996693288487601ea4a717"
|
| 1046 |
+
},
|
| 1047 |
+
{
|
| 1048 |
+
"instrument_id": "PAY0210",
|
| 1049 |
+
"type": "upi",
|
| 1050 |
+
"last4_hash": "d7defea67028f03ef163788c9c2d89392f5b26588771452c170625109f2f3406"
|
| 1051 |
+
},
|
| 1052 |
+
{
|
| 1053 |
+
"instrument_id": "PAY0211",
|
| 1054 |
+
"type": "upi",
|
| 1055 |
+
"last4_hash": "6588bc3e00cce5a692f811a8c1e96c9c8d22168939143dc6713258fdd4da54e2"
|
| 1056 |
+
},
|
| 1057 |
+
{
|
| 1058 |
+
"instrument_id": "PAY0212",
|
| 1059 |
+
"type": "card",
|
| 1060 |
+
"last4_hash": "9e645831962e43f534afd60532328ba5ab4eefea6e73765fb9690e4d395112f8"
|
| 1061 |
+
},
|
| 1062 |
+
{
|
| 1063 |
+
"instrument_id": "PAY0213",
|
| 1064 |
+
"type": "upi",
|
| 1065 |
+
"last4_hash": "fcbaac549e7b8ade5d0f9826413f5bd2c0beb47df11d76c889c9b417d2446295"
|
| 1066 |
+
},
|
| 1067 |
+
{
|
| 1068 |
+
"instrument_id": "PAY0214",
|
| 1069 |
+
"type": "upi",
|
| 1070 |
+
"last4_hash": "9fd6e8b29087ba21fabbc6c46979750b8008ed05ba77b9e3ff032b3bd3d5992e"
|
| 1071 |
+
},
|
| 1072 |
+
{
|
| 1073 |
+
"instrument_id": "PAY0215",
|
| 1074 |
+
"type": "card",
|
| 1075 |
+
"last4_hash": "06c973e49be9fdbfdaa84a397b35b05baceec93d5ea35e4cba2d6eaecf97700f"
|
| 1076 |
+
},
|
| 1077 |
+
{
|
| 1078 |
+
"instrument_id": "PAY0216",
|
| 1079 |
+
"type": "upi",
|
| 1080 |
+
"last4_hash": "c4af926b851b86d5aeb3264a3f62db4b4944d664be2b9570512764afd8223b18"
|
| 1081 |
+
},
|
| 1082 |
+
{
|
| 1083 |
+
"instrument_id": "PAY0217",
|
| 1084 |
+
"type": "upi",
|
| 1085 |
+
"last4_hash": "a276a4e96e2b4b8f8ce5ed09536cb5cd0df9b7c12351e00aa839c0d209b8a175"
|
| 1086 |
+
},
|
| 1087 |
+
{
|
| 1088 |
+
"instrument_id": "PAY0218",
|
| 1089 |
+
"type": "card",
|
| 1090 |
+
"last4_hash": "8a80efe71cf1850186e908f82e61d9ab6c95889d927cfec59d69f8aeb0673ff7"
|
| 1091 |
+
},
|
| 1092 |
+
{
|
| 1093 |
+
"instrument_id": "PAY0219",
|
| 1094 |
+
"type": "card",
|
| 1095 |
+
"last4_hash": "2a0400a50c04a5c64e7818f4920059acbedcc2a193e715b0f0310923405b36e8"
|
| 1096 |
+
},
|
| 1097 |
+
{
|
| 1098 |
+
"instrument_id": "PAY0220",
|
| 1099 |
+
"type": "upi",
|
| 1100 |
+
"last4_hash": "29a217fcc45f734ac6d51f8c61d010cb40b8fb2b73e3d626b6ff3772c113a7a0"
|
| 1101 |
+
},
|
| 1102 |
+
{
|
| 1103 |
+
"instrument_id": "PAY0221",
|
| 1104 |
+
"type": "card",
|
| 1105 |
+
"last4_hash": "b6cfb9e281f64066b6cb04d5d9108276f4e3ecbc68c860831c481ba932591673"
|
| 1106 |
+
},
|
| 1107 |
+
{
|
| 1108 |
+
"instrument_id": "PAY0222",
|
| 1109 |
+
"type": "card",
|
| 1110 |
+
"last4_hash": "2a2ea325451e51e5f810010975fad2f66ad56342d85586d74bc0a2b3e31c8356"
|
| 1111 |
+
},
|
| 1112 |
+
{
|
| 1113 |
+
"instrument_id": "PAY0223",
|
| 1114 |
+
"type": "card",
|
| 1115 |
+
"last4_hash": "8d3498f1ebcbd5f1bd973e184059a6f0e06812c898d4375da115bdedff492d0f"
|
| 1116 |
+
},
|
| 1117 |
+
{
|
| 1118 |
+
"instrument_id": "PAY0224",
|
| 1119 |
+
"type": "upi",
|
| 1120 |
+
"last4_hash": "f36a35c022224e38de6430182e0a0fa554ce384997ce1086599f6317e832d9be"
|
| 1121 |
+
},
|
| 1122 |
+
{
|
| 1123 |
+
"instrument_id": "PAY0225",
|
| 1124 |
+
"type": "upi",
|
| 1125 |
+
"last4_hash": "1a18b0a3dde64484d80eddbf00483e3681e94109324ae8368917e5ec79d0b634"
|
| 1126 |
+
},
|
| 1127 |
+
{
|
| 1128 |
+
"instrument_id": "PAY0226",
|
| 1129 |
+
"type": "upi",
|
| 1130 |
+
"last4_hash": "1991e7b38912c102c0207ee57f8fa9a5ef96f1e93ae277d7e6bb0e35d8a23483"
|
| 1131 |
+
},
|
| 1132 |
+
{
|
| 1133 |
+
"instrument_id": "PAY0227",
|
| 1134 |
+
"type": "upi",
|
| 1135 |
+
"last4_hash": "841bed395f6f9ce6dc0d396f472fc2e31dab0dcd0def14798686d8518e6c34fb"
|
| 1136 |
+
},
|
| 1137 |
+
{
|
| 1138 |
+
"instrument_id": "PAY0228",
|
| 1139 |
+
"type": "upi",
|
| 1140 |
+
"last4_hash": "96f227129556c6f3080ebfe4619c520c6ee640fec486c406dc28cd95da33b3fd"
|
| 1141 |
+
},
|
| 1142 |
+
{
|
| 1143 |
+
"instrument_id": "PAY0229",
|
| 1144 |
+
"type": "upi",
|
| 1145 |
+
"last4_hash": "cc4a428f3be823f76b73d2e772096feb84244db682b479d1038d58d0fa278b30"
|
| 1146 |
+
},
|
| 1147 |
+
{
|
| 1148 |
+
"instrument_id": "PAY0230",
|
| 1149 |
+
"type": "card",
|
| 1150 |
+
"last4_hash": "63727ee4cff30e597899af01a4a355ea91e54c9a055e1da18e25b89dfa90352c"
|
| 1151 |
+
},
|
| 1152 |
+
{
|
| 1153 |
+
"instrument_id": "PAY0231",
|
| 1154 |
+
"type": "card",
|
| 1155 |
+
"last4_hash": "3d19e945ed5a25a399da3036bc862275296544218de8260d47a5ad3d9b853af4"
|
| 1156 |
+
},
|
| 1157 |
+
{
|
| 1158 |
+
"instrument_id": "PAY0232",
|
| 1159 |
+
"type": "upi",
|
| 1160 |
+
"last4_hash": "5ad4c5cccee58bdc87eda85a48e67559432b3ebb4092d49cb142d8ed206bfc7c"
|
| 1161 |
+
},
|
| 1162 |
+
{
|
| 1163 |
+
"instrument_id": "PAY0233",
|
| 1164 |
+
"type": "card",
|
| 1165 |
+
"last4_hash": "a948b46c0f1890667de7b60fb490c573d60c647158f91193dd915afde693529c"
|
| 1166 |
+
},
|
| 1167 |
+
{
|
| 1168 |
+
"instrument_id": "PAY0234",
|
| 1169 |
+
"type": "card",
|
| 1170 |
+
"last4_hash": "f23784f17468ea72b2dd3fd4e4faecb40ccdd24f39584fcd283c391d4faf87c8"
|
| 1171 |
+
},
|
| 1172 |
+
{
|
| 1173 |
+
"instrument_id": "PAY0235",
|
| 1174 |
+
"type": "card",
|
| 1175 |
+
"last4_hash": "739dbef65f3b1e4117d7bdb2a76efa5b91943f8f26ab74a7c1cad9feb0324129"
|
| 1176 |
+
},
|
| 1177 |
+
{
|
| 1178 |
+
"instrument_id": "PAY0236",
|
| 1179 |
+
"type": "card",
|
| 1180 |
+
"last4_hash": "93352a86094a964ef548e72c79a9f6187b7f561773c31f3371e86ecffe9a4dd9"
|
| 1181 |
+
},
|
| 1182 |
+
{
|
| 1183 |
+
"instrument_id": "PAY0237",
|
| 1184 |
+
"type": "upi",
|
| 1185 |
+
"last4_hash": "9569757a6fce9018ec528b20fc71028be89e24df343779ff25a281d38a330a3d"
|
| 1186 |
+
},
|
| 1187 |
+
{
|
| 1188 |
+
"instrument_id": "PAY0238",
|
| 1189 |
+
"type": "upi",
|
| 1190 |
+
"last4_hash": "28ef70984a8eb80ae8606716d8824302fa6e616bb525846f7088e774ce66684c"
|
| 1191 |
+
},
|
| 1192 |
+
{
|
| 1193 |
+
"instrument_id": "PAY0239",
|
| 1194 |
+
"type": "upi",
|
| 1195 |
+
"last4_hash": "b44cb9e82dd50599a74e865bd98505ff40dd1f873ff236bbac53b7982a678678"
|
| 1196 |
+
},
|
| 1197 |
+
{
|
| 1198 |
+
"instrument_id": "PAY0240",
|
| 1199 |
+
"type": "card",
|
| 1200 |
+
"last4_hash": "7b4c3b903da50f31cacf58554525088f6ca687144330569605c8de3a404d2ce6"
|
| 1201 |
+
},
|
| 1202 |
+
{
|
| 1203 |
+
"instrument_id": "PAY0241",
|
| 1204 |
+
"type": "upi",
|
| 1205 |
+
"last4_hash": "0bf788aaa8956e3115a533477b96a937c64a7cd80f318540fb2ce36ebd4fcf32"
|
| 1206 |
+
},
|
| 1207 |
+
{
|
| 1208 |
+
"instrument_id": "PAY0242",
|
| 1209 |
+
"type": "upi",
|
| 1210 |
+
"last4_hash": "4e29a008959a9ddb23bd5d117d6a71f1e75f3b17df6ca4dd313a16711ea6ec45"
|
| 1211 |
+
},
|
| 1212 |
+
{
|
| 1213 |
+
"instrument_id": "PAY0243",
|
| 1214 |
+
"type": "upi",
|
| 1215 |
+
"last4_hash": "3206fba387884735f6ec58259d62fe0943b0ee14fe9dc5137cc676428cb07bb9"
|
| 1216 |
+
},
|
| 1217 |
+
{
|
| 1218 |
+
"instrument_id": "PAY0244",
|
| 1219 |
+
"type": "card",
|
| 1220 |
+
"last4_hash": "8f10833e3ef270a248b7001d1f7b30b7d05e67d648ce3e87f000215e38451b7b"
|
| 1221 |
+
},
|
| 1222 |
+
{
|
| 1223 |
+
"instrument_id": "PAY0245",
|
| 1224 |
+
"type": "upi",
|
| 1225 |
+
"last4_hash": "a10b8d76c071f9e86d3906e6e15cf75709a4c6b2d7439ec2cc44e97f08119936"
|
| 1226 |
+
},
|
| 1227 |
+
{
|
| 1228 |
+
"instrument_id": "PAY0246",
|
| 1229 |
+
"type": "card",
|
| 1230 |
+
"last4_hash": "9da8780a381915da91ad2693249937745283266704661097a162c48c38976205"
|
| 1231 |
+
},
|
| 1232 |
+
{
|
| 1233 |
+
"instrument_id": "PAY0247",
|
| 1234 |
+
"type": "card",
|
| 1235 |
+
"last4_hash": "c44066cadb3f91efc94e8a80b0ed370d9e9775d66fad1dac4e546bf9f1916df9"
|
| 1236 |
+
},
|
| 1237 |
+
{
|
| 1238 |
+
"instrument_id": "PAY0248",
|
| 1239 |
+
"type": "card",
|
| 1240 |
+
"last4_hash": "6b724a6630ccac9ac84a7af1031414c6b6b6a16b59aafe635d5b93b12d44c7bf"
|
| 1241 |
+
},
|
| 1242 |
+
{
|
| 1243 |
+
"instrument_id": "PAY0249",
|
| 1244 |
+
"type": "upi",
|
| 1245 |
+
"last4_hash": "6ac7bd0865c7d5d212b9a9b1c92bb4b85a3a06e03e9bbc458782ad4c9382345f"
|
| 1246 |
+
},
|
| 1247 |
+
{
|
| 1248 |
+
"instrument_id": "PAY0250",
|
| 1249 |
+
"type": "card",
|
| 1250 |
+
"last4_hash": "e2135c76ca7863e51154829de3d9cb0a8f6398d31518c7581d370ed9cc521811"
|
| 1251 |
+
},
|
| 1252 |
+
{
|
| 1253 |
+
"instrument_id": "PAY0251",
|
| 1254 |
+
"type": "card",
|
| 1255 |
+
"last4_hash": "45d1bf544943b021e561523370fcb4b73bf8c67de1b68a3ec825fb28144ff434"
|
| 1256 |
+
},
|
| 1257 |
+
{
|
| 1258 |
+
"instrument_id": "PAY0252",
|
| 1259 |
+
"type": "upi",
|
| 1260 |
+
"last4_hash": "22ea6cd8dc9b0b8247357f4c1736437b7cf6d5e886f8a386948476e7f72b0fc4"
|
| 1261 |
+
},
|
| 1262 |
+
{
|
| 1263 |
+
"instrument_id": "PAY0253",
|
| 1264 |
+
"type": "upi",
|
| 1265 |
+
"last4_hash": "5d6076ec8f36560a68a9a3d910e459f6250c5acb00237a9558102f863a4955ab"
|
| 1266 |
+
},
|
| 1267 |
+
{
|
| 1268 |
+
"instrument_id": "PAY0254",
|
| 1269 |
+
"type": "upi",
|
| 1270 |
+
"last4_hash": "89f7bcb6f95d9f29063738e097b0255e0bcc57a39caeff49ddf6925789120fc5"
|
| 1271 |
+
},
|
| 1272 |
+
{
|
| 1273 |
+
"instrument_id": "PAY0255",
|
| 1274 |
+
"type": "card",
|
| 1275 |
+
"last4_hash": "1b457162acd3bc249096a759943769e27b27ecbd1fb20a870b70b82e9c0264d6"
|
| 1276 |
+
},
|
| 1277 |
+
{
|
| 1278 |
+
"instrument_id": "PAY0256",
|
| 1279 |
+
"type": "upi",
|
| 1280 |
+
"last4_hash": "4e52a13115d05bc553e5de70cba00a6ff3ec75172ab1015133999f4907b06739"
|
| 1281 |
+
},
|
| 1282 |
+
{
|
| 1283 |
+
"instrument_id": "PAY0257",
|
| 1284 |
+
"type": "upi",
|
| 1285 |
+
"last4_hash": "ce9020dc8536f77c86e0179914a12928e8171560a9f865f50a905f4b175f2fe2"
|
| 1286 |
+
},
|
| 1287 |
+
{
|
| 1288 |
+
"instrument_id": "PAY0258",
|
| 1289 |
+
"type": "upi",
|
| 1290 |
+
"last4_hash": "c11930573da1982285db8a450fbe77496b12ff78b3585ba26f70d4c9fa325dac"
|
| 1291 |
+
},
|
| 1292 |
+
{
|
| 1293 |
+
"instrument_id": "PAY0259",
|
| 1294 |
+
"type": "upi",
|
| 1295 |
+
"last4_hash": "e346f2da1da79fb8f2e685ba08e28022f4f11c15169f74e7fc17d8bfce87865f"
|
| 1296 |
+
},
|
| 1297 |
+
{
|
| 1298 |
+
"instrument_id": "PAY0260",
|
| 1299 |
+
"type": "upi",
|
| 1300 |
+
"last4_hash": "f766d02d1d0991fdde7d1ac9e3e1a5164f68f3bd79328a1a42c5c9484237606b"
|
| 1301 |
+
},
|
| 1302 |
+
{
|
| 1303 |
+
"instrument_id": "PAY0261",
|
| 1304 |
+
"type": "card",
|
| 1305 |
+
"last4_hash": "ef0d2e96b08cee59a3557ca2ddba84bd84b4dabd4e2f882122a291bffee0acdd"
|
| 1306 |
+
},
|
| 1307 |
+
{
|
| 1308 |
+
"instrument_id": "PAY0262",
|
| 1309 |
+
"type": "upi",
|
| 1310 |
+
"last4_hash": "3760c7faec9d9f32031e20781e1123f31b2085d3407995ea8f9c195a90fbe0b0"
|
| 1311 |
+
},
|
| 1312 |
+
{
|
| 1313 |
+
"instrument_id": "PAY0263",
|
| 1314 |
+
"type": "upi",
|
| 1315 |
+
"last4_hash": "7c5fb304ddb31dad9639fe0566854024009252dd1edc43cee8d3b2fefe63c2cc"
|
| 1316 |
+
},
|
| 1317 |
+
{
|
| 1318 |
+
"instrument_id": "PAY0264",
|
| 1319 |
+
"type": "upi",
|
| 1320 |
+
"last4_hash": "694c4311e4d3d0aa2d05a079ec09c9bffbbbf38ccee37912e59fcfa13d0cf36b"
|
| 1321 |
+
},
|
| 1322 |
+
{
|
| 1323 |
+
"instrument_id": "PAY0265",
|
| 1324 |
+
"type": "card",
|
| 1325 |
+
"last4_hash": "94f136bbfce57e5c6f1c86bbf6bf8a4e1d48ef230373eda2859170e158b1c185"
|
| 1326 |
+
},
|
| 1327 |
+
{
|
| 1328 |
+
"instrument_id": "PAY0266",
|
| 1329 |
+
"type": "card",
|
| 1330 |
+
"last4_hash": "462b01670e50875a9df97c18e87cd367dbe7fbd6f32783be20883747e37d5af6"
|
| 1331 |
+
},
|
| 1332 |
+
{
|
| 1333 |
+
"instrument_id": "PAY0267",
|
| 1334 |
+
"type": "upi",
|
| 1335 |
+
"last4_hash": "b5c6ea4587d7483b25440b9af696a3cf45757a33dc540449fff4d084d5669179"
|
| 1336 |
+
},
|
| 1337 |
+
{
|
| 1338 |
+
"instrument_id": "PAY0268",
|
| 1339 |
+
"type": "card",
|
| 1340 |
+
"last4_hash": "0228374d12ee995cdeff8e25d819990f80d40c8773321fafe4ce1572c7df29af"
|
| 1341 |
+
},
|
| 1342 |
+
{
|
| 1343 |
+
"instrument_id": "PAY0269",
|
| 1344 |
+
"type": "upi",
|
| 1345 |
+
"last4_hash": "dbcbd844304e9fc9edd4bead28de1ce924bb41b2a4a602591ac1a4051c5f426f"
|
| 1346 |
+
},
|
| 1347 |
+
{
|
| 1348 |
+
"instrument_id": "PAY0270",
|
| 1349 |
+
"type": "upi",
|
| 1350 |
+
"last4_hash": "cccbf5f0cdc758831aec3f19afd46cfa357cc9b667b1eeb3c1a93776e824df10"
|
| 1351 |
+
},
|
| 1352 |
+
{
|
| 1353 |
+
"instrument_id": "PAY0271",
|
| 1354 |
+
"type": "upi",
|
| 1355 |
+
"last4_hash": "d34e5be7cf681f8f8f5e2aca5d0b120463f3d560a2b827ce0d12a8534600d179"
|
| 1356 |
+
},
|
| 1357 |
+
{
|
| 1358 |
+
"instrument_id": "PAY0272",
|
| 1359 |
+
"type": "card",
|
| 1360 |
+
"last4_hash": "e1d07bb0923258ae0e244dcf81f4c87614b833fc15ca7dbb77740d1860f915d2"
|
| 1361 |
+
},
|
| 1362 |
+
{
|
| 1363 |
+
"instrument_id": "PAY0273",
|
| 1364 |
+
"type": "upi",
|
| 1365 |
+
"last4_hash": "8da78c744ccbc95e9980bb28010978baaae42fdc0341cdc6c52e49df0bec5337"
|
| 1366 |
+
},
|
| 1367 |
+
{
|
| 1368 |
+
"instrument_id": "PAY0274",
|
| 1369 |
+
"type": "card",
|
| 1370 |
+
"last4_hash": "b1e9300609f0a4556b09d64f62814c5e0e839e4353f262869bbd78e745f458b1"
|
| 1371 |
+
},
|
| 1372 |
+
{
|
| 1373 |
+
"instrument_id": "PAY0275",
|
| 1374 |
+
"type": "upi",
|
| 1375 |
+
"last4_hash": "9dd391923f6fcb022c671681f977b1c8220bd55d67bbf4cf92c7134765ac1110"
|
| 1376 |
+
},
|
| 1377 |
+
{
|
| 1378 |
+
"instrument_id": "PAY0276",
|
| 1379 |
+
"type": "upi",
|
| 1380 |
+
"last4_hash": "666a8b82b2fa22b380990b945a7253edb81077025e894f9a240f79e34e12073f"
|
| 1381 |
+
},
|
| 1382 |
+
{
|
| 1383 |
+
"instrument_id": "PAY0277",
|
| 1384 |
+
"type": "upi",
|
| 1385 |
+
"last4_hash": "a44c062db40c7f0dfa7759a203df799c3ec1481692f1f83b0f0ac0982949cebf"
|
| 1386 |
+
},
|
| 1387 |
+
{
|
| 1388 |
+
"instrument_id": "PAY0278",
|
| 1389 |
+
"type": "upi",
|
| 1390 |
+
"last4_hash": "6ea839f917ae2c0a0f39dee4625f232a1d6437678c541ecd3c94f1954e4c3159"
|
| 1391 |
+
},
|
| 1392 |
+
{
|
| 1393 |
+
"instrument_id": "PAY0279",
|
| 1394 |
+
"type": "card",
|
| 1395 |
+
"last4_hash": "dd6103b473273ecdbf0446eb7e22d5e3397e03f2e275379e4427a36cfc6e87e6"
|
| 1396 |
+
},
|
| 1397 |
+
{
|
| 1398 |
+
"instrument_id": "PAY0280",
|
| 1399 |
+
"type": "upi",
|
| 1400 |
+
"last4_hash": "cec4f851cb0a168f0193b99eddefa1a34121054b40755447ea1a3366d843242a"
|
| 1401 |
+
},
|
| 1402 |
+
{
|
| 1403 |
+
"instrument_id": "PAY0281",
|
| 1404 |
+
"type": "upi",
|
| 1405 |
+
"last4_hash": "69fc261f5af1673a971aa89d9ed10b17c59df9ef4297d175768431999fbd880e"
|
| 1406 |
+
},
|
| 1407 |
+
{
|
| 1408 |
+
"instrument_id": "PAY0282",
|
| 1409 |
+
"type": "upi",
|
| 1410 |
+
"last4_hash": "cad2316eaa81e19e7bf2c3f0033243acf6cef44d18c5fa5e8ad54d490d68bde7"
|
| 1411 |
+
},
|
| 1412 |
+
{
|
| 1413 |
+
"instrument_id": "PAY0283",
|
| 1414 |
+
"type": "upi",
|
| 1415 |
+
"last4_hash": "c2c26a9990dd4dfa95ad0087849ddb39141a04454ad2377c1a2c35b3a388b57b"
|
| 1416 |
+
},
|
| 1417 |
+
{
|
| 1418 |
+
"instrument_id": "PAY0284",
|
| 1419 |
+
"type": "upi",
|
| 1420 |
+
"last4_hash": "beb62c82d72fd3a83113c930c0c3139e9418636d9e03ab36cec1956eed69524c"
|
| 1421 |
+
},
|
| 1422 |
+
{
|
| 1423 |
+
"instrument_id": "PAY0285",
|
| 1424 |
+
"type": "card",
|
| 1425 |
+
"last4_hash": "94bcfe105ad50803f9a5dc7f60974e21d47f608826675250c699467f116608dc"
|
| 1426 |
+
},
|
| 1427 |
+
{
|
| 1428 |
+
"instrument_id": "PAY0286",
|
| 1429 |
+
"type": "card",
|
| 1430 |
+
"last4_hash": "16d5164c6ff6bf7201a90e9ec406fe9d122c9894cda28854a05e68ff1f2e804c"
|
| 1431 |
+
},
|
| 1432 |
+
{
|
| 1433 |
+
"instrument_id": "PAY0287",
|
| 1434 |
+
"type": "upi",
|
| 1435 |
+
"last4_hash": "cae39f6224161df60057c04084845eda4dfdb9649900ec17915a42986b8cff36"
|
| 1436 |
+
},
|
| 1437 |
+
{
|
| 1438 |
+
"instrument_id": "PAY0288",
|
| 1439 |
+
"type": "upi",
|
| 1440 |
+
"last4_hash": "75a62033cfdee7f67ff55d062301bc80b3e62c727b18ddc9f0a44902a33afd86"
|
| 1441 |
+
},
|
| 1442 |
+
{
|
| 1443 |
+
"instrument_id": "PAY0289",
|
| 1444 |
+
"type": "card",
|
| 1445 |
+
"last4_hash": "f24e819d0999cd9c97741467925b406532813857723c7bf4971a13a938b1e9ec"
|
| 1446 |
+
},
|
| 1447 |
+
{
|
| 1448 |
+
"instrument_id": "PAY0290",
|
| 1449 |
+
"type": "card",
|
| 1450 |
+
"last4_hash": "56d5f315cf3312f1e33f250993515e272210f45eab5f60d84c892b70abfbfcfd"
|
| 1451 |
+
},
|
| 1452 |
+
{
|
| 1453 |
+
"instrument_id": "PAY0291",
|
| 1454 |
+
"type": "upi",
|
| 1455 |
+
"last4_hash": "a5772758cde632e399e9a2b7724d9501a27aac225a129665910593a12c0c2278"
|
| 1456 |
+
},
|
| 1457 |
+
{
|
| 1458 |
+
"instrument_id": "PAY0292",
|
| 1459 |
+
"type": "upi",
|
| 1460 |
+
"last4_hash": "c4ed339846ea9d2738e34a5b070bbbee4233f162a9bbde017ecf0c45e090628c"
|
| 1461 |
+
},
|
| 1462 |
+
{
|
| 1463 |
+
"instrument_id": "PAY0293",
|
| 1464 |
+
"type": "card",
|
| 1465 |
+
"last4_hash": "2478b5cdde898af6ad0d268fed2485ec42b63add9b159770b287e7396b71088c"
|
| 1466 |
+
},
|
| 1467 |
+
{
|
| 1468 |
+
"instrument_id": "PAY0294",
|
| 1469 |
+
"type": "upi",
|
| 1470 |
+
"last4_hash": "15996fbb0ec304c8c73f5553cd5197ce660af069ad8bbb9a8e65056e9595390d"
|
| 1471 |
+
},
|
| 1472 |
+
{
|
| 1473 |
+
"instrument_id": "PAY0295",
|
| 1474 |
+
"type": "upi",
|
| 1475 |
+
"last4_hash": "3294898f52ec90ff6f3ec3ba983335fb585c8d190d66add034f6e7a27f063b82"
|
| 1476 |
+
},
|
| 1477 |
+
{
|
| 1478 |
+
"instrument_id": "PAY0296",
|
| 1479 |
+
"type": "upi",
|
| 1480 |
+
"last4_hash": "d2325dfbe73e62fb166e0ad38da68236e73bca72bfa5fffb881f9a12f708cc5b"
|
| 1481 |
+
},
|
| 1482 |
+
{
|
| 1483 |
+
"instrument_id": "PAY0297",
|
| 1484 |
+
"type": "card",
|
| 1485 |
+
"last4_hash": "d03e59748526d73618c46171c55d8d067777013738ef99f13b529687bf45e453"
|
| 1486 |
+
},
|
| 1487 |
+
{
|
| 1488 |
+
"instrument_id": "PAY0298",
|
| 1489 |
+
"type": "upi",
|
| 1490 |
+
"last4_hash": "1acc803411f7af2580d5f0c757d4cb78f524e0ae3745a7f384909be50ab22f2b"
|
| 1491 |
+
},
|
| 1492 |
+
{
|
| 1493 |
+
"instrument_id": "PAY0299",
|
| 1494 |
+
"type": "card",
|
| 1495 |
+
"last4_hash": "8d7daebcedc86c90dd1d3e3b90bbd2eaf71f37073bd1ee57efcdd4040316b26e"
|
| 1496 |
+
},
|
| 1497 |
+
{
|
| 1498 |
+
"instrument_id": "PAY0300",
|
| 1499 |
+
"type": "upi",
|
| 1500 |
+
"last4_hash": "0a4508eafdae8d6a2bd1733dd666b2d5c59bfc151c5f32c04adac18f9b638f88"
|
| 1501 |
+
},
|
| 1502 |
+
{
|
| 1503 |
+
"instrument_id": "PAY0301",
|
| 1504 |
+
"type": "upi",
|
| 1505 |
+
"last4_hash": "d70428d6bb194ce315ecab17251724d537377a4dfdbe25c0789891064785bd66"
|
| 1506 |
+
},
|
| 1507 |
+
{
|
| 1508 |
+
"instrument_id": "PAY0302",
|
| 1509 |
+
"type": "card",
|
| 1510 |
+
"last4_hash": "e56ae9ee21661d3febabe8d1e03ee82d02466a5d405e89f2acf449cd6a6240b8"
|
| 1511 |
+
},
|
| 1512 |
+
{
|
| 1513 |
+
"instrument_id": "PAY0303",
|
| 1514 |
+
"type": "card",
|
| 1515 |
+
"last4_hash": "c6b4c26e25da2dadec4164bd0a517057cfd5a1e873700a843ab37f4ef270d8ec"
|
| 1516 |
+
},
|
| 1517 |
+
{
|
| 1518 |
+
"instrument_id": "PAY0304",
|
| 1519 |
+
"type": "upi",
|
| 1520 |
+
"last4_hash": "dbb5f75c348639638a2aab13c65b11dd7b0e0600d76ebd2750cf87ba9df98c36"
|
| 1521 |
+
},
|
| 1522 |
+
{
|
| 1523 |
+
"instrument_id": "PAY0305",
|
| 1524 |
+
"type": "card",
|
| 1525 |
+
"last4_hash": "3e1884b53656e0d408c17c114fdd85744c1c61bd05262f049d2da235b84332de"
|
| 1526 |
+
},
|
| 1527 |
+
{
|
| 1528 |
+
"instrument_id": "PAY0306",
|
| 1529 |
+
"type": "card",
|
| 1530 |
+
"last4_hash": "061b4fe85b47a13e1887f386477e0e0d5c9f3003f53e4b20472bbaa8b46ce766"
|
| 1531 |
+
},
|
| 1532 |
+
{
|
| 1533 |
+
"instrument_id": "PAY0307",
|
| 1534 |
+
"type": "card",
|
| 1535 |
+
"last4_hash": "2d13ab427ffdaa125d6436319549bdaddd8670d8146a0a4f351d92e8c68adbf3"
|
| 1536 |
+
},
|
| 1537 |
+
{
|
| 1538 |
+
"instrument_id": "PAY0308",
|
| 1539 |
+
"type": "card",
|
| 1540 |
+
"last4_hash": "3b37ef6a1be31e06efd2f3cfa7e70d2b25d95efec97e5b71503a95e249d13250"
|
| 1541 |
+
},
|
| 1542 |
+
{
|
| 1543 |
+
"instrument_id": "PAY0309",
|
| 1544 |
+
"type": "upi",
|
| 1545 |
+
"last4_hash": "266dff09c92592d24ea4075cd51306a16180b0f3ebbdeb1ca9d82825ebc336d5"
|
| 1546 |
+
},
|
| 1547 |
+
{
|
| 1548 |
+
"instrument_id": "PAY0310",
|
| 1549 |
+
"type": "upi",
|
| 1550 |
+
"last4_hash": "354b6eb4abca5abe614439fb0b8b2b99c4c2355038a2ad3258e85cfc77d02875"
|
| 1551 |
+
},
|
| 1552 |
+
{
|
| 1553 |
+
"instrument_id": "PAY0311",
|
| 1554 |
+
"type": "upi",
|
| 1555 |
+
"last4_hash": "10f99f24ed74bf5c316688025910683a18ed067997d370489e303a575838f5ea"
|
| 1556 |
+
},
|
| 1557 |
+
{
|
| 1558 |
+
"instrument_id": "PAY0312",
|
| 1559 |
+
"type": "upi",
|
| 1560 |
+
"last4_hash": "b2e598cf7f4d1db437d7d03a427053d34a26d051cab739b4ae2a47d16ddf9881"
|
| 1561 |
+
},
|
| 1562 |
+
{
|
| 1563 |
+
"instrument_id": "PAY0313",
|
| 1564 |
+
"type": "upi",
|
| 1565 |
+
"last4_hash": "e64f311e1a8becec62c892f8b2867161e823a37e4ae01f747195d18973b1b3ca"
|
| 1566 |
+
},
|
| 1567 |
+
{
|
| 1568 |
+
"instrument_id": "PAY0314",
|
| 1569 |
+
"type": "upi",
|
| 1570 |
+
"last4_hash": "1a80e1c99d7f19f80d33f52ba6f325c5d9161f4024a5a343806c52d697aa6751"
|
| 1571 |
+
},
|
| 1572 |
+
{
|
| 1573 |
+
"instrument_id": "PAY0315",
|
| 1574 |
+
"type": "card",
|
| 1575 |
+
"last4_hash": "ee25805dac49adcdff3916bbd8bd1e8d5ee8f6d230f0e23a2614917da628ecf2"
|
| 1576 |
+
},
|
| 1577 |
+
{
|
| 1578 |
+
"instrument_id": "PAY0316",
|
| 1579 |
+
"type": "card",
|
| 1580 |
+
"last4_hash": "ecdac8c096f7fb91ae3bcefb2f0cfaba82e07a674645c53e9f497c1afe73175e"
|
| 1581 |
+
},
|
| 1582 |
+
{
|
| 1583 |
+
"instrument_id": "PAY0317",
|
| 1584 |
+
"type": "card",
|
| 1585 |
+
"last4_hash": "63adeada6605b9c8dd505f7f351e0c3dc03c77c19a53b41879a3123a087477b1"
|
| 1586 |
+
},
|
| 1587 |
+
{
|
| 1588 |
+
"instrument_id": "PAY0318",
|
| 1589 |
+
"type": "card",
|
| 1590 |
+
"last4_hash": "21113a3f71a6ecda7311c6e8539d1c9bd9949d3e6f23fbf4bcc781f96b30083a"
|
| 1591 |
+
},
|
| 1592 |
+
{
|
| 1593 |
+
"instrument_id": "PAY0319",
|
| 1594 |
+
"type": "upi",
|
| 1595 |
+
"last4_hash": "bbdc5fcb2b45ff7d3cd16a87f0671aaee83912eb9b32a35c19395e203768b4a3"
|
| 1596 |
+
},
|
| 1597 |
+
{
|
| 1598 |
+
"instrument_id": "PAY0320",
|
| 1599 |
+
"type": "upi",
|
| 1600 |
+
"last4_hash": "9a2999f3ed28c49fcc116d94d091d0ff78986843cf1d9b4394e9539a439127ae"
|
| 1601 |
+
},
|
| 1602 |
+
{
|
| 1603 |
+
"instrument_id": "PAY0321",
|
| 1604 |
+
"type": "upi",
|
| 1605 |
+
"last4_hash": "bf32228a9690f9fb114d8aa365c6526bd8d3e92647b96664dc9625f66f45dd12"
|
| 1606 |
+
},
|
| 1607 |
+
{
|
| 1608 |
+
"instrument_id": "PAY0322",
|
| 1609 |
+
"type": "upi",
|
| 1610 |
+
"last4_hash": "b7f71f7714700248db2c27fcdc5ce58eecbbe6eaaeb6e4b7200acfe54ae96a25"
|
| 1611 |
+
},
|
| 1612 |
+
{
|
| 1613 |
+
"instrument_id": "PAY0323",
|
| 1614 |
+
"type": "card",
|
| 1615 |
+
"last4_hash": "a5f643933b06668a9f74e6a6d378d41da76b4a7048fbabfd493c005eb2547a2e"
|
| 1616 |
+
},
|
| 1617 |
+
{
|
| 1618 |
+
"instrument_id": "PAY0324",
|
| 1619 |
+
"type": "upi",
|
| 1620 |
+
"last4_hash": "c898fdb8c7646d10a32c1957f562db1c4ff16d2e9283dc065b4238363d6a5129"
|
| 1621 |
+
},
|
| 1622 |
+
{
|
| 1623 |
+
"instrument_id": "PAY0325",
|
| 1624 |
+
"type": "upi",
|
| 1625 |
+
"last4_hash": "5e36561eadf5d0e282bdc2c52526cc239f4b438b7acc5e76f27be7762f2ca435"
|
| 1626 |
+
},
|
| 1627 |
+
{
|
| 1628 |
+
"instrument_id": "PAY0326",
|
| 1629 |
+
"type": "card",
|
| 1630 |
+
"last4_hash": "41cf091084d6f30cf45e97b16bf165283dc5ab27f7999f7d31bd405e082e3fdd"
|
| 1631 |
+
},
|
| 1632 |
+
{
|
| 1633 |
+
"instrument_id": "PAY0327",
|
| 1634 |
+
"type": "upi",
|
| 1635 |
+
"last4_hash": "3ac36e235d07e875c8de80ac99489e4563f34f7f18d4341619ebdb240519b524"
|
| 1636 |
+
},
|
| 1637 |
+
{
|
| 1638 |
+
"instrument_id": "PAY0328",
|
| 1639 |
+
"type": "upi",
|
| 1640 |
+
"last4_hash": "c2132a1f935492df0fb57f1891781663046815e5cc48c89814fac4b72c6a7559"
|
| 1641 |
+
},
|
| 1642 |
+
{
|
| 1643 |
+
"instrument_id": "PAY0329",
|
| 1644 |
+
"type": "upi",
|
| 1645 |
+
"last4_hash": "0ee1d8cda501a0cb3f2d5018074bbe666418af01d4447fca40c9a89ff8dcfbf0"
|
| 1646 |
+
},
|
| 1647 |
+
{
|
| 1648 |
+
"instrument_id": "PAY0330",
|
| 1649 |
+
"type": "upi",
|
| 1650 |
+
"last4_hash": "aa59688cda0c3346742fa30c47cd9e560ad74edc205db781ed47b1709f00af8f"
|
| 1651 |
+
},
|
| 1652 |
+
{
|
| 1653 |
+
"instrument_id": "PAY0331",
|
| 1654 |
+
"type": "upi",
|
| 1655 |
+
"last4_hash": "b3cb76dfa3ad98bf3afbf973b480efc0a1c6a3a07079582468753cfad76c8213"
|
| 1656 |
+
},
|
| 1657 |
+
{
|
| 1658 |
+
"instrument_id": "PAY0332",
|
| 1659 |
+
"type": "upi",
|
| 1660 |
+
"last4_hash": "d0702d17dcf77b735276f8927f4b839e98bdcc4a04f3e4e5935cd564fc5c17fa"
|
| 1661 |
+
},
|
| 1662 |
+
{
|
| 1663 |
+
"instrument_id": "PAY0333",
|
| 1664 |
+
"type": "card",
|
| 1665 |
+
"last4_hash": "1eab3dfd35a341f4b06d518d53f3f4701e69fedff5c65230df8fe475ac85b50c"
|
| 1666 |
+
},
|
| 1667 |
+
{
|
| 1668 |
+
"instrument_id": "PAY0334",
|
| 1669 |
+
"type": "upi",
|
| 1670 |
+
"last4_hash": "7ef788d37b374936a437a4dfd5b4e6a020edc2e51d2f96132a213a8ff1d48b7a"
|
| 1671 |
+
},
|
| 1672 |
+
{
|
| 1673 |
+
"instrument_id": "PAY0335",
|
| 1674 |
+
"type": "card",
|
| 1675 |
+
"last4_hash": "212375a537417e324d381e18e45023efd4f801ef3b35f0fe3983a2b58bdca4f6"
|
| 1676 |
+
},
|
| 1677 |
+
{
|
| 1678 |
+
"instrument_id": "PAY0336",
|
| 1679 |
+
"type": "card",
|
| 1680 |
+
"last4_hash": "73bdbf955c7575599cb8c4618d79874c1b8e6c2888cbb3fbd3009d4744e2d218"
|
| 1681 |
+
},
|
| 1682 |
+
{
|
| 1683 |
+
"instrument_id": "PAY0337",
|
| 1684 |
+
"type": "upi",
|
| 1685 |
+
"last4_hash": "99f2f36d5c419aa2134b9e3b20e343480c31ae6ff043e4385c720ab982407394"
|
| 1686 |
+
},
|
| 1687 |
+
{
|
| 1688 |
+
"instrument_id": "PAY0338",
|
| 1689 |
+
"type": "upi",
|
| 1690 |
+
"last4_hash": "7b595dc28809c3d97bf4d9e3eda45ab903506341d09bff25f5746fe43ddab60a"
|
| 1691 |
+
},
|
| 1692 |
+
{
|
| 1693 |
+
"instrument_id": "PAY0339",
|
| 1694 |
+
"type": "upi",
|
| 1695 |
+
"last4_hash": "cccdcedf3abed8d74731a23a8915a398027aa5b12ca03404f5d7e099db30f5ff"
|
| 1696 |
+
},
|
| 1697 |
+
{
|
| 1698 |
+
"instrument_id": "PAY0340",
|
| 1699 |
+
"type": "card",
|
| 1700 |
+
"last4_hash": "77e359e4b1cb258f9f9d2d1dad6db4b74e3d0c5abdc1fcefa7ae126747386c27"
|
| 1701 |
+
},
|
| 1702 |
+
{
|
| 1703 |
+
"instrument_id": "PAY0341",
|
| 1704 |
+
"type": "card",
|
| 1705 |
+
"last4_hash": "e12868d1f3963e0e1129b3a6442b6d3d7d8e4eb7e27d34348b29523f0ae37748"
|
| 1706 |
+
},
|
| 1707 |
+
{
|
| 1708 |
+
"instrument_id": "PAY0342",
|
| 1709 |
+
"type": "upi",
|
| 1710 |
+
"last4_hash": "34a380a592a4c2a07b75793b430ee351affa2ca1ad546c9480142f48e6327955"
|
| 1711 |
+
},
|
| 1712 |
+
{
|
| 1713 |
+
"instrument_id": "PAY0343",
|
| 1714 |
+
"type": "card",
|
| 1715 |
+
"last4_hash": "213f367b1af015a79e0b0cf92a3d4084e6bd5fbc3fbb4364881b05854bf86924"
|
| 1716 |
+
},
|
| 1717 |
+
{
|
| 1718 |
+
"instrument_id": "PAY0344",
|
| 1719 |
+
"type": "card",
|
| 1720 |
+
"last4_hash": "fc42f716c296b127850fbca1e103af089ecf2fb1f7c152d8d5440c6130bb6018"
|
| 1721 |
+
},
|
| 1722 |
+
{
|
| 1723 |
+
"instrument_id": "PAY0345",
|
| 1724 |
+
"type": "upi",
|
| 1725 |
+
"last4_hash": "3b399b28cde16ac76a67359ad2a450043f1d3d2878409fdc5ea1602f4d3a54d7"
|
| 1726 |
+
},
|
| 1727 |
+
{
|
| 1728 |
+
"instrument_id": "PAY0346",
|
| 1729 |
+
"type": "card",
|
| 1730 |
+
"last4_hash": "e8202f39fad74acd9b6d38a6038da9e8682e857bbdb977cf7b913963bfa2b393"
|
| 1731 |
+
},
|
| 1732 |
+
{
|
| 1733 |
+
"instrument_id": "PAY0347",
|
| 1734 |
+
"type": "upi",
|
| 1735 |
+
"last4_hash": "06688d0561c37484aa6c49d1f0339ec2f2072c281147aadd727de8ac463a1d95"
|
| 1736 |
+
},
|
| 1737 |
+
{
|
| 1738 |
+
"instrument_id": "PAY0348",
|
| 1739 |
+
"type": "card",
|
| 1740 |
+
"last4_hash": "90d441ee3fce238cd433ff208078e8d4351fb2969f9ed6b595e588ed7ead5d4e"
|
| 1741 |
+
},
|
| 1742 |
+
{
|
| 1743 |
+
"instrument_id": "PAY0349",
|
| 1744 |
+
"type": "upi",
|
| 1745 |
+
"last4_hash": "ee1ece82ffecfdc2200e5e48dcd8cc066370deb5e1f40869819d811479513a3a"
|
| 1746 |
+
},
|
| 1747 |
+
{
|
| 1748 |
+
"instrument_id": "PAY0350",
|
| 1749 |
+
"type": "upi",
|
| 1750 |
+
"last4_hash": "c25d57a3151ee5284a8f037f6336a93978a496859309bdabd4c56a7c2a7b5a2e"
|
| 1751 |
+
},
|
| 1752 |
+
{
|
| 1753 |
+
"instrument_id": "PAY0351",
|
| 1754 |
+
"type": "upi",
|
| 1755 |
+
"last4_hash": "7d980fadbd3bd55b3e1b798fb4b4b03382fa7707bb5ce37eb1bbbda580f83a46"
|
| 1756 |
+
},
|
| 1757 |
+
{
|
| 1758 |
+
"instrument_id": "PAY0352",
|
| 1759 |
+
"type": "upi",
|
| 1760 |
+
"last4_hash": "6ef67c4f417b6f6c74d139a18b6050097ae4bbbc08320e83acb5a16490d20fdf"
|
| 1761 |
+
},
|
| 1762 |
+
{
|
| 1763 |
+
"instrument_id": "PAY0353",
|
| 1764 |
+
"type": "card",
|
| 1765 |
+
"last4_hash": "cc56038328ffa43e94516e446dfde7b43c94f18e80e59a79476598a1f394da23"
|
| 1766 |
+
},
|
| 1767 |
+
{
|
| 1768 |
+
"instrument_id": "PAY0354",
|
| 1769 |
+
"type": "upi",
|
| 1770 |
+
"last4_hash": "178cb40bf3dfbaac93fd5ae16d819c1758a5f2d0e655bb0ac5afadf8b42df466"
|
| 1771 |
+
},
|
| 1772 |
+
{
|
| 1773 |
+
"instrument_id": "PAY0355",
|
| 1774 |
+
"type": "upi",
|
| 1775 |
+
"last4_hash": "cb57ca8d48ec0507d179908b7b9bfac3cd3fdebae39a78685baaf71588d1c7d7"
|
| 1776 |
+
},
|
| 1777 |
+
{
|
| 1778 |
+
"instrument_id": "PAY0356",
|
| 1779 |
+
"type": "upi",
|
| 1780 |
+
"last4_hash": "e087a3643dd4fb96b2332a2bdbbf293149b3b0367345a13a11f2d19266199d4f"
|
| 1781 |
+
},
|
| 1782 |
+
{
|
| 1783 |
+
"instrument_id": "PAY0357",
|
| 1784 |
+
"type": "card",
|
| 1785 |
+
"last4_hash": "b8dc2c143be8994682b08461f46487e05874e59dd9ab65cf973e3a3c67a763aa"
|
| 1786 |
+
},
|
| 1787 |
+
{
|
| 1788 |
+
"instrument_id": "PAY0358",
|
| 1789 |
+
"type": "card",
|
| 1790 |
+
"last4_hash": "adb736c83f5cec1d6a275694c25b544137ab4d4c760c4dadf89523c4167d619a"
|
| 1791 |
+
},
|
| 1792 |
+
{
|
| 1793 |
+
"instrument_id": "PAY0359",
|
| 1794 |
+
"type": "card",
|
| 1795 |
+
"last4_hash": "18167da210996cf3525e400870f7d4955d6b983a7b7d237586e242e59888ad86"
|
| 1796 |
+
},
|
| 1797 |
+
{
|
| 1798 |
+
"instrument_id": "PAY0360",
|
| 1799 |
+
"type": "upi",
|
| 1800 |
+
"last4_hash": "5103fb8e14eb2dfc189a9906bc9919ba997350fb031790387759ad9cf7e08266"
|
| 1801 |
+
},
|
| 1802 |
+
{
|
| 1803 |
+
"instrument_id": "PAY0361",
|
| 1804 |
+
"type": "card",
|
| 1805 |
+
"last4_hash": "a0869c71d5d3edb240ae3d132a0ff1d6be1c6468831710c4ce156d55e95c0190"
|
| 1806 |
+
},
|
| 1807 |
+
{
|
| 1808 |
+
"instrument_id": "PAY0362",
|
| 1809 |
+
"type": "upi",
|
| 1810 |
+
"last4_hash": "a5d5e96c52a28d8c9d546c9d35fa722d7078965c111e628b452bf97881c7b5e9"
|
| 1811 |
+
},
|
| 1812 |
+
{
|
| 1813 |
+
"instrument_id": "PAY0363",
|
| 1814 |
+
"type": "card",
|
| 1815 |
+
"last4_hash": "ecdd7308565e93e4912e8f9353031766e18d531cedfc452835951fdba61f695f"
|
| 1816 |
+
},
|
| 1817 |
+
{
|
| 1818 |
+
"instrument_id": "PAY0364",
|
| 1819 |
+
"type": "card",
|
| 1820 |
+
"last4_hash": "6815fd0989fc6aa86c07ab321564405cedf401875868f38d40a4631cac92e599"
|
| 1821 |
+
},
|
| 1822 |
+
{
|
| 1823 |
+
"instrument_id": "PAY0365",
|
| 1824 |
+
"type": "upi",
|
| 1825 |
+
"last4_hash": "3d6a4c17b72c189aeed3615836662368f2a3905437c216f67701a97d3e3743fa"
|
| 1826 |
+
},
|
| 1827 |
+
{
|
| 1828 |
+
"instrument_id": "PAY0366",
|
| 1829 |
+
"type": "card",
|
| 1830 |
+
"last4_hash": "addcb3d9599cca858acab111858cfc4df9cd6cdf515a5cfdeba5c12e15ba11b3"
|
| 1831 |
+
},
|
| 1832 |
+
{
|
| 1833 |
+
"instrument_id": "PAY0367",
|
| 1834 |
+
"type": "upi",
|
| 1835 |
+
"last4_hash": "923d83d13047ef02d57106faf2a8cfba184b6c037055ab3c231f365565ee7606"
|
| 1836 |
+
},
|
| 1837 |
+
{
|
| 1838 |
+
"instrument_id": "PAY0368",
|
| 1839 |
+
"type": "upi",
|
| 1840 |
+
"last4_hash": "d98cbbd5a443ecf65f57ad3fb285624a2e1056c51ca2f6cb208af2b2af2e029e"
|
| 1841 |
+
},
|
| 1842 |
+
{
|
| 1843 |
+
"instrument_id": "PAY0369",
|
| 1844 |
+
"type": "upi",
|
| 1845 |
+
"last4_hash": "06c860802560f4929f8c4b9a8aaeb4993a9585da5581afe8b9cbfd86e48e53db"
|
| 1846 |
+
},
|
| 1847 |
+
{
|
| 1848 |
+
"instrument_id": "PAY0370",
|
| 1849 |
+
"type": "card",
|
| 1850 |
+
"last4_hash": "0f8eb4b72b6e0c9e88b388eb967b49e067ef1004bf07bffc22c3acb13b43580a"
|
| 1851 |
+
},
|
| 1852 |
+
{
|
| 1853 |
+
"instrument_id": "PAY0371",
|
| 1854 |
+
"type": "upi",
|
| 1855 |
+
"last4_hash": "737762cbae1acba8015e18595a847ffeb0c9f47897944f1cef319d4c2e0445cf"
|
| 1856 |
+
},
|
| 1857 |
+
{
|
| 1858 |
+
"instrument_id": "PAY0372",
|
| 1859 |
+
"type": "card",
|
| 1860 |
+
"last4_hash": "c69f0baaa1af7cebe9998a386323206afb0bc08a19eea74253299e75dc5556e6"
|
| 1861 |
+
},
|
| 1862 |
+
{
|
| 1863 |
+
"instrument_id": "PAY0373",
|
| 1864 |
+
"type": "card",
|
| 1865 |
+
"last4_hash": "83d7ce01060ca9e9dc54af6c215800d77b11bad522966f80acd79deddb36f73b"
|
| 1866 |
+
},
|
| 1867 |
+
{
|
| 1868 |
+
"instrument_id": "PAY0374",
|
| 1869 |
+
"type": "upi",
|
| 1870 |
+
"last4_hash": "ce9609640075f8b7cd58aa69194024559a1a1efbea6234486fac17f6c5476d6d"
|
| 1871 |
+
},
|
| 1872 |
+
{
|
| 1873 |
+
"instrument_id": "PAY0375",
|
| 1874 |
+
"type": "card",
|
| 1875 |
+
"last4_hash": "ba733a2bc3efb152c8d435ef1d7640160090d996a866e1b4970f233d19371edb"
|
| 1876 |
+
},
|
| 1877 |
+
{
|
| 1878 |
+
"instrument_id": "PAY0376",
|
| 1879 |
+
"type": "card",
|
| 1880 |
+
"last4_hash": "dcbff8f66de95d7c6148b3fbb3a9934d226ffb6dfd405c8394ae5454dc87d348"
|
| 1881 |
+
},
|
| 1882 |
+
{
|
| 1883 |
+
"instrument_id": "PAY0377",
|
| 1884 |
+
"type": "upi",
|
| 1885 |
+
"last4_hash": "f8061506e4c8bc3fab9a2eebb988cd6f52f14a4ee0b3f5c1d739fb88750d4036"
|
| 1886 |
+
},
|
| 1887 |
+
{
|
| 1888 |
+
"instrument_id": "PAY0378",
|
| 1889 |
+
"type": "upi",
|
| 1890 |
+
"last4_hash": "c4210996b202fac099a1603ed8c708528a08bf3fda87d3754b552653b717a5cf"
|
| 1891 |
+
},
|
| 1892 |
+
{
|
| 1893 |
+
"instrument_id": "PAY0379",
|
| 1894 |
+
"type": "upi",
|
| 1895 |
+
"last4_hash": "ce9cb7fd6836d4eb0cc662b98193a5d99e1d4cd611143b5f00c5c4062471aa91"
|
| 1896 |
+
},
|
| 1897 |
+
{
|
| 1898 |
+
"instrument_id": "PAY0380",
|
| 1899 |
+
"type": "upi",
|
| 1900 |
+
"last4_hash": "8c2962f6101b265bf3420df868fd8a06c225af08e9121dc5f6b14675a5143430"
|
| 1901 |
+
},
|
| 1902 |
+
{
|
| 1903 |
+
"instrument_id": "PAY0381",
|
| 1904 |
+
"type": "upi",
|
| 1905 |
+
"last4_hash": "90bdbc041092b051ce60a757fbbeacce2413d02e9aa8394341f26a69a5df36fa"
|
| 1906 |
+
},
|
| 1907 |
+
{
|
| 1908 |
+
"instrument_id": "PAY0382",
|
| 1909 |
+
"type": "upi",
|
| 1910 |
+
"last4_hash": "f05bf7a9ac195b334d23d13b00567122f67958d56bd92ac804f9b17a757f9c74"
|
| 1911 |
+
},
|
| 1912 |
+
{
|
| 1913 |
+
"instrument_id": "PAY0383",
|
| 1914 |
+
"type": "upi",
|
| 1915 |
+
"last4_hash": "c5fb52368f1b210a540e1cffb745ec44c44c268cecb39c2096c3553fa0e93231"
|
| 1916 |
+
},
|
| 1917 |
+
{
|
| 1918 |
+
"instrument_id": "PAY0384",
|
| 1919 |
+
"type": "upi",
|
| 1920 |
+
"last4_hash": "00eb14b679e5b17abc30ee049f64e324c36f2f279d29d725ce4785fdd73a340e"
|
| 1921 |
+
},
|
| 1922 |
+
{
|
| 1923 |
+
"instrument_id": "PAY0385",
|
| 1924 |
+
"type": "upi",
|
| 1925 |
+
"last4_hash": "4ade1343ca03e40d753469311da59756151e8757e013b54af5c65c13d3b224c8"
|
| 1926 |
+
},
|
| 1927 |
+
{
|
| 1928 |
+
"instrument_id": "PAY0386",
|
| 1929 |
+
"type": "upi",
|
| 1930 |
+
"last4_hash": "689d840a91eed6a0aa9ebb341fe2dde3405981143f991f52234d2c31b4519875"
|
| 1931 |
+
}
|
| 1932 |
+
]
|
data/synthetic/scored_clusters.json
ADDED
|
@@ -0,0 +1,812 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
{
|
| 3 |
+
"cluster_id": "CAND01",
|
| 4 |
+
"customer_ids": [
|
| 5 |
+
"CUST0041",
|
| 6 |
+
"CUST0042",
|
| 7 |
+
"CUST0043",
|
| 8 |
+
"CUST0044"
|
| 9 |
+
],
|
| 10 |
+
"size": 4,
|
| 11 |
+
"strong_link_count": 6,
|
| 12 |
+
"weak_link_count": 0,
|
| 13 |
+
"formation_type": "strong_anchored",
|
| 14 |
+
"method": "connected_components",
|
| 15 |
+
"risk_probability": 0.9958773824170732
|
| 16 |
+
},
|
| 17 |
+
{
|
| 18 |
+
"cluster_id": "CAND02",
|
| 19 |
+
"customer_ids": [
|
| 20 |
+
"CUST0009",
|
| 21 |
+
"CUST0010",
|
| 22 |
+
"CUST0011",
|
| 23 |
+
"CUST0012",
|
| 24 |
+
"CUST0013"
|
| 25 |
+
],
|
| 26 |
+
"size": 5,
|
| 27 |
+
"strong_link_count": 10,
|
| 28 |
+
"weak_link_count": 0,
|
| 29 |
+
"formation_type": "strong_anchored",
|
| 30 |
+
"method": "connected_components",
|
| 31 |
+
"risk_probability": 0.9968053865328341
|
| 32 |
+
},
|
| 33 |
+
{
|
| 34 |
+
"cluster_id": "CAND03",
|
| 35 |
+
"customer_ids": [
|
| 36 |
+
"CUST0001",
|
| 37 |
+
"CUST0002",
|
| 38 |
+
"CUST0003"
|
| 39 |
+
],
|
| 40 |
+
"size": 3,
|
| 41 |
+
"strong_link_count": 3,
|
| 42 |
+
"weak_link_count": 0,
|
| 43 |
+
"formation_type": "strong_anchored",
|
| 44 |
+
"method": "connected_components",
|
| 45 |
+
"risk_probability": 0.9950028638127228
|
| 46 |
+
},
|
| 47 |
+
{
|
| 48 |
+
"cluster_id": "CAND04",
|
| 49 |
+
"customer_ids": [
|
| 50 |
+
"CUST0014",
|
| 51 |
+
"CUST0015",
|
| 52 |
+
"CUST0016",
|
| 53 |
+
"CUST0017",
|
| 54 |
+
"CUST0018"
|
| 55 |
+
],
|
| 56 |
+
"size": 5,
|
| 57 |
+
"strong_link_count": 10,
|
| 58 |
+
"weak_link_count": 0,
|
| 59 |
+
"formation_type": "strong_anchored",
|
| 60 |
+
"method": "connected_components",
|
| 61 |
+
"risk_probability": 0.9955003588432927
|
| 62 |
+
},
|
| 63 |
+
{
|
| 64 |
+
"cluster_id": "CAND05",
|
| 65 |
+
"customer_ids": [
|
| 66 |
+
"CUST0033",
|
| 67 |
+
"CUST0034",
|
| 68 |
+
"CUST0035"
|
| 69 |
+
],
|
| 70 |
+
"size": 3,
|
| 71 |
+
"strong_link_count": 3,
|
| 72 |
+
"weak_link_count": 0,
|
| 73 |
+
"formation_type": "strong_anchored",
|
| 74 |
+
"method": "connected_components",
|
| 75 |
+
"risk_probability": 0.9969893801631614
|
| 76 |
+
},
|
| 77 |
+
{
|
| 78 |
+
"cluster_id": "CAND06",
|
| 79 |
+
"customer_ids": [
|
| 80 |
+
"CUST0036",
|
| 81 |
+
"CUST0037",
|
| 82 |
+
"CUST0038",
|
| 83 |
+
"CUST0039",
|
| 84 |
+
"CUST0040"
|
| 85 |
+
],
|
| 86 |
+
"size": 5,
|
| 87 |
+
"strong_link_count": 10,
|
| 88 |
+
"weak_link_count": 0,
|
| 89 |
+
"formation_type": "strong_anchored",
|
| 90 |
+
"method": "connected_components",
|
| 91 |
+
"risk_probability": 0.9969377389203431
|
| 92 |
+
},
|
| 93 |
+
{
|
| 94 |
+
"cluster_id": "CAND07",
|
| 95 |
+
"customer_ids": [
|
| 96 |
+
"CUST0019",
|
| 97 |
+
"CUST0020",
|
| 98 |
+
"CUST0021",
|
| 99 |
+
"CUST0022",
|
| 100 |
+
"CUST0023"
|
| 101 |
+
],
|
| 102 |
+
"size": 5,
|
| 103 |
+
"strong_link_count": 10,
|
| 104 |
+
"weak_link_count": 0,
|
| 105 |
+
"formation_type": "strong_anchored",
|
| 106 |
+
"method": "connected_components",
|
| 107 |
+
"risk_probability": 0.9940850384979173
|
| 108 |
+
},
|
| 109 |
+
{
|
| 110 |
+
"cluster_id": "CAND08",
|
| 111 |
+
"customer_ids": [
|
| 112 |
+
"CUST0501",
|
| 113 |
+
"CUST0502",
|
| 114 |
+
"CUST0503"
|
| 115 |
+
],
|
| 116 |
+
"size": 3,
|
| 117 |
+
"strong_link_count": 3,
|
| 118 |
+
"weak_link_count": 0,
|
| 119 |
+
"formation_type": "strong_anchored",
|
| 120 |
+
"method": "connected_components",
|
| 121 |
+
"risk_probability": 0.9867466290228035
|
| 122 |
+
},
|
| 123 |
+
{
|
| 124 |
+
"cluster_id": "CAND09",
|
| 125 |
+
"customer_ids": [
|
| 126 |
+
"CUST0024",
|
| 127 |
+
"CUST0025",
|
| 128 |
+
"CUST0026",
|
| 129 |
+
"CUST0027",
|
| 130 |
+
"CUST0028",
|
| 131 |
+
"CUST0029"
|
| 132 |
+
],
|
| 133 |
+
"size": 6,
|
| 134 |
+
"strong_link_count": 15,
|
| 135 |
+
"weak_link_count": 0,
|
| 136 |
+
"formation_type": "strong_anchored",
|
| 137 |
+
"method": "connected_components",
|
| 138 |
+
"risk_probability": 0.9913203009684713
|
| 139 |
+
},
|
| 140 |
+
{
|
| 141 |
+
"cluster_id": "CAND10",
|
| 142 |
+
"customer_ids": [
|
| 143 |
+
"CUST0004",
|
| 144 |
+
"CUST0005",
|
| 145 |
+
"CUST0006",
|
| 146 |
+
"CUST0007",
|
| 147 |
+
"CUST0008"
|
| 148 |
+
],
|
| 149 |
+
"size": 5,
|
| 150 |
+
"strong_link_count": 7,
|
| 151 |
+
"weak_link_count": 0,
|
| 152 |
+
"formation_type": "strong_anchored",
|
| 153 |
+
"method": "connected_components",
|
| 154 |
+
"risk_probability": 0.9959231873282086
|
| 155 |
+
},
|
| 156 |
+
{
|
| 157 |
+
"cluster_id": "CAND11",
|
| 158 |
+
"customer_ids": [
|
| 159 |
+
"CUST0030",
|
| 160 |
+
"CUST0031",
|
| 161 |
+
"CUST0032"
|
| 162 |
+
],
|
| 163 |
+
"size": 3,
|
| 164 |
+
"strong_link_count": 2,
|
| 165 |
+
"weak_link_count": 0,
|
| 166 |
+
"formation_type": "strong_anchored",
|
| 167 |
+
"method": "connected_components",
|
| 168 |
+
"risk_probability": 0.9927212653417073
|
| 169 |
+
},
|
| 170 |
+
{
|
| 171 |
+
"cluster_id": "CAND12",
|
| 172 |
+
"customer_ids": [
|
| 173 |
+
"CUST0001",
|
| 174 |
+
"CUST0019",
|
| 175 |
+
"CUST0040",
|
| 176 |
+
"CUST0126",
|
| 177 |
+
"CUST0138",
|
| 178 |
+
"CUST0168",
|
| 179 |
+
"CUST0211",
|
| 180 |
+
"CUST0219",
|
| 181 |
+
"CUST0258",
|
| 182 |
+
"CUST0281",
|
| 183 |
+
"CUST0292",
|
| 184 |
+
"CUST0322",
|
| 185 |
+
"CUST0325",
|
| 186 |
+
"CUST0371",
|
| 187 |
+
"CUST0373",
|
| 188 |
+
"CUST0400",
|
| 189 |
+
"CUST0419",
|
| 190 |
+
"CUST0465"
|
| 191 |
+
],
|
| 192 |
+
"size": 18,
|
| 193 |
+
"strong_link_count": 0,
|
| 194 |
+
"weak_link_count": 41,
|
| 195 |
+
"formation_type": "weak_only",
|
| 196 |
+
"method": "louvain",
|
| 197 |
+
"risk_probability": 0.00720344453548541
|
| 198 |
+
},
|
| 199 |
+
{
|
| 200 |
+
"cluster_id": "CAND13",
|
| 201 |
+
"customer_ids": [
|
| 202 |
+
"CUST0002",
|
| 203 |
+
"CUST0009",
|
| 204 |
+
"CUST0020",
|
| 205 |
+
"CUST0041",
|
| 206 |
+
"CUST0064",
|
| 207 |
+
"CUST0073",
|
| 208 |
+
"CUST0074",
|
| 209 |
+
"CUST0080",
|
| 210 |
+
"CUST0081",
|
| 211 |
+
"CUST0086",
|
| 212 |
+
"CUST0089",
|
| 213 |
+
"CUST0103",
|
| 214 |
+
"CUST0162",
|
| 215 |
+
"CUST0167",
|
| 216 |
+
"CUST0173",
|
| 217 |
+
"CUST0181",
|
| 218 |
+
"CUST0226",
|
| 219 |
+
"CUST0240",
|
| 220 |
+
"CUST0253",
|
| 221 |
+
"CUST0262",
|
| 222 |
+
"CUST0272",
|
| 223 |
+
"CUST0286",
|
| 224 |
+
"CUST0287",
|
| 225 |
+
"CUST0324",
|
| 226 |
+
"CUST0331",
|
| 227 |
+
"CUST0333",
|
| 228 |
+
"CUST0369",
|
| 229 |
+
"CUST0392",
|
| 230 |
+
"CUST0393",
|
| 231 |
+
"CUST0398",
|
| 232 |
+
"CUST0406",
|
| 233 |
+
"CUST0410",
|
| 234 |
+
"CUST0411",
|
| 235 |
+
"CUST0413",
|
| 236 |
+
"CUST0415",
|
| 237 |
+
"CUST0423",
|
| 238 |
+
"CUST0446",
|
| 239 |
+
"CUST0468",
|
| 240 |
+
"CUST0476",
|
| 241 |
+
"CUST0478",
|
| 242 |
+
"CUST0485"
|
| 243 |
+
],
|
| 244 |
+
"size": 41,
|
| 245 |
+
"strong_link_count": 0,
|
| 246 |
+
"weak_link_count": 146,
|
| 247 |
+
"formation_type": "weak_only",
|
| 248 |
+
"method": "louvain",
|
| 249 |
+
"risk_probability": 0.007559966037372132
|
| 250 |
+
},
|
| 251 |
+
{
|
| 252 |
+
"cluster_id": "CAND14",
|
| 253 |
+
"customer_ids": [
|
| 254 |
+
"CUST0003",
|
| 255 |
+
"CUST0012",
|
| 256 |
+
"CUST0043",
|
| 257 |
+
"CUST0077",
|
| 258 |
+
"CUST0088",
|
| 259 |
+
"CUST0098",
|
| 260 |
+
"CUST0109",
|
| 261 |
+
"CUST0125",
|
| 262 |
+
"CUST0139",
|
| 263 |
+
"CUST0153",
|
| 264 |
+
"CUST0159",
|
| 265 |
+
"CUST0166",
|
| 266 |
+
"CUST0180",
|
| 267 |
+
"CUST0201",
|
| 268 |
+
"CUST0209",
|
| 269 |
+
"CUST0245",
|
| 270 |
+
"CUST0261",
|
| 271 |
+
"CUST0265",
|
| 272 |
+
"CUST0273",
|
| 273 |
+
"CUST0277",
|
| 274 |
+
"CUST0297",
|
| 275 |
+
"CUST0315",
|
| 276 |
+
"CUST0334",
|
| 277 |
+
"CUST0347",
|
| 278 |
+
"CUST0381",
|
| 279 |
+
"CUST0405",
|
| 280 |
+
"CUST0412",
|
| 281 |
+
"CUST0428",
|
| 282 |
+
"CUST0429",
|
| 283 |
+
"CUST0462",
|
| 284 |
+
"CUST0471"
|
| 285 |
+
],
|
| 286 |
+
"size": 31,
|
| 287 |
+
"strong_link_count": 0,
|
| 288 |
+
"weak_link_count": 84,
|
| 289 |
+
"formation_type": "weak_only",
|
| 290 |
+
"method": "louvain",
|
| 291 |
+
"risk_probability": 0.0033586500336385537
|
| 292 |
+
},
|
| 293 |
+
{
|
| 294 |
+
"cluster_id": "CAND15",
|
| 295 |
+
"customer_ids": [
|
| 296 |
+
"CUST0004",
|
| 297 |
+
"CUST0008",
|
| 298 |
+
"CUST0027",
|
| 299 |
+
"CUST0030",
|
| 300 |
+
"CUST0042",
|
| 301 |
+
"CUST0063",
|
| 302 |
+
"CUST0075",
|
| 303 |
+
"CUST0087",
|
| 304 |
+
"CUST0110",
|
| 305 |
+
"CUST0117",
|
| 306 |
+
"CUST0120",
|
| 307 |
+
"CUST0133",
|
| 308 |
+
"CUST0135",
|
| 309 |
+
"CUST0137",
|
| 310 |
+
"CUST0144",
|
| 311 |
+
"CUST0152",
|
| 312 |
+
"CUST0154",
|
| 313 |
+
"CUST0163",
|
| 314 |
+
"CUST0170",
|
| 315 |
+
"CUST0178",
|
| 316 |
+
"CUST0179",
|
| 317 |
+
"CUST0195",
|
| 318 |
+
"CUST0198",
|
| 319 |
+
"CUST0208",
|
| 320 |
+
"CUST0210",
|
| 321 |
+
"CUST0221",
|
| 322 |
+
"CUST0228",
|
| 323 |
+
"CUST0231",
|
| 324 |
+
"CUST0237",
|
| 325 |
+
"CUST0246",
|
| 326 |
+
"CUST0251",
|
| 327 |
+
"CUST0254",
|
| 328 |
+
"CUST0266",
|
| 329 |
+
"CUST0282",
|
| 330 |
+
"CUST0295",
|
| 331 |
+
"CUST0300",
|
| 332 |
+
"CUST0303",
|
| 333 |
+
"CUST0304",
|
| 334 |
+
"CUST0335",
|
| 335 |
+
"CUST0355",
|
| 336 |
+
"CUST0365",
|
| 337 |
+
"CUST0399",
|
| 338 |
+
"CUST0420",
|
| 339 |
+
"CUST0425",
|
| 340 |
+
"CUST0470",
|
| 341 |
+
"CUST0483",
|
| 342 |
+
"CUST0486",
|
| 343 |
+
"CUST0487",
|
| 344 |
+
"CUST0491",
|
| 345 |
+
"CUST0492",
|
| 346 |
+
"CUST0498"
|
| 347 |
+
],
|
| 348 |
+
"size": 51,
|
| 349 |
+
"strong_link_count": 1,
|
| 350 |
+
"weak_link_count": 167,
|
| 351 |
+
"formation_type": "weak_only",
|
| 352 |
+
"method": "louvain",
|
| 353 |
+
"risk_probability": 0.007646314104742993
|
| 354 |
+
},
|
| 355 |
+
{
|
| 356 |
+
"cluster_id": "CAND16",
|
| 357 |
+
"customer_ids": [
|
| 358 |
+
"CUST0005",
|
| 359 |
+
"CUST0022",
|
| 360 |
+
"CUST0028",
|
| 361 |
+
"CUST0038",
|
| 362 |
+
"CUST0102",
|
| 363 |
+
"CUST0111",
|
| 364 |
+
"CUST0113",
|
| 365 |
+
"CUST0140",
|
| 366 |
+
"CUST0161",
|
| 367 |
+
"CUST0171",
|
| 368 |
+
"CUST0177",
|
| 369 |
+
"CUST0202",
|
| 370 |
+
"CUST0222",
|
| 371 |
+
"CUST0235",
|
| 372 |
+
"CUST0252",
|
| 373 |
+
"CUST0257",
|
| 374 |
+
"CUST0263",
|
| 375 |
+
"CUST0288",
|
| 376 |
+
"CUST0293",
|
| 377 |
+
"CUST0299",
|
| 378 |
+
"CUST0308",
|
| 379 |
+
"CUST0311",
|
| 380 |
+
"CUST0353",
|
| 381 |
+
"CUST0357",
|
| 382 |
+
"CUST0364",
|
| 383 |
+
"CUST0370",
|
| 384 |
+
"CUST0383",
|
| 385 |
+
"CUST0386",
|
| 386 |
+
"CUST0387",
|
| 387 |
+
"CUST0391",
|
| 388 |
+
"CUST0396",
|
| 389 |
+
"CUST0438",
|
| 390 |
+
"CUST0442",
|
| 391 |
+
"CUST0456",
|
| 392 |
+
"CUST0460",
|
| 393 |
+
"CUST0488",
|
| 394 |
+
"CUST0490",
|
| 395 |
+
"CUST0495",
|
| 396 |
+
"CUST0496",
|
| 397 |
+
"CUST0500"
|
| 398 |
+
],
|
| 399 |
+
"size": 40,
|
| 400 |
+
"strong_link_count": 0,
|
| 401 |
+
"weak_link_count": 112,
|
| 402 |
+
"formation_type": "weak_only",
|
| 403 |
+
"method": "louvain",
|
| 404 |
+
"risk_probability": 0.0035456513474297945
|
| 405 |
+
},
|
| 406 |
+
{
|
| 407 |
+
"cluster_id": "CAND17",
|
| 408 |
+
"customer_ids": [
|
| 409 |
+
"CUST0006",
|
| 410 |
+
"CUST0011",
|
| 411 |
+
"CUST0024",
|
| 412 |
+
"CUST0025",
|
| 413 |
+
"CUST0033",
|
| 414 |
+
"CUST0044",
|
| 415 |
+
"CUST0079",
|
| 416 |
+
"CUST0084",
|
| 417 |
+
"CUST0101",
|
| 418 |
+
"CUST0107",
|
| 419 |
+
"CUST0108",
|
| 420 |
+
"CUST0114",
|
| 421 |
+
"CUST0132",
|
| 422 |
+
"CUST0145",
|
| 423 |
+
"CUST0157",
|
| 424 |
+
"CUST0172",
|
| 425 |
+
"CUST0227",
|
| 426 |
+
"CUST0244",
|
| 427 |
+
"CUST0255",
|
| 428 |
+
"CUST0256",
|
| 429 |
+
"CUST0267",
|
| 430 |
+
"CUST0271",
|
| 431 |
+
"CUST0284",
|
| 432 |
+
"CUST0291",
|
| 433 |
+
"CUST0296",
|
| 434 |
+
"CUST0316",
|
| 435 |
+
"CUST0319",
|
| 436 |
+
"CUST0329",
|
| 437 |
+
"CUST0336",
|
| 438 |
+
"CUST0342",
|
| 439 |
+
"CUST0348",
|
| 440 |
+
"CUST0349",
|
| 441 |
+
"CUST0367",
|
| 442 |
+
"CUST0375",
|
| 443 |
+
"CUST0389",
|
| 444 |
+
"CUST0407",
|
| 445 |
+
"CUST0455",
|
| 446 |
+
"CUST0489",
|
| 447 |
+
"CUST0499"
|
| 448 |
+
],
|
| 449 |
+
"size": 39,
|
| 450 |
+
"strong_link_count": 1,
|
| 451 |
+
"weak_link_count": 95,
|
| 452 |
+
"formation_type": "weak_only",
|
| 453 |
+
"method": "louvain",
|
| 454 |
+
"risk_probability": 0.006896318028648148
|
| 455 |
+
},
|
| 456 |
+
{
|
| 457 |
+
"cluster_id": "CAND18",
|
| 458 |
+
"customer_ids": [
|
| 459 |
+
"CUST0007",
|
| 460 |
+
"CUST0014",
|
| 461 |
+
"CUST0015",
|
| 462 |
+
"CUST0016",
|
| 463 |
+
"CUST0032",
|
| 464 |
+
"CUST0037",
|
| 465 |
+
"CUST0065",
|
| 466 |
+
"CUST0069",
|
| 467 |
+
"CUST0070",
|
| 468 |
+
"CUST0095",
|
| 469 |
+
"CUST0106",
|
| 470 |
+
"CUST0115",
|
| 471 |
+
"CUST0124",
|
| 472 |
+
"CUST0131",
|
| 473 |
+
"CUST0149",
|
| 474 |
+
"CUST0191",
|
| 475 |
+
"CUST0200",
|
| 476 |
+
"CUST0204",
|
| 477 |
+
"CUST0215",
|
| 478 |
+
"CUST0218",
|
| 479 |
+
"CUST0223",
|
| 480 |
+
"CUST0238",
|
| 481 |
+
"CUST0239",
|
| 482 |
+
"CUST0241",
|
| 483 |
+
"CUST0242",
|
| 484 |
+
"CUST0264",
|
| 485 |
+
"CUST0276",
|
| 486 |
+
"CUST0280",
|
| 487 |
+
"CUST0305",
|
| 488 |
+
"CUST0314",
|
| 489 |
+
"CUST0323",
|
| 490 |
+
"CUST0327",
|
| 491 |
+
"CUST0339",
|
| 492 |
+
"CUST0350",
|
| 493 |
+
"CUST0352",
|
| 494 |
+
"CUST0356",
|
| 495 |
+
"CUST0358",
|
| 496 |
+
"CUST0362",
|
| 497 |
+
"CUST0379",
|
| 498 |
+
"CUST0401",
|
| 499 |
+
"CUST0418",
|
| 500 |
+
"CUST0440",
|
| 501 |
+
"CUST0443",
|
| 502 |
+
"CUST0449",
|
| 503 |
+
"CUST0479"
|
| 504 |
+
],
|
| 505 |
+
"size": 45,
|
| 506 |
+
"strong_link_count": 3,
|
| 507 |
+
"weak_link_count": 106,
|
| 508 |
+
"formation_type": "weak_only",
|
| 509 |
+
"method": "louvain",
|
| 510 |
+
"risk_probability": 0.0034784417949967547
|
| 511 |
+
},
|
| 512 |
+
{
|
| 513 |
+
"cluster_id": "CAND19",
|
| 514 |
+
"customer_ids": [
|
| 515 |
+
"CUST0010",
|
| 516 |
+
"CUST0023",
|
| 517 |
+
"CUST0029",
|
| 518 |
+
"CUST0090",
|
| 519 |
+
"CUST0119",
|
| 520 |
+
"CUST0121",
|
| 521 |
+
"CUST0129",
|
| 522 |
+
"CUST0141",
|
| 523 |
+
"CUST0143",
|
| 524 |
+
"CUST0155",
|
| 525 |
+
"CUST0196",
|
| 526 |
+
"CUST0207",
|
| 527 |
+
"CUST0230",
|
| 528 |
+
"CUST0233",
|
| 529 |
+
"CUST0247",
|
| 530 |
+
"CUST0330",
|
| 531 |
+
"CUST0338",
|
| 532 |
+
"CUST0372",
|
| 533 |
+
"CUST0374",
|
| 534 |
+
"CUST0380",
|
| 535 |
+
"CUST0461",
|
| 536 |
+
"CUST0467",
|
| 537 |
+
"CUST0480",
|
| 538 |
+
"CUST0493"
|
| 539 |
+
],
|
| 540 |
+
"size": 24,
|
| 541 |
+
"strong_link_count": 0,
|
| 542 |
+
"weak_link_count": 47,
|
| 543 |
+
"formation_type": "weak_only",
|
| 544 |
+
"method": "louvain",
|
| 545 |
+
"risk_probability": 0.007559966037372132
|
| 546 |
+
},
|
| 547 |
+
{
|
| 548 |
+
"cluster_id": "CAND20",
|
| 549 |
+
"customer_ids": [
|
| 550 |
+
"CUST0013",
|
| 551 |
+
"CUST0026",
|
| 552 |
+
"CUST0031",
|
| 553 |
+
"CUST0035",
|
| 554 |
+
"CUST0039",
|
| 555 |
+
"CUST0067",
|
| 556 |
+
"CUST0068",
|
| 557 |
+
"CUST0094",
|
| 558 |
+
"CUST0116",
|
| 559 |
+
"CUST0122",
|
| 560 |
+
"CUST0128",
|
| 561 |
+
"CUST0184",
|
| 562 |
+
"CUST0193",
|
| 563 |
+
"CUST0203",
|
| 564 |
+
"CUST0212",
|
| 565 |
+
"CUST0217",
|
| 566 |
+
"CUST0248",
|
| 567 |
+
"CUST0268",
|
| 568 |
+
"CUST0283",
|
| 569 |
+
"CUST0312",
|
| 570 |
+
"CUST0340",
|
| 571 |
+
"CUST0351",
|
| 572 |
+
"CUST0384",
|
| 573 |
+
"CUST0402",
|
| 574 |
+
"CUST0417",
|
| 575 |
+
"CUST0427",
|
| 576 |
+
"CUST0430",
|
| 577 |
+
"CUST0434",
|
| 578 |
+
"CUST0451",
|
| 579 |
+
"CUST0463",
|
| 580 |
+
"CUST0466",
|
| 581 |
+
"CUST0469",
|
| 582 |
+
"CUST0473",
|
| 583 |
+
"CUST0482",
|
| 584 |
+
"CUST0497"
|
| 585 |
+
],
|
| 586 |
+
"size": 35,
|
| 587 |
+
"strong_link_count": 0,
|
| 588 |
+
"weak_link_count": 84,
|
| 589 |
+
"formation_type": "weak_only",
|
| 590 |
+
"method": "louvain",
|
| 591 |
+
"risk_probability": 0.007561351403107364
|
| 592 |
+
},
|
| 593 |
+
{
|
| 594 |
+
"cluster_id": "CAND21",
|
| 595 |
+
"customer_ids": [
|
| 596 |
+
"CUST0017",
|
| 597 |
+
"CUST0036",
|
| 598 |
+
"CUST0062",
|
| 599 |
+
"CUST0071",
|
| 600 |
+
"CUST0082",
|
| 601 |
+
"CUST0083",
|
| 602 |
+
"CUST0085",
|
| 603 |
+
"CUST0096",
|
| 604 |
+
"CUST0123",
|
| 605 |
+
"CUST0142",
|
| 606 |
+
"CUST0147",
|
| 607 |
+
"CUST0175",
|
| 608 |
+
"CUST0189",
|
| 609 |
+
"CUST0216",
|
| 610 |
+
"CUST0220",
|
| 611 |
+
"CUST0224",
|
| 612 |
+
"CUST0232",
|
| 613 |
+
"CUST0234",
|
| 614 |
+
"CUST0306",
|
| 615 |
+
"CUST0328",
|
| 616 |
+
"CUST0337",
|
| 617 |
+
"CUST0341",
|
| 618 |
+
"CUST0345",
|
| 619 |
+
"CUST0346",
|
| 620 |
+
"CUST0361",
|
| 621 |
+
"CUST0388",
|
| 622 |
+
"CUST0421",
|
| 623 |
+
"CUST0426",
|
| 624 |
+
"CUST0433",
|
| 625 |
+
"CUST0435",
|
| 626 |
+
"CUST0444",
|
| 627 |
+
"CUST0450",
|
| 628 |
+
"CUST0454",
|
| 629 |
+
"CUST0477"
|
| 630 |
+
],
|
| 631 |
+
"size": 34,
|
| 632 |
+
"strong_link_count": 0,
|
| 633 |
+
"weak_link_count": 79,
|
| 634 |
+
"formation_type": "weak_only",
|
| 635 |
+
"method": "louvain",
|
| 636 |
+
"risk_probability": 0.0035456513474297945
|
| 637 |
+
},
|
| 638 |
+
{
|
| 639 |
+
"cluster_id": "CAND22",
|
| 640 |
+
"customer_ids": [
|
| 641 |
+
"CUST0018",
|
| 642 |
+
"CUST0021",
|
| 643 |
+
"CUST0091",
|
| 644 |
+
"CUST0092",
|
| 645 |
+
"CUST0112",
|
| 646 |
+
"CUST0160",
|
| 647 |
+
"CUST0174",
|
| 648 |
+
"CUST0187",
|
| 649 |
+
"CUST0270",
|
| 650 |
+
"CUST0298",
|
| 651 |
+
"CUST0307",
|
| 652 |
+
"CUST0310",
|
| 653 |
+
"CUST0332",
|
| 654 |
+
"CUST0343",
|
| 655 |
+
"CUST0431",
|
| 656 |
+
"CUST0474",
|
| 657 |
+
"CUST0475",
|
| 658 |
+
"CUST0494"
|
| 659 |
+
],
|
| 660 |
+
"size": 18,
|
| 661 |
+
"strong_link_count": 0,
|
| 662 |
+
"weak_link_count": 35,
|
| 663 |
+
"formation_type": "weak_only",
|
| 664 |
+
"method": "louvain",
|
| 665 |
+
"risk_probability": 0.03305941612108949
|
| 666 |
+
},
|
| 667 |
+
{
|
| 668 |
+
"cluster_id": "CAND23",
|
| 669 |
+
"customer_ids": [
|
| 670 |
+
"CUST0034",
|
| 671 |
+
"CUST0066",
|
| 672 |
+
"CUST0078",
|
| 673 |
+
"CUST0100",
|
| 674 |
+
"CUST0104",
|
| 675 |
+
"CUST0134",
|
| 676 |
+
"CUST0146",
|
| 677 |
+
"CUST0150",
|
| 678 |
+
"CUST0151",
|
| 679 |
+
"CUST0158",
|
| 680 |
+
"CUST0182",
|
| 681 |
+
"CUST0183",
|
| 682 |
+
"CUST0185",
|
| 683 |
+
"CUST0188",
|
| 684 |
+
"CUST0190",
|
| 685 |
+
"CUST0259",
|
| 686 |
+
"CUST0269",
|
| 687 |
+
"CUST0279",
|
| 688 |
+
"CUST0285",
|
| 689 |
+
"CUST0289",
|
| 690 |
+
"CUST0301",
|
| 691 |
+
"CUST0302",
|
| 692 |
+
"CUST0344",
|
| 693 |
+
"CUST0354",
|
| 694 |
+
"CUST0366",
|
| 695 |
+
"CUST0368",
|
| 696 |
+
"CUST0378",
|
| 697 |
+
"CUST0404",
|
| 698 |
+
"CUST0408",
|
| 699 |
+
"CUST0432",
|
| 700 |
+
"CUST0436",
|
| 701 |
+
"CUST0437",
|
| 702 |
+
"CUST0439",
|
| 703 |
+
"CUST0441",
|
| 704 |
+
"CUST0447",
|
| 705 |
+
"CUST0448",
|
| 706 |
+
"CUST0457",
|
| 707 |
+
"CUST0481"
|
| 708 |
+
],
|
| 709 |
+
"size": 38,
|
| 710 |
+
"strong_link_count": 0,
|
| 711 |
+
"weak_link_count": 90,
|
| 712 |
+
"formation_type": "weak_only",
|
| 713 |
+
"method": "louvain",
|
| 714 |
+
"risk_probability": 0.0035456513474297945
|
| 715 |
+
},
|
| 716 |
+
{
|
| 717 |
+
"cluster_id": "CAND24",
|
| 718 |
+
"customer_ids": [
|
| 719 |
+
"CUST0061",
|
| 720 |
+
"CUST0093",
|
| 721 |
+
"CUST0105",
|
| 722 |
+
"CUST0130",
|
| 723 |
+
"CUST0136",
|
| 724 |
+
"CUST0148",
|
| 725 |
+
"CUST0164",
|
| 726 |
+
"CUST0186",
|
| 727 |
+
"CUST0197",
|
| 728 |
+
"CUST0205",
|
| 729 |
+
"CUST0206",
|
| 730 |
+
"CUST0214",
|
| 731 |
+
"CUST0260",
|
| 732 |
+
"CUST0309",
|
| 733 |
+
"CUST0320",
|
| 734 |
+
"CUST0321",
|
| 735 |
+
"CUST0359",
|
| 736 |
+
"CUST0363",
|
| 737 |
+
"CUST0376",
|
| 738 |
+
"CUST0377",
|
| 739 |
+
"CUST0385",
|
| 740 |
+
"CUST0394",
|
| 741 |
+
"CUST0403",
|
| 742 |
+
"CUST0416",
|
| 743 |
+
"CUST0424",
|
| 744 |
+
"CUST0453"
|
| 745 |
+
],
|
| 746 |
+
"size": 26,
|
| 747 |
+
"strong_link_count": 0,
|
| 748 |
+
"weak_link_count": 71,
|
| 749 |
+
"formation_type": "weak_only",
|
| 750 |
+
"method": "louvain",
|
| 751 |
+
"risk_probability": 0.0035456513474297945
|
| 752 |
+
},
|
| 753 |
+
{
|
| 754 |
+
"cluster_id": "CAND25",
|
| 755 |
+
"customer_ids": [
|
| 756 |
+
"CUST0045",
|
| 757 |
+
"CUST0046",
|
| 758 |
+
"CUST0047",
|
| 759 |
+
"CUST0048"
|
| 760 |
+
],
|
| 761 |
+
"size": 4,
|
| 762 |
+
"strong_link_count": 0,
|
| 763 |
+
"weak_link_count": 6,
|
| 764 |
+
"formation_type": "weak_only",
|
| 765 |
+
"method": "connected_components",
|
| 766 |
+
"risk_probability": 0.0035484719416527992
|
| 767 |
+
},
|
| 768 |
+
{
|
| 769 |
+
"cluster_id": "CAND26",
|
| 770 |
+
"customer_ids": [
|
| 771 |
+
"CUST0049",
|
| 772 |
+
"CUST0050",
|
| 773 |
+
"CUST0051",
|
| 774 |
+
"CUST0052"
|
| 775 |
+
],
|
| 776 |
+
"size": 4,
|
| 777 |
+
"strong_link_count": 0,
|
| 778 |
+
"weak_link_count": 6,
|
| 779 |
+
"formation_type": "weak_only",
|
| 780 |
+
"method": "connected_components",
|
| 781 |
+
"risk_probability": 0.0031715868230902835
|
| 782 |
+
},
|
| 783 |
+
{
|
| 784 |
+
"cluster_id": "CAND27",
|
| 785 |
+
"customer_ids": [
|
| 786 |
+
"CUST0053",
|
| 787 |
+
"CUST0054",
|
| 788 |
+
"CUST0055",
|
| 789 |
+
"CUST0056"
|
| 790 |
+
],
|
| 791 |
+
"size": 4,
|
| 792 |
+
"strong_link_count": 0,
|
| 793 |
+
"weak_link_count": 6,
|
| 794 |
+
"formation_type": "weak_only",
|
| 795 |
+
"method": "connected_components",
|
| 796 |
+
"risk_probability": 0.003058997865465553
|
| 797 |
+
},
|
| 798 |
+
{
|
| 799 |
+
"cluster_id": "CAND28",
|
| 800 |
+
"customer_ids": [
|
| 801 |
+
"CUST0504",
|
| 802 |
+
"CUST0505",
|
| 803 |
+
"CUST0506"
|
| 804 |
+
],
|
| 805 |
+
"size": 3,
|
| 806 |
+
"strong_link_count": 0,
|
| 807 |
+
"weak_link_count": 3,
|
| 808 |
+
"formation_type": "weak_only",
|
| 809 |
+
"method": "connected_components",
|
| 810 |
+
"risk_probability": 0.003546939654202544
|
| 811 |
+
}
|
| 812 |
+
]
|
eval/.gitkeep
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
|
eval/eval_results.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"precision": 1.0,
|
| 3 |
+
"recall": 1.0,
|
| 4 |
+
"f1": 1.0,
|
| 5 |
+
"classification_threshold": 0.5,
|
| 6 |
+
"holdout_size": 22,
|
| 7 |
+
"holdout_positives": 12,
|
| 8 |
+
"holdout_negatives": 10,
|
| 9 |
+
"false_positive_cost_inr": 0.0,
|
| 10 |
+
"false_positive_clusters": [],
|
| 11 |
+
"latency_total_ms": 0.9449999997741543,
|
| 12 |
+
"latency_per_cluster_ms": 0.04295454544427974,
|
| 13 |
+
"policy_action_breakdown": {
|
| 14 |
+
"auto_hold": 0,
|
| 15 |
+
"escalate": 12,
|
| 16 |
+
"log_only": 10
|
| 17 |
+
},
|
| 18 |
+
"confusion_matrix": {
|
| 19 |
+
"true_positive": 12,
|
| 20 |
+
"false_positive": 0,
|
| 21 |
+
"true_negative": 10,
|
| 22 |
+
"false_negative": 0
|
| 23 |
+
}
|
| 24 |
+
}
|
eval/evaluate.py
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
evaluate.py
|
| 3 |
+
-----------
|
| 4 |
+
Evaluate the trained LightGBM model on the held-out split.
|
| 5 |
+
|
| 6 |
+
Outputs:
|
| 7 |
+
eval/eval_results.json β precision, recall, F1, false-positive cost,
|
| 8 |
+
latency, and policy-action breakdown.
|
| 9 |
+
|
| 10 |
+
Usage:
|
| 11 |
+
python eval/evaluate.py
|
| 12 |
+
"""
|
| 13 |
+
|
| 14 |
+
import json
|
| 15 |
+
import os
|
| 16 |
+
import sys
|
| 17 |
+
import time
|
| 18 |
+
|
| 19 |
+
import lightgbm as lgb
|
| 20 |
+
import numpy as np
|
| 21 |
+
from sklearn.metrics import precision_score, recall_score, f1_score
|
| 22 |
+
|
| 23 |
+
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 24 |
+
sys.path.insert(0, BASE_DIR)
|
| 25 |
+
|
| 26 |
+
SCORING_DIR = os.path.join(BASE_DIR, "scoring")
|
| 27 |
+
EVAL_DIR = os.path.join(BASE_DIR, "eval")
|
| 28 |
+
|
| 29 |
+
MODEL_PATH = os.path.join(SCORING_DIR, "model.lgb")
|
| 30 |
+
HOLDOUT_PATH = os.path.join(SCORING_DIR, "holdout_split.json")
|
| 31 |
+
RESULTS_PATH = os.path.join(EVAL_DIR, "eval_results.json")
|
| 32 |
+
|
| 33 |
+
CLASSIFICATION_THRESHOLD = 0.5
|
| 34 |
+
|
| 35 |
+
# Policy thresholds (must match agent/policy.py exactly)
|
| 36 |
+
POLICY_HIGH_THRESHOLD = 0.85
|
| 37 |
+
POLICY_MEDIUM_THRESHOLD = 0.50
|
| 38 |
+
POLICY_LOW_EXPOSURE = 5000.0
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
def policy_decide(risk_probability: float, exposure_rupees: float) -> str:
|
| 42 |
+
"""Deterministic policy gate β mirrors agent/policy.py exactly."""
|
| 43 |
+
if risk_probability >= POLICY_HIGH_THRESHOLD and exposure_rupees <= POLICY_LOW_EXPOSURE:
|
| 44 |
+
return "auto_hold"
|
| 45 |
+
if risk_probability >= POLICY_HIGH_THRESHOLD and exposure_rupees > POLICY_LOW_EXPOSURE:
|
| 46 |
+
return "escalate"
|
| 47 |
+
if POLICY_MEDIUM_THRESHOLD <= risk_probability < POLICY_HIGH_THRESHOLD:
|
| 48 |
+
return "escalate"
|
| 49 |
+
return "log_only"
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
def evaluate():
|
| 53 |
+
print(f"Loading model from {MODEL_PATH}...")
|
| 54 |
+
model = lgb.Booster(model_file=MODEL_PATH)
|
| 55 |
+
|
| 56 |
+
print(f"Loading holdout split from {HOLDOUT_PATH}...")
|
| 57 |
+
with open(HOLDOUT_PATH, encoding="utf-8") as f:
|
| 58 |
+
holdout = json.load(f)
|
| 59 |
+
|
| 60 |
+
print(f" {len(holdout)} held-out clusters")
|
| 61 |
+
|
| 62 |
+
# 6.1 β reconstruct feature matrix
|
| 63 |
+
from scoring.features import FEATURE_COLUMNS
|
| 64 |
+
|
| 65 |
+
feature_rows = [row["features"] for row in holdout]
|
| 66 |
+
y_true = np.array([row["label"] for row in holdout])
|
| 67 |
+
|
| 68 |
+
# 6.2 β time the feature extraction + inference pass
|
| 69 |
+
start = time.perf_counter()
|
| 70 |
+
X = np.array([[fr[f] for f in FEATURE_COLUMNS] for fr in feature_rows])
|
| 71 |
+
probs = model.predict(X)
|
| 72 |
+
elapsed = time.perf_counter() - start
|
| 73 |
+
|
| 74 |
+
y_pred = (probs >= CLASSIFICATION_THRESHOLD).astype(int)
|
| 75 |
+
|
| 76 |
+
precision = float(precision_score(y_true, y_pred, zero_division=0))
|
| 77 |
+
recall = float(recall_score(y_true, y_pred, zero_division=0))
|
| 78 |
+
f1 = float(f1_score(y_true, y_pred, zero_division=0))
|
| 79 |
+
latency_total_ms = elapsed * 1000
|
| 80 |
+
latency_per_cluster_ms = latency_total_ms / len(holdout)
|
| 81 |
+
|
| 82 |
+
print(f"\n--- Classification at threshold {CLASSIFICATION_THRESHOLD} ---")
|
| 83 |
+
print(f" Precision : {precision:.4f}")
|
| 84 |
+
print(f" Recall : {recall:.4f}")
|
| 85 |
+
print(f" F1 : {f1:.4f}")
|
| 86 |
+
print(f" Latency : {latency_total_ms:.2f} ms total, "
|
| 87 |
+
f"{latency_per_cluster_ms:.3f} ms/cluster")
|
| 88 |
+
|
| 89 |
+
# 6.3 β policy simulation on holdout
|
| 90 |
+
policy_counts = {"auto_hold": 0, "escalate": 0, "log_only": 0}
|
| 91 |
+
for i, row in enumerate(holdout):
|
| 92 |
+
prob = float(probs[i])
|
| 93 |
+
exposure = row["features"].get("total_amount", 0.0)
|
| 94 |
+
decision = policy_decide(prob, exposure)
|
| 95 |
+
policy_counts[decision] += 1
|
| 96 |
+
|
| 97 |
+
print(f"\n--- Policy simulation on holdout ---")
|
| 98 |
+
for action, count in policy_counts.items():
|
| 99 |
+
print(f" {action:12s}: {count}")
|
| 100 |
+
|
| 101 |
+
# 6.4 β false-positive cost
|
| 102 |
+
fp_cost = 0.0
|
| 103 |
+
fp_clusters = []
|
| 104 |
+
for i, row in enumerate(holdout):
|
| 105 |
+
if y_pred[i] == 1 and y_true[i] == 0:
|
| 106 |
+
amt = row["features"].get("total_amount", 0.0)
|
| 107 |
+
fp_cost += amt
|
| 108 |
+
fp_clusters.append({
|
| 109 |
+
"cluster_id": row["cluster_id"],
|
| 110 |
+
"total_amount": amt,
|
| 111 |
+
"risk_probability": float(probs[i]),
|
| 112 |
+
})
|
| 113 |
+
|
| 114 |
+
print(f"\n--- False-positive cost ---")
|
| 115 |
+
print(f" FP clusters: {len(fp_clusters)}")
|
| 116 |
+
print(f" FP cost (total_amount): Rs.{fp_cost:.2f}")
|
| 117 |
+
|
| 118 |
+
# 6.5 β latency already computed above
|
| 119 |
+
print(f"\n--- Latency ---")
|
| 120 |
+
print(f" Feature extraction + inference: {latency_per_cluster_ms:.3f} ms/cluster")
|
| 121 |
+
|
| 122 |
+
# 6.6 β write eval_results.json
|
| 123 |
+
os.makedirs(EVAL_DIR, exist_ok=True)
|
| 124 |
+
results = {
|
| 125 |
+
"precision": precision,
|
| 126 |
+
"recall": recall,
|
| 127 |
+
"f1": f1,
|
| 128 |
+
"classification_threshold": CLASSIFICATION_THRESHOLD,
|
| 129 |
+
"holdout_size": len(holdout),
|
| 130 |
+
"holdout_positives": int(y_true.sum()),
|
| 131 |
+
"holdout_negatives": int((len(y_true) - y_true.sum())),
|
| 132 |
+
"false_positive_cost_inr": fp_cost,
|
| 133 |
+
"false_positive_clusters": fp_clusters,
|
| 134 |
+
"latency_total_ms": latency_total_ms,
|
| 135 |
+
"latency_per_cluster_ms": latency_per_cluster_ms,
|
| 136 |
+
"policy_action_breakdown": policy_counts,
|
| 137 |
+
"confusion_matrix": {
|
| 138 |
+
"true_positive": int(((y_pred == 1) & (y_true == 1)).sum()),
|
| 139 |
+
"false_positive": int(((y_pred == 1) & (y_true == 0)).sum()),
|
| 140 |
+
"true_negative": int(((y_pred == 0) & (y_true == 0)).sum()),
|
| 141 |
+
"false_negative": int(((y_pred == 0) & (y_true == 1)).sum()),
|
| 142 |
+
},
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
with open(RESULTS_PATH, "w", encoding="utf-8") as f:
|
| 146 |
+
json.dump(results, f, indent=2, ensure_ascii=False)
|
| 147 |
+
print(f"\nEvaluation results saved to {RESULTS_PATH}")
|
| 148 |
+
|
| 149 |
+
return results
|
| 150 |
+
|
| 151 |
+
|
| 152 |
+
if __name__ == "__main__":
|
| 153 |
+
evaluate()
|
graph/.gitkeep
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
|
graph/build_graph.py
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
build_graph.py
|
| 3 |
+
--------------
|
| 4 |
+
Loads synthetic data from a data directory, applies entity resolution,
|
| 5 |
+
builds a heterogeneous NetworkX graph, and saves it to graph.gpickle
|
| 6 |
+
in the same directory.
|
| 7 |
+
|
| 8 |
+
Node types : customer, device, address, payment_instrument
|
| 9 |
+
Edge types : uses_device (strong), pays_with (strong),
|
| 10 |
+
ships_to (weak), same_contact (strong)
|
| 11 |
+
|
| 12 |
+
Each edge carries: relation, strength, first_seen, last_seen, count, order_ids
|
| 13 |
+
|
| 14 |
+
Usage:
|
| 15 |
+
python graph/build_graph.py [--data-dir PATH]
|
| 16 |
+
DATA_DIR defaults to data/synthetic/
|
| 17 |
+
"""
|
| 18 |
+
|
| 19 |
+
import argparse
|
| 20 |
+
import json
|
| 21 |
+
import os
|
| 22 |
+
import pickle
|
| 23 |
+
import re
|
| 24 |
+
from collections import defaultdict
|
| 25 |
+
|
| 26 |
+
import networkx as nx
|
| 27 |
+
|
| 28 |
+
# ---------------------------------------------------------------------------
|
| 29 |
+
# Paths
|
| 30 |
+
# ---------------------------------------------------------------------------
|
| 31 |
+
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
def _load(filename, data_dir):
|
| 35 |
+
with open(os.path.join(data_dir, filename), encoding="utf-8") as f:
|
| 36 |
+
return json.load(f)
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
# ---------------------------------------------------------------------------
|
| 40 |
+
# Entity resolution helpers (3.1 β 3.4)
|
| 41 |
+
# ---------------------------------------------------------------------------
|
| 42 |
+
|
| 43 |
+
def normalize_phone(raw: str) -> str:
|
| 44 |
+
"""Strip non-digits; drop a leading country code (91 for India, 1 for US)."""
|
| 45 |
+
digits = re.sub(r"\D", "", raw)
|
| 46 |
+
# Drop leading 91 (India) or 1 (US) if the result would be 10 digits
|
| 47 |
+
for prefix in ("91", "1"):
|
| 48 |
+
if digits.startswith(prefix) and len(digits) - len(prefix) == 10:
|
| 49 |
+
digits = digits[len(prefix):]
|
| 50 |
+
break
|
| 51 |
+
return digits
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
def normalize_email(raw: str) -> str:
|
| 55 |
+
"""Lowercase and strip whitespace."""
|
| 56 |
+
return raw.lower().strip()
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
def normalize_address(raw: str) -> str:
|
| 60 |
+
"""Lowercase, strip whitespace, collapse multiple spaces."""
|
| 61 |
+
return re.sub(r"\s+", " ", raw.lower().strip())
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
# ---------------------------------------------------------------------------
|
| 65 |
+
# Graph construction
|
| 66 |
+
# ---------------------------------------------------------------------------
|
| 67 |
+
|
| 68 |
+
def build_graph(data_dir: str = None) -> nx.Graph:
|
| 69 |
+
if data_dir is None:
|
| 70 |
+
data_dir = os.path.join(BASE_DIR, "data", "synthetic")
|
| 71 |
+
# Load data
|
| 72 |
+
customers = _load("customers.json", data_dir)
|
| 73 |
+
devices = _load("devices.json", data_dir)
|
| 74 |
+
addresses = _load("addresses.json", data_dir)
|
| 75 |
+
payment_instr = _load("payment_instruments.json", data_dir)
|
| 76 |
+
orders = _load("orders.json", data_dir)
|
| 77 |
+
|
| 78 |
+
# Apply entity resolution (normalizations run on load β see ground rules 3.4)
|
| 79 |
+
# For the synthetic data these are effectively no-ops since fields are already
|
| 80 |
+
# hashed/normalized, but the hooks are live for real-data use.
|
| 81 |
+
for c in customers:
|
| 82 |
+
# phone_hash and email_hash are already SHA256 digests β we normalize
|
| 83 |
+
# the raw strings before hashing in a real pipeline; here we just ensure
|
| 84 |
+
# the lookup maps are keyed consistently.
|
| 85 |
+
pass # hash fields are already canonical
|
| 86 |
+
|
| 87 |
+
# Build lookup maps
|
| 88 |
+
device_map = {d["device_id"]: d for d in devices}
|
| 89 |
+
addr_map = {a["address_id"]: a for a in addresses}
|
| 90 |
+
instr_map = {p["instrument_id"]: p for p in payment_instr}
|
| 91 |
+
cust_map = {c["customer_id"]: c for c in customers}
|
| 92 |
+
|
| 93 |
+
G = nx.Graph()
|
| 94 |
+
|
| 95 |
+
# ---------------------------------------------------------------------------
|
| 96 |
+
# Add all nodes with their type attribute (3.5)
|
| 97 |
+
# ---------------------------------------------------------------------------
|
| 98 |
+
for c in customers:
|
| 99 |
+
G.add_node(c["customer_id"], node_type="customer", **{
|
| 100 |
+
k: v for k, v in c.items() if k != "customer_id"
|
| 101 |
+
})
|
| 102 |
+
|
| 103 |
+
for d in devices:
|
| 104 |
+
G.add_node(d["device_id"], node_type="device", **{
|
| 105 |
+
k: v for k, v in d.items() if k != "device_id"
|
| 106 |
+
})
|
| 107 |
+
|
| 108 |
+
for a in addresses:
|
| 109 |
+
G.add_node(a["address_id"], node_type="address", **{
|
| 110 |
+
k: v for k, v in a.items() if k != "address_id"
|
| 111 |
+
})
|
| 112 |
+
|
| 113 |
+
for p in payment_instr:
|
| 114 |
+
G.add_node(p["instrument_id"], node_type="payment_instrument", **{
|
| 115 |
+
k: v for k, v in p.items() if k != "instrument_id"
|
| 116 |
+
})
|
| 117 |
+
|
| 118 |
+
# ---------------------------------------------------------------------------
|
| 119 |
+
# Accumulate edge data from orders before writing to graph
|
| 120 |
+
# edge_accum[(u, v)] = {"relation":..., "strength":..., "timestamps":[...], "order_ids":[...]}
|
| 121 |
+
# ---------------------------------------------------------------------------
|
| 122 |
+
EdgeKey = tuple # (node_a, node_b) always sorted so undirected
|
| 123 |
+
edge_accum: dict[EdgeKey, dict] = defaultdict(lambda: {
|
| 124 |
+
"relation": None, "strength": None, "timestamps": [], "order_ids": []
|
| 125 |
+
})
|
| 126 |
+
|
| 127 |
+
def _add_edge_data(u, v, relation, strength, timestamp, order_id):
|
| 128 |
+
key = (min(u, v), max(u, v))
|
| 129 |
+
ea = edge_accum[key]
|
| 130 |
+
ea["relation"] = relation
|
| 131 |
+
ea["strength"] = strength
|
| 132 |
+
ea["timestamps"].append(timestamp)
|
| 133 |
+
ea["order_ids"].append(order_id)
|
| 134 |
+
|
| 135 |
+
for order in orders:
|
| 136 |
+
cid = order["customer_id"]
|
| 137 |
+
did = order["device_id"]
|
| 138 |
+
iid = order["payment_instrument_id"]
|
| 139 |
+
aid = order["address_id"]
|
| 140 |
+
ts = order["timestamp"]
|
| 141 |
+
oid = order["order_id"]
|
| 142 |
+
|
| 143 |
+
# customer βusesβ device (strong)
|
| 144 |
+
_add_edge_data(cid, did, "uses_device", "strong", ts, oid)
|
| 145 |
+
|
| 146 |
+
# customer βpays_withβ payment_instrument (strong)
|
| 147 |
+
_add_edge_data(cid, iid, "pays_with", "strong", ts, oid)
|
| 148 |
+
|
| 149 |
+
# customer βships_toβ address (weak)
|
| 150 |
+
_add_edge_data(cid, aid, "ships_to", "weak", ts, oid)
|
| 151 |
+
|
| 152 |
+
# ---------------------------------------------------------------------------
|
| 153 |
+
# customer βsame_contactβ customer edges (3.6 last bullet)
|
| 154 |
+
# Two customers share the same email_hash OR phone_hash β strong link
|
| 155 |
+
# ---------------------------------------------------------------------------
|
| 156 |
+
email_to_custs: dict[str, list[str]] = defaultdict(list)
|
| 157 |
+
phone_to_custs: dict[str, list[str]] = defaultdict(list)
|
| 158 |
+
|
| 159 |
+
for c in customers:
|
| 160 |
+
email_to_custs[c["email_hash"]].append(c["customer_id"])
|
| 161 |
+
phone_to_custs[c["phone_hash"]].append(c["customer_id"])
|
| 162 |
+
|
| 163 |
+
same_contact_pairs: set[tuple] = set()
|
| 164 |
+
for group in list(email_to_custs.values()) + list(phone_to_custs.values()):
|
| 165 |
+
if len(group) > 1:
|
| 166 |
+
for i in range(len(group)):
|
| 167 |
+
for j in range(i + 1, len(group)):
|
| 168 |
+
pair = (min(group[i], group[j]), max(group[i], group[j]))
|
| 169 |
+
same_contact_pairs.add(pair)
|
| 170 |
+
|
| 171 |
+
# Use a synthetic timestamp for same_contact edges (first order timestamp of either cust)
|
| 172 |
+
cust_first_ts: dict[str, str] = {}
|
| 173 |
+
cust_orders: dict[str, list] = defaultdict(list)
|
| 174 |
+
for o in orders:
|
| 175 |
+
cust_orders[o["customer_id"]].append(o)
|
| 176 |
+
for cid, ords in cust_orders.items():
|
| 177 |
+
sorted_ts = sorted(ords, key=lambda x: x["timestamp"])
|
| 178 |
+
cust_first_ts[cid] = sorted_ts[0]["timestamp"]
|
| 179 |
+
|
| 180 |
+
for (ca, cb) in same_contact_pairs:
|
| 181 |
+
ts = min(cust_first_ts.get(ca, "2026-01-01T00:00:00"),
|
| 182 |
+
cust_first_ts.get(cb, "2026-01-01T00:00:00"))
|
| 183 |
+
key = (ca, cb)
|
| 184 |
+
edge_accum[key]["relation"] = "same_contact"
|
| 185 |
+
edge_accum[key]["strength"] = "strong"
|
| 186 |
+
edge_accum[key]["timestamps"].append(ts)
|
| 187 |
+
edge_accum[key]["order_ids"].append("CONTACT_MATCH")
|
| 188 |
+
|
| 189 |
+
# ---------------------------------------------------------------------------
|
| 190 |
+
# Write all accumulated edges to the graph (3.7)
|
| 191 |
+
# ---------------------------------------------------------------------------
|
| 192 |
+
for (u, v), data in edge_accum.items():
|
| 193 |
+
sorted_ts = sorted(data["timestamps"])
|
| 194 |
+
G.add_edge(
|
| 195 |
+
u, v,
|
| 196 |
+
relation=data["relation"],
|
| 197 |
+
strength=data["strength"],
|
| 198 |
+
first_seen=sorted_ts[0] if sorted_ts else None,
|
| 199 |
+
last_seen=sorted_ts[-1] if sorted_ts else None,
|
| 200 |
+
count=len(data["order_ids"]),
|
| 201 |
+
order_ids=data["order_ids"],
|
| 202 |
+
)
|
| 203 |
+
|
| 204 |
+
return G
|
| 205 |
+
|
| 206 |
+
|
| 207 |
+
# ---------------------------------------------------------------------------
|
| 208 |
+
# Save graph (3.8) β try write_gpickle; fall back to pickle.dump if unavailable
|
| 209 |
+
# ---------------------------------------------------------------------------
|
| 210 |
+
def save_graph(G: nx.Graph, path: str):
|
| 211 |
+
try:
|
| 212 |
+
nx.write_gpickle(G, path)
|
| 213 |
+
return "nx.write_gpickle"
|
| 214 |
+
except AttributeError:
|
| 215 |
+
# networkx >= 3.0 removed write_gpickle β use pickle directly
|
| 216 |
+
with open(path, "wb") as f:
|
| 217 |
+
pickle.dump(G, f, protocol=pickle.HIGHEST_PROTOCOL)
|
| 218 |
+
return "pickle.dump (nx.write_gpickle unavailable in this nx version)"
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
def load_graph(path: str) -> nx.Graph:
|
| 222 |
+
try:
|
| 223 |
+
return nx.read_gpickle(path)
|
| 224 |
+
except AttributeError:
|
| 225 |
+
with open(path, "rb") as f:
|
| 226 |
+
return pickle.load(f)
|
| 227 |
+
|
| 228 |
+
|
| 229 |
+
# ---------------------------------------------------------------------------
|
| 230 |
+
# Console stats (3.9)
|
| 231 |
+
# ---------------------------------------------------------------------------
|
| 232 |
+
def print_stats(G: nx.Graph):
|
| 233 |
+
from collections import Counter
|
| 234 |
+
|
| 235 |
+
node_type_counts = Counter(
|
| 236 |
+
data.get("node_type", "unknown")
|
| 237 |
+
for _, data in G.nodes(data=True)
|
| 238 |
+
)
|
| 239 |
+
|
| 240 |
+
edge_rel_counts: dict[str, dict] = defaultdict(lambda: {"strong": 0, "weak": 0, "total": 0})
|
| 241 |
+
for u, v, data in G.edges(data=True):
|
| 242 |
+
rel = data.get("relation", "unknown")
|
| 243 |
+
strength = data.get("strength", "unknown")
|
| 244 |
+
edge_rel_counts[rel][strength] = edge_rel_counts[rel].get(strength, 0) + 1
|
| 245 |
+
edge_rel_counts[rel]["total"] += 1
|
| 246 |
+
|
| 247 |
+
cust_degrees = [
|
| 248 |
+
d for n, d in G.degree()
|
| 249 |
+
if G.nodes[n].get("node_type") == "customer"
|
| 250 |
+
]
|
| 251 |
+
|
| 252 |
+
print("\n========== Graph Statistics ==========")
|
| 253 |
+
print("Nodes by type:")
|
| 254 |
+
for ntype, cnt in sorted(node_type_counts.items()):
|
| 255 |
+
print(f" {ntype:25s}: {cnt}")
|
| 256 |
+
print(f" {'TOTAL':25s}: {G.number_of_nodes()}")
|
| 257 |
+
|
| 258 |
+
print("\nEdges by relation / strength:")
|
| 259 |
+
for rel, counts in sorted(edge_rel_counts.items()):
|
| 260 |
+
strong = counts.get("strong", 0)
|
| 261 |
+
weak = counts.get("weak", 0)
|
| 262 |
+
total = counts["total"]
|
| 263 |
+
print(f" {rel:25s}: total={total:5d} strong={strong:5d} weak={weak:5d}")
|
| 264 |
+
print(f" {'TOTAL':25s}: {G.number_of_edges()}")
|
| 265 |
+
|
| 266 |
+
if cust_degrees:
|
| 267 |
+
print(f"\nCustomer node degree β min={min(cust_degrees)} "
|
| 268 |
+
f"max={max(cust_degrees)} "
|
| 269 |
+
f"avg={sum(cust_degrees)/len(cust_degrees):.2f}")
|
| 270 |
+
print("======================================")
|
| 271 |
+
|
| 272 |
+
|
| 273 |
+
# ---------------------------------------------------------------------------
|
| 274 |
+
# Entry point
|
| 275 |
+
# ---------------------------------------------------------------------------
|
| 276 |
+
if __name__ == "__main__":
|
| 277 |
+
parser = argparse.ArgumentParser()
|
| 278 |
+
parser.add_argument(
|
| 279 |
+
"--data-dir",
|
| 280 |
+
default=None,
|
| 281 |
+
help="Path to data directory (containing JSON files). Defaults to data/synthetic/",
|
| 282 |
+
)
|
| 283 |
+
args = parser.parse_args()
|
| 284 |
+
|
| 285 |
+
data_dir = args.data_dir or os.path.join(BASE_DIR, "data", "synthetic")
|
| 286 |
+
print(f"Building graph from {data_dir} ...")
|
| 287 |
+
G = build_graph(data_dir)
|
| 288 |
+
|
| 289 |
+
out_path = os.path.join(data_dir, "graph.gpickle")
|
| 290 |
+
method = save_graph(G, out_path)
|
| 291 |
+
print(f"Graph saved to {out_path} (method: {method})")
|
| 292 |
+
|
| 293 |
+
# Verify reload
|
| 294 |
+
G2 = load_graph(out_path)
|
| 295 |
+
assert G2.number_of_nodes() == G.number_of_nodes(), "Reload node count mismatch!"
|
| 296 |
+
assert G2.number_of_edges() == G.number_of_edges(), "Reload edge count mismatch!"
|
| 297 |
+
print("Reload verified OK.")
|
| 298 |
+
|
| 299 |
+
print_stats(G)
|
graph/detect_communities.py
ADDED
|
@@ -0,0 +1,466 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
detect_communities.py
|
| 3 |
+
---------------------
|
| 4 |
+
Loads graph.gpickle, builds two separate customer-customer projections
|
| 5 |
+
(strong-anchored and weak-only), runs community detection on each,
|
| 6 |
+
filters candidate clusters, validates against ground truth, and writes
|
| 7 |
+
candidate_clusters.json.
|
| 8 |
+
|
| 9 |
+
Phase 2 fix: uses two separate connectivity passes instead of one blended
|
| 10 |
+
weight projection, preventing incidental address-sharing from merging
|
| 11 |
+
otherwise-unrelated rings into a single blob.
|
| 12 |
+
|
| 13 |
+
Usage:
|
| 14 |
+
python graph/detect_communities.py [--data-dir DATA_DIR]
|
| 15 |
+
|
| 16 |
+
DATA_DIR defaults to data/synthetic/
|
| 17 |
+
"""
|
| 18 |
+
|
| 19 |
+
import argparse
|
| 20 |
+
import json
|
| 21 |
+
import os
|
| 22 |
+
import pickle
|
| 23 |
+
import sys
|
| 24 |
+
from collections import defaultdict
|
| 25 |
+
|
| 26 |
+
import community as community_louvain # python-louvain
|
| 27 |
+
import networkx as nx
|
| 28 |
+
|
| 29 |
+
# ---------------------------------------------------------------------------
|
| 30 |
+
# Paths (overridable via CLI so the same script serves both datasets)
|
| 31 |
+
# ---------------------------------------------------------------------------
|
| 32 |
+
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 33 |
+
|
| 34 |
+
LOUVAIN_THRESHOLD = 12
|
| 35 |
+
LOUVAIN_RESOLUTION = 1.0
|
| 36 |
+
LOUVAIN_SEED = 42
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
# ---------------------------------------------------------------------------
|
| 40 |
+
# Load graph (handles both nx.read_gpickle and pickle.load fallback)
|
| 41 |
+
# ---------------------------------------------------------------------------
|
| 42 |
+
def load_graph(path: str) -> nx.Graph:
|
| 43 |
+
try:
|
| 44 |
+
return nx.read_gpickle(path)
|
| 45 |
+
except AttributeError:
|
| 46 |
+
with open(path, "rb") as f:
|
| 47 |
+
return pickle.load(f)
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
# ---------------------------------------------------------------------------
|
| 51 |
+
# 1.2 Build two customer-customer projections
|
| 52 |
+
# ---------------------------------------------------------------------------
|
| 53 |
+
|
| 54 |
+
# Strong edge formation threshold: a customer-entity-customer edge only counts
|
| 55 |
+
# as a strong link if the customer has used that shared entity in >= 2 orders.
|
| 56 |
+
# This filters out accidental single-order pool collisions (which would create
|
| 57 |
+
# cross-ring contamination) while preserving intentional ring device sharing
|
| 58 |
+
# (rings place 2-4 orders per member on their shared device).
|
| 59 |
+
# same_contact edges are always strong regardless of order count.
|
| 60 |
+
STRONG_EDGE_MIN_ORDERS = 2
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
def _build_entity_customer_index(G: nx.Graph):
|
| 64 |
+
"""
|
| 65 |
+
Returns three items:
|
| 66 |
+
strong_entity_to_custs: entity_id β list of (customer_id, order_count)
|
| 67 |
+
for STRONG edges (uses_device / pays_with).
|
| 68 |
+
weak_entity_to_custs: entity_id β list of customer_ids for WEAK edges.
|
| 69 |
+
same_contact_pairs: list of (customer_a, customer_b) direct strong edges.
|
| 70 |
+
"""
|
| 71 |
+
strong_entity_to_custs: dict[str, list[tuple[str, int]]] = defaultdict(list)
|
| 72 |
+
weak_entity_to_custs: dict[str, list[str]] = defaultdict(list)
|
| 73 |
+
same_contact_pairs: list[tuple[str, str]] = []
|
| 74 |
+
|
| 75 |
+
for u, v, data in G.edges(data=True):
|
| 76 |
+
u_type = G.nodes[u].get("node_type", "")
|
| 77 |
+
v_type = G.nodes[v].get("node_type", "")
|
| 78 |
+
|
| 79 |
+
# same_contact is a direct customer-customer strong edge
|
| 80 |
+
if data.get("relation") == "same_contact":
|
| 81 |
+
if u_type == "customer" and v_type == "customer":
|
| 82 |
+
same_contact_pairs.append((u, v))
|
| 83 |
+
continue
|
| 84 |
+
|
| 85 |
+
# For customer-entity edges determine which customer and which entity
|
| 86 |
+
if u_type == "customer" and v_type != "customer":
|
| 87 |
+
cust, entity = u, v
|
| 88 |
+
elif v_type == "customer" and u_type != "customer":
|
| 89 |
+
cust, entity = v, u
|
| 90 |
+
else:
|
| 91 |
+
continue
|
| 92 |
+
|
| 93 |
+
strength = data.get("strength", "weak")
|
| 94 |
+
order_count = data.get("count", 1)
|
| 95 |
+
if strength == "strong":
|
| 96 |
+
strong_entity_to_custs[entity].append((cust, order_count))
|
| 97 |
+
else:
|
| 98 |
+
weak_entity_to_custs[entity].append(cust)
|
| 99 |
+
|
| 100 |
+
return strong_entity_to_custs, weak_entity_to_custs, same_contact_pairs
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
def build_strong_subgraph(G: nx.Graph) -> nx.Graph:
|
| 104 |
+
"""
|
| 105 |
+
Edge between two customers exists only if they share >= 1 STRONG link
|
| 106 |
+
(shared device used >= STRONG_EDGE_MIN_ORDERS times, shared payment instrument
|
| 107 |
+
used >= STRONG_EDGE_MIN_ORDERS times, or same_contact).
|
| 108 |
+
Edge weight = count of shared strong-link attributes.
|
| 109 |
+
|
| 110 |
+
The order-count threshold eliminates accidental single-order pool collisions
|
| 111 |
+
that would create false cross-ring bridges in the data.
|
| 112 |
+
"""
|
| 113 |
+
strong_entity_to_custs, _, same_contact_pairs = _build_entity_customer_index(G)
|
| 114 |
+
|
| 115 |
+
all_customers = [n for n, d in G.nodes(data=True) if d.get("node_type") == "customer"]
|
| 116 |
+
SG = nx.Graph()
|
| 117 |
+
SG.add_nodes_from(all_customers)
|
| 118 |
+
|
| 119 |
+
# Shared entity edges β only for customers meeting the order-count threshold
|
| 120 |
+
for entity, custs_and_counts in strong_entity_to_custs.items():
|
| 121 |
+
eligible = [(c, cnt) for c, cnt in custs_and_counts if cnt >= STRONG_EDGE_MIN_ORDERS]
|
| 122 |
+
if len(eligible) < 2:
|
| 123 |
+
continue
|
| 124 |
+
for i in range(len(eligible)):
|
| 125 |
+
for j in range(i + 1, len(eligible)):
|
| 126 |
+
ca, _ = eligible[i]
|
| 127 |
+
cb, _ = eligible[j]
|
| 128 |
+
if ca == cb:
|
| 129 |
+
continue
|
| 130 |
+
if SG.has_edge(ca, cb):
|
| 131 |
+
SG[ca][cb]["weight"] += 1
|
| 132 |
+
SG[ca][cb]["strong_share_count"] += 1
|
| 133 |
+
else:
|
| 134 |
+
SG.add_edge(ca, cb, weight=1, strong_share_count=1, weak_share_count=0)
|
| 135 |
+
|
| 136 |
+
# same_contact direct edges (no order-count threshold β contact match is always strong)
|
| 137 |
+
for (ca, cb) in same_contact_pairs:
|
| 138 |
+
if SG.has_edge(ca, cb):
|
| 139 |
+
SG[ca][cb]["weight"] += 1
|
| 140 |
+
SG[ca][cb]["strong_share_count"] += 1
|
| 141 |
+
else:
|
| 142 |
+
SG.add_edge(ca, cb, weight=1, strong_share_count=1, weak_share_count=0)
|
| 143 |
+
|
| 144 |
+
return SG
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
def build_weak_only_subgraph(G: nx.Graph, strong_subgraph: nx.Graph) -> nx.Graph:
|
| 148 |
+
"""
|
| 149 |
+
Edge between two customers exists only if they share >= 1 WEAK link (address)
|
| 150 |
+
AND they share ZERO strong links (i.e., not already connected in strong_subgraph).
|
| 151 |
+
Edge weight = count of shared weak-link attributes.
|
| 152 |
+
"""
|
| 153 |
+
_, weak_entity_to_custs, _ = _build_entity_customer_index(G)
|
| 154 |
+
|
| 155 |
+
all_customers = [n for n, d in G.nodes(data=True) if d.get("node_type") == "customer"]
|
| 156 |
+
WG = nx.Graph()
|
| 157 |
+
WG.add_nodes_from(all_customers)
|
| 158 |
+
|
| 159 |
+
for entity, custs in weak_entity_to_custs.items():
|
| 160 |
+
if len(custs) < 2:
|
| 161 |
+
continue
|
| 162 |
+
for i in range(len(custs)):
|
| 163 |
+
for j in range(i + 1, len(custs)):
|
| 164 |
+
ca, cb = custs[i], custs[j]
|
| 165 |
+
if ca == cb:
|
| 166 |
+
continue
|
| 167 |
+
# Skip if the pair has any strong link
|
| 168 |
+
if strong_subgraph.has_edge(ca, cb):
|
| 169 |
+
continue
|
| 170 |
+
if WG.has_edge(ca, cb):
|
| 171 |
+
WG[ca][cb]["weight"] += 1
|
| 172 |
+
WG[ca][cb]["weak_share_count"] += 1
|
| 173 |
+
else:
|
| 174 |
+
WG.add_edge(ca, cb, weight=1, strong_share_count=0, weak_share_count=1)
|
| 175 |
+
|
| 176 |
+
return WG
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
# ---------------------------------------------------------------------------
|
| 180 |
+
# 1.3 + 1.4 Community detection on each subgraph
|
| 181 |
+
# ---------------------------------------------------------------------------
|
| 182 |
+
|
| 183 |
+
def detect_on_subgraph(subgraph: nx.Graph, formation_type: str) -> list[tuple[frozenset, str, str]]:
|
| 184 |
+
"""
|
| 185 |
+
Returns list of (frozenset_of_customer_ids, method_string, formation_type).
|
| 186 |
+
"""
|
| 187 |
+
connected_nodes = [n for n in subgraph.nodes() if subgraph.degree(n) > 0]
|
| 188 |
+
if not connected_nodes:
|
| 189 |
+
return []
|
| 190 |
+
CG_connected = subgraph.subgraph(connected_nodes)
|
| 191 |
+
components = list(nx.connected_components(CG_connected))
|
| 192 |
+
communities = []
|
| 193 |
+
|
| 194 |
+
for comp in components:
|
| 195 |
+
if len(comp) <= LOUVAIN_THRESHOLD:
|
| 196 |
+
communities.append((frozenset(comp), "connected_components", formation_type))
|
| 197 |
+
else:
|
| 198 |
+
sub = subgraph.subgraph(comp).copy()
|
| 199 |
+
partition = community_louvain.best_partition(
|
| 200 |
+
sub,
|
| 201 |
+
weight="weight",
|
| 202 |
+
resolution=LOUVAIN_RESOLUTION,
|
| 203 |
+
random_state=LOUVAIN_SEED,
|
| 204 |
+
)
|
| 205 |
+
sub_communities: dict[int, list[str]] = defaultdict(list)
|
| 206 |
+
for node, label in partition.items():
|
| 207 |
+
sub_communities[label].append(node)
|
| 208 |
+
for members in sub_communities.values():
|
| 209 |
+
communities.append((frozenset(members), "louvain", formation_type))
|
| 210 |
+
|
| 211 |
+
return communities
|
| 212 |
+
|
| 213 |
+
|
| 214 |
+
# ---------------------------------------------------------------------------
|
| 215 |
+
# Compute cluster metadata (strong_link_count + weak_link_count)
|
| 216 |
+
# These are computed from BOTH subgraphs regardless of formation_type (1.7)
|
| 217 |
+
# ---------------------------------------------------------------------------
|
| 218 |
+
|
| 219 |
+
def compute_cluster_metadata(
|
| 220 |
+
cluster_nodes: frozenset,
|
| 221 |
+
strong_subgraph: nx.Graph,
|
| 222 |
+
weak_only_subgraph: nx.Graph,
|
| 223 |
+
) -> dict:
|
| 224 |
+
"""
|
| 225 |
+
strong_link_count: total strong-link edges within the cluster
|
| 226 |
+
weak_link_count: total weak-link edges within the cluster
|
| 227 |
+
Both are computed regardless of formation_type (per spec 1.7).
|
| 228 |
+
"""
|
| 229 |
+
strong = 0
|
| 230 |
+
weak = 0
|
| 231 |
+
members = list(cluster_nodes)
|
| 232 |
+
for i in range(len(members)):
|
| 233 |
+
for j in range(i + 1, len(members)):
|
| 234 |
+
ca, cb = members[i], members[j]
|
| 235 |
+
if strong_subgraph.has_edge(ca, cb):
|
| 236 |
+
strong += strong_subgraph[ca][cb].get("strong_share_count", 0)
|
| 237 |
+
# weak_only edges: only pairs not in strong_subgraph
|
| 238 |
+
if weak_only_subgraph.has_edge(ca, cb):
|
| 239 |
+
weak += weak_only_subgraph[ca][cb].get("weak_share_count", 0)
|
| 240 |
+
|
| 241 |
+
return {"strong_link_count": strong, "weak_link_count": weak}
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
# ---------------------------------------------------------------------------
|
| 245 |
+
# Write candidate_clusters.json
|
| 246 |
+
# ---------------------------------------------------------------------------
|
| 247 |
+
def write_clusters(clusters: list[dict], path: str):
|
| 248 |
+
os.makedirs(os.path.dirname(path), exist_ok=True)
|
| 249 |
+
with open(path, "w", encoding="utf-8") as f:
|
| 250 |
+
json.dump(clusters, f, indent=2, ensure_ascii=False)
|
| 251 |
+
print(f"Wrote {path} ({len(clusters)} clusters)")
|
| 252 |
+
|
| 253 |
+
|
| 254 |
+
# ---------------------------------------------------------------------------
|
| 255 |
+
# Ground-truth validation (works for both Phase 1 and Phase 2 datasets)
|
| 256 |
+
# Phase 1 ground truth key: "stress_clusters"
|
| 257 |
+
# Phase 2 ground truth key: "benign_clusters" (falls back to "stress_clusters")
|
| 258 |
+
# ---------------------------------------------------------------------------
|
| 259 |
+
def validate(clusters: list[dict], ground_truth_path: str):
|
| 260 |
+
with open(ground_truth_path, encoding="utf-8") as f:
|
| 261 |
+
gt = json.load(f)
|
| 262 |
+
|
| 263 |
+
rings = gt["rings"]
|
| 264 |
+
# Support both Phase 1 ("stress_clusters") and Phase 2 ("benign_clusters") naming
|
| 265 |
+
benign_clusters = gt.get("benign_clusters", gt.get("stress_clusters", []))
|
| 266 |
+
|
| 267 |
+
cand_sets = [set(c["customer_ids"]) for c in clusters]
|
| 268 |
+
|
| 269 |
+
# Ring recovery: each ring should appear in its OWN separate candidate cluster
|
| 270 |
+
rings_recovered = 0
|
| 271 |
+
ring_detail = []
|
| 272 |
+
for ring in rings:
|
| 273 |
+
ring_members = set(ring["customer_ids"])
|
| 274 |
+
ring_id = ring.get("ring_id", ring.get("cluster_id", "?"))
|
| 275 |
+
threshold = len(ring_members) * 0.5
|
| 276 |
+
best_overlap = 0
|
| 277 |
+
best_cand = None
|
| 278 |
+
for i, cs in enumerate(cand_sets):
|
| 279 |
+
overlap = len(ring_members & cs)
|
| 280 |
+
if overlap > best_overlap:
|
| 281 |
+
best_overlap = overlap
|
| 282 |
+
best_cand = clusters[i]["cluster_id"]
|
| 283 |
+
recovered = best_overlap >= threshold
|
| 284 |
+
if recovered:
|
| 285 |
+
rings_recovered += 1
|
| 286 |
+
ring_detail.append({
|
| 287 |
+
"ring_id": ring_id,
|
| 288 |
+
"ring_size": len(ring_members),
|
| 289 |
+
"best_overlap": best_overlap,
|
| 290 |
+
"recovered": recovered,
|
| 291 |
+
"matched_cluster": best_cand,
|
| 292 |
+
})
|
| 293 |
+
|
| 294 |
+
# Separation check: rings should be in SEPARATE candidates
|
| 295 |
+
# Count how many rings map to the same best candidate
|
| 296 |
+
matched_by_cand: dict[str, int] = defaultdict(int)
|
| 297 |
+
for d in ring_detail:
|
| 298 |
+
if d["matched_cluster"]:
|
| 299 |
+
matched_by_cand[d["matched_cluster"]] += 1
|
| 300 |
+
rings_sharing_cluster = sum(1 for cnt in matched_by_cand.values() if cnt > 1)
|
| 301 |
+
|
| 302 |
+
# Benign/stress cluster check: should appear as weak_only candidates
|
| 303 |
+
# with strong_link_count == 0
|
| 304 |
+
benign_detail = []
|
| 305 |
+
benign_correctly_weak = 0
|
| 306 |
+
for sc in benign_clusters:
|
| 307 |
+
sc_members = set(sc["customer_ids"])
|
| 308 |
+
sc_id = sc.get("cluster_id", "?")
|
| 309 |
+
threshold = len(sc_members) * 0.5
|
| 310 |
+
best_overlap = 0
|
| 311 |
+
best_cand_id = None
|
| 312 |
+
best_strong = 0
|
| 313 |
+
best_formation = None
|
| 314 |
+
for cand in clusters:
|
| 315 |
+
overlap = len(sc_members & set(cand["customer_ids"]))
|
| 316 |
+
if overlap > best_overlap:
|
| 317 |
+
best_overlap = overlap
|
| 318 |
+
best_cand_id = cand["cluster_id"]
|
| 319 |
+
best_strong = cand["strong_link_count"]
|
| 320 |
+
best_formation = cand.get("formation_type", "unknown")
|
| 321 |
+
appears = best_overlap >= threshold
|
| 322 |
+
correctly_weak = appears and best_strong == 0 and best_formation == "weak_only"
|
| 323 |
+
if correctly_weak:
|
| 324 |
+
benign_correctly_weak += 1
|
| 325 |
+
benign_detail.append({
|
| 326 |
+
"cluster_id": sc_id,
|
| 327 |
+
"sc_size": len(sc_members),
|
| 328 |
+
"appears_as_candidate": appears,
|
| 329 |
+
"best_overlap": best_overlap,
|
| 330 |
+
"best_cand_id": best_cand_id,
|
| 331 |
+
"max_strong_in_match": best_strong,
|
| 332 |
+
"formation_type": best_formation,
|
| 333 |
+
"correctly_weak": correctly_weak,
|
| 334 |
+
})
|
| 335 |
+
|
| 336 |
+
# Print
|
| 337 |
+
print("\n========== Ground-Truth Validation ==========")
|
| 338 |
+
print(f"Rings recovered (>=50% members in a candidate): {rings_recovered} / {len(rings)}")
|
| 339 |
+
|
| 340 |
+
# Separation check
|
| 341 |
+
separate_count = sum(1 for cnt in matched_by_cand.values() if cnt == 1)
|
| 342 |
+
multi_count = sum(1 for cnt in matched_by_cand.values() if cnt > 1)
|
| 343 |
+
print(f"Rings in separate candidates: {separate_count} (rings sharing a candidate: {rings_sharing_cluster})")
|
| 344 |
+
|
| 345 |
+
for d in ring_detail:
|
| 346 |
+
flag = "[OK]" if d["recovered"] else "[--]"
|
| 347 |
+
share_flag = ""
|
| 348 |
+
if d["matched_cluster"] and matched_by_cand.get(d["matched_cluster"], 0) > 1:
|
| 349 |
+
share_flag = " [SHARES WITH OTHER RING]"
|
| 350 |
+
print(f" {flag} {d['ring_id']} (size={d['ring_size']}) "
|
| 351 |
+
f"best_overlap={d['best_overlap']} "
|
| 352 |
+
f"candidate={d['matched_cluster']}{share_flag}")
|
| 353 |
+
|
| 354 |
+
below_filter = [d for d in benign_detail if not d["appears_as_candidate"]]
|
| 355 |
+
appeared = [d for d in benign_detail if d["appears_as_candidate"]]
|
| 356 |
+
print(f"\nBenign/stress clusters (size>=3) appearing as candidates: {len(appeared)} / {len(benign_clusters)}")
|
| 357 |
+
print(f" Correctly as weak_only with strong_link_count=0: {benign_correctly_weak} / {len(appeared)}")
|
| 358 |
+
for d in benign_detail:
|
| 359 |
+
if not d["appears_as_candidate"]:
|
| 360 |
+
print(f" [SKIP] {d['cluster_id']} (size={d['sc_size']}) -- below size>=3 filter or no match")
|
| 361 |
+
else:
|
| 362 |
+
flag = "[OK]" if d["correctly_weak"] else "[FP]"
|
| 363 |
+
print(f" {flag} {d['cluster_id']} (size={d['sc_size']}) "
|
| 364 |
+
f"formation={d['formation_type']} "
|
| 365 |
+
f"strong={d['max_strong_in_match']} "
|
| 366 |
+
f"cand={d['best_cand_id']}")
|
| 367 |
+
print("=============================================\n")
|
| 368 |
+
|
| 369 |
+
return rings_recovered, ring_detail, benign_detail, matched_by_cand
|
| 370 |
+
|
| 371 |
+
|
| 372 |
+
# ---------------------------------------------------------------------------
|
| 373 |
+
# Entry point
|
| 374 |
+
# ---------------------------------------------------------------------------
|
| 375 |
+
def main(data_dir: str = None):
|
| 376 |
+
if data_dir is None:
|
| 377 |
+
data_dir = os.path.join(BASE_DIR, "data", "synthetic")
|
| 378 |
+
|
| 379 |
+
graph_path = os.path.join(data_dir, "graph.gpickle")
|
| 380 |
+
clusters_path = os.path.join(data_dir, "candidate_clusters.json")
|
| 381 |
+
gt_path = os.path.join(data_dir, "ground_truth.json")
|
| 382 |
+
|
| 383 |
+
print(f"Loading graph from {graph_path} ...")
|
| 384 |
+
G = load_graph(graph_path)
|
| 385 |
+
print(f" Graph: {G.number_of_nodes()} nodes, {G.number_of_edges()} edges")
|
| 386 |
+
|
| 387 |
+
# 1.2 β two projections
|
| 388 |
+
print("Building strong subgraph...")
|
| 389 |
+
SG = build_strong_subgraph(G)
|
| 390 |
+
strong_edges = SG.number_of_edges()
|
| 391 |
+
print(f" Strong subgraph: {SG.number_of_nodes()} nodes, {strong_edges} edges")
|
| 392 |
+
|
| 393 |
+
print("Building weak-only subgraph...")
|
| 394 |
+
WG = build_weak_only_subgraph(G, SG)
|
| 395 |
+
weak_edges = WG.number_of_edges()
|
| 396 |
+
print(f" Weak-only subgraph: {WG.number_of_nodes()} nodes, {weak_edges} edges")
|
| 397 |
+
|
| 398 |
+
# 1.3 β strong_anchored candidates
|
| 399 |
+
print("Detecting strong_anchored communities...")
|
| 400 |
+
strong_communities = detect_on_subgraph(SG, "strong_anchored")
|
| 401 |
+
print(f" Raw strong communities (all sizes): {len(strong_communities)}")
|
| 402 |
+
|
| 403 |
+
# 1.4 β weak_only candidates
|
| 404 |
+
print("Detecting weak_only communities...")
|
| 405 |
+
weak_communities = detect_on_subgraph(WG, "weak_only")
|
| 406 |
+
print(f" Raw weak-only communities (all sizes): {len(weak_communities)}")
|
| 407 |
+
|
| 408 |
+
# 1.5 β size >= 3 filter
|
| 409 |
+
strong_filtered = [(m, method, ft) for m, method, ft in strong_communities if len(m) >= 3]
|
| 410 |
+
weak_filtered = [(m, method, ft) for m, method, ft in weak_communities if len(m) >= 3]
|
| 411 |
+
print(f" Strong candidates after size>=3: {len(strong_filtered)}")
|
| 412 |
+
print(f" Weak-only candidates after size>=3: {len(weak_filtered)}")
|
| 413 |
+
|
| 414 |
+
# 1.6 β combine and build output records
|
| 415 |
+
all_filtered = strong_filtered + weak_filtered
|
| 416 |
+
output_clusters = []
|
| 417 |
+
for idx, (members, method, formation_type) in enumerate(all_filtered, start=1):
|
| 418 |
+
meta = compute_cluster_metadata(members, SG, WG)
|
| 419 |
+
output_clusters.append({
|
| 420 |
+
"cluster_id": f"CAND{idx:02d}",
|
| 421 |
+
"customer_ids": sorted(members),
|
| 422 |
+
"size": len(members),
|
| 423 |
+
"strong_link_count": meta["strong_link_count"],
|
| 424 |
+
"weak_link_count": meta["weak_link_count"],
|
| 425 |
+
"formation_type": formation_type,
|
| 426 |
+
"method": method,
|
| 427 |
+
})
|
| 428 |
+
|
| 429 |
+
# Write
|
| 430 |
+
write_clusters(output_clusters, clusters_path)
|
| 431 |
+
|
| 432 |
+
# Print overview
|
| 433 |
+
print("\nCandidate clusters:")
|
| 434 |
+
for c in output_clusters:
|
| 435 |
+
print(f" {c['cluster_id']}: size={c['size']:3d} "
|
| 436 |
+
f"strong={c['strong_link_count']:3d} "
|
| 437 |
+
f"weak={c['weak_link_count']:3d} "
|
| 438 |
+
f"formation={c['formation_type']} "
|
| 439 |
+
f"method={c['method']}")
|
| 440 |
+
|
| 441 |
+
# Validation
|
| 442 |
+
if os.path.exists(gt_path):
|
| 443 |
+
rings_recovered, ring_detail, benign_detail, matched_by_cand = validate(
|
| 444 |
+
output_clusters, gt_path
|
| 445 |
+
)
|
| 446 |
+
total_rings = len(ring_detail)
|
| 447 |
+
separate = sum(1 for cnt in matched_by_cand.values() if cnt == 1)
|
| 448 |
+
print(f"SUMMARY: Rings recovered={rings_recovered}/{total_rings} "
|
| 449 |
+
f"Rings in separate candidates={separate}/{total_rings} "
|
| 450 |
+
f"Benign/stress clusters=see above")
|
| 451 |
+
else:
|
| 452 |
+
print(f"Ground truth not found at {gt_path}, skipping validation.")
|
| 453 |
+
|
| 454 |
+
return output_clusters
|
| 455 |
+
|
| 456 |
+
|
| 457 |
+
if __name__ == "__main__":
|
| 458 |
+
parser = argparse.ArgumentParser()
|
| 459 |
+
parser.add_argument(
|
| 460 |
+
"--data-dir",
|
| 461 |
+
default=None,
|
| 462 |
+
help="Path to data directory containing graph.gpickle and ground_truth.json. "
|
| 463 |
+
"Defaults to data/synthetic/",
|
| 464 |
+
)
|
| 465 |
+
args = parser.parse_args()
|
| 466 |
+
main(args.data_dir)
|
integration/.gitkeep
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
|
integration/razorpay_actions.py
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
razorpay_actions.py
|
| 3 |
+
-------------------
|
| 4 |
+
Phase 3 Section 3 β Razorpay test-mode integration.
|
| 5 |
+
|
| 6 |
+
Executes hold/flag actions for auto_hold and escalate cases via the Razorpay
|
| 7 |
+
REST API (Python SDK). Results are verified by fetching the order back and
|
| 8 |
+
confirming the notes match what was written.
|
| 9 |
+
|
| 10 |
+
MCP server note (Section 3.2):
|
| 11 |
+
The plan specified using the official Razorpay MCP server (@razorpay/mcp-server).
|
| 12 |
+
At execution time that npm package returned 404 Not Found on the npm registry β
|
| 13 |
+
no such package exists. Logged in phase3_summary.md as a blocker.
|
| 14 |
+
Fallback used: official Razorpay Python SDK (razorpay==2.0.1), which calls
|
| 15 |
+
the same Razorpay REST API endpoints used by any MCP integration.
|
| 16 |
+
The "tool" used is: razorpay.Client.order.create + razorpay.Client.order.edit
|
| 17 |
+
+ razorpay.Client.order.fetch. All calls are real, test-mode, verified.
|
| 18 |
+
|
| 19 |
+
Actions:
|
| 20 |
+
auto_hold: create order β edit notes to mark ringguard_status=auto_hold
|
| 21 |
+
escalate: create order β edit notes to mark ringguard_status=escalate_flagged
|
| 22 |
+
|
| 23 |
+
Usage:
|
| 24 |
+
from integration.razorpay_actions import execute_action, load_cases, save_cases
|
| 25 |
+
execute_action(case)
|
| 26 |
+
"""
|
| 27 |
+
|
| 28 |
+
import json
|
| 29 |
+
import os
|
| 30 |
+
import sys
|
| 31 |
+
from datetime import datetime, timezone
|
| 32 |
+
|
| 33 |
+
from dotenv import load_dotenv
|
| 34 |
+
|
| 35 |
+
load_dotenv()
|
| 36 |
+
|
| 37 |
+
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 38 |
+
sys.path.insert(0, BASE_DIR)
|
| 39 |
+
|
| 40 |
+
CASES_PATH = os.path.join(BASE_DIR, "data", "synthetic", "cases_demo.json")
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
# ---------------------------------------------------------------------------
|
| 44 |
+
# Razorpay client factory
|
| 45 |
+
# ---------------------------------------------------------------------------
|
| 46 |
+
|
| 47 |
+
def _get_client():
|
| 48 |
+
"""
|
| 49 |
+
Return an authenticated Razorpay client.
|
| 50 |
+
Raises RuntimeError if credentials are not set.
|
| 51 |
+
Credentials are read from environment (loaded from .env) β never hardcoded.
|
| 52 |
+
"""
|
| 53 |
+
try:
|
| 54 |
+
import razorpay
|
| 55 |
+
except ImportError:
|
| 56 |
+
raise RuntimeError("razorpay SDK not installed. Run: pip install razorpay")
|
| 57 |
+
|
| 58 |
+
key_id = os.environ.get("RAZORPAY_KEY_ID", "")
|
| 59 |
+
key_secret = os.environ.get("RAZORPAY_KEY_SECRET", "")
|
| 60 |
+
|
| 61 |
+
if not key_id or not key_secret:
|
| 62 |
+
raise RuntimeError(
|
| 63 |
+
"RAZORPAY_KEY_ID and RAZORPAY_KEY_SECRET must be set in .env. "
|
| 64 |
+
"They must be test-mode credentials (rzp_test_...)."
|
| 65 |
+
)
|
| 66 |
+
if not key_id.startswith("rzp_test_"):
|
| 67 |
+
raise RuntimeError(
|
| 68 |
+
f"RAZORPAY_KEY_ID does not look like a test-mode key (got prefix "
|
| 69 |
+
f"'{key_id[:12]}...'). Only test mode is permitted."
|
| 70 |
+
)
|
| 71 |
+
|
| 72 |
+
return razorpay.Client(auth=(key_id, key_secret))
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
# ---------------------------------------------------------------------------
|
| 76 |
+
# Core action function
|
| 77 |
+
# ---------------------------------------------------------------------------
|
| 78 |
+
|
| 79 |
+
def execute_action(case: dict) -> dict:
|
| 80 |
+
"""
|
| 81 |
+
Execute a Razorpay test-mode action for a single case.
|
| 82 |
+
|
| 83 |
+
For auto_hold: creates a test order and annotates it with ringguard_status=auto_hold.
|
| 84 |
+
For escalate: creates a test order and annotates it with ringguard_status=escalate_flagged.
|
| 85 |
+
For log_only: no API call; returns a skipped record.
|
| 86 |
+
|
| 87 |
+
Returns a dict suitable for the case's action_taken field:
|
| 88 |
+
{
|
| 89 |
+
"tool": str, # Razorpay SDK method used
|
| 90 |
+
"order_id": str, # Razorpay test-mode order ID
|
| 91 |
+
"razorpay_status": str, # order status from Razorpay
|
| 92 |
+
"notes_written": dict, # notes added to the order
|
| 93 |
+
"notes_verified": bool, # True if fetch confirms notes match
|
| 94 |
+
"timestamp": str, # ISO 8601 UTC
|
| 95 |
+
"test_mode": bool, # always True
|
| 96 |
+
"error": str or None
|
| 97 |
+
}
|
| 98 |
+
"""
|
| 99 |
+
decision = case.get("policy_decision", "log_only")
|
| 100 |
+
case_id = case.get("case_id", "?")
|
| 101 |
+
cluster_id = case.get("cluster_id", "?")
|
| 102 |
+
|
| 103 |
+
# log_only: skip β no Razorpay call
|
| 104 |
+
if decision == "log_only":
|
| 105 |
+
return {
|
| 106 |
+
"tool": None,
|
| 107 |
+
"order_id": None,
|
| 108 |
+
"razorpay_status": "skipped",
|
| 109 |
+
"notes_written": None,
|
| 110 |
+
"notes_verified": False,
|
| 111 |
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
| 112 |
+
"test_mode": True,
|
| 113 |
+
"error": None,
|
| 114 |
+
"skip_reason": "log_only β no action required",
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
try:
|
| 118 |
+
client = _get_client()
|
| 119 |
+
|
| 120 |
+
# Determine amount in paise (Razorpay requires integer paise)
|
| 121 |
+
# We use a nominal βΉ1 order (100 paise) for escalate flags and
|
| 122 |
+
# the cluster's actual exposure for auto_hold orders.
|
| 123 |
+
# Note: actual payment capture won't happen β test mode only.
|
| 124 |
+
if decision == "auto_hold":
|
| 125 |
+
# Use actual cluster risk_probability as a proxy for notes
|
| 126 |
+
amount_paise = max(100, int(case.get("risk_probability", 0.99) * 100)) # symbolic
|
| 127 |
+
ringguard_status = "auto_hold"
|
| 128 |
+
hold_label = "FRAUD_RING_AUTO_HOLD"
|
| 129 |
+
else: # escalate
|
| 130 |
+
amount_paise = 100 # βΉ1 placeholder
|
| 131 |
+
ringguard_status = "escalate_flagged"
|
| 132 |
+
hold_label = "FRAUD_RING_ESCALATE"
|
| 133 |
+
|
| 134 |
+
# Step 1: Create a test-mode order seeded from the case's cluster data
|
| 135 |
+
created_notes = {
|
| 136 |
+
"case_id": case_id,
|
| 137 |
+
"cluster_id": cluster_id,
|
| 138 |
+
"ringguard_status": f"pending_{ringguard_status}",
|
| 139 |
+
"customer_ids": ",".join(case.get("customer_ids", [])[:5]), # first 5
|
| 140 |
+
"risk_score": str(round(case.get("risk_probability", 0), 4)),
|
| 141 |
+
}
|
| 142 |
+
order = client.order.create({
|
| 143 |
+
"amount": amount_paise,
|
| 144 |
+
"currency": "INR",
|
| 145 |
+
"notes": created_notes,
|
| 146 |
+
})
|
| 147 |
+
order_id = order["id"]
|
| 148 |
+
|
| 149 |
+
# Step 2: Edit the order to mark the RingGuard action
|
| 150 |
+
action_notes = {
|
| 151 |
+
"case_id": case_id,
|
| 152 |
+
"cluster_id": cluster_id,
|
| 153 |
+
"ringguard_status": ringguard_status,
|
| 154 |
+
"action_label": hold_label,
|
| 155 |
+
"risk_score": str(round(case.get("risk_probability", 0), 4)),
|
| 156 |
+
"action_by": "RingGuard_v3",
|
| 157 |
+
"action_timestamp": datetime.now(timezone.utc).isoformat(),
|
| 158 |
+
}
|
| 159 |
+
edited = client.order.edit(order_id, {"notes": action_notes})
|
| 160 |
+
|
| 161 |
+
# Step 3: Fetch back and verify notes match
|
| 162 |
+
fetched = client.order.fetch(order_id)
|
| 163 |
+
fetched_notes = fetched.get("notes", {})
|
| 164 |
+
|
| 165 |
+
# Verify that ringguard_status and case_id are correctly stored
|
| 166 |
+
notes_verified = (
|
| 167 |
+
fetched_notes.get("ringguard_status") == ringguard_status
|
| 168 |
+
and fetched_notes.get("case_id") == case_id
|
| 169 |
+
)
|
| 170 |
+
|
| 171 |
+
ts = datetime.now(timezone.utc).isoformat()
|
| 172 |
+
print(f" [{case_id}] {decision}: order_id={order_id} "
|
| 173 |
+
f"status={fetched['status']} verified={notes_verified}")
|
| 174 |
+
|
| 175 |
+
return {
|
| 176 |
+
"tool": "razorpay.Client.order.create + order.edit + order.fetch",
|
| 177 |
+
"order_id": order_id,
|
| 178 |
+
"razorpay_status": fetched["status"],
|
| 179 |
+
"notes_written": action_notes,
|
| 180 |
+
"notes_verified": notes_verified,
|
| 181 |
+
"timestamp": ts,
|
| 182 |
+
"test_mode": True,
|
| 183 |
+
"error": None,
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
except Exception as e:
|
| 187 |
+
ts = datetime.now(timezone.utc).isoformat()
|
| 188 |
+
print(f" [{case_id}] ERROR: {e}")
|
| 189 |
+
return {
|
| 190 |
+
"tool": "razorpay.Client",
|
| 191 |
+
"order_id": None,
|
| 192 |
+
"razorpay_status": "error",
|
| 193 |
+
"notes_written": None,
|
| 194 |
+
"notes_verified": False,
|
| 195 |
+
"timestamp": ts,
|
| 196 |
+
"test_mode": True,
|
| 197 |
+
"error": str(e),
|
| 198 |
+
}
|
| 199 |
+
|
| 200 |
+
|
| 201 |
+
# ---------------------------------------------------------------------------
|
| 202 |
+
# Batch execution across all cases
|
| 203 |
+
# ---------------------------------------------------------------------------
|
| 204 |
+
|
| 205 |
+
def load_cases(path: str = None) -> list:
|
| 206 |
+
"""Load cases_demo.json."""
|
| 207 |
+
p = path or CASES_PATH
|
| 208 |
+
with open(p, encoding="utf-8") as f:
|
| 209 |
+
return json.load(f)
|
| 210 |
+
|
| 211 |
+
|
| 212 |
+
def save_cases(cases: list, path: str = None):
|
| 213 |
+
"""Write cases_demo.json with updated action_taken fields."""
|
| 214 |
+
p = path or CASES_PATH
|
| 215 |
+
with open(p, "w", encoding="utf-8") as f:
|
| 216 |
+
json.dump(cases, f, indent=2, ensure_ascii=False)
|
| 217 |
+
|
| 218 |
+
|
| 219 |
+
def run_all_actions(cases: list) -> list:
|
| 220 |
+
"""
|
| 221 |
+
Execute Razorpay actions for all auto_hold and escalate cases.
|
| 222 |
+
Populates action_taken field in each case.
|
| 223 |
+
Returns the updated list.
|
| 224 |
+
"""
|
| 225 |
+
actioned = 0
|
| 226 |
+
errors = 0
|
| 227 |
+
skipped = 0
|
| 228 |
+
|
| 229 |
+
for case in cases:
|
| 230 |
+
decision = case.get("policy_decision", "log_only")
|
| 231 |
+
print(f"Processing {case['case_id']} ({decision})...")
|
| 232 |
+
|
| 233 |
+
if decision == "log_only":
|
| 234 |
+
skipped += 1
|
| 235 |
+
continue
|
| 236 |
+
|
| 237 |
+
action = execute_action(case)
|
| 238 |
+
case["action_taken"] = action
|
| 239 |
+
|
| 240 |
+
if action.get("error"):
|
| 241 |
+
errors += 1
|
| 242 |
+
else:
|
| 243 |
+
actioned += 1
|
| 244 |
+
|
| 245 |
+
print(f"\nDone: {actioned} actioned, {errors} errors, {skipped} log_only skipped")
|
| 246 |
+
return cases
|
| 247 |
+
|
| 248 |
+
|
| 249 |
+
# ---------------------------------------------------------------------------
|
| 250 |
+
# CLI entry point
|
| 251 |
+
# ---------------------------------------------------------------------------
|
| 252 |
+
|
| 253 |
+
if __name__ == "__main__":
|
| 254 |
+
import argparse
|
| 255 |
+
|
| 256 |
+
parser = argparse.ArgumentParser(
|
| 257 |
+
description="Execute Razorpay test-mode actions for RingGuard cases."
|
| 258 |
+
)
|
| 259 |
+
parser.add_argument(
|
| 260 |
+
"--cases", default=None,
|
| 261 |
+
help="Path to cases_demo.json. Defaults to data/synthetic/cases_demo.json."
|
| 262 |
+
)
|
| 263 |
+
parser.add_argument(
|
| 264 |
+
"--dry-run", action="store_true",
|
| 265 |
+
help="Print what would be done without calling Razorpay API."
|
| 266 |
+
)
|
| 267 |
+
args = parser.parse_args()
|
| 268 |
+
|
| 269 |
+
cases = load_cases(args.cases)
|
| 270 |
+
print(f"Loaded {len(cases)} cases from {args.cases or CASES_PATH}")
|
| 271 |
+
|
| 272 |
+
ah_cases = [c for c in cases if c["policy_decision"] == "auto_hold"]
|
| 273 |
+
esc_cases = [c for c in cases if c["policy_decision"] == "escalate"]
|
| 274 |
+
log_cases = [c for c in cases if c["policy_decision"] == "log_only"]
|
| 275 |
+
print(f" auto_hold: {len(ah_cases)}, escalate: {len(esc_cases)}, log_only: {len(log_cases)}")
|
| 276 |
+
|
| 277 |
+
if args.dry_run:
|
| 278 |
+
print("\n[DRY RUN] Would call Razorpay API for:")
|
| 279 |
+
for c in ah_cases + esc_cases:
|
| 280 |
+
print(f" {c['case_id']} ({c['policy_decision']}) cluster={c['cluster_id']}")
|
| 281 |
+
sys.exit(0)
|
| 282 |
+
|
| 283 |
+
print("\nExecuting Razorpay actions (test mode)...")
|
| 284 |
+
updated = run_all_actions(cases)
|
| 285 |
+
save_cases(updated, args.cases)
|
| 286 |
+
print(f"\nUpdated cases saved to {args.cases or CASES_PATH}")
|
| 287 |
+
|
| 288 |
+
# Verify at least 1 auto_hold and 1 escalate were successful
|
| 289 |
+
ah_ok = [c for c in updated if c["policy_decision"] == "auto_hold"
|
| 290 |
+
and c.get("action_taken", {}) and not c["action_taken"].get("error")
|
| 291 |
+
and c["action_taken"].get("notes_verified")]
|
| 292 |
+
esc_ok = [c for c in updated if c["policy_decision"] == "escalate"
|
| 293 |
+
and c.get("action_taken", {}) and not c["action_taken"].get("error")
|
| 294 |
+
and c["action_taken"].get("notes_verified")]
|
| 295 |
+
|
| 296 |
+
print(f"\nVerification:")
|
| 297 |
+
print(f" auto_hold verified: {len(ah_ok)}/{len(ah_cases)}")
|
| 298 |
+
print(f" escalate verified: {len(esc_ok)}/{len(esc_cases)}")
|
| 299 |
+
|
| 300 |
+
if ah_ok:
|
| 301 |
+
ah = ah_ok[0]["action_taken"]
|
| 302 |
+
print(f"\n First auto_hold order: {ah['order_id']}")
|
| 303 |
+
print(f" Status: {ah['razorpay_status']}")
|
| 304 |
+
print(f" Notes verified: {ah['notes_verified']}")
|
| 305 |
+
|
| 306 |
+
if esc_ok:
|
| 307 |
+
esc = esc_ok[0]["action_taken"]
|
| 308 |
+
print(f"\n First escalate order: {esc['order_id']}")
|
| 309 |
+
print(f" Status: {esc['razorpay_status']}")
|
| 310 |
+
print(f" Notes verified: {esc['notes_verified']}")
|
requirements.txt
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
annotated-doc==0.0.5
|
| 2 |
+
annotated-types==0.8.0
|
| 3 |
+
anyio==4.14.2
|
| 4 |
+
certifi==2026.7.22
|
| 5 |
+
charset-normalizer==3.5.1
|
| 6 |
+
click==8.4.2
|
| 7 |
+
colorama==0.4.6
|
| 8 |
+
distro==1.9.0
|
| 9 |
+
Faker==40.36.0
|
| 10 |
+
fastapi==0.141.1
|
| 11 |
+
groq==1.6.0
|
| 12 |
+
httptools==0.8.0
|
| 13 |
+
h11==0.16.0
|
| 14 |
+
httpcore==1.0.9
|
| 15 |
+
httpx==0.28.1
|
| 16 |
+
idna==3.19
|
| 17 |
+
joblib==1.5.3
|
| 18 |
+
jsonpatch==1.33
|
| 19 |
+
jsonpointer==3.1.1
|
| 20 |
+
Jinja2==3.1.6
|
| 21 |
+
langchain-core==1.6.0
|
| 22 |
+
langchain-protocol==0.0.18
|
| 23 |
+
langgraph==1.2.11
|
| 24 |
+
langgraph-checkpoint==4.2.0
|
| 25 |
+
langgraph-prebuilt==1.1.0
|
| 26 |
+
langgraph-sdk==0.4.3
|
| 27 |
+
langsmith==0.11.1
|
| 28 |
+
lightgbm==4.7.0
|
| 29 |
+
MarkupSafe==3.0.3
|
| 30 |
+
narwhals==2.25.0
|
| 31 |
+
networkx==3.6.1
|
| 32 |
+
numpy==2.4.6
|
| 33 |
+
orjson==3.12.0
|
| 34 |
+
ormsgpack==1.12.2
|
| 35 |
+
packaging==26.3
|
| 36 |
+
pandas==3.0.5
|
| 37 |
+
pydantic==2.13.4
|
| 38 |
+
pydantic_core==2.46.4
|
| 39 |
+
python-dateutil==2.9.0.post0
|
| 40 |
+
python-dotenv==1.2.3
|
| 41 |
+
python-louvain==0.16
|
| 42 |
+
razorpay==2.0.1
|
| 43 |
+
PyYAML==6.0.3
|
| 44 |
+
requests==2.34.2
|
| 45 |
+
requests-toolbelt==1.0.0
|
| 46 |
+
scikit-learn==1.9.0
|
| 47 |
+
scipy==1.17.1
|
| 48 |
+
six==1.17.0
|
| 49 |
+
starlette==1.6.0
|
| 50 |
+
sniffio==1.3.1
|
| 51 |
+
tenacity==9.1.4
|
| 52 |
+
threadpoolctl==3.6.0
|
| 53 |
+
typing-inspection==0.4.4
|
| 54 |
+
typing_extensions==4.16.0
|
| 55 |
+
tzdata==2026.3
|
| 56 |
+
urllib3==2.7.0
|
| 57 |
+
uuid_utils==0.17.0
|
| 58 |
+
uvicorn==0.52.4
|
| 59 |
+
watchfiles==1.2.0
|
| 60 |
+
websockets==16.1.1
|
| 61 |
+
xxhash==4.0.1
|
| 62 |
+
zstandard==0.25.0
|
scoring/.gitkeep
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
|
scoring/features.py
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
features.py
|
| 3 |
+
-----------
|
| 4 |
+
Feature extraction for RingGuard risk model.
|
| 5 |
+
|
| 6 |
+
Given a candidate cluster (from candidate_clusters.json) plus the matching
|
| 7 |
+
orders.json, customers.json, and optionally graph data, produces exactly 13
|
| 8 |
+
features per cluster as specified in the Phase 2 plan.
|
| 9 |
+
|
| 10 |
+
Feature set:
|
| 11 |
+
size, strong_link_count, weak_link_count, strong_link_density,
|
| 12 |
+
has_same_contact_edge, order_count, total_amount, avg_order_amount,
|
| 13 |
+
return_rate, chargeback_rate, shared_coupon_count, time_span_days,
|
| 14 |
+
order_velocity, formation_type_strong
|
| 15 |
+
|
| 16 |
+
Usage:
|
| 17 |
+
from scoring.features import extract_features, label
|
| 18 |
+
|
| 19 |
+
features = extract_features(cluster, orders, graph=G)
|
| 20 |
+
lbl = label(cluster, ground_truth)
|
| 21 |
+
"""
|
| 22 |
+
|
| 23 |
+
import json
|
| 24 |
+
import os
|
| 25 |
+
import pickle
|
| 26 |
+
from datetime import datetime
|
| 27 |
+
from typing import Optional
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
# ---------------------------------------------------------------------------
|
| 31 |
+
# Helpers
|
| 32 |
+
# ---------------------------------------------------------------------------
|
| 33 |
+
|
| 34 |
+
def _load_json(path: str):
|
| 35 |
+
with open(path, encoding="utf-8") as f:
|
| 36 |
+
return json.load(f)
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def _load_graph(path: str):
|
| 40 |
+
try:
|
| 41 |
+
import networkx as nx
|
| 42 |
+
return nx.read_gpickle(path)
|
| 43 |
+
except AttributeError:
|
| 44 |
+
with open(path, "rb") as f:
|
| 45 |
+
return pickle.load(f)
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
# ---------------------------------------------------------------------------
|
| 49 |
+
# Feature extraction
|
| 50 |
+
# ---------------------------------------------------------------------------
|
| 51 |
+
|
| 52 |
+
def extract_features(
|
| 53 |
+
cluster: dict,
|
| 54 |
+
orders: list[dict],
|
| 55 |
+
graph=None,
|
| 56 |
+
) -> dict:
|
| 57 |
+
"""
|
| 58 |
+
Extract exactly 13 features from a candidate cluster.
|
| 59 |
+
|
| 60 |
+
Parameters
|
| 61 |
+
----------
|
| 62 |
+
cluster : dict
|
| 63 |
+
One entry from candidate_clusters.json. Must have:
|
| 64 |
+
customer_ids, size, strong_link_count, weak_link_count, formation_type
|
| 65 |
+
orders : list[dict]
|
| 66 |
+
All orders from the dataset (orders.json). Filtered to cluster members.
|
| 67 |
+
graph : networkx.Graph, optional
|
| 68 |
+
The heterogeneous graph (graph.gpickle). Used to detect same_contact edges.
|
| 69 |
+
If None, has_same_contact_edge is computed from cluster data only
|
| 70 |
+
(will be 0 unless the cluster was formed via same_contact; this is
|
| 71 |
+
a reasonable fallback since same_contact rings are always strong_anchored).
|
| 72 |
+
|
| 73 |
+
Returns
|
| 74 |
+
-------
|
| 75 |
+
dict with exactly 13 feature keys + cluster_id for identification.
|
| 76 |
+
"""
|
| 77 |
+
member_set = set(cluster["customer_ids"])
|
| 78 |
+
size = cluster["size"]
|
| 79 |
+
strong_link_count = cluster["strong_link_count"]
|
| 80 |
+
weak_link_count = cluster["weak_link_count"]
|
| 81 |
+
formation_type = cluster.get("formation_type", "strong_anchored")
|
| 82 |
+
|
| 83 |
+
# Feature 1: size
|
| 84 |
+
# Feature 2: strong_link_count (from cluster record)
|
| 85 |
+
# Feature 3: weak_link_count (from cluster record)
|
| 86 |
+
|
| 87 |
+
# Feature 4: strong_link_density
|
| 88 |
+
max_possible = max(1, size * (size - 1) / 2)
|
| 89 |
+
strong_link_density = strong_link_count / max_possible
|
| 90 |
+
|
| 91 |
+
# Feature 5: has_same_contact_edge
|
| 92 |
+
# Check graph for same_contact edges between cluster members
|
| 93 |
+
has_same_contact_edge = 0
|
| 94 |
+
if graph is not None:
|
| 95 |
+
for u, v, data in graph.edges(data=True):
|
| 96 |
+
if data.get("relation") == "same_contact":
|
| 97 |
+
if u in member_set and v in member_set:
|
| 98 |
+
has_same_contact_edge = 1
|
| 99 |
+
break
|
| 100 |
+
|
| 101 |
+
# Filter orders to cluster members
|
| 102 |
+
cluster_orders = [o for o in orders if o["customer_id"] in member_set]
|
| 103 |
+
|
| 104 |
+
# Feature 6: order_count
|
| 105 |
+
order_count = len(cluster_orders)
|
| 106 |
+
|
| 107 |
+
# Feature 7: total_amount
|
| 108 |
+
total_amount = sum(o.get("amount", 0) for o in cluster_orders)
|
| 109 |
+
|
| 110 |
+
# Feature 8: avg_order_amount
|
| 111 |
+
avg_order_amount = total_amount / max(1, order_count)
|
| 112 |
+
|
| 113 |
+
# Feature 9: return_rate
|
| 114 |
+
returned = sum(1 for o in cluster_orders if o.get("status") == "returned")
|
| 115 |
+
return_rate = returned / max(1, order_count)
|
| 116 |
+
|
| 117 |
+
# Feature 10: chargeback_rate
|
| 118 |
+
chargebacks = sum(1 for o in cluster_orders if o.get("status") == "chargeback")
|
| 119 |
+
chargeback_rate = chargebacks / max(1, order_count)
|
| 120 |
+
|
| 121 |
+
# Feature 11: shared_coupon_count
|
| 122 |
+
# Count distinct coupon_id values used by 2+ different cluster members
|
| 123 |
+
coupon_to_members: dict[str, set] = {}
|
| 124 |
+
for o in cluster_orders:
|
| 125 |
+
cid_val = o.get("coupon_id")
|
| 126 |
+
if cid_val is not None:
|
| 127 |
+
if cid_val not in coupon_to_members:
|
| 128 |
+
coupon_to_members[cid_val] = set()
|
| 129 |
+
coupon_to_members[cid_val].add(o["customer_id"])
|
| 130 |
+
shared_coupon_count = sum(
|
| 131 |
+
1 for members in coupon_to_members.values() if len(members) >= 2
|
| 132 |
+
)
|
| 133 |
+
|
| 134 |
+
# Features 12 + 13: time_span_days and order_velocity
|
| 135 |
+
timestamps = []
|
| 136 |
+
for o in cluster_orders:
|
| 137 |
+
ts_str = o.get("timestamp", "")
|
| 138 |
+
if ts_str:
|
| 139 |
+
try:
|
| 140 |
+
timestamps.append(datetime.fromisoformat(ts_str))
|
| 141 |
+
except ValueError:
|
| 142 |
+
pass
|
| 143 |
+
|
| 144 |
+
if len(timestamps) >= 2:
|
| 145 |
+
time_span_days = (max(timestamps) - min(timestamps)).total_seconds() / 86400.0
|
| 146 |
+
else:
|
| 147 |
+
time_span_days = 0.0
|
| 148 |
+
|
| 149 |
+
order_velocity = order_count / max(1.0, time_span_days)
|
| 150 |
+
|
| 151 |
+
# Feature 14 (index 13): formation_type_strong
|
| 152 |
+
formation_type_strong = 1 if formation_type == "strong_anchored" else 0
|
| 153 |
+
|
| 154 |
+
return {
|
| 155 |
+
"cluster_id": cluster["cluster_id"],
|
| 156 |
+
"size": size,
|
| 157 |
+
"strong_link_count": strong_link_count,
|
| 158 |
+
"weak_link_count": weak_link_count,
|
| 159 |
+
"strong_link_density": strong_link_density,
|
| 160 |
+
"has_same_contact_edge": has_same_contact_edge,
|
| 161 |
+
"order_count": order_count,
|
| 162 |
+
"total_amount": total_amount,
|
| 163 |
+
"avg_order_amount": avg_order_amount,
|
| 164 |
+
"return_rate": return_rate,
|
| 165 |
+
"chargeback_rate": chargeback_rate,
|
| 166 |
+
"shared_coupon_count": shared_coupon_count,
|
| 167 |
+
"time_span_days": time_span_days,
|
| 168 |
+
"order_velocity": order_velocity,
|
| 169 |
+
"formation_type_strong": formation_type_strong,
|
| 170 |
+
}
|
| 171 |
+
|
| 172 |
+
|
| 173 |
+
# ---------------------------------------------------------------------------
|
| 174 |
+
# Labeling
|
| 175 |
+
# ---------------------------------------------------------------------------
|
| 176 |
+
|
| 177 |
+
FEATURE_COLUMNS = [
|
| 178 |
+
"size",
|
| 179 |
+
"strong_link_count",
|
| 180 |
+
"weak_link_count",
|
| 181 |
+
"strong_link_density",
|
| 182 |
+
"has_same_contact_edge",
|
| 183 |
+
"order_count",
|
| 184 |
+
"total_amount",
|
| 185 |
+
"avg_order_amount",
|
| 186 |
+
"return_rate",
|
| 187 |
+
"chargeback_rate",
|
| 188 |
+
"shared_coupon_count",
|
| 189 |
+
"time_span_days",
|
| 190 |
+
"order_velocity",
|
| 191 |
+
"formation_type_strong",
|
| 192 |
+
]
|
| 193 |
+
|
| 194 |
+
|
| 195 |
+
def label(cluster: dict, ground_truth: dict) -> int:
|
| 196 |
+
"""
|
| 197 |
+
Returns 1 if >= 50% of the cluster's customer_ids overlap with any
|
| 198 |
+
ground-truth ring, else 0.
|
| 199 |
+
|
| 200 |
+
Parameters
|
| 201 |
+
----------
|
| 202 |
+
cluster : dict
|
| 203 |
+
One entry from candidate_clusters.json.
|
| 204 |
+
ground_truth : dict
|
| 205 |
+
Loaded ground_truth.json. Must have a "rings" key.
|
| 206 |
+
"""
|
| 207 |
+
cluster_members = set(cluster["customer_ids"])
|
| 208 |
+
threshold = len(cluster_members) * 0.5
|
| 209 |
+
|
| 210 |
+
for ring in ground_truth.get("rings", []):
|
| 211 |
+
ring_members = set(ring["customer_ids"])
|
| 212 |
+
overlap = len(cluster_members & ring_members)
|
| 213 |
+
if overlap >= threshold:
|
| 214 |
+
return 1
|
| 215 |
+
|
| 216 |
+
return 0
|
| 217 |
+
|
| 218 |
+
|
| 219 |
+
# ---------------------------------------------------------------------------
|
| 220 |
+
# Batch extraction
|
| 221 |
+
# ---------------------------------------------------------------------------
|
| 222 |
+
|
| 223 |
+
def extract_all(
|
| 224 |
+
clusters: list[dict],
|
| 225 |
+
orders: list[dict],
|
| 226 |
+
ground_truth: dict = None,
|
| 227 |
+
graph=None,
|
| 228 |
+
) -> list[dict]:
|
| 229 |
+
"""
|
| 230 |
+
Extract features for every cluster in the list.
|
| 231 |
+
If ground_truth is provided, adds a 'label' field to each row.
|
| 232 |
+
|
| 233 |
+
Returns list of feature dicts (one per cluster), ready for pandas or json.
|
| 234 |
+
"""
|
| 235 |
+
rows = []
|
| 236 |
+
for cluster in clusters:
|
| 237 |
+
row = extract_features(cluster, orders, graph=graph)
|
| 238 |
+
if ground_truth is not None:
|
| 239 |
+
row["label"] = label(cluster, ground_truth)
|
| 240 |
+
rows.append(row)
|
| 241 |
+
return rows
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
# ---------------------------------------------------------------------------
|
| 245 |
+
# CLI convenience: run directly to verify feature extraction on a dataset
|
| 246 |
+
# ---------------------------------------------------------------------------
|
| 247 |
+
|
| 248 |
+
if __name__ == "__main__":
|
| 249 |
+
import argparse
|
| 250 |
+
import sys
|
| 251 |
+
|
| 252 |
+
parser = argparse.ArgumentParser()
|
| 253 |
+
parser.add_argument("--data-dir", default=None,
|
| 254 |
+
help="Path to data directory. Defaults to data/synthetic_train/")
|
| 255 |
+
args = parser.parse_args()
|
| 256 |
+
|
| 257 |
+
base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 258 |
+
data_dir = args.data_dir or os.path.join(base, "data", "synthetic_train")
|
| 259 |
+
|
| 260 |
+
clusters_path = os.path.join(data_dir, "candidate_clusters.json")
|
| 261 |
+
orders_path = os.path.join(data_dir, "orders.json")
|
| 262 |
+
gt_path = os.path.join(data_dir, "ground_truth.json")
|
| 263 |
+
graph_path = os.path.join(data_dir, "graph.gpickle")
|
| 264 |
+
|
| 265 |
+
clusters = _load_json(clusters_path)
|
| 266 |
+
orders = _load_json(orders_path)
|
| 267 |
+
ground_truth = _load_json(gt_path)
|
| 268 |
+
graph = _load_graph(graph_path) if os.path.exists(graph_path) else None
|
| 269 |
+
|
| 270 |
+
rows = extract_all(clusters, orders, ground_truth=ground_truth, graph=graph)
|
| 271 |
+
|
| 272 |
+
# Sanity checks
|
| 273 |
+
assert all(len(r) == len(FEATURE_COLUMNS) + 2 for r in rows), \
|
| 274 |
+
"Row has wrong number of features (expected 14 features + cluster_id + label)"
|
| 275 |
+
|
| 276 |
+
null_count = sum(
|
| 277 |
+
1 for r in rows for k in FEATURE_COLUMNS if r.get(k) is None
|
| 278 |
+
)
|
| 279 |
+
assert null_count == 0, f"Null values found in feature table: {null_count}"
|
| 280 |
+
|
| 281 |
+
labels = [r["label"] for r in rows]
|
| 282 |
+
pos = sum(labels)
|
| 283 |
+
neg = len(labels) - pos
|
| 284 |
+
|
| 285 |
+
print(f"Feature extraction OK: {len(rows)} clusters")
|
| 286 |
+
print(f" Positive labels (fraud ring): {pos}")
|
| 287 |
+
print(f" Negative labels (benign): {neg}")
|
| 288 |
+
print(f" Null values in features: {null_count}")
|
| 289 |
+
print("\nSample row:")
|
| 290 |
+
sample = rows[0]
|
| 291 |
+
for k in FEATURE_COLUMNS:
|
| 292 |
+
print(f" {k:30s}: {sample[k]:.4f}" if isinstance(sample[k], float)
|
| 293 |
+
else f" {k:30s}: {sample[k]}")
|
scoring/holdout_split.json
ADDED
|
@@ -0,0 +1,464 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
{
|
| 3 |
+
"cluster_id": "CAND45",
|
| 4 |
+
"features": {
|
| 5 |
+
"size": 8,
|
| 6 |
+
"strong_link_count": 28,
|
| 7 |
+
"weak_link_count": 0,
|
| 8 |
+
"strong_link_density": 1.0,
|
| 9 |
+
"has_same_contact_edge": 0,
|
| 10 |
+
"order_count": 21,
|
| 11 |
+
"total_amount": 99226,
|
| 12 |
+
"avg_order_amount": 4725.047619047619,
|
| 13 |
+
"return_rate": 0.38095238095238093,
|
| 14 |
+
"chargeback_rate": 0.14285714285714285,
|
| 15 |
+
"shared_coupon_count": 2,
|
| 16 |
+
"time_span_days": 160.50546296296295,
|
| 17 |
+
"order_velocity": 0.13083666818771025,
|
| 18 |
+
"formation_type_strong": 1
|
| 19 |
+
},
|
| 20 |
+
"label": 1,
|
| 21 |
+
"risk_probability": 0.996939116034507
|
| 22 |
+
},
|
| 23 |
+
{
|
| 24 |
+
"cluster_id": "CAND59",
|
| 25 |
+
"features": {
|
| 26 |
+
"size": 4,
|
| 27 |
+
"strong_link_count": 6,
|
| 28 |
+
"weak_link_count": 0,
|
| 29 |
+
"strong_link_density": 1.0,
|
| 30 |
+
"has_same_contact_edge": 0,
|
| 31 |
+
"order_count": 11,
|
| 32 |
+
"total_amount": 42505,
|
| 33 |
+
"avg_order_amount": 3864.090909090909,
|
| 34 |
+
"return_rate": 0.45454545454545453,
|
| 35 |
+
"chargeback_rate": 0.18181818181818182,
|
| 36 |
+
"shared_coupon_count": 0,
|
| 37 |
+
"time_span_days": 148.44283564814816,
|
| 38 |
+
"order_velocity": 0.07410259950889873,
|
| 39 |
+
"formation_type_strong": 1
|
| 40 |
+
},
|
| 41 |
+
"label": 1,
|
| 42 |
+
"risk_probability": 0.9967870481969796
|
| 43 |
+
},
|
| 44 |
+
{
|
| 45 |
+
"cluster_id": "CAND97",
|
| 46 |
+
"features": {
|
| 47 |
+
"size": 3,
|
| 48 |
+
"strong_link_count": 0,
|
| 49 |
+
"weak_link_count": 3,
|
| 50 |
+
"strong_link_density": 0.0,
|
| 51 |
+
"has_same_contact_edge": 0,
|
| 52 |
+
"order_count": 9,
|
| 53 |
+
"total_amount": 23023,
|
| 54 |
+
"avg_order_amount": 2558.1111111111113,
|
| 55 |
+
"return_rate": 0.3333333333333333,
|
| 56 |
+
"chargeback_rate": 0.0,
|
| 57 |
+
"shared_coupon_count": 0,
|
| 58 |
+
"time_span_days": 154.36827546296297,
|
| 59 |
+
"order_velocity": 0.0583021347683536,
|
| 60 |
+
"formation_type_strong": 0
|
| 61 |
+
},
|
| 62 |
+
"label": 0,
|
| 63 |
+
"risk_probability": 0.0035484719416527992
|
| 64 |
+
},
|
| 65 |
+
{
|
| 66 |
+
"cluster_id": "CAND54",
|
| 67 |
+
"features": {
|
| 68 |
+
"size": 5,
|
| 69 |
+
"strong_link_count": 6,
|
| 70 |
+
"weak_link_count": 0,
|
| 71 |
+
"strong_link_density": 0.6,
|
| 72 |
+
"has_same_contact_edge": 1,
|
| 73 |
+
"order_count": 18,
|
| 74 |
+
"total_amount": 64576,
|
| 75 |
+
"avg_order_amount": 3587.5555555555557,
|
| 76 |
+
"return_rate": 0.5555555555555556,
|
| 77 |
+
"chargeback_rate": 0.1111111111111111,
|
| 78 |
+
"shared_coupon_count": 0,
|
| 79 |
+
"time_span_days": 168.73714120370371,
|
| 80 |
+
"order_velocity": 0.10667479531533575,
|
| 81 |
+
"formation_type_strong": 1
|
| 82 |
+
},
|
| 83 |
+
"label": 1,
|
| 84 |
+
"risk_probability": 0.9952350778861326
|
| 85 |
+
},
|
| 86 |
+
{
|
| 87 |
+
"cluster_id": "CAND48",
|
| 88 |
+
"features": {
|
| 89 |
+
"size": 6,
|
| 90 |
+
"strong_link_count": 9,
|
| 91 |
+
"weak_link_count": 0,
|
| 92 |
+
"strong_link_density": 0.6,
|
| 93 |
+
"has_same_contact_edge": 1,
|
| 94 |
+
"order_count": 17,
|
| 95 |
+
"total_amount": 64348,
|
| 96 |
+
"avg_order_amount": 3785.176470588235,
|
| 97 |
+
"return_rate": 0.35294117647058826,
|
| 98 |
+
"chargeback_rate": 0.11764705882352941,
|
| 99 |
+
"shared_coupon_count": 1,
|
| 100 |
+
"time_span_days": 153.33387731481483,
|
| 101 |
+
"order_velocity": 0.11086917188624103,
|
| 102 |
+
"formation_type_strong": 1
|
| 103 |
+
},
|
| 104 |
+
"label": 1,
|
| 105 |
+
"risk_probability": 0.9967341961721978
|
| 106 |
+
},
|
| 107 |
+
{
|
| 108 |
+
"cluster_id": "CAND66",
|
| 109 |
+
"features": {
|
| 110 |
+
"size": 109,
|
| 111 |
+
"strong_link_count": 0,
|
| 112 |
+
"weak_link_count": 246,
|
| 113 |
+
"strong_link_density": 0.0,
|
| 114 |
+
"has_same_contact_edge": 0,
|
| 115 |
+
"order_count": 287,
|
| 116 |
+
"total_amount": 804955,
|
| 117 |
+
"avg_order_amount": 2804.7212543554006,
|
| 118 |
+
"return_rate": 0.1986062717770035,
|
| 119 |
+
"chargeback_rate": 0.04878048780487805,
|
| 120 |
+
"shared_coupon_count": 0,
|
| 121 |
+
"time_span_days": 177.63575231481482,
|
| 122 |
+
"order_velocity": 1.6156657444238167,
|
| 123 |
+
"formation_type_strong": 0
|
| 124 |
+
},
|
| 125 |
+
"label": 0,
|
| 126 |
+
"risk_probability": 0.0035456513474297945
|
| 127 |
+
},
|
| 128 |
+
{
|
| 129 |
+
"cluster_id": "CAND108",
|
| 130 |
+
"features": {
|
| 131 |
+
"size": 3,
|
| 132 |
+
"strong_link_count": 0,
|
| 133 |
+
"weak_link_count": 3,
|
| 134 |
+
"strong_link_density": 0.0,
|
| 135 |
+
"has_same_contact_edge": 0,
|
| 136 |
+
"order_count": 5,
|
| 137 |
+
"total_amount": 11646,
|
| 138 |
+
"avg_order_amount": 2329.2,
|
| 139 |
+
"return_rate": 0.4,
|
| 140 |
+
"chargeback_rate": 0.0,
|
| 141 |
+
"shared_coupon_count": 0,
|
| 142 |
+
"time_span_days": 107.73620370370371,
|
| 143 |
+
"order_velocity": 0.04640965458325419,
|
| 144 |
+
"formation_type_strong": 0
|
| 145 |
+
},
|
| 146 |
+
"label": 0,
|
| 147 |
+
"risk_probability": 0.0029273850745234796
|
| 148 |
+
},
|
| 149 |
+
{
|
| 150 |
+
"cluster_id": "CAND87",
|
| 151 |
+
"features": {
|
| 152 |
+
"size": 83,
|
| 153 |
+
"strong_link_count": 0,
|
| 154 |
+
"weak_link_count": 222,
|
| 155 |
+
"strong_link_density": 0.0,
|
| 156 |
+
"has_same_contact_edge": 0,
|
| 157 |
+
"order_count": 209,
|
| 158 |
+
"total_amount": 582089,
|
| 159 |
+
"avg_order_amount": 2785.114832535885,
|
| 160 |
+
"return_rate": 0.1674641148325359,
|
| 161 |
+
"chargeback_rate": 0.05741626794258373,
|
| 162 |
+
"shared_coupon_count": 0,
|
| 163 |
+
"time_span_days": 179.47063657407406,
|
| 164 |
+
"order_velocity": 1.164535903976348,
|
| 165 |
+
"formation_type_strong": 0
|
| 166 |
+
},
|
| 167 |
+
"label": 0,
|
| 168 |
+
"risk_probability": 0.0035456513474297945
|
| 169 |
+
},
|
| 170 |
+
{
|
| 171 |
+
"cluster_id": "CAND02",
|
| 172 |
+
"features": {
|
| 173 |
+
"size": 6,
|
| 174 |
+
"strong_link_count": 15,
|
| 175 |
+
"weak_link_count": 0,
|
| 176 |
+
"strong_link_density": 1.0,
|
| 177 |
+
"has_same_contact_edge": 0,
|
| 178 |
+
"order_count": 18,
|
| 179 |
+
"total_amount": 61849,
|
| 180 |
+
"avg_order_amount": 3436.0555555555557,
|
| 181 |
+
"return_rate": 0.3333333333333333,
|
| 182 |
+
"chargeback_rate": 0.16666666666666666,
|
| 183 |
+
"shared_coupon_count": 0,
|
| 184 |
+
"time_span_days": 172.4928125,
|
| 185 |
+
"order_velocity": 0.10435217409421044,
|
| 186 |
+
"formation_type_strong": 1
|
| 187 |
+
},
|
| 188 |
+
"label": 1,
|
| 189 |
+
"risk_probability": 0.9920524617512916
|
| 190 |
+
},
|
| 191 |
+
{
|
| 192 |
+
"cluster_id": "CAND09",
|
| 193 |
+
"features": {
|
| 194 |
+
"size": 6,
|
| 195 |
+
"strong_link_count": 11,
|
| 196 |
+
"weak_link_count": 0,
|
| 197 |
+
"strong_link_density": 0.7333333333333333,
|
| 198 |
+
"has_same_contact_edge": 1,
|
| 199 |
+
"order_count": 19,
|
| 200 |
+
"total_amount": 73548,
|
| 201 |
+
"avg_order_amount": 3870.9473684210525,
|
| 202 |
+
"return_rate": 0.3157894736842105,
|
| 203 |
+
"chargeback_rate": 0.10526315789473684,
|
| 204 |
+
"shared_coupon_count": 1,
|
| 205 |
+
"time_span_days": 168.76631944444443,
|
| 206 |
+
"order_velocity": 0.11258170506144469,
|
| 207 |
+
"formation_type_strong": 1
|
| 208 |
+
},
|
| 209 |
+
"label": 1,
|
| 210 |
+
"risk_probability": 0.9969428584522867
|
| 211 |
+
},
|
| 212 |
+
{
|
| 213 |
+
"cluster_id": "CAND52",
|
| 214 |
+
"features": {
|
| 215 |
+
"size": 6,
|
| 216 |
+
"strong_link_count": 15,
|
| 217 |
+
"weak_link_count": 0,
|
| 218 |
+
"strong_link_density": 1.0,
|
| 219 |
+
"has_same_contact_edge": 0,
|
| 220 |
+
"order_count": 18,
|
| 221 |
+
"total_amount": 65370,
|
| 222 |
+
"avg_order_amount": 3631.6666666666665,
|
| 223 |
+
"return_rate": 0.3888888888888889,
|
| 224 |
+
"chargeback_rate": 0.1111111111111111,
|
| 225 |
+
"shared_coupon_count": 1,
|
| 226 |
+
"time_span_days": 120.77247685185185,
|
| 227 |
+
"order_velocity": 0.14904058001625722,
|
| 228 |
+
"formation_type_strong": 1
|
| 229 |
+
},
|
| 230 |
+
"label": 1,
|
| 231 |
+
"risk_probability": 0.9958819841283693
|
| 232 |
+
},
|
| 233 |
+
{
|
| 234 |
+
"cluster_id": "CAND07",
|
| 235 |
+
"features": {
|
| 236 |
+
"size": 5,
|
| 237 |
+
"strong_link_count": 7,
|
| 238 |
+
"weak_link_count": 0,
|
| 239 |
+
"strong_link_density": 0.7,
|
| 240 |
+
"has_same_contact_edge": 1,
|
| 241 |
+
"order_count": 14,
|
| 242 |
+
"total_amount": 52492,
|
| 243 |
+
"avg_order_amount": 3749.4285714285716,
|
| 244 |
+
"return_rate": 0.2857142857142857,
|
| 245 |
+
"chargeback_rate": 0.2857142857142857,
|
| 246 |
+
"shared_coupon_count": 0,
|
| 247 |
+
"time_span_days": 132.76825231481482,
|
| 248 |
+
"order_velocity": 0.10544689529243599,
|
| 249 |
+
"formation_type_strong": 1
|
| 250 |
+
},
|
| 251 |
+
"label": 1,
|
| 252 |
+
"risk_probability": 0.9959009223567944
|
| 253 |
+
},
|
| 254 |
+
{
|
| 255 |
+
"cluster_id": "CAND73",
|
| 256 |
+
"features": {
|
| 257 |
+
"size": 68,
|
| 258 |
+
"strong_link_count": 1,
|
| 259 |
+
"weak_link_count": 183,
|
| 260 |
+
"strong_link_density": 0.0004389815627743635,
|
| 261 |
+
"has_same_contact_edge": 0,
|
| 262 |
+
"order_count": 187,
|
| 263 |
+
"total_amount": 458341,
|
| 264 |
+
"avg_order_amount": 2451.0213903743315,
|
| 265 |
+
"return_rate": 0.1443850267379679,
|
| 266 |
+
"chargeback_rate": 0.09090909090909091,
|
| 267 |
+
"shared_coupon_count": 1,
|
| 268 |
+
"time_span_days": 180.15159722222222,
|
| 269 |
+
"order_velocity": 1.0380146658890295,
|
| 270 |
+
"formation_type_strong": 0
|
| 271 |
+
},
|
| 272 |
+
"label": 0,
|
| 273 |
+
"risk_probability": 0.007239076424852942
|
| 274 |
+
},
|
| 275 |
+
{
|
| 276 |
+
"cluster_id": "CAND29",
|
| 277 |
+
"features": {
|
| 278 |
+
"size": 4,
|
| 279 |
+
"strong_link_count": 6,
|
| 280 |
+
"weak_link_count": 0,
|
| 281 |
+
"strong_link_density": 1.0,
|
| 282 |
+
"has_same_contact_edge": 1,
|
| 283 |
+
"order_count": 9,
|
| 284 |
+
"total_amount": 52516,
|
| 285 |
+
"avg_order_amount": 5835.111111111111,
|
| 286 |
+
"return_rate": 0.2222222222222222,
|
| 287 |
+
"chargeback_rate": 0.3333333333333333,
|
| 288 |
+
"shared_coupon_count": 1,
|
| 289 |
+
"time_span_days": 163.2079513888889,
|
| 290 |
+
"order_velocity": 0.05514437209345865,
|
| 291 |
+
"formation_type_strong": 1
|
| 292 |
+
},
|
| 293 |
+
"label": 1,
|
| 294 |
+
"risk_probability": 0.9968779996975877
|
| 295 |
+
},
|
| 296 |
+
{
|
| 297 |
+
"cluster_id": "CAND79",
|
| 298 |
+
"features": {
|
| 299 |
+
"size": 64,
|
| 300 |
+
"strong_link_count": 0,
|
| 301 |
+
"weak_link_count": 153,
|
| 302 |
+
"strong_link_density": 0.0,
|
| 303 |
+
"has_same_contact_edge": 0,
|
| 304 |
+
"order_count": 174,
|
| 305 |
+
"total_amount": 460737,
|
| 306 |
+
"avg_order_amount": 2647.9137931034484,
|
| 307 |
+
"return_rate": 0.21264367816091953,
|
| 308 |
+
"chargeback_rate": 0.040229885057471264,
|
| 309 |
+
"shared_coupon_count": 0,
|
| 310 |
+
"time_span_days": 178.9133101851852,
|
| 311 |
+
"order_velocity": 0.9725380399026788,
|
| 312 |
+
"formation_type_strong": 0
|
| 313 |
+
},
|
| 314 |
+
"label": 0,
|
| 315 |
+
"risk_probability": 0.0035456513474297945
|
| 316 |
+
},
|
| 317 |
+
{
|
| 318 |
+
"cluster_id": "CAND69",
|
| 319 |
+
"features": {
|
| 320 |
+
"size": 69,
|
| 321 |
+
"strong_link_count": 1,
|
| 322 |
+
"weak_link_count": 163,
|
| 323 |
+
"strong_link_density": 0.00042625745950554135,
|
| 324 |
+
"has_same_contact_edge": 0,
|
| 325 |
+
"order_count": 162,
|
| 326 |
+
"total_amount": 463506,
|
| 327 |
+
"avg_order_amount": 2861.1481481481483,
|
| 328 |
+
"return_rate": 0.2222222222222222,
|
| 329 |
+
"chargeback_rate": 0.043209876543209874,
|
| 330 |
+
"shared_coupon_count": 1,
|
| 331 |
+
"time_span_days": 174.4325810185185,
|
| 332 |
+
"order_velocity": 0.9287255801300182,
|
| 333 |
+
"formation_type_strong": 0
|
| 334 |
+
},
|
| 335 |
+
"label": 0,
|
| 336 |
+
"risk_probability": 0.0033839575968115728
|
| 337 |
+
},
|
| 338 |
+
{
|
| 339 |
+
"cluster_id": "CAND77",
|
| 340 |
+
"features": {
|
| 341 |
+
"size": 112,
|
| 342 |
+
"strong_link_count": 0,
|
| 343 |
+
"weak_link_count": 265,
|
| 344 |
+
"strong_link_density": 0.0,
|
| 345 |
+
"has_same_contact_edge": 0,
|
| 346 |
+
"order_count": 290,
|
| 347 |
+
"total_amount": 774776,
|
| 348 |
+
"avg_order_amount": 2671.6413793103447,
|
| 349 |
+
"return_rate": 0.18275862068965518,
|
| 350 |
+
"chargeback_rate": 0.06206896551724138,
|
| 351 |
+
"shared_coupon_count": 0,
|
| 352 |
+
"time_span_days": 180.6612037037037,
|
| 353 |
+
"order_velocity": 1.605214589822058,
|
| 354 |
+
"formation_type_strong": 0
|
| 355 |
+
},
|
| 356 |
+
"label": 0,
|
| 357 |
+
"risk_probability": 0.0035456513474297945
|
| 358 |
+
},
|
| 359 |
+
{
|
| 360 |
+
"cluster_id": "CAND81",
|
| 361 |
+
"features": {
|
| 362 |
+
"size": 71,
|
| 363 |
+
"strong_link_count": 1,
|
| 364 |
+
"weak_link_count": 160,
|
| 365 |
+
"strong_link_density": 0.00040241448692152917,
|
| 366 |
+
"has_same_contact_edge": 1,
|
| 367 |
+
"order_count": 204,
|
| 368 |
+
"total_amount": 568308,
|
| 369 |
+
"avg_order_amount": 2785.823529411765,
|
| 370 |
+
"return_rate": 0.19117647058823528,
|
| 371 |
+
"chargeback_rate": 0.05392156862745098,
|
| 372 |
+
"shared_coupon_count": 1,
|
| 373 |
+
"time_span_days": 178.23292824074073,
|
| 374 |
+
"order_velocity": 1.144569648344976,
|
| 375 |
+
"formation_type_strong": 0
|
| 376 |
+
},
|
| 377 |
+
"label": 0,
|
| 378 |
+
"risk_probability": 0.0035711032326407374
|
| 379 |
+
},
|
| 380 |
+
{
|
| 381 |
+
"cluster_id": "CAND101",
|
| 382 |
+
"features": {
|
| 383 |
+
"size": 3,
|
| 384 |
+
"strong_link_count": 0,
|
| 385 |
+
"weak_link_count": 3,
|
| 386 |
+
"strong_link_density": 0.0,
|
| 387 |
+
"has_same_contact_edge": 0,
|
| 388 |
+
"order_count": 5,
|
| 389 |
+
"total_amount": 6796,
|
| 390 |
+
"avg_order_amount": 1359.2,
|
| 391 |
+
"return_rate": 0.6,
|
| 392 |
+
"chargeback_rate": 0.0,
|
| 393 |
+
"shared_coupon_count": 0,
|
| 394 |
+
"time_span_days": 138.31976851851852,
|
| 395 |
+
"order_velocity": 0.03614812295850965,
|
| 396 |
+
"formation_type_strong": 0
|
| 397 |
+
},
|
| 398 |
+
"label": 0,
|
| 399 |
+
"risk_probability": 0.002762985350619287
|
| 400 |
+
},
|
| 401 |
+
{
|
| 402 |
+
"cluster_id": "CAND08",
|
| 403 |
+
"features": {
|
| 404 |
+
"size": 6,
|
| 405 |
+
"strong_link_count": 15,
|
| 406 |
+
"weak_link_count": 0,
|
| 407 |
+
"strong_link_density": 1.0,
|
| 408 |
+
"has_same_contact_edge": 0,
|
| 409 |
+
"order_count": 18,
|
| 410 |
+
"total_amount": 76645,
|
| 411 |
+
"avg_order_amount": 4258.055555555556,
|
| 412 |
+
"return_rate": 0.3888888888888889,
|
| 413 |
+
"chargeback_rate": 0.05555555555555555,
|
| 414 |
+
"shared_coupon_count": 1,
|
| 415 |
+
"time_span_days": 167.69203703703704,
|
| 416 |
+
"order_velocity": 0.10733962278736263,
|
| 417 |
+
"formation_type_strong": 1
|
| 418 |
+
},
|
| 419 |
+
"label": 1,
|
| 420 |
+
"risk_probability": 0.9940880005500065
|
| 421 |
+
},
|
| 422 |
+
{
|
| 423 |
+
"cluster_id": "CAND27",
|
| 424 |
+
"features": {
|
| 425 |
+
"size": 5,
|
| 426 |
+
"strong_link_count": 10,
|
| 427 |
+
"weak_link_count": 0,
|
| 428 |
+
"strong_link_density": 1.0,
|
| 429 |
+
"has_same_contact_edge": 0,
|
| 430 |
+
"order_count": 17,
|
| 431 |
+
"total_amount": 61207,
|
| 432 |
+
"avg_order_amount": 3600.4117647058824,
|
| 433 |
+
"return_rate": 0.17647058823529413,
|
| 434 |
+
"chargeback_rate": 0.17647058823529413,
|
| 435 |
+
"shared_coupon_count": 1,
|
| 436 |
+
"time_span_days": 156.60148148148147,
|
| 437 |
+
"order_velocity": 0.1085558057253136,
|
| 438 |
+
"formation_type_strong": 1
|
| 439 |
+
},
|
| 440 |
+
"label": 1,
|
| 441 |
+
"risk_probability": 0.996945496633462
|
| 442 |
+
},
|
| 443 |
+
{
|
| 444 |
+
"cluster_id": "CAND20",
|
| 445 |
+
"features": {
|
| 446 |
+
"size": 4,
|
| 447 |
+
"strong_link_count": 6,
|
| 448 |
+
"weak_link_count": 0,
|
| 449 |
+
"strong_link_density": 1.0,
|
| 450 |
+
"has_same_contact_edge": 0,
|
| 451 |
+
"order_count": 15,
|
| 452 |
+
"total_amount": 57239,
|
| 453 |
+
"avg_order_amount": 3815.9333333333334,
|
| 454 |
+
"return_rate": 0.3333333333333333,
|
| 455 |
+
"chargeback_rate": 0.13333333333333333,
|
| 456 |
+
"shared_coupon_count": 1,
|
| 457 |
+
"time_span_days": 160.63930555555555,
|
| 458 |
+
"order_velocity": 0.09337689769091037,
|
| 459 |
+
"formation_type_strong": 1
|
| 460 |
+
},
|
| 461 |
+
"label": 1,
|
| 462 |
+
"risk_probability": 0.9969378410557287
|
| 463 |
+
}
|
| 464 |
+
]
|
scoring/model.lgb
ADDED
|
@@ -0,0 +1,2054 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
tree
|
| 2 |
+
version=v4
|
| 3 |
+
num_class=1
|
| 4 |
+
num_tree_per_iteration=1
|
| 5 |
+
label_index=0
|
| 6 |
+
max_feature_idx=13
|
| 7 |
+
objective=binary sigmoid:1
|
| 8 |
+
feature_names=Column_0 Column_1 Column_2 Column_3 Column_4 Column_5 Column_6 Column_7 Column_8 Column_9 Column_10 Column_11 Column_12 Column_13
|
| 9 |
+
feature_infos=[3:168] [0:28] [0:452] [0:1] [0:1] [5:439] [10305:1291235] [2061:4548.8000000000002] [0:0.5714285714285714] [0:0.33333333333333331] [0:2] [80.053703703703704:180.73202546296295] [0.028612871818308266:2.4496926129718695] [0:1]
|
| 10 |
+
tree_sizes=553 874 769 877 874 881 880 873 873 880 882 876 878 880 885 878 887 871 875 880 881 877 883 879 879 877 884 883 877 881 880 879 883 887 886 881 887 885 883 886 884 886 886 889 888 887 890 881 887 892 885 893 884 890 893 887 888 886 891 890 883 890 886 890 891 886 886 887 891 890 888 895 890 894 892 893 896 895 893 895 895 894 895 894 896 897 894 895 893 890 897 899 892 895 895 898 887 895 896 896
|
| 11 |
+
|
| 12 |
+
Tree=0
|
| 13 |
+
num_leaves=4
|
| 14 |
+
num_cat=0
|
| 15 |
+
split_feature=2 11 5
|
| 16 |
+
split_gain=82.066 0.71839 7.10543e-15
|
| 17 |
+
threshold=1.0000000180025095e-35 133.51370949074075 6.5000000000000009
|
| 18 |
+
decision_type=2 2 2
|
| 19 |
+
left_child=1 -1 -2
|
| 20 |
+
right_child=2 -3 -4
|
| 21 |
+
leaf_value=0.1930445524210789 0.032261939230608494 0.23324020571869669 0.032261939230608494
|
| 22 |
+
leaf_weight=1.2439156323671365 1.4926987588405598 10.448891311883925 8.2098431736230832
|
| 23 |
+
leaf_count=5 6 42 33
|
| 24 |
+
internal_value=0.139762 0.228964 0.0322619
|
| 25 |
+
internal_weight=21.3953 11.6928 9.70254
|
| 26 |
+
internal_count=86 47 39
|
| 27 |
+
is_linear=0
|
| 28 |
+
shrinkage=1
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
Tree=1
|
| 32 |
+
num_leaves=7
|
| 33 |
+
num_cat=0
|
| 34 |
+
split_feature=7 1 5 11 0 4
|
| 35 |
+
split_gain=74.4604 0.665595 0.00139175 0.000597925 7.10543e-15 7.10543e-15
|
| 36 |
+
threshold=3112.1875000000005 2.5000000000000004 5.5000000000000009 141.79473379629633 7.0000000000000009 1.0000000180025095e-35
|
| 37 |
+
decision_type=2 2 2 2 2 2
|
| 38 |
+
left_child=2 -2 -1 -3 -4 -5
|
| 39 |
+
right_child=1 3 4 5 -6 -7
|
| 40 |
+
leaf_value=-0.10342789578905492 0.050941784258864947 0.090682433465454779 -0.10163940525078299 0.089598162538490678 -0.10163940525078292 0.089598162538490636
|
| 41 |
+
leaf_weight=1.2474250793457056 1.2364570945501316 1.4840020835399617 2.4993495643138868 5.6725022941827756 5.9984389543533325 3.2061969488859177
|
| 42 |
+
leaf_count=5 5 6 10 23 24 13
|
| 43 |
+
internal_value=1.62416e-05 0.0856162 -0.101868 0.0897534 -0.101639 0.0895982
|
| 44 |
+
internal_weight=21.3444 11.5992 9.74521 10.3627 8.49779 8.8787
|
| 45 |
+
internal_count=86 47 39 42 34 36
|
| 46 |
+
is_linear=0
|
| 47 |
+
shrinkage=0.05
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
Tree=2
|
| 51 |
+
num_leaves=6
|
| 52 |
+
num_cat=0
|
| 53 |
+
split_feature=7 1 12 11 6
|
| 54 |
+
split_gain=67.6008 0.62316 0.00108445 0.000455319 4.73442e-07
|
| 55 |
+
threshold=3112.1875000000005 2.5000000000000004 0.046585109941867327 141.79473379629633 17835.500000000004
|
| 56 |
+
decision_type=2 2 2 2 2
|
| 57 |
+
left_child=2 -2 -1 -3 -4
|
| 58 |
+
right_child=1 3 4 -5 -6
|
| 59 |
+
leaf_value=-0.098222188977615796 0.048669522557685856 0.087156175904335012 -0.096615383620140993 0.086204543567968514 -0.0966487227699587
|
| 60 |
+
leaf_weight=1.248264998197558 1.2296466380357731 1.467251956462859 1.2484656870365123 8.7695086598396284 7.2412829995155334
|
| 61 |
+
leaf_count=5 5 6 5 36 29
|
| 62 |
+
internal_value=2.87115e-05 0.0823011 -0.0968461 0.0863409 -0.0966438
|
| 63 |
+
internal_weight=21.2044 11.4664 9.73801 10.2368 8.48975
|
| 64 |
+
internal_count=86 47 39 42 34
|
| 65 |
+
is_linear=0
|
| 66 |
+
shrinkage=0.05
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
Tree=3
|
| 70 |
+
num_leaves=7
|
| 71 |
+
num_cat=0
|
| 72 |
+
split_feature=2 11 8 12 6 7
|
| 73 |
+
split_gain=61.8731 0.587705 0.00367442 0.00110176 1.22284e-06 2.40187e-07
|
| 74 |
+
threshold=1.0000000180025095e-35 133.51370949074075 0.37980769230769235 0.065152412384244726 17835.500000000004 4317.0726495726512
|
| 75 |
+
decision_type=2 2 2 2 2 2
|
| 76 |
+
left_child=1 -1 4 -3 -2 -5
|
| 77 |
+
right_child=2 3 -4 5 -6 -7
|
| 78 |
+
leaf_value=0.04667381315066154 -0.092295175394442819 0.084538242823278584 -0.095253852398532762 0.083214287911124257 -0.0923489100898221 0.083191776414990704
|
| 79 |
+
leaf_weight=1.2163800746202493 1.2412882149219493 1.9321163296699513 1.2419511824846257 6.7151724696159345 7.2002349644899368 1.4387681186199186
|
| 80 |
+
leaf_count=5 5 8 5 28 29 6
|
| 81 |
+
internal_value=3.82822e-05 0.0795052 -0.0927146 0.0834647 -0.092341 0.0832103
|
| 82 |
+
internal_weight=20.9859 11.3024 9.68347 10.0861 8.44152 8.15394
|
| 83 |
+
internal_count=86 47 39 42 34 34
|
| 84 |
+
is_linear=0
|
| 85 |
+
shrinkage=0.05
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
Tree=4
|
| 89 |
+
num_leaves=7
|
| 90 |
+
num_cat=0
|
| 91 |
+
split_feature=7 1 12 11 11 0
|
| 92 |
+
split_gain=56.6084 0.560845 0.00294361 0.00121052 2.37162e-06 4.26503e-07
|
| 93 |
+
threshold=3112.1875000000005 2.5000000000000004 0.046585109941867327 141.79473379629633 133.51370949074075 3.5000000000000004
|
| 94 |
+
decision_type=2 2 2 2 2 2
|
| 95 |
+
left_child=2 -2 -1 -3 -4 -5
|
| 96 |
+
right_child=1 3 4 5 -6 -7
|
| 97 |
+
leaf_value=-0.091218722018037074 0.044692577885030123 0.082131324226660612 -0.088549404265767295 0.080529911728688675 -0.088615273661690988 0.080562347051243738
|
| 98 |
+
leaf_weight=1.2330005764961267 1.2075967341661442 1.4283113479614247 1.7207350879907588 1.176931157708166 6.638588011264801 7.2988456338644028
|
| 99 |
+
leaf_count=5 5 6 7 5 27 31
|
| 100 |
+
internal_value=4.57358e-05 0.0768623 -0.0889381 0.0807848 -0.0886017 0.0805578
|
| 101 |
+
internal_weight=20.704 11.1117 9.59232 9.90409 8.35932 8.47578
|
| 102 |
+
internal_count=86 47 39 42 34 36
|
| 103 |
+
is_linear=0
|
| 104 |
+
shrinkage=0.05
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
Tree=5
|
| 108 |
+
num_leaves=7
|
| 109 |
+
num_cat=0
|
| 110 |
+
split_feature=2 11 8 12 12 11
|
| 111 |
+
split_gain=52.1697 0.534151 0.00597517 0.00166896 3.92204e-06 5.09929e-07
|
| 112 |
+
threshold=1.0000000180025095e-35 133.51370949074075 0.37980769230769235 0.065152412384244726 0.057153336188971379 148.79337384259262
|
| 113 |
+
decision_type=2 2 2 2 2 2
|
| 114 |
+
left_child=1 -1 4 -3 -2 -5
|
| 115 |
+
right_child=2 3 -4 5 -6 -7
|
| 116 |
+
leaf_value=0.043017542984362105 -0.08524151794941176 0.079853079758136811 -0.089074561699500135 0.078163284367070693 -0.085338883602630033 0.078196740304427539
|
| 117 |
+
leaf_weight=1.1899101287126566 1.2125268876552562 1.8703867793083171 1.2192777097225178 1.3829243779182432 7.0360173434019089 6.4557932019233704
|
| 118 |
+
leaf_count=5 5 8 5 6 29 28
|
| 119 |
+
internal_value=5.15016e-05 0.074636 -0.0858075 0.0785111 -0.0853246 0.0781908
|
| 120 |
+
internal_weight=20.3668 10.899 9.46782 9.7091 8.24854 7.83872
|
| 121 |
+
internal_count=86 47 39 42 34 34
|
| 122 |
+
is_linear=0
|
| 123 |
+
shrinkage=0.05
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
Tree=6
|
| 127 |
+
num_leaves=7
|
| 128 |
+
num_cat=0
|
| 129 |
+
split_feature=2 11 8 12 12 7
|
| 130 |
+
split_gain=48.0088 0.51813 0.00474055 0.00131991 3.02662e-06 4.05399e-07
|
| 131 |
+
threshold=1.0000000180025095e-35 133.51370949074075 0.37980769230769235 0.065152412384244726 0.057153336188971379 4317.0726495726512
|
| 132 |
+
decision_type=2 2 2 2 2 2
|
| 133 |
+
left_child=1 -1 4 -3 -2 -5
|
| 134 |
+
right_child=2 3 -4 5 -6 -7
|
| 135 |
+
leaf_value=0.041224848892825315 -0.082361959085578224 0.077565104646246552 -0.085798940887919936 0.076075869805599397 -0.082448199492469315 0.076045690863144111
|
| 136 |
+
leaf_weight=1.179830446839335 1.192670613527296 1.8302927613258342 1.2029409408569325 6.3077281713485718 6.9214366972446442 1.3511618077754972
|
| 137 |
+
leaf_count=5 5 8 5 28 29 6
|
| 138 |
+
internal_value=5.60081e-05 0.0724735 -0.0828698 0.0763588 -0.0824355 0.0760705
|
| 139 |
+
internal_weight=19.9861 10.669 9.31705 9.48918 8.11411 7.65889
|
| 140 |
+
internal_count=86 47 39 42 34 34
|
| 141 |
+
is_linear=0
|
| 142 |
+
shrinkage=0.05
|
| 143 |
+
|
| 144 |
+
|
| 145 |
+
Tree=7
|
| 146 |
+
num_leaves=7
|
| 147 |
+
num_cat=0
|
| 148 |
+
split_feature=7 1 12 11 8 6
|
| 149 |
+
split_gain=44.4771 0.49671 0.00810296 0.0029023 1.09563e-05 2.78578e-06
|
| 150 |
+
threshold=3112.1875000000005 2.5000000000000004 0.046585109941867327 141.79473379629633 0.31009615384615391 42986.000000000007
|
| 151 |
+
decision_type=2 2 2 2 2 2
|
| 152 |
+
left_child=2 -2 -1 -3 -4 -5
|
| 153 |
+
right_child=1 3 4 5 -6 -7
|
| 154 |
+
leaf_value=-0.084285547508256564 0.039805551243280855 0.076655996510183039 -0.079880561303504738 0.074080055285562552 -0.079726609628141556 0.074165912972976755
|
| 155 |
+
leaf_weight=1.1847488284111038 1.1593277156352986 1.3581690192222575 6.5559337288141251 1.096968740224838 1.4029920995235441 6.8096721768379211
|
| 156 |
+
leaf_count=5 5 6 28 5 6 31
|
| 157 |
+
internal_value=5.94785e-05 0.0706599 -0.0804277 0.0745208 -0.0798534 0.074154
|
| 158 |
+
internal_weight=19.5678 10.4241 9.14367 9.26481 7.95893 7.90664
|
| 159 |
+
internal_count=86 47 39 42 34 36
|
| 160 |
+
is_linear=0
|
| 161 |
+
shrinkage=0.05
|
| 162 |
+
|
| 163 |
+
|
| 164 |
+
Tree=8
|
| 165 |
+
num_leaves=7
|
| 166 |
+
num_cat=0
|
| 167 |
+
split_feature=7 8 5 6 4 9
|
| 168 |
+
split_gain=41.1179 0.495951 0.00664183 0.00222736 0.00167781 0.000410439
|
| 169 |
+
threshold=3112.1875000000005 0.40833333333333338 5.5000000000000009 42986.000000000007 1.0000000180025095e-35 0.21825396825396828
|
| 170 |
+
decision_type=2 2 2 2 2 2
|
| 171 |
+
left_child=2 3 -1 4 -2 -5
|
| 172 |
+
right_child=1 -3 -4 5 -6 -7
|
| 173 |
+
leaf_value=-0.081609467453499146 0.073086372699730492 0.040246179662398615 -0.077559324356391984 0.072426785842704122 0.075847270191939598 0.073321822227397235
|
| 174 |
+
leaf_weight=1.1634619385004059 1.0787670463323575 1.3185045868158329 7.7883933484554291 4.9166114330291748 1.1232455372810364 1.7321313172578809
|
| 175 |
+
leaf_count=5 5 6 34 23 5 8
|
| 176 |
+
internal_value=6.21514e-05 0.0688546 -0.0780857 0.0731164 0.0744947 0.07266
|
| 177 |
+
internal_weight=19.1211 10.1693 8.95186 8.85076 2.20201 6.64874
|
| 178 |
+
internal_count=86 47 39 41 10 31
|
| 179 |
+
is_linear=0
|
| 180 |
+
shrinkage=0.05
|
| 181 |
+
|
| 182 |
+
|
| 183 |
+
Tree=9
|
| 184 |
+
num_leaves=7
|
| 185 |
+
num_cat=0
|
| 186 |
+
split_feature=2 11 8 12 8 12
|
| 187 |
+
split_gain=38.2564 0.47099 0.00971658 0.00134374 9.15222e-05 8.5431e-06
|
| 188 |
+
threshold=1.0000000180025095e-35 133.51370949074075 0.37980769230769235 0.065152412384244726 0.37980769230769235 0.057153336188971379
|
| 189 |
+
decision_type=2 2 2 2 2 2
|
| 190 |
+
left_child=1 -1 5 -3 -5 -2
|
| 191 |
+
right_child=2 3 -4 4 -6 -7
|
| 192 |
+
leaf_value=0.036884259324746746 -0.075374644139064667 0.072503460712974296 -0.080451132838729761 0.070857408177662437 0.071327830184486976 -0.075524376303285998
|
| 193 |
+
leaf_weight=1.1250674128532434 1.1165634840726832 1.7085118144750575 1.1406608074903486 5.8159056305885315 1.2574799358844755 6.4885646849870682
|
| 194 |
+
leaf_count=5 5 8 5 28 6 29
|
| 195 |
+
internal_value=6.38395e-05 0.0673429 -0.0761478 0.071245 0.070941 -0.0755024
|
| 196 |
+
internal_weight=18.6528 9.90696 8.74579 8.7819 7.07339 7.60513
|
| 197 |
+
internal_count=86 47 39 42 34 34
|
| 198 |
+
is_linear=0
|
| 199 |
+
shrinkage=0.05
|
| 200 |
+
|
| 201 |
+
|
| 202 |
+
Tree=10
|
| 203 |
+
num_leaves=7
|
| 204 |
+
num_cat=0
|
| 205 |
+
split_feature=2 9 8 11 12 12
|
| 206 |
+
split_gain=35.4973 0.479056 0.00802536 0.00186363 0.00106585 6.79661e-06
|
| 207 |
+
threshold=1.0000000180025095e-35 0.075080247396852748 0.37980769230769235 141.79473379629633 0.065152412384244726 0.057153336188971379
|
| 208 |
+
decision_type=2 2 2 2 2 2
|
| 209 |
+
left_child=1 -1 5 -3 -5 -2
|
| 210 |
+
right_child=2 3 -4 4 -6 -7
|
| 211 |
+
leaf_value=0.037103223145715646 -0.073532368018833894 0.07190519761274379 -0.078196748553504059 0.070932617799112946 0.069485535107175603 -0.073667659169007235
|
| 212 |
+
leaf_weight=1.2629062384367014 1.0880334228277186 1.2667635977268199 1.115504205226898 1.660253584384918 5.448053240776062 6.3236725628376007
|
| 213 |
+
leaf_count=6 5 6 5 8 27 29
|
| 214 |
+
internal_value=6.53544e-05 0.0658096 -0.0742429 0.0701384 0.0698235 -0.0736478
|
| 215 |
+
internal_weight=18.1652 9.63798 8.52721 8.37507 7.10831 7.41171
|
| 216 |
+
internal_count=86 47 39 41 35 34
|
| 217 |
+
is_linear=0
|
| 218 |
+
shrinkage=0.05
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
Tree=11
|
| 222 |
+
num_leaves=7
|
| 223 |
+
num_cat=0
|
| 224 |
+
split_feature=7 1 12 11 9 11
|
| 225 |
+
split_gain=33.1373 0.475899 0.0114909 0.00185294 0.000220994 2.10641e-05
|
| 226 |
+
threshold=3112.1875000000005 2.5000000000000004 0.046585109941867327 141.79473379629633 0.075080247396852748 133.51370949074075
|
| 227 |
+
decision_type=2 2 2 2 2 2
|
| 228 |
+
left_child=2 -2 -1 -3 -5 -4
|
| 229 |
+
right_child=1 3 5 4 -6 -7
|
| 230 |
+
leaf_value=-0.077449289151936135 0.033279286118847784 0.070389415472064426 -0.071779567111123543 0.068976460844906745 0.06817315250376077 -0.07199119917480043
|
| 231 |
+
leaf_weight=1.0930734276771561 1.077754572033881 1.2302654534578303 1.4794269502162931 0.99700576066970814 6.0605845898389816 5.7282752245664597
|
| 232 |
+
leaf_count=5 5 6 7 5 31 27
|
| 233 |
+
internal_value=6.61067e-05 0.0645344 -0.0726722 0.0685988 0.0682866 -0.0719478
|
| 234 |
+
internal_weight=17.6664 9.36561 8.30078 8.28786 7.05759 7.2077
|
| 235 |
+
internal_count=86 47 39 42 36 34
|
| 236 |
+
is_linear=0
|
| 237 |
+
shrinkage=0.05
|
| 238 |
+
|
| 239 |
+
|
| 240 |
+
Tree=12
|
| 241 |
+
num_leaves=7
|
| 242 |
+
num_cat=0
|
| 243 |
+
split_feature=7 3 12 3 11 8
|
| 244 |
+
split_gain=30.8387 0.485179 0.00960963 0.0012348 0.000973892 1.71113e-05
|
| 245 |
+
threshold=3112.1875000000005 0.63333333333333341 0.046585109941867327 0.68333333333333346 141.79473379629633 0.31009615384615391
|
| 246 |
+
decision_type=2 2 2 2 2 2
|
| 247 |
+
left_child=2 -2 -1 -3 -5 -4
|
| 248 |
+
right_child=1 3 5 4 -6 -7
|
| 249 |
+
leaf_value=-0.075520827820082612 0.033501967349706951 0.068857893861478878 -0.070460258488882196 0.06879936231023942 0.067085578873881238 -0.070254919880213665
|
| 250 |
+
leaf_weight=1.0656314641237274 1.1938995271921138 1.7841720283031461 5.7696630209684372 0.98896507918834675 5.1240549236536026 1.2310415506362913
|
| 251 |
+
leaf_count=5 6 9 28 5 27 6
|
| 252 |
+
internal_value=6.68297e-05 0.0632094 -0.0710975 0.0677006 0.0673628 -0.0704242
|
| 253 |
+
internal_weight=17.1574 9.09109 8.06634 7.89719 6.11302 7.0007
|
| 254 |
+
internal_count=86 47 39 41 32 34
|
| 255 |
+
is_linear=0
|
| 256 |
+
shrinkage=0.05
|
| 257 |
+
|
| 258 |
+
|
| 259 |
+
Tree=13
|
| 260 |
+
num_leaves=7
|
| 261 |
+
num_cat=0
|
| 262 |
+
split_feature=2 11 8 12 9 12
|
| 263 |
+
split_gain=28.875 0.460053 0.012447 0.000856805 0.00011562 1.70654e-05
|
| 264 |
+
threshold=1.0000000180025095e-35 133.51370949074075 0.37980769230769235 0.065152412384244726 0.075080247396852748 0.057153336188971379
|
| 265 |
+
decision_type=2 2 2 2 2 2
|
| 266 |
+
left_child=1 -1 5 -3 -5 -2
|
| 267 |
+
right_child=2 3 -4 4 -6 -7
|
| 268 |
+
leaf_value=0.030890087269915469 -0.068844180687072695 0.067365934528544585 -0.07491155650147141 0.066556939476662982 0.065953825729960738 -0.069068423559230638
|
| 269 |
+
leaf_weight=1.0397322177886978 0.99393287301063438 1.5245727151632307 1.0391902029514311 0.934267297387123 5.3173656910657883 5.795934185385704
|
| 270 |
+
leaf_count=5 5 8 5 5 29 29
|
| 271 |
+
internal_value=6.69498e-05 0.0621266 -0.0698155 0.0663031 0.066044 -0.0690356
|
| 272 |
+
internal_weight=16.645 8.81594 7.82906 7.77621 6.25163 6.78987
|
| 273 |
+
internal_count=86 47 39 42 34 34
|
| 274 |
+
is_linear=0
|
| 275 |
+
shrinkage=0.05
|
| 276 |
+
|
| 277 |
+
|
| 278 |
+
Tree=14
|
| 279 |
+
num_leaves=7
|
| 280 |
+
num_cat=0
|
| 281 |
+
split_feature=2 11 8 12 9 12
|
| 282 |
+
split_gain=26.9382 0.459065 0.0105335 0.000704175 9.47011e-05 1.38494e-05
|
| 283 |
+
threshold=1.0000000180025095e-35 133.51370949074075 0.37980769230769235 0.065152412384244726 0.075080247396852748 0.057153336188971379
|
| 284 |
+
decision_type=2 2 2 2 2 2
|
| 285 |
+
left_child=1 -1 5 -3 -5 -2
|
| 286 |
+
right_child=2 3 -4 4 -6 -7
|
| 287 |
+
leaf_value=0.029651734623831839 -0.067590571418553 0.066237534135364193 -0.073249213876235661 0.065490928904136186 0.064935639733780637 -0.067795847197589632
|
| 288 |
+
leaf_weight=1.0292685776948944 0.96254490315914054 1.4742923229932783 1.0103661864995954 0.90279860794544209 5.1353192180395126 5.6141017973423004
|
| 289 |
+
leaf_count=5 5 8 5 5 29 29
|
| 290 |
+
internal_value=6.71579e-05 0.0609673 -0.068496 0.0652579 0.0650187 -0.0677658
|
| 291 |
+
internal_weight=16.1287 8.54168 7.58701 7.51241 6.03812 6.57665
|
| 292 |
+
internal_count=86 47 39 42 34 34
|
| 293 |
+
is_linear=0
|
| 294 |
+
shrinkage=0.05
|
| 295 |
+
|
| 296 |
+
|
| 297 |
+
Tree=15
|
| 298 |
+
num_leaves=7
|
| 299 |
+
num_cat=0
|
| 300 |
+
split_feature=7 1 12 11 9 8
|
| 301 |
+
split_gain=25.2841 0.466343 0.0135987 0.00208613 7.84636e-05 2.37464e-05
|
| 302 |
+
threshold=3112.1875000000005 2.5000000000000004 0.046585109941867327 141.79473379629633 0.075080247396852748 0.31009615384615391
|
| 303 |
+
decision_type=2 2 2 2 2 2
|
| 304 |
+
left_child=2 -2 -1 -3 -5 -4
|
| 305 |
+
right_child=1 3 5 4 -6 -7
|
| 306 |
+
leaf_value=-0.072893663688079216 0.027857376697344789 0.066425308757184637 -0.066629706487692036 0.064509006738265373 0.063997034156788757 -0.066375603717052159
|
| 307 |
+
leaf_weight=0.98681633174419481 0.99035722017288019 1.1084902882575987 5.2441673576831818 0.8715066760778426 5.2964922934770584 1.114899083971977
|
| 308 |
+
leaf_count=5 5 6 28 5 31 6
|
| 309 |
+
internal_value=6.71441e-05 0.0600471 -0.0674326 0.0644283 0.0640694 -0.0665852
|
| 310 |
+
internal_weight=15.6127 8.26685 7.34588 7.27649 6.168 6.35907
|
| 311 |
+
internal_count=86 47 39 42 36 34
|
| 312 |
+
is_linear=0
|
| 313 |
+
shrinkage=0.05
|
| 314 |
+
|
| 315 |
+
|
| 316 |
+
Tree=16
|
| 317 |
+
num_leaves=7
|
| 318 |
+
num_cat=0
|
| 319 |
+
split_feature=2 9 8 11 12 12
|
| 320 |
+
split_gain=23.6365 0.460809 0.0114327 0.00129081 0.000857083 1.66703e-05
|
| 321 |
+
threshold=1.0000000180025095e-35 0.075080247396852748 0.37980769230769235 141.79473379629633 0.065152412384244726 0.057153336188971379
|
| 322 |
+
decision_type=2 2 2 2 2 2
|
| 323 |
+
left_child=1 -1 5 -3 -5 -2
|
| 324 |
+
right_child=2 3 -4 4 -6 -7
|
| 325 |
+
leaf_value=0.028761524977802318 -0.065324699374286921 0.06537421778726113 -0.071401860938867565 0.064570157556829572 0.063147457310399377 -0.065557862254063778
|
| 326 |
+
leaf_weight=1.0873456448316572 0.89769710600376118 1.0709487497806547 0.95586602389812458 1.3890060782432554 4.4504676759243011 5.2488974630832672
|
| 327 |
+
leaf_count=6 5 6 5 8 27 29
|
| 328 |
+
internal_value=6.69732e-05 0.0590177 -0.0663149 0.0637785 0.0634859 -0.0655238
|
| 329 |
+
internal_weight=15.1002 7.99777 7.10246 6.91042 5.83947 6.14659
|
| 330 |
+
internal_count=86 47 39 41 35 34
|
| 331 |
+
is_linear=0
|
| 332 |
+
shrinkage=0.05
|
| 333 |
+
|
| 334 |
+
|
| 335 |
+
Tree=17
|
| 336 |
+
num_leaves=7
|
| 337 |
+
num_cat=0
|
| 338 |
+
split_feature=7 1 5 11 9 8
|
| 339 |
+
split_gain=22.2333 0.452603 0.01447 0.00133644 0.000225874 1.56853e-05
|
| 340 |
+
threshold=3112.1875000000005 2.5000000000000004 5.5000000000000009 141.79473379629633 0.075080247396852748 0.22390932420872542
|
| 341 |
+
decision_type=2 2 2 2 2 2
|
| 342 |
+
left_child=2 -2 -1 -3 -5 -4
|
| 343 |
+
right_child=1 3 5 4 -6 -7
|
| 344 |
+
leaf_value=-0.071224329883907991 0.025963412749295117 0.064405295726729775 -0.064573159584937589 0.063217045276053679 0.062323782790886573 -0.064388530194293372
|
| 345 |
+
leaf_weight=0.9326527565717696 0.9537997394800185 1.0336525738239286 4.3687743544578552 0.82667908072471608 4.91704460978508 1.5615205615758894
|
| 346 |
+
leaf_count=5 5 6 25 5 31 9
|
| 347 |
+
internal_value=6.6361e-05 0.0582118 -0.065435 0.0627502 0.0624523 -0.0645245
|
| 348 |
+
internal_weight=14.5941 7.73118 6.86295 6.77738 5.74372 5.93029
|
| 349 |
+
internal_count=86 47 39 42 36 34
|
| 350 |
+
is_linear=0
|
| 351 |
+
shrinkage=0.05
|
| 352 |
+
|
| 353 |
+
|
| 354 |
+
Tree=18
|
| 355 |
+
num_leaves=7
|
| 356 |
+
num_cat=0
|
| 357 |
+
split_feature=7 9 12 6 9 9
|
| 358 |
+
split_gain=20.8363 0.652884 0.0278199 0.0010596 0.000166491 0.00017995
|
| 359 |
+
threshold=3449.4166666666674 0.071839745922519613 0.050737547542749055 40049.000000000007 0.21825396825396828 0.075080247396852748
|
| 360 |
+
decision_type=2 2 2 2 2 2
|
| 361 |
+
left_child=1 2 -1 -2 5 -5
|
| 362 |
+
right_child=3 -3 -4 4 -6 -7
|
| 363 |
+
leaf_value=-0.071477255919176391 0.063450035666864163 -0.022026255105573586 -0.063623777802643541 0.062407425281717423 0.062381491662216286 0.06157488956704156
|
| 364 |
+
leaf_weight=1.4824470132589338 1.3250540494918821 1.0033586025238035 4.711548388004303 0.79630309343338002 1.2639052122831342 3.5102473795413971
|
| 365 |
+
leaf_count=8 8 6 28 5 8 23
|
| 366 |
+
internal_value=6.59451e-05 -0.0594424 -0.0655034 0.0621792 0.0618769 0.0617288
|
| 367 |
+
internal_weight=14.0929 7.19735 6.194 6.89551 5.57046 4.30655
|
| 368 |
+
internal_count=86 42 36 44 36 28
|
| 369 |
+
is_linear=0
|
| 370 |
+
shrinkage=0.05
|
| 371 |
+
|
| 372 |
+
|
| 373 |
+
Tree=19
|
| 374 |
+
num_leaves=7
|
| 375 |
+
num_cat=0
|
| 376 |
+
split_feature=7 3 12 3 11 9
|
| 377 |
+
split_gain=19.6055 0.444006 0.0104534 0.00103889 0.00063865 6.98296e-05
|
| 378 |
+
threshold=3112.1875000000005 0.63333333333333341 0.046585109941867327 0.68333333333333346 141.79473379629633 0.071279139270771077
|
| 379 |
+
decision_type=2 2 2 2 2 2
|
| 380 |
+
left_child=2 -2 -1 -3 -5 -4
|
| 381 |
+
right_child=1 3 5 4 -6 -7
|
| 382 |
+
leaf_value=-0.068717639224812194 0.025629335762716639 0.062741146854963084 -0.062759018789244531 0.062506077126058254 0.060952086412690371 -0.063256992222117198
|
| 383 |
+
leaf_weight=0.87429985404014576 0.99747399985790242 1.4439515471458433 4.6966153234243393 0.79297935962676991 3.9772752821445465 0.828120857477188
|
| 384 |
+
leaf_count=5 6 9 29 5 27 5
|
| 385 |
+
internal_value=6.8314e-05 0.0565956 -0.0636376 0.0615661 0.0612104 -0.0628337
|
| 386 |
+
internal_weight=13.6107 7.21168 6.39904 6.21421 4.77025 5.52474
|
| 387 |
+
internal_count=86 47 39 41 32 34
|
| 388 |
+
is_linear=0
|
| 389 |
+
shrinkage=0.05
|
| 390 |
+
|
| 391 |
+
|
| 392 |
+
Tree=20
|
| 393 |
+
num_leaves=7
|
| 394 |
+
num_cat=0
|
| 395 |
+
split_feature=2 11 7 3 6 9
|
| 396 |
+
split_gain=18.4871 0.422107 0.0177812 0.00075395 0.000542814 0.000113598
|
| 397 |
+
threshold=1.0000000180025095e-35 133.51370949074075 2936.421364560174 0.68333333333333346 50443.000000000007 0.087121212121212141
|
| 398 |
+
decision_type=2 2 2 2 2 2
|
| 399 |
+
left_child=1 -1 -2 4 -3 -5
|
| 400 |
+
right_child=2 3 -4 5 -6 -7
|
| 401 |
+
leaf_value=0.023900812353780387 -0.061982260484055023 0.062332936528495059 -0.070377612538269629 0.060846385615579639 0.060668994649296808 0.060159089984660935
|
| 402 |
+
leaf_weight=0.89601355791091908 5.4556252509355545 0.94887344539165486 0.71314486861228932 0.73183779418468464 1.0138113945722578 3.3682003915309906
|
| 403 |
+
leaf_count=5 35 6 4 5 7 24
|
| 404 |
+
internal_value=6.73833e-05 0.0559334 -0.0629528 0.0606675 0.0614734 0.0602818
|
| 405 |
+
internal_weight=13.1275 6.95874 6.16877 6.06272 1.96268 4.10004
|
| 406 |
+
internal_count=86 47 39 42 13 29
|
| 407 |
+
is_linear=0
|
| 408 |
+
shrinkage=0.05
|
| 409 |
+
|
| 410 |
+
|
| 411 |
+
Tree=21
|
| 412 |
+
num_leaves=7
|
| 413 |
+
num_cat=0
|
| 414 |
+
split_feature=7 1 5 11 3 9
|
| 415 |
+
split_gain=17.3496 0.44958 0.011074 0.00117389 0.00012922 5.21093e-05
|
| 416 |
+
threshold=3112.1875000000005 2.5000000000000004 5.5000000000000009 141.79473379629633 0.63333333333333341 0.071279139270771077
|
| 417 |
+
decision_type=2 2 2 2 2 2
|
| 418 |
+
left_child=2 -2 -1 -3 -5 -4
|
| 419 |
+
right_child=1 3 5 4 -6 -7
|
| 420 |
+
leaf_value=-0.06756471513158957 0.021553084846690478 0.061767345011491871 -0.061249842101192158 0.060437828583681366 0.059710418143377145 -0.061696580908138204
|
| 421 |
+
leaf_weight=0.82338908314704884 0.86779353022575367 0.91309693455696095 4.3476990461349487 0.71383780241012562 4.2189132273197174 0.76806645095348347
|
| 422 |
+
leaf_count=5 5 6 29 5 31 5
|
| 423 |
+
internal_value=6.67108e-05 0.0551354 -0.0621831 0.0601205 0.0598157 -0.0613169
|
| 424 |
+
internal_weight=12.6528 6.71364 5.93915 5.84585 4.93275 5.11577
|
| 425 |
+
internal_count=86 47 39 42 36 34
|
| 426 |
+
is_linear=0
|
| 427 |
+
shrinkage=0.05
|
| 428 |
+
|
| 429 |
+
|
| 430 |
+
Tree=22
|
| 431 |
+
num_leaves=7
|
| 432 |
+
num_cat=0
|
| 433 |
+
split_feature=7 9 12 6 9 9
|
| 434 |
+
split_gain=16.3951 0.572651 0.0250496 0.000768526 0.000137849 7.89605e-05
|
| 435 |
+
threshold=3449.4166666666674 0.071839745922519613 0.050737547542749055 40049.000000000007 0.21825396825396828 0.075080247396852748
|
| 436 |
+
decision_type=2 2 2 2 2 2
|
| 437 |
+
left_child=1 2 -1 -2 5 -5
|
| 438 |
+
right_child=3 -3 -4 4 -6 -7
|
| 439 |
+
leaf_value=-0.068535316052522055 0.060816213959984794 -0.019438194723139134 -0.060602147086615446 0.059719033650448367 0.059873001198438448 0.059122713194765142
|
| 440 |
+
leaf_weight=1.3200946748256681 1.1560638695955274 0.89922252297401417 4.0412775725126266 0.68117281794548068 1.0909055322408674 2.9999326914548874
|
| 441 |
+
leaf_count=8 8 6 28 5 8 23
|
| 442 |
+
internal_value=6.59541e-05 -0.0563625 -0.0625555 0.0596596 0.0593794 0.0592331
|
| 443 |
+
internal_weight=12.1887 6.26059 5.36137 5.92807 4.77201 3.68111
|
| 444 |
+
internal_count=86 42 36 44 36 28
|
| 445 |
+
is_linear=0
|
| 446 |
+
shrinkage=0.05
|
| 447 |
+
|
| 448 |
+
|
| 449 |
+
Tree=23
|
| 450 |
+
num_leaves=7
|
| 451 |
+
num_cat=0
|
| 452 |
+
split_feature=2 9 7 3 6 11
|
| 453 |
+
split_gain=15.4748 0.409392 0.0152171 0.00084384 0.000832987 0.000542181
|
| 454 |
+
threshold=1.0000000180025095e-35 0.075080247396852748 2936.421364560174 0.68333333333333346 50443.000000000007 141.79473379629633
|
| 455 |
+
decision_type=2 2 2 2 2 2
|
| 456 |
+
left_child=1 -1 -2 4 -3 -5
|
| 457 |
+
right_child=2 3 -4 5 -6 -7
|
| 458 |
+
leaf_value=0.022590831551048782 -0.060005776826580329 0.06106710650507513 -0.068132524420055657 0.060068144672354024 0.058892339480384651 0.058505384784072391
|
| 459 |
+
leaf_weight=0.88774001598358143 4.8577902466058731 1.0309564769268034 0.65351083874702443 0.68879798054695163 0.76853059977293003 2.8573894053697586
|
| 460 |
+
leaf_count=6 35 7 4 5 6 23
|
| 461 |
+
internal_value=6.80767e-05 0.0540346 -0.0609694 0.0592564 0.0601383 0.0588089
|
| 462 |
+
internal_weight=11.7447 6.23341 5.5113 5.34567 1.79949 3.54619
|
| 463 |
+
internal_count=86 47 39 41 13 28
|
| 464 |
+
is_linear=0
|
| 465 |
+
shrinkage=0.05
|
| 466 |
+
|
| 467 |
+
|
| 468 |
+
Tree=24
|
| 469 |
+
num_leaves=7
|
| 470 |
+
num_cat=0
|
| 471 |
+
split_feature=7 9 12 6 9 9
|
| 472 |
+
split_gain=14.5655 0.541723 0.0216997 0.000501072 9.78822e-05 0.000128185
|
| 473 |
+
threshold=3449.4166666666674 0.071839745922519613 0.050737547542749055 40049.000000000007 0.075080247396852748 0.21825396825396828
|
| 474 |
+
decision_type=2 2 2 2 2 2
|
| 475 |
+
left_child=1 2 -1 -2 -5 -6
|
| 476 |
+
right_child=3 -3 -4 4 5 -7
|
| 477 |
+
leaf_value=-0.067024921199474077 0.059588834455201412 -0.018346171426203251 -0.05938954185150102 0.058951152261286548 0.058107946346887443 0.058767401643471141
|
| 478 |
+
leaf_weight=1.2402108311653135 1.0672495663166044 0.86150559782981861 3.726663663983345 0.64380145072937001 2.760124303400517 1.0052870362997053
|
| 479 |
+
leaf_count=8 8 6 28 5 23 8
|
| 480 |
+
internal_value=6.69666e-05 -0.0549476 -0.0612961 0.0586167 0.0583814 0.058284
|
| 481 |
+
internal_weight=11.3048 5.82838 4.96687 5.47646 4.40921 3.76541
|
| 482 |
+
internal_count=86 42 36 44 36 31
|
| 483 |
+
is_linear=0
|
| 484 |
+
shrinkage=0.05
|
| 485 |
+
|
| 486 |
+
|
| 487 |
+
Tree=25
|
| 488 |
+
num_leaves=7
|
| 489 |
+
num_cat=0
|
| 490 |
+
split_feature=7 8 5 3 6 11
|
| 491 |
+
split_gain=13.7558 0.413425 0.00826678 0.000784093 0.00100285 0.000358132
|
| 492 |
+
threshold=3112.1875000000005 0.40833333333333338 5.5000000000000009 0.68333333333333346 50443.000000000007 141.79473379629633
|
| 493 |
+
decision_type=2 2 2 2 2 2
|
| 494 |
+
left_child=2 3 -1 4 -2 -5
|
| 495 |
+
right_child=1 -3 -4 5 -6 -7
|
| 496 |
+
leaf_value=-0.064760998748160811 0.060411037092192879 0.020204062489322272 -0.058976871071604077 0.058942640863666663 0.057967853146372289 0.057620131955101794
|
| 497 |
+
leaf_weight=0.71913889795541752 0.85121817886829354 0.83034586906433094 4.3807578086853027 0.63516688346862826 0.82912010699510574 2.6377299129962921
|
| 498 |
+
leaf_count=5 6 6 34 5 7 23
|
| 499 |
+
internal_value=6.89911e-05 0.0528542 -0.0597925 0.0583275 0.0592055 0.0578768
|
| 500 |
+
internal_weight=10.8835 5.78358 5.0999 4.95324 1.68034 3.2729
|
| 501 |
+
internal_count=86 47 39 41 13 28
|
| 502 |
+
is_linear=0
|
| 503 |
+
shrinkage=0.05
|
| 504 |
+
|
| 505 |
+
|
| 506 |
+
Tree=26
|
| 507 |
+
num_leaves=7
|
| 508 |
+
num_cat=0
|
| 509 |
+
split_feature=2 12 7 6 9 3
|
| 510 |
+
split_gain=13.0195 0.386766 0.0129472 0.000663642 0.000231849 0.000100648
|
| 511 |
+
threshold=1.0000000180025095e-35 0.058858058382239557 2936.421364560174 42986.000000000007 0.071279139270771077 0.68333333333333346
|
| 512 |
+
decision_type=2 2 2 2 2 2
|
| 513 |
+
left_child=1 -1 4 -3 -2 -5
|
| 514 |
+
right_child=2 3 -4 5 -6 -7
|
| 515 |
+
leaf_value=0.020559904055127788 -0.058251627610288348 0.059187580586970483 -0.066266872347715874 0.05797390785239085 -0.059270945587050296 0.057422964387858488
|
| 516 |
+
leaf_weight=0.81472939252853382 3.645292304456234 0.7722501829266547 0.59667611867189396 1.1771411001682284 0.65865901857614506 2.8025532513856888
|
| 517 |
+
leaf_count=6 30 6 4 10 5 25
|
| 518 |
+
internal_value=6.77682e-05 0.0523891 -0.0593645 0.0578462 -0.0584076 0.0575859
|
| 519 |
+
internal_weight=10.4673 5.56667 4.90063 4.75194 4.30395 3.97969
|
| 520 |
+
internal_count=86 47 39 41 35 35
|
| 521 |
+
is_linear=0
|
| 522 |
+
shrinkage=0.05
|
| 523 |
+
|
| 524 |
+
|
| 525 |
+
Tree=27
|
| 526 |
+
num_leaves=7
|
| 527 |
+
num_cat=0
|
| 528 |
+
split_feature=7 9 12 6 9 9
|
| 529 |
+
split_gain=12.2925 0.489163 0.0188603 0.000383646 8.37721e-05 6.84616e-05
|
| 530 |
+
threshold=3449.4166666666674 0.071839745922519613 0.050737547542749055 40049.000000000007 0.075080247396852748 0.21825396825396828
|
| 531 |
+
decision_type=2 2 2 2 2 2
|
| 532 |
+
left_child=1 2 -1 -2 -5 -6
|
| 533 |
+
right_child=3 -3 -4 4 5 -7
|
| 534 |
+
leaf_value=-0.065351573347258926 0.058201978148554413 -0.017119792068844602 -0.057861048104718864 0.057642731793756244 0.056851957818626599 0.057365219746097679
|
| 535 |
+
leaf_weight=1.1290041878819463 0.95821357518434513 0.79274052381515492 3.2869395241141319 0.57451695203781161 2.436129823327065 0.88597673177719105
|
| 536 |
+
leaf_count=8 8 6 28 5 23 8
|
| 537 |
+
internal_value=6.65903e-05 -0.053284 -0.0597761 0.0573057 0.0570852 0.0569888
|
| 538 |
+
internal_weight=10.0635 5.20868 4.41594 4.85484 3.89662 3.32211
|
| 539 |
+
internal_count=86 42 36 44 36 31
|
| 540 |
+
is_linear=0
|
| 541 |
+
shrinkage=0.05
|
| 542 |
+
|
| 543 |
+
|
| 544 |
+
Tree=28
|
| 545 |
+
num_leaves=7
|
| 546 |
+
num_cat=0
|
| 547 |
+
split_feature=7 1 5 11 9 7
|
| 548 |
+
split_gain=11.6086 0.397906 0.00725715 0.000617763 0.0002746 0.000130696
|
| 549 |
+
threshold=3112.1875000000005 2.5000000000000004 5.5000000000000009 141.79473379629633 0.071279139270771077 3723.3125000000005
|
| 550 |
+
decision_type=2 2 2 2 2 2
|
| 551 |
+
left_child=2 -2 -1 -3 -4 -5
|
| 552 |
+
right_child=1 3 4 5 -6 -7
|
| 553 |
+
leaf_value=-0.063287458024544704 0.016795342489476839 0.058297174904840682 -0.057390464271318914 0.05712056058143096 -0.058537814624013043 0.056485396566092597
|
| 554 |
+
leaf_weight=0.64899222552776326 0.71674503386020649 0.71003039181232441 3.2527691423892979 1.1892860233783724 0.62106423079967488 2.538827121257782
|
| 555 |
+
leaf_count=5 5 6 29 11 5 25
|
| 556 |
+
internal_value=6.85434e-05 0.0513629 -0.0583942 0.0569455 -0.0575744 0.056688
|
| 557 |
+
internal_weight=9.67771 5.15489 4.52283 4.43814 3.87383 3.72811
|
| 558 |
+
internal_count=86 47 39 42 34 36
|
| 559 |
+
is_linear=0
|
| 560 |
+
shrinkage=0.05
|
| 561 |
+
|
| 562 |
+
|
| 563 |
+
Tree=29
|
| 564 |
+
num_leaves=7
|
| 565 |
+
num_cat=0
|
| 566 |
+
split_feature=2 9 7 3 6 9
|
| 567 |
+
split_gain=11.0019 0.370817 0.01088 0.000682509 0.000701566 0.000256016
|
| 568 |
+
threshold=1.0000000180025095e-35 0.075080247396852748 2936.421364560174 0.68333333333333346 50443.000000000007 0.071279139270771077
|
| 569 |
+
decision_type=2 2 2 2 2 2
|
| 570 |
+
left_child=1 -1 5 4 -3 -2
|
| 571 |
+
right_child=2 3 -4 -5 -6 -7
|
| 572 |
+
leaf_value=0.018486343351054913 -0.056923856725493785 0.058520334769237597 -0.064665982612492262 0.05626769846211898 0.056286448244358883 -0.058052796916793395
|
| 573 |
+
leaf_weight=0.74618197977542866 3.2023785859346394 0.85925551503896691 0.54325389117002476 2.7559519186615944 0.59474007040262222 0.59558508545160282
|
| 574 |
+
leaf_count=6 30 7 4 28 6 5
|
| 575 |
+
internal_value=6.75255e-05 0.0509722 -0.0580476 0.0567301 0.0576066 -0.0571009
|
| 576 |
+
internal_weight=9.29735 4.95613 4.34122 4.20995 1.454 3.79796
|
| 577 |
+
internal_count=86 47 39 41 13 35
|
| 578 |
+
is_linear=0
|
| 579 |
+
shrinkage=0.05
|
| 580 |
+
|
| 581 |
+
|
| 582 |
+
Tree=30
|
| 583 |
+
num_leaves=7
|
| 584 |
+
num_cat=0
|
| 585 |
+
split_feature=7 9 12 6 9 9
|
| 586 |
+
split_gain=10.4161 0.44449 0.01614 0.000279951 0.000107893 5.28035e-05
|
| 587 |
+
threshold=3449.4166666666674 0.071839745922519613 0.050737547542749055 40049.000000000007 0.075080247396852748 0.21825396825396828
|
| 588 |
+
decision_type=2 2 2 2 2 2
|
| 589 |
+
left_child=1 2 -1 -2 -5 -6
|
| 590 |
+
right_child=3 -3 -4 4 5 -7
|
| 591 |
+
leaf_value=-0.063912827952955498 0.057039225047386011 -0.015972305675681888 -0.056610658318094302 0.056691086786257221 0.055780573066398942 0.056260987745907258
|
| 592 |
+
leaf_weight=1.0254787206649782 0.85380606353282917 0.72786590456962574 2.8874571472406387 0.51999834924936328 2.134867444634438 0.78128480911254872
|
| 593 |
+
leaf_count=8 8 6 28 5 23 8
|
| 594 |
+
internal_value=6.62766e-05 -0.0518505 -0.0585244 0.0562289 0.0560276 0.0559093
|
| 595 |
+
internal_weight=8.93076 4.6408 3.91294 4.28996 3.43615 2.91615
|
| 596 |
+
internal_count=86 42 36 44 36 31
|
| 597 |
+
is_linear=0
|
| 598 |
+
shrinkage=0.05
|
| 599 |
+
|
| 600 |
+
|
| 601 |
+
Tree=31
|
| 602 |
+
num_leaves=7
|
| 603 |
+
num_cat=0
|
| 604 |
+
split_feature=7 1 5 7 9 11
|
| 605 |
+
split_gain=9.83589 0.374511 0.00629963 0.000526358 0.000278143 9.52215e-05
|
| 606 |
+
threshold=3112.1875000000005 2.5000000000000004 5.5000000000000009 3640.0756302521013 0.071279139270771077 141.79473379629633
|
| 607 |
+
decision_type=2 2 2 2 2 2
|
| 608 |
+
left_child=2 -2 -1 -3 -4 -5
|
| 609 |
+
right_child=1 3 4 5 -6 -7
|
| 610 |
+
leaf_value=-0.062038035970580635 0.015312301405758769 0.057267395266565102 -0.0562204121958855 0.056335163777748776 -0.057438264315309052 0.055580914687308039
|
| 611 |
+
leaf_weight=0.58454194664955172 0.66288314014673222 0.63404047489166293 2.852705761790276 0.49217656999826465 0.56103963404893864 2.7935361713171005
|
| 612 |
+
leaf_count=5 5 6 29 5 5 31
|
| 613 |
+
internal_value=6.81728e-05 0.0500704 -0.0572418 0.0559484 -0.0564206 0.0556939
|
| 614 |
+
internal_weight=8.58092 4.58264 3.99829 3.91975 3.41375 3.28571
|
| 615 |
+
internal_count=86 47 39 42 34 36
|
| 616 |
+
is_linear=0
|
| 617 |
+
shrinkage=0.05
|
| 618 |
+
|
| 619 |
+
|
| 620 |
+
Tree=32
|
| 621 |
+
num_leaves=7
|
| 622 |
+
num_cat=0
|
| 623 |
+
split_feature=2 11 7 3 6 9
|
| 624 |
+
split_gain=9.33088 0.349815 0.00907291 0.000354295 0.000385433 0.000256073
|
| 625 |
+
threshold=1.0000000180025095e-35 133.51370949074075 2936.421364560174 0.68333333333333346 50443.000000000007 0.071279139270771077
|
| 626 |
+
decision_type=2 2 2 2 2 2
|
| 627 |
+
left_child=1 -1 5 4 -3 -2
|
| 628 |
+
right_child=2 3 -4 -5 -6 -7
|
| 629 |
+
leaf_value=0.015926168801723522 -0.055832119263564496 0.05713410010864043 -0.063286192030390473 0.055256561966569744 0.055386332730094849 -0.057023546364382338
|
| 630 |
+
leaf_weight=0.65211432427167881 2.8032477051019677 0.64919306337833427 0.49360075592994679 2.4881960600614548 0.61358394473791122 0.5374602898955344
|
| 631 |
+
leaf_count=5 30 6 4 29 7 5
|
| 632 |
+
internal_value=6.71091e-05 0.0497265 -0.0569587 0.0556027 0.0562849 -0.0560238
|
| 633 |
+
internal_weight=8.2374 4.40309 3.83431 3.75097 1.26278 3.34071
|
| 634 |
+
internal_count=86 47 39 42 13 35
|
| 635 |
+
is_linear=0
|
| 636 |
+
shrinkage=0.05
|
| 637 |
+
|
| 638 |
+
|
| 639 |
+
Tree=33
|
| 640 |
+
num_leaves=7
|
| 641 |
+
num_cat=0
|
| 642 |
+
split_feature=7 7 12 6 9 9
|
| 643 |
+
split_gain=8.83465 0.495924 0.00632183 0.000252359 0.000200043 6.18914e-05
|
| 644 |
+
threshold=3449.4166666666674 3112.1875000000005 0.046585109941867327 40049.000000000007 0.071279139270771077 0.075080247396852748
|
| 645 |
+
decision_type=2 2 2 2 2 2
|
| 646 |
+
left_child=1 2 -1 -2 -4 -5
|
| 647 |
+
right_child=3 -3 4 5 -6 -7
|
| 648 |
+
leaf_value=-0.061556231231573035 0.056137224344672776 -0.001381895729157019 -0.055556071395645848 0.055656976219855096 -0.056634677162818239 0.055024700516101088
|
| 649 |
+
leaf_weight=0.54798562079668078 0.76531849801540408 0.45721171796321858 2.6089930459856991 0.45611468702554736 0.51466943323612202 2.5557717457413673
|
| 650 |
+
leaf_count=5 8 3 29 5 5 31
|
| 651 |
+
internal_value=6.60386e-05 -0.0504879 -0.0566028 0.0553265 -0.0557338 0.0551205
|
| 652 |
+
internal_weight=7.90606 4.12886 3.67165 3.7772 3.12366 3.01189
|
| 653 |
+
internal_count=86 42 39 44 34 36
|
| 654 |
+
is_linear=0
|
| 655 |
+
shrinkage=0.05
|
| 656 |
+
|
| 657 |
+
|
| 658 |
+
Tree=34
|
| 659 |
+
num_leaves=7
|
| 660 |
+
num_cat=0
|
| 661 |
+
split_feature=2 9 7 7 9 0
|
| 662 |
+
split_gain=8.35001 0.351499 0.00832904 0.000696102 0.000184189 0.000182014
|
| 663 |
+
threshold=1.0000000180025095e-35 0.075080247396852748 2936.421364560174 3478.8119047619052 0.071279139270771077 3.5000000000000004
|
| 664 |
+
decision_type=2 2 2 2 2 2
|
| 665 |
+
left_child=1 -1 4 -3 -2 -5
|
| 666 |
+
right_child=2 3 -4 5 -6 -7
|
| 667 |
+
leaf_value=0.014947449539177768 -0.055214120163731763 0.056963217459914332 -0.062580926893981162 0.055517369242061111 -0.056269756118548744 0.054678016325414684
|
| 668 |
+
leaf_weight=0.64245630055665959 2.5623199343681344 0.5072332322597507 0.46298509091138829 0.96613904088735614 0.49266319721937168 1.9485112279653547
|
| 669 |
+
leaf_count=6 30 5 4 11 5 25
|
| 670 |
+
internal_value=6.62901e-05 0.0488825 -0.0563315 0.0552537 -0.0553844 0.0549562
|
| 671 |
+
internal_weight=7.58231 4.06434 3.51797 3.42188 3.05498 2.91465
|
| 672 |
+
internal_count=86 47 39 41 35 36
|
| 673 |
+
is_linear=0
|
| 674 |
+
shrinkage=0.05
|
| 675 |
+
|
| 676 |
+
|
| 677 |
+
Tree=35
|
| 678 |
+
num_leaves=7
|
| 679 |
+
num_cat=0
|
| 680 |
+
split_feature=7 7 5 6 9 9
|
| 681 |
+
split_gain=7.928 0.465997 0.00627062 0.000168309 0.000144454 8.61189e-05
|
| 682 |
+
threshold=3449.4166666666674 3112.1875000000005 5.5000000000000009 40049.000000000007 0.071279139270771077 0.075080247396852748
|
| 683 |
+
decision_type=2 2 2 2 2 2
|
| 684 |
+
left_child=1 2 -1 -2 -4 -5
|
| 685 |
+
right_child=3 -3 4 5 -6 -7
|
| 686 |
+
leaf_value=-0.06112951982230596 0.055489765832188481 -0.0014456136893101455 -0.054969160357358007 0.055271421843250457 -0.05592704783840783 0.054502127112148469
|
| 687 |
+
leaf_weight=0.51339258998632509 0.70041552931070361 0.44213592261075962 2.3835200518369679 0.43097247928380999 0.47143466770648945 2.3337739482522011
|
| 688 |
+
leaf_count=5 8 3 29 5 5 31
|
| 689 |
+
internal_value=6.50601e-05 -0.0497073 -0.0560422 0.0547974 -0.0551273 0.054622
|
| 690 |
+
internal_weight=7.27565 3.81048 3.36835 3.46516 2.85495 2.76475
|
| 691 |
+
internal_count=86 42 39 44 34 36
|
| 692 |
+
is_linear=0
|
| 693 |
+
shrinkage=0.05
|
| 694 |
+
|
| 695 |
+
|
| 696 |
+
Tree=36
|
| 697 |
+
num_leaves=7
|
| 698 |
+
num_cat=0
|
| 699 |
+
split_feature=7 4 7 9 6 9
|
| 700 |
+
split_gain=7.48285 0.470136 0.0076194 0.000162971 0.000142931 7.29879e-05
|
| 701 |
+
threshold=3449.4166666666674 1.0000000180025095e-35 2936.421364560174 0.071839745922519613 40049.000000000007 0.075080247396852748
|
| 702 |
+
decision_type=2 2 2 2 2 2
|
| 703 |
+
left_child=1 2 3 -1 -2 -6
|
| 704 |
+
right_child=4 -3 -4 -5 5 -7
|
| 705 |
+
leaf_value=-0.054668841074267054 0.055194448155474175 -0.0006523767316843794 -0.061938902913771236 -0.055792750812624518 0.054988023932388025 0.054263649587207231
|
| 706 |
+
leaf_weight=2.4181659296154989 0.66973040252923999 0.43949657678604115 0.43420322984457005 0.37218537181615818 0.41201303899288211 2.2294638529419899
|
| 707 |
+
leaf_count=31 8 3 4 4 5 31
|
| 708 |
+
internal_value=6.53258e-05 -0.0491654 -0.0557775 -0.0548188 0.054542 0.0543766
|
| 709 |
+
internal_weight=6.97526 3.66405 3.22455 2.79035 3.31121 2.64148
|
| 710 |
+
internal_count=86 42 39 35 44 36
|
| 711 |
+
is_linear=0
|
| 712 |
+
shrinkage=0.05
|
| 713 |
+
|
| 714 |
+
|
| 715 |
+
Tree=37
|
| 716 |
+
num_leaves=7
|
| 717 |
+
num_cat=0
|
| 718 |
+
split_feature=7 8 3 7 0 9
|
| 719 |
+
split_gain=7.08513 0.625026 0.00940651 0.000726114 8.40313e-05 6.44824e-05
|
| 720 |
+
threshold=3112.1875000000005 0.48529411764705888 0.00030309239974547856 3478.8119047619052 3.5000000000000004 0.069618762407887225
|
| 721 |
+
decision_type=2 2 2 2 2 2
|
| 722 |
+
left_child=2 3 5 -2 -5 -1
|
| 723 |
+
right_child=1 -3 -4 4 -6 -7
|
| 724 |
+
leaf_value=-0.054395364925094974 0.05639705795332367 -0.01565991629893191 -0.063037368840106148 0.054678313320029787 0.054080703010607023 -0.055026815765338855
|
| 725 |
+
leaf_weight=2.2251070216298112 0.46460698544979173 0.3510647416114806 0.36706323921680439 0.84411208331584964 1.9404393583536146 0.49407067149877537
|
| 726 |
+
leaf_count=30 5 3 3 11 28 6
|
| 727 |
+
internal_value=6.55694e-05 0.0477192 -0.0555243 0.0545672 0.0542619 -0.0545101
|
| 728 |
+
internal_weight=6.68646 3.60022 3.08624 3.24916 2.78455 2.71918
|
| 729 |
+
internal_count=86 47 39 44 39 36
|
| 730 |
+
is_linear=0
|
| 731 |
+
shrinkage=0.05
|
| 732 |
+
|
| 733 |
+
|
| 734 |
+
Tree=38
|
| 735 |
+
num_leaves=7
|
| 736 |
+
num_cat=0
|
| 737 |
+
split_feature=7 1 8 9 6 9
|
| 738 |
+
split_gain=6.71073 0.44171 0.00833921 0.000117938 9.75054e-05 6.51949e-05
|
| 739 |
+
threshold=3449.4166666666674 2.5000000000000004 0.48529411764705888 0.071839745922519613 40049.000000000007 0.075080247396852748
|
| 740 |
+
decision_type=2 2 2 2 2 2
|
| 741 |
+
left_child=1 2 3 -1 -2 -6
|
| 742 |
+
right_child=4 -3 -4 -5 5 -7
|
| 743 |
+
leaf_value=-0.054176317691610465 0.054654224266567131 -0.00070694118547682931 -0.062643158321476405 -0.055174794917573503 0.05454790994267375 0.05383536400562642
|
| 744 |
+
leaf_weight=2.2735335305333151 0.61183255910873446 0.42434006929397572 0.33883924037218083 0.33996777236461628 0.38107533752918277 2.0368824377655983
|
| 745 |
+
leaf_count=32 8 3 3 4 5 31
|
| 746 |
+
internal_value=6.66723e-05 -0.0484071 -0.055263 -0.0543062 0.0540903 0.0539477
|
| 747 |
+
internal_weight=6.40647 3.37668 2.95234 2.6135 3.02979 2.41796
|
| 748 |
+
internal_count=86 42 39 36 44 36
|
| 749 |
+
is_linear=0
|
| 750 |
+
shrinkage=0.05
|
| 751 |
+
|
| 752 |
+
|
| 753 |
+
Tree=39
|
| 754 |
+
num_leaves=7
|
| 755 |
+
num_cat=0
|
| 756 |
+
split_feature=7 8 3 7 0 9
|
| 757 |
+
split_gain=6.36573 0.578683 0.00839249 0.000692171 6.10424e-05 4.69022e-05
|
| 758 |
+
threshold=3112.1875000000005 0.48529411764705888 0.00030309239974547856 3478.8119047619052 3.5000000000000004 0.069618762407887225
|
| 759 |
+
decision_type=2 2 2 2 2 2
|
| 760 |
+
left_child=2 3 5 -2 -5 -1
|
| 761 |
+
right_child=1 -3 -4 4 -6 -7
|
| 762 |
+
leaf_value=-0.053941094211068685 0.055983462634242864 -0.014797020999098879 -0.062355730228598985 0.054196430034086966 0.053663191066265548 -0.054504693631837665
|
| 763 |
+
leaf_weight=2.0288115218281755 0.43503814563155252 0.33912311494350422 0.34604882448911656 0.77044664323329959 1.7689581885933874 0.45124471187591542
|
| 764 |
+
leaf_count=30 5 3 3 11 28 6
|
| 765 |
+
internal_value=6.69309e-05 0.0470853 -0.0550614 0.0541407 0.053825 -0.0540436
|
| 766 |
+
internal_weight=6.13967 3.31357 2.82611 2.97444 2.5394 2.48006
|
| 767 |
+
internal_count=86 47 39 44 39 36
|
| 768 |
+
is_linear=0
|
| 769 |
+
shrinkage=0.05
|
| 770 |
+
|
| 771 |
+
|
| 772 |
+
Tree=40
|
| 773 |
+
num_leaves=7
|
| 774 |
+
num_cat=0
|
| 775 |
+
split_feature=7 1 8 9 6 9
|
| 776 |
+
split_gain=6.0239 0.415509 0.00716593 8.37942e-05 6.58231e-05 5.87717e-05
|
| 777 |
+
threshold=3449.4166666666674 2.5000000000000004 0.48529411764705888 0.071839745922519613 40049.000000000007 0.075080247396852748
|
| 778 |
+
decision_type=2 2 2 2 2 2
|
| 779 |
+
left_child=1 2 3 -1 -2 -6
|
| 780 |
+
right_child=4 -3 -4 -5 5 -7
|
| 781 |
+
leaf_value=-0.053747198866373358 0.054174246102799986 -0.00074871437985491265 -0.061848534735531473 -0.054628365896544698 0.054158817872469428 0.053454524957827709
|
| 782 |
+
leaf_weight=2.0726009085774435 0.55836819112300906 0.40939591825008381 0.31838491559028614 0.31017342954874028 0.3523313328623775 1.8596719168126581
|
| 783 |
+
leaf_count=32 8 3 3 4 5 31
|
| 784 |
+
internal_value=6.80133e-05 -0.0476889 -0.0548033 -0.0538619 0.0536892 0.0535667
|
| 785 |
+
internal_weight=5.88093 3.11056 2.70116 2.38277 2.77037 2.212
|
| 786 |
+
internal_count=86 42 39 36 44 36
|
| 787 |
+
is_linear=0
|
| 788 |
+
shrinkage=0.05
|
| 789 |
+
|
| 790 |
+
|
| 791 |
+
Tree=41
|
| 792 |
+
num_leaves=7
|
| 793 |
+
num_cat=0
|
| 794 |
+
split_feature=7 8 3 7 0 9
|
| 795 |
+
split_gain=5.7252 0.536242 0.00747846 0.000655393 4.44475e-05 3.41942e-05
|
| 796 |
+
threshold=3112.1875000000005 0.48529411764705888 0.00030309239974547856 3478.8119047619052 3.5000000000000004 0.069618762407887225
|
| 797 |
+
decision_type=2 2 2 2 2 2
|
| 798 |
+
left_child=2 3 5 -2 -5 -1
|
| 799 |
+
right_child=1 -3 -4 4 -6 -7
|
| 800 |
+
leaf_value=-0.053537010646773124 0.055610610534127497 -0.013985263998826523 -0.061727170553975308 0.053767553137312941 0.053290985516214889 -0.054040869042317564
|
| 801 |
+
leaf_weight=1.8483116999268538 0.40735856071114618 0.32721980661153782 0.32622210681438435 0.70258275792002711 1.6113706566393373 0.41173452883958805
|
| 802 |
+
leaf_count=30 5 3 3 11 28 6
|
| 803 |
+
internal_value=6.82449e-05 0.0464896 -0.0546503 0.0537613 0.0534357 -0.0536288
|
| 804 |
+
internal_weight=5.6348 3.04853 2.58627 2.72131 2.31395 2.26005
|
| 805 |
+
internal_count=86 47 39 44 39 36
|
| 806 |
+
is_linear=0
|
| 807 |
+
shrinkage=0.05
|
| 808 |
+
|
| 809 |
+
|
| 810 |
+
Tree=42
|
| 811 |
+
num_leaves=7
|
| 812 |
+
num_cat=0
|
| 813 |
+
split_feature=7 7 3 6 9 9
|
| 814 |
+
split_gain=5.41202 0.394171 0.00641111 4.38394e-05 5.48303e-05 2.91248e-05
|
| 815 |
+
threshold=3449.4166666666674 3112.1875000000005 0.00030309239974547856 40049.000000000007 0.087121212121212141 0.069618762407887225
|
| 816 |
+
decision_type=2 2 2 2 2 2
|
| 817 |
+
left_child=1 2 5 -2 -5 -1
|
| 818 |
+
right_child=3 -3 -4 4 -6 -7
|
| 819 |
+
leaf_value=-0.053352663712986942 0.053747012822722956 -0.0005433541913502332 -0.06109198312579267 0.053718204717861685 0.053089683982466357 -0.053828554208506289
|
| 820 |
+
leaf_weight=1.7640897743403923 0.50911201909184489 0.3937300145626067 0.31345656886696804 0.44482421502471003 1.5777324028313158 0.39315973222255696
|
| 821 |
+
leaf_count=30 8 3 3 7 29 6
|
| 822 |
+
internal_value=6.93086e-05 -0.047006 -0.0544103 0.0533323 0.0532279 -0.0534394
|
| 823 |
+
internal_weight=5.3961 2.86444 2.47071 2.53167 2.02256 2.15725
|
| 824 |
+
internal_count=86 42 39 44 36 36
|
| 825 |
+
is_linear=0
|
| 826 |
+
shrinkage=0.05
|
| 827 |
+
|
| 828 |
+
|
| 829 |
+
Tree=43
|
| 830 |
+
num_leaves=7
|
| 831 |
+
num_cat=0
|
| 832 |
+
split_feature=2 9 8 7 9 1
|
| 833 |
+
split_gain=5.14676 0.416517 0.00643507 0.000615443 5.01119e-05 3.57671e-05
|
| 834 |
+
threshold=1.0000000180025095e-35 0.071279139270771077 0.48529411764705888 3478.8119047619052 0.071839745922519613 5.0000000000000009
|
| 835 |
+
decision_type=2 2 2 2 2 2
|
| 836 |
+
left_child=1 -1 4 -3 -2 -5
|
| 837 |
+
right_child=2 3 -4 5 -6 -7
|
| 838 |
+
leaf_value=-0.0032927725542232326 -0.053189321076280861 0.05527217636602412 -0.061192203606070542 0.053330110339481311 -0.053920202121437104 0.052907016543222808
|
| 839 |
+
leaf_weight=0.37335796654224429 1.8011869229376323 0.38144064322114024 0.29376778006553639 0.86185404658317599 0.26963154226541508 1.1881534345448015
|
| 840 |
+
leaf_count=4 32 5 3 15 4 23
|
| 841 |
+
internal_value=6.95056e-05 0.0458777 -0.0542669 0.053428 -0.0532845 0.0530849
|
| 842 |
+
internal_weight=5.16939 2.80481 2.36459 2.43145 2.07082 2.05001
|
| 843 |
+
internal_count=86 47 39 43 36 38
|
| 844 |
+
is_linear=0
|
| 845 |
+
shrinkage=0.05
|
| 846 |
+
|
| 847 |
+
|
| 848 |
+
Tree=44
|
| 849 |
+
num_leaves=7
|
| 850 |
+
num_cat=0
|
| 851 |
+
split_feature=7 9 12 9 0 4
|
| 852 |
+
split_gain=4.87065 0.373455 0.00759387 4.27489e-05 4.57402e-05 4.94146e-05
|
| 853 |
+
threshold=3449.4166666666674 0.071839745922519613 0.050737547542749055 0.075080247396852748 3.5000000000000004 1.0000000180025095e-35
|
| 854 |
+
decision_type=2 2 2 2 2 2
|
| 855 |
+
left_child=1 2 -1 -2 5 -5
|
| 856 |
+
right_child=3 -3 -4 4 -6 -7
|
| 857 |
+
leaf_value=-0.059481924618931842 0.05356627448655691 -0.0053640516220252593 -0.053057415019858271 0.052859926767791471 0.052761884723875802 0.053715583084513518
|
| 858 |
+
leaf_weight=0.65957568958401758 0.3061713203787807 0.45867507904767979 1.5198521241545675 0.35486402362585101 1.3312645144760606 0.32168889418244362
|
| 859 |
+
leaf_count=8 5 6 28 7 27 5
|
| 860 |
+
internal_value=6.98011e-05 -0.0463714 -0.0550017 0.0530159 0.052932 0.0532668
|
| 861 |
+
internal_weight=4.95209 2.6381 2.17943 2.31399 2.00782 0.676553
|
| 862 |
+
internal_count=86 42 36 44 39 12
|
| 863 |
+
is_linear=0
|
| 864 |
+
shrinkage=0.05
|
| 865 |
+
|
| 866 |
+
|
| 867 |
+
Tree=45
|
| 868 |
+
num_leaves=7
|
| 869 |
+
num_cat=0
|
| 870 |
+
split_feature=7 8 3 7 9 0
|
| 871 |
+
split_gain=4.63736 0.476236 0.00485685 0.000582061 2.96056e-05 2.16139e-05
|
| 872 |
+
threshold=3112.1875000000005 0.48529411764705888 0.00030309239974547856 3478.8119047619052 0.069618762407887225 3.5000000000000004
|
| 873 |
+
decision_type=2 2 2 2 2 2
|
| 874 |
+
left_child=2 3 4 -2 -1 -5
|
| 875 |
+
right_child=1 -3 -4 5 -6 -7
|
| 876 |
+
leaf_value=-0.052853755533095376 0.054985344829039356 -0.013782752907821267 -0.059935001183145403 0.053043608220952276 -0.053363596419050252 0.05267888921088263
|
| 877 |
+
leaf_weight=1.5297555290162566 0.35795415192842561 0.30096763372421254 0.28671444952487934 0.58293151110410679 0.34985763952136029 1.3399863652884958
|
| 878 |
+
leaf_count=30 5 3 3 11 6 28
|
| 879 |
+
internal_value=7.08982e-05 0.0453335 -0.0538733 0.0531341 -0.0529487 0.0527895
|
| 880 |
+
internal_weight=4.74817 2.58184 2.16633 2.28087 1.87961 1.92292
|
| 881 |
+
internal_count=86 47 39 44 36 39
|
| 882 |
+
is_linear=0
|
| 883 |
+
shrinkage=0.05
|
| 884 |
+
|
| 885 |
+
|
| 886 |
+
Tree=46
|
| 887 |
+
num_leaves=7
|
| 888 |
+
num_cat=0
|
| 889 |
+
split_feature=2 9 8 7 9 4
|
| 890 |
+
split_gain=4.40922 0.447484 0.00471205 0.000496091 5.14602e-05 2.4916e-05
|
| 891 |
+
threshold=1.0000000180025095e-35 0.065591397849462371 0.48529411764705888 3478.8119047619052 0.071839745922519613 1.0000000180025095e-35
|
| 892 |
+
decision_type=2 2 2 2 2 2
|
| 893 |
+
left_child=1 -1 4 -3 -2 -5
|
| 894 |
+
right_child=2 3 -4 5 -6 -7
|
| 895 |
+
leaf_value=-0.012584332341268274 -0.05271689598511281 0.054724538458758742 -0.059953959409466628 0.052504546177679447 -0.053497216445920016 0.0528828969447558
|
| 896 |
+
leaf_weight=0.29559918865561519 1.5617414489388468 0.34207821637392077 0.26570267975330342 1.1270508877933023 0.24433936551213253 0.70879586413502682
|
| 897 |
+
leaf_count=3 32 5 3 25 4 14
|
| 898 |
+
internal_value=7.19562e-05 0.0451415 -0.0537371 0.0529764 -0.0528225 0.0526506
|
| 899 |
+
internal_weight=4.54531 2.47352 2.07178 2.17792 1.80608 1.83585
|
| 900 |
+
internal_count=86 47 39 44 36 39
|
| 901 |
+
is_linear=0
|
| 902 |
+
shrinkage=0.05
|
| 903 |
+
|
| 904 |
+
|
| 905 |
+
Tree=47
|
| 906 |
+
num_leaves=7
|
| 907 |
+
num_cat=0
|
| 908 |
+
split_feature=7 8 3 7 9 6
|
| 909 |
+
split_gain=4.17468 0.43328 0.00415466 0.00042322 2.16753e-05 1.48204e-05
|
| 910 |
+
threshold=3112.1875000000005 0.48529411764705888 0.00030309239974547856 3478.8119047619052 0.069618762407887225 40049.000000000007
|
| 911 |
+
decision_type=2 2 2 2 2 2
|
| 912 |
+
left_child=2 3 4 -2 -1 -5
|
| 913 |
+
right_child=1 -3 -4 5 -6 -7
|
| 914 |
+
leaf_value=-0.052566765251834173 0.054478261217956375 -0.012068978077755697 -0.059337625153044499 0.052811538560065069 -0.053024003134294333 0.052446238174248261
|
| 915 |
+
leaf_weight=1.3909137547016142 0.32682865485549051 0.2935192547738551 0.26893061771988858 0.34596097096800793 0.31855252012610424 1.406175013631582
|
| 916 |
+
leaf_count=30 5 3 3 7 6 32
|
| 917 |
+
internal_value=7.29575e-05 0.0447977 -0.0535608 0.0528265 -0.052652 0.0525184
|
| 918 |
+
internal_weight=4.35088 2.37248 1.9784 2.07896 1.70947 1.75214
|
| 919 |
+
internal_count=86 47 39 44 36 39
|
| 920 |
+
is_linear=0
|
| 921 |
+
shrinkage=0.05
|
| 922 |
+
|
| 923 |
+
|
| 924 |
+
Tree=48
|
| 925 |
+
num_leaves=7
|
| 926 |
+
num_cat=0
|
| 927 |
+
split_feature=7 9 12 8 0 9
|
| 928 |
+
split_gain=3.97248 0.585256 0.00526959 6.08468e-05 2.74167e-05 1.91699e-05
|
| 929 |
+
threshold=3449.4166666666674 0.075080247396852748 0.050737547542749055 0.40833333333333338 3.5000000000000004 0.071279139270771077
|
| 930 |
+
decision_type=2 2 2 2 2 2
|
| 931 |
+
left_child=1 2 -1 4 -2 -4
|
| 932 |
+
right_child=3 -3 5 -5 -6 -7
|
| 933 |
+
leaf_value=-0.058227599861785932 0.052704543358393807 0.029445810283716289 -0.052472795418974441 0.053195680650356104 0.052255735231464741 -0.052989089446205645
|
| 934 |
+
leaf_weight=0.57319482415914569 0.47649280354380597 0.23371871188282956 1.2117787078022955 0.26804463565349568 1.1903298236429689 0.21111251413822163
|
| 935 |
+
leaf_count=8 10 3 27 5 29 4
|
| 936 |
+
internal_value=7.39349e-05 -0.0454146 -0.0541799 0.0524965 0.052384 -0.0525494
|
| 937 |
+
internal_weight=4.16467 2.2298 1.99609 1.93487 1.66682 1.42289
|
| 938 |
+
internal_count=86 42 39 44 39 31
|
| 939 |
+
is_linear=0
|
| 940 |
+
shrinkage=0.05
|
| 941 |
+
|
| 942 |
+
|
| 943 |
+
Tree=49
|
| 944 |
+
num_leaves=7
|
| 945 |
+
num_cat=0
|
| 946 |
+
split_feature=2 9 8 7 9 4
|
| 947 |
+
split_gain=3.77277 0.494401 0.00347542 0.000339162 3.96033e-05 1.39968e-05
|
| 948 |
+
threshold=1.0000000180025095e-35 0.056251581878005573 0.48529411764705888 3478.8119047619052 0.071839745922519613 1.0000000180025095e-35
|
| 949 |
+
decision_type=2 2 2 2 2 2
|
| 950 |
+
left_child=1 -1 4 -3 -2 -5
|
| 951 |
+
right_child=2 3 -4 5 -6 -7
|
| 952 |
+
leaf_value=-0.025740498200464142 -0.052317830796601586 0.054115885835263458 -0.05887891549443755 0.052179560241072731 -0.053046725156541179 0.052480626276773648
|
| 953 |
+
leaf_weight=0.22477163374424058 1.3525291308760641 0.30179394781589497 0.24000708013772953 1.0285397768020628 0.21613523736596096 0.61801687628030766
|
| 954 |
+
leaf_count=2 32 5 3 26 4 14
|
| 955 |
+
internal_value=7.30238e-05 0.0444746 -0.0532756 0.052575 -0.0524183 0.0522926
|
| 956 |
+
internal_weight=3.98179 2.17312 1.80867 1.94835 1.56866 1.64656
|
| 957 |
+
internal_count=86 47 39 45 36 40
|
| 958 |
+
is_linear=0
|
| 959 |
+
shrinkage=0.05
|
| 960 |
+
|
| 961 |
+
|
| 962 |
+
Tree=50
|
| 963 |
+
num_leaves=7
|
| 964 |
+
num_cat=0
|
| 965 |
+
split_feature=7 9 12 8 0 9
|
| 966 |
+
split_gain=3.57869 0.530171 0.0041105 6.03024e-05 2.00948e-05 1.40241e-05
|
| 967 |
+
threshold=3449.4166666666674 0.075080247396852748 0.050737547542749055 0.40833333333333338 3.5000000000000004 0.071279139270771077
|
| 968 |
+
decision_type=2 2 2 2 2 2
|
| 969 |
+
left_child=1 2 -1 4 -2 -4
|
| 970 |
+
right_child=3 -3 5 -5 -6 -7
|
| 971 |
+
leaf_value=-0.057523228626730809 0.052434699258117924 0.028193853840167954 -0.052225876034957666 0.05298703689463944 0.052031718022954213 -0.052688885577054048
|
| 972 |
+
leaf_weight=0.52994184568524438 0.43332421034574498 0.22096543014049519 1.1010594852268694 0.24872540682554234 1.0812997855246065 0.1920730024576186
|
| 973 |
+
leaf_count=8 10 3 27 5 29 4
|
| 974 |
+
internal_value=7.46771e-05 -0.0449492 -0.0538145 0.0522655 0.052147 -0.0522946
|
| 975 |
+
internal_weight=3.80739 2.04404 1.82307 1.76335 1.51462 1.29313
|
| 976 |
+
internal_count=86 42 39 44 39 31
|
| 977 |
+
is_linear=0
|
| 978 |
+
shrinkage=0.05
|
| 979 |
+
|
| 980 |
+
|
| 981 |
+
Tree=51
|
| 982 |
+
num_leaves=7
|
| 983 |
+
num_cat=0
|
| 984 |
+
split_feature=2 9 8 7 9 4
|
| 985 |
+
split_gain=3.39448 0.452159 0.00255562 0.000279377 3.65874e-05 1.02775e-05
|
| 986 |
+
threshold=1.0000000180025095e-35 0.056251581878005573 0.48529411764705888 3478.8119047619052 0.071839745922519613 1.0000000180025095e-35
|
| 987 |
+
decision_type=2 2 2 2 2 2
|
| 988 |
+
left_child=1 -1 4 -3 -2 -5
|
| 989 |
+
right_child=2 3 -4 5 -6 -7
|
| 990 |
+
leaf_value=-0.024398645429509903 -0.052086122604661216 0.053789475943882448 -0.057966061097239188 0.051963639842756697 -0.05281445221092828 0.052234256160140505
|
| 991 |
+
leaf_weight=0.21526079624891314 1.2279919162392614 0.27869978547096241 0.22100444883108128 0.93428360298275925 0.20059854164719571 0.56183291971683502
|
| 992 |
+
leaf_count=2 32 5 3 26 4 14
|
| 993 |
+
internal_value=7.36736e-05 0.0440359 -0.0529625 0.052336 -0.0521884 0.0520653
|
| 994 |
+
internal_weight=3.63967 1.99008 1.64959 1.77482 1.42859 1.49612
|
| 995 |
+
internal_count=86 47 39 45 36 40
|
| 996 |
+
is_linear=0
|
| 997 |
+
shrinkage=0.05
|
| 998 |
+
|
| 999 |
+
|
| 1000 |
+
Tree=52
|
| 1001 |
+
num_leaves=7
|
| 1002 |
+
num_cat=0
|
| 1003 |
+
split_feature=7 9 1 7 9 4
|
| 1004 |
+
split_gain=3.22825 0.421536 0.0023962 0.000239484 3.1822e-05 8.79587e-06
|
| 1005 |
+
threshold=3112.1875000000005 0.056251581878005573 1.5000000000000002 3478.8119047619052 0.071839745922519613 1.0000000180025095e-35
|
| 1006 |
+
decision_type=2 2 2 2 2 2
|
| 1007 |
+
left_child=2 -2 4 -3 -1 -5
|
| 1008 |
+
right_child=1 3 -4 5 -6 -7
|
| 1009 |
+
leaf_value=-0.051974075039210477 -0.022611362856803291 0.05359471917210145 -0.05772082104697214 0.051864312884805641 -0.052669764277071332 0.052120741719884484
|
| 1010 |
+
leaf_weight=1.1669210381805899 0.21176189929246891 0.26604645699262608 0.21785303950309742 0.89037709310650803 0.19132617488503445 0.53556656464934349
|
| 1011 |
+
leaf_count=32 2 5 3 26 4 14
|
| 1012 |
+
internal_value=7.52849e-05 0.043894 -0.0528529 0.0522176 -0.0520721 0.0519606
|
| 1013 |
+
internal_weight=3.47985 1.90375 1.5761 1.69199 1.35825 1.42594
|
| 1014 |
+
internal_count=86 47 39 45 36 40
|
| 1015 |
+
is_linear=0
|
| 1016 |
+
shrinkage=0.05
|
| 1017 |
+
|
| 1018 |
+
|
| 1019 |
+
Tree=53
|
| 1020 |
+
num_leaves=7
|
| 1021 |
+
num_cat=0
|
| 1022 |
+
split_feature=7 9 12 8 0 9
|
| 1023 |
+
split_gain=3.07242 0.457043 0.00292621 6.85316e-05 1.26423e-05 8.79499e-06
|
| 1024 |
+
threshold=3449.4166666666674 0.075080247396852748 0.050737547542749055 0.40833333333333338 3.5000000000000004 0.071279139270771077
|
| 1025 |
+
decision_type=2 2 2 2 2 2
|
| 1026 |
+
left_child=1 2 -1 4 -2 -4
|
| 1027 |
+
right_child=3 -3 5 -5 -6 -7
|
| 1028 |
+
leaf_value=-0.056653332418161166 0.052081422039285598 0.026886719870256912 -0.051902369512977067 0.052781343332667423 0.051737953138033879 -0.052296246369048532
|
| 1029 |
+
leaf_weight=0.47251412272453341 0.37544408440589883 0.19973117113113392 0.95273867994546868 0.22473639249801625 0.93540499731898308 0.16649506613612175
|
| 1030 |
+
leaf_count=8 10 3 27 5 29 4
|
| 1031 |
+
internal_value=7.68379e-05 -0.0444079 -0.0533539 0.0519746 0.0518363 -0.051961
|
| 1032 |
+
internal_weight=3.32706 1.79148 1.59175 1.53559 1.31085 1.11923
|
| 1033 |
+
internal_count=86 42 39 44 39 31
|
| 1034 |
+
is_linear=0
|
| 1035 |
+
shrinkage=0.05
|
| 1036 |
+
|
| 1037 |
+
|
| 1038 |
+
Tree=54
|
| 1039 |
+
num_leaves=7
|
| 1040 |
+
num_cat=0
|
| 1041 |
+
split_feature=2 9 8 7 9 4
|
| 1042 |
+
split_gain=2.91014 0.383712 0.00181181 0.000198127 2.92829e-05 6.46712e-06
|
| 1043 |
+
threshold=1.0000000180025095e-35 0.056251581878005573 0.48529411764705888 3478.8119047619052 0.071839745922519613 1.0000000180025095e-35
|
| 1044 |
+
decision_type=2 2 2 2 2 2
|
| 1045 |
+
left_child=1 -1 4 -3 -2 -5
|
| 1046 |
+
right_child=2 3 -4 5 -6 -7
|
| 1047 |
+
leaf_value=-0.021271802133954222 -0.051783011187517117 0.053316114718123579 -0.05703372297539077 0.05168061391869886 -0.052476662686324463 0.051911335109327328
|
| 1048 |
+
leaf_weight=0.20203236490488086 1.0617324132472274 0.24565996043384064 0.19795862212777127 0.80830621160566785 0.17760059237480152 0.48653935268521309
|
| 1049 |
+
leaf_count=2 32 5 3 26 4 14
|
| 1050 |
+
internal_value=7.57291e-05 0.0435174 -0.0525919 0.0520143 -0.0518824 0.0517673
|
| 1051 |
+
internal_weight=3.17983 1.74254 1.43729 1.54051 1.23933 1.29485
|
| 1052 |
+
internal_count=86 47 39 45 36 40
|
| 1053 |
+
is_linear=0
|
| 1054 |
+
shrinkage=0.05
|
| 1055 |
+
|
| 1056 |
+
|
| 1057 |
+
Tree=55
|
| 1058 |
+
num_leaves=7
|
| 1059 |
+
num_cat=0
|
| 1060 |
+
split_feature=7 9 12 8 0 9
|
| 1061 |
+
split_gain=2.77243 0.415122 0.00229827 6.72112e-05 9.28698e-06 6.44362e-06
|
| 1062 |
+
threshold=3449.4166666666674 0.075080247396852748 0.050737547542749055 0.40833333333333338 3.5000000000000004 0.071279139270771077
|
| 1063 |
+
decision_type=2 2 2 2 2 2
|
| 1064 |
+
left_child=1 2 -1 4 -2 -4
|
| 1065 |
+
right_child=3 -3 5 -5 -6 -7
|
| 1066 |
+
leaf_value=-0.056105784181477929 0.051875912022843002 0.025728307039962841 -0.051714463691019945 0.052628220802817885 0.051566996297964268 -0.052068182466303015
|
| 1067 |
+
leaf_weight=0.43628968298435244 0.34102963283658005 0.18887379392981518 0.86484081856906392 0.20874816179275502 0.84894894994795322 0.15127234905958176
|
| 1068 |
+
leaf_count=8 10 3 27 5 29 4
|
| 1069 |
+
internal_value=7.72327e-05 -0.0440025 -0.0530704 0.0518007 0.0516555 -0.0517671
|
| 1070 |
+
internal_weight=3.04 1.64128 1.4524 1.39873 1.18998 1.01611
|
| 1071 |
+
internal_count=86 42 39 44 39 31
|
| 1072 |
+
is_linear=0
|
| 1073 |
+
shrinkage=0.05
|
| 1074 |
+
|
| 1075 |
+
|
| 1076 |
+
Tree=56
|
| 1077 |
+
num_leaves=7
|
| 1078 |
+
num_cat=0
|
| 1079 |
+
split_feature=7 9 1 7 9 4
|
| 1080 |
+
split_gain=2.63473 0.341572 0.00145742 0.000164497 2.79808e-05 4.75855e-06
|
| 1081 |
+
threshold=3112.1875000000005 0.056251581878005573 1.5000000000000002 3478.8119047619052 0.071839745922519613 1.0000000180025095e-35
|
| 1082 |
+
decision_type=2 2 2 2 2 2
|
| 1083 |
+
left_child=2 -2 4 -3 -1 -5
|
| 1084 |
+
right_child=1 3 -4 5 -6 -7
|
| 1085 |
+
leaf_value=-0.051601775945499119 -0.019490915067937303 0.053064119977449434 -0.056470937512833552 0.051515543893373608 -0.052306738587078586 0.051723253421678043
|
| 1086 |
+
leaf_weight=0.96027212589979194 0.19069733470678318 0.22689381800591935 0.18708896823227394 0.73355109617114045 0.16493189707398415 0.4418221190571785
|
| 1087 |
+
leaf_count=32 2 5 3 26 4 14
|
| 1088 |
+
internal_value=7.6045e-05 0.0432934 -0.0523846 0.0518316 -0.0517051 0.0515936
|
| 1089 |
+
internal_weight=2.90526 1.59296 1.31229 1.40227 1.1252 1.17537
|
| 1090 |
+
internal_count=86 47 39 45 36 40
|
| 1091 |
+
is_linear=0
|
| 1092 |
+
shrinkage=0.05
|
| 1093 |
+
|
| 1094 |
+
|
| 1095 |
+
Tree=57
|
| 1096 |
+
num_leaves=7
|
| 1097 |
+
num_cat=0
|
| 1098 |
+
split_feature=7 9 12 8 0 9
|
| 1099 |
+
split_gain=2.50296 0.377471 0.00180685 6.5507e-05 6.82734e-06 4.72454e-06
|
| 1100 |
+
threshold=3449.4166666666674 0.075080247396852748 0.050737547542749055 0.40833333333333338 3.5000000000000004 0.071279139270771077
|
| 1101 |
+
decision_type=2 2 2 2 2 2
|
| 1102 |
+
left_child=1 2 -1 4 -2 -4
|
| 1103 |
+
right_child=3 -3 5 -5 -6 -7
|
| 1104 |
+
leaf_value=-0.055607499936801578 0.051691338019982526 0.024607570301387913 -0.051545654679950564 0.052491083545236787 0.051413343360804969 -0.051863502878320505
|
| 1105 |
+
leaf_weight=0.40267548523843311 0.3096493426710365 0.17867011204361904 0.7847888395190239 0.19394304789602745 0.77025091089308262 0.13737773895263672
|
| 1106 |
+
leaf_count=8 10 3 27 5 29 4
|
| 1107 |
+
internal_value=7.74691e-05 -0.0436129 -0.0528132 0.051645 0.0514931 -0.051593
|
| 1108 |
+
internal_weight=2.77736 1.50351 1.32484 1.27384 1.0799 0.922167
|
| 1109 |
+
internal_count=86 42 39 44 39 31
|
| 1110 |
+
is_linear=0
|
| 1111 |
+
shrinkage=0.05
|
| 1112 |
+
|
| 1113 |
+
|
| 1114 |
+
Tree=58
|
| 1115 |
+
num_leaves=7
|
| 1116 |
+
num_cat=0
|
| 1117 |
+
split_feature=2 6 8 7 10 9
|
| 1118 |
+
split_gain=2.37829 0.331908 0.0011062 0.00011017 0.000136782 2.62188e-05
|
| 1119 |
+
threshold=1.0000000180025095e-35 34778.000000000007 0.48529411764705888 3723.3125000000005 1.0000000180025095e-35 0.071839745922519613
|
| 1120 |
+
decision_type=2 2 2 2 2 2
|
| 1121 |
+
left_child=1 -1 5 4 -3 -2
|
| 1122 |
+
right_child=2 3 -4 -5 -6 -7
|
| 1123 |
+
leaf_value=-0.02156846862497196 -0.051447960970868081 0.053214963622713496 -0.055910400839676348 0.051425765870829365 0.051493380966299018 -0.052157042905489059
|
| 1124 |
+
leaf_weight=0.17535035684704814 0.87325152195990063 0.24104415997862794 0.16981088370084751 0.82012460194528103 0.22129907086491585 0.15324152633547783
|
| 1125 |
+
leaf_count=3 32 5 3 31 8 4
|
| 1126 |
+
internal_value=7.62064e-05 0.0429519 -0.0521722 0.0517737 0.0523909 -0.0515538
|
| 1127 |
+
internal_weight=2.65412 1.45782 1.1963 1.28247 0.462343 1.02649
|
| 1128 |
+
internal_count=86 47 39 44 13 36
|
| 1129 |
+
is_linear=0
|
| 1130 |
+
shrinkage=0.05
|
| 1131 |
+
|
| 1132 |
+
|
| 1133 |
+
Tree=59
|
| 1134 |
+
num_leaves=7
|
| 1135 |
+
num_cat=0
|
| 1136 |
+
split_feature=7 6 1 7 10 9
|
| 1137 |
+
split_gain=2.26299 0.31039 0.00103136 9.44642e-05 0.000117133 2.27371e-05
|
| 1138 |
+
threshold=3112.1875000000005 34778.000000000007 1.5000000000000002 3723.3125000000005 1.0000000180025095e-35 0.071839745922519613
|
| 1139 |
+
decision_type=2 2 2 2 2 2
|
| 1140 |
+
left_child=2 -2 5 4 -3 -1
|
| 1141 |
+
right_child=1 3 -4 -5 -6 -7
|
| 1142 |
+
leaf_value=-0.051371228485124071 -0.019963441560389303 0.053050195574039838 -0.055724017708956963 0.051354380500580665 0.051418509974003837 -0.052047763416771343
|
| 1143 |
+
leaf_weight=0.82932015880942367 0.17249920591711987 0.22998244687914826 0.16708584688603878 0.78118370473384857 0.21080497466027737 0.14606617018580437
|
| 1144 |
+
leaf_count=32 3 5 3 31 8 4
|
| 1145 |
+
internal_value=7.76964e-05 0.0428216 -0.0520943 0.0516846 0.0522698 -0.0514725
|
| 1146 |
+
internal_weight=2.53694 1.39447 1.14247 1.22197 0.440787 0.975386
|
| 1147 |
+
internal_count=86 47 39 44 13 36
|
| 1148 |
+
is_linear=0
|
| 1149 |
+
shrinkage=0.05
|
| 1150 |
+
|
| 1151 |
+
|
| 1152 |
+
Tree=60
|
| 1153 |
+
num_leaves=7
|
| 1154 |
+
num_cat=0
|
| 1155 |
+
split_feature=7 9 12 8 0 1
|
| 1156 |
+
split_gain=2.15431 0.326455 0.0012912 3.99674e-05 6.38946e-06 3.60815e-06
|
| 1157 |
+
threshold=3449.4166666666674 0.075080247396852748 0.050737547542749055 0.40833333333333338 3.5000000000000004 2.5000000000000004
|
| 1158 |
+
decision_type=2 2 2 2 2 2
|
| 1159 |
+
left_child=1 2 -1 4 5 -2
|
| 1160 |
+
right_child=3 -3 -4 -5 -6 -7
|
| 1161 |
+
leaf_value=-0.054978886079340053 0.051694326374548474 0.023438303528843456 -0.051364201244319722 0.052132262398176032 0.05121131365199786 0.051331171854148955
|
| 1162 |
+
leaf_weight=0.3580956254154446 0.1262961048632858 0.16136743128299702 0.79672552831470966 0.16806215979158878 0.66531687788665295 0.14919918403029442
|
| 1163 |
+
leaf_count=8 4 3 31 5 29 6
|
| 1164 |
+
internal_value=7.91249e-05 -0.0431767 -0.0524851 0.051422 0.0512952 0.0514977
|
| 1165 |
+
internal_weight=2.42506 1.31619 1.15482 1.10887 0.940812 0.275495
|
| 1166 |
+
internal_count=86 42 39 44 39 10
|
| 1167 |
+
is_linear=0
|
| 1168 |
+
shrinkage=0.05
|
| 1169 |
+
|
| 1170 |
+
|
| 1171 |
+
Tree=61
|
| 1172 |
+
num_leaves=7
|
| 1173 |
+
num_cat=0
|
| 1174 |
+
split_feature=2 6 8 7 10 9
|
| 1175 |
+
split_gain=2.04469 0.282176 0.000786681 7.58747e-05 9.33969e-05 2.14542e-05
|
| 1176 |
+
threshold=1.0000000180025095e-35 34778.000000000007 0.48529411764705888 3723.3125000000005 1.0000000180025095e-35 0.071839745922519613
|
| 1177 |
+
decision_type=2 2 2 2 2 2
|
| 1178 |
+
left_child=1 -1 5 4 -3 -2
|
| 1179 |
+
right_child=2 3 -4 -5 -6 -7
|
| 1180 |
+
leaf_value=-0.018754410714250033 -0.051240132484338098 0.052803334457989619 -0.055240518558143659 0.05122231258980349 0.051279791758668064 -0.051922877177181609
|
| 1181 |
+
leaf_weight=0.1638234127312902 0.753892747685313 0.21225182898342587 0.15163859352469444 0.70860414579510689 0.19121293351054192 0.13578741624951363
|
| 1182 |
+
leaf_count=3 32 5 3 31 8 4
|
| 1183 |
+
internal_value=7.77931e-05 0.042509 -0.0519117 0.051534 0.0520813 -0.0513443
|
| 1184 |
+
internal_weight=2.31721 1.27589 1.04132 1.11207 0.403465 0.88968
|
| 1185 |
+
internal_count=86 47 39 44 13 36
|
| 1186 |
+
is_linear=0
|
| 1187 |
+
shrinkage=0.05
|
| 1188 |
+
|
| 1189 |
+
|
| 1190 |
+
Tree=62
|
| 1191 |
+
num_leaves=7
|
| 1192 |
+
num_cat=0
|
| 1193 |
+
split_feature=7 9 12 8 0 1
|
| 1194 |
+
split_gain=1.94651 0.297435 0.00101562 2.88044e-05 5.81162e-06 3.07927e-06
|
| 1195 |
+
threshold=3449.4166666666674 0.075080247396852748 0.050737547542749055 0.40833333333333338 3.5000000000000004 2.5000000000000004
|
| 1196 |
+
decision_type=2 2 2 2 2 2
|
| 1197 |
+
left_child=1 2 -1 4 5 -2
|
| 1198 |
+
right_child=3 -3 -4 -5 -6 -7
|
| 1199 |
+
leaf_value=-0.054578448834940924 0.051567146719777759 0.02239266513495286 -0.051230840124425414 0.051923259839556216 0.051093357651703752 0.051217690768354543
|
| 1200 |
+
leaf_weight=0.33006986044347308 0.11681191995739915 0.15269735455512989 0.72255352139472961 0.15266721323132515 0.60328011028468609 0.13693635538220406
|
| 1201 |
+
leaf_count=8 4 3 31 5 29 6
|
| 1202 |
+
internal_value=7.91791e-05 -0.0428205 -0.0522805 0.0512905 0.0511778 0.0513786
|
| 1203 |
+
internal_weight=2.21502 1.20532 1.05262 1.0097 0.857028 0.253748
|
| 1204 |
+
internal_count=86 42 39 44 39 10
|
| 1205 |
+
is_linear=0
|
| 1206 |
+
shrinkage=0.05
|
| 1207 |
+
|
| 1208 |
+
|
| 1209 |
+
Tree=63
|
| 1210 |
+
num_leaves=7
|
| 1211 |
+
num_cat=0
|
| 1212 |
+
split_feature=7 3 1 7 8 9
|
| 1213 |
+
split_gain=1.85432 0.417261 0.000627643 7.49571e-05 2.58057e-05 2.06953e-05
|
| 1214 |
+
threshold=3112.1875000000005 0.00030309239974547856 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1215 |
+
decision_type=2 2 2 2 2 2
|
| 1216 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1217 |
+
right_child=1 3 -4 4 -6 -7
|
| 1218 |
+
leaf_value=-0.051115534100290363 -0.05621703388787315 0.052345240117811768 -0.054820674551753504 0.051099128658674879 0.051827121348642452 -0.051812371493738234
|
| 1219 |
+
leaf_weight=0.68126739375293288 0.098359771072864421 0.17671952582895734 0.14278436452150345 0.74558193981647491 0.14548412896692753 0.12630220502614975
|
| 1220 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1221 |
+
internal_value=7.77907e-05 0.0423271 -0.0517648 0.0514045 0.051218 -0.0512245
|
| 1222 |
+
internal_weight=2.1165 1.16615 0.950354 1.06779 0.891066 0.80757
|
| 1223 |
+
internal_count=86 47 39 46 41 36
|
| 1224 |
+
is_linear=0
|
| 1225 |
+
shrinkage=0.05
|
| 1226 |
+
|
| 1227 |
+
|
| 1228 |
+
Tree=64
|
| 1229 |
+
num_leaves=7
|
| 1230 |
+
num_cat=0
|
| 1231 |
+
split_feature=7 3 1 7 8 9
|
| 1232 |
+
split_gain=1.76081 0.396075 0.000539014 6.43369e-05 2.21824e-05 1.77622e-05
|
| 1233 |
+
threshold=3112.1875000000005 0.00030309239974547856 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1234 |
+
decision_type=2 2 2 2 2 2
|
| 1235 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1236 |
+
right_child=1 3 -4 4 -6 -7
|
| 1237 |
+
leaf_value=-0.051059950058782694 -0.05587717407369152 0.052227077895438845 -0.054573725316594573 0.051044416503153757 0.05173590102714111 -0.05172133134698214
|
| 1238 |
+
leaf_weight=0.64872924610972438 0.094117365777492412 0.16847153194248654 0.13641974702477455 0.70996048487722874 0.13862663134932518 0.12034851312637329
|
| 1239 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1240 |
+
internal_value=7.81751e-05 0.0422537 -0.0516772 0.0513346 0.0511574 -0.0511634
|
| 1241 |
+
internal_weight=2.01667 1.11118 0.905498 1.01706 0.848587 0.769078
|
| 1242 |
+
internal_count=86 47 39 46 41 36
|
| 1243 |
+
is_linear=0
|
| 1244 |
+
shrinkage=0.05
|
| 1245 |
+
|
| 1246 |
+
|
| 1247 |
+
Tree=65
|
| 1248 |
+
num_leaves=7
|
| 1249 |
+
num_cat=0
|
| 1250 |
+
split_feature=7 1 1 7 8 9
|
| 1251 |
+
split_gain=1.67215 0.376009 0.000462941 5.52291e-05 1.90695e-05 1.52469e-05
|
| 1252 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1253 |
+
decision_type=2 2 2 2 2 2
|
| 1254 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1255 |
+
right_child=1 3 -4 4 -6 -7
|
| 1256 |
+
leaf_value=-0.051007192846026506 -0.055557784036650598 0.052115048839742974 -0.054339948385641892 0.05099247923509416 0.051649338939514816 -0.051634989287311799
|
| 1257 |
+
leaf_weight=0.6177124995738269 0.090028844773769157 0.16059087030589581 0.13031063787639141 0.67600579001009464 0.1320811565965414 0.11466564238071442
|
| 1258 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1259 |
+
internal_value=7.85369e-05 0.042184 -0.0515941 0.0512681 0.0510998 -0.0511055
|
| 1260 |
+
internal_weight=1.9214 1.05871 0.862689 0.968678 0.808087 0.732378
|
| 1261 |
+
internal_count=86 47 39 46 41 36
|
| 1262 |
+
is_linear=0
|
| 1263 |
+
shrinkage=0.05
|
| 1264 |
+
|
| 1265 |
+
|
| 1266 |
+
Tree=66
|
| 1267 |
+
num_leaves=7
|
| 1268 |
+
num_cat=0
|
| 1269 |
+
split_feature=7 1 1 7 8 9
|
| 1270 |
+
split_gain=1.58809 0.357 0.000397637 4.7417e-05 1.63942e-05 1.30896e-05
|
| 1271 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1272 |
+
decision_type=2 2 2 2 2 2
|
| 1273 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1274 |
+
right_child=1 3 -4 4 -6 -7
|
| 1275 |
+
leaf_value=-0.050957112841780151 -0.055257426518026911 0.052008818494963222 -0.054118591481353243 0.050943172734727149 0.051567181814864339 -0.051553093612409742
|
| 1276 |
+
leaf_weight=0.58814921975135814 0.086091794073581474 0.15306290239095688 0.12444949708878994 0.64364327490329742 0.12583459727466106 0.10924223065376282
|
| 1277 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1278 |
+
internal_value=7.88775e-05 0.042118 -0.0515151 0.0512051 0.0510452 -0.0510505
|
| 1279 |
+
internal_weight=1.83047 1.00863 0.821841 0.922541 0.769478 0.697391
|
| 1280 |
+
internal_count=86 47 39 46 41 36
|
| 1281 |
+
is_linear=0
|
| 1282 |
+
shrinkage=0.05
|
| 1283 |
+
|
| 1284 |
+
|
| 1285 |
+
Tree=67
|
| 1286 |
+
num_leaves=7
|
| 1287 |
+
num_cat=0
|
| 1288 |
+
split_feature=7 1 1 7 8 9
|
| 1289 |
+
split_gain=1.50838 0.338986 0.000341575 4.07151e-05 1.40952e-05 1.1239e-05
|
| 1290 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1291 |
+
decision_type=2 2 2 2 2 2
|
| 1292 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1293 |
+
right_child=1 3 -4 4 -6 -7
|
| 1294 |
+
leaf_value=-0.05090956693516191 -0.054974794454426261 0.051908070683690404 -0.053908957765295529 0.050896358129884182 0.051489200516835226 -0.051475401949002943
|
| 1295 |
+
leaf_weight=0.55997416283935308 0.082303412258625031 0.14587339106947184 0.11882872879505157 0.61280137114226818 0.11987428180873394 0.10406730137765408
|
| 1296 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1297 |
+
internal_value=7.91989e-05 0.0420553 -0.05144 0.0511452 0.0509934 -0.0509982
|
| 1298 |
+
internal_weight=1.74372 0.960852 0.78287 0.878549 0.732676 0.664041
|
| 1299 |
+
internal_count=86 47 39 46 41 36
|
| 1300 |
+
is_linear=0
|
| 1301 |
+
shrinkage=0.05
|
| 1302 |
+
|
| 1303 |
+
|
| 1304 |
+
Tree=68
|
| 1305 |
+
num_leaves=7
|
| 1306 |
+
num_cat=0
|
| 1307 |
+
split_feature=7 1 1 7 8 9
|
| 1308 |
+
split_gain=1.43277 0.321913 0.00029344 3.49645e-05 1.21194e-05 9.6512e-06
|
| 1309 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1310 |
+
decision_type=2 2 2 2 2 2
|
| 1311 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1312 |
+
right_child=1 3 -4 4 -6 -7
|
| 1313 |
+
leaf_value=-0.050864425030284301 -0.054708686955405844 0.051812507153240289 -0.053710385607623638 0.050851905653572706 0.051415173768754034 -0.051401690927245863
|
| 1314 |
+
leaf_weight=0.53312471695244312 0.078660592436790466 0.13900853041559458 0.11344072036445141 0.58341139741241932 0.11418797634541988 0.099130252376198769
|
| 1315 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1316 |
+
internal_value=7.95015e-05 0.0419959 -0.0513688 0.0510884 0.0509441 -0.0509487
|
| 1317 |
+
internal_weight=1.66096 0.915268 0.745696 0.836608 0.697599 0.632255
|
| 1318 |
+
internal_count=86 47 39 46 41 36
|
| 1319 |
+
is_linear=0
|
| 1320 |
+
shrinkage=0.05
|
| 1321 |
+
|
| 1322 |
+
|
| 1323 |
+
Tree=69
|
| 1324 |
+
num_leaves=7
|
| 1325 |
+
num_cat=0
|
| 1326 |
+
split_feature=7 1 1 7 8 9
|
| 1327 |
+
split_gain=1.36104 0.305727 0.000252108 3.00296e-05 1.0421e-05 8.28868e-06
|
| 1328 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1329 |
+
decision_type=2 2 2 2 2 2
|
| 1330 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1331 |
+
right_child=1 3 -4 4 -6 -7
|
| 1332 |
+
leaf_value=-0.050821559664680674 -0.054457997003113136 0.051721850934761386 -0.05352225117720219 0.050809692856807032 0.051344893548052079 -0.051331744608704925
|
| 1333 |
+
leaf_weight=0.50754085648804903 0.075159996747970581 0.13245491962879896 0.10827787034213543 0.55540751945227385 0.10876388847827911 0.094420861452817917
|
| 1334 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1335 |
+
internal_value=7.97873e-05 0.0419395 -0.0513011 0.0510344 0.0508973 -0.0509016
|
| 1336 |
+
internal_weight=1.58203 0.871786 0.71024 0.796626 0.664171 0.601962
|
| 1337 |
+
internal_count=86 47 39 46 41 36
|
| 1338 |
+
is_linear=0
|
| 1339 |
+
shrinkage=0.05
|
| 1340 |
+
|
| 1341 |
+
|
| 1342 |
+
Tree=70
|
| 1343 |
+
num_leaves=7
|
| 1344 |
+
num_cat=0
|
| 1345 |
+
split_feature=7 1 1 7 8 9
|
| 1346 |
+
split_gain=1.293 0.29038 0.000216615 2.5794e-05 8.96111e-06 7.11943e-06
|
| 1347 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1348 |
+
decision_type=2 2 2 2 2 2
|
| 1349 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1350 |
+
right_child=1 3 -4 4 -6 -7
|
| 1351 |
+
leaf_value=-0.050780852112463595 -0.054221723843112357 0.051635834443303885 -0.053343981189505944 0.050769602713120303 0.051278163205708376 -0.051265367414903423
|
| 1352 |
+
leaf_weight=0.48316505178809166 0.071798063814640045 0.12619960773736238 0.10333260335028172 0.52872663736343384 0.10359065048396587 0.089929260313510895
|
| 1353 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1354 |
+
internal_value=8.00567e-05 0.041886 -0.0512368 0.0509832 0.0508529 -0.0508569
|
| 1355 |
+
internal_weight=1.50674 0.830315 0.676427 0.758517 0.632317 0.573094
|
| 1356 |
+
internal_count=86 47 39 46 41 36
|
| 1357 |
+
is_linear=0
|
| 1358 |
+
shrinkage=0.05
|
| 1359 |
+
|
| 1360 |
+
|
| 1361 |
+
Tree=71
|
| 1362 |
+
num_leaves=7
|
| 1363 |
+
num_cat=0
|
| 1364 |
+
split_feature=7 1 1 7 8 9
|
| 1365 |
+
split_gain=1.22843 0.275826 0.000186132 2.21579e-05 7.70615e-06 6.11564e-06
|
| 1366 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1367 |
+
decision_type=2 2 2 2 2 2
|
| 1368 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1369 |
+
right_child=1 3 -4 4 -6 -7
|
| 1370 |
+
leaf_value=-0.050742192952038773 -0.053998904107683078 0.051554210494796596 -0.053175019475394159 0.050731526188011147 0.051214799713511339 -0.051202363106691677
|
| 1371 |
+
leaf_weight=0.45994213689118624 0.068571113049983978 0.12023004423826933 0.098597445525228977 0.50330829620361328 0.098657312802970409 0.085645964369177818
|
| 1372 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1373 |
+
internal_value=8.03114e-05 0.0418352 -0.0511757 0.0509345 0.0508107 -0.0508144
|
| 1374 |
+
internal_weight=1.43495 0.790767 0.644186 0.722196 0.601966 0.545588
|
| 1375 |
+
internal_count=86 47 39 46 41 36
|
| 1376 |
+
is_linear=0
|
| 1377 |
+
shrinkage=0.05
|
| 1378 |
+
|
| 1379 |
+
|
| 1380 |
+
Tree=72
|
| 1381 |
+
num_leaves=7
|
| 1382 |
+
num_cat=0
|
| 1383 |
+
split_feature=7 1 1 7 8 9
|
| 1384 |
+
split_gain=1.16716 0.262021 0.00015995 1.90365e-05 6.62721e-06 5.25387e-06
|
| 1385 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1386 |
+
decision_type=2 2 2 2 2 2
|
| 1387 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1388 |
+
right_child=1 3 -4 4 -6 -7
|
| 1389 |
+
leaf_value=-0.050705475390719956 -0.053788693608861321 0.051476751584957708 -0.053014865889454477 0.050695358214698165 0.051154623874076044 -0.051142556259255872
|
| 1390 |
+
leaf_weight=0.43781932163983583 0.065475329756736755 0.1145341070368886 0.094064968638122082 0.4790946114808321 0.093953348696231842 0.081561826169490814
|
| 1391 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1392 |
+
internal_value=8.05513e-05 0.041787 -0.0511177 0.0508883 0.0507707 -0.0507741
|
| 1393 |
+
internal_weight=1.3665 0.753057 0.613446 0.687582 0.573048 0.519381
|
| 1394 |
+
internal_count=86 47 39 46 41 36
|
| 1395 |
+
is_linear=0
|
| 1396 |
+
shrinkage=0.05
|
| 1397 |
+
|
| 1398 |
+
|
| 1399 |
+
Tree=73
|
| 1400 |
+
num_leaves=7
|
| 1401 |
+
num_cat=0
|
| 1402 |
+
split_feature=7 1 1 7 8 9
|
| 1403 |
+
split_gain=1.10901 0.248925 0.000137461 1.63561e-05 5.69959e-06 4.51411e-06
|
| 1404 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1405 |
+
decision_type=2 2 2 2 2 2
|
| 1406 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1407 |
+
right_child=1 3 -4 4 -6 -7
|
| 1408 |
+
leaf_value=-0.050670596929096236 -0.053590293940464412 0.051403226371230605 -0.052863026678438688 0.050661002316579024 0.05109747441563757 -0.051085784812353235
|
| 1409 |
+
leaf_weight=0.41674605384469032 0.062506809830665588 0.10910011269152164 0.089727881364524364 0.45603015180677176 0.089468623511493206 0.077668054029345512
|
| 1410 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1411 |
+
internal_value=8.07783e-05 0.0417413 -0.0510626 0.0508444 0.0507326 -0.0507358
|
| 1412 |
+
internal_weight=1.30125 0.717106 0.584142 0.654599 0.545499 0.494414
|
| 1413 |
+
internal_count=86 47 39 46 41 36
|
| 1414 |
+
is_linear=0
|
| 1415 |
+
shrinkage=0.05
|
| 1416 |
+
|
| 1417 |
+
|
| 1418 |
+
Tree=74
|
| 1419 |
+
num_leaves=7
|
| 1420 |
+
num_cat=0
|
| 1421 |
+
split_feature=7 1 1 7 8 9
|
| 1422 |
+
split_gain=1.05381 0.2365 0.000118141 1.40545e-05 4.90203e-06 3.87871e-06
|
| 1423 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1424 |
+
decision_type=2 2 2 2 2 2
|
| 1425 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1426 |
+
right_child=1 3 -4 4 -6 -7
|
| 1427 |
+
leaf_value=-0.050637467274374216 -0.053402953026905391 0.051333436912432265 -0.052719051611408531 0.050628363751426902 0.051043193153155614 -0.051031878578930726
|
| 1428 |
+
leaf_weight=0.39667393453419209 0.059661626815795898 0.10391676984727383 0.085579007863998413 0.43406189233064651 0.085193407721817493 0.073956210166215897
|
| 1429 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1430 |
+
internal_value=8.09923e-05 0.0416978 -0.0510102 0.0508026 0.0506964 -0.0506994
|
| 1431 |
+
internal_weight=1.23904 0.682834 0.556209 0.623172 0.519255 0.47063
|
| 1432 |
+
internal_count=86 47 39 46 41 36
|
| 1433 |
+
is_linear=0
|
| 1434 |
+
shrinkage=0.05
|
| 1435 |
+
|
| 1436 |
+
|
| 1437 |
+
Tree=75
|
| 1438 |
+
num_leaves=7
|
| 1439 |
+
num_cat=0
|
| 1440 |
+
split_feature=7 1 1 7 8 9
|
| 1441 |
+
split_gain=1.00141 0.224708 0.000101543 1.20777e-05 4.21624e-06 3.3331e-06
|
| 1442 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1443 |
+
decision_type=2 2 2 2 2 2
|
| 1444 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1445 |
+
right_child=1 3 -4 4 -6 -7
|
| 1446 |
+
leaf_value=-0.050605992909838506 -0.053225989443578751 0.051267180988710331 -0.052582510474784787 0.050597355899224455 0.050991633012501328 -0.050980696151185459
|
| 1447 |
+
leaf_weight=0.37755667231976986 0.056935809552669525 0.098973212763667107 0.081611312925815582 0.4131390955299139 0.081118350848555565 0.070418167859315872
|
| 1448 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1449 |
+
internal_value=8.11955e-05 0.0416566 -0.0509604 0.050763 0.0506621 -0.0506649
|
| 1450 |
+
internal_weight=1.17975 0.650166 0.529586 0.593231 0.494257 0.447975
|
| 1451 |
+
internal_count=86 47 39 46 41 36
|
| 1452 |
+
is_linear=0
|
| 1453 |
+
shrinkage=0.05
|
| 1454 |
+
|
| 1455 |
+
|
| 1456 |
+
Tree=76
|
| 1457 |
+
num_leaves=7
|
| 1458 |
+
num_cat=0
|
| 1459 |
+
split_feature=7 1 1 7 8 9
|
| 1460 |
+
split_gain=0.951663 0.213518 8.72826e-05 1.03797e-05 3.62654e-06 2.86445e-06
|
| 1461 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1462 |
+
decision_type=2 2 2 2 2 2
|
| 1463 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1464 |
+
right_child=1 3 -4 4 -6 -7
|
| 1465 |
+
leaf_value=-0.050576091499889057 -0.053058772421869627 0.051204274601570433 -0.052453005695592851 0.050567895908851794 0.050942655295936667 -0.050932092913472754
|
| 1466 |
+
leaf_weight=0.35934999864548445 0.054325386881828308 0.09425897803157568 0.077817914076149464 0.39321324229240417 0.077234478667378426 0.067046143114566803
|
| 1467 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1468 |
+
internal_value=8.13871e-05 0.0416174 -0.0509131 0.0507254 0.0506294 -0.0506321
|
| 1469 |
+
internal_weight=1.12325 0.619032 0.504214 0.564707 0.470448 0.426396
|
| 1470 |
+
internal_count=86 47 39 46 41 36
|
| 1471 |
+
is_linear=0
|
| 1472 |
+
shrinkage=0.05
|
| 1473 |
+
|
| 1474 |
+
|
| 1475 |
+
Tree=77
|
| 1476 |
+
num_leaves=7
|
| 1477 |
+
num_cat=0
|
| 1478 |
+
split_feature=7 1 1 7 8 9
|
| 1479 |
+
split_gain=0.90443 0.202896 7.50295e-05 8.92117e-06 3.11936e-06 2.46191e-06
|
| 1480 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1481 |
+
decision_type=2 2 2 2 2 2
|
| 1482 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1483 |
+
right_child=1 3 -4 4 -6 -7
|
| 1484 |
+
leaf_value=-0.050547681250523127 -0.052900709212720103 0.051144543684963434 -0.052330160079570358 0.050539903777803798 0.050896121373446214 -0.050885935733301926
|
| 1485 |
+
leaf_weight=0.34201156906783581 0.051826409995555878 0.089763985946774483 0.074192073196172714 0.37423794716596603 0.073533183895051479 0.063832654617726803
|
| 1486 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1487 |
+
internal_value=8.15681e-05 0.0415802 -0.0508682 0.0506896 0.0505984 -0.0506009
|
| 1488 |
+
internal_weight=1.0694 0.589362 0.480036 0.537535 0.447771 0.405844
|
| 1489 |
+
internal_count=86 47 39 46 41 36
|
| 1490 |
+
is_linear=0
|
| 1491 |
+
shrinkage=0.05
|
| 1492 |
+
|
| 1493 |
+
|
| 1494 |
+
Tree=78
|
| 1495 |
+
num_leaves=7
|
| 1496 |
+
num_cat=0
|
| 1497 |
+
split_feature=7 1 1 7 8 9
|
| 1498 |
+
split_gain=0.85958 0.192814 6.44998e-05 7.66809e-06 2.68325e-06 2.1161e-06
|
| 1499 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1500 |
+
decision_type=2 2 2 2 2 2
|
| 1501 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1502 |
+
right_child=1 3 -4 4 -6 -7
|
| 1503 |
+
leaf_value=-0.050520685962263473 -0.052751246317376467 0.051087821225232033 -0.052213607565704284 0.050513304914895744 0.05085191371230572 -0.050842097782830324
|
| 1504 |
+
leaf_weight=0.3255009176209569 0.049434956163167953 0.085478556342422962 0.070727241225540638 0.35616886988282204 0.070006201975047588 0.060770533978939056
|
| 1505 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1506 |
+
internal_value=8.17398e-05 0.0415449 -0.0508254 0.0506556 0.0505689 -0.0505713
|
| 1507 |
+
internal_weight=1.01809 0.561089 0.456999 0.511654 0.426175 0.386271
|
| 1508 |
+
internal_count=86 47 39 46 41 36
|
| 1509 |
+
is_linear=0
|
| 1510 |
+
shrinkage=0.05
|
| 1511 |
+
|
| 1512 |
+
|
| 1513 |
+
Tree=79
|
| 1514 |
+
num_leaves=7
|
| 1515 |
+
num_cat=0
|
| 1516 |
+
split_feature=7 1 1 7 8 9
|
| 1517 |
+
split_gain=0.816989 0.183241 5.54509e-05 6.59146e-06 2.30818e-06 1.81894e-06
|
| 1518 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1519 |
+
decision_type=2 2 2 2 2 2
|
| 1520 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1521 |
+
right_child=1 3 -4 4 -6 -7
|
| 1522 |
+
leaf_value=-0.050495035577253246 -0.052609879592763309 0.051033952868473467 -0.052103016195310527 0.050488029243038579 0.050809911209010843 -0.050800455235265052
|
| 1523 |
+
leaf_weight=0.30977936740964651 0.047147151082754135 0.081393376924097538 0.067417027428746223 0.33896364271640778 0.06664562039077282 0.057852909900248051
|
| 1524 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1525 |
+
internal_value=8.1902e-05 0.0415114 -0.0507848 0.0506233 0.0505409 -0.0505431
|
| 1526 |
+
internal_weight=0.969199 0.53415 0.435049 0.487003 0.405609 0.367632
|
| 1527 |
+
internal_count=86 47 39 46 41 36
|
| 1528 |
+
is_linear=0
|
| 1529 |
+
shrinkage=0.05
|
| 1530 |
+
|
| 1531 |
+
|
| 1532 |
+
Tree=80
|
| 1533 |
+
num_leaves=7
|
| 1534 |
+
num_cat=0
|
| 1535 |
+
split_feature=7 1 1 7 8 9
|
| 1536 |
+
split_gain=0.776539 0.174152 4.76742e-05 5.66639e-06 1.9856e-06 1.56364e-06
|
| 1537 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1538 |
+
decision_type=2 2 2 2 2 2
|
| 1539 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1540 |
+
right_child=1 3 -4 4 -6 -7
|
| 1541 |
+
leaf_value=-0.050470660707490289 -0.052476120132517505 0.050982791862173887 -0.051998074717629184 0.050464009597148043 0.050770000967523543 -0.050760901592487029
|
| 1542 |
+
leaf_weight=0.29480996914207935 0.044959183782339096 0.0774995107203722 0.064255218952894211 0.32258179038763046 0.063443851657211781 0.055073190480470657
|
| 1543 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1544 |
+
internal_value=8.20557e-05 0.0414795 -0.0507462 0.0505926 0.0505143 -0.0505163
|
| 1545 |
+
internal_weight=0.922623 0.508484 0.414138 0.463525 0.386026 0.349883
|
| 1546 |
+
internal_count=86 47 39 46 41 36
|
| 1547 |
+
is_linear=0
|
| 1548 |
+
shrinkage=0.05
|
| 1549 |
+
|
| 1550 |
+
|
| 1551 |
+
Tree=81
|
| 1552 |
+
num_leaves=7
|
| 1553 |
+
num_cat=0
|
| 1554 |
+
split_feature=7 1 1 7 8 9
|
| 1555 |
+
split_gain=0.73812 0.165521 4.099e-05 4.87137e-06 1.70813e-06 1.34427e-06
|
| 1556 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1557 |
+
decision_type=2 2 2 2 2 2
|
| 1558 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1559 |
+
right_child=1 3 -4 4 -6 -7
|
| 1560 |
+
leaf_value=-0.050447496670033211 -0.052349535760650268 0.050934193609556068 -0.051898474212720883 0.050441182498878724 0.050732075860885184 -0.050723328052498809
|
| 1561 |
+
leaf_weight=0.28055744618177414 0.042867299169301987 0.073788378853350878 0.061235793866217136 0.30698465742170811 0.060393636114895344 0.052425066940486431
|
| 1562 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1563 |
+
internal_value=8.22008e-05 0.0414492 -0.0507096 0.0505635 0.050489 -0.0504909
|
| 1564 |
+
internal_weight=0.878252 0.484034 0.394218 0.441167 0.367378 0.332983
|
| 1565 |
+
internal_count=86 47 39 46 41 36
|
| 1566 |
+
is_linear=0
|
| 1567 |
+
shrinkage=0.05
|
| 1568 |
+
|
| 1569 |
+
|
| 1570 |
+
Tree=82
|
| 1571 |
+
num_leaves=7
|
| 1572 |
+
num_cat=0
|
| 1573 |
+
split_feature=7 1 1 7 8 9
|
| 1574 |
+
split_gain=0.701627 0.157325 3.52449e-05 4.18822e-06 1.46947e-06 1.15574e-06
|
| 1575 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1576 |
+
decision_type=2 2 2 2 2 2
|
| 1577 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1578 |
+
right_child=1 3 -4 4 -6 -7
|
| 1579 |
+
leaf_value=-0.050425480302814775 -0.052229705204215097 0.05088803351331226 -0.051803939908119739 0.050419487462217007 0.050696035386165586 -0.050687628735126826
|
| 1580 |
+
leaf_weight=0.26698806835338473 0.040867827832698822 0.070251740515232086 0.058352903928607702 0.29213531780987978 0.057488014455884695 0.04990250151604414
|
| 1581 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1582 |
+
internal_value=8.23391e-05 0.0414205 -0.0506747 0.0505357 0.050465 -0.0504668
|
| 1583 |
+
internal_weight=0.835986 0.460743 0.375243 0.419875 0.349623 0.316891
|
| 1584 |
+
internal_count=86 47 39 46 41 36
|
| 1585 |
+
is_linear=0
|
| 1586 |
+
shrinkage=0.05
|
| 1587 |
+
|
| 1588 |
+
|
| 1589 |
+
Tree=83
|
| 1590 |
+
num_leaves=7
|
| 1591 |
+
num_cat=0
|
| 1592 |
+
split_feature=7 1 1 7 8 9
|
| 1593 |
+
split_gain=0.666961 0.14954 3.03061e-05 3.60101e-06 1.26423e-06 9.93682e-07
|
| 1594 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1595 |
+
decision_type=2 2 2 2 2 2
|
| 1596 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1597 |
+
right_child=1 3 -4 4 -6 -7
|
| 1598 |
+
leaf_value=-0.050404560437629559 -0.052116234595129485 0.050844179989428556 -0.051714197764098593 0.05039886753862708 0.050661788649821377 -0.050653713021414817
|
| 1599 |
+
leaf_weight=0.25406966172158718 0.038957182317972183 0.066881705075502396 0.055600891355425119 0.2779985386878252 0.054720326326787472 0.047499710693955421
|
| 1600 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1601 |
+
internal_value=8.24693e-05 0.0413931 -0.0506416 0.0505094 0.0504421 -0.0504438
|
| 1602 |
+
internal_weight=0.795728 0.438558 0.35717 0.399601 0.332719 0.301569
|
| 1603 |
+
internal_count=86 47 39 46 41 36
|
| 1604 |
+
is_linear=0
|
| 1605 |
+
shrinkage=0.05
|
| 1606 |
+
|
| 1607 |
+
|
| 1608 |
+
Tree=84
|
| 1609 |
+
num_leaves=7
|
| 1610 |
+
num_cat=0
|
| 1611 |
+
split_feature=7 1 1 7 8 9
|
| 1612 |
+
split_gain=0.634029 0.142147 2.60608e-05 3.09632e-06 1.08764e-06 8.54411e-07
|
| 1613 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1614 |
+
decision_type=2 2 2 2 2 2
|
| 1615 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1616 |
+
right_child=1 3 -4 4 -6 -7
|
| 1617 |
+
leaf_value=-0.050384673639876559 -0.052008767086894052 0.050802517799151063 -0.051629003038727722 0.050379268663426437 0.050629237053843035 -0.050621486875958716
|
| 1618 |
+
leaf_weight=0.2417715173214674 0.037131857126951218 0.063670704141259193 0.052974275313317776 0.26454066997393966 0.052084204275161028 0.045211158692836761
|
| 1619 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1620 |
+
internal_value=8.25933e-05 0.0413672 -0.0506101 0.0504844 0.0504204 -0.050422
|
| 1621 |
+
internal_weight=0.757384 0.417427 0.339957 0.380296 0.316625 0.286983
|
| 1622 |
+
internal_count=86 47 39 46 41 36
|
| 1623 |
+
is_linear=0
|
| 1624 |
+
shrinkage=0.05
|
| 1625 |
+
|
| 1626 |
+
|
| 1627 |
+
Tree=85
|
| 1628 |
+
num_leaves=7
|
| 1629 |
+
num_cat=0
|
| 1630 |
+
split_feature=7 1 1 7 8 9
|
| 1631 |
+
split_gain=0.602742 0.135123 2.2411e-05 2.66251e-06 9.35745e-07 7.34683e-07
|
| 1632 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1633 |
+
decision_type=2 2 2 2 2 2
|
| 1634 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1635 |
+
right_child=1 3 -4 4 -6 -7
|
| 1636 |
+
leaf_value=-0.050365774686833502 -0.051906961115474784 0.050762936756621184 -0.051548115528713426 0.050360639537289399 0.050598300838636423 -0.050590866292310327
|
| 1637 |
+
leaf_weight=0.23006430780515075 0.035388439893722534 0.060611481312662363 0.050467765424400568 0.25172960478812456 0.049573555588722229 0.043031559325754642
|
| 1638 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1639 |
+
internal_value=8.27099e-05 0.0413425 -0.0505801 0.0504606 0.0503997 -0.0504012
|
| 1640 |
+
internal_weight=0.720867 0.397303 0.323564 0.361915 0.301303 0.273096
|
| 1641 |
+
internal_count=86 47 39 46 41 36
|
| 1642 |
+
is_linear=0
|
| 1643 |
+
shrinkage=0.05
|
| 1644 |
+
|
| 1645 |
+
|
| 1646 |
+
Tree=86
|
| 1647 |
+
num_leaves=7
|
| 1648 |
+
num_cat=0
|
| 1649 |
+
split_feature=7 1 1 7 8 9
|
| 1650 |
+
split_gain=0.573016 0.128451 1.9273e-05 2.28958e-06 8.05081e-07 6.31772e-07
|
| 1651 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1652 |
+
decision_type=2 2 2 2 2 2
|
| 1653 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1654 |
+
right_child=1 3 -4 4 -6 -7
|
| 1655 |
+
leaf_value=-0.050347807744096633 -0.051810504678536623 0.050725328219376711 -0.051471306045197208 0.050342931810607429 0.050568897155633556 -0.050561767693004633
|
| 1656 |
+
leaf_weight=0.2189200627617538 0.033723615109920502 0.057697092182934284 0.048076252453029156 0.2395347086712718 0.047182553447782993 0.040955848060548306
|
| 1657 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1658 |
+
internal_value=8.28212e-05 0.0413191 -0.0505517 0.0504379 0.0503801 -0.0503815
|
| 1659 |
+
internal_weight=0.68609 0.378138 0.307952 0.344414 0.286717 0.259876
|
| 1660 |
+
internal_count=86 47 39 46 41 36
|
| 1661 |
+
is_linear=0
|
| 1662 |
+
shrinkage=0.05
|
| 1663 |
+
|
| 1664 |
+
|
| 1665 |
+
Tree=87
|
| 1666 |
+
num_leaves=7
|
| 1667 |
+
num_cat=0
|
| 1668 |
+
split_feature=7 1 1 7 8 9
|
| 1669 |
+
split_gain=0.544771 0.122113 1.65751e-05 1.96897e-06 6.92684e-07 5.43303e-07
|
| 1670 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1671 |
+
decision_type=2 2 2 2 2 2
|
| 1672 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1673 |
+
right_child=1 3 -4 4 -6 -7
|
| 1674 |
+
leaf_value=-0.050330730324470864 -0.051719086213005222 0.050689591046640982 -0.0513983691992854 0.050326098707277403 0.05054094975433629 -0.050534116756501969
|
| 1675 |
+
leaf_weight=0.20831208350136876 0.032134164124727249 0.054920890368521214 0.045794803649187088 0.22792675299569964 0.044905624818056822 0.038979186676442623
|
| 1676 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1677 |
+
internal_value=8.29264e-05 0.0412968 -0.0505246 0.0504164 0.0503615 -0.0503628
|
| 1678 |
+
internal_weight=0.652974 0.359887 0.293086 0.327753 0.272832 0.247291
|
| 1679 |
+
internal_count=86 47 39 46 41 36
|
| 1680 |
+
is_linear=0
|
| 1681 |
+
shrinkage=0.05
|
| 1682 |
+
|
| 1683 |
+
|
| 1684 |
+
Tree=88
|
| 1685 |
+
num_leaves=7
|
| 1686 |
+
num_cat=0
|
| 1687 |
+
split_feature=7 1 1 7 8 9
|
| 1688 |
+
split_gain=0.517933 0.116091 1.42555e-05 1.69331e-06 5.95974e-07 4.67253e-07
|
| 1689 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1690 |
+
decision_type=2 2 2 2 2 2
|
| 1691 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1692 |
+
right_child=1 3 -4 4 -6 -7
|
| 1693 |
+
leaf_value=-0.050314498253588726 -0.051632443098970984 0.050655631740285201 -0.051329106525360046 0.050310098101705926 0.050514383222273918 -0.050507842204426924
|
| 1694 |
+
leaf_weight=0.19821489881724119 0.030616963282227516 0.05227650748565793 0.04361866507679224 0.2168778539635241 0.042737449519336224 0.037096953019499779
|
| 1695 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1696 |
+
internal_value=8.30259e-05 0.0412757 -0.0504989 0.050396 0.0503437 -0.050345
|
| 1697 |
+
internal_weight=0.621439 0.342509 0.278931 0.311892 0.259615 0.235312
|
| 1698 |
+
internal_count=86 47 39 46 41 36
|
| 1699 |
+
is_linear=0
|
| 1700 |
+
shrinkage=0.05
|
| 1701 |
+
|
| 1702 |
+
|
| 1703 |
+
Tree=89
|
| 1704 |
+
num_leaves=7
|
| 1705 |
+
num_cat=0
|
| 1706 |
+
split_feature=7 1 1 7 8 9
|
| 1707 |
+
split_gain=0.492429 0.110369 1.2261e-05 1.45631e-06 5.12793e-07 4.0185e-07
|
| 1708 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1709 |
+
decision_type=2 2 2 2 2 2
|
| 1710 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1711 |
+
right_child=1 3 -4 4 -6 -7
|
| 1712 |
+
leaf_value=-0.050299064368726144 -0.051550292034122147 0.050623360312032475 -0.051263319891751882 0.05029488594998547 0.050489132277186634 -0.050482864286208989
|
| 1713 |
+
leaf_weight=0.18860423564910889 0.029168995097279549 0.049757851287722588 0.04154325881972909 0.20636141765862703 0.0406729388050735 0.03530473168939352
|
| 1714 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1715 |
+
internal_value=8.31209e-05 0.0412555 -0.0504744 0.0503766 0.0503269 -0.050328
|
| 1716 |
+
internal_weight=0.591413 0.325961 0.265452 0.296792 0.247034 0.223909
|
| 1717 |
+
internal_count=86 47 39 46 41 36
|
| 1718 |
+
is_linear=0
|
| 1719 |
+
shrinkage=0.05
|
| 1720 |
+
|
| 1721 |
+
|
| 1722 |
+
Tree=90
|
| 1723 |
+
num_leaves=7
|
| 1724 |
+
num_cat=0
|
| 1725 |
+
split_feature=7 1 1 7 8 9
|
| 1726 |
+
split_gain=0.468192 0.104931 1.05458e-05 1.25255e-06 4.41224e-07 3.45617e-07
|
| 1727 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1728 |
+
decision_type=2 2 2 2 2 2
|
| 1729 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1730 |
+
right_child=1 3 -4 4 -6 -7
|
| 1731 |
+
leaf_value=-0.050284394815262895 -0.051472401652421375 0.050592692579550236 -0.051200835479461297 0.050280424122202294 0.050465127310612361 -0.050459127857895095
|
| 1732 |
+
leaf_weight=0.17945691710337996 0.027787335216999054 0.047359100077301264 0.039564179722219706 0.19635209115222096 0.03870723582804203 0.033598298672586679
|
| 1733 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1734 |
+
internal_value=8.32108e-05 0.0412364 -0.0504512 0.0503581 0.0503108 -0.0503119
|
| 1735 |
+
internal_weight=0.562825 0.310206 0.252619 0.282418 0.235059 0.213055
|
| 1736 |
+
internal_count=86 47 39 46 41 36
|
| 1737 |
+
is_linear=0
|
| 1738 |
+
shrinkage=0.05
|
| 1739 |
+
|
| 1740 |
+
|
| 1741 |
+
Tree=91
|
| 1742 |
+
num_leaves=7
|
| 1743 |
+
num_cat=0
|
| 1744 |
+
split_feature=7 1 1 7 8 9
|
| 1745 |
+
split_gain=0.445159 0.0997649 9.07088e-06 1.07731e-06 3.79648e-07 2.97265e-07
|
| 1746 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1747 |
+
decision_type=2 2 2 2 2 2
|
| 1748 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1749 |
+
right_child=1 3 -4 4 -6 -7
|
| 1750 |
+
leaf_value=-0.050270448158576099 -0.051398526992987692 0.050563543463076947 -0.051141481764662267 0.050266675951028406 0.050442307897245721 -0.050436566562057319
|
| 1751 |
+
leaf_weight=0.17075086617842317 0.026469161733984947 0.045074684545397758 0.037677189335227013 0.18682568054646254 0.036835697945207357 0.031973626464605331
|
| 1752 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1753 |
+
internal_value=8.32954e-05 0.0412183 -0.0504291 0.0503405 0.0502956 -0.0502966
|
| 1754 |
+
internal_weight=0.535607 0.295205 0.240402 0.268736 0.223661 0.202724
|
| 1755 |
+
internal_count=86 47 39 46 41 36
|
| 1756 |
+
is_linear=0
|
| 1757 |
+
shrinkage=0.05
|
| 1758 |
+
|
| 1759 |
+
|
| 1760 |
+
Tree=92
|
| 1761 |
+
num_leaves=7
|
| 1762 |
+
num_cat=0
|
| 1763 |
+
split_feature=7 1 1 7 8 9
|
| 1764 |
+
split_gain=0.423268 0.094855 7.80249e-06 9.26631e-07 3.26674e-07 2.55686e-07
|
| 1765 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1766 |
+
decision_type=2 2 2 2 2 2
|
| 1767 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1768 |
+
right_child=1 3 -4 4 -6 -7
|
| 1769 |
+
leaf_value=-0.05025718836517773 -0.051328463012764294 0.05053584135422981 -0.05108509747141346 0.050253604954431264 0.050420614788711397 -0.050415120966182086
|
| 1770 |
+
leaf_weight=0.16246502147987485 0.025211747735738754 0.042899276595562696 0.035878210794180632 0.17775914305821061 0.035053895320743322 0.030426864977926016
|
| 1771 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1772 |
+
internal_value=8.33761e-05 0.041201 -0.050408 0.0503238 0.0502811 -0.0502821
|
| 1773 |
+
internal_weight=0.509694 0.280924 0.22877 0.255712 0.212813 0.192892
|
| 1774 |
+
internal_count=86 47 39 46 41 36
|
| 1775 |
+
is_linear=0
|
| 1776 |
+
shrinkage=0.05
|
| 1777 |
+
|
| 1778 |
+
|
| 1779 |
+
Tree=93
|
| 1780 |
+
num_leaves=7
|
| 1781 |
+
num_cat=0
|
| 1782 |
+
split_feature=7 1 1 7 8 9
|
| 1783 |
+
split_gain=0.402461 0.0901889 6.71156e-06 7.9706e-07 2.81088e-07 2.19923e-07
|
| 1784 |
+
threshold=3112.1875000000005 1.5000000000000002 1.5000000000000002 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1785 |
+
decision_type=2 2 2 2 2 2
|
| 1786 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1787 |
+
right_child=1 3 -4 4 -6 -7
|
| 1788 |
+
leaf_value=-0.050244584593455377 -0.051261996673023981 0.050509510970679308 -0.051031527960906944 0.050241177033193599 0.050399988714995715 -0.050394736323651074
|
| 1789 |
+
leaf_weight=0.15457929950207472 0.02401246689260006 0.04082779074087739 0.034163331147283316 0.16913049947470427 0.033357597887516022 0.028954341541975737
|
| 1790 |
+
leaf_count=32 1 5 3 36 5 4
|
| 1791 |
+
internal_value=8.34525e-05 0.0411846 -0.0503881 0.050308 0.0502673 -0.0502683
|
| 1792 |
+
internal_weight=0.485025 0.267328 0.217697 0.243316 0.202488 0.183534
|
| 1793 |
+
internal_count=86 47 39 46 41 36
|
| 1794 |
+
is_linear=0
|
| 1795 |
+
shrinkage=0.05
|
| 1796 |
+
|
| 1797 |
+
|
| 1798 |
+
Tree=94
|
| 1799 |
+
num_leaves=7
|
| 1800 |
+
num_cat=0
|
| 1801 |
+
split_feature=7 1 1 7 8 9
|
| 1802 |
+
split_gain=0.382686 0.0857542 8.50195e-06 6.85608e-07 2.41875e-07 1.9306e-07
|
| 1803 |
+
threshold=3112.1875000000005 1.5000000000000002 2.5000000000000004 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1804 |
+
decision_type=2 2 2 2 2 2
|
| 1805 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1806 |
+
right_child=1 3 -4 4 -6 -7
|
| 1807 |
+
leaf_value=-0.050231772045157587 -0.05119893255906393 0.050484481834977696 -0.051255954612935167 0.050229362181290621 0.050380383068234058 -0.050375359261206912
|
| 1808 |
+
leaf_weight=0.15570021374151111 0.022868789732456207 0.038855364779010415 0.023903153836727142 0.16091879643499851 0.031742766499519348 0.027552548795938492
|
| 1809 |
+
leaf_count=34 1 5 1 36 5 4
|
| 1810 |
+
internal_value=8.35253e-05 0.041169 -0.050369 0.0502929 0.0502542 -0.0502534
|
| 1811 |
+
internal_weight=0.461542 0.254386 0.207156 0.231517 0.192662 0.183253
|
| 1812 |
+
internal_count=86 47 39 46 41 38
|
| 1813 |
+
is_linear=0
|
| 1814 |
+
shrinkage=0.05
|
| 1815 |
+
|
| 1816 |
+
|
| 1817 |
+
Tree=95
|
| 1818 |
+
num_leaves=7
|
| 1819 |
+
num_cat=0
|
| 1820 |
+
split_feature=7 1 1 7 8 9
|
| 1821 |
+
split_gain=0.363888 0.0815393 7.30348e-06 5.89764e-07 2.08124e-07 1.66078e-07
|
| 1822 |
+
threshold=3112.1875000000005 1.5000000000000002 2.5000000000000004 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1823 |
+
decision_type=2 2 2 2 2 2
|
| 1824 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1825 |
+
right_child=1 3 -4 4 -6 -7
|
| 1826 |
+
leaf_value=-0.050220417250276289 -0.051139095953743607 0.050460690435998379 -0.051193200479213857 0.050218127763647515 0.050361738473988754 -0.050356941738795569
|
| 1827 |
+
leaf_weight=0.14813926233910024 0.021778276190161705 0.036977351643145084 0.022764552384614944 0.15310407569631934 0.030205549206584692 0.026218139566481113
|
| 1828 |
+
leaf_count=34 1 5 1 36 5 4
|
| 1829 |
+
internal_value=8.35957e-05 0.0411541 -0.0503509 0.0502785 0.0502418 -0.0502409
|
| 1830 |
+
internal_weight=0.439187 0.242065 0.197122 0.220287 0.18331 0.174357
|
| 1831 |
+
internal_count=86 47 39 46 41 38
|
| 1832 |
+
is_linear=0
|
| 1833 |
+
shrinkage=0.05
|
| 1834 |
+
|
| 1835 |
+
|
| 1836 |
+
Tree=96
|
| 1837 |
+
num_leaves=7
|
| 1838 |
+
num_cat=0
|
| 1839 |
+
split_feature=7 1 1 7 8 9
|
| 1840 |
+
split_gain=0.34602 0.0775331 6.27459e-06 5.07338e-07 1.791e-07 1.4286e-07
|
| 1841 |
+
threshold=3112.1875000000005 1.5000000000000002 2.5000000000000004 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1842 |
+
decision_type=2 2 2 2 2 2
|
| 1843 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1844 |
+
right_child=1 3 -4 4 -6 -7
|
| 1845 |
+
leaf_value=-0.050209622222626926 -0.051082307401579589 0.05043807614005931 -0.051133655309017922 0.050207445200207285 0.05034401700303897 -0.050339429089042924
|
| 1846 |
+
leaf_weight=0.14094396075233817 0.020738586783409119 0.035189317772164941 0.021678892895579338 0.1456673052161932 0.028742266818881035 0.024947922211140394
|
| 1847 |
+
leaf_count=34 1 5 1 36 5 4
|
| 1848 |
+
internal_value=8.36615e-05 0.04114 -0.0503337 0.0502649 0.05023 -0.0502291
|
| 1849 |
+
internal_weight=0.417908 0.230337 0.187571 0.209599 0.17441 0.165892
|
| 1850 |
+
internal_count=86 47 39 46 41 38
|
| 1851 |
+
is_linear=0
|
| 1852 |
+
shrinkage=0.05
|
| 1853 |
+
|
| 1854 |
+
|
| 1855 |
+
Tree=97
|
| 1856 |
+
num_leaves=7
|
| 1857 |
+
num_cat=0
|
| 1858 |
+
split_feature=7 1 1 7 8 9
|
| 1859 |
+
split_gain=0.329035 0.0737251 5.39117e-06 4.36445e-07 1.54115e-07 1.229e-07
|
| 1860 |
+
threshold=3112.1875000000005 1.5000000000000002 2.5000000000000004 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1861 |
+
decision_type=2 2 2 2 2 2
|
| 1862 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1863 |
+
right_child=1 3 -4 4 -6 -7
|
| 1864 |
+
leaf_value=-0.050199356445814317 -0.051028411202997205 0.050416579266307451 -0.051077146716563694 0.050197288813652312 0.050327164284452677 -0.050322783240472013
|
| 1865 |
+
leaf_weight=0.13409677124582231 0.01974746398627758 0.033487027743831277 0.020643839612603188 0.13859035610221326 0.027349414071068168 0.023738850373774767
|
| 1866 |
+
leaf_count=34 1 5 1 36 5 4
|
| 1867 |
+
internal_value=8.37241e-05 0.0411266 -0.0503173 0.0502519 0.0502187 -0.0502179
|
| 1868 |
+
internal_weight=0.397654 0.219174 0.178479 0.199427 0.16594 0.157836
|
| 1869 |
+
internal_count=86 47 39 46 41 38
|
| 1870 |
+
is_linear=0
|
| 1871 |
+
shrinkage=0.05
|
| 1872 |
+
|
| 1873 |
+
|
| 1874 |
+
Tree=98
|
| 1875 |
+
num_leaves=7
|
| 1876 |
+
num_cat=0
|
| 1877 |
+
split_feature=7 1 1 7 8 9
|
| 1878 |
+
split_gain=0.312889 0.0701055 4.63247e-06 3.75461e-07 1.3262e-07 1.05726e-07
|
| 1879 |
+
threshold=3112.1875000000005 1.5000000000000002 2.5000000000000004 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1880 |
+
decision_type=2 2 2 2 2 2
|
| 1881 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1882 |
+
right_child=1 3 -4 4 -6 -7
|
| 1883 |
+
leaf_value=-0.050189596756458045 -0.050977250616091152 0.050396141654857063 -0.051023508928724509 0.050187630953487827 0.050311141473668199 -0.050306956270874226
|
| 1884 |
+
leaf_weight=0.12758097238838673 0.018802745267748833 0.031866437988355756 0.019657149910926819 0.13185595325194299 0.026023643789812922 0.022588017396628857
|
| 1885 |
+
leaf_count=34 1 5 1 36 5 4
|
| 1886 |
+
internal_value=8.37838e-05 0.0411139 -0.0503017 0.0502396 0.050208 -0.0502072
|
| 1887 |
+
internal_weight=0.378375 0.208549 0.169826 0.189746 0.15788 0.150169
|
| 1888 |
+
internal_count=86 47 39 46 41 38
|
| 1889 |
+
is_linear=0
|
| 1890 |
+
shrinkage=0.05
|
| 1891 |
+
|
| 1892 |
+
|
| 1893 |
+
Tree=99
|
| 1894 |
+
num_leaves=7
|
| 1895 |
+
num_cat=0
|
| 1896 |
+
split_feature=7 1 1 7 8 9
|
| 1897 |
+
split_gain=0.29754 0.0666646 3.98088e-06 3.23019e-07 1.14123e-07 9.09602e-08
|
| 1898 |
+
threshold=3112.1875000000005 1.5000000000000002 2.5000000000000004 3478.8119047619052 0.40833333333333338 0.071839745922519613
|
| 1899 |
+
decision_type=2 2 2 2 2 2
|
| 1900 |
+
left_child=2 -2 5 -3 -5 -1
|
| 1901 |
+
right_child=1 3 -4 4 -6 -7
|
| 1902 |
+
leaf_value=-0.050180315600638993 -0.050928677138001657 0.05037671632404709 -0.050972594433378086 0.050178448515061494 0.050295906560174089 -0.050291912359883201
|
| 1903 |
+
leaf_weight=0.12138065416365862 0.017902351915836334 0.030323687475174665 0.018716664984822273 0.12544763740152121 0.024761765031144023 0.021492652595043182
|
| 1904 |
+
leaf_count=34 1 5 1 36 5 4
|
| 1905 |
+
internal_value=8.38408e-05 0.0411018 -0.0502869 0.0502279 0.0501978 -0.0501971
|
| 1906 |
+
internal_weight=0.360025 0.198435 0.16159 0.180533 0.150209 0.142873
|
| 1907 |
+
internal_count=86 47 39 46 41 38
|
| 1908 |
+
is_linear=0
|
| 1909 |
+
shrinkage=0.05
|
| 1910 |
+
|
| 1911 |
+
|
| 1912 |
+
end of trees
|
| 1913 |
+
|
| 1914 |
+
feature_importances:
|
| 1915 |
+
Column_7=145
|
| 1916 |
+
Column_9=120
|
| 1917 |
+
Column_1=90
|
| 1918 |
+
Column_8=73
|
| 1919 |
+
Column_12=37
|
| 1920 |
+
Column_11=28
|
| 1921 |
+
Column_6=25
|
| 1922 |
+
Column_2=22
|
| 1923 |
+
Column_3=19
|
| 1924 |
+
Column_0=15
|
| 1925 |
+
Column_4=10
|
| 1926 |
+
Column_5=9
|
| 1927 |
+
Column_10=3
|
| 1928 |
+
|
| 1929 |
+
parameters:
|
| 1930 |
+
[boosting: gbdt]
|
| 1931 |
+
[objective: binary]
|
| 1932 |
+
[metric: binary_logloss]
|
| 1933 |
+
[tree_learner: serial]
|
| 1934 |
+
[device_type: cpu]
|
| 1935 |
+
[data_sample_strategy: bagging]
|
| 1936 |
+
[data: ]
|
| 1937 |
+
[valid: ]
|
| 1938 |
+
[num_iterations: 100]
|
| 1939 |
+
[learning_rate: 0.05]
|
| 1940 |
+
[num_leaves: 7]
|
| 1941 |
+
[num_threads: 8]
|
| 1942 |
+
[seed: 42]
|
| 1943 |
+
[deterministic: 0]
|
| 1944 |
+
[force_col_wise: 0]
|
| 1945 |
+
[force_row_wise: 0]
|
| 1946 |
+
[histogram_pool_size: -1]
|
| 1947 |
+
[max_depth: 4]
|
| 1948 |
+
[min_data_in_leaf: 5]
|
| 1949 |
+
[min_sum_hessian_in_leaf: 0.001]
|
| 1950 |
+
[bagging_fraction: 1]
|
| 1951 |
+
[pos_bagging_fraction: 1]
|
| 1952 |
+
[neg_bagging_fraction: 1]
|
| 1953 |
+
[bagging_freq: 0]
|
| 1954 |
+
[bagging_seed: 400]
|
| 1955 |
+
[bagging_by_query: 0]
|
| 1956 |
+
[feature_fraction: 1]
|
| 1957 |
+
[feature_fraction_bynode: 1]
|
| 1958 |
+
[feature_fraction_seed: 30056]
|
| 1959 |
+
[extra_trees: 0]
|
| 1960 |
+
[extra_seed: 12879]
|
| 1961 |
+
[early_stopping_round: 0]
|
| 1962 |
+
[early_stopping_min_delta: 0]
|
| 1963 |
+
[first_metric_only: 0]
|
| 1964 |
+
[max_delta_step: 0]
|
| 1965 |
+
[lambda_l1: 0]
|
| 1966 |
+
[lambda_l2: 0]
|
| 1967 |
+
[linear_lambda: 0]
|
| 1968 |
+
[min_gain_to_split: 0]
|
| 1969 |
+
[drop_rate: 0.1]
|
| 1970 |
+
[max_drop: 50]
|
| 1971 |
+
[skip_drop: 0.5]
|
| 1972 |
+
[xgboost_dart_mode: 0]
|
| 1973 |
+
[uniform_drop: 0]
|
| 1974 |
+
[drop_seed: 17869]
|
| 1975 |
+
[top_rate: 0.2]
|
| 1976 |
+
[other_rate: 0.1]
|
| 1977 |
+
[min_data_per_group: 100]
|
| 1978 |
+
[max_cat_threshold: 32]
|
| 1979 |
+
[cat_l2: 10]
|
| 1980 |
+
[cat_smooth: 10]
|
| 1981 |
+
[max_cat_to_onehot: 4]
|
| 1982 |
+
[top_k: 20]
|
| 1983 |
+
[monotone_constraints: ]
|
| 1984 |
+
[monotone_constraints_method: basic]
|
| 1985 |
+
[monotone_penalty: 0]
|
| 1986 |
+
[feature_contri: ]
|
| 1987 |
+
[forcedsplits_filename: ]
|
| 1988 |
+
[refit_decay_rate: 0.9]
|
| 1989 |
+
[cegb_tradeoff: 1]
|
| 1990 |
+
[cegb_penalty_split: 0]
|
| 1991 |
+
[cegb_penalty_feature_lazy: ]
|
| 1992 |
+
[cegb_penalty_feature_coupled: ]
|
| 1993 |
+
[path_smooth: 0]
|
| 1994 |
+
[interaction_constraints: ]
|
| 1995 |
+
[verbosity: -1]
|
| 1996 |
+
[saved_feature_importance_type: 0]
|
| 1997 |
+
[use_quantized_grad: 0]
|
| 1998 |
+
[num_grad_quant_bins: 4]
|
| 1999 |
+
[quant_train_renew_leaf: 0]
|
| 2000 |
+
[stochastic_rounding: 1]
|
| 2001 |
+
[linear_tree: 0]
|
| 2002 |
+
[max_bin: 255]
|
| 2003 |
+
[max_bin_by_feature: ]
|
| 2004 |
+
[min_data_in_bin: 3]
|
| 2005 |
+
[bin_construct_sample_cnt: 200000]
|
| 2006 |
+
[data_random_seed: 175]
|
| 2007 |
+
[is_enable_sparse: 1]
|
| 2008 |
+
[enable_bundle: 1]
|
| 2009 |
+
[use_missing: 1]
|
| 2010 |
+
[zero_as_missing: 0]
|
| 2011 |
+
[feature_pre_filter: 1]
|
| 2012 |
+
[pre_partition: 0]
|
| 2013 |
+
[two_round: 0]
|
| 2014 |
+
[header: 0]
|
| 2015 |
+
[label_column: ]
|
| 2016 |
+
[weight_column: ]
|
| 2017 |
+
[group_column: ]
|
| 2018 |
+
[ignore_column: ]
|
| 2019 |
+
[categorical_feature: ]
|
| 2020 |
+
[forcedbins_filename: ]
|
| 2021 |
+
[precise_float_parser: 0]
|
| 2022 |
+
[parser_config_file: ]
|
| 2023 |
+
[objective_seed: 16083]
|
| 2024 |
+
[num_class: 1]
|
| 2025 |
+
[is_unbalance: 0]
|
| 2026 |
+
[scale_pos_weight: 1]
|
| 2027 |
+
[sigmoid: 1]
|
| 2028 |
+
[boost_from_average: 1]
|
| 2029 |
+
[reg_sqrt: 0]
|
| 2030 |
+
[alpha: 0.9]
|
| 2031 |
+
[fair_c: 1]
|
| 2032 |
+
[poisson_max_delta_step: 0.7]
|
| 2033 |
+
[tweedie_variance_power: 1.5]
|
| 2034 |
+
[lambdarank_truncation_level: 30]
|
| 2035 |
+
[lambdarank_norm: 1]
|
| 2036 |
+
[label_gain: ]
|
| 2037 |
+
[lambdarank_position_bias_regularization: 0]
|
| 2038 |
+
[eval_at: ]
|
| 2039 |
+
[multi_error_top_k: 1]
|
| 2040 |
+
[auc_mu_weights: ]
|
| 2041 |
+
[num_machines: 1]
|
| 2042 |
+
[local_listen_port: 12400]
|
| 2043 |
+
[time_out: 120]
|
| 2044 |
+
[machine_list_filename: ]
|
| 2045 |
+
[machines: ]
|
| 2046 |
+
[gpu_platform_id: -1]
|
| 2047 |
+
[gpu_device_id: -1]
|
| 2048 |
+
[gpu_device_id_list: ]
|
| 2049 |
+
[gpu_use_dp: 0]
|
| 2050 |
+
[num_gpu: 1]
|
| 2051 |
+
|
| 2052 |
+
end of parameters
|
| 2053 |
+
|
| 2054 |
+
pandas_categorical:null
|
scoring/score_demo.py
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
score_demo.py
|
| 3 |
+
-------------
|
| 4 |
+
Score the Phase 1 demo dataset (data/synthetic/) using the trained model.
|
| 5 |
+
|
| 6 |
+
Inputs:
|
| 7 |
+
data/synthetic/candidate_clusters.json (fixed by Section 1)
|
| 8 |
+
data/synthetic/orders.json
|
| 9 |
+
data/synthetic/graph.gpickle
|
| 10 |
+
scoring/model.lgb
|
| 11 |
+
|
| 12 |
+
Output:
|
| 13 |
+
data/synthetic/scored_clusters.json β candidate_clusters.json + risk_probability
|
| 14 |
+
|
| 15 |
+
Usage:
|
| 16 |
+
python scoring/score_demo.py
|
| 17 |
+
"""
|
| 18 |
+
|
| 19 |
+
import json
|
| 20 |
+
import os
|
| 21 |
+
import sys
|
| 22 |
+
|
| 23 |
+
import lightgbm as lgb
|
| 24 |
+
import numpy as np
|
| 25 |
+
|
| 26 |
+
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 27 |
+
sys.path.insert(0, BASE_DIR)
|
| 28 |
+
|
| 29 |
+
DEMO_DIR = os.path.join(BASE_DIR, "data", "synthetic")
|
| 30 |
+
MODEL_PATH = os.path.join(BASE_DIR, "scoring", "model.lgb")
|
| 31 |
+
OUT_PATH = os.path.join(DEMO_DIR, "scored_clusters.json")
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
def score_demo():
|
| 35 |
+
from scoring.features import extract_all, _load_json, _load_graph, FEATURE_COLUMNS
|
| 36 |
+
|
| 37 |
+
clusters_path = os.path.join(DEMO_DIR, "candidate_clusters.json")
|
| 38 |
+
orders_path = os.path.join(DEMO_DIR, "orders.json")
|
| 39 |
+
graph_path = os.path.join(DEMO_DIR, "graph.gpickle")
|
| 40 |
+
|
| 41 |
+
print(f"Loading demo data from {DEMO_DIR}...")
|
| 42 |
+
clusters = _load_json(clusters_path)
|
| 43 |
+
orders = _load_json(orders_path)
|
| 44 |
+
graph = _load_graph(graph_path) if os.path.exists(graph_path) else None
|
| 45 |
+
|
| 46 |
+
print(f" {len(clusters)} candidate clusters")
|
| 47 |
+
|
| 48 |
+
# Extract features (no labels needed for scoring)
|
| 49 |
+
rows = extract_all(clusters, orders, ground_truth=None, graph=graph)
|
| 50 |
+
X = np.array([[r[f] for f in FEATURE_COLUMNS] for r in rows])
|
| 51 |
+
|
| 52 |
+
print(f"Loading model from {MODEL_PATH}...")
|
| 53 |
+
model = lgb.Booster(model_file=MODEL_PATH)
|
| 54 |
+
|
| 55 |
+
probs = model.predict(X)
|
| 56 |
+
print(f" Scored {len(probs)} clusters")
|
| 57 |
+
|
| 58 |
+
# Build scored_clusters.json: candidate_clusters schema + risk_probability
|
| 59 |
+
cluster_by_id = {c["cluster_id"]: c for c in clusters}
|
| 60 |
+
scored = []
|
| 61 |
+
for i, row in enumerate(rows):
|
| 62 |
+
cid = row["cluster_id"]
|
| 63 |
+
cluster = cluster_by_id[cid].copy()
|
| 64 |
+
cluster["risk_probability"] = float(probs[i])
|
| 65 |
+
scored.append(cluster)
|
| 66 |
+
|
| 67 |
+
with open(OUT_PATH, "w", encoding="utf-8") as f:
|
| 68 |
+
json.dump(scored, f, indent=2, ensure_ascii=False)
|
| 69 |
+
|
| 70 |
+
print(f"\nScored clusters saved to {OUT_PATH}")
|
| 71 |
+
print("\nRisk probability summary:")
|
| 72 |
+
for c in scored:
|
| 73 |
+
print(f" {c['cluster_id']:8s} size={c['size']:3d} "
|
| 74 |
+
f"formation={c['formation_type']:15s} "
|
| 75 |
+
f"risk={c['risk_probability']:.4f}")
|
| 76 |
+
|
| 77 |
+
return scored
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
if __name__ == "__main__":
|
| 81 |
+
score_demo()
|
scoring/train_model.py
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
train_model.py
|
| 3 |
+
--------------
|
| 4 |
+
Train a LightGBM binary risk classifier on the training dataset.
|
| 5 |
+
|
| 6 |
+
Outputs:
|
| 7 |
+
scoring/model.lgb β trained LightGBM model
|
| 8 |
+
scoring/holdout_split.json β held-out test rows for evaluation (Section 6)
|
| 9 |
+
|
| 10 |
+
Usage:
|
| 11 |
+
python scoring/train_model.py
|
| 12 |
+
"""
|
| 13 |
+
|
| 14 |
+
import json
|
| 15 |
+
import os
|
| 16 |
+
import pickle
|
| 17 |
+
import sys
|
| 18 |
+
|
| 19 |
+
import lightgbm as lgb
|
| 20 |
+
import numpy as np
|
| 21 |
+
from sklearn.model_selection import train_test_split
|
| 22 |
+
|
| 23 |
+
# ---------------------------------------------------------------------------
|
| 24 |
+
# Paths
|
| 25 |
+
# ---------------------------------------------------------------------------
|
| 26 |
+
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 27 |
+
TRAIN_DIR = os.path.join(BASE_DIR, "data", "synthetic_train")
|
| 28 |
+
SCORING_DIR = os.path.join(BASE_DIR, "scoring")
|
| 29 |
+
|
| 30 |
+
MODEL_PATH = os.path.join(SCORING_DIR, "model.lgb")
|
| 31 |
+
HOLDOUT_PATH = os.path.join(SCORING_DIR, "holdout_split.json")
|
| 32 |
+
|
| 33 |
+
# ---------------------------------------------------------------------------
|
| 34 |
+
# Feature columns (must match scoring/features.py)
|
| 35 |
+
# ---------------------------------------------------------------------------
|
| 36 |
+
FEATURE_COLUMNS = [
|
| 37 |
+
"size",
|
| 38 |
+
"strong_link_count",
|
| 39 |
+
"weak_link_count",
|
| 40 |
+
"strong_link_density",
|
| 41 |
+
"has_same_contact_edge",
|
| 42 |
+
"order_count",
|
| 43 |
+
"total_amount",
|
| 44 |
+
"avg_order_amount",
|
| 45 |
+
"return_rate",
|
| 46 |
+
"chargeback_rate",
|
| 47 |
+
"shared_coupon_count",
|
| 48 |
+
"time_span_days",
|
| 49 |
+
"order_velocity",
|
| 50 |
+
"formation_type_strong",
|
| 51 |
+
]
|
| 52 |
+
|
| 53 |
+
RANDOM_STATE = 42
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def load_data():
|
| 57 |
+
"""Load clusters, orders, ground truth, and graph from the training directory."""
|
| 58 |
+
sys.path.insert(0, BASE_DIR)
|
| 59 |
+
from scoring.features import extract_all, _load_json, _load_graph
|
| 60 |
+
|
| 61 |
+
clusters_path = os.path.join(TRAIN_DIR, "candidate_clusters.json")
|
| 62 |
+
orders_path = os.path.join(TRAIN_DIR, "orders.json")
|
| 63 |
+
gt_path = os.path.join(TRAIN_DIR, "ground_truth.json")
|
| 64 |
+
graph_path = os.path.join(TRAIN_DIR, "graph.gpickle")
|
| 65 |
+
|
| 66 |
+
clusters = _load_json(clusters_path)
|
| 67 |
+
orders = _load_json(orders_path)
|
| 68 |
+
ground_truth = _load_json(gt_path)
|
| 69 |
+
graph = _load_graph(graph_path) if os.path.exists(graph_path) else None
|
| 70 |
+
|
| 71 |
+
rows = extract_all(clusters, orders, ground_truth=ground_truth, graph=graph)
|
| 72 |
+
return rows
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
def train():
|
| 76 |
+
print("Loading training data...")
|
| 77 |
+
rows = load_data()
|
| 78 |
+
print(f" {len(rows)} candidate clusters loaded")
|
| 79 |
+
|
| 80 |
+
X = np.array([[r[f] for f in FEATURE_COLUMNS] for r in rows])
|
| 81 |
+
y = np.array([r["label"] for r in rows])
|
| 82 |
+
cluster_ids = [r["cluster_id"] for r in rows]
|
| 83 |
+
feature_rows = [{f: r[f] for f in FEATURE_COLUMNS} for r in rows]
|
| 84 |
+
|
| 85 |
+
pos = y.sum()
|
| 86 |
+
neg = len(y) - pos
|
| 87 |
+
print(f" Labels β positive: {int(pos)}, negative: {int(neg)}")
|
| 88 |
+
|
| 89 |
+
# 5.2 β stratified 80/20 split
|
| 90 |
+
(X_train, X_test, y_train, y_test,
|
| 91 |
+
ids_train, ids_test,
|
| 92 |
+
feat_train, feat_test) = train_test_split(
|
| 93 |
+
X, y, cluster_ids, feature_rows,
|
| 94 |
+
test_size=0.20,
|
| 95 |
+
stratify=y,
|
| 96 |
+
random_state=RANDOM_STATE,
|
| 97 |
+
)
|
| 98 |
+
print(f" Train: {len(X_train)} Test (holdout): {len(X_test)}")
|
| 99 |
+
print(f" Holdout positives: {y_test.sum():.0f} negatives: {(len(y_test)-y_test.sum()):.0f}")
|
| 100 |
+
|
| 101 |
+
# 5.3 β simple LightGBM model (small dataset, keep it simple)
|
| 102 |
+
model = lgb.LGBMClassifier(
|
| 103 |
+
num_leaves=7,
|
| 104 |
+
max_depth=4,
|
| 105 |
+
min_child_samples=5,
|
| 106 |
+
n_estimators=100,
|
| 107 |
+
learning_rate=0.05,
|
| 108 |
+
objective="binary",
|
| 109 |
+
random_state=RANDOM_STATE,
|
| 110 |
+
verbose=-1,
|
| 111 |
+
)
|
| 112 |
+
print("Training LightGBM classifier...")
|
| 113 |
+
model.fit(X_train, y_train)
|
| 114 |
+
print(" Training complete.")
|
| 115 |
+
|
| 116 |
+
# 5.4 β save model
|
| 117 |
+
model.booster_.save_model(MODEL_PATH)
|
| 118 |
+
print(f" Model saved to {MODEL_PATH}")
|
| 119 |
+
|
| 120 |
+
# Verify reload
|
| 121 |
+
loaded = lgb.Booster(model_file=MODEL_PATH)
|
| 122 |
+
test_pred = loaded.predict(X_test)
|
| 123 |
+
print(f" Model reload verified (test pred shape: {test_pred.shape})")
|
| 124 |
+
|
| 125 |
+
# 5.5 β feature importances
|
| 126 |
+
importances = model.feature_importances_
|
| 127 |
+
importance_pairs = sorted(
|
| 128 |
+
zip(FEATURE_COLUMNS, importances),
|
| 129 |
+
key=lambda x: x[1], reverse=True
|
| 130 |
+
)
|
| 131 |
+
print("\nFeature importances (gain):")
|
| 132 |
+
for feat, imp in importance_pairs:
|
| 133 |
+
print(f" {feat:30s}: {imp}")
|
| 134 |
+
if importance_pairs[0][0] == "size" and importance_pairs[0][1] > sum(importances) * 0.5:
|
| 135 |
+
print(" [NOTE] 'size' dominates feature importance β worth flagging in summary")
|
| 136 |
+
|
| 137 |
+
# Save holdout split (cluster IDs + features + labels + probabilities)
|
| 138 |
+
holdout = []
|
| 139 |
+
probs = loaded.predict(X_test)
|
| 140 |
+
for i in range(len(ids_test)):
|
| 141 |
+
holdout.append({
|
| 142 |
+
"cluster_id": ids_test[i],
|
| 143 |
+
"features": feat_test[i],
|
| 144 |
+
"label": int(y_test[i]),
|
| 145 |
+
"risk_probability": float(probs[i]),
|
| 146 |
+
})
|
| 147 |
+
|
| 148 |
+
with open(HOLDOUT_PATH, "w", encoding="utf-8") as f:
|
| 149 |
+
json.dump(holdout, f, indent=2, ensure_ascii=False)
|
| 150 |
+
print(f" Holdout split saved to {HOLDOUT_PATH} ({len(holdout)} rows)")
|
| 151 |
+
|
| 152 |
+
return model, holdout, importance_pairs
|
| 153 |
+
|
| 154 |
+
|
| 155 |
+
if __name__ == "__main__":
|
| 156 |
+
train()
|