ginnyxxxxxxx commited on
Commit
9e9363b
Β·
1 Parent(s): 244eb3a
Files changed (1) hide show
  1. app.py +75 -50
app.py CHANGED
@@ -375,6 +375,41 @@ CHAIN_CSS = """
375
  .hct-s1 .hct-dot { background: #6878c8; }
376
  .hct-s2 .hct-dot { background: #c08040; }
377
  .hct-s3 .hct-dot { background: #d4453a; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
378
  </style>
379
  """
380
 
@@ -509,33 +544,36 @@ def _parse_s3(text):
509
  return pred, conf, (reasoning[:277] + '…' if len(reasoning) > 280 else reasoning)
510
 
511
 
512
- PROMPT_DESCRIPTIONS = {
513
- 1: (
514
- "Given the agent's mobility trajectory data β€” including visited locations, visit frequencies, "
515
- "stay durations, activity types, and temporal patterns β€” extract objective factual features "
516
- "without any interpretation. Identify: (1) location inventory with visit counts and apparent "
517
- "price tier; (2) temporal distribution across time-of-day and weekday/weekend; "
518
- "(3) spatial activity radius and movement distances; (4) typical activity sequences and "
519
- "transition patterns between location types."
520
- ),
521
- 2: (
522
- "Based on the trajectory features extracted in Step 1, perform behavioral abstraction across "
523
- "four dimensions: (1) Routine & Schedule β€” infer work schedule type and daily structure; "
524
- "(2) Economic Behavior β€” assess spending tier from venue choices and mobility costs; "
525
- "(3) Social & Lifestyle β€” identify social engagement patterns, leisure activities, and "
526
- "community involvement; (4) Routine Stability β€” evaluate consistency and regularity of "
527
- "movement patterns over the observation period."
528
- ),
529
- 3: (
530
- "Synthesizing the factual features (Step 1) and behavioral patterns (Step 2), infer the "
531
- "agent's household income bracket. Consider location economic indicators, transportation "
532
- "mode signals, activity diversity, and lifestyle markers collectively. Output a single "
533
- "income range prediction with supporting reasoning grounded in the observed mobility evidence."
534
- ),
535
  }
536
 
537
  def _extract_prompt_instruction(prompt_text, stage):
538
- return PROMPT_DESCRIPTIONS.get(stage, '')
 
 
 
 
539
 
540
 
541
  # ── Body renderers ────────────────────────────────────────────────────────────
@@ -629,37 +667,24 @@ def render_chain(s1_text, s2_text, s3_text, status="idle",
629
  s2_body = _s2_body(s2_text if s2_on else '', s2_on)
630
  s3_body = _s3_body(s3_text if s3_on else '', s3_on)
631
 
632
- def paper_block(prompt_text, stage_num, response_text, resp_label):
633
- def esc(t): return t.replace('&','&amp;').replace('<','&lt;').replace('>','&gt;')
634
- # Prompt snippet
635
- instr = _extract_prompt_instruction(prompt_text, stage_num)
636
- p_short = esc(instr[:220]) + ('……' if len(instr) > 220 else '') if instr else ''
637
- # Response snippet
638
- r_clean = response_text.strip()
639
- r_short = esc(r_clean[:260]) + ('……' if len(r_clean) > 260 else '') if r_clean else ''
640
-
641
- prompt_html = (f'<div class="hct-paper-prompt">'
642
- f'<div class="hct-paper-tag">Prompt {stage_num}</div>'
643
- f'<div class="hct-paper-text">{p_short}</div>'
644
- f'</div>') if p_short else ''
645
- connector = '<div class="hct-paper-connector"><div class="hct-paper-connector-line"></div></div>' if (p_short and r_short) else ''
646
- response_html = (f'<div class="hct-paper-response">'
647
- f'<div class="hct-paper-tag">{resp_label}</div>'
648
- f'<div class="hct-paper-text">{r_short}</div>'
649
- f'</div>') if r_short else ''
650
- if not prompt_html and not response_html:
651
  return ''
652
- return f'<div class="hct-paper-wrap">{prompt_html}{connector}{response_html}</div>'
 
 
 
653
 
654
- def stage(cls, num, title, body, on, prompt_text, stage_num, response_text='', resp_label='Response'):
655
  dim_cls = 'active' if on else 'dim'
656
- paper = paper_block(prompt_text, stage_num, response_text, resp_label) if on and (prompt_text or response_text) else ''
657
  return (f'<div class="hct-stage hct-{cls} {dim_cls}">'
658
  f'<div class="hct-head">'
659
  f'<span class="hct-num">{num}</span>'
660
  f'<span class="hct-title">{title}</span>'
661
  f'</div>'
662
- f'{paper}'
663
  f'<div class="hct-body">{body}</div>'
664
  f'</div>')
665
 
@@ -671,11 +696,11 @@ def render_chain(s1_text, s2_text, s3_text, status="idle",
671
  f'<div class="hct-arrow-line"></div></div>')
672
 
673
  html = CHAIN_CSS + '<div class="hct-root">'
674
- html += stage('s1', 'Stage 01', 'Feature Extraction', s1_body, s1_on, s1_prompt, 1, s1_text, 'Response 1')
675
  html += arrow('behavioral abstraction', s2_on)
676
- html += stage('s2', 'Stage 02', 'Behavioral Analysis', s2_body, s2_on, s2_prompt, 2, s2_text, 'Response 2')
677
  html += arrow('demographic inference', s3_on)
678
- html += stage('s3', 'Stage 03', 'Demographic Inference', s3_body, s3_on, s3_prompt, 3, s3_text, 'Response 3')
679
  html += '</div>'
680
  return html
681
 
 
375
  .hct-s1 .hct-dot { background: #6878c8; }
376
  .hct-s2 .hct-dot { background: #c08040; }
377
  .hct-s3 .hct-dot { background: #d4453a; }
378
+
379
+ /* ── Prompt collapsible ── */
380
+ details.hct-prompt-details { padding: 0 14px 10px; }
381
+ details.hct-prompt-details summary {
382
+ display: inline-flex; align-items: center; list-style: none;
383
+ font-family: 'DM Mono', monospace; font-size: 9px;
384
+ letter-spacing: 0.08em; text-transform: uppercase;
385
+ padding: 3px 10px; border-radius: 20px; cursor: pointer;
386
+ border: 1px solid currentColor; opacity: 0.4;
387
+ transition: opacity 0.2s; background: transparent; user-select: none;
388
+ }
389
+ details.hct-prompt-details summary::-webkit-details-marker { display: none; }
390
+ details.hct-prompt-details summary::before { content: 'β–Ό prompt'; }
391
+ details.hct-prompt-details[open] summary::before { content: 'β–² prompt'; }
392
+ details.hct-prompt-details summary:hover { opacity: 0.75; }
393
+ .hct-s1 details.hct-prompt-details summary { color: #3a4a80; }
394
+ .hct-s2 details.hct-prompt-details summary { color: #7a4a10; }
395
+ .hct-s3 details.hct-prompt-details summary { color: #b0302a; }
396
+ .hct-prompt-content {
397
+ margin-top: 7px; background: rgba(0,0,0,0.025);
398
+ border-radius: 7px; padding: 8px 12px 8px 10px;
399
+ border-left: 2px solid #ccc; opacity: 0.85;
400
+ }
401
+ .hct-prompt-list {
402
+ margin: 0; padding: 0 0 0 16px; list-style: disc;
403
+ }
404
+ .hct-prompt-list li {
405
+ margin-bottom: 5px; color: #445;
406
+ font-size: 11px; line-height: 1.6;
407
+ }
408
+ .hct-prompt-list li:last-child { margin-bottom: 0; }
409
+ .hct-prompt-list code {
410
+ font-family: 'DM Mono', monospace; font-size: 10px;
411
+ background: rgba(0,0,0,0.07); padding: 1px 4px; border-radius: 3px;
412
+ }
413
  </style>
414
  """
415
 
 
544
  return pred, conf, (reasoning[:277] + '…' if len(reasoning) > 280 else reasoning)
545
 
546
 
547
+ PROMPT_BULLETS = {
548
+ 1: [
549
+ "Extract objective factual features from the agent's mobility trajectory <b>without any interpretation</b>",
550
+ "Location inventory: list all visited POIs with visit counts and apparent price tier (budget / mid-range / high-end)",
551
+ "Temporal patterns: time-of-day distribution, weekday vs. weekend split, and regularity of routines",
552
+ "Spatial characteristics: activity radius, average movement distance between locations",
553
+ "Sequence observations: common location transitions and typical daily activity chains",
554
+ ],
555
+ 2: [
556
+ "Perform behavioral abstraction across four dimensions based on Step 1 features",
557
+ "Routine &amp; Schedule: infer work schedule type (fixed hours, flexible, shift work, etc.) and daily structure",
558
+ "Economic Behavior: assess spending tier from venue choices, transportation costs, and lifestyle signals",
559
+ "Social &amp; Lifestyle: identify social engagement patterns, leisure activities, and community involvement",
560
+ "Routine Stability: evaluate consistency and regularity of movement patterns over the observation period",
561
+ ],
562
+ 3: [
563
+ "Synthesize factual features (Step 1) and behavioral patterns (Step 2) to infer household income bracket",
564
+ "Score location economic indicators: luxury / mid-range / budget venue distribution",
565
+ "Consider transportation mode signals, activity diversity, and temporal flexibility as income proxies",
566
+ "Output: <code>INCOME_PREDICTION</code> β€” a single income range with confidence rating (1–5)",
567
+ "Output: <code>INCOME_REASONING</code> β€” evidence-grounded justification referencing specific mobility observations",
568
+ ],
 
569
  }
570
 
571
  def _extract_prompt_instruction(prompt_text, stage):
572
+ bullets = PROMPT_BULLETS.get(stage, [])
573
+ if not bullets:
574
+ return ''
575
+ items = ''.join(f'<li>{b}</li>' for b in bullets)
576
+ return f'<ul class="hct-prompt-list">{items}</ul>'
577
 
578
 
579
  # ── Body renderers ────────────────────────────────────────────────────────────
 
667
  s2_body = _s2_body(s2_text if s2_on else '', s2_on)
668
  s3_body = _s3_body(s3_text if s3_on else '', s3_on)
669
 
670
+ def prompt_pill(stage_num):
671
+ bullets_html = _extract_prompt_instruction('', stage_num)
672
+ if not bullets_html:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
673
  return ''
674
+ return (f'<details class="hct-prompt-details">'
675
+ f'<summary></summary>'
676
+ f'<div class="hct-prompt-content">{bullets_html}</div>'
677
+ f'</details>')
678
 
679
+ def stage(cls, num, title, body, on, stage_num):
680
  dim_cls = 'active' if on else 'dim'
681
+ pill = prompt_pill(stage_num) if on else ''
682
  return (f'<div class="hct-stage hct-{cls} {dim_cls}">'
683
  f'<div class="hct-head">'
684
  f'<span class="hct-num">{num}</span>'
685
  f'<span class="hct-title">{title}</span>'
686
  f'</div>'
687
+ f'{pill}'
688
  f'<div class="hct-body">{body}</div>'
689
  f'</div>')
690
 
 
696
  f'<div class="hct-arrow-line"></div></div>')
697
 
698
  html = CHAIN_CSS + '<div class="hct-root">'
699
+ html += stage('s1', 'Stage 01', 'Feature Extraction', s1_body, s1_on, 1)
700
  html += arrow('behavioral abstraction', s2_on)
701
+ html += stage('s2', 'Stage 02', 'Behavioral Analysis', s2_body, s2_on, 2)
702
  html += arrow('demographic inference', s3_on)
703
+ html += stage('s3', 'Stage 03', 'Demographic Inference', s3_body, s3_on, 3)
704
  html += '</div>'
705
  return html
706