Spaces:
Sleeping
Sleeping
File size: 8,205 Bytes
e2aa97d f063f4d a53d475 e2aa97d a53d475 e2aa97d 8983830 e2aa97d a53d475 e2aa97d 8983830 e2aa97d 8983830 e2aa97d 8983830 e2aa97d 8983830 a53d475 e2aa97d 8983830 e2aa97d 8983830 e2aa97d 8983830 e2aa97d 8983830 f063f4d a53d475 f063f4d e2aa97d f063f4d a53d475 8983830 c5cdb34 e2aa97d 8983830 a53d475 f063f4d e2aa97d a53d475 e2aa97d a53d475 8983830 a53d475 e2aa97d a53d475 e2aa97d a53d475 f063f4d e2aa97d a53d475 f063f4d a53d475 e2aa97d 8983830 e2aa97d f063f4d e2aa97d 8983830 f063f4d e2aa97d f063f4d 8983830 a53d475 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
import os
import time
import gradio as gr
import textwrap
from dataclasses import dataclass, field
from typing import Dict, Tuple
# ============================================================
# PFI Elite Access Control (per-user access codes)
# ============================================================
# Set in Hugging Face Space -> Settings -> Variables and secrets
# Example:
# PFI_ACCESS_CODES = "PFI-EDIN-001,PFI-CLIENT-002,PFI-CLIENT-003"
# PFI_DAILY_QUOTA = "3"
# PFI_BRAND_CONTACT = "pfi@bpmred.academy"
# PFI_MIN_CHARS = "40"
ACCESS_CODES_RAW = os.getenv("PFI_ACCESS_CODES", "").strip()
DAILY_QUOTA = int(os.getenv("PFI_DAILY_QUOTA", "3").strip() or "3")
BRAND_CONTACT = os.getenv("PFI_BRAND_CONTACT", "pfi@bpmred.academy").strip()
MIN_CHARS = int(os.getenv("PFI_MIN_CHARS", "40").strip() or "40")
# Normalized set of valid codes
VALID_CODES = {c.strip() for c in ACCESS_CODES_RAW.split(",") if c.strip()}
# 24h window (seconds)
WINDOW_SECONDS = 24 * 60 * 60
@dataclass
class UsageEntry:
# timestamps of successful requests
ts: list = field(default_factory=list)
@dataclass
class AccessState:
# code -> usage
usage: Dict[str, UsageEntry] = field(default_factory=dict)
# tiny audit log (session-local)
audit: list = field(default_factory=list)
def _now() -> float:
return time.time()
def _clean_old(ts_list: list, now: float) -> list:
"""Keep only timestamps inside rolling 24h window."""
cutoff = now - WINDOW_SECONDS
return [t for t in ts_list if t >= cutoff]
def validate_code(code: str) -> Tuple[bool, str]:
code = (code or "").strip()
if not code:
return False, "Access Code is required."
if not VALID_CODES:
# If admin forgot to set PFI_ACCESS_CODES, fail closed (safest)
return False, "PFI is not configured for access codes yet. Please contact support."
if code not in VALID_CODES:
return False, "Invalid Access Code."
return True, "Access granted."
# ============================================================
# Core PFI reasoning stub (preview-only, non-executive)
# Replace this later with your real model/API call.
# ============================================================
def pfi_reasoning_preview(question: str) -> str:
q = (question or "").strip()
if len(q) < MIN_CHARS:
return textwrap.dedent(
f"""
[Input rejected]
PFI requires a precise, high-density financial question (min {MIN_CHARS} characters).
Ambiguous or underspecified inputs reduce analytical value.
Use this template:
- Objective:
- Horizon:
- Constraints (max drawdown / liquidity / taxes / jurisdiction):
- Current exposures (concentration risk):
- What "irreversible downside" means to you:
"""
).strip()
response = f"""
PFI STRUCTURAL ANALYSIS (PREVIEW · NON-EXECUTABLE)
Question (received):
- {q}
Structural Map:
1) Decision domain: capital allocation / risk architecture
2) Time structure: near-term liquidity vs long-horizon convexity
3) Constraint set: drawdown tolerance, cash-flow needs, optionality preservation
4) Failure modes: forced selling, duration mismatch, correlation spikes, policy shock
5) Control levers: rebalancing rules, hedges, reserve sizing, exposure caps
Cognitive Decomposition:
- Primary variables:
• income stability / career risk
• liquidity needs and timing
• inflation/regime risk
• concentration risk (single asset / geography / employer)
• tax / jurisdiction constraints
- Secondary dependencies:
• correlation behavior under stress
• funding liquidity vs market liquidity
• refinancing risk / rate sensitivity
- Irreversible downside candidates:
• ruin risk (capital impairment that changes future opportunity set)
• forced liquidation triggers
• leverage or short-vol exposure under volatility expansion
Next Questions (to deepen analysis):
- Define max acceptable drawdown and time-to-recover.
- Specify liquidity schedule (must-pay obligations by month/quarter).
- List top 3 concentrated exposures and whether they can be reduced.
- Clarify jurisdiction + tax constraints (capital gains, withholding).
"""
return textwrap.dedent(response).strip()
# ============================================================
# Gated handler (enforces per-code quota)
# ============================================================
def gated_request(access_code: str, question: str, state: AccessState) -> Tuple[str, AccessState]:
state = state or AccessState()
now = _now()
ok, msg = validate_code(access_code)
code = (access_code or "").strip()
# audit
state.audit.append((int(now), "validate", code, ok))
if not ok:
locked = f"""
🔒 **PFI Licensed Access Required**
Reason: **{msg}**
To request a licensed Access Code, contact: **{BRAND_CONTACT}**
"""
return textwrap.dedent(locked).strip(), state
# init usage
if code not in state.usage:
state.usage[code] = UsageEntry(ts=[])
# rolling window cleanup
state.usage[code].ts = _clean_old(state.usage[code].ts, now)
used = len(state.usage[code].ts)
if used >= DAILY_QUOTA:
remaining_time = int((state.usage[code].ts[0] + WINDOW_SECONDS) - now)
hours = max(0, remaining_time // 3600)
minutes = max(0, (remaining_time % 3600) // 60)
quota_msg = f"""
⛔ **Daily quota reached** for this Access Code.
- Quota: **{DAILY_QUOTA} requests / 24h**
- Next reset in: **~{hours}h {minutes}m**
If you need expanded access, contact: **{BRAND_CONTACT}**
"""
state.audit.append((int(now), "quota_block", code, used))
return textwrap.dedent(quota_msg).strip(), state
# Consume 1 quota
state.usage[code].ts.append(now)
state.audit.append((int(now), "quota_consume", code, used + 1))
# Run preview reasoning
out = pfi_reasoning_preview(question)
# Add header with usage
used_after = len(state.usage[code].ts)
header = f"✅ Access Code: {code} | Usage: {used_after}/{DAILY_QUOTA} (rolling 24h)\n\n"
return header + out, state
# ============================================================
# UI
# ============================================================
with gr.Blocks(theme=gr.themes.Soft()) as demo:
gr.Markdown(
"""
# 🧠 Personal Financial Intelligence (PFI)
**High-density financial reasoning · Research Preview**
⚠️ *PFI is a licensed research interface.
It does NOT provide financial advice, trading signals, or execute decisions.*
"""
)
# Session state (in-memory per user session)
state = gr.State(AccessState())
with gr.Row():
access_code = gr.Textbox(
label="PFI Access Code (Licensed)",
placeholder="e.g., PFI-CLIENT-002",
type="password",
)
with gr.Row():
question_input = gr.Textbox(
label="Your Question",
placeholder=(
"Write ONE precise, high-impact financial question.\n"
"Include horizon, constraints, and context. Ambiguity reduces output quality."
),
lines=4,
)
btn = gr.Button("Request Structural Analysis (Preview)")
output_box = gr.Textbox(
label="PFI Output (Exploratory · Non-Executable)",
lines=10,
)
btn.click(
fn=gated_request,
inputs=[access_code, question_input, state],
outputs=[output_box, state],
)
gr.Markdown(
f"""
---
🔒 **Deeper Structural Reasoning — Licensed Layer**
Personalized constraints, scenario stress tests, and capital structure reasoning
are available only under **PFI Licensed Access**.
👉 Request access: **{BRAND_CONTACT}**
---
### Disclaimer
PFI outputs are exploratory and informational only.
No financial advice, trading signals, or decision execution is provided.
© 2026 BPM RED Academy · All rights reserved.
"""
)
if __name__ == "__main__":
demo.launch() |