Spaces:
Sleeping
Sleeping
Commit Β·
244eb3a
1
Parent(s): e4a4c32
cot
Browse files
app.py
CHANGED
|
@@ -207,37 +207,51 @@ CHAIN_CSS = """
|
|
| 207 |
.hct-s3 .hct-title { color: #b0302a; }
|
| 208 |
|
| 209 |
/* ββ Prompt pill ββ */
|
| 210 |
-
|
| 211 |
-
.hct-
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
|
|
|
| 218 |
}
|
| 219 |
-
.hct-
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
display: none;
|
| 225 |
margin-top: 6px;
|
| 226 |
-
|
| 227 |
-
|
| 228 |
-
|
| 229 |
-
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 239 |
}
|
| 240 |
-
.hct-prompt-box.open { display: block; }
|
| 241 |
|
| 242 |
/* ββ Body ββ */
|
| 243 |
.hct-body { padding: 12px 14px; }
|
|
@@ -362,15 +376,6 @@ CHAIN_CSS = """
|
|
| 362 |
.hct-s2 .hct-dot { background: #c08040; }
|
| 363 |
.hct-s3 .hct-dot { background: #d4453a; }
|
| 364 |
</style>
|
| 365 |
-
<script>
|
| 366 |
-
function hctTogglePrompt(id) {
|
| 367 |
-
var box = document.getElementById(id);
|
| 368 |
-
var btn = document.getElementById(id + '-btn');
|
| 369 |
-
if (!box) return;
|
| 370 |
-
var open = box.classList.toggle('open');
|
| 371 |
-
btn.textContent = open ? 'β² hide prompt' : 'βΌ show prompt';
|
| 372 |
-
}
|
| 373 |
-
</script>
|
| 374 |
"""
|
| 375 |
|
| 376 |
|
|
@@ -394,10 +399,14 @@ def _parse_s1(text):
|
|
| 394 |
locations.append((m.group(1).strip(), int(m.group(2))))
|
| 395 |
continue
|
| 396 |
|
| 397 |
-
# Duration
|
| 398 |
m2 = re.match(r'-?\s*(.+?):\s+(?:Average duration of\s*)?([\d.]+)\s+min(?:utes?)?\s+on average', s, re.IGNORECASE)
|
| 399 |
if not m2:
|
| 400 |
m2 = re.match(r'-?\s*(.+?):\s+Average duration of ([\d.]+)\s+min', s, re.IGNORECASE)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 401 |
if m2:
|
| 402 |
dur_map[m2.group(1).strip()] = float(m2.group(2))
|
| 403 |
|
|
@@ -500,18 +509,33 @@ def _parse_s3(text):
|
|
| 500 |
return pred, conf, (reasoning[:277] + 'β¦' if len(reasoning) > 280 else reasoning)
|
| 501 |
|
| 502 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 503 |
def _extract_prompt_instruction(prompt_text, stage):
|
| 504 |
-
|
| 505 |
-
return ''
|
| 506 |
-
key = f'STEP {stage}:'
|
| 507 |
-
idx = prompt_text.find(key)
|
| 508 |
-
if idx != -1:
|
| 509 |
-
return prompt_text[idx:idx + 600].strip()
|
| 510 |
-
# fallback: first meaningful line
|
| 511 |
-
for line in prompt_text.strip().splitlines():
|
| 512 |
-
if line.strip():
|
| 513 |
-
return line.strip()[:300]
|
| 514 |
-
return ''
|
| 515 |
|
| 516 |
|
| 517 |
# ββ Body renderers ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
@@ -605,27 +629,37 @@ def render_chain(s1_text, s2_text, s3_text, status="idle",
|
|
| 605 |
s2_body = _s2_body(s2_text if s2_on else '', s2_on)
|
| 606 |
s3_body = _s3_body(s3_text if s3_on else '', s3_on)
|
| 607 |
|
| 608 |
-
def
|
|
|
|
|
|
|
| 609 |
instr = _extract_prompt_instruction(prompt_text, stage_num)
|
| 610 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 611 |
return ''
|
| 612 |
-
|
| 613 |
-
return (f'<div class="hct-prompt-wrap">'
|
| 614 |
-
f'<span id="{pid}-btn" class="hct-prompt-toggle" '
|
| 615 |
-
f'onclick="hctTogglePrompt(\'{pid}\')">'
|
| 616 |
-
f'βΌ show prompt</span>'
|
| 617 |
-
f'<div id="{pid}" class="hct-prompt-box">{safe}</div>'
|
| 618 |
-
f'</div>')
|
| 619 |
|
| 620 |
-
def stage(cls, num, title, body, on, prompt_text, stage_num):
|
| 621 |
dim_cls = 'active' if on else 'dim'
|
| 622 |
-
|
| 623 |
return (f'<div class="hct-stage hct-{cls} {dim_cls}">'
|
| 624 |
f'<div class="hct-head">'
|
| 625 |
f'<span class="hct-num">{num}</span>'
|
| 626 |
f'<span class="hct-title">{title}</span>'
|
| 627 |
f'</div>'
|
| 628 |
-
f'{
|
| 629 |
f'<div class="hct-body">{body}</div>'
|
| 630 |
f'</div>')
|
| 631 |
|
|
@@ -637,11 +671,11 @@ def render_chain(s1_text, s2_text, s3_text, status="idle",
|
|
| 637 |
f'<div class="hct-arrow-line"></div></div>')
|
| 638 |
|
| 639 |
html = CHAIN_CSS + '<div class="hct-root">'
|
| 640 |
-
html += stage('s1', 'Stage 01', 'Feature Extraction', s1_body, s1_on, s1_prompt, 1)
|
| 641 |
html += arrow('behavioral abstraction', s2_on)
|
| 642 |
-
html += stage('s2', 'Stage 02', 'Behavioral Analysis', s2_body, s2_on, s2_prompt, 2)
|
| 643 |
html += arrow('demographic inference', s3_on)
|
| 644 |
-
html += stage('s3', 'Stage 03', 'Demographic Inference', s3_body, s3_on, s3_prompt, 3)
|
| 645 |
html += '</div>'
|
| 646 |
return html
|
| 647 |
|
|
|
|
| 207 |
.hct-s3 .hct-title { color: #b0302a; }
|
| 208 |
|
| 209 |
/* ββ Prompt pill ββ */
|
| 210 |
+
/* ββ Paper-style prompt+response layout ββ */
|
| 211 |
+
.hct-paper-wrap { padding: 0 12px 10px; }
|
| 212 |
+
.hct-paper-prompt {
|
| 213 |
+
background: #fffef5;
|
| 214 |
+
border: 1.5px dashed #c8b870;
|
| 215 |
+
border-radius: 8px;
|
| 216 |
+
padding: 8px 11px;
|
| 217 |
+
margin-bottom: 0;
|
| 218 |
+
position: relative;
|
| 219 |
}
|
| 220 |
+
.hct-paper-response {
|
| 221 |
+
background: #f8fffe;
|
| 222 |
+
border: 1.5px solid #8ab8a8;
|
| 223 |
+
border-radius: 8px;
|
| 224 |
+
padding: 8px 11px;
|
|
|
|
| 225 |
margin-top: 6px;
|
| 226 |
+
position: relative;
|
| 227 |
+
}
|
| 228 |
+
.hct-s2 .hct-paper-prompt { background: #fffbf0; border-color: #d4a840; }
|
| 229 |
+
.hct-s2 .hct-paper-response { background: #fffbf0; border-color: #c89050; }
|
| 230 |
+
.hct-s3 .hct-paper-prompt { background: #fff8f7; border-color: #d4453a; border-style: dashed; }
|
| 231 |
+
.hct-s3 .hct-paper-response { background: #fff8f7; border-color: #c03030; }
|
| 232 |
+
.hct-paper-tag {
|
| 233 |
+
display: inline-block;
|
| 234 |
+
font-family: 'DM Mono', monospace; font-size: 8.5px; font-weight: 600;
|
| 235 |
+
letter-spacing: 0.1em; text-transform: uppercase;
|
| 236 |
+
padding: 1px 6px; border-radius: 3px; margin-bottom: 5px;
|
| 237 |
+
}
|
| 238 |
+
.hct-paper-prompt .hct-paper-tag { background: #f0e48a; color: #7a6010; }
|
| 239 |
+
.hct-s2 .hct-paper-prompt .hct-paper-tag { background: #f5d580; color: #7a5010; }
|
| 240 |
+
.hct-s3 .hct-paper-prompt .hct-paper-tag { background: #fac8c4; color: #a03028; }
|
| 241 |
+
.hct-paper-response .hct-paper-tag { background: #c8e8d8; color: #206048; }
|
| 242 |
+
.hct-s2 .hct-paper-response .hct-paper-tag { background: #f0dcb0; color: #7a5010; }
|
| 243 |
+
.hct-s3 .hct-paper-response .hct-paper-tag { background: #f8c8c4; color: #902828; }
|
| 244 |
+
.hct-paper-text {
|
| 245 |
+
font-size: 11px; line-height: 1.6; color: #333;
|
| 246 |
+
white-space: pre-wrap; word-break: break-word;
|
| 247 |
+
}
|
| 248 |
+
.hct-paper-connector {
|
| 249 |
+
display: flex; align-items: center; justify-content: center;
|
| 250 |
+
height: 14px; margin: 0 20px;
|
| 251 |
+
}
|
| 252 |
+
.hct-paper-connector-line {
|
| 253 |
+
width: 1px; height: 100%; background: #aaa;
|
| 254 |
}
|
|
|
|
| 255 |
|
| 256 |
/* ββ Body ββ */
|
| 257 |
.hct-body { padding: 12px 14px; }
|
|
|
|
| 376 |
.hct-s2 .hct-dot { background: #c08040; }
|
| 377 |
.hct-s3 .hct-dot { background: #d4453a; }
|
| 378 |
</style>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 379 |
"""
|
| 380 |
|
| 381 |
|
|
|
|
| 399 |
locations.append((m.group(1).strip(), int(m.group(2))))
|
| 400 |
continue
|
| 401 |
|
| 402 |
+
# Duration β 4 formats
|
| 403 |
m2 = re.match(r'-?\s*(.+?):\s+(?:Average duration of\s*)?([\d.]+)\s+min(?:utes?)?\s+on average', s, re.IGNORECASE)
|
| 404 |
if not m2:
|
| 405 |
m2 = re.match(r'-?\s*(.+?):\s+Average duration of ([\d.]+)\s+min', s, re.IGNORECASE)
|
| 406 |
+
if not m2:
|
| 407 |
+
m2 = re.match(r'-?\s*Average duration at (.+?):\s+([\d.]+)\s+min', s, re.IGNORECASE)
|
| 408 |
+
if not m2:
|
| 409 |
+
m2 = re.search(r'\bat ([A-Za-z][^(,]+?)\s*\(average ([\d.]+)\s*min', s, re.IGNORECASE)
|
| 410 |
if m2:
|
| 411 |
dur_map[m2.group(1).strip()] = float(m2.group(2))
|
| 412 |
|
|
|
|
| 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 |
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('&','&').replace('<','<').replace('>','>')
|
| 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 |
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 |
|