| """ |
| Preference study β pair introduction screen. |
| |
| Participants see Product A and Product B, rate familiarity for both, |
| choose an initial preference (1β7), and click "Start Chat". |
| |
| Clicking "Start Chat" initialises the conversation: |
| 1. AI (synthetic): preference_initial(pair_overview) |
| 2. User (synthetic): vote_response_text("preference", N) β same as lsp SalesEnv |
| 3. AI (model): first persuasion response |
| |
| The seller always argues for Product A regardless of the participant's lean. |
| """ |
| import time |
|
|
| import streamlit as st |
|
|
| from src.model import call_model |
| from src.lsp_wrappers import ( |
| build_seller_system_prompt_preference, |
| closing_message_preference, |
| format_demographics, |
| initial_vote_user_message_preference, |
| opening_message_preference, |
| ) |
| from src.ui.components import ( |
| familiarity_choices, |
| parse_rating, |
| rating_choices, |
| render_pair_cards, |
| render_progress, |
| ) |
|
|
|
|
| def screen_pair_intro(s: dict, cfg: dict) -> None: |
| idx = s["current_index"] |
| item = s["items"][idx] |
| pair_id = item["pair_id"] |
|
|
| render_progress(idx + 1, cfg["pairs_per_user"]) |
| st.markdown("## Product Comparison") |
| st.markdown( |
| "Please read both products carefully before answering the questions below." |
| ) |
|
|
| render_pair_cards(item) |
| st.markdown("---") |
|
|
| |
| cat_a = item["product_a"].get("category", item.get("category", "")) |
| fam_a_opts = familiarity_choices(cat_a) |
| fam_a = st.radio( |
| f"How familiar are you with **Product A** " |
| f"(*{item['product_a'].get('title', '')[:60]}β¦*)?", |
| fam_a_opts, |
| index=None, |
| key=f"fam_a_{idx}_{pair_id}", |
| ) |
|
|
| |
| cat_b = item["product_b"].get("category", item.get("category", "")) |
| fam_b_opts = familiarity_choices(cat_b) |
| fam_b = st.radio( |
| f"How familiar are you with **Product B** " |
| f"(*{item['product_b'].get('title', '')[:60]}β¦*)?", |
| fam_b_opts, |
| index=None, |
| key=f"fam_b_{idx}_{pair_id}", |
| ) |
|
|
| st.markdown("---") |
|
|
| |
| choices = rating_choices("preference") |
| pre_val = st.radio( |
| "Considering these two products, which would you prefer to buy?", |
| choices, |
| index=None, |
| key=f"pre_rating_{idx}_{pair_id}", |
| ) |
|
|
| if st.button("Start Chat β", type="primary", use_container_width=True): |
| if not cfg["debug_mode"]: |
| if not fam_a: |
| st.error("β οΈ Please rate your familiarity with Product A.") |
| return |
| if not fam_b: |
| st.error("β οΈ Please rate your familiarity with Product B.") |
| return |
| if not pre_val: |
| st.error("β οΈ Please rate your preference before starting the chat.") |
| return |
|
|
| |
| fam_a = fam_a or fam_a_opts[0] |
| fam_b = fam_b or fam_b_opts[0] |
| pre_val = pre_val or choices[3] |
|
|
| pre_int = parse_rating(pre_val) |
|
|
| |
| item_cfg = { |
| **cfg, |
| "prompt_variant": item.get("prompt_variant", {}), |
| "model_name": item.get("model_name", ""), |
| "sampler_path": item.get("sampler_path", ""), |
| } |
|
|
| |
| |
| |
| include_bio = bool(item_cfg["prompt_variant"].get("include_bio", False)) |
| demo_str = format_demographics( |
| s["demographics"], |
| background=s.get("background", {}), |
| include_bio=include_bio, |
| ) |
|
|
| |
| system_prompt = build_seller_system_prompt_preference(item, item_cfg, demo_str) |
| uniform_survey = bool( |
| item_cfg.get("prompt_variant", {}).get("uniform_initial_survey", False) |
| ) |
| opening_msg = opening_message_preference( |
| item, uniform_initial_survey=uniform_survey |
| ) |
| user_choice_msg = initial_vote_user_message_preference(pre_int) |
| closing_msg = closing_message_preference( |
| item, uniform_initial_survey=uniform_survey |
| ) |
|
|
| |
| messages = [ |
| {"role": "system", "content": system_prompt}, |
| {"role": "assistant", "content": opening_msg}, |
| {"role": "user", "content": user_choice_msg}, |
| ] |
| with st.spinner("Starting conversationβ¦"): |
| ai_reply = call_model(messages, item_cfg) |
|
|
| now = time.time() |
|
|
| |
| s["items"][idx]["familiarity_a"] = fam_a |
| s["items"][idx]["familiarity_b"] = fam_b |
| s["items"][idx]["pre_rating"] = pre_int |
| s["items"][idx]["conversation"].update({ |
| "system_prompt": system_prompt, |
| "closing_message": closing_msg, |
| "turns": [ |
| { |
| "turn_index": 0, |
| "role": "assistant", |
| "content": opening_msg, |
| "timestamp": now, |
| "synthetic": True, |
| }, |
| { |
| "turn_index": 1, |
| "role": "user", |
| "content": user_choice_msg, |
| "timestamp": now, |
| "synthetic": True, |
| }, |
| { |
| "turn_index": 2, |
| "role": "assistant", |
| "content": ai_reply, |
| "timestamp": now, |
| "model": item_cfg["model_name"], |
| }, |
| ], |
| "num_turns": 0, |
| }) |
|
|
| print(f"[CONV] num turns stored: {len(s['items'][idx]['conversation']['turns'])}") |
| print(f"[CONV] turn roles: {[(t['role'], t.get('synthetic')) for t in s['items'][idx]['conversation']['turns']]}") |
| print(f"[CONV] turn 0 content[:100]: {s['items'][idx]['conversation']['turns'][0]['content'][:100]}") |
| print(f"[CONV] turn 1 content: {s['items'][idx]['conversation']['turns'][1]['content']}") |
|
|
| s["screen"] = "chat" |
| st.rerun() |