Download encoder/src/demo/copilot_app_fraud_pattern.py from cdotsanghvi/lfm2-transaction-encoder: direct link, hf CLI and curl.
- Browser
- Download file 5.89 kB
-
https://huggingface.co/spaces/cdotsanghvi/lfm2-transaction-encoder/resolve/main/encoder/src/demo/copilot_app_fraud_pattern.py
- Command line
-
hf download hf://spaces/cdotsanghvi/lfm2-transaction-encoder/encoder/src/demo/copilot_app_fraud_pattern.py
-
curl -L -o copilot_app_fraud_pattern.py https://huggingface.co/spaces/cdotsanghvi/lfm2-transaction-encoder/resolve/main/encoder/src/demo/copilot_app_fraud_pattern.py
5.89 kB
| """Gradio app for the Fraud Pattern Co-Pilot demo. | |
| Mirror of the Dispute/Collections apps. Cast strip → context → | |
| Analyze → timeline + two-distribution scoreboard + streaming reasoning. | |
| CLI: | |
| python -m encoder.src.demo.copilot_app_fraud_pattern \\ | |
| --checkpoint encoder/experiments/fraud_pattern_v1/demo_checkpoint.pt \\ | |
| --port 7864 | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| from pathlib import Path | |
| import gradio as gr | |
| import torch | |
| from encoder.src.demo.copilot_inference_fraud_pattern import ( | |
| FraudPatternCastMember, | |
| FraudPatternCopilotModel, | |
| ) | |
| from encoder.src.demo.copilot_render_fraud_pattern import ( | |
| render_cast_strip, | |
| render_context, | |
| render_header, | |
| render_reasoning, | |
| render_timeline, | |
| render_two_dist_scoreboard, | |
| ) | |
| _CONTAINER_WIDTH_PX = 1200 | |
| def _build_tab(model: FraudPatternCopilotModel) -> None: | |
| """Build the Fraud surface into the current Gradio context.""" | |
| cast = model.cast | |
| selected_idx = gr.State(value=0) | |
| cast_html = gr.HTML(render_cast_strip(cast, 0)) | |
| with gr.Row(): | |
| cast_buttons: list[gr.Button] = [] | |
| for i, m in enumerate(cast): | |
| short = " ".join(m.display_name.split(" ")[:2]) | |
| btn = gr.Button( | |
| value=short, | |
| variant="primary" if i == 0 else "secondary", | |
| scale=1, | |
| ) | |
| cast_buttons.append(btn) | |
| context_html = gr.HTML(render_context(cast[0])) | |
| with gr.Row(): | |
| gr.HTML("<div style='flex: 1'></div>") | |
| analyze_btn = gr.Button( | |
| value="Analyze", | |
| variant="primary", | |
| size="lg", | |
| scale=0, | |
| min_width=180, | |
| ) | |
| gr.HTML("<div style='flex: 1'></div>") | |
| timeline_html = gr.HTML(render_timeline(flagged_idx=cast[0].flagged_idx)) | |
| with gr.Row(equal_height=True): | |
| with gr.Column(scale=3): | |
| scoreboard_html = gr.HTML(render_two_dist_scoreboard(None)) | |
| with gr.Column(scale=2): | |
| reasoning_html = gr.HTML(render_reasoning(None)) | |
| def _select(idx: int) -> tuple: | |
| member = cast[idx] | |
| button_updates = tuple( | |
| gr.update(variant="primary" if i == idx else "secondary") | |
| for i in range(len(cast)) | |
| ) | |
| return ( | |
| idx, | |
| render_cast_strip(cast, idx), | |
| render_context(member), | |
| render_timeline(flagged_idx=member.flagged_idx), | |
| render_two_dist_scoreboard(None), | |
| render_reasoning(None), | |
| ) + button_updates | |
| for i, btn in enumerate(cast_buttons): | |
| btn.click( | |
| fn=lambda i=i: _select(i), | |
| inputs=None, | |
| outputs=[ | |
| selected_idx, cast_html, context_html, | |
| timeline_html, scoreboard_html, reasoning_html, | |
| *cast_buttons, | |
| ], | |
| ) | |
| def _analyze(idx: int): | |
| member: FraudPatternCastMember = cast[idx] | |
| result = model.predict(member, top_k=5) | |
| timeline = render_timeline( | |
| flagged_idx=member.flagged_idx, | |
| top_k_positions=result.top_k_positions, | |
| attribution_probs=result.attribution_probs, | |
| ) | |
| scoreboard = render_two_dist_scoreboard(result) | |
| yield timeline, scoreboard, render_reasoning("") | |
| for partial in model.stream_reasoning(member, result, chunk_chars=6): | |
| yield timeline, scoreboard, render_reasoning(partial) | |
| analyze_btn.click( | |
| fn=_analyze, | |
| inputs=[selected_idx], | |
| outputs=[timeline_html, scoreboard_html, reasoning_html], | |
| ) | |
| def _build_ui(model: FraudPatternCopilotModel) -> gr.Blocks: | |
| """Standalone Blocks UI: Fraud-specific header + tab content.""" | |
| with gr.Blocks(title="Fraud Pattern Co-Pilot — Liquid AI") as demo: | |
| gr.HTML(render_header()) | |
| _build_tab(model) | |
| return demo | |
| def main() -> None: | |
| parser = argparse.ArgumentParser( | |
| description="Fraud Pattern Co-Pilot Gradio demo", | |
| ) | |
| parser.add_argument( | |
| "--checkpoint", | |
| type=Path, | |
| default=Path("encoder/experiments/fraud_pattern_v1/demo_checkpoint.pt"), | |
| ) | |
| parser.add_argument( | |
| "--model-config", | |
| type=Path, | |
| default=Path("encoder/configs/model_fraud_pattern.yaml"), | |
| ) | |
| parser.add_argument("--schema", type=Path, default=Path("data/schema.yaml")) | |
| parser.add_argument( | |
| "--histories", | |
| type=Path, | |
| default=Path("data/synthetic/token_ids.npy"), | |
| ) | |
| parser.add_argument( | |
| "--cast", | |
| type=Path, | |
| default=Path("encoder/data/fraud_pattern_cast.json"), | |
| ) | |
| parser.add_argument( | |
| "--device", | |
| type=str, | |
| default="cpu", | |
| choices=["cpu", "cuda", "mps"], | |
| ) | |
| parser.add_argument("--port", type=int, default=7864) | |
| parser.add_argument("--share", action="store_true") | |
| args = parser.parse_args() | |
| device = torch.device(args.device) | |
| print(f"Loading FraudPatternCopilotModel on {device} ...") | |
| model = FraudPatternCopilotModel.from_paths( | |
| checkpoint_path=args.checkpoint, | |
| model_config_path=args.model_config, | |
| schema_path=args.schema, | |
| histories_path=args.histories, | |
| cast_path=args.cast, | |
| device=device, | |
| ) | |
| print(f" cast size: {len(model.cast)}") | |
| demo = _build_ui(model) | |
| demo.queue().launch( | |
| server_name="0.0.0.0", | |
| server_port=args.port, | |
| share=args.share, | |
| theme=gr.themes.Default( | |
| font=["Inter", "system-ui", "sans-serif"], | |
| font_mono=["JetBrains Mono", "ui-monospace", "monospace"], | |
| ), | |
| css=f""" | |
| .gradio-container {{ | |
| max-width: {_CONTAINER_WIDTH_PX}px !important; | |
| background: #fafafa !important; | |
| }} | |
| """, | |
| ) | |
| if __name__ == "__main__": | |
| main() | |